@jbrowse/app-core 5.0.0-beta.13 → 5.0.0-beta.14

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 (44) hide show
  1. package/esm/AppSession/AppSessionMixin.d.ts +110 -92
  2. package/esm/Assemblies/AssembliesMixin.d.ts +30 -0
  3. package/esm/HistoryManagement/index.d.ts +2 -0
  4. package/esm/HistoryManagement/index.js +2 -0
  5. package/esm/JBrowseConfig/RootConfiguration.d.ts +3 -2
  6. package/esm/JBrowseConfig/RootConfiguration.js +3 -2
  7. package/esm/JBrowseConfig/index.d.ts +2 -3
  8. package/esm/JBrowseConfig/index.js +2 -3
  9. package/esm/JBrowseModel/index.d.ts +9 -1
  10. package/esm/JBrowseModel/index.js +8 -7
  11. package/esm/JbApi/jbApi.js +5 -2
  12. package/esm/RootMenu/index.d.ts +2 -0
  13. package/esm/RootMenu/index.js +2 -0
  14. package/esm/SessionSpec/index.d.ts +2 -2
  15. package/esm/SessionSpec/index.js +1 -1
  16. package/esm/SessionSpec/parseSessionSpecUrl.d.ts +19 -0
  17. package/esm/SessionSpec/parseSessionSpecUrl.js +29 -0
  18. package/esm/WorkspaceLayout/WorkspaceContainer.js +2 -10
  19. package/esm/WorkspaceLayout/WorkspacePanelActions.js +1 -1
  20. package/esm/WorkspaceLayout/WorkspaceTab.d.ts +2 -3
  21. package/esm/WorkspaceLayout/WorkspaceTab.js +2 -2
  22. package/esm/WorkspaceLayout/model.d.ts +10 -15
  23. package/esm/WorkspaceLayout/model.js +36 -65
  24. package/esm/WorkspaceLayout/tree.d.ts +3 -6
  25. package/esm/WorkspaceLayout/tree.js +8 -12
  26. package/esm/WorkspaceLayout/useLayoutDrag.js +10 -4
  27. package/esm/index.d.ts +5 -3
  28. package/esm/index.js +3 -2
  29. package/esm/queryParams.d.ts +2 -0
  30. package/esm/queryParams.js +16 -5
  31. package/esm/sessionSummary.d.ts +16 -0
  32. package/esm/sessionSummary.js +57 -0
  33. package/esm/ui/App/DrawerHeaderHelpDialog.d.ts +3 -2
  34. package/esm/ui/App/DrawerHeaderHelpDialog.js +4 -2
  35. package/esm/ui/App/JBrowseTabMenu.d.ts +3 -2
  36. package/esm/ui/App/JBrowseTabMenu.js +4 -2
  37. package/esm/ui/App/ThemeModeButton.d.ts +4 -5
  38. package/esm/ui/App/ThemeModeButton.js +18 -11
  39. package/esm/ui/App/ViewContainer.js +7 -1
  40. package/esm/ui/App/ViewMenu.js +34 -25
  41. package/esm/ui/App/ViewWrapper.js +2 -2
  42. package/esm/ui/App/viewTitle.d.ts +6 -1
  43. package/esm/ui/App/viewTitle.js +7 -2
  44. package/package.json +6 -6
@@ -29,6 +29,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
29
29
  } & {
30
30
  defaultValue: unknown;
31
31
  };
32
+ readonly circularRefNames: {
33
+ type: "stringArray";
34
+ } & {
35
+ defaultValue: unknown;
36
+ };
32
37
  readonly geneticCodesLocation: {
33
38
  type: "maybeFileLocation";
34
39
  };
@@ -69,6 +74,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
69
74
  } & {
70
75
  defaultValue: unknown;
71
76
  };
77
+ readonly circularRefNames: {
78
+ type: "stringArray";
79
+ } & {
80
+ defaultValue: unknown;
81
+ };
72
82
  readonly geneticCodesLocation: {
73
83
  type: "maybeFileLocation";
74
84
  };
@@ -128,6 +138,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
128
138
  } & {
129
139
  defaultValue: unknown;
130
140
  };
