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

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 (55) hide show
  1. package/esm/HistoryManagement/index.d.ts +3 -0
  2. package/esm/JBrowseConfig/RootConfiguration.d.ts +1 -8
  3. package/esm/JBrowseConfig/RootConfiguration.js +2 -6
  4. package/esm/JBrowseConfig/index.d.ts +1 -8
  5. package/esm/JBrowseModel/index.d.ts +1 -8
  6. package/esm/JbApi/jbApi.d.ts +2 -2
  7. package/esm/JbApi/jbApi.js +12 -10
  8. package/esm/SessionSpec/loadSessionSpec.js +2 -12
  9. package/esm/WorkspaceLayout/LayoutRenderer.d.ts +0 -10
  10. package/esm/WorkspaceLayout/LayoutRenderer.js +34 -101
  11. package/esm/WorkspaceLayout/PanelView.js +19 -45
  12. package/esm/WorkspaceLayout/TabStrip.d.ts +2 -2
  13. package/esm/WorkspaceLayout/TabStrip.js +36 -104
  14. package/esm/WorkspaceLayout/WorkspaceContainer.d.ts +0 -9
  15. package/esm/WorkspaceLayout/WorkspaceContainer.js +9 -34
  16. package/esm/WorkspaceLayout/WorkspacePanelActions.d.ts +1 -16
  17. package/esm/WorkspaceLayout/WorkspacePanelActions.js +45 -50
  18. package/esm/WorkspaceLayout/WorkspaceTab.d.ts +1 -16
  19. package/esm/WorkspaceLayout/WorkspaceTab.js +11 -47
  20. package/esm/WorkspaceLayout/dropZone.d.ts +7 -37
  21. package/esm/WorkspaceLayout/dropZone.js +7 -44
  22. package/esm/WorkspaceLayout/model.d.ts +42 -112
  23. package/esm/WorkspaceLayout/model.js +139 -268
  24. package/esm/WorkspaceLayout/panelChrome.d.ts +4 -7
  25. package/esm/WorkspaceLayout/panelChrome.js +0 -2
  26. package/esm/WorkspaceLayout/spec.d.ts +10 -51
  27. package/esm/WorkspaceLayout/spec.js +12 -80
  28. package/esm/WorkspaceLayout/splitter.d.ts +3 -19
  29. package/esm/WorkspaceLayout/splitter.js +5 -21
  30. package/esm/WorkspaceLayout/tabName.d.ts +8 -0
  31. package/esm/WorkspaceLayout/tabName.js +14 -0
  32. package/esm/WorkspaceLayout/tree.d.ts +19 -76
  33. package/esm/WorkspaceLayout/tree.js +29 -122
  34. package/esm/WorkspaceLayout/useLayoutDrag.d.ts +4 -22
  35. package/esm/WorkspaceLayout/useLayoutDrag.js +46 -174
  36. package/esm/WorkspaceLayout/usePointerGesture.d.ts +24 -0
  37. package/esm/WorkspaceLayout/usePointerGesture.js +83 -0
  38. package/esm/WorkspaceLayout/workspaceTheme.d.ts +27 -0
  39. package/esm/WorkspaceLayout/workspaceTheme.js +37 -0
  40. package/esm/ui/App/App.js +3 -0
  41. package/esm/ui/App/JBrowseTabMenu.js +1 -1
  42. package/esm/ui/App/ThemeModeButton.js +5 -4
  43. package/esm/ui/App/ViewMenu.js +47 -29
  44. package/esm/ui/App/ViewsContainer.js +3 -4
  45. package/esm/ui/App/lazyParts.d.ts +0 -5
  46. package/esm/ui/App/lazyParts.js +0 -1
  47. package/esm/ui/App/preloadAppShell.js +3 -6
  48. package/esm/ui/App/types.d.ts +3 -2
  49. package/esm/ui/App/useViewVisibility.d.ts +1 -1
  50. package/esm/ui/App/useViewVisibility.js +1 -1
  51. package/package.json +5 -5
  52. package/esm/WorkspaceLayout/dockviewTheme.d.ts +0 -69
  53. package/esm/WorkspaceLayout/dockviewTheme.js +0 -82
  54. package/esm/ui/App/ClassicViewsContainer.d.ts +0 -6
  55. package/esm/ui/App/ClassicViewsContainer.js +0 -22
