@jbrowse/core 5.0.0-beta.1 → 5.0.0-beta.3
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.
- package/README.md +112 -43
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +2 -2
- package/esm/BaseFeatureWidget/index.d.ts +1 -1
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
- package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
- package/esm/BaseFeatureWidget/types.d.ts +10 -2
- package/esm/PluginLoader.d.ts +1 -0
- package/esm/PluginLoader.js +52 -8
- package/esm/PluginManager.d.ts +99 -17
- package/esm/PluginManager.js +194 -26
- package/esm/ReExports/BaseFeatureDetails.js +1 -1
- package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
- package/esm/ReExports/MuiDataGridReExports.js +2 -2
- package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
- package/esm/ReExports/barrelOnlyNames.js +63 -0
- package/esm/ReExports/modules.js +31 -109
- package/esm/ReExports/publicTracks.d.ts +1 -0
- package/esm/ReExports/publicTracks.js +14 -0
- package/esm/ReExports/publicUi.d.ts +4 -0
- package/esm/ReExports/publicUi.js +33 -0
- package/esm/ReExports/publicUtil.d.ts +1 -1
- package/esm/ReExports/publicUtil.js +8 -4
- package/esm/ReExports/sharedModules.d.ts +96 -0
- package/esm/ReExports/sharedModules.js +66 -0
- package/esm/ReExports/uiStub.d.ts +2 -0
- package/esm/ReExports/uiStub.js +11 -0
- package/esm/ReExports/workerModules.d.ts +2 -0
- package/esm/ReExports/workerModules.js +15 -0
- package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
- package/esm/ReExports/workerNamespaceNames.js +281 -0
- package/esm/configuration/configurationSchema.d.ts +5 -38
- package/esm/configuration/configurationSchema.js +64 -40
- package/esm/configuration/index.d.ts +2 -2
- package/esm/configuration/index.js +1 -1
- package/esm/configuration/promotableDefaults.d.ts +54 -19
- package/esm/configuration/promotableDefaults.js +117 -48
- package/esm/configuration/promotablePin.d.ts +50 -40
- package/esm/configuration/promotableResolve.d.ts +1 -1
- package/esm/configuration/promotableResolve.js +1 -1
- package/esm/configuration/tabixIndexFields.d.ts +2 -2
- package/esm/configuration/tabixIndexFields.js +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +12 -0
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +35 -4
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +41 -0
- package/esm/data_adapters/BaseAdapter/featureDensity.js +32 -0
- package/esm/data_adapters/BaseAdapter/index.d.ts +2 -1
- package/esm/data_adapters/BaseAdapter/index.js +1 -0
- package/esm/data_adapters/BaseAdapter/stats.d.ts +33 -1
- package/esm/data_adapters/BaseAdapter/stats.js +52 -13
- package/esm/data_adapters/BaseAdapter/types.d.ts +3 -8
- package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
- package/esm/pluggableElementTypes/AdapterType.js +1 -1
- package/esm/pluggableElementTypes/DisplayType.d.ts +4 -12
- package/esm/pluggableElementTypes/DisplayType.js +3 -10
- package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
- package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
- package/esm/pluggableElementTypes/ViewType.d.ts +20 -4
- package/esm/pluggableElementTypes/ViewType.js +32 -4
- package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
- package/esm/pluggableElementTypes/extendElementType.js +9 -5
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +44 -3
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +75 -2
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +21 -0
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +34 -2
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +49 -0
- package/esm/pluggableElementTypes/models/BaseViewModel.js +28 -0
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +14 -10
- package/esm/pluggableElementTypes/models/assertDisplayContract.js +25 -32
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
- package/esm/rpc/RpcRegistry.d.ts +10 -0
- package/esm/rpc/byteBudget.d.ts +9 -0
- package/esm/rpc/coreRpcMethods.d.ts +1 -0
- package/esm/rpc/coreRpcMethods.js +1 -0
- package/esm/rpc/methods/CoreGetFeatureDensity.d.ts +11 -0
- package/esm/rpc/methods/CoreGetFeatureDensity.js +22 -0
- package/esm/svg/svgReady.d.ts +1 -0
- package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
- package/esm/ui/CascadingMenu.js +30 -8
- package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
- package/esm/ui/ExportSvgDialog.d.ts +1 -1
- package/esm/ui/LoadingOverlay.d.ts +14 -0
- package/esm/ui/LoadingOverlay.js +1 -1
- package/esm/ui/MenuTypes.d.ts +14 -5
- package/esm/ui/MenuTypes.js +3 -0
- package/esm/ui/PaletteContext.d.ts +11 -4
- package/esm/ui/PaletteContext.js +34 -5
- package/esm/ui/PinAdornment.js +31 -43
- package/esm/ui/ScrollChrome.d.ts +16 -0
- package/esm/ui/ScrollChrome.js +12 -0
- package/esm/ui/ScrollZoomToggle.d.ts +4 -3
- package/esm/ui/ScrollZoomToggle.js +4 -3
- package/esm/ui/SizeSliderRow.js +1 -1
- package/esm/ui/index.d.ts +3 -3
- package/esm/ui/index.js +4 -4
- package/esm/ui/launchViewMenu.js +7 -1
- package/esm/ui/legendMenuItem.d.ts +10 -16
- package/esm/ui/legendMenuItem.js +9 -20
- package/esm/ui/makeSizeMenu.js +1 -1
- package/esm/ui/menuItemAdornment.d.ts +2 -3
- package/esm/ui/menuItemAdornment.js +2 -3
- package/esm/ui/menuItems.d.ts +2 -3
- package/esm/ui/menuItems.js +1 -2
- package/esm/ui/palette.d.ts +11 -11
- package/esm/ui/palette.js +11 -11
- package/esm/ui/promotablePinCoverage.d.ts +16 -2
- package/esm/ui/promotablePinCoverage.js +40 -3
- package/esm/ui/theme.js +5 -0
- package/esm/ui/toggleMenuItems.d.ts +14 -9
- package/esm/ui/toggleMenuItems.js +32 -15
- package/esm/util/Base1DUtils.d.ts +4 -2
- package/esm/util/Base1DUtils.js +12 -4
- package/esm/util/SvgCanvas.js +4 -3
- package/esm/util/adapterConfigKey.d.ts +12 -0
- package/esm/util/adapterConfigKey.js +14 -0
- package/esm/util/adapterMetadata.js +2 -1
- package/esm/util/addAndShowTrack.d.ts +1 -1
- package/esm/util/addAndShowTrack.js +5 -1
- package/esm/util/addTrackFromWidget.js +2 -2
- package/esm/util/analytics.js +4 -5
- package/esm/util/cacheBudgets.d.ts +22 -19
- package/esm/util/cacheBudgets.js +22 -19
- package/esm/util/clampToContig.d.ts +17 -0
- package/esm/util/clampToContig.js +19 -0
- package/esm/util/colorBits.d.ts +2 -1
- package/esm/util/colorBits.js +2 -5
- package/esm/util/createStopTokenRotation.d.ts +9 -7
- package/esm/util/createStopTokenRotation.js +7 -27
- package/esm/util/featureTypes.d.ts +24 -0
- package/esm/util/featureTypes.js +35 -0
- package/esm/util/fetchContext.d.ts +2 -2
- package/esm/util/fetchContext.js +2 -2
- package/esm/util/fetchPhases.d.ts +10 -10
- package/esm/util/hooks.d.ts +8 -0
- package/esm/util/hooks.js +27 -0
- package/esm/util/index.d.ts +6 -5
- package/esm/util/index.js +5 -4
- package/esm/util/installFetch.d.ts +71 -34
- package/esm/util/installFetch.js +57 -29
- package/esm/util/installInitAutorun.d.ts +14 -13
- package/esm/util/installInitAutorun.js +17 -17
- package/esm/util/installPrerequisiteFetch.d.ts +86 -0
- package/esm/util/installPrerequisiteFetch.js +73 -0
- package/esm/util/lazyAfterAttach.d.ts +13 -0
- package/esm/util/lazyAfterAttach.js +31 -0
- package/esm/util/legendCandidates.d.ts +50 -0
- package/esm/util/legendCandidates.js +87 -0
- package/esm/util/mstUtils.d.ts +12 -1
- package/esm/util/mstUtils.js +20 -2
- package/esm/util/openFeatureWidget.d.ts +5 -0
- package/esm/util/openFeatureWidget.js +1 -0
- package/esm/util/openViews.d.ts +16 -0
- package/esm/util/openViews.js +22 -0
- package/esm/util/parentWalk.d.ts +1 -1
- package/esm/util/parentWalk.js +1 -1
- package/esm/util/pluginStore.d.ts +1 -0
- package/esm/util/pluginStore.js +8 -1
- package/esm/util/range.d.ts +13 -9
- package/esm/util/range.js +17 -8
- package/esm/util/renderToStaticMarkup.js +10 -0
- package/esm/util/rxjs.d.ts +16 -0
- package/esm/util/rxjs.js +49 -0
- package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
- package/esm/util/scheduleDetachedDestroy.js +24 -0
- package/esm/util/scrollLatch.d.ts +1 -0
- package/esm/util/scrollLatch.js +8 -0
- package/esm/util/stopToken.d.ts +6 -5
- package/esm/util/tabix.d.ts +10 -4
- package/esm/util/tabix.js +11 -5
- package/esm/util/trackConfigDelta.d.ts +6 -6
- package/esm/util/trackConfigDelta.js +3 -3
- package/esm/util/tracks.d.ts +48 -0
- package/esm/util/tracks.js +192 -66
- package/esm/util/types/index.d.ts +58 -10
- package/esm/util/types/index.js +3 -0
- package/esm/util/unknownSnapshotKeys.d.ts +36 -0
- package/esm/util/unknownSnapshotKeys.js +69 -0
- package/esm/util/usePanelVirtualScroll.d.ts +6 -2
- package/esm/util/usePanelVirtualScroll.js +6 -2
- package/esm/util/useRowVirtualScroll.d.ts +1 -1
- package/esm/util/useRowVirtualScroll.js +1 -1
- package/esm/util/useVirtualScrollWheel.js +11 -1
- package/esm/util/viewStatus.d.ts +23 -0
- package/esm/util/viewStatus.js +17 -0
- package/esm/util/wheelZoom.d.ts +3 -1
- package/esm/util/wheelZoom.js +39 -14
- package/esm/util/whenViewSettled.d.ts +17 -4
- package/esm/util/whenViewSettled.js +19 -6
- package/esm/util/withLaunchInput.d.ts +168 -0
- package/esm/util/withLaunchInput.js +273 -0
- package/package.json +19 -11
- package/esm/ui/promotableMenuItems.d.ts +0 -19
- package/esm/ui/promotableMenuItems.js +0 -89
- package/esm/util/applyInitSettings.d.ts +0 -79
- package/esm/util/applyInitSettings.js +0 -91
|
@@ -58,7 +58,17 @@ onWheel) {
|
|
|
58
58
|
// not-yet-committed model read.
|
|
59
59
|
const runningRef = useRef(0);
|
|
60
60
|
const applyScroll = useCallback((e, { scrollTop, viewportHeight, scrollableHeight }, commit) => {
|
|
61
|
-
|
|
61
|
+
// Each handler takes the gesture whose dominant axis is its own: a
|
|
62
|
+
// sideways swipe belongs to the view's pan, and consuming its small
|
|
63
|
+
// vertical component would both drift the panel and — since consuming
|
|
64
|
+
// means preventDefault, which is how the view knows to stay out — kill
|
|
65
|
+
// the pan the user actually asked for. A tie is vertical, matching the
|
|
66
|
+
// view's own zoom-vs-pan tie-break. Raw deltas, because both axes of one
|
|
67
|
+
// event share a deltaMode. `holds` is what keeps this from cutting a
|
|
68
|
+
// gesture in half: once the panel has latched, the sideways momentum
|
|
69
|
+
// trailing a vertical scroll stays with the panel.
|
|
70
|
+
const sideways = Math.abs(e.deltaX) > Math.abs(e.deltaY);
|
|
71
|
+
if (scrollableHeight <= 0 || (sideways && !latch.holds(e))) {
|
|
62
72
|
return;
|
|
63
73
|
}
|
|
64
74
|
// A fresh frame (nothing pending) re-syncs to the model's live scrollTop;
|
package/esm/util/viewStatus.d.ts
CHANGED
|
@@ -56,3 +56,26 @@ export interface ViewStatusInputs {
|
|
|
56
56
|
* with nothing anywhere saying why. `noRegions` is that state, named.
|
|
57
57
|
*/
|
|
58
58
|
export declare function computeViewStatus({ error, hasSomethingToShow, loading, }: ViewStatusInputs): ViewStatus;
|
|
59
|
+
/**
|
|
60
|
+
* The slice of `AssemblyManager` this needs, spelled out rather than imported:
|
|
61
|
+
* the real type is an MST model a `PluginManager` built, so naming it here
|
|
62
|
+
* would cost this leaf the whole application's type graph (`util/CLAUDE.md`).
|
|
63
|
+
*/
|
|
64
|
+
interface AssemblyErrorSource {
|
|
65
|
+
get: (name: string) => {
|
|
66
|
+
error?: unknown;
|
|
67
|
+
} | undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The assembly failures behind a view's `assemblyNames`, joined, or `undefined`
|
|
71
|
+
* when there are none.
|
|
72
|
+
*
|
|
73
|
+
* **Undefined and not `''`**, which is the whole reason this is shared. Three
|
|
74
|
+
* views spelled it as a bare `.join(', ')`, and a getter that answers the empty
|
|
75
|
+
* string for "nothing failed" reads as an error to every `!== undefined` test —
|
|
76
|
+
* `DotplotView.error` folded it in with `??`, so the view reported a terminal
|
|
77
|
+
* error permanently and jbrowse-img refused to render any dotplot. The in-app
|
|
78
|
+
* readers all happened to be truthiness tests, which is why it stayed invisible.
|
|
79
|
+
*/
|
|
80
|
+
export declare function assemblyErrorMessage(assemblyManager: AssemblyErrorSource, assemblyNames: string[]): string | undefined;
|
|
81
|
+
export {};
|
package/esm/util/viewStatus.js
CHANGED
|
@@ -18,3 +18,20 @@ export function computeViewStatus({ error, hasSomethingToShow, loading, }) {
|
|
|
18
18
|
const pending = loading();
|
|
19
19
|
return pending ? { type: 'loading', ...pending } : { type: 'ready' };
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The assembly failures behind a view's `assemblyNames`, joined, or `undefined`
|
|
23
|
+
* when there are none.
|
|
24
|
+
*
|
|
25
|
+
* **Undefined and not `''`**, which is the whole reason this is shared. Three
|
|
26
|
+
* views spelled it as a bare `.join(', ')`, and a getter that answers the empty
|
|
27
|
+
* string for "nothing failed" reads as an error to every `!== undefined` test —
|
|
28
|
+
* `DotplotView.error` folded it in with `??`, so the view reported a terminal
|
|
29
|
+
* error permanently and jbrowse-img refused to render any dotplot. The in-app
|
|
30
|
+
* readers all happened to be truthiness tests, which is why it stayed invisible.
|
|
31
|
+
*/
|
|
32
|
+
export function assemblyErrorMessage(assemblyManager, assemblyNames) {
|
|
33
|
+
const errors = assemblyNames
|
|
34
|
+
.map(name => assemblyManager.get(name)?.error)
|
|
35
|
+
.filter(e => !!e);
|
|
36
|
+
return errors.length > 0 ? errors.join(', ') : undefined;
|
|
37
|
+
}
|
package/esm/util/wheelZoom.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface WheelZoomTarget {
|
|
|
17
17
|
views: WheelZoomView[];
|
|
18
18
|
scrollZoom: boolean;
|
|
19
19
|
originElement: () => HTMLElement | undefined;
|
|
20
|
+
hold?: <T>(fn: () => T) => T;
|
|
20
21
|
}
|
|
21
22
|
export interface WheelZoomControllerOptions {
|
|
22
23
|
element: HTMLElement;
|
|
@@ -37,9 +38,10 @@ export interface WheelZoomControllerOptions {
|
|
|
37
38
|
/**
|
|
38
39
|
* The one wheel gesture handler for linear views. Its decision matrix:
|
|
39
40
|
*
|
|
41
|
+
* - a wheel a nested scroller already consumed → declined, it owns the gesture
|
|
40
42
|
* - ctrl/meta+wheel, or (scrollZoom && |dy| >= |dx|) → zoom about the cursor
|
|
41
43
|
* - shift+wheel while scrollZoom is on → declined, we pass
|
|
42
|
-
* - a
|
|
44
|
+
* - a sideways delta, unless one arrives mid-zoom → pan by dx
|
|
43
45
|
*
|
|
44
46
|
* Declining shift is what leaves a nested panel its own scroll
|
|
45
47
|
* (`usePanelVirtualScroll`) — it is not a way back to the page. Browsers turn
|
package/esm/util/wheelZoom.js
CHANGED
|
@@ -89,9 +89,10 @@ export function applyZoomAccum(bpPerPx, zoomAccum, elapsedMs) {
|
|
|
89
89
|
/**
|
|
90
90
|
* The one wheel gesture handler for linear views. Its decision matrix:
|
|
91
91
|
*
|
|
92
|
+
* - a wheel a nested scroller already consumed → declined, it owns the gesture
|
|
92
93
|
* - ctrl/meta+wheel, or (scrollZoom && |dy| >= |dx|) → zoom about the cursor
|
|
93
94
|
* - shift+wheel while scrollZoom is on → declined, we pass
|
|
94
|
-
* - a
|
|
95
|
+
* - a sideways delta, unless one arrives mid-zoom → pan by dx
|
|
95
96
|
*
|
|
96
97
|
* Declining shift is what leaves a nested panel its own scroll
|
|
97
98
|
* (`usePanelVirtualScroll`) — it is not a way back to the page. Browsers turn
|
|
@@ -141,26 +142,41 @@ export function createWheelZoomController({ element, resolveTarget, swallowUnhan
|
|
|
141
142
|
s.originLeft = origin.getBoundingClientRect().left;
|
|
142
143
|
}
|
|
143
144
|
const originLeft = s.originLeft;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
const apply = () => {
|
|
146
|
+
transaction(() => {
|
|
147
|
+
if (s.zoomAccum !== 0 && originLeft !== undefined) {
|
|
148
|
+
const offset = s.lastClientX - originLeft;
|
|
149
|
+
for (const view of target.views) {
|
|
150
|
+
view.zoomTo(applyZoomAccum(view.bpPerPx, s.zoomAccum, elapsed), offset);
|
|
151
|
+
}
|
|
149
152
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
if (s.scrollDelta !== 0) {
|
|
154
|
+
for (const view of target.views) {
|
|
155
|
+
view.horizontalScroll(s.scrollDelta);
|
|
156
|
+
}
|
|
154
157
|
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
if (target.hold) {
|
|
161
|
+
target.hold(apply);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
apply();
|
|
165
|
+
}
|
|
157
166
|
}
|
|
158
167
|
s.zoomAccum = 0;
|
|
159
168
|
s.scrollDelta = 0;
|
|
160
169
|
}
|
|
161
170
|
function onWheel(event) {
|
|
162
171
|
onEvent?.(event);
|
|
163
|
-
|
|
172
|
+
// A nested vertical scroller preventDefaults exactly what it consumed, and
|
|
173
|
+
// that flag is still readable on the way up, so the view declines what a
|
|
174
|
+
// panel is already scrolling: a trackpad emits a small deltaX alongside
|
|
175
|
+
// every vertical swipe, which used to pan the genome sideways under someone
|
|
176
|
+
// who was only scrolling reads. No timer of our own — the scroll latch
|
|
177
|
+
// holds the whole continuous gesture, boundary included, and releasing it
|
|
178
|
+
// is the pause that ends the gesture.
|
|
179
|
+
const gated = event.defaultPrevented || (presence !== undefined && !presence.isOver);
|
|
164
180
|
const target = gated ? undefined : resolveTarget(event);
|
|
165
181
|
if (target && !(event.shiftKey && target.scrollZoom)) {
|
|
166
182
|
// a gap longer than the frame-elapsed clamp means this event starts a new
|
|
@@ -216,7 +232,16 @@ export function createWheelZoomController({ element, resolveTarget, swallowUnhan
|
|
|
216
232
|
Math.abs(deltaX) > Math.abs(2 * deltaY)) {
|
|
217
233
|
event.preventDefault();
|
|
218
234
|
}
|
|
219
|
-
|
|
235
|
+
// Pan on a gesture that is actually sideways. A trackpad puts a small
|
|
236
|
+
// deltaX on every vertical swipe, and panning on it drifted the genome
|
|
237
|
+
// under anyone scrolling a track — including where no panel handler
|
|
238
|
+
// reports the scroll for us to decline, as with the natively-scrolling
|
|
239
|
+
// pinned-tracks block. Ties go vertical, the same way the zoom test
|
|
240
|
+
// above resolves them. With scrollZoom on this changes nothing: a
|
|
241
|
+
// vertical-dominant wheel was already taken as a zoom.
|
|
242
|
+
if (Math.abs(deltaX) > Math.abs(deltaY)) {
|
|
243
|
+
s.scrollDelta = accumulateScroll(s.scrollDelta, deltaX);
|
|
244
|
+
}
|
|
220
245
|
}
|
|
221
246
|
frame.schedule(flush);
|
|
222
247
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Wait until a view has either initialized
|
|
2
|
+
* Wait until a view has either initialized — launch blob consumed and all — or
|
|
3
|
+
* failed, and report which.
|
|
3
4
|
*
|
|
4
5
|
* `initialized` folds in a view's assemblies, so an assembly that fails to load
|
|
5
6
|
* leaves it false **forever**. A bare `when(() => view.initialized)` therefore
|
|
@@ -9,6 +10,15 @@
|
|
|
9
10
|
* export hung behind its dialog's spinner, and a launched breakpoint split view
|
|
10
11
|
* that opened but was never navigated or zoomed.
|
|
11
12
|
*
|
|
13
|
+
* `pendingLaunch` is the other half, and it matters because `initialized` can
|
|
14
|
+
* go true MID-launch: LGV's flips the moment displayedRegions land, while the
|
|
15
|
+
* same apply pass still has tracks to attach — so a caller acting there reads a
|
|
16
|
+
* positioned view with its tracks missing (an SVG export saves it that way).
|
|
17
|
+
* A launch failure cannot hang this: the state machine either clears the blob
|
|
18
|
+
* (materialized, reported as a snackbar) or sets the view's `error`
|
|
19
|
+
* (installInitAutorun's failure policy). A view with no launch machinery has no
|
|
20
|
+
* `pendingLaunch` and the term is vacuously satisfied.
|
|
21
|
+
*
|
|
12
22
|
* Every view exposes a resolved `error` beside `initialized`, so waiting on the
|
|
13
23
|
* pair turns the hang into something reportable. What to report is the caller's,
|
|
14
24
|
* because the vocabularies genuinely differ — an export says "cannot export"
|
|
@@ -16,12 +26,15 @@
|
|
|
16
26
|
* says the launch failed — which is why this returns the answer instead of
|
|
17
27
|
* throwing one wording at both.
|
|
18
28
|
*
|
|
19
|
-
* No time bound, deliberately: `initialized || error` is a
|
|
20
|
-
* slow-but-healthy remote assembly is waited out rather than
|
|
29
|
+
* No time bound, deliberately: `(initialized && launch consumed) || error` is a
|
|
30
|
+
* terminal set, so a slow-but-healthy remote assembly is waited out rather than
|
|
31
|
+
* guessed at.
|
|
21
32
|
*
|
|
22
|
-
* @returns true if the view initialized, false if it
|
|
33
|
+
* @returns true if the view initialized (and consumed any launch), false if it
|
|
34
|
+
* settled on an error
|
|
23
35
|
*/
|
|
24
36
|
export declare function whenViewSettled(view: {
|
|
25
37
|
initialized: boolean;
|
|
26
38
|
error: unknown;
|
|
39
|
+
pendingLaunch?: unknown;
|
|
27
40
|
}): Promise<boolean>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { when } from 'mobx';
|
|
2
2
|
/**
|
|
3
|
-
* Wait until a view has either initialized
|
|
3
|
+
* Wait until a view has either initialized — launch blob consumed and all — or
|
|
4
|
+
* failed, and report which.
|
|
4
5
|
*
|
|
5
6
|
* `initialized` folds in a view's assemblies, so an assembly that fails to load
|
|
6
7
|
* leaves it false **forever**. A bare `when(() => view.initialized)` therefore
|
|
@@ -10,6 +11,15 @@ import { when } from 'mobx';
|
|
|
10
11
|
* export hung behind its dialog's spinner, and a launched breakpoint split view
|
|
11
12
|
* that opened but was never navigated or zoomed.
|
|
12
13
|
*
|
|
14
|
+
* `pendingLaunch` is the other half, and it matters because `initialized` can
|
|
15
|
+
* go true MID-launch: LGV's flips the moment displayedRegions land, while the
|
|
16
|
+
* same apply pass still has tracks to attach — so a caller acting there reads a
|
|
17
|
+
* positioned view with its tracks missing (an SVG export saves it that way).
|
|
18
|
+
* A launch failure cannot hang this: the state machine either clears the blob
|
|
19
|
+
* (materialized, reported as a snackbar) or sets the view's `error`
|
|
20
|
+
* (installInitAutorun's failure policy). A view with no launch machinery has no
|
|
21
|
+
* `pendingLaunch` and the term is vacuously satisfied.
|
|
22
|
+
*
|
|
13
23
|
* Every view exposes a resolved `error` beside `initialized`, so waiting on the
|
|
14
24
|
* pair turns the hang into something reportable. What to report is the caller's,
|
|
15
25
|
* because the vocabularies genuinely differ — an export says "cannot export"
|
|
@@ -17,12 +27,15 @@ import { when } from 'mobx';
|
|
|
17
27
|
* says the launch failed — which is why this returns the answer instead of
|
|
18
28
|
* throwing one wording at both.
|
|
19
29
|
*
|
|
20
|
-
* No time bound, deliberately: `initialized || error` is a
|
|
21
|
-
* slow-but-healthy remote assembly is waited out rather than
|
|
30
|
+
* No time bound, deliberately: `(initialized && launch consumed) || error` is a
|
|
31
|
+
* terminal set, so a slow-but-healthy remote assembly is waited out rather than
|
|
32
|
+
* guessed at.
|
|
22
33
|
*
|
|
23
|
-
* @returns true if the view initialized, false if it
|
|
34
|
+
* @returns true if the view initialized (and consumed any launch), false if it
|
|
35
|
+
* settled on an error
|
|
24
36
|
*/
|
|
25
37
|
export async function whenViewSettled(view) {
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
const ready = () => view.initialized && view.pendingLaunch === undefined;
|
|
39
|
+
await when(() => ready() || !!view.error);
|
|
40
|
+
return ready();
|
|
28
41
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export { legacyInitMessage, unknownKeysMessage } from './unknownSnapshotKeys.ts';
|
|
2
|
+
import type { IAnyModelType, IModelType, SnapshotIn, SnapshotOut } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
/**
|
|
4
|
+
* The slice of a PluginManager the partition reads: which view type a
|
|
5
|
+
* snapshot's `type` names, and that type's state model as REGISTERED — the
|
|
6
|
+
* one `extendViewType` may have composed more properties onto after the
|
|
7
|
+
* factory wrapped its own.
|
|
8
|
+
*/
|
|
9
|
+
export interface ViewTypeLookup {
|
|
10
|
+
viewTypes: {
|
|
11
|
+
has: (name: string) => boolean;
|
|
12
|
+
};
|
|
13
|
+
getViewType: (name: string) => {
|
|
14
|
+
isStateModelLoaded: boolean;
|
|
15
|
+
stateModel: IAnyModelType;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface LaunchInputOptions<M extends IAnyModelType> {
|
|
19
|
+
/** the PluginManager; without it the partition sees only the wrapped model */
|
|
20
|
+
registry?: ViewTypeLookup;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a snapshot shows the launch applied — rows built, regions set. The
|
|
23
|
+
* blob persists only until then: a snapshot taken mid-load (an autosave
|
|
24
|
+
* firing before the launch autorun navigates) has to rebuild the view rather
|
|
25
|
+
* than drop it to the import form, and a materialized view has nothing left
|
|
26
|
+
* to rebuild. `installInitAutorun` keys its failure policy off the same line,
|
|
27
|
+
* read from the live node. `Partial` because a `stripDefault` property is
|
|
28
|
+
* absent from the snapshot when empty, whatever its declared type says.
|
|
29
|
+
*/
|
|
30
|
+
materialized: (snap: Partial<SnapshotOut<M>>) => boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* How a launch key's value is told apart from the state property of the same
|
|
34
|
+
* name. A key whose name collides with nothing is `launch`; the rest name the
|
|
35
|
+
* discriminator that splits one authored array into the recipe entries the
|
|
36
|
+
* launcher resolves and the built snapshots MST restores.
|
|
37
|
+
*
|
|
38
|
+
* `replay` is the one that is not remapped at all: the value lands on its
|
|
39
|
+
* property, and a copy rides in the blob so the launcher can run the ordered
|
|
40
|
+
* imperative step the property write alone does not produce.
|
|
41
|
+
*/
|
|
42
|
+
export type LaunchKeyKind = 'launch' | 'trackEntries' | 'rows' | 'highlightEntries' | 'replay';
|
|
43
|
+
export interface LaunchKeySpec {
|
|
44
|
+
kind: LaunchKeyKind;
|
|
45
|
+
}
|
|
46
|
+
export interface LaunchKeyRegistration<Commands, PassThrough extends string = never> {
|
|
47
|
+
keys: Record<string, LaunchKeySpec>;
|
|
48
|
+
passThrough: readonly PassThrough[];
|
|
49
|
+
/** never assigned; it carries `Commands` to `withLaunchInput`'s return type */
|
|
50
|
+
commands?: Commands;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The launch keys a view captured, plus what it has to report.
|
|
54
|
+
*
|
|
55
|
+
* `Commands` is not made partial: hand-authored JSON is what fills this, so a
|
|
56
|
+
* key the interface marks required is not a guarantee here either way, and the
|
|
57
|
+
* launcher already guards the ones it cannot proceed without.
|
|
58
|
+
*/
|
|
59
|
+
export type LaunchInput<Commands> = Commands & {
|
|
60
|
+
unknown?: Record<string, unknown>;
|
|
61
|
+
malformed?: Record<string, unknown>;
|
|
62
|
+
legacyInit?: boolean;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The blob when it still holds something to apply, else undefined. A view's
|
|
66
|
+
* gates ask this rather than the raw property: a snapshot whose only launch
|
|
67
|
+
* content was a typo has nothing to launch, and a view that thinks otherwise
|
|
68
|
+
* waits on an assembly nobody named and never leaves the spinner.
|
|
69
|
+
*
|
|
70
|
+
* Returns the blob itself, never a copy — the launch autorun clears by
|
|
71
|
+
* identity, and a fresh object per read strands the init it just applied.
|
|
72
|
+
*/
|
|
73
|
+
export declare function pendingLaunch<C>(launch: LaunchInput<C> | undefined): LaunchInput<C> | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* A view's snapshot type, widened to the authored shape: every launch key is
|
|
76
|
+
* accepted beside the declared properties, and a key that is both takes either
|
|
77
|
+
* meaning. Excess-property checking then makes a misspelled key an error at
|
|
78
|
+
* every literal site — a `defaultSession` view, an `addView` call, a
|
|
79
|
+
* `createViewState` spec.
|
|
80
|
+
*/
|
|
81
|
+
export type LaunchSnapshotIn<M extends IAnyModelType, Commands, PassThrough extends string = never> = Omit<SnapshotIn<M>, keyof Commands> & {
|
|
82
|
+
[K in keyof Commands]?: K extends keyof SnapshotIn<M> ? Commands[K] | SnapshotIn<M>[K] : Commands[K];
|
|
83
|
+
} & {
|
|
84
|
+
[K in PassThrough]?: unknown;
|
|
85
|
+
} & {
|
|
86
|
+
/**
|
|
87
|
+
* @deprecated v4's nesting. Write every setting directly on the view object;
|
|
88
|
+
* this is unwrapped on the way in and warns.
|
|
89
|
+
*/
|
|
90
|
+
init?: Commands;
|
|
91
|
+
};
|
|
92
|
+
type ReservedKey = 'id' | 'type' | 'launch';
|
|
93
|
+
/**
|
|
94
|
+
* What a view can be launched with, derived: the keys its launcher interprets
|
|
95
|
+
* (`Commands`) plus every declared property of its state model, optional, in
|
|
96
|
+
* the property's own snapshot type. Nothing is restated, so a property is
|
|
97
|
+
* authorable — and TYPED — from the line that declares it.
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* export type LinearSyntenyViewInit = ViewInit<
|
|
101
|
+
* LinearSyntenyViewStateModel,
|
|
102
|
+
* LinearSyntenyViewCommands
|
|
103
|
+
* >
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* The twin of `LaunchSnapshotIn` above, from the other end: that one widens a
|
|
107
|
+
* snapshot type for a literal MST site, this one is what a caller BUILDING a
|
|
108
|
+
* spec annotates, so its commands stay required and its properties optional.
|
|
109
|
+
*/
|
|
110
|
+
export type ViewInit<M extends IAnyModelType, Commands> = Commands & Partial<Omit<SnapshotIn<M>, keyof Commands | ReservedKey>>;
|
|
111
|
+
export type LaunchInputModel<M extends IAnyModelType, Commands, PassThrough extends string = never> = M extends IModelType<infer P, infer O, any, infer S> ? IModelType<P, O, LaunchSnapshotIn<M, Commands, PassThrough>, S> : never;
|
|
112
|
+
/**
|
|
113
|
+
* Declare one view's launch keys. The argument is
|
|
114
|
+
* `Record<keyof Commands, LaunchKeySpec>`, so a command the view interprets and
|
|
115
|
+
* nobody registered is a compile error rather than a key that partitions as a
|
|
116
|
+
* typo and warns.
|
|
117
|
+
*
|
|
118
|
+
* `passThrough` names keys that are neither a launch key nor a declared
|
|
119
|
+
* property and still belong on the snapshot — a legacy spelling the view's own
|
|
120
|
+
* `preProcessSnapshot` converts.
|
|
121
|
+
*/
|
|
122
|
+
export declare function defineLaunchKeys<Commands>(): <const P extends readonly string[] = readonly never[]>(keys: Record<keyof Commands, LaunchKeySpec>, { passThrough }?: {
|
|
123
|
+
passThrough?: P;
|
|
124
|
+
}) => LaunchKeyRegistration<Commands, P[number]>;
|
|
125
|
+
/**
|
|
126
|
+
* The part of a launch spec that belongs on the snapshot: everything but the
|
|
127
|
+
* launch keys, and the identity and `launch` keys no spec may set. For a caller
|
|
128
|
+
* that applies the launch itself and builds the view from a snapshot — a
|
|
129
|
+
* synteny row, whose parent navigates it and opens its tracks — so what it
|
|
130
|
+
* hands MST is settings only, and the view's own partition sorts those into
|
|
131
|
+
* properties and reported typos.
|
|
132
|
+
*/
|
|
133
|
+
export declare function snapshotSettings(spec: Record<string, unknown>, registration: LaunchKeyRegistration<unknown, string> | undefined): {
|
|
134
|
+
[k: string]: unknown;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Accept a view's settings written directly on the view object, and move the
|
|
138
|
+
* ones a launcher has to resolve into the internal `launch` property.
|
|
139
|
+
*
|
|
140
|
+
* The partition is a `preProcessSnapshot` and is PURE. A session's view type is
|
|
141
|
+
* a `types.union`, so MST runs every member's preprocessor against every
|
|
142
|
+
* candidate snapshot while deciding which one matches, and runs it about twice
|
|
143
|
+
* more per instantiation; a warning from in here fires against snapshots that
|
|
144
|
+
* are about to be rejected. `afterAttach` — reached only by a snapshot that won
|
|
145
|
+
* — reports what the partition captured.
|
|
146
|
+
*
|
|
147
|
+
* `registry` is the PluginManager. With it the partition classifies against
|
|
148
|
+
* the view type as registered, `extendViewType`'s added properties included;
|
|
149
|
+
* without it, against the model as wrapped here. `materialized` draws the line
|
|
150
|
+
* past which the blob is no longer persisted; see `LaunchInputOptions`.
|
|
151
|
+
*
|
|
152
|
+
* ORDER: MST runs preprocessors in the reverse of the order they were added, so
|
|
153
|
+
* this belongs on the chain BEFORE a view's own legacy-key preprocessor, where
|
|
154
|
+
* it partitions the snapshot MST finally consumes rather than a key that remap
|
|
155
|
+
* is about to convert.
|
|
156
|
+
*
|
|
157
|
+
* The widening cast is the LAST link that may change the creation type: it
|
|
158
|
+
* replaces `CustomC`, so a `.props()` added after it is invisible to
|
|
159
|
+
* `SnapshotIn`. Further `preProcessSnapshot`/`postProcessSnapshot` links are
|
|
160
|
+
* fine — both carry `CustomC` through.
|
|
161
|
+
*
|
|
162
|
+
* Not `types.snapshotProcessor`, which carries the same widened input and stops
|
|
163
|
+
* being a `ModelType`. `PluginManager.pluggableMstType` filters union members on
|
|
164
|
+
* `isModelType`, so a wrapped view is dropped from the session's view union
|
|
165
|
+
* without a word, and `ViewType.stateModel` and every `.properties`
|
|
166
|
+
* introspection site break with it.
|
|
167
|
+
*/
|
|
168
|
+
export declare function withLaunchInput<M extends IAnyModelType, Commands, PassThrough extends string>(model: M, registration: LaunchKeyRegistration<Commands, PassThrough>, { registry, materialized }: LaunchInputOptions<M>): LaunchInputModel<M, Commands, PassThrough>;
|