@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
|
@@ -144,6 +144,27 @@ export declare function createBaseTrackModel(pm: PluginManager, trackType: strin
|
|
|
144
144
|
* #action
|
|
145
145
|
*/
|
|
146
146
|
setResizing(flag: boolean): void;
|
|
147
|
+
/**
|
|
148
|
+
* #action
|
|
149
|
+
* `applyDisplaySettings` on the display being drawn (`activeDisplay`,
|
|
150
|
+
* which a shown track always has — this is not meaningful on a bare
|
|
151
|
+
* config node) — the track-level entry for "restyle this track in
|
|
152
|
+
* place" (a session spec's inline keys, an agent's settings bag). Only
|
|
153
|
+
* that one display: settings vocabularies are per display type, so
|
|
154
|
+
* broadcasting one bag across a track's other displays would mis-route
|
|
155
|
+
* keys; address a non-active display directly if that is what you mean.
|
|
156
|
+
* See BaseDisplayModel for the routing and the `allowSetters` opt-in.
|
|
157
|
+
*/
|
|
158
|
+
applyDisplaySettings(settings: Record<string, unknown>, options?: {
|
|
159
|
+
allowSetters?: boolean;
|
|
160
|
+
}): {
|
|
161
|
+
applied: string[];
|
|
162
|
+
unapplied: string[];
|
|
163
|
+
failed: {
|
|
164
|
+
key: string;
|
|
165
|
+
error: string;
|
|
166
|
+
}[];
|
|
167
|
+
};
|
|
147
168
|
/**
|
|
148
169
|
* #action
|
|
149
170
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lazy } from 'react';
|
|
2
|
-
import { addDisposer, getSnapshot, types } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
import { addDisposer, getSnapshot, isAlive, types, } from '@jbrowse/mobx-state-tree';
|
|
3
3
|
import Save from '@mui/icons-material/Save';
|
|
4
4
|
import { compareStructural, reaction } from 'mobx';
|
|
5
5
|
import { ConfigurationReference, getConf } from '../../configuration/index.js';
|
|
@@ -251,6 +251,20 @@ export function createBaseTrackModel(pm, trackType, baseTrackConfig) {
|
|
|
251
251
|
setResizing(flag) {
|
|
252
252
|
self.resizing = flag;
|
|
253
253
|
},
|
|
254
|
+
/**
|
|
255
|
+
* #action
|
|
256
|
+
* `applyDisplaySettings` on the display being drawn (`activeDisplay`,
|
|
257
|
+
* which a shown track always has — this is not meaningful on a bare
|
|
258
|
+
* config node) — the track-level entry for "restyle this track in
|
|
259
|
+
* place" (a session spec's inline keys, an agent's settings bag). Only
|
|
260
|
+
* that one display: settings vocabularies are per display type, so
|
|
261
|
+
* broadcasting one bag across a track's other displays would mis-route
|
|
262
|
+
* keys; address a non-active display directly if that is what you mean.
|
|
263
|
+
* See BaseDisplayModel for the routing and the `allowSetters` opt-in.
|
|
264
|
+
*/
|
|
265
|
+
applyDisplaySettings(settings, options) {
|
|
266
|
+
return self.activeDisplay.applyDisplaySettings(settings, options);
|
|
267
|
+
},
|
|
254
268
|
/**
|
|
255
269
|
* #action
|
|
256
270
|
*/
|
|
@@ -261,6 +275,9 @@ export function createBaseTrackModel(pm, trackType, baseTrackConfig) {
|
|
|
261
275
|
}
|
|
262
276
|
const displays = self.configuration.displays;
|
|
263
277
|
const displayConf = getDisplayConf(displays, newDisplayId);
|
|
278
|
+
// same interception showTrackGeneric makes: a registered-but-unloaded
|
|
279
|
+
// display would otherwise fail as an opaque union mismatch below
|
|
280
|
+
pm.resolveDisplayTypeRecord(displayConf.type)?.assertStateModelLoaded();
|
|
264
281
|
self.displays[idx] = {
|
|
265
282
|
...initialSnapshot,
|
|
266
283
|
type: displayConf.type,
|
|
@@ -434,9 +451,24 @@ export function createBaseTrackModel(pm, trackType, baseTrackConfig) {
|
|
|
434
451
|
// being replaced, so leaving the menu up would keep a
|
|
435
452
|
// list of items built against a destroyed MST node
|
|
436
453
|
keepMenuOpen: false,
|
|
454
|
+
// the chosen display's state model may still be a dynamic
|
|
455
|
+
// import away, so load it before swapping — replaceDisplay
|
|
456
|
+
// itself stays a plain sync action
|
|
437
457
|
onClick: () => {
|
|
438
458
|
if (d.displayId !== shownId) {
|
|
439
|
-
|
|
459
|
+
void (async () => {
|
|
460
|
+
try {
|
|
461
|
+
await pm
|
|
462
|
+
.resolveDisplayTypeRecord(d.type)
|
|
463
|
+
?.loadStateModel();
|
|
464
|
+
if (isAlive(self)) {
|
|
465
|
+
self.replaceDisplay(shownId, d.displayId, self.activeDisplay.getPortableSettings?.(d.displayId) ?? {});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (e) {
|
|
469
|
+
getSession(self).notifyError(`${e}`, e);
|
|
470
|
+
}
|
|
471
|
+
})();
|
|
440
472
|
}
|
|
441
473
|
},
|
|
442
474
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MenuItem } from '../../ui/index.ts';
|
|
2
|
+
import type { AbstractTrackModel, AbstractViewModel } from '../../util/types/index.ts';
|
|
2
3
|
import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
3
4
|
/**
|
|
4
5
|
* #stateModel BaseViewModel
|
|
@@ -66,6 +67,30 @@ declare const BaseViewModel: import("@jbrowse/mobx-state-tree").IModelType<{
|
|
|
66
67
|
* #method
|
|
67
68
|
*/
|
|
68
69
|
menuItems(): MenuItem[];
|
|
70
|
+
/**
|
|
71
|
+
* #getter
|
|
72
|
+
* The tracks this view puts in the census — its own, not a nested view's.
|
|
73
|
+
*
|
|
74
|
+
* Empty here, and overridden by the views that have any: the base cannot
|
|
75
|
+
* read `self.tracks` for them, because what a view keeps under that name
|
|
76
|
+
* is the view's business. react-msaview's holds its MSA annotation rows —
|
|
77
|
+
* `{ReactComponent, model}` objects with no configuration and no displays
|
|
78
|
+
* — and a base that helped itself to them handed them to the readiness
|
|
79
|
+
* marker as tracks, which error-paged every session holding an MSA view.
|
|
80
|
+
*/
|
|
81
|
+
readonly ownTracks: AbstractTrackModel[];
|
|
82
|
+
/**
|
|
83
|
+
* #getter
|
|
84
|
+
* The views nested directly inside this one, which the census counts as
|
|
85
|
+
* views in their own right — a synteny stack's genome rows, a breakpoint
|
|
86
|
+
* split view's panels.
|
|
87
|
+
*
|
|
88
|
+
* Empty here for the same reason, and the dotplot is why it has to be a
|
|
89
|
+
* declaration rather than a walk of `views`: that prop name holds its two
|
|
90
|
+
* 1D *axis* models, which are view-shaped and are not views the user
|
|
91
|
+
* opened. No structural test separates the two — only the view knows.
|
|
92
|
+
*/
|
|
93
|
+
readonly ownViews: AbstractViewModel[];
|
|
69
94
|
} & {
|
|
70
95
|
/**
|
|
71
96
|
* #action
|
|
@@ -172,6 +197,30 @@ export declare const BaseViewModelWithDisplayedRegions: import("@jbrowse/mobx-st
|
|
|
172
197
|
* #method
|
|
173
198
|
*/
|
|
174
199
|
menuItems(): MenuItem[];
|
|
200
|
+
/**
|
|
201
|
+
* #getter
|
|
202
|
+
* The tracks this view puts in the census — its own, not a nested view's.
|
|
203
|
+
*
|
|
204
|
+
* Empty here, and overridden by the views that have any: the base cannot
|
|
205
|
+
* read `self.tracks` for them, because what a view keeps under that name
|
|
206
|
+
* is the view's business. react-msaview's holds its MSA annotation rows —
|
|
207
|
+
* `{ReactComponent, model}` objects with no configuration and no displays
|
|
208
|
+
* — and a base that helped itself to them handed them to the readiness
|
|
209
|
+
* marker as tracks, which error-paged every session holding an MSA view.
|
|
210
|
+
*/
|
|
211
|
+
readonly ownTracks: AbstractTrackModel[];
|
|
212
|
+
/**
|
|
213
|
+
* #getter
|
|
214
|
+
* The views nested directly inside this one, which the census counts as
|
|
215
|
+
* views in their own right — a synteny stack's genome rows, a breakpoint
|
|
216
|
+
* split view's panels.
|
|
217
|
+
*
|
|
218
|
+
* Empty here for the same reason, and the dotplot is why it has to be a
|
|
219
|
+
* declaration rather than a walk of `views`: that prop name holds its two
|
|
220
|
+
* 1D *axis* models, which are view-shaped and are not views the user
|
|
221
|
+
* opened. No structural test separates the two — only the view knows.
|
|
222
|
+
*/
|
|
223
|
+
readonly ownViews: AbstractViewModel[];
|
|
175
224
|
} & {
|
|
176
225
|
/**
|
|
177
226
|
* #action
|
|
@@ -94,6 +94,34 @@ const BaseViewModel = types
|
|
|
94
94
|
menuItems() {
|
|
95
95
|
return [];
|
|
96
96
|
},
|
|
97
|
+
/**
|
|
98
|
+
* #getter
|
|
99
|
+
* The tracks this view puts in the census — its own, not a nested view's.
|
|
100
|
+
*
|
|
101
|
+
* Empty here, and overridden by the views that have any: the base cannot
|
|
102
|
+
* read `self.tracks` for them, because what a view keeps under that name
|
|
103
|
+
* is the view's business. react-msaview's holds its MSA annotation rows —
|
|
104
|
+
* `{ReactComponent, model}` objects with no configuration and no displays
|
|
105
|
+
* — and a base that helped itself to them handed them to the readiness
|
|
106
|
+
* marker as tracks, which error-paged every session holding an MSA view.
|
|
107
|
+
*/
|
|
108
|
+
get ownTracks() {
|
|
109
|
+
return [];
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* #getter
|
|
113
|
+
* The views nested directly inside this one, which the census counts as
|
|
114
|
+
* views in their own right — a synteny stack's genome rows, a breakpoint
|
|
115
|
+
* split view's panels.
|
|
116
|
+
*
|
|
117
|
+
* Empty here for the same reason, and the dotplot is why it has to be a
|
|
118
|
+
* declaration rather than a walk of `views`: that prop name holds its two
|
|
119
|
+
* 1D *axis* models, which are view-shaped and are not views the user
|
|
120
|
+
* opened. No structural test separates the two — only the view knows.
|
|
121
|
+
*/
|
|
122
|
+
get ownViews() {
|
|
123
|
+
return [];
|
|
124
|
+
},
|
|
97
125
|
}))
|
|
98
126
|
.actions(self => ({
|
|
99
127
|
/**
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { IAnyStateTreeNode } from '@jbrowse/mobx-state-tree';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Checks that a display's fetch foundation attached it exactly once — the one
|
|
4
|
+
* ordering contract here that is a *state* rather than a declaration, so no
|
|
5
|
+
* selector can reach it. Costs a `WeakSet` lookup, so it runs in a production
|
|
6
|
+
* build too and reports through `contractReports`, which is silent until
|
|
7
|
+
* something arms it.
|
|
6
8
|
*
|
|
7
9
|
* Called once per display from **whichever fetch foundation installed its
|
|
8
10
|
* autoruns** — `MultiRegionDisplayMixin`'s `afterAttach` for the per-region
|
|
@@ -58,8 +60,9 @@ interface RetryContractHost {
|
|
|
58
60
|
reloadCounter: number;
|
|
59
61
|
fetchInert: boolean;
|
|
60
62
|
/**
|
|
61
|
-
* Optional: the
|
|
62
|
-
* declares it. A
|
|
63
|
+
* Optional: chord and the breakpoint overlay have no two-stage fetch, so
|
|
64
|
+
* neither declares it. A fetch that grows one declares it and gets the
|
|
65
|
+
* deferral.
|
|
63
66
|
*/
|
|
64
67
|
awaitingPrerequisite?: boolean;
|
|
65
68
|
/**
|
|
@@ -69,14 +72,15 @@ interface RetryContractHost {
|
|
|
69
72
|
*/
|
|
70
73
|
viewportEmpty?: boolean;
|
|
71
74
|
}
|
|
72
|
-
/** Called by `FetchMixin.runFetch`.
|
|
75
|
+
/** Called by `FetchMixin.runFetch`. */
|
|
73
76
|
export declare function noteFetchStarted(self: object): void;
|
|
74
77
|
/** Reads and clears the flag above, so each check starts from a known state. */
|
|
75
78
|
export declare function takeFetchStarted(self: object): boolean;
|
|
76
79
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
+
* Checks that a display's `reload()` can actually reach a fetch — the retry
|
|
81
|
+
* contract, which `DisplayErrorBar` depends on and which no type can state.
|
|
82
|
+
* Costs an `untracked` read per autorun run against a fetch, so it runs in a
|
|
83
|
+
* production build too and reports through `contractReports`.
|
|
80
84
|
*
|
|
81
85
|
* **The button is the contract.** `DisplayErrorBar`'s only action is
|
|
82
86
|
* `model.reload()`, so every state that can raise the error bar has to be one
|
|
@@ -89,7 +93,7 @@ export declare function takeFetchStarted(self: object): boolean;
|
|
|
89
93
|
* has changed. Arc shipped exactly that: a `prepare` declining on `dataCurrent`,
|
|
90
94
|
* with the error clearing on click and no arcs ever coming back. The fix this
|
|
91
95
|
* message asks for is what `GlobalFetchMixin.reload()` now does for that whole
|
|
92
|
-
* family — drop `
|
|
96
|
+
* family — drop `loadedFetchKey`, so `dataCurrent` goes false and the
|
|
93
97
|
* gate opens.
|
|
94
98
|
*
|
|
95
99
|
* Detected at the moment it happens rather than statically, because the relation
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { getMembers } from '@jbrowse/mobx-state-tree';
|
|
2
|
+
import { reportContractViolation } from '@jbrowse/render-core/contractReports';
|
|
2
3
|
import { untracked } from 'mobx';
|
|
3
4
|
// Nodes whose fetch foundation has already installed its autoruns. Keyed on the
|
|
4
5
|
// node rather than the model type: every display of a type would otherwise
|
|
5
6
|
// report from the second instance onward.
|
|
6
7
|
const attached = new WeakSet();
|
|
7
8
|
function report(message) {
|
|
8
|
-
|
|
9
|
-
// the session loader as an invalid track and the display is silently dropped
|
|
10
|
-
// — which would hide the very contract violation this is reporting.
|
|
11
|
-
console.error(`[jbrowse display contract] ${message}`);
|
|
9
|
+
reportContractViolation('display', message);
|
|
12
10
|
}
|
|
13
11
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* Checks that a display's fetch foundation attached it exactly once — the one
|
|
13
|
+
* ordering contract here that is a *state* rather than a declaration, so no
|
|
14
|
+
* selector can reach it. Costs a `WeakSet` lookup, so it runs in a production
|
|
15
|
+
* build too and reports through `contractReports`, which is silent until
|
|
16
|
+
* something arms it.
|
|
17
17
|
*
|
|
18
18
|
* Called once per display from **whichever fetch foundation installed its
|
|
19
19
|
* autoruns** — `MultiRegionDisplayMixin`'s `afterAttach` for the per-region
|
|
@@ -46,19 +46,17 @@ function report(message) {
|
|
|
46
46
|
* points nowhere near the cause.
|
|
47
47
|
*/
|
|
48
48
|
export function assertDisplayContract(self, installedBy = "the per-region fetch foundation's afterAttach") {
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
attached.add(self);
|
|
61
|
-
}
|
|
49
|
+
if (attached.has(self)) {
|
|
50
|
+
report(`${getMembers(self).name}: ${installedBy} ran twice on one display, ` +
|
|
51
|
+
`so its fetch autoruns are installed twice (double fetches, double ` +
|
|
52
|
+
`clears). Our MST fork auto-chains lifecycle hooks, so the usual ` +
|
|
53
|
+
`cause is a superAfterAttach() call in this display's afterAttach — ` +
|
|
54
|
+
`delete it. Otherwise this display composes two fetch foundations, ` +
|
|
55
|
+
`or calls an installer it already gets from a mixin. ` +
|
|
56
|
+
`See agent-docs/ARCHITECTURE.md §"What not to do".`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
attached.add(self);
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
62
|
// Displays whose fetch has started since the last time the caller looked, and
|
|
@@ -85,11 +83,8 @@ export function assertDisplayContract(self, installedBy = "the per-region fetch
|
|
|
85
83
|
// on the display with the liveliest one.
|
|
86
84
|
const fetchStarted = new WeakSet();
|
|
87
85
|
const ledgers = new WeakMap();
|
|
88
|
-
/** Called by `FetchMixin.runFetch`.
|
|
86
|
+
/** Called by `FetchMixin.runFetch`. */
|
|
89
87
|
export function noteFetchStarted(self) {
|
|
90
|
-
if (process.env.NODE_ENV === 'production') {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
88
|
fetchStarted.add(self);
|
|
94
89
|
ledgers.get(self)?.('fetched');
|
|
95
90
|
}
|
|
@@ -98,9 +93,10 @@ export function takeFetchStarted(self) {
|
|
|
98
93
|
return fetchStarted.delete(self);
|
|
99
94
|
}
|
|
100
95
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
96
|
+
* Checks that a display's `reload()` can actually reach a fetch — the retry
|
|
97
|
+
* contract, which `DisplayErrorBar` depends on and which no type can state.
|
|
98
|
+
* Costs an `untracked` read per autorun run against a fetch, so it runs in a
|
|
99
|
+
* production build too and reports through `contractReports`.
|
|
104
100
|
*
|
|
105
101
|
* **The button is the contract.** `DisplayErrorBar`'s only action is
|
|
106
102
|
* `model.reload()`, so every state that can raise the error bar has to be one
|
|
@@ -113,7 +109,7 @@ export function takeFetchStarted(self) {
|
|
|
113
109
|
* has changed. Arc shipped exactly that: a `prepare` declining on `dataCurrent`,
|
|
114
110
|
* with the error clearing on click and no arcs ever coming back. The fix this
|
|
115
111
|
* message asks for is what `GlobalFetchMixin.reload()` now does for that whole
|
|
116
|
-
* family — drop `
|
|
112
|
+
* family — drop `loadedFetchKey`, so `dataCurrent` goes false and the
|
|
117
113
|
* gate opens.
|
|
118
114
|
*
|
|
119
115
|
* Detected at the moment it happens rather than statically, because the relation
|
|
@@ -195,9 +191,6 @@ export function takeFetchStarted(self) {
|
|
|
195
191
|
* is worse than the bug being checked for.
|
|
196
192
|
*/
|
|
197
193
|
export function makeRetryContractCheck(self) {
|
|
198
|
-
if (process.env.NODE_ENV === 'production') {
|
|
199
|
-
return () => { };
|
|
200
|
-
}
|
|
201
194
|
// eslint-disable-next-line no-restricted-syntax -- instrumentation
|
|
202
195
|
let lastCounter = untracked(() => self.reloadCounter);
|
|
203
196
|
function noteRetryContractOutcome(outcome) {
|
|
@@ -229,7 +222,7 @@ export function makeRetryContractCheck(self) {
|
|
|
229
222
|
`fetch autorun's gate still declines, so Retry is a dead ` +
|
|
230
223
|
`button — it clears the error and nothing refetches. reload() has ` +
|
|
231
224
|
`to invalidate whatever that gate reads, not just bump the ` +
|
|
232
|
-
`counter (GlobalFetchMixin.reload drops
|
|
225
|
+
`counter (GlobalFetchMixin.reload drops loadedFetchKey so ` +
|
|
233
226
|
`dataCurrent goes false). If this display is deliberately not ` +
|
|
234
227
|
`fetching, say so with fetchInert — the loading scrim and the SVG ` +
|
|
235
228
|
`export read it too; if this run declined only because a ` +
|
|
@@ -61,7 +61,13 @@ export function preprocessTrackConfigSnapshot(pluginManager, snapshot) {
|
|
|
61
61
|
const canonical = displayAliasMap.get(d.type);
|
|
62
62
|
return canonical ? { ...d, type: canonical } : d;
|
|
63
63
|
})
|
|
64
|
-
.filter(d =>
|
|
64
|
+
.filter(d => {
|
|
65
|
+
const known = knownDisplayTypes.has(d.type);
|
|
66
|
+
if (!known) {
|
|
67
|
+
console.warn(`Dropping display of unknown type "${d.type}" from track "${snap.trackId}": no registered display type has that name`);
|
|
68
|
+
}
|
|
69
|
+
return known;
|
|
70
|
+
})
|
|
65
71
|
.filter(d => {
|
|
66
72
|
const dup = seenTypes.has(d.type);
|
|
67
73
|
seenTypes.add(d.type);
|
package/esm/rpc/RpcRegistry.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FeatureDensity } from '../data_adapters/BaseAdapter/featureDensity.ts';
|
|
1
2
|
import type { StatusCallback } from '../util/progress.ts';
|
|
2
3
|
import type { UnwrapRpcResult } from '../util/rpc.ts';
|
|
3
4
|
import type { Feature, SimpleFeatureSerialized } from '../util/simpleFeature.ts';
|
|
@@ -52,6 +53,15 @@ export interface RpcRegistry {
|
|
|
52
53
|
};
|
|
53
54
|
return: number | undefined;
|
|
54
55
|
};
|
|
56
|
+
CoreGetFeatureDensity: {
|
|
57
|
+
args: {
|
|
58
|
+
adapterConfig: Record<string, unknown>;
|
|
59
|
+
regions: RegionLike[];
|
|
60
|
+
bpPerPx: number;
|
|
61
|
+
headers?: Record<string, string>;
|
|
62
|
+
};
|
|
63
|
+
return: FeatureDensity[] | undefined;
|
|
64
|
+
};
|
|
55
65
|
CoreGetInfo: {
|
|
56
66
|
args: {
|
|
57
67
|
adapterConfig: Record<string, unknown>;
|
package/esm/rpc/byteBudget.d.ts
CHANGED
|
@@ -6,6 +6,15 @@ import type { AugmentedRegion } from '../util/types/data.ts';
|
|
|
6
6
|
* budget, or the save dialog's bound on the whole download.
|
|
7
7
|
*/
|
|
8
8
|
export type ByteEstimateScope = 'largestRegion' | 'wholeRequest';
|
|
9
|
+
/**
|
|
10
|
+
* The one spelling of a gated feature RPC's budget argument: the number the
|
|
11
|
+
* worker measures against, undefined when the gate declined to act and nothing
|
|
12
|
+
* is measured. A call-site argument, never part of `rpcProps`, because it
|
|
13
|
+
* swings at 20kb and on force-load.
|
|
14
|
+
*/
|
|
15
|
+
export interface GatedFetchArgs {
|
|
16
|
+
byteLimit?: number;
|
|
17
|
+
}
|
|
9
18
|
export interface ByteMeasurableAdapter {
|
|
10
19
|
getRegionByteSize: (regions: AugmentedRegion[], opts?: {
|
|
11
20
|
stopToken?: StopToken;
|
|
@@ -5,5 +5,6 @@ export { default as CoreGetFeatures } from './methods/CoreGetFeatures.ts';
|
|
|
5
5
|
export { default as CoreGetSequence } from './methods/CoreGetSequence.ts';
|
|
6
6
|
export { default as CoreFreeResources } from './methods/CoreFreeResources.ts';
|
|
7
7
|
export { default as CoreGetRegionByteEstimate } from './methods/CoreGetRegionByteEstimate.ts';
|
|
8
|
+
export { default as CoreGetFeatureDensity } from './methods/CoreGetFeatureDensity.ts';
|
|
8
9
|
export { default as CoreGetRegions } from './methods/CoreGetRegions.ts';
|
|
9
10
|
export { default as CoreGetExportData } from './methods/CoreGetExportData.ts';
|
|
@@ -5,5 +5,6 @@ export { default as CoreGetFeatures } from './methods/CoreGetFeatures.js';
|
|
|
5
5
|
export { default as CoreGetSequence } from './methods/CoreGetSequence.js';
|
|
6
6
|
export { default as CoreFreeResources } from './methods/CoreFreeResources.js';
|
|
7
7
|
export { default as CoreGetRegionByteEstimate } from './methods/CoreGetRegionByteEstimate.js';
|
|
8
|
+
export { default as CoreGetFeatureDensity } from './methods/CoreGetFeatureDensity.js';
|
|
8
9
|
export { default as CoreGetRegions } from './methods/CoreGetRegions.js';
|
|
9
10
|
export { default as CoreGetExportData } from './methods/CoreGetExportData.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import RpcMethodTypeWithRenameRegions from '../../pluggableElementTypes/RpcMethodTypeWithRenameRegions.ts';
|
|
2
|
+
import type { RpcExecuteArgs } from '../RpcRegistry.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The density tier's read: features per bin at the view's bp/px for regions the
|
|
5
|
+
* region-too-large gate refused. Answers `undefined` for an adapter with no
|
|
6
|
+
* density source, and the display keeps the banner.
|
|
7
|
+
*/
|
|
8
|
+
export default class CoreGetFeatureDensity extends RpcMethodTypeWithRenameRegions<'CoreGetFeatureDensity'> {
|
|
9
|
+
name: 'CoreGetFeatureDensity';
|
|
10
|
+
execute(args: RpcExecuteArgs<'CoreGetFeatureDensity'>): Promise<import("../../data_adapters/BaseAdapter/featureDensity.ts").FeatureDensity[] | undefined>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isFeatureAdapter } from '../../data_adapters/BaseAdapter/index.js';
|
|
2
|
+
import { getAdapter } from '../../data_adapters/dataAdapterCache.js';
|
|
3
|
+
import RpcMethodTypeWithRenameRegions from '../../pluggableElementTypes/RpcMethodTypeWithRenameRegions.js';
|
|
4
|
+
/**
|
|
5
|
+
* The density tier's read: features per bin at the view's bp/px for regions the
|
|
6
|
+
* region-too-large gate refused. Answers `undefined` for an adapter with no
|
|
7
|
+
* density source, and the display keeps the banner.
|
|
8
|
+
*/
|
|
9
|
+
export default class CoreGetFeatureDensity extends RpcMethodTypeWithRenameRegions {
|
|
10
|
+
name = 'CoreGetFeatureDensity';
|
|
11
|
+
async execute(args) {
|
|
12
|
+
const { adapterConfig, sessionId, regions, bpPerPx, stopToken } = args;
|
|
13
|
+
const { dataAdapter } = await getAdapter(this.pluginManager, sessionId, adapterConfig);
|
|
14
|
+
return isFeatureAdapter(dataAdapter)
|
|
15
|
+
? dataAdapter.getFeatureDensity(regions, {
|
|
16
|
+
bpPerPx,
|
|
17
|
+
stopToken,
|
|
18
|
+
statusCallback: args.statusCallback,
|
|
19
|
+
})
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/esm/svg/svgReady.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ export declare function awaitSvgReady(model: Pick<SvgExportable, 'svgReady' | 'e
|
|
|
94
94
|
export declare function awaitViewInitialized(view: {
|
|
95
95
|
initialized: boolean;
|
|
96
96
|
error: unknown;
|
|
97
|
+
pendingLaunch?: unknown;
|
|
97
98
|
}): Promise<void>;
|
|
98
99
|
/**
|
|
99
100
|
* How the export answers "a track failed": by failing. A track whose data won't
|
|
@@ -9,7 +9,7 @@ export interface BaseExportSvgOptions {
|
|
|
9
9
|
declare const _default: ({ model, handleClose, exportSvg, children, checkboxes, }: {
|
|
10
10
|
model: IAnyStateTreeNode;
|
|
11
11
|
handleClose: () => void;
|
|
12
|
-
exportSvg: (opts: BaseExportSvgOptions) => Promise<
|
|
12
|
+
exportSvg: (opts: BaseExportSvgOptions) => Promise<unknown>;
|
|
13
13
|
children?: React.ReactNode;
|
|
14
14
|
checkboxes?: React.ReactNode;
|
|
15
15
|
}) => import("react").JSX.Element;
|
package/esm/ui/CascadingMenu.js
CHANGED
|
@@ -6,7 +6,7 @@ import { makeStyles } from '../util/tss-react/index.js';
|
|
|
6
6
|
import { useEventCallback } from '../util/useEventCallback.js';
|
|
7
7
|
import HoverMenu from './HoverMenu.js';
|
|
8
8
|
import { MenuItemTrailing } from './MenuItemTrailing.js';
|
|
9
|
-
import { staysOpenOnClick } from './MenuTypes.js';
|
|
9
|
+
import { resolveSubMenu, staysOpenOnClick } from './MenuTypes.js';
|
|
10
10
|
import { hasMenuItemAdornment } from './menuItemAdornment.js';
|
|
11
11
|
import { isAimedAtPanel } from './submenuAim.js';
|
|
12
12
|
// Compact section headers so tall menus (e.g. a display's flat "Show..."
|
|
@@ -24,6 +24,12 @@ const useStyles = makeStyles()(theme => ({
|
|
|
24
24
|
borderTop: `1px solid ${theme.palette.divider}`,
|
|
25
25
|
marginTop: 4,
|
|
26
26
|
},
|
|
27
|
+
// a leading subHeader has no rows above it to divide from, so the rule and
|
|
28
|
+
// its space would float against the menu's top edge
|
|
29
|
+
leadingSubHeader: {
|
|
30
|
+
borderTopWidth: 0,
|
|
31
|
+
marginTop: 0,
|
|
32
|
+
},
|
|
27
33
|
}));
|
|
28
34
|
const CascadingMenuContext = createContext(undefined);
|
|
29
35
|
function useCascadingMenu() {
|
|
@@ -312,17 +318,36 @@ function CascadingSubmenu({ item, itemKey, inset, columns, hover, onNavigateBack
|
|
|
312
318
|
// up
|
|
313
319
|
paperRef: isOpen ? hover.panelRef : undefined, onClose: () => {
|
|
314
320
|
hover.setSubmenu(undefined);
|
|
315
|
-
}, children: _jsx(
|
|
321
|
+
}, children: _jsx(SubMenuList, { item: item, onNavigateBack: () => {
|
|
316
322
|
hover.setSubmenu(undefined);
|
|
317
323
|
anchorEl?.focus();
|
|
318
324
|
} }) })] }));
|
|
319
325
|
}
|
|
326
|
+
// Resolves the rows inside the panel, which MUI mounts only while it is open:
|
|
327
|
+
// a function-form `subMenu` is not called by listing the parent menu. An
|
|
328
|
+
// observer so the observables that builder reads re-render the open panel, the
|
|
329
|
+
// way an array built in the root observer's render already did.
|
|
330
|
+
const SubMenuList = observer(function SubMenuList({ item, onNavigateBack, }) {
|
|
331
|
+
return (_jsx(CascadingMenuList, { menuItems: resolveSubMenu(item), onNavigateBack: onNavigateBack }));
|
|
332
|
+
});
|
|
320
333
|
// One clickable menu row: label (with optional leading icon) plus its trailing
|
|
321
334
|
// value/help/adornment decorations. The menu-wide `columns` flags let every row
|
|
322
335
|
// reserve matching decoration slots so the columns line up down the menu.
|
|
323
336
|
function CascadingMenuItem({ item, inset, columns, onNavigateBack, onHover, }) {
|
|
324
337
|
const { closeAfterItemClick, onMenuItemClick, onCloseRoot } = useCascadingMenu();
|
|
325
|
-
return (_jsx(DisabledTooltip, { item: item, children: _jsxs(MenuItem, { "data-testid": makeTestId('menuitem', item.label), disabled: item.disabled,
|
|
338
|
+
return (_jsx(DisabledTooltip, { item: item, children: _jsxs(MenuItem, { "data-testid": makeTestId('menuitem', item.label), disabled: item.disabled,
|
|
339
|
+
// A checkbox or radio row states its own value. The glyph
|
|
340
|
+
// `MenuItemEndDecoration` swaps is an `aria-hidden` icon, so without
|
|
341
|
+
// these a screen reader reads "Curved lines" identically whether the
|
|
342
|
+
// setting is on or off, and a test has no way to ask but the MUI icon's
|
|
343
|
+
// internal testid.
|
|
344
|
+
role: item.type === 'checkbox'
|
|
345
|
+
? 'menuitemcheckbox'
|
|
346
|
+
: item.type === 'radio'
|
|
347
|
+
? 'menuitemradio'
|
|
348
|
+
: undefined, "aria-checked": item.type === 'checkbox' || item.type === 'radio'
|
|
349
|
+
? item.checked
|
|
350
|
+
: undefined, onClick: () => {
|
|
326
351
|
// onCloseRoot runs before the callback, so item.onClick must NOT read
|
|
327
352
|
// model state that closing clears (e.g. a right-click menu's ephemeral
|
|
328
353
|
// hit/context fields): capture that state when the menu items are
|
|
@@ -339,7 +364,7 @@ function CascadingMenuItem({ item, inset, columns, onNavigateBack, onHover, }) {
|
|
|
339
364
|
}, children: [_jsx(MenuItemLeadingIcon, { Icon: item.icon }), _jsx(ListItemText, { primary: item.label, secondary: item.subLabel, inset: inset }), _jsx(MenuItemTrailing, { item: item, columns: columns })] }) }));
|
|
340
365
|
}
|
|
341
366
|
function CascadingMenuList({ menuItems, onNavigateBack, }) {
|
|
342
|
-
const { classes } = useStyles();
|
|
367
|
+
const { classes, cx } = useStyles();
|
|
343
368
|
const hover = useSubmenuHover();
|
|
344
369
|
// every row a pointer can rest on asks for the open panel to go away; only a
|
|
345
370
|
// row that owns a submenu, or the panel itself, keeps one up. Whether the ask
|
|
@@ -360,10 +385,7 @@ function CascadingMenuList({ menuItems, onNavigateBack, }) {
|
|
|
360
385
|
return _jsx(Divider, { component: "li" }, `divider-${idx}`);
|
|
361
386
|
}
|
|
362
387
|
if (item.type === 'subHeader') {
|
|
363
|
-
return (_jsx(ListSubheader, { className: classes.subHeader, onMouseEnter: closeOnHover,
|
|
364
|
-
// a leading subHeader has no rows above it to divide from, so drop
|
|
365
|
-
// the divider rule that would otherwise float at the menu's top edge
|
|
366
|
-
sx: idx === 0 ? { borderTop: 'none', marginTop: 0 } : undefined, children: item.label }, `subHeader-${item.label}`));
|
|
388
|
+
return (_jsx(ListSubheader, { className: cx(classes.subHeader, idx === 0 && classes.leadingSubHeader), onMouseEnter: closeOnHover, children: item.label }, `subHeader-${item.label}`));
|
|
367
389
|
}
|
|
368
390
|
if (item.type === 'custom') {
|
|
369
391
|
return (_jsx(CustomMenuRow, { item: item, onHover: closeOnHover }, `custom-${item.label}`));
|
|
@@ -15,12 +15,11 @@ export default function ErrorMessageStackTraceDialog({ error, onClose, extra, })
|
|
|
15
15
|
const errorText = error ? `${error}` : '';
|
|
16
16
|
const stackTrace = formatErrorStack(error);
|
|
17
17
|
const { data: mappedStackTrace, isLoading } = useFetch(['mappedStackTrace', stackTrace], () => mapStackTrace(stackTrace));
|
|
18
|
-
// The rung
|
|
19
|
-
// which rungs exist, since Canvas2D means neither and WebGL2 means no
|
|
20
|
-
// It
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// the report they sent still said WebGL2.
|
|
18
|
+
// The rung createGpuHal built, not a list of the ones available: it already
|
|
19
|
+
// says which rungs exist, since Canvas2D means neither and WebGL2 means no
|
|
20
|
+
// WebGPU. It also honours the GPU banner's "disable GPU", which matters most
|
|
21
|
+
// in exactly this dialog — a user reporting a rendering bug has often already
|
|
22
|
+
// clicked it.
|
|
24
23
|
const graphicsInfo = graphicsCapabilities
|
|
25
24
|
? `Graphics: ${effectiveRenderer(graphicsCapabilities)}`
|
|
26
25
|
: '';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BaseExportSvgOptions } from './BaseExportSvgDialog.tsx';
|
|
2
2
|
export default function ExportSvgDialog({ model, handleClose, }: {
|
|
3
3
|
model: {
|
|
4
|
-
exportSvg(opts: BaseExportSvgOptions): Promise<
|
|
4
|
+
exportSvg(opts: BaseExportSvgOptions): Promise<unknown>;
|
|
5
5
|
};
|
|
6
6
|
handleClose: () => void;
|
|
7
7
|
}): import("react").JSX.Element;
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns false, then flips true once `active` has stayed true continuously for
|
|
3
|
+
* `delayMs`. Each activation gets a fresh delay, and the flag drops the moment
|
|
4
|
+
* `active` does.
|
|
5
|
+
*
|
|
6
|
+
* Keyed on a count of RISING edges rather than on `active` itself, so the
|
|
7
|
+
* falling edge does no work at all. A display refetching through a wheel zoom
|
|
8
|
+
* flips `active` several times a second — it finishes a fetch, waits out the
|
|
9
|
+
* debounce, starts the next — and an effect depending on `active` tore its timer
|
|
10
|
+
* down and built a new one on each of those, twice over, for a scrim that by
|
|
11
|
+
* construction never appears. Deriving the flag from a comparison instead means
|
|
12
|
+
* one `setTimeout` per loading pulse, which is the floor for these semantics.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useDelayedFlag(active: boolean, delayMs: number): boolean;
|
|
1
15
|
export default function LoadingOverlay({ statusMessage, progress, isVisible, immediate, canceled, onCancel, onRetry, }: {
|
|
2
16
|
statusMessage?: string;
|
|
3
17
|
progress?: number;
|
package/esm/ui/LoadingOverlay.js
CHANGED
|
@@ -27,7 +27,7 @@ const flashDelayMs = 250;
|
|
|
27
27
|
* construction never appears. Deriving the flag from a comparison instead means
|
|
28
28
|
* one `setTimeout` per loading pulse, which is the floor for these semantics.
|
|
29
29
|
*/
|
|
30
|
-
function useDelayedFlag(active, delayMs) {
|
|
30
|
+
export function useDelayedFlag(active, delayMs) {
|
|
31
31
|
const [previous, setPrevious] = useState(active);
|
|
32
32
|
const [activation, setActivation] = useState(0);
|
|
33
33
|
if (previous !== active) {
|