141
+ readonly circularRefNames: {
142
+ type: "stringArray";
143
+ } & {
144
+ defaultValue: unknown;
145
+ };
131
146
  readonly geneticCodesLocation: {
132
147
  type: "maybeFileLocation";
133
148
  };
@@ -164,6 +179,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
164
179
  } & {
165
180
  defaultValue: unknown;
166
181
  };
182
+ readonly circularRefNames: {
183
+ type: "stringArray";
184
+ } & {
185
+ defaultValue: unknown;
186
+ };
167
187
  readonly geneticCodesLocation: {
168
188
  type: "maybeFileLocation";
169
189
  };
@@ -217,6 +237,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
217
237
  } & {
218
238
  defaultValue: unknown;
219
239
  };
240
+ readonly circularRefNames: {
241
+ type: "stringArray";
242
+ } & {
243
+ defaultValue: unknown;
244
+ };
220
245
  readonly geneticCodesLocation: {
221
246
  type: "maybeFileLocation";
222
247
  };
@@ -253,6 +278,11 @@ export declare function AssembliesMixin(_pluginManager: PluginManager, assemblyC
253
278
  } & {
254
279
  defaultValue: unknown;
255
280
  };
281
+ readonly circularRefNames: {
282
+ type: "stringArray";
283
+ } & {
284
+ defaultValue: unknown;
285
+ };
256
286
  readonly geneticCodesLocation: {
257
287
  type: "maybeFileLocation";
258
288
  };
@@ -3,6 +3,8 @@ export declare function historyShortcut(e: ShortcutKeys): "redo" | "undo" | unde
3
3
  /**
4
4
  * #stateModel HistoryManagementMixin
5
5
  * #category root
6
+ * Adds undo and redo of session changes to the root model, bound to Ctrl+Z
7
+ * and Ctrl+Y (Cmd on macOS).
6
8
  */