@@ -1,11 +1,4 @@
1
- /**
2
- * Where a pointer sitting over a panel would drop a view.
3
- *
4
- * Kept as geometry over a plain rect rather than reading the DOM, because this
5
- * is the part of drag-and-drop with actual decisions in it — the edge band, the
6
- * tie-break between two edges, what happens in the middle — and all of it is
7
- * checkable without rendering anything or synthesising a pointer.
8
- */
1
+ /** Drop geometry over plain rects, so it is testable without a DOM. */
9
2
  export type DropZone = 'center' | 'left' | 'right' | 'top' | 'bottom';
10
3
  export interface Rect {
11
4
  left: number;
@@ -13,11 +6,7 @@ export interface Rect {
13
6
  width: number;
14
7
  height: number;
15
8
  }
16
- /**
17
- * Where a drop would land. `zone` alone says which half of a cell; `strip` is
18
- * set when the pointer is on the tab strip itself, which is a finer answer than
19
- * `center` — that one appends, this one says where in the order.
20
- */
9
+ /** `strip` is set on the tab strip, and gives a position in the tab order. */
21
10
  export interface DropTarget {
22
11
  zone: DropZone;
23
12
  strip?: StripDrop;
@@ -30,33 +19,14 @@ export interface StripDrop {
30
19
  left: number;
31
20
  }
32
21
  /**
33
- * `center` means "add as a tab in this panel"; an edge means "split this panel
34
- * and put the view in the new half".
35
- *
36
- * The bands are proportional rather than a fixed pixel depth so a narrow panel
37
- * stays droppable — at a fixed 40px a 100px-wide panel would be all edge and
38
- * have no centre to drop a tab into. `edgeFraction` is capped below 0.5 for the
39
- * same reason: at 0.5 the centre vanishes entirely.
40
- *
41
- * Corners go to whichever edge the pointer is proportionally deeper into, so
42
- * the diagonal is the tie-break and neither axis silently wins. **This is a
43
- * deliberate divergence from dockview**, whose `calculateQuadrantAsPercentage`
44
- * tests left, right, top, bottom in that order and returns the first hit — so
45
- * in its top-left corner `left` always wins, however far into the top band the
46
- * pointer is. Its band is 20% where this defaults to 25%.
22
+ * `center` adds as a tab; an edge splits the panel. Bands are proportional and
23
+ * capped below half, so a narrow panel keeps a centre. A corner goes to the
24
+ * edge the pointer is proportionally deeper into.
47
25
  */
48
26
  export declare function dropZoneAt(rect: Rect, x: number, y: number, edgeFraction?: number): DropZone;
49
27
  /**
50
- * Which gap between tabs a pointer at `x` is nearest — the insertion index a
51
- * drop there would use, and the x to draw the caret at.
52
- *
53
- * The test is each tab's MIDPOINT rather than its edges, so every x belongs to
54
- * exactly one gap and there is no dead band between tabs where a drop would
55
- * have to fall back to appending. `rects` are in strip order and `x` is in
56
- * their coordinate space, whatever that is — this function does not know
57
- * whether it was handed viewport or panel-relative numbers.
58
- *
59
- * An empty strip is index 0, which is the only sensible place for a first tab.
28
+ * The gap between tabs nearest `x`, by tab midpoint so every x has exactly one.
29
+ * `x` is in the rects' coordinate space, whichever that is.
60
30
  */
61
31
  export declare function stripDropAt(rects: Rect[], x: number): StripDrop;
62
32
  /**
@@ -1,26 +1,8 @@
1
+ /** Drop geometry over plain rects, so it is testable without a DOM. */
1
2
  /**
2
- * Where a pointer sitting over a panel would drop a view.
3
- *
4
- * Kept as geometry over a plain rect rather than reading the DOM, because this
5
- * is the part of drag-and-drop with actual decisions in it — the edge band, the
6
- * tie-break between two edges, what happens in the middle — and all of it is
7
- * checkable without rendering anything or synthesising a pointer.
8
- */
9
- /**
10
- * `center` means "add as a tab in this panel"; an edge means "split this panel
11
- * and put the view in the new half".
12
- *
13
- * The bands are proportional rather than a fixed pixel depth so a narrow panel
14
- * stays droppable — at a fixed 40px a 100px-wide panel would be all edge and
15
- * have no centre to drop a tab into. `edgeFraction` is capped below 0.5 for the
16
- * same reason: at 0.5 the centre vanishes entirely.
17
- *
18
- * Corners go to whichever edge the pointer is proportionally deeper into, so
19
- * the diagonal is the tie-break and neither axis silently wins. **This is a
20
- * deliberate divergence from dockview**, whose `calculateQuadrantAsPercentage`
21
- * tests left, right, top, bottom in that order and returns the first hit — so
22
- * in its top-left corner `left` always wins, however far into the top band the
23
- * pointer is. Its band is 20% where this defaults to 25%.
3
+ * `center` adds as a tab; an edge splits the panel. Bands are proportional and
4
+ * capped below half, so a narrow panel keeps a centre. A corner goes to the
5
+ * edge the pointer is proportionally deeper into.
24
6
  */
25
7
  export function dropZoneAt(rect, x, y, edgeFraction = 0.25) {
26
8
  const fraction = Math.min(Math.max(edgeFraction, 0), 0.49);
@@ -43,16 +25,8 @@ export function dropZoneAt(rect, x, y, edgeFraction = 0.25) {
43
25
  return depths.reduce((best, candidate) => candidate.depth > best.depth ? candidate : best).zone;
44
26
  }
45
27
  /**
46
- * Which gap between tabs a pointer at `x` is nearest — the insertion index a
47
- * drop there would use, and the x to draw the caret at.
48
- *
49
- * The test is each tab's MIDPOINT rather than its edges, so every x belongs to
50
- * exactly one gap and there is no dead band between tabs where a drop would
51
- * have to fall back to appending. `rects` are in strip order and `x` is in
52
- * their coordinate space, whatever that is — this function does not know
53
- * whether it was handed viewport or panel-relative numbers.
54
- *
55
- * An empty strip is index 0, which is the only sensible place for a first tab.
28
+ * The gap between tabs nearest `x`, by tab midpoint so every x has exactly one.
29
+ * `x` is in the rects' coordinate space, whichever that is.
56
30
  */
57
31
  export function stripDropAt(rects, x) {
58
32
  for (const [i, rect] of rects.entries()) {
@@ -66,18 +40,7 @@ export function stripDropAt(rects, x) {
66
40
  left: last ? last.left + last.width : 0,
67
41
  };
68
42
  }
69
- /**
70
- * What each zone means, in one table.
71
- *
72
- * `split` is the split a drop there asks for — which way the panel divides and
73
- * whether the new half goes first; `center` is not a split. `rect` is where the
74
- * indicator is drawn, as CSS percentages of the panel.
75
- *
76
- * One table rather than two switches because the pair has to agree: the shaded
77
- * half IS the half the drop lands in, and that is the whole content of the
78
- * indicator. Written apart, `right` could shade the left half and nothing would
79
- * be wrong with either function on its own.
80
- */
43
+ // one table, so the shaded half and the half a drop lands in cannot disagree
81
44
  const ZONES = {
82
45
  left: {
83
46
  split: { direction: 'row', before: true },
@@ -78,29 +78,16 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
78
78
  }>>, [undefined]>;
79
79
  activePanelId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
80
80
  /**
81
- * Show only this cell, at the size of the whole workspace.
82
- *
83
- * Deliberately HERE and not a `maximized` flag on `PanelNode`. On the
84
- * node it would be inside `tree.ts`, the half that carries the risk and
85
- * is proven by a randomised operation sequence asserting canonical form
86
- * after every step — and every operation would then have to say what it
87
- * does to the flag: a split of a maximized panel, a drag of its last tab
88
- * out, a normalize that collapses it into its parent. Beside
89
- * `activePanelId` it is the same class of thing as `activePanelId`,
90
- * including its failure mode, which `livePanelIds` already repairs.
81
+ * Show only this cell, at the size of the whole workspace. Kept here
82
+ * rather than as a flag on `PanelNode` so no `tree.ts` operation has to
83
+ * say what it does to it.
91
84
  */
92
85
  maximizedPanelId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
93
86
  }, {
94
87
  /**
95
- * The plain tree the pure functions take.
96
- *
97
- * `getSnapshot` is a `keepAlive` computed, so this is cached and
98
- * referentially stable — which also lets MST's reconcile short-circuit on
99
- * identity when `apply` writes an untouched subtree back.
100
- *
101
- * Uncast on purpose: the models below and the interfaces in `tree.ts` are
102
- * two spellings of one shape, and this assignment is the only thing that
103
- * checks they agree.
88
+ * Referentially stable, since `getSnapshot` is cached. Uncast on
89
+ * purpose: this assignment is what checks the models above agree with
90
+ * the interfaces in `tree.ts`.
104
91
  */
105
92
  readonly tree: LayoutTree;
106
93
  } & {
@@ -115,31 +102,18 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
115
102
  /** The tab a panel is showing, or its first. */
116
103
  activeTabOf(panelId: string): TabNode | undefined;
117
104
  /**
118
- * What to render: the maximized cell alone, or the whole tree.
119
- *
120
- * Sized to 1 rather than handed over as it sits. A pane's `size` is its
121
- * share of its siblings, and CSS distributes free space by grow factor
122
- * only up to a total of 1 — so a cell that was a third of a row, alone
123
- * in the workspace with `flexGrow: 0.33`, draws a third of the window
124
- * and leaves the rest blank.
105
+ * The maximized cell alone, or the whole tree. The cell is resized to 1
106
+ * because CSS hands out free space by grow factor only up to a total of
107
+ * 1, so a third-of-a-row cell would draw a third of the window.
125
108
  */
126
109
  readonly visibleTree: LayoutTree;
127
110
  } & {
128
111
  setActivePanelId(panelId: string | undefined): void;
129
112
  /**
130
- * Show one cell at the size of the workspace, or go back.
131
- *
132
- * A toggle rather than a pair, because the gesture is a toggle: the
133
- * strip's double-click and the cell menu's one item both mean "this
134
- * cell, or not any more". Maximizing a DIFFERENT cell while one is
135
- * already maximized moves the mode rather than restoring, which is
136
- * what the menu item on another cell's strip is asking for.
137
- *
138
- * Mounts no views that were not mounted — it is the same cell showing
139
- * the same tab — and unmounts every other cell's, so the WebGL2
140
- * context ceiling (`agent-docs/reference/GPU_CONTEXT_BUDGET.md`) can
141
- * only go down. That is the reason it is this and not a `display:
142
- * none` over a still-mounted workspace.
113
+ * Show one cell at the size of the workspace, or go back; naming a
114
+ * different cell moves the mode. Unmounts every other cell's views
115
+ * rather than hiding them, to stay under the WebGL2 context ceiling
116
+ * (`agent-docs/reference/GPU_PORTABILITY.md`).
143
117
  */
144
118
  toggleMaximizedPanel(panelId: string): void;
145
119
  restorePanels(): void;
@@ -151,106 +125,62 @@ export declare function WorkspaceLayoutMixin(): import("@jbrowse/mobx-state-tree
151
125
  /** "New empty tab": a tab in an existing cell, showing the launcher. */
152
126
  addTab(panelId: string, viewIds?: string[]): TabNode | undefined;
153
127
  /**
154
- * Close a tab, and the cell with it if that was its last.
155
- *
156
- * A cell whose tabs are all gone is the state `pruneEmptyPanel` was
157
- * written for — "dragging the last tab out of a split and leaving a
158
- * blank half is the one place an empty panel is clearly not what was
159
- * meant" — and closing that tab arrives at the identical half by a
160
- * different gesture. It rendered nothing at all, not even the launcher
161
- * an empty TAB shows, so the only way back out of it was the `+`.
162
- *
163
- * `pruneEmptyPanel` carries both guards already: a cell with tabs left
164
- * stays, and the last cell in the workspace stays whatever happens to
165
- * it, since there is nowhere for the tree to collapse to.
128
+ * Close a tab, and its cell too if that was the last tab and not the
129
+ * workspace's last cell: a tabless cell renders nothing at all.
166
130
  */
167
131
  closeTab(tabId: string): void;
168
132
  addViewToTab(tabId: string, viewId: string): void;
169
- /**
170
- * Drop a dragged tab into an existing panel, as a tab.
171
- *
172
- * One action, so the tree never exists in a state where the tab is in
173
- * both panels or neither. The imperative bridge needed an explicit
174
- * `runInAction` around the unassign+reassign pair for exactly this, and
175
- * a comment explaining that without it the reconcile autorun would
176
- * observe the gap and re-home the view.
177
- */
133
+ /** Drop a dragged tab into an existing panel, as a tab. */
178
134
  dropTabInPanel(tabId: string, targetPanelId: string, index?: number): void;
179
135
  /** Drop a dragged tab on a panel edge: split, and land in the new half. */
180
136
  dropTabInNewSplit(tabId: string, targetPanelId: string, direction: 'row' | 'column', before: boolean): string | undefined;
181
137
  setSizes(branchId: string, sizes: number[]): void;
182
138
  /**
183
- * Arrange the workspace as a spec states.
184
- *
185
- * The spec is the same shape a session spec's `layout` takes: a leaf's
186
- * `views` names views by index into `session.views` or by id, so
187
- * `{ direction: 'horizontal', children: [{ views: [0] }, { views: [1] }] }`
188
- * means here what it means in a link. A leaf spelled any other way, an
189
- * index past the end or an id no view has throws rather than arranging
190
- * nothing — an untyped caller used to collapse the workspace into one
191
- * blank tab that way.
192
- *
193
- * There is no `init` property and no standing request: the spec is
194
- * converted and *becomes* the layout, here and now. `init` existed only
195
- * because dockview had to be told, could not be told before it mounted,
196
- * and had to be told again afterwards — three problems that all came
197
- * from the layout living somewhere this action could not reach.
139
+ * Arrange the workspace as a spec states, in the shape a session
140
+ * spec's `layout` takes: a leaf's `views` names views by index into
141
+ * `session.views` or by id. A malformed leaf, an index past the end or
142
+ * an unknown id throws.
198
143
  */
199
144
  applyLayoutSpec(spec: LayoutSpecNode): string[];
200
145
  /**
201
146
  * ViewMenu's "move to new tab": the view leaves its tab for a new one.
202
- *
203
147
  * `allViewIds` is EVERY view in the session, defaulting to the host's
204
- * own list — homing drops any view the list does not name, so the
205
- * `[viewId]` default this used to carry unhomed all the others.
148
+ * own list, since homing drops any view the list omits.
206
149
  */
207
150
  moveViewToNewTab(viewId: string, allViewIds?: string[]): string | undefined;
208
151
  /**
209
- * ViewMenu's "move to split view": the view leaves for a new cell.
210
- * `allViewIds` is every view in the session — see `moveViewToNewTab`.
152
+ * ViewMenu's "move to split": the view leaves for a new cell to the
153
+ * right (`row`) or below (`column`) of its own.
154
+ */
155
+ moveViewToSplit(viewId: string, direction: 'row' | 'column', allViewIds?: string[]): string | undefined;
156
+ /**
157
+ * ViewMenu's "move to tab": the view joins an existing tab, which
158
+ * becomes the one shown.
211
159
  */
212
- moveViewToSplitRight(viewId: string, allViewIds?: string[]): string | undefined;
160
+ moveViewToTab(viewId: string, tabId: string, allViewIds?: string[]): void;
213
161
  homeUnassignedViews(viewIds: string[]): void;
214
162
  } & {
215
163
  /**
216
- * Move one view relative to the others. PUBLIC API: an external plugin
217
- * calls this behind a `'setPendingMove' in session` guard
218
- * (jbrowse-plugin-protein3d, putting a protein view beside its genome
219
- * view). It survived the last storage change by being kept as sugar, and
220
- * it survives this one the same way — a capability-detecting caller
221
- * cannot tell you it lost a capability.
222
- *
223
- * **`allViewIds` is therefore OPTIONAL, and has to stay that way.** The
224
- * plugin passes the move alone, because that was the whole signature when
225
- * its call site was written; requiring the second argument threw
226
- * `undefined.filter` out of a launch the plugin does not wrap, and the
227
- * figure was again the only thing that noticed. Keeping the NAME is half
228
- * of not breaking a runtime lookup — the call has to keep working as it
229
- * is spelled.
164
+ * Move one view to a new tab or a split beside its cell, keeping the
165
+ * 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.
230
168
  */
231
169
  setPendingMove(move: PendingMove | undefined, allViewIds?: string[]): void;
232
170
  /**
233
- * The whole-workspace re-arrange: every view one cell, in one of four
234
- * shapes. Restored from the dockview header's four "Global:" commands,
235
- * which went with that component and were not reimplemented.
236
- *
237
- * `allViewIds` is passed in rather than read off the session for the same
238
- * reason `moveViewToNewTab` takes it: this mixin owns the tree and has no
239
- * view list of its own. Passing `session.views` order means the
240
- * arrangement it states is already the order views render in, so unlike a
241
- * session spec's layout there is nothing for `orderViews` to apply.
171
+ * 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.
242
174
  */
243
175
  tileViews(mode: TileMode, allViewIds: string[]): void;
244
176
  /**
245
177
  * #action
246
- * Arrange the session's views into panels. Calls `applyLayoutSpec`,
247
- * turns workspaces mode on for this session (a layout renders nowhere
248
- * else), and orders `session.views` to the spec's top-to-bottom
249
- * order, which tabs read their order from. Without the last two steps
250
- * the layout applies but does not display, or the tabs appear in the
251
- * wrong order. Leaves take view ids or indexes into `session.views`; a
252
- * layout that seats no view throws rather than leaving a blank tab. A
253
- * session spec's `layout` and an agent's live re-layout both call it.
178
+ * Arrange the session's views into panels: `applyLayoutSpec`, then
179
+ * `session.views` ordered to the spec's top-to-bottom order, which tabs
180
+ * read their order from. Leaves take view ids or indexes into
181
+ * `session.views`; a layout that seats no view throws rather than
182
+ * leaving a blank tab. A session spec's `layout` and an agent's live
183
+ * re-layout both call it.
254
184
  */
255
185
  layoutViews(spec: LayoutSpecNode): string[];
256
186
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;