7
9
  export declare function HistoryManagementMixin(): import("@jbrowse/mobx-state-tree").IModelType<{
8
10
  /**
@@ -28,6 +28,8 @@ export function historyShortcut(e) {
28
28
  /**
29
29
  * #stateModel HistoryManagementMixin
30
30
  * #category root
31
+ * Adds undo and redo of session changes to the root model, bound to Ctrl+Z
32
+ * and Ctrl+Y (Cmd on macOS).
31
33
  */
32
34
  export function HistoryManagementMixin() {
33
35
  return types
@@ -3,8 +3,9 @@ import type { ConfigurationSchemaDefinition } from '@jbrowse/core/configuration'
3
3
  /**
4
4
  * #config JBrowseConfiguration
5
5
  * #category root
6
- * this is the entry under the `configuration` key
7
- * e.g.
6
+ * Holds the app-wide settings in the `configuration` key of a config file,
7
+ * beside `assemblies` and `tracks`.
8
+ *
8
9
  * ```json
9
10
  * {
10
11
  * assemblies,
@@ -5,8 +5,9 @@ import { DEFAULT_SHARE_URL } from './defaultShareUrl.js';
5
5
  /**
6
6
  * #config JBrowseConfiguration
7
7
  * #category root
8
- * this is the entry under the `configuration` key
9
- * e.g.
8
+ * Holds the app-wide settings in the `configuration` key of a config file,
9
+ * beside `assemblies` and `tracks`.
10
+ *
10
11
  * ```json
11
12
  * {
12
13
  * assemblies,
@@ -6,9 +6,8 @@ export { DEFAULT_SHARE_URL } from './defaultShareUrl.ts';
6
6
  * #config JBrowseRootConfig
7
7
  * #category root
8
8
  *
9
- * this is a config model representing a config.json (for jbrowse-web) or
10
- * somefile.jbrowse (for jbrowse-desktop, where configs have the .jbrowse
11
- * extension)
9
+ * Holds a whole JBrowse config file: the `config.json` of jbrowse-web, or a
10
+ * file with the `.jbrowse` extension in jbrowse-desktop.
12
11
  *
13
12
  * also includes any pluginManager.pluginConfigurationSchemas(), so plugins
14
13
  * that have a configurationSchema field on their class are mixed into this
@@ -5,9 +5,8 @@ export { DEFAULT_SHARE_URL } from './defaultShareUrl.js';
5
5
  * #config JBrowseRootConfig
6
6
  * #category root
7
7
  *
8
- * this is a config model representing a config.json (for jbrowse-web) or
9
- * somefile.jbrowse (for jbrowse-desktop, where configs have the .jbrowse
10
- * extension)
8
+ * Holds a whole JBrowse config file: the `config.json` of jbrowse-web, or a
9
+ * file with the `.jbrowse` extension in jbrowse-desktop.
11
10
  *
12
11
  * also includes any pluginManager.pluginConfigurationSchemas(), so plugins
13
12
  * that have a configurationSchema field on their class are mixed into this
@@ -3,6 +3,14 @@ import type { BaseAssemblyConfigSchema } from '@jbrowse/core/assemblyManager';
3
3
  import type { AnyConfiguration, AnyConfigurationModel, ConfigurationSchemaDefinition } from '@jbrowse/core/configuration';
4
4
  import type { PluginDefinition } from '@jbrowse/core/pluginDefinitions';
5
5
  import type RpcManager from '@jbrowse/core/rpc/RpcManager';
6
+ /**
7
+ * #stateModel AppCoreJBrowseModel
8
+ * #category root
9
+ * Holds the loaded config file, usually at `rootModel.jbrowse`, with actions
10
+ * that add and remove its assemblies and tracks. The model builds on the
11
+ * [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model, which a
12
+ * state model can do because a config model is itself an MST tree.
13
+ */
6
14
  export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, extraConfigSlots, }: {
7
15
  pluginManager: PluginManager;
8
16
  assemblyConfigSchema: BaseAssemblyConfigSchema;
@@ -165,7 +173,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, ext
165
173
  /**
166
174
  * #action
167
175
  */
168
- addAssemblyConf(conf: AnyConfigurationModel): (import("@jbrowse/core/configuration").ConfigNodeProps<any> & import("@jbrowse/core/configuration").ConfigNodeActions & import("@jbrowse/core/configuration").ConfigNodeBrand<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>) | undefined;
176
+ addAssemblyConf(conf: AnyConfiguration): (import("@jbrowse/core/configuration").ConfigNodeProps<any> & import("@jbrowse/core/configuration").ConfigNodeActions & import("@jbrowse/core/configuration").ConfigNodeBrand<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>) | undefined;
169
177
  /**
170
178
  * #action
171
179
  */
@@ -6,13 +6,6 @@ import { expandLooseTrackConfig } from '@jbrowse/core/util/tracks';
6
6
  import { cast, getParent, getSnapshot, isStateTreeNode, types, } from '@jbrowse/mobx-state-tree';
7
7
  import { toJS } from 'mobx';
8
8
  import { JBrowseConfigF } from '../JBrowseConfig/index.js';
9
- /**
10
- * #stateModel AppCoreJBrowseModel
11
- * #category root
12
- * built on the [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model —
13
- * config models are MST trees themselves, which is why this state model is
14
- * allowed to build on one. Generally found on a property named rootModel.jbrowse
15
- */
16
9
  // A config with exactly one assembly is what every loose track and search index
17
10
  // is on, so `assemblyNames` may be left off; with several, each has to say.
18
11
  function expandLooseTracks(snapshot, pluginManager) {
@@ -42,6 +35,14 @@ function expandLooseTracks(snapshot, pluginManager) {
42
35
  : {}),
43
36
  };
44
37
  }
38
+ /**
39
+ * #stateModel AppCoreJBrowseModel
40
+ * #category root
41
+ * Holds the loaded config file, usually at `rootModel.jbrowse`, with actions
42
+ * that add and remove its assemblies and tracks. The model builds on the
43
+ * [JBrowseRootConfig](/docs/config/jbrowserootconfig) config model, which a
44
+ * state model can do because a config model is itself an MST tree.
45
+ */
45
46
  export function JBrowseModelF({ pluginManager, assemblyConfigSchema, extraConfigSlots, }) {
46
47
  const model = JBrowseConfigF({
47
48
  pluginManager,
@@ -72,6 +72,9 @@ function displayState(track) {
72
72
  return { display: display.type, error: String(e) };
73
73
  }
74
74
  }
75
+ function raisesPicker(views) {
76
+ return !!views?.some(view => view.searchPicker || raisesPicker(view.ownViews));
77
+ }
75
78
  /**
76
79
  * The drawer and any modal, for the same reason `offscreen` is reported: both
77
80
  * are on top of the views in a screenshot that otherwise looks right.
@@ -94,7 +97,7 @@ function sessionChrome(session) {
94
97
  },
95
98
  }
96
99
  : {};
97
- const dialog = s.DialogComponent
100
+ const dialog = s.DialogComponent || raisesPicker(s.views)
98
101
  ? {
99
102
  dialog: {
100
103
  note: 'a modal dialog is open over the app, so a screenshot is of the dialog',
@@ -1024,7 +1027,7 @@ const JB_HELP = `jb drives this JBrowse app programmatically (window.jb in a bro
1024
1027
 
1025
1028
  Orient first: jb.sessionSummary(). Introspect, never guess: jb.listTracks(search?, limit?) answers { total, tracks } with the trackIds; jb.describeSlots(jb.trackModel('someTrackId').activeDisplay.configuration) for the settings keys a display accepts — an unknown settings key is not an error, it lands in applyDisplaySettings' "unapplied" list as { key, reason }, so read the report; jb.inspect(node) — jb.view(), jb.trackModel('someTrackId'), session.views[0] — for its getters, actions and modelType.
1026
1029
 
1027
- The model is mobx-state-tree: mutate only through actions (raw assignment throws), and write display settings with track.applyDisplaySettings(settings). A display's grammar settings are its plot, activeDisplay.plot, by slot name: facet ('strand' or { field, domain? }), color (a CSS color or { field: 'type', domain?, range? }), rows, unit (what a row stands for: 'read' | 'chain' on alignments, 'sample' | 'haplotype' on multi-sample variants), scales, filter (['jexl:feature.score > 10']), and on a mark display marks and transform. Edit structuredClone(activeDisplay.plot), check it with activeDisplay.plotProblems(draft), which throws what a config refuses, and write it with activeDisplay.applyPlot(draft): each setting replaced whole, null resetting one. An alignments track takes the same facet, its field a read dimension ('pairOrientation', 'mapq', ...) or a tag ('tags.HP'). LinearMarkDisplay plots a track's features as ggplot2 does, on a feature, alignments, variant or quantitative track, in seven settings: marks, a list drawn in order of { mark: 'bar' | 'point' | 'rule' | 'line' | 'span' | 'text' | 'link', encoding: { y: 'score', x?, x2?, row?, color?, shape?, text?, size? }, each a feature field or a jexl: expression, a constant written { value: 'red' }, transform?: steps such as { type: 'coverage' } or a bin then an aggregate, which fill the y they write, minBpPerPx?, maxBpPerPx? }, beside transform, facet, rows, rowColor, scales ({ y: { type, domainMin, domainMax, autoscaleGroup, title } }) and filter. await view.launchTrack(trackId, {}, { type: 'LinearMarkDisplay', marks: [...] }) draws a track with it, shown already or not (on a GWASTrack, type 'LinearManhattanDisplay'). activeDisplay.notices names a mark the config cannot draw, or one whose field no loaded feature holds. Build views declaratively with jb.loadSessionSpec({ views: [{ type: 'LinearGenomeView', assembly, loc, tracks: [...] }] }), which replaces the session; jb.addView(oneViewSpec) opens one more view beside what is open; jb.setSession(document) rewrites the session as a document — what jb.mst.getSnapshot(jb.session) answers, edited: a view keeps its id and is patched in place, loc on it navigates, a { trackId } entry in its tracks opens that track. Act on a view with await view.navToLocString('BRCA1' or 'chr1:1-1000'), which also SHOWS the track whose search index answered a gene name unless a 4th arg { showHitTrack: false } says not to; await view.launchTrack(trackId, {}, settings) shows a track with settings, view.hideTrack(trackId) hides it. Arrange open views into panels with session.layoutViews({ direction: 'horizontal', children: [{ views: [viewId] }, ...] }), a leaf naming view ids or session.views indexes; await jb.fitToWindow() shrinks what is open until the session fits the window; add data with jb.addTrack({ location }) (an absolute path or a URL), or show a track the catalog already holds with jb.addTrack({ trackId, settings? }); read data with await jb.getFeatures({ trackId, loc?, assembly?, viewId?, regions?, byteLimit? }), which renames refNames ("chr1" vs "1") so the file answers and reads on the worker the track's display uses. Anything lower level is jb.require('@jbrowse/core/util') and friends, the module registry plugins link against. After changing anything, await jb.waitReady(ms) and read its notifications and notReady lists before trusting the screen.
1030
+ The model is mobx-state-tree: mutate only through actions (raw assignment throws), and write display settings with track.applyDisplaySettings(settings). A display's grammar settings are its plot, activeDisplay.plot, by slot name: facet ('strand' or { field, domain? }), color (a CSS color or { field: 'type', domain?, range? }), rows, unit (what a row stands for: 'read' | 'chain' on alignments, 'sample' | 'haplotype' on multi-sample variants), sort (an alignments row order: 'split', or { type: 'strand', pos, refName }), scales, filter (['jexl:feature.score > 10']), and on a mark display marks and transform. Edit structuredClone(activeDisplay.plot), check it with activeDisplay.plotProblems(draft), which throws what a config refuses, and write it with activeDisplay.applyPlot(draft): each setting replaced whole, null resetting one. An alignments track takes the same facet, its field a read dimension ('pairOrientation', 'mapq', ...) or a tag ('tags.HP'). LinearMarkDisplay plots a track's features as ggplot2 does, on a feature, alignments, variant or quantitative track, in seven settings: marks, a list drawn in order of { mark: 'bar' | 'point' | 'rule' | 'line' | 'span' | 'text' | 'link', encoding: { y: 'score', x?, x2?, row?, color?, shape?, text?, size? }, each a feature field or a jexl: expression, a constant written { value: 'red' }, transform?: steps such as { type: 'coverage' } or a bin then an aggregate, which fill the y they write, minBpPerPx?, maxBpPerPx? }, beside transform, facet, rows, rowColor, scales ({ y: { type, domainMin, domainMax, autoscaleGroup, title } }) and filter. await view.launchTrack(trackId, {}, { type: 'LinearMarkDisplay', marks: [...] }) draws a track with it, shown already or not (on a GWASTrack, type 'LinearManhattanDisplay'). activeDisplay.notices names a mark the config cannot draw, or one whose field no loaded feature holds. Build views declaratively with jb.loadSessionSpec({ views: [{ type: 'LinearGenomeView', assembly, loc, tracks: [...] }] }), which replaces the session; jb.addView(oneViewSpec) opens one more view beside what is open; jb.setSession(document) rewrites the session as a document — what jb.mst.getSnapshot(jb.session) answers, edited: a view keeps its id and is patched in place, loc on it navigates, a { trackId } entry in its tracks opens that track. Act on a view with await view.navToLocString('BRCA1' or 'chr1:1-1000'), which also SHOWS the track whose search index answered a gene name unless a 4th arg { showHitTrack: false } says not to; await view.launchTrack(trackId, {}, settings) shows a track with settings, view.hideTrack(trackId) hides it. Arrange open views into panels with session.layoutViews({ direction: 'horizontal', children: [{ views: [viewId] }, ...] }), a leaf naming view ids or session.views indexes; await jb.fitToWindow() shrinks what is open until the session fits the window; add data with jb.addTrack({ location }) (an absolute path or a URL), or show a track the catalog already holds with jb.addTrack({ trackId, settings? }); read data with await jb.getFeatures({ trackId, loc?, assembly?, viewId?, regions?, byteLimit? }), which renames refNames ("chr1" vs "1") so the file answers and reads on the worker the track's display uses. Anything lower level is jb.require('@jbrowse/core/util') and friends, the module registry plugins link against. After changing anything, await jb.waitReady(ms) and read its notifications and notReady lists before trusting the screen.
1028
1031
 
1029
1032
  Views nest and several can be open. jb.view(viewId?) is the open view, and jb.view(), jb.trackModel(trackId), jb.visibleRegions(), jb.addTrack and jb.getFeatures over a visible region throw naming the candidates rather than picking one when more than one view could answer — pass viewId (from jb.sessionSummary()) to say which. A synteny or breakpoint view's viewId also covers its rows: the named view answers when it can, and otherwise its rows do.
1030
1033
 
@@ -2,6 +2,8 @@ import type { MenuAction } from '../menus.ts';
2
2
  import type { MenuItem } from '@jbrowse/core/ui/menuItems';
3
3
  /**
4
4
  * #stateModel RootAppMenuMixin
5
+ * Adds actions to the root model that let plugins add menus and menu items to
6
+ * the app bar.
5
7
  */
6
8
  export declare function RootAppMenuMixin(): import("@jbrowse/mobx-state-tree").IModelType<{}, {
7
9
  mutableMenuActions: MenuAction[];
@@ -1,6 +1,8 @@
1
1
  import { types } from '@jbrowse/mobx-state-tree';
2
2
  /**
3
3
  * #stateModel RootAppMenuMixin
4
+ * Adds actions to the root model that let plugins add menus and menu items to
5
+ * the app bar.
4
6
  */
5
7
  export function RootAppMenuMixin() {
6
8
  return types
@@ -1,6 +1,6 @@
1
1
  export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.ts';
2
2
  export { addSessionTracks, launchSpecView, launchableSpecView, loadSessionSpec, viewTypeProblem, } from './loadSessionSpec.ts';
3
- export { parseSessionSpecUrl } from './parseSessionSpecUrl.ts';
3
+ export { parseSessionSnapshotUrl, parseSessionSpecUrl, } from './parseSessionSpecUrl.ts';
4
4
  export type { LgvUrlInit } from './lgvUrlInit.ts';
5
- export type { ParsedSessionSpec } from './parseSessionSpecUrl.ts';
5
+ export type { ParsedSessionSnapshotUrl, ParsedSessionSpec, } from './parseSessionSpecUrl.ts';
6
6
  export type { LayoutNode, ViewSpec } from './types.ts';
@@ -1,3 +1,3 @@
1
1
  export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.js';
2
2
  export { addSessionTracks, launchSpecView, launchableSpecView, loadSessionSpec, viewTypeProblem, } from './loadSessionSpec.js';
3
- export { parseSessionSpecUrl } from './parseSessionSpecUrl.js';
3
+ export { parseSessionSnapshotUrl, parseSessionSpecUrl, } from './parseSessionSpecUrl.js';
@@ -4,4 +4,23 @@ export interface ParsedSessionSpec {
4
4
  spec: Omit<SessionSpec, 'sessionName'>;
5
5
  sessionName?: string;
6
6
  }
7
+ export interface ParsedSessionSnapshotUrl {
8
+ configUrl: string;
9
+ /** the `session=` value as it is in the link, prefix included, undecoded */
10
+ session: string;
11
+ /** a `share-` link's key; the share service never sees it */
12
+ password?: string;
13
+ /** the JBrowse Web page the link points at, which a relative shareURL is relative to */
14
+ pageUrl: string;
15
+ }
16
+ /**
17
+ * The session snapshot a link hands over whole — carried in it (`encoded-…`,
18
+ * `json-…`) or stored by the share service under the id it names (`share-…`) —
19
+ * with the config it applies to. Undefined for any other link.
20
+ *
21
+ * A link with no `config=` means the instance's own `config.json`, as it does
22
+ * to the JBrowse Web page the link points at. A snapshot names assemblies and
23
+ * tracks by id and holds none of them, so there is always a config to fetch.
24
+ */
25
+ export declare function parseSessionSnapshotUrl(input: string): ParsedSessionSnapshotUrl | undefined;
7
26
  export declare function parseSessionSpecUrl(input: string): ParsedSessionSpec;
@@ -134,6 +134,35 @@ function readSessionTracks(params) {
134
134
  }
135
135
  return parsed;
136
136
  }
137
+ /**
138
+ * The session snapshot a link hands over whole — carried in it (`encoded-…`,
139
+ * `json-…`) or stored by the share service under the id it names (`share-…`) —
140
+ * with the config it applies to. Undefined for any other link.
141
+ *
142
+ * A link with no `config=` means the instance's own `config.json`, as it does
143
+ * to the JBrowse Web page the link points at. A snapshot names assemblies and
144
+ * tracks by id and holds none of them, so there is always a config to fetch.
145
+ */
146
+ export function parseSessionSnapshotUrl(input) {
147
+ let url;
148
+ try {
149
+ url = unwrapProtocolUrl(new URL(input.trim()));
150
+ }
151
+ catch {
152
+ return undefined;
153
+ }
154
+ const params = readAllQueryParams(url);
155
+ const session = params.get('session');
156
+ return session && /^(share|encoded|json)-/.test(session)
157
+ ? {
158
+ configUrl: new URL(params.get('config') ?? 'config.json', url.href)
159
+ .href,
160
+ session,
161
+ password: params.get('password') ?? undefined,
162
+ pageUrl: url.href,
163
+ }
164
+ : undefined;
165
+ }
137
166
  export function parseSessionSpecUrl(input) {
138
167
  let url;
139
168
  try {
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Suspense, useCallback, useEffect, useMemo } from 'react';
2
+ import { Suspense, useCallback, useMemo } from 'react';
3
3
  import { makeStyles } from '@jbrowse/core/util/tss-react';
4
- import { autorun } from 'mobx';
5
4
  import { observer } from 'mobx-react';
6
5
  import ViewStack from '../ui/App/ViewStack.js';
7
6
  import { ViewLauncher } from '../ui/App/lazyParts.js';
@@ -27,13 +26,6 @@ const useStyles = makeStyles()(theme => ({
27
26
  export const WorkspaceContainer = observer(function WorkspaceContainer({ session, }) {
28
27
  const { classes } = useStyles();
29
28
  const { drag, handlers } = useLayoutDrag(session);
30
- // #region autorunInEffect
31
- useEffect(() => autorun(() => {
32
- // homes newly launched views; reads session.views here because an
33
- // action's reads are untracked
34
- session.homeUnassignedViews(session.views.map(v => v.id));
35
- }), [session]);
36
- // #endregion
37
29
  // the layout does not own views, so every close gesture goes through here
38
30
  // or leaks them
39
31
  const closeViews = useCallback((viewIds) => {
@@ -65,7 +57,7 @@ export const WorkspaceContainer = observer(function WorkspaceContainer({ session
65
57
  renderPanelActions: panel => (_jsx(WorkspacePanelActions, { panel: panel, session: session, onClose: () => {
66
58
  closePanel(panel.id);
67
59
  } })),
68
- renderTabLabel: tab => (_jsx(WorkspaceTab, { tab: tab, views: viewsOf(session, tab.viewIds), session: session, layout: session, onClose: () => {
60
+ renderTabLabel: tab => (_jsx(WorkspaceTab, { tab: tab, views: viewsOf(session, tab.viewIds), session: session, onClose: () => {
69
61
  closeTab(tab.id);
70
62
  } })),
71
63
  renderTabContent: tab => {
@@ -33,7 +33,7 @@ export const WorkspacePanelActions = observer(function WorkspacePanelActions({ p
33
33
  const canClose = session.panels.length > 1;
34
34
  const maximized = session.maximizedPanelId === panel.id;
35
35
  const tile = (mode) => {
36
- session.tileViews(mode, session.views.map(v => v.id));
36
+ session.tileViews(mode);
37
37
  };
38
38
  return (_jsxs("div", { className: classes.actions, children: [_jsx(CascadingMenuButton, { menuItems: [
39
39
  {
@@ -2,11 +2,10 @@ import type { WorkspaceSessionType } from '../ui/App/types.ts';
2
2
  import type { WorkspaceLayout } from './model.ts';
3
3
  import type { TabNode } from './tree.ts';
4
4
  import type { AbstractViewModel } from '@jbrowse/core/util';
5
- export declare const WorkspaceTab: ({ tab, views, session, layout, onClose, }: {
5
+ export declare const WorkspaceTab: ({ tab, views, session, onClose, }: {
6
6
  tab: TabNode;
7
7
  views: AbstractViewModel[];
8
- session: WorkspaceSessionType;
9
- layout: WorkspaceLayout;
8
+ session: WorkspaceSessionType & WorkspaceLayout;
10
9
  /** closes the tab and the views it holds */
11
10
  onClose: () => void;
12
11
  }) => import("react").JSX.Element;
@@ -31,7 +31,7 @@ const useStyles = makeStyles()(theme => ({
31
31
  flex: 1,
32
32
  },
33
33
  }));
34
- export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session, layout, onClose, }) {
34
+ export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session, onClose, }) {
35
35
  const { classes } = useStyles();
36
36
  const [editing, setEditing] = useState(false);
37
37
  const [draft, setDraft] = useState('');
@@ -44,7 +44,7 @@ export const WorkspaceTab = observer(function WorkspaceTab({ tab, views, session
44
44
  const save = () => {
45
45
  const name = draft.trim();
46
46
  const automatic = tabDisplayName({ ...tab, title: undefined }, views, session);
47
- layout.renameTab(tab.id, name && name !== automatic ? name : undefined);
47
+ session.renameTab(tab.id, name && name !== automatic ? name : undefined);
48
48
  setEditing(false);
49
49
  };
50
50
  return (_jsx("div", { className: classes.tab, children: editing ? (_jsx(InputBase, { autoFocus: true, className: classes.editInput, value: draft, onChange: e => {
@@ -97,10 +97,6 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
97
97
  findTab(tabId: string): TabHome | undefined;
98
98
  tabContainingView(viewId: string): TabHome | undefined;
99
99
  panelContainingView(viewId: string): PanelNode | undefined;
100
- /** The views a tab renders: its members, in `session.views` order. */
101
- viewIdsForTab(tabId: string, order: string[]): string[];
102
- /** The tab a panel is showing, or its first. */
103
- activeTabOf(panelId: string): TabNode | undefined;
104
100
  /**
105
101
  * The maximized cell alone, or the whole tree. The cell is resized to 1
106
102
  * because CSS hands out free space by grow factor only up to a total of
@@ -144,35 +140,32 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
144
140
  applyLayoutSpec(spec: LayoutSpecNode): string[];
145
141
  /**
146
142
  * ViewMenu's "move to new tab": the view leaves its tab for a new one.
147
- * `allViewIds` is EVERY view in the session, defaulting to the host's
148
- * own list, since homing drops any view the list omits.
149
143
  */
150
- moveViewToNewTab(viewId: string, allViewIds?: string[]): string | undefined;
144
+ moveViewToNewTab(viewId: string): string | undefined;
151
145
  /**
152
146
  * ViewMenu's "move to split": the view leaves for a new cell to the
153
147
  * right (`row`) or below (`column`) of its own.
154
148
  */
155
- moveViewToSplit(viewId: string, direction: 'row' | 'column', allViewIds?: string[]): string | undefined;
149
+ moveViewToSplit(viewId: string, direction: 'row' | 'column'): string | undefined;
156
150
  /**
157
151
  * ViewMenu's "move to tab": the view joins an existing tab, which
158
152
  * becomes the one shown.
159
153
  */
160
- moveViewToTab(viewId: string, tabId: string, allViewIds?: string[]): void;
154
+ moveViewToTab(viewId: string, tabId: string): void;
161
155
  homeUnassignedViews(viewIds: string[]): void;
162
156
  } & {
163
157
  /**
164
158
  * Move one view to a new tab or a split beside its cell, keeping the
165
159
  * rest of the arrangement. PUBLIC API: protein3d and msaview call it
166
- * with the move alone, so `allViewIds` stays optional; it is read only
167
- * on a host with no view list.
160
+ * with the move alone. The second argument is an old plugin signature;
161
+ * the session's own views are read instead.
168
162
  */
169
- setPendingMove(move: PendingMove | undefined, allViewIds?: string[]): void;
163
+ setPendingMove(move: PendingMove | undefined, _allViewIds?: string[]): void;
170
164
  /**
171
165
  * Re-arrange the whole workspace, one view per cell, in one of four
172
- * shapes. Pass `allViewIds` in `session.views` order so there is
173
- * nothing for `orderViews` to apply.
166
+ * shapes, in `session.views` order.
174
167
  */
175
- tileViews(mode: TileMode, allViewIds: string[]): void;
168
+ tileViews(mode: TileMode): void;
176
169
  /**
177
170
  * #action
178
171
  * Arrange the session's views into panels: `applyLayoutSpec`, then
@@ -183,6 +176,8 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
183
176
  * re-layout both call it.
184
177
  */
185
178
  layoutViews(spec: LayoutSpecNode): string[];
179
+ } & {
180
+ afterAttach(): void;
186
181
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
187
182
  export type WorkspaceLayoutMixinType = ReturnType<typeof WorkspaceLayoutMixin>;
188
183
  export interface WorkspaceLayout extends Instance<WorkspaceLayoutMixinType> {