@jbrowse/core 5.0.0-beta.1 → 5.0.0-beta.11
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 +1709 -390
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +5 -5
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -5
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +34 -29
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseCard.js +1 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BasicValue.d.ts +11 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BasicValue.js +37 -14
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.d.ts +1 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +15 -31
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +4 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +12 -25
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetailsFrame.d.ts +11 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetailsFrame.js +11 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +8 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +24 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Formatter.js +6 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +5 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.d.ts +6 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +7 -18
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.d.ts +16 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +49 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.d.ts +0 -8
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.js +6 -29
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceContents.js +7 -34
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceName.js +2 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/TranscriptSelector.js +3 -1
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/model.d.ts +12 -0
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/model.js +12 -5
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/useSequenceData.js +8 -5
- package/esm/BaseFeatureWidget/configSchema.d.ts +1 -1
- package/esm/BaseFeatureWidget/formatDetails.d.ts +13 -29
- package/esm/BaseFeatureWidget/formatDetails.js +62 -83
- package/esm/BaseFeatureWidget/index.d.ts +2 -1
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +42 -29
- package/esm/BaseFeatureWidget/stateModelFactory.js +98 -98
- package/esm/BaseFeatureWidget/types.d.ts +12 -6
- package/esm/BaseFeatureWidget/util.d.ts +0 -10
- package/esm/BaseFeatureWidget/util.js +0 -17
- package/esm/CorePlugin.js +34 -3
- package/esm/PluginLoader.d.ts +24 -13
- package/esm/PluginLoader.js +167 -51
- package/esm/PluginManager.d.ts +130 -24
- package/esm/PluginManager.js +180 -32
- package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
- package/esm/ReExports/MuiDataGridReExports.js +2 -2
- package/esm/ReExports/coreModules.generated.d.ts +2 -0
- package/esm/ReExports/coreModules.generated.js +530 -0
- package/esm/ReExports/coreWorkerModules.generated.d.ts +2 -0
- package/esm/ReExports/coreWorkerModules.generated.js +490 -0
- package/esm/ReExports/frameworkModules.d.ts +2 -0
- package/esm/ReExports/frameworkModules.js +68 -0
- package/esm/ReExports/frameworkShared.d.ts +12 -0
- package/esm/ReExports/frameworkShared.js +16 -0
- package/esm/ReExports/frameworkWorkerModules.generated.d.ts +2 -0
- package/esm/ReExports/frameworkWorkerModules.generated.js +130 -0
- package/esm/ReExports/list.js +528 -79
- package/esm/ReExports/modules.d.ts +1 -1
- package/esm/ReExports/modules.js +10 -165
- package/esm/ReExports/registry.d.ts +1 -0
- package/esm/ReExports/registry.js +23 -5
- package/esm/ReExports/uiStub.d.ts +3 -0
- package/esm/ReExports/uiStub.js +33 -0
- package/esm/ReExports/workerModules.d.ts +2 -0
- package/esm/ReExports/workerModules.js +11 -0
- package/esm/TextSearch/TextSearchManager.d.ts +27 -13
- package/esm/TextSearch/TextSearchManager.js +77 -36
- package/esm/TextSearch/places.d.ts +12 -0
- package/esm/TextSearch/places.js +94 -0
- package/esm/assemblyManager/assembly.d.ts +21 -19
- package/esm/assemblyManager/assembly.js +28 -26
- package/esm/assemblyManager/assemblyAdapters.d.ts +1 -1
- package/esm/assemblyManager/assemblyAdapters.js +8 -2
- package/esm/assemblyManager/assemblyConfigSchema.d.ts +31 -90
- package/esm/assemblyManager/assemblyConfigSchema.js +35 -47
- package/esm/assemblyManager/assemblyManager.d.ts +35 -180
- package/esm/assemblyManager/assemblyManager.js +47 -51
- package/esm/assemblyManager/expandAssemblyConfigShorthand.d.ts +25 -18
- package/esm/assemblyManager/expandAssemblyConfigShorthand.js +78 -49
- package/esm/assemblyManager/geneticCodes.js +2 -5
- package/esm/assemblyManager/getSequenceAdapterConfig.d.ts +10 -0
- package/esm/assemblyManager/getSequenceAdapterConfig.js +10 -0
- package/esm/assemblyManager/indexAssemblyNames.d.ts +9 -0
- package/esm/assemblyManager/indexAssemblyNames.js +22 -0
- package/esm/assemblyManager/loadRefNameMap.d.ts +1 -1
- package/esm/assemblyManager/loadRefNameMap.js +4 -9
- package/esm/assemblyManager/refNameMapKey.d.ts +7 -0
- package/esm/assemblyManager/refNameMapKey.js +12 -0
- package/esm/checkPlugins.d.ts +2 -0
- package/esm/checkPlugins.js +38 -17
- package/esm/configuration/bamIndexFields.d.ts +49 -0
- package/esm/configuration/bamIndexFields.js +41 -0
- package/esm/configuration/configurationSchema.d.ts +101 -71
- package/esm/configuration/configurationSchema.js +207 -134
- package/esm/configuration/configurationSchemaUnion.d.ts +39 -0
- package/esm/configuration/configurationSchemaUnion.js +56 -0
- package/esm/configuration/configurationSlot.d.ts +150 -60
- package/esm/configuration/configurationSlot.js +103 -75
- package/esm/configuration/fillLocations.d.ts +14 -0
- package/esm/configuration/fillLocations.js +14 -0
- package/esm/configuration/formatAboutConfigSchema.d.ts +7 -21
- package/esm/configuration/formatDetailsConfigSchema.d.ts +11 -37
- package/esm/configuration/formatDetailsConfigSchema.js +10 -13
- package/esm/configuration/fullConfSnapshot.d.ts +4 -19
- package/esm/configuration/fullConfSnapshot.js +30 -52
- package/esm/configuration/getConf.d.ts +45 -41
- package/esm/configuration/getConf.js +111 -44
- package/esm/configuration/index.d.ts +26 -11
- package/esm/configuration/index.js +16 -7
- package/esm/configuration/indexType.d.ts +26 -0
- package/esm/configuration/indexType.js +38 -0
- package/esm/configuration/mergeFormatCallbacks.d.ts +6 -7
- package/esm/configuration/mergeFormatCallbacks.js +13 -10
- package/esm/configuration/plot.d.ts +61 -0
- package/esm/configuration/plot.js +142 -0
- package/esm/configuration/readConfObject.d.ts +2 -24
- package/esm/configuration/readConfObject.js +20 -63
- package/esm/configuration/requirements.d.ts +37 -0
- package/esm/configuration/requirements.js +88 -0
- package/esm/configuration/schemaRegistry.d.ts +32 -15
- package/esm/configuration/schemaRegistry.js +33 -35
- package/esm/configuration/schemaTypes.d.ts +21 -5
- package/esm/configuration/schemaTypes.js +66 -55
- package/esm/configuration/slotFacade.d.ts +12 -29
- package/esm/configuration/slotFacade.js +44 -23
- package/esm/configuration/snapshotPreprocess.d.ts +43 -0
- package/esm/configuration/snapshotPreprocess.js +161 -0
- package/esm/configuration/tabixIndexFields.d.ts +30 -4
- package/esm/configuration/tabixIndexFields.js +21 -4
- package/esm/configuration/tabixShorthand.d.ts +34 -17
- package/esm/configuration/tabixShorthand.js +49 -22
- package/esm/configuration/types.d.ts +182 -43
- package/esm/configuration/uriShorthand.d.ts +9 -0
- package/esm/configuration/uriShorthand.js +16 -0
- package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +13 -19
- package/esm/data_adapters/BaseAdapter/BaseAdapter.js +12 -19
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +40 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +68 -5
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +40 -0
- package/esm/data_adapters/BaseAdapter/featureDensity.js +31 -0
- package/esm/data_adapters/BaseAdapter/index.d.ts +23 -3
- package/esm/data_adapters/BaseAdapter/index.js +1 -0
- package/esm/data_adapters/BaseAdapter/rowSources.d.ts +37 -0
- package/esm/data_adapters/BaseAdapter/rowSources.js +7 -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 +8 -12
- package/esm/data_adapters/BaseAdapter/zoomRange.d.ts +10 -0
- package/esm/data_adapters/CytobandAdapter/CytobandAdapter.js +1 -1
- package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +7 -11
- package/esm/data_adapters/CytobandAdapter/configSchema.js +3 -17
- package/esm/data_adapters/dataAdapterCache.d.ts +19 -2
- package/esm/data_adapters/dataAdapterCache.js +44 -10
- package/esm/data_adapters/getFeatureAdapter.d.ts +6 -4
- package/esm/data_adapters/getFeatureAdapter.js +8 -8
- package/esm/data_adapters/getSequenceSubAdapter.d.ts +7 -9
- package/esm/data_adapters/getSequenceSubAdapter.js +8 -10
- package/esm/pluggableElementTypes/AdapterType.d.ts +8 -8
- package/esm/pluggableElementTypes/AdapterType.js +1 -1
- package/esm/pluggableElementTypes/DisplayType.d.ts +53 -16
- package/esm/pluggableElementTypes/DisplayType.js +28 -12
- package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +32 -0
- package/esm/pluggableElementTypes/LazyStateModelElement.js +77 -0
- package/esm/pluggableElementTypes/PluggableElementBase.d.ts +3 -5
- package/esm/pluggableElementTypes/PluggableElementBase.js +3 -5
- package/esm/pluggableElementTypes/RpcMethodType.d.ts +11 -1
- package/esm/pluggableElementTypes/RpcMethodType.js +25 -9
- package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.d.ts +1 -2
- package/esm/pluggableElementTypes/TextSearchAdapterType.d.ts +7 -7
- package/esm/pluggableElementTypes/ViewType.d.ts +20 -4
- package/esm/pluggableElementTypes/ViewType.js +32 -4
- package/esm/pluggableElementTypes/WidgetType.d.ts +6 -0
- package/esm/pluggableElementTypes/WidgetType.js +6 -0
- package/esm/pluggableElementTypes/addMenuItems.d.ts +3 -2
- package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
- package/esm/pluggableElementTypes/extendElementType.js +9 -5
- package/esm/pluggableElementTypes/index.d.ts +2 -1
- package/esm/pluggableElementTypes/index.js +2 -9
- package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +19 -9
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +122 -28
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +155 -11
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +65 -16
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +179 -117
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +87 -18
- package/esm/pluggableElementTypes/models/BaseViewModel.js +54 -11
- package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +26 -16
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +15 -11
- package/esm/pluggableElementTypes/models/assertDisplayContract.js +25 -32
- package/esm/pluggableElementTypes/models/baseConnectionConfig.d.ts +22 -18
- package/esm/pluggableElementTypes/models/baseConnectionConfig.js +5 -5
- package/esm/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +26 -31
- package/esm/pluggableElementTypes/models/baseTrackConfig.d.ts +108 -147
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +96 -73
- package/esm/pluggableElementTypes/models/components/SaveTrackData.js +4 -6
- package/esm/pluggableElementTypes/models/components/fetchTrackData.d.ts +3 -4
- package/esm/pluggableElementTypes/models/components/fetchTrackData.js +3 -3
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.d.ts +23 -13
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +80 -48
- package/esm/pluggableElementTypes/models/index.d.ts +2 -3
- package/esm/pluggableElementTypes/models/index.js +2 -3
- package/esm/pluggableElementTypes/models/migrateTrackConfig.d.ts +15 -1
- package/esm/pluggableElementTypes/models/migrateTrackConfig.js +85 -25
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.d.ts +4 -3
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +141 -19
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/types.d.ts +3 -3
- package/esm/pluginDefinitions.d.ts +34 -7
- package/esm/pluginDefinitions.js +54 -20
- package/esm/rpc/BaseRpcDriver.d.ts +2 -2
- package/esm/rpc/BaseRpcDriver.js +25 -30
- package/esm/rpc/MainThreadRpcDriver.d.ts +2 -2
- package/esm/rpc/MainThreadRpcDriver.js +13 -8
- package/esm/rpc/RpcClient.d.ts +18 -6
- package/esm/rpc/RpcClient.js +51 -16
- package/esm/rpc/RpcManager.d.ts +14 -10
- package/esm/rpc/RpcManager.js +11 -1
- package/esm/rpc/RpcRegistry.d.ts +40 -7
- package/esm/rpc/RpcServer.d.ts +3 -1
- package/esm/rpc/RpcServer.js +19 -12
- package/esm/rpc/WebWorkerRpcDriver.d.ts +11 -4
- package/esm/rpc/WebWorkerRpcDriver.js +64 -68
- package/esm/rpc/byteBudget.d.ts +20 -5
- package/esm/rpc/byteBudget.js +16 -5
- package/esm/rpc/configSchema.d.ts +7 -21
- package/esm/rpc/coreRpcMethods.d.ts +4 -0
- package/esm/rpc/coreRpcMethods.js +4 -0
- package/esm/rpc/methods/CoreGetEncodedFeature.d.ts +13 -0
- package/esm/rpc/methods/CoreGetEncodedFeature.js +32 -0
- package/esm/rpc/methods/CoreGetEncodedLayers.d.ts +16 -0
- package/esm/rpc/methods/CoreGetEncodedLayers.js +59 -0
- package/esm/rpc/methods/CoreGetExportData.js +3 -4
- package/esm/rpc/methods/CoreGetFeatureDensity.d.ts +11 -0
- package/esm/rpc/methods/CoreGetFeatureDensity.js +22 -0
- package/esm/rpc/methods/CoreGetFeatures.js +3 -5
- package/esm/rpc/methods/CoreGetRefNames.js +2 -12
- package/esm/rpc/methods/CoreGetRegionByteEstimate.js +1 -1
- package/esm/rpc/methods/CoreGetSequence.js +2 -2
- package/esm/rpc/methods/CoreLoadAdapterCode.d.ts +13 -0
- package/esm/rpc/methods/CoreLoadAdapterCode.js +16 -0
- package/esm/rpc/methods/layerFeatures.d.ts +33 -0
- package/esm/rpc/methods/layerFeatures.js +29 -0
- package/esm/svg/SvgExport.js +6 -7
- package/esm/svg/SvgThemeProviders.d.ts +12 -0
- package/esm/svg/SvgThemeProviders.js +15 -0
- package/esm/svg/exportViewSvg.d.ts +28 -0
- package/esm/svg/exportViewSvg.js +13 -0
- package/esm/svg/normalizeSvgMarkup.d.ts +7 -0
- package/esm/svg/normalizeSvgMarkup.js +99 -0
- package/esm/svg/serializeSvg.d.ts +7 -0
- package/esm/svg/serializeSvg.js +11 -0
- package/esm/svg/svgId.d.ts +1 -1
- package/esm/svg/svgId.js +1 -1
- package/esm/svg/svgReady.d.ts +9 -7
- package/esm/svg/svgReady.js +8 -7
- package/esm/svg/trackNames.d.ts +7 -5
- package/esm/svg/trackNames.js +12 -9
- package/esm/svg/wrapSvgExport.js +6 -74
- package/esm/ui/AddCustomPluginDialog.js +3 -8
- package/esm/ui/AppReadyMarker.d.ts +45 -0
- package/esm/ui/AppReadyMarker.js +89 -0
- package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
- package/esm/ui/CascadingMenu.js +181 -104
- package/esm/ui/DropDownMenu.js +2 -1
- package/esm/ui/ErrorBanner.js +1 -1
- package/esm/ui/ErrorBoundary.d.ts +2 -2
- package/esm/ui/ErrorMessageStackTraceContents.js +2 -1
- package/esm/ui/ErrorMessageStackTraceDialog.js +5 -11
- package/esm/ui/ExportSvgDialog.d.ts +1 -1
- package/esm/ui/FileDropZone.js +2 -1
- package/esm/ui/FileSelector/useInternetAccounts.d.ts +156 -96
- package/esm/ui/HoverMenu.d.ts +1 -2
- package/esm/ui/HoverMenu.js +6 -3
- package/esm/ui/JexlFilterDialog.d.ts +13 -10
- package/esm/ui/JexlFilterDialog.js +122 -50
- package/esm/ui/JexlFilterRowEditors.d.ts +15 -0
- package/esm/ui/JexlFilterRowEditors.js +90 -0
- package/esm/ui/LazyBaseTooltip.d.ts +4 -0
- package/esm/ui/LazyBaseTooltip.js +9 -0
- package/esm/ui/LegendSwatchGlyph.js +26 -21
- package/esm/ui/LoadingOverlay.d.ts +14 -0
- package/esm/ui/LoadingOverlay.js +4 -2
- package/esm/ui/MenuTypes.d.ts +23 -53
- package/esm/ui/MenuTypes.js +3 -0
- package/esm/ui/MonospaceTextField.d.ts +2 -1
- package/esm/ui/MonospaceTextField.js +23 -20
- package/esm/ui/PaletteContext.d.ts +10 -5
- package/esm/ui/PaletteContext.js +44 -6
- package/esm/ui/RefNameAutocomplete/SearchOption.d.ts +13 -0
- package/esm/ui/RefNameAutocomplete/SearchOption.js +45 -0
- package/esm/ui/RefNameAutocomplete/index.d.ts +1 -2
- package/esm/ui/RefNameAutocomplete/index.js +8 -2
- package/esm/ui/RefNameAutocomplete/util.d.ts +13 -0
- package/esm/ui/RefNameAutocomplete/util.js +42 -1
- package/esm/ui/ResizeHandle.d.ts +3 -1
- package/esm/ui/ResizeHandle.js +44 -11
- package/esm/ui/ScrollChrome.d.ts +13 -0
- package/esm/ui/ScrollChrome.js +11 -0
- package/esm/ui/ScrollEdgeShadow.d.ts +6 -9
- package/esm/ui/ScrollEdgeShadow.js +14 -35
- package/esm/ui/ScrollZoomToggle.d.ts +4 -27
- package/esm/ui/ScrollZoomToggle.js +34 -51
- package/esm/ui/SessionJsonPanel.d.ts +3 -0
- package/esm/ui/SessionJsonPanel.js +14 -0
- package/esm/ui/SettingsChangesTable.d.ts +1 -0
- package/esm/ui/SettingsChangesTable.js +49 -11
- package/esm/ui/ShareLinkField.d.ts +1 -3
- package/esm/ui/ShareLinkField.js +13 -40
- package/esm/ui/SizeSliderRow.d.ts +1 -3
- package/esm/ui/SizeSliderRow.js +4 -6
- package/esm/ui/SnackbarModel.js +79 -67
- package/esm/ui/StatusProgressBar.js +2 -2
- package/esm/ui/SvgColorLegend.d.ts +9 -4
- package/esm/ui/SvgColorLegend.js +82 -41
- package/esm/ui/VerticalScrollbar.d.ts +13 -34
- package/esm/ui/VerticalScrollbar.js +29 -83
- package/esm/ui/ViewLoadingScreen.d.ts +5 -4
- package/esm/ui/ViewLoadingScreen.js +8 -32
- package/esm/ui/colorScale.d.ts +92 -0
- package/esm/ui/colorScale.js +72 -0
- package/esm/ui/colors.d.ts +64 -0
- package/esm/ui/colors.js +230 -1
- package/esm/ui/hoverBoxStyle.d.ts +14 -2
- package/esm/ui/hoverBoxStyle.js +17 -2
- package/esm/ui/index.d.ts +12 -12
- package/esm/ui/index.js +14 -22
- package/esm/ui/launchViewMenu.js +15 -5
- package/esm/ui/legendMenuItem.d.ts +10 -32
- package/esm/ui/legendMenuItem.js +9 -36
- package/esm/ui/legendSpec.d.ts +15 -8
- package/esm/ui/legendSpec.js +14 -23
- package/esm/ui/makeSizeMenu.d.ts +0 -6
- package/esm/ui/makeSizeMenu.js +6 -30
- package/esm/ui/measureLegendText.js +1 -1
- package/esm/ui/menuItemAdornment.d.ts +9 -20
- package/esm/ui/menuItemAdornment.js +10 -32
- package/esm/ui/menuItems.d.ts +2 -7
- package/esm/ui/menuItems.js +1 -6
- package/esm/ui/multiTrackMenuItems.d.ts +6 -0
- package/esm/ui/palette.d.ts +118 -116
- package/esm/ui/palette.js +114 -75
- package/esm/ui/replaceViewAction.d.ts +1 -1
- package/esm/ui/replaceViewAction.js +1 -1
- package/esm/ui/theme.d.ts +43 -119
- package/esm/ui/theme.js +62 -78
- package/esm/ui/toggleMenuItems.d.ts +1 -3
- package/esm/ui/toggleMenuItems.js +6 -5
- package/esm/ui/useAssemblySelection.d.ts +4 -4
- package/esm/ui/viewHeaderHeight.d.ts +1 -0
- package/esm/ui/viewHeaderHeight.js +1 -0
- package/esm/util/Base1DUtils.d.ts +5 -3
- package/esm/util/Base1DUtils.js +14 -6
- package/esm/util/Base1DViewModel.d.ts +2 -1
- package/esm/util/Base1DViewModel.js +3 -2
- package/esm/util/SvgCanvas.d.ts +15 -13
- package/esm/util/SvgCanvas.js +76 -56
- package/esm/util/TimeTraveller.d.ts +3 -0
- package/esm/util/TimeTraveller.js +34 -2
- package/esm/util/aborting.d.ts +39 -0
- package/esm/util/aborting.js +88 -6
- package/esm/util/adapterMetadata.d.ts +1 -1
- package/esm/util/adapterMetadata.js +6 -5
- package/esm/util/addAndShowTrack.d.ts +2 -5
- package/esm/util/addAndShowTrack.js +5 -1
- package/esm/util/addRelativeUris.d.ts +17 -5
- package/esm/util/addRelativeUris.js +46 -10
- package/esm/util/addTrackFromWidget.d.ts +2 -5
- package/esm/util/addTrackFromWidget.js +5 -4
- package/esm/util/aggregateFieldName.d.ts +10 -0
- package/esm/util/aggregateFieldName.js +8 -0
- package/esm/util/analytics.js +46 -13
- package/esm/util/animationAllowed.d.ts +9 -0
- package/esm/util/animationAllowed.js +13 -0
- package/esm/util/applyRowResizeWheel.d.ts +10 -5
- package/esm/util/applyRowResizeWheel.js +10 -21
- package/esm/util/bandHeight.d.ts +10 -0
- package/esm/util/bandHeight.js +29 -0
- package/esm/util/bandLayout.d.ts +4 -4
- package/esm/util/bandLayout.js +4 -4
- package/esm/util/baseDisplayConfig.d.ts +8 -0
- package/esm/util/baseDisplayConfig.js +27 -0
- package/esm/util/bezierConnector.d.ts +4 -3
- package/esm/util/bezierConnector.js +38 -45
- package/esm/util/bgzfWorkerPool.d.ts +20 -74
- package/esm/util/bgzfWorkerPool.js +20 -74
- package/esm/util/binnedAggregate.d.ts +17 -0
- package/esm/util/binnedAggregate.js +275 -0
- package/esm/util/cacheBudgets.d.ts +22 -19
- package/esm/util/cacheBudgets.js +22 -19
- package/esm/util/cachedSetup.d.ts +16 -6
- package/esm/util/cachedSetup.js +108 -38
- package/esm/util/categoricalField.d.ts +56 -0
- package/esm/util/categoricalField.js +73 -0
- package/esm/util/cellMatches.d.ts +23 -0
- package/esm/util/cellMatches.js +264 -0
- package/esm/util/cellsStep.d.ts +29 -0
- package/esm/util/cellsStep.js +437 -0
- package/esm/util/clampToContig.d.ts +17 -0
- package/esm/util/clampToContig.js +19 -0
- package/esm/util/coarseStripHTML.js +1 -2
- package/esm/util/color/cssColorsLevel4.d.ts +1 -0
- package/esm/util/color/cssColorsLevel4.js +1 -0
- package/esm/util/color/index.d.ts +5 -3
- package/esm/util/color/index.js +7 -4
- package/esm/util/colorBits.d.ts +3 -3
- package/esm/util/colorBits.js +19 -44
- package/esm/util/colorRamp.d.ts +49 -5
- package/esm/util/colorRamp.js +169 -18
- package/esm/util/colorScale.d.ts +156 -0
- package/esm/util/colorScale.js +243 -0
- package/esm/util/colorSchemes.d.ts +21 -0
- package/esm/util/colorSchemes.js +30 -0
- package/esm/util/copyToClipboard.js +8 -1
- package/esm/util/{createStopTokenRotation.d.ts → createAbortRotation.d.ts} +21 -23
- package/esm/util/{createStopTokenRotation.js → createAbortRotation.js} +21 -52
- package/esm/util/createSvgRasterCanvas.d.ts +10 -0
- package/esm/util/cssColorParse.d.ts +15 -0
- package/esm/util/cssColorParse.js +53 -0
- package/esm/util/diagonalizeRegions.d.ts +2 -3
- package/esm/util/diagonalizeRegions.js +8 -13
- package/esm/util/expandLooseSearchIndex.d.ts +19 -0
- package/esm/util/expandLooseSearchIndex.js +29 -0
- package/esm/util/featureTable.d.ts +224 -0
- package/esm/util/featureTable.js +366 -0
- package/esm/util/featureTransforms.d.ts +81 -0
- package/esm/util/featureTransforms.js +1231 -0
- package/esm/util/featureTypes.d.ts +24 -0
- package/esm/util/featureTypes.js +35 -0
- package/esm/util/fetchAndMaybeUnzip.js +16 -9
- package/esm/util/fetchContext.d.ts +7 -8
- package/esm/util/fetchContext.js +3 -3
- package/esm/util/fetchHub.d.ts +4 -2
- package/esm/util/fetchHub.js +2 -2
- package/esm/util/fetchPhases.d.ts +10 -10
- package/esm/util/fetchSeq.d.ts +2 -3
- package/esm/util/fetchSeq.js +2 -2
- package/esm/util/fieldReader.d.ts +17 -0
- package/esm/util/fieldReader.js +62 -0
- package/esm/util/formatBytes.js +1 -1
- package/esm/util/formatGuessers.d.ts +25 -14
- package/esm/util/formatGuessers.js +42 -27
- package/esm/util/formatRelativeTime.js +1 -1
- package/esm/util/freezeDeep.d.ts +8 -10
- package/esm/util/freezeDeep.js +8 -10
- package/esm/util/getLocationUri.d.ts +2 -1
- package/esm/util/getLocationUri.js +8 -2
- package/esm/util/groupKeys.d.ts +76 -0
- package/esm/util/groupKeys.js +156 -0
- package/esm/util/highlights.d.ts +10 -6
- package/esm/util/highlights.js +12 -25
- package/esm/util/hooks.d.ts +31 -2
- package/esm/util/hooks.js +72 -3
- package/esm/util/index.d.ts +11 -11
- package/esm/util/index.js +11 -10
- package/esm/util/indexCandidates.d.ts +1 -31
- package/esm/util/indexCandidates.js +5 -63
- package/esm/util/installFetch.d.ts +77 -37
- package/esm/util/installFetch.js +65 -38
- package/esm/util/installInitAutorun.d.ts +14 -13
- package/esm/util/installInitAutorun.js +17 -17
- package/esm/util/installPrerequisiteFetch.d.ts +115 -0
- package/esm/util/installPrerequisiteFetch.js +111 -0
- package/esm/util/intervals.js +9 -4
- package/esm/util/io/index.js +22 -15
- package/esm/util/isDataCurrent.d.ts +7 -5
- package/esm/util/isDataCurrent.js +9 -6
- package/esm/util/isTextEntryFocused.d.ts +7 -0
- package/esm/util/isTextEntryFocused.js +16 -0
- package/esm/util/jexl.js +24 -21
- package/esm/util/jexlFilterRows.d.ts +89 -0
- package/esm/util/jexlFilterRows.js +252 -0
- package/esm/util/jexlFilters.d.ts +32 -57
- package/esm/util/jexlFilters.js +31 -29
- package/esm/util/jexlStrings.d.ts +3 -4
- package/esm/util/jexlStrings.js +2 -3
- package/esm/util/layouts/GranularRectLayout.d.ts +8 -1
- package/esm/util/layouts/GranularRectLayout.js +25 -8
- package/esm/util/lazyAfterAttach.d.ts +13 -0
- package/esm/util/lazyAfterAttach.js +31 -0
- package/esm/util/lazyWithPreload.d.ts +19 -0
- package/esm/util/lazyWithPreload.js +27 -0
- package/esm/util/legendCandidates.d.ts +72 -0
- package/esm/util/legendCandidates.js +138 -0
- package/esm/util/locString.js +5 -2
- package/esm/util/localStorage.js +4 -4
- package/esm/util/markEncoding.d.ts +150 -0
- package/esm/util/markEncoding.js +885 -0
- package/esm/util/markEncodingTypes.d.ts +595 -0
- package/esm/util/markEncodingTypes.js +8 -0
- package/esm/util/mst-reflection.d.ts +2 -20
- package/esm/util/mst-reflection.js +3 -53
- package/esm/util/mstUtils.d.ts +31 -23
- package/esm/util/mstUtils.js +39 -24
- package/esm/util/numericUtils.d.ts +7 -0
- package/esm/util/numericUtils.js +16 -0
- package/esm/util/numericValue.d.ts +14 -0
- package/esm/util/numericValue.js +34 -0
- package/esm/util/openFeatureWidget.d.ts +5 -0
- package/esm/util/openFeatureWidget.js +2 -2
- package/esm/util/openViews.d.ts +17 -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/parseLineByLine.d.ts +4 -5
- package/esm/util/parseLineByLine.js +8 -14
- package/esm/util/pluginStore.d.ts +6 -8
- package/esm/util/pluginStore.js +17 -16
- package/esm/util/preloadComponent.d.ts +5 -0
- package/esm/util/preloadComponent.js +11 -0
- package/esm/util/progress.d.ts +22 -22
- package/esm/util/progress.js +27 -26
- package/esm/util/quantileExtent.d.ts +49 -0
- package/esm/util/quantileExtent.js +162 -0
- package/esm/util/range.d.ts +13 -9
- package/esm/util/range.js +17 -8
- package/esm/util/renameRegions.d.ts +26 -6
- package/esm/util/renameRegions.js +68 -54
- package/esm/util/renderToStaticMarkup.js +24 -14
- package/esm/util/rxjs.d.ts +23 -8
- package/esm/util/rxjs.js +61 -15
- package/esm/util/samplesTsv.d.ts +49 -0
- package/esm/util/samplesTsv.js +86 -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/selectEncodedFeature.d.ts +16 -0
- package/esm/util/selectEncodedFeature.js +34 -0
- package/esm/util/sessionSharing.d.ts +7 -5
- package/esm/util/sessionSharing.js +23 -23
- package/esm/util/shapeNameList.d.ts +2 -0
- package/esm/util/shapeNameList.js +6 -0
- package/esm/util/shapeNames.d.ts +7 -0
- package/esm/util/shapeNames.js +11 -0
- package/esm/util/simpleFeature.d.ts +0 -1
- package/esm/util/springAnimate.js +1 -1
- package/esm/util/starFusion.d.ts +26 -0
- package/esm/util/starFusion.js +37 -0
- package/esm/util/stepTables.d.ts +96 -0
- package/esm/util/stepTables.js +277 -0
- package/esm/util/svAlt.d.ts +145 -0
- package/esm/util/svAlt.js +364 -0
- package/esm/util/svgColorProps.d.ts +11 -0
- package/esm/util/svgColorProps.js +28 -1
- package/esm/util/systemColorScheme.d.ts +12 -0
- package/esm/util/systemColorScheme.js +27 -0
- package/esm/util/tabix.d.ts +19 -10
- package/esm/util/tabix.js +19 -14
- package/esm/util/thresholdScale.d.ts +91 -0
- package/esm/util/thresholdScale.js +166 -0
- package/esm/util/timeGate.d.ts +4 -5
- package/esm/util/timeGate.js +4 -5
- package/esm/util/trackConfigDelta.d.ts +26 -26
- package/esm/util/trackConfigDelta.js +63 -47
- package/esm/util/tracks.d.ts +120 -66
- package/esm/util/tracks.js +501 -151
- package/esm/util/translateTranscript.d.ts +44 -0
- package/esm/util/translateTranscript.js +102 -0
- package/esm/util/types/data.d.ts +0 -2
- package/esm/util/types/index.d.ts +121 -22
- package/esm/util/types/index.js +9 -0
- package/esm/util/types/mst.d.ts +3 -0
- package/esm/util/types/mst.js +4 -0
- package/esm/util/types/renameIds.d.ts +1 -0
- package/esm/util/types/renameIds.js +29 -0
- package/esm/util/types/services.d.ts +1 -1
- package/esm/util/unknownSnapshotKeys.d.ts +53 -0
- package/esm/util/unknownSnapshotKeys.js +76 -0
- package/esm/util/useFeatureSequence.js +5 -5
- package/esm/util/useFetch.d.ts +3 -4
- package/esm/util/useFetch.js +19 -10
- package/esm/util/useFetchPlugins.d.ts +6 -2
- package/esm/util/useFetchPlugins.js +7 -3
- package/esm/util/usePanZoom.js +10 -3
- package/esm/util/usePanelVirtualScroll.d.ts +7 -35
- package/esm/util/usePanelVirtualScroll.js +9 -36
- package/esm/util/useRafCommit.js +1 -0
- package/esm/util/useRowVirtualScroll.d.ts +6 -29
- package/esm/util/useRowVirtualScroll.js +8 -49
- package/esm/util/useVirtualScrollWheel.d.ts +20 -4
- package/esm/util/useVirtualScrollWheel.js +40 -74
- package/esm/util/viewHighlights.d.ts +3 -0
- package/esm/util/viewHighlights.js +5 -0
- package/esm/util/viewStatus.d.ts +47 -15
- package/esm/util/viewStatus.js +34 -0
- package/esm/util/wheelZoom.d.ts +7 -1
- package/esm/util/wheelZoom.js +85 -19
- package/esm/util/whenViewSettled.d.ts +55 -8
- package/esm/util/whenViewSettled.js +56 -7
- package/esm/util/withFeatureDetails.js +4 -0
- package/esm/util/withLaunchInput.d.ts +174 -0
- package/esm/util/withLaunchInput.js +274 -0
- package/package.json +75 -24
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Position.d.ts +0 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Position.js +0 -8
- package/esm/BaseFeatureWidget/BaseFeatureDetail/types.d.ts +0 -8
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.d.ts +0 -80
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.js +0 -583
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +0 -141
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.js +0 -1116
- package/esm/ReExports/BaseFeatureDetails.d.ts +0 -1
- package/esm/ReExports/BaseFeatureDetails.js +0 -10
- package/esm/ReExports/index.d.ts +0 -1
- package/esm/ReExports/index.js +0 -1
- package/esm/ReExports/publicUtil.d.ts +0 -1
- package/esm/ReExports/publicUtil.js +0 -28
- package/esm/configuration/promotableDefaults.d.ts +0 -199
- package/esm/configuration/promotableDefaults.js +0 -326
- package/esm/configuration/promotablePin.d.ts +0 -55
- package/esm/configuration/promotablePin.js +0 -1
- package/esm/configuration/promotableResolve.d.ts +0 -108
- package/esm/configuration/promotableResolve.js +0 -117
- package/esm/configuration/promotableSlots.d.ts +0 -12
- package/esm/configuration/promotableSlots.js +0 -45
- package/esm/configuration/slotShape.d.ts +0 -12
- package/esm/configuration/slotShape.js +0 -84
- package/esm/pluggableElementTypes/models/HighlightsMixin.d.ts +0 -51
- package/esm/pluggableElementTypes/models/HighlightsMixin.js +0 -78
- package/esm/ui/PinAdornment.d.ts +0 -5
- package/esm/ui/PinAdornment.js +0 -79
- package/esm/ui/SvgGradientLegend.d.ts +0 -26
- package/esm/ui/SvgGradientLegend.js +0 -26
- package/esm/ui/highlightChipReveal.d.ts +0 -32
- package/esm/ui/highlightChipReveal.js +0 -39
- package/esm/ui/promotableMenuItems.d.ts +0 -19
- package/esm/ui/promotableMenuItems.js +0 -89
- package/esm/ui/promotablePinCoverage.d.ts +0 -44
- package/esm/ui/promotablePinCoverage.js +0 -87
- package/esm/util/applyInitSettings.d.ts +0 -79
- package/esm/util/applyInitSettings.js +0 -91
- package/esm/util/openDisplays.d.ts +0 -23
- package/esm/util/openDisplays.js +0 -79
- package/esm/util/stopToken.d.ts +0 -211
- package/esm/util/stopToken.js +0 -438
- /package/esm/{BaseFeatureWidget/BaseFeatureDetail/types.js → data_adapters/BaseAdapter/zoomRange.js} +0 -0
package/esm/util/tracks.js
CHANGED
|
@@ -8,13 +8,20 @@ export { getFileName } from './getFileName.js';
|
|
|
8
8
|
// it. `fetchContext.ts` takes it from mstUtils instead, which is what keeps the
|
|
9
9
|
// configuration schemas this file pulls in out of the fetch harness's graph.
|
|
10
10
|
export { getRpcSessionId } from './parentWalk.js';
|
|
11
|
-
|
|
11
|
+
export { makeIndex } from './formatGuessers.js';
|
|
12
|
+
export { isLooseTrackConfig, } from '@jbrowse/add-track-core';
|
|
13
|
+
import { isLooseTrackConfig, } from '@jbrowse/add-track-core';
|
|
14
|
+
import { asModelType, getParent, getSnapshot, getType, hasParent, isAlive, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
|
|
12
15
|
import { observable, runInAction, untracked } from 'mobx';
|
|
13
|
-
import {
|
|
16
|
+
import { readConfObject } from '../configuration/index.js';
|
|
17
|
+
import { adapterConfigCacheKey } from '../data_adapters/dataAdapterCache.js';
|
|
18
|
+
import { displayCandidates, displayTypesFedBy, } from '../pluggableElementTypes/models/baseTrackConfig.js';
|
|
14
19
|
import { getFileHandle, storeFileHandle, verifyPermission, } from './fileHandleStore.js';
|
|
20
|
+
import { makeIndex } from './formatGuessers.js';
|
|
15
21
|
import { getFileName } from './getFileName.js';
|
|
16
22
|
import { getContainingView, getEnv, getSession, objectHash, } from './mstUtils.js';
|
|
17
23
|
import { isViewModel } from './types/index.js';
|
|
24
|
+
import { setterOnlyMessage, unknownKeysMessage } from './unknownSnapshotKeys.js';
|
|
18
25
|
// Deliberately uncached. This used to memoize on a permanent WeakMap keyed by
|
|
19
26
|
// track, but every caller reads it from inside a reactive getter or autorun: the
|
|
20
27
|
// memo meant the reaction never subscribed to the config, so editing
|
|
@@ -76,12 +83,22 @@ export function isSameAssemblyName(a, b, assemblyManager) {
|
|
|
76
83
|
* `ReferenceSequenceTrack` does not — its schema omits the slot deliberately
|
|
77
84
|
* (see `createReferenceSeqTrackConfig`), because the assembly config holding it
|
|
78
85
|
* IS its assembly, so the name is read off the parent instead.
|
|
86
|
+
*
|
|
87
|
+
* That makes a sequence track's assembly **positional**, so a copy of one that
|
|
88
|
+
* is not inside its assembly cannot answer at all — and a detached config is
|
|
89
|
+
* what every hydration path produces (`hydrateTrackConfig`, and the working
|
|
90
|
+
* copy a non-admin's edits would go to, ADR-032). `hasParent` is the guard:
|
|
91
|
+
* without it the walk raises MST's "Failed to find the parent" from a helper
|
|
92
|
+
* whose other two failure modes are a plain `undefined`.
|
|
79
93
|
*/
|
|
80
94
|
function confAssemblyNames(conf) {
|
|
81
95
|
const trackAssemblyNames = readConfObject(conf, 'assemblyNames');
|
|
82
96
|
if (trackAssemblyNames) {
|
|
83
97
|
return trackAssemblyNames;
|
|
84
98
|
}
|
|
99
|
+
if (!hasParent(conf)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
85
102
|
const parent = getParent(conf);
|
|
86
103
|
return 'sequence' in parent
|
|
87
104
|
? [readConfObject(parent, 'name')]
|
|
@@ -108,6 +125,15 @@ export function getConfAssemblyNames(conf) {
|
|
|
108
125
|
export function getConfAssemblyNamesOrNone(conf) {
|
|
109
126
|
return confAssemblyNames(conf) ?? [];
|
|
110
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* The RPC session id a track's own requests go out under, from its config:
|
|
130
|
+
* what `BaseTrackModel.rpcSessionId` computes, for a caller holding no model.
|
|
131
|
+
* A call under any other id lands on another worker, which builds a second
|
|
132
|
+
* copy of the adapter that nothing frees.
|
|
133
|
+
*/
|
|
134
|
+
export function getConfRpcSessionId(conf) {
|
|
135
|
+
return adapterConfigCacheKey(readConfObject(conf, 'adapter'));
|
|
136
|
+
}
|
|
111
137
|
export const UNKNOWN = 'UNKNOWN';
|
|
112
138
|
export const UNSUPPORTED = 'UNSUPPORTED';
|
|
113
139
|
let blobMap = {};
|
|
@@ -257,34 +283,6 @@ export function findFileHandleIds(obj) {
|
|
|
257
283
|
export async function restoreFileHandlesFromSnapshot(sessionSnapshot, requestPermission = false) {
|
|
258
284
|
return restoreFileHandles([...findFileHandleIds(sessionSnapshot)], requestPermission);
|
|
259
285
|
}
|
|
260
|
-
/**
|
|
261
|
-
* creates a new location from the provided location including the appropriate
|
|
262
|
-
* suffix and location type
|
|
263
|
-
*
|
|
264
|
-
* @param location - the FileLocation
|
|
265
|
-
* @param suffix - the file suffix (e.g. .bam)
|
|
266
|
-
* @returns the constructed location object from the provided parameters
|
|
267
|
-
*/
|
|
268
|
-
export function makeIndex(location, suffix) {
|
|
269
|
-
if ('uri' in location) {
|
|
270
|
-
return {
|
|
271
|
-
uri: location.uri + suffix,
|
|
272
|
-
locationType: 'UriLocation',
|
|
273
|
-
// carry the parent's baseUri so a derived sibling index resolves against
|
|
274
|
-
// the same config location as the file it indexes
|
|
275
|
-
...(location.baseUri ? { baseUri: location.baseUri } : {}),
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
else if ('localPath' in location) {
|
|
279
|
-
return {
|
|
280
|
-
localPath: location.localPath + suffix,
|
|
281
|
-
locationType: 'LocalPathLocation',
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
return location;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
286
|
/**
|
|
289
287
|
* constructs a potential index file (with suffix) from the provided file name
|
|
290
288
|
*
|
|
@@ -368,8 +366,12 @@ export function guessAdapter(file, index, adapterHint, model) {
|
|
|
368
366
|
}
|
|
369
367
|
export function guessTrackType(adapterType, model, file) {
|
|
370
368
|
if (model) {
|
|
371
|
-
|
|
372
|
-
|
|
369
|
+
// getEnv(model), not getEnv(getSession(model)): the env is tree-wide, so
|
|
370
|
+
// the session hop only narrowed what may be passed here — a session itself
|
|
371
|
+
// has no session ancestor, so guessAdapter above accepted one and this
|
|
372
|
+
// threw on it
|
|
373
|
+
const { pluginManager } = getEnv(model);
|
|
374
|
+
const trackTypeGuesser = pluginManager.evaluateExtensionPoint(
|
|
373
375
|
/** #extensionPoint Core-guessTrackTypeForLocation | sync | Guess a track type from a file location */
|
|
374
376
|
'Core-guessTrackTypeForLocation', () => undefined);
|
|
375
377
|
const trackType = trackTypeGuesser(adapterType, file);
|
|
@@ -391,38 +393,39 @@ export function guessTrackType(adapterType, model, file) {
|
|
|
391
393
|
* the caller can ask for a full config instead.
|
|
392
394
|
*/
|
|
393
395
|
export function guessTrackConf(input, pluginManager, assemblyName) {
|
|
394
|
-
const { uri, index, ...extra } = typeof input === 'string' ? { uri: input } : input;
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
? { uri: index, locationType: 'UriLocation' }
|
|
398
|
-
|
|
396
|
+
const { uri, index, baseUri, ...extra } = typeof input === 'string' ? { uri: input } : input;
|
|
397
|
+
const base = baseUri ? { baseUri } : {};
|
|
398
|
+
return {
|
|
399
|
+
...guessTrackConfForLocation({ uri, locationType: 'UriLocation', ...base }, index ? { uri: index, locationType: 'UriLocation', ...base } : undefined, pluginManager, assemblyName),
|
|
400
|
+
...extra,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* {@link guessTrackConf} over an already-built {@link FileLocation}, for a
|
|
405
|
+
* caller holding a location the loose `{ uri }` vocabulary cannot spell — a
|
|
406
|
+
* desktop local path. Kept separate so `LooseTrackInput` stays URI-only: it
|
|
407
|
+
* sits on the track-config union and the root config's `tracks`, where a
|
|
408
|
+
* local path would be a config a web deployment could not open.
|
|
409
|
+
*
|
|
410
|
+
* The `trackId` is a content hash of the adapter, not a timestamp, so adding
|
|
411
|
+
* the same file twice is idempotent — `addToSession` dedupes on it.
|
|
412
|
+
*/
|
|
413
|
+
export function guessTrackConfForLocation(file, index, pluginManager, assemblyName) {
|
|
399
414
|
const adapterGuesser = pluginManager.evaluateExtensionPoint('Core-guessAdapterForLocation', () => undefined);
|
|
400
|
-
const adapter = adapterGuesser(file,
|
|
415
|
+
const adapter = adapterGuesser(file, index, undefined);
|
|
416
|
+
const name = getFileName(file);
|
|
401
417
|
if (!adapter || adapter.type === UNKNOWN) {
|
|
402
|
-
throw new Error(`could not infer a track type from "${
|
|
418
|
+
throw new Error(`could not infer a track type from "${name}"; pass a full track config instead`);
|
|
403
419
|
}
|
|
404
420
|
const trackTypeGuesser = pluginManager.evaluateExtensionPoint('Core-guessTrackTypeForLocation', () => undefined);
|
|
405
|
-
const name = getFileName(file);
|
|
406
421
|
return {
|
|
407
422
|
trackId: `${name}-${objectHash(adapter).slice(0, 8)}`,
|
|
408
423
|
type: trackTypeGuesser(adapter.type, file) ?? 'FeatureTrack',
|
|
409
424
|
name,
|
|
410
425
|
assemblyNames: assemblyName ? [assemblyName] : [],
|
|
411
426
|
adapter,
|
|
412
|
-
...extra,
|
|
413
427
|
};
|
|
414
428
|
}
|
|
415
|
-
/**
|
|
416
|
-
* Whether a track snapshot is the loose `{ uri, ... }` form — a data file with
|
|
417
|
-
* no `adapter` — that {@link expandLooseTrackConfig} expands.
|
|
418
|
-
*/
|
|
419
|
-
export function isLooseTrackConfig(snap) {
|
|
420
|
-
return (typeof snap === 'object' &&
|
|
421
|
-
snap !== null &&
|
|
422
|
-
!Array.isArray(snap) &&
|
|
423
|
-
typeof snap.uri === 'string' &&
|
|
424
|
-
!('adapter' in snap));
|
|
425
|
-
}
|
|
426
429
|
/**
|
|
427
430
|
* Expand a loose track config into a full one and leave any other snapshot
|
|
428
431
|
* untouched, so it can sit on every path a track snapshot enters the tree by:
|
|
@@ -476,27 +479,83 @@ export function getTrackName(conf, session) {
|
|
|
476
479
|
: (conf.trackId ?? '');
|
|
477
480
|
return trackName || trackId;
|
|
478
481
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
482
|
+
// The first-show path spreads the same settings into the display's `create()`
|
|
483
|
+
// snapshot, so a DECLARED PROP (`resolution` on the wiggle displays) has
|
|
484
|
+
// already landed by the time applyDisplaySettings reports it took no slot.
|
|
485
|
+
// Only a declared prop: MST restores nothing else from a snapshot, so a
|
|
486
|
+
// volatile or a getter of the same name (`scrollTop`) did not land and the
|
|
487
|
+
// caller has to hear about it.
|
|
488
|
+
function didNotLand(unapplied, display) {
|
|
489
|
+
const model = display ? asModelType(getType(display)) : undefined;
|
|
490
|
+
const props = model ? Object.keys(model.properties) : [];
|
|
491
|
+
return unapplied.filter(entry => !props.includes(entry.key));
|
|
492
|
+
}
|
|
493
|
+
function notifySettingsReport(session, trackId, displayType, unapplied, failed) {
|
|
494
|
+
const label = `${displayType} for track "${trackId}"`;
|
|
495
|
+
const keys = (of) => of.map(entry => entry.key);
|
|
496
|
+
const setterOnly = unapplied.filter(e => e.reason === 'setter-only');
|
|
497
|
+
const unknown = unapplied.filter(e => e.reason !== 'setter-only');
|
|
498
|
+
if (unknown.length) {
|
|
499
|
+
session.notifyError(unknownKeysMessage(label, keys(unknown)));
|
|
500
|
+
}
|
|
501
|
+
if (setterOnly.length) {
|
|
502
|
+
session.notifyError(setterOnlyMessage(label, keys(setterOnly)));
|
|
503
|
+
}
|
|
504
|
+
if (failed.length) {
|
|
505
|
+
session.notifyError(`Track "${trackId}" rejected ${failed.map(f => `${f.key}: ${f.error}`).join('; ')}`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
// The display a shown track switches to for a `type` it is not drawn as.
|
|
509
|
+
function displaySwitch(self, trackId, track, requested) {
|
|
510
|
+
if (requested === undefined) {
|
|
511
|
+
return undefined;
|
|
512
|
+
}
|
|
513
|
+
const { pluginManager } = getEnv(self);
|
|
514
|
+
const type = pluginManager.resolveDisplayTypeRecord(requested)?.name;
|
|
515
|
+
if (type === track.activeDisplay.type) {
|
|
516
|
+
return undefined;
|
|
517
|
+
}
|
|
518
|
+
const target = track.compatibleDisplays.find(d => d.type === type);
|
|
519
|
+
if (!target) {
|
|
520
|
+
const view = isViewModel(self) ? self : getContainingView(self);
|
|
521
|
+
throw new Error(`Track "${trackId}" cannot be shown as "${requested}" in a ${view.type}. It takes: ${track.compatibleDisplays.map(d => d.type).join(', ')}`);
|
|
522
|
+
}
|
|
523
|
+
return target;
|
|
524
|
+
}
|
|
525
|
+
// A switch carries the settings in the new display's snapshot, as a first show
|
|
526
|
+
// does, and hands off to the async launch while that display's state model is
|
|
527
|
+
// still a dynamic import.
|
|
528
|
+
function restyleShown(self, trackId, found, displayInitialSnapshot) {
|
|
529
|
+
const { pluginManager } = getEnv(self);
|
|
530
|
+
const session = getSession(self);
|
|
531
|
+
const track = found;
|
|
532
|
+
const { type, ...settings } = displayInitialSnapshot;
|
|
533
|
+
try {
|
|
534
|
+
const target = displaySwitch(self, trackId, track, type);
|
|
535
|
+
if (target) {
|
|
536
|
+
const record = pluginManager.resolveDisplayTypeRecord(target.type);
|
|
537
|
+
if (record && !record.isStateModelLoaded) {
|
|
538
|
+
void launchTrackGeneric(self, trackId, {}, displayInitialSnapshot);
|
|
539
|
+
return undefined;
|
|
540
|
+
}
|
|
541
|
+
track.replaceDisplay(track.activeDisplay.configuration.displayId, target.displayId, {
|
|
542
|
+
...track.activeDisplay.getPortableSettings?.(target.displayId),
|
|
543
|
+
...settings,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
if (Object.keys(settings).length && track.applyDisplaySettings) {
|
|
547
|
+
const report = track.applyDisplaySettings(settings);
|
|
548
|
+
notifySettingsReport(session, trackId, track.activeDisplay.type, target
|
|
549
|
+
? didNotLand(report.unapplied, track.displays[0])
|
|
550
|
+
: report.unapplied, report.failed);
|
|
551
|
+
}
|
|
552
|
+
return found;
|
|
553
|
+
}
|
|
554
|
+
catch (e) {
|
|
555
|
+
session.notifyError(`${e}`, e);
|
|
556
|
+
return undefined;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
500
559
|
/**
|
|
501
560
|
* The display type names a view can render, as a lookup set. Built once per
|
|
502
561
|
* view and handed to {@link viewCanDisplayTrack} for every track, rather than
|
|
@@ -506,17 +565,10 @@ export function viewDisplayNames(pluginManager, viewType) {
|
|
|
506
565
|
return new Set(pluginManager.getViewType(viewType).displayTypes.map(d => d.name));
|
|
507
566
|
}
|
|
508
567
|
/**
|
|
509
|
-
* Whether a view rendering `viewDisplays` can open a track
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
*
|
|
513
|
-
* refuse.
|
|
514
|
-
*
|
|
515
|
-
* Reads the *track type's* registered displays rather than a config's own
|
|
516
|
-
* `displays` array, which is both cheaper and the only form available on an
|
|
517
|
-
* un-hydrated frozen track config (ADR-032). The two agree, since
|
|
518
|
-
* `preprocessTrackConfigSnapshot` injects a stub display for every display the
|
|
519
|
-
* track type registers.
|
|
568
|
+
* Whether a view rendering `viewDisplays` can open a track at all: does the
|
|
569
|
+
* track's adapter feed a display the view draws. The coarse half of the
|
|
570
|
+
* question {@link pickDisplayForView} answers precisely, over the same
|
|
571
|
+
* candidates, so a picker never offers a track `showTrackGeneric` will refuse.
|
|
520
572
|
*
|
|
521
573
|
* Two answers that are easy to get wrong, and both have been:
|
|
522
574
|
*
|
|
@@ -530,20 +582,101 @@ export function viewDisplayNames(pluginManager, viewType) {
|
|
|
530
582
|
* every track passes. That is a policy rather than a fact, and it lives here
|
|
531
583
|
* so the pickers agree on it.
|
|
532
584
|
*/
|
|
533
|
-
export function viewCanDisplayTrack(pluginManager, viewDisplays,
|
|
534
|
-
if (!pluginManager.trackTypes.has(
|
|
585
|
+
export function viewCanDisplayTrack(pluginManager, viewDisplays, track) {
|
|
586
|
+
if (!pluginManager.trackTypes.has(track.type)) {
|
|
535
587
|
return false;
|
|
536
588
|
}
|
|
537
589
|
return (viewDisplays.size === 0 ||
|
|
538
|
-
pluginManager
|
|
539
|
-
|
|
540
|
-
|
|
590
|
+
displayTypesFedBy(pluginManager, track.type, track.adapter).some(name => viewDisplays.has(name)));
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Whether every name in `subset` appears in `superset`. An absent superset
|
|
594
|
+
* contains nothing; an absent subset is contained by anything.
|
|
595
|
+
*/
|
|
596
|
+
function containsAll(superset = [], subset = []) {
|
|
597
|
+
const s = new Set(superset);
|
|
598
|
+
return subset.every(x => s.has(x));
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* The tracks a view can be offered: those that support every assembly it
|
|
602
|
+
* displays, and that declare a display it can draw. The track selector's tree
|
|
603
|
+
* and every other picker that opens a track into a view read this one answer,
|
|
604
|
+
* or one of them offers a track the next hides.
|
|
605
|
+
*/
|
|
606
|
+
export function filterTracks(tracks, self) {
|
|
607
|
+
const { view } = self;
|
|
608
|
+
if (!view) {
|
|
609
|
+
return [];
|
|
610
|
+
}
|
|
611
|
+
const { assemblyManager } = getSession(view);
|
|
612
|
+
const { pluginManager } = getEnv(view);
|
|
613
|
+
const canonical = (names) => canonicalAssemblyNames(names, assemblyManager);
|
|
614
|
+
const viewAssemblyNames = canonical(self.assemblyNames);
|
|
615
|
+
const viewDisplays = viewDisplayNames(pluginManager, view.type);
|
|
616
|
+
return tracks.filter(c => {
|
|
617
|
+
const trackAssemblyNames = readConfObject(c, 'assemblyNames');
|
|
618
|
+
return (
|
|
619
|
+
// a view that declares no assemblies (one still initializing) constrains
|
|
620
|
+
// nothing; otherwise the track must cover every one of them
|
|
621
|
+
(viewAssemblyNames.length === 0 ||
|
|
622
|
+
containsAll(trackAssemblyNames && canonical(trackAssemblyNames), viewAssemblyNames)) &&
|
|
623
|
+
viewCanDisplayTrack(pluginManager, viewDisplays, {
|
|
624
|
+
type: c.type,
|
|
625
|
+
adapter: c.adapter,
|
|
626
|
+
}));
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* The assembly's own sequence track, when the view can draw one. It is in no
|
|
631
|
+
* track list — the config lives on the assembly (see {@link getConfAssemblyNames}
|
|
632
|
+
* on why a sequence track's assembly is positional) — so a picker that walks
|
|
633
|
+
* `session.tracks` alone cannot offer the track most views open first.
|
|
634
|
+
*/
|
|
635
|
+
function refSeqTrackConf(assemblyName, view) {
|
|
636
|
+
const { assemblyManager } = getSession(view);
|
|
637
|
+
const { pluginManager } = getEnv(view);
|
|
638
|
+
const conf = assemblyManager.get(assemblyName)?.configuration.sequence;
|
|
639
|
+
// the same display-compatibility question filterTracks asks of every other
|
|
640
|
+
// track, so a view that cannot draw a sequence is not offered one
|
|
641
|
+
return conf &&
|
|
642
|
+
viewCanDisplayTrack(pluginManager, viewDisplayNames(pluginManager, view.type), { type: conf.type, adapter: conf.adapter })
|
|
643
|
+
? conf
|
|
644
|
+
: undefined;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Every track config a view can be offered, each assembly's sequence track
|
|
648
|
+
* first and then {@link filterTracks} over the list handed in.
|
|
649
|
+
*/
|
|
650
|
+
export function offeredTracks(tracks, self) {
|
|
651
|
+
const { view, assemblyNames } = self;
|
|
652
|
+
if (!view) {
|
|
653
|
+
return [];
|
|
654
|
+
}
|
|
655
|
+
return [
|
|
656
|
+
...assemblyNames.map(name => refSeqTrackConf(name, view)),
|
|
657
|
+
...filterTracks(tracks, self),
|
|
658
|
+
].filter(conf => conf !== undefined);
|
|
541
659
|
}
|
|
542
|
-
|
|
660
|
+
/**
|
|
661
|
+
* Which display a track opens with in a given view, and the declared entry
|
|
662
|
+
* that configures it: `{ type, conf }`, or undefined when the view draws none
|
|
663
|
+
* of the candidates or the requested type is not among them.
|
|
664
|
+
*
|
|
665
|
+
* The **type** is the requested one, checked rather than taken on faith (an
|
|
666
|
+
* unchecked one resolved its dangling `<trackId>-<type>` id back to the
|
|
667
|
+
* track's default display, and the caller was told it got what it asked for),
|
|
668
|
+
* else the first candidate among the view's own display types, else the first
|
|
669
|
+
* it draws at all. The **config** is then the declared entry of that type,
|
|
670
|
+
* never another one the view supports: `display.type ===
|
|
671
|
+
* display.configuration.type` is the invariant `DisplayConfigurationReference`
|
|
672
|
+
* assumes when it falls back to resolving by type.
|
|
673
|
+
*/
|
|
674
|
+
export function pickDisplayForView({ candidates, declaredDisplays, requestedType, viewDisplayTypes, preferredDisplayTypes = new Set(), }) {
|
|
543
675
|
const supported = new Set(viewDisplayTypes);
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
676
|
+
const drawable = candidates.filter(name => supported.has(name));
|
|
677
|
+
const type = requestedType === undefined
|
|
678
|
+
? (drawable.find(name => preferredDisplayTypes.has(name)) ?? drawable[0])
|
|
679
|
+
: drawable.find(name => name === requestedType);
|
|
547
680
|
return type === undefined
|
|
548
681
|
? undefined
|
|
549
682
|
: { type, conf: declaredDisplays.find(d => d.type === type) };
|
|
@@ -572,6 +705,79 @@ export function normalizeTrackInit(t) {
|
|
|
572
705
|
};
|
|
573
706
|
}
|
|
574
707
|
}
|
|
708
|
+
function resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot, inlineConf) {
|
|
709
|
+
const { pluginManager } = getEnv(self);
|
|
710
|
+
const session = getSession(self);
|
|
711
|
+
// `trackId` seeds the expansion because `guessTrackConf` otherwise
|
|
712
|
+
// synthesizes one from the filename, and the dedupe in the callers and
|
|
713
|
+
// `hideTrackGeneric` both look the track up by the id the caller passed.
|
|
714
|
+
// Only for the loose form: spreading a live MST node (SvInspector's
|
|
715
|
+
// circular track) would flatten it out of the `isStateTreeNode` branch.
|
|
716
|
+
const inlineRawConf = isLooseTrackConfig(inlineConf)
|
|
717
|
+
? expandLooseTrackConfig({ trackId, ...inlineConf }, pluginManager)
|
|
718
|
+
: inlineConf;
|
|
719
|
+
const rawConf = inlineRawConf ?? session.getTrackById(trackId);
|
|
720
|
+
if (!rawConf) {
|
|
721
|
+
throw new Error(`Could not resolve identifier "${trackId}"`);
|
|
722
|
+
}
|
|
723
|
+
const confSnapshot = structuredClone(isStateTreeNode(rawConf) ? getSnapshot(rawConf) : rawConf);
|
|
724
|
+
// `& { type: string }` because `rawConf` unions a live node with a loose
|
|
725
|
+
// `Record<string, unknown>`, and the node's `type: string` widens back to
|
|
726
|
+
// `unknown` across that union
|
|
727
|
+
const conf = pluginManager.evaluateExtensionPoint('Core-preProcessTrackConfig', confSnapshot);
|
|
728
|
+
const trackType = pluginManager.getTrackType(conf.type);
|
|
729
|
+
// Validate only a conf that is not already in the tree. `configSchema.create`
|
|
730
|
+
// here builds an entire config node and throws it away purely to surface a
|
|
731
|
+
// nice error; its preProcessSnapshot also re-runs Core-preProcessTrackConfig
|
|
732
|
+
// on a snapshot this function just preprocessed. A conf that is a state tree
|
|
733
|
+
// node was validated when MST created it, so all of that is pure waste on
|
|
734
|
+
// the common showTrack path.
|
|
735
|
+
if (!isStateTreeNode(rawConf)) {
|
|
736
|
+
try {
|
|
737
|
+
trackType.configSchema.create(conf, getEnv(self));
|
|
738
|
+
}
|
|
739
|
+
catch (e) {
|
|
740
|
+
throw new Error(`Track "${trackId}" has an invalid configuration: ${e}`, {
|
|
741
|
+
cause: e,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
// A track container that isn't itself a view — a synteny level, which owns
|
|
746
|
+
// a track list but has no width and no registered view type — takes the
|
|
747
|
+
// display choice from the view it sits in, which is the same node
|
|
748
|
+
// getContainingView already resolves to for everything else beneath it.
|
|
749
|
+
const view = isViewModel(self) ? self : getContainingView(self);
|
|
750
|
+
const viewType = pluginManager.getViewType(view.type);
|
|
751
|
+
const candidates = displayCandidates(pluginManager, conf);
|
|
752
|
+
const viewDisplayTypes = viewType.displayTypes.map(d => d.name);
|
|
753
|
+
// Aliases resolve first, so a caller or a config naming a pre-consolidation
|
|
754
|
+
// display type (`LinearPileupDisplay`) reaches the type that replaced it; a
|
|
755
|
+
// name no display answers to stays as written, for the refusal to quote.
|
|
756
|
+
const canonical = (name) => pluginManager.resolveDisplayTypeRecord(name)?.name ?? name;
|
|
757
|
+
const requested = displayInitialSnapshot.type;
|
|
758
|
+
const declaredDisplays = conf.displays ?? [];
|
|
759
|
+
const picked = pickDisplayForView({
|
|
760
|
+
candidates,
|
|
761
|
+
declaredDisplays: declaredDisplays.map(d => ({
|
|
762
|
+
...d,
|
|
763
|
+
type: canonical(d.type),
|
|
764
|
+
})),
|
|
765
|
+
requestedType: requested === undefined ? undefined : canonical(requested),
|
|
766
|
+
viewDisplayTypes,
|
|
767
|
+
preferredDisplayTypes: new Set(viewType.displayTypes
|
|
768
|
+
.filter(d => d.viewType === view.type)
|
|
769
|
+
.map(d => d.name)),
|
|
770
|
+
});
|
|
771
|
+
if (!picked) {
|
|
772
|
+
const drawable = candidates.filter(name => viewDisplayTypes.includes(name));
|
|
773
|
+
throw new Error(requested === undefined
|
|
774
|
+
? `Could not find a compatible display for view type ${view.type}`
|
|
775
|
+
: `Track "${trackId}" cannot be shown as "${requested}" in a ${view.type}. ${drawable.length > 0
|
|
776
|
+
? `It takes: ${drawable.join(', ')}`
|
|
777
|
+
: 'This view draws none of its display types'}`);
|
|
778
|
+
}
|
|
779
|
+
return { rawConf, conf, trackType, picked };
|
|
780
|
+
}
|
|
575
781
|
export function showTrackGeneric(self, trackId,
|
|
576
782
|
// `object`, annotated, rather than inferred from the default. A bare `{}`
|
|
577
783
|
// accepts every non-nullish value, numbers included, which is how a synteny
|
|
@@ -591,85 +797,60 @@ inlineConf) {
|
|
|
591
797
|
const session = getSession(self);
|
|
592
798
|
const found = self.tracks.find(t => t.configuration.trackId === trackId);
|
|
593
799
|
if (found) {
|
|
594
|
-
return found;
|
|
800
|
+
return restyleShown(self, trackId, found, displayInitialSnapshot);
|
|
595
801
|
}
|
|
596
802
|
// Single choke point for all "open a track" paths — errors surface as
|
|
597
803
|
// snackbars. Config is validated before the push so the open set never holds
|
|
598
804
|
// a broken track.
|
|
599
805
|
try {
|
|
600
|
-
const rawConf = (
|
|
601
|
-
session.getTrackById(trackId);
|
|
602
|
-
if (!rawConf) {
|
|
603
|
-
throw new Error(`Could not resolve identifier "${trackId}"`);
|
|
604
|
-
}
|
|
605
|
-
const confSnapshot = structuredClone(isStateTreeNode(rawConf) ? getSnapshot(rawConf) : rawConf);
|
|
606
|
-
const conf = pluginManager.evaluateExtensionPoint('Core-preProcessTrackConfig', confSnapshot);
|
|
607
|
-
const trackType = pluginManager.getTrackType(conf.type);
|
|
608
|
-
// Validate only a conf that is not already in the tree. `configSchema.create`
|
|
609
|
-
// here builds an entire config node and throws it away purely to surface a
|
|
610
|
-
// nice error; its preProcessSnapshot also re-runs Core-preProcessTrackConfig
|
|
611
|
-
// on a snapshot this function just preprocessed. A conf that is a state tree
|
|
612
|
-
// node was validated when MST created it, so all of that is pure waste on
|
|
613
|
-
// the common showTrack path.
|
|
614
|
-
if (!isStateTreeNode(rawConf)) {
|
|
615
|
-
try {
|
|
616
|
-
trackType.configSchema.create(conf, getEnv(self));
|
|
617
|
-
}
|
|
618
|
-
catch (e) {
|
|
619
|
-
throw new Error(`Track "${trackId}" has an invalid configuration: ${e}`, { cause: e });
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
// A track container that isn't itself a view — a synteny level, which owns
|
|
623
|
-
// a track list but has no width and no registered view type — takes the
|
|
624
|
-
// display choice from the view it sits in, which is the same node
|
|
625
|
-
// getContainingView already resolves to for everything else beneath it.
|
|
626
|
-
const view = isViewModel(self) ? self : getContainingView(self);
|
|
627
|
-
const viewType = pluginManager.getViewType(view.type);
|
|
628
|
-
const picked = pickDisplayForView({
|
|
629
|
-
declaredDisplays: conf.displays ?? [],
|
|
630
|
-
requestedType: displayInitialSnapshot.type,
|
|
631
|
-
trackDisplayTypes: trackType.displayTypes.map(d => d.name),
|
|
632
|
-
viewDisplayTypes: viewType.displayTypes.map(d => d.name),
|
|
633
|
-
});
|
|
634
|
-
if (!picked) {
|
|
635
|
-
throw new Error(`Could not find a compatible display for view type ${view.type}`);
|
|
636
|
-
}
|
|
806
|
+
const { rawConf, conf, trackType, picked } = resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot, inlineConf);
|
|
637
807
|
const { type: displayType, conf: displayConf } = picked;
|
|
638
808
|
const displayId = displayConf?.displayId ?? `${trackId}-${displayType}`;
|
|
809
|
+
// a registered display whose model is not loaded yet: the load re-enters
|
|
810
|
+
// through the view's own showTrack action, so a synchronous caller gets the
|
|
811
|
+
// track a tick late; a caller that needs it back awaits launchTrack
|
|
812
|
+
const displayRecord = pluginManager.resolveDisplayTypeRecord(displayType);
|
|
813
|
+
if (displayRecord && !displayRecord.isStateModelLoaded) {
|
|
814
|
+
void launchTrackGeneric(self, trackId, initialSnapshot, displayInitialSnapshot, inlineConf);
|
|
815
|
+
return undefined;
|
|
816
|
+
}
|
|
639
817
|
const track = trackType.stateModel.create({
|
|
640
818
|
...initialSnapshot,
|
|
641
819
|
type: conf.type,
|
|
642
|
-
|
|
820
|
+
// `rawConf`, not the caller's `inlineConf`: the loose `{ trackId, uri }`
|
|
821
|
+
// form has no `type` for the config schema to dispatch on, and the
|
|
822
|
+
// concrete schema this lands on carries no loose preprocessor — that one
|
|
823
|
+
// is on `pluggableConfigSchemaType('track')`, which a track model's
|
|
824
|
+
// `ConfigurationReference` is not. Not `conf` either: that has already
|
|
825
|
+
// run Core-preProcessTrackConfig, which the schema's own
|
|
826
|
+
// preProcessSnapshot runs again.
|
|
827
|
+
configuration: inlineConf ? rawConf : trackId,
|
|
643
828
|
displays: [
|
|
644
829
|
{
|
|
645
830
|
...displayConf,
|
|
646
|
-
type: displayType,
|
|
647
831
|
configuration: displayId,
|
|
648
832
|
...displayInitialSnapshot,
|
|
833
|
+
type: displayType,
|
|
649
834
|
},
|
|
650
835
|
],
|
|
651
836
|
});
|
|
652
837
|
self.tracks.push(track);
|
|
653
838
|
// Display settings (height, color, …) are config slots now, not display
|
|
654
839
|
// instance props — passed in the display snapshot they'd be dropped as
|
|
655
|
-
// unknown MST keys.
|
|
656
|
-
// display config so they take effect and
|
|
657
|
-
//
|
|
658
|
-
//
|
|
659
|
-
//
|
|
660
|
-
//
|
|
661
|
-
//
|
|
662
|
-
//
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
670
|
-
display.configuration.setSlot(key, value);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
840
|
+
// unknown MST keys. applyDisplaySettings routes the ones that are real
|
|
841
|
+
// slots onto the persistent display config so they take effect and
|
|
842
|
+
// survive hide/retick (#5591), running the schema's preProcessSnapshot
|
|
843
|
+
// first so shorthand expansions and legacy-key migrations reach this path
|
|
844
|
+
// too — a session spec, share link, or embed writes slots here rather
|
|
845
|
+
// than creating a config from a snapshot, and those surfaces are meant to
|
|
846
|
+
// speak the same vocabulary. Runs after the push so the display's config
|
|
847
|
+
// reference can resolve. Slots only, deliberately: this is the
|
|
848
|
+
// declarative surface, and `allowSetters` stays off so a spec key cannot
|
|
849
|
+
// reach internal display actions.
|
|
850
|
+
const displaySettings = Object.fromEntries(Object.entries(displayInitialSnapshot).filter(([key]) => key !== 'type'));
|
|
851
|
+
const report = track.applyDisplaySettings(displaySettings);
|
|
852
|
+
const drawn = track.displays[0];
|
|
853
|
+
notifySettingsReport(session, trackId, displayType, didNotLand(report.unapplied, drawn), report.failed);
|
|
673
854
|
// if this track came from a connection, persist its config so it survives
|
|
674
855
|
// reload without re-establishing the connection (no-op otherwise)
|
|
675
856
|
session.captureConnectionTrack?.(trackId);
|
|
@@ -708,6 +889,137 @@ export function toggleTrackGeneric(self, trackId) {
|
|
|
708
889
|
? false
|
|
709
890
|
: !!showTrackGeneric(self, trackId);
|
|
710
891
|
}
|
|
892
|
+
/**
|
|
893
|
+
* Start loading the state model and component of the display a track would
|
|
894
|
+
* open with, without opening it, for a caller that knows the track is coming.
|
|
895
|
+
* Anything that fails here is the launch's to report.
|
|
896
|
+
*/
|
|
897
|
+
export function warmTrackDisplayGeneric(self, trackId, displayInitialSnapshot = {}, assemblyName) {
|
|
898
|
+
const { pluginManager } = getEnv(self);
|
|
899
|
+
try {
|
|
900
|
+
const { picked } = resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot);
|
|
901
|
+
pluginManager
|
|
902
|
+
.resolveDisplayTypeRecord(picked.type)
|
|
903
|
+
?.loadStateModel()
|
|
904
|
+
.catch(() => { });
|
|
905
|
+
warmTrackAdapter(self, trackId, assemblyName);
|
|
906
|
+
}
|
|
907
|
+
catch {
|
|
908
|
+
// the launch reports an unresolvable track
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
function adapterTypesIn(value, pluginManager, found = new Set()) {
|
|
912
|
+
if (typeof value === 'object' && value !== null) {
|
|
913
|
+
const { type } = value;
|
|
914
|
+
if (typeof type === 'string' && pluginManager.hasAdapterType(type)) {
|
|
915
|
+
found.add(type);
|
|
916
|
+
}
|
|
917
|
+
for (const child of Object.values(value)) {
|
|
918
|
+
adapterTypesIn(child, pluginManager, found);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return found;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Load the track's adapter code and read its index in the worker, beside the
|
|
925
|
+
* assembly load the track's first request waits for.
|
|
926
|
+
*
|
|
927
|
+
* Sent under the id the track's own requests will use, so it reaches, and
|
|
928
|
+
* boots, the worker that serves them. That id hashes the adapter config as the
|
|
929
|
+
* track's config node reads it, so a frozen config.json entry is read through a
|
|
930
|
+
* node of its type: its raw adapter snapshot hashes to another worker.
|
|
931
|
+
*
|
|
932
|
+
* `assemblyName` is the one the view is launching on. The track's own
|
|
933
|
+
* `assemblyNames[0]` is not that: a reference-reading adapter is built for the
|
|
934
|
+
* genome its request names, and warming it for the config's first assembly
|
|
935
|
+
* would build an instance the view never reads.
|
|
936
|
+
*/
|
|
937
|
+
function declaresLanes(adapterConfig, pluginManager) {
|
|
938
|
+
const { type } = adapterConfig;
|
|
939
|
+
return (typeof type === 'string' &&
|
|
940
|
+
pluginManager.hasAdapterType(type) &&
|
|
941
|
+
pluginManager
|
|
942
|
+
.getAdapterType(type)
|
|
943
|
+
.adapterCapabilities.includes('headerLanes'));
|
|
944
|
+
}
|
|
945
|
+
function warmTrackAdapter(self, trackId, assemblyName) {
|
|
946
|
+
const { pluginManager } = getEnv(self);
|
|
947
|
+
const session = getSession(self);
|
|
948
|
+
const raw = session.getTrackById(trackId);
|
|
949
|
+
const conf = isStateTreeNode(raw)
|
|
950
|
+
? raw
|
|
951
|
+
: typeof raw?.type === 'string'
|
|
952
|
+
? pluginManager
|
|
953
|
+
.getTrackType(raw.type)
|
|
954
|
+
.configSchema.create(raw, { pluginManager })
|
|
955
|
+
: undefined;
|
|
956
|
+
if (conf) {
|
|
957
|
+
const adapterConfig = readConfObject(conf, 'adapter');
|
|
958
|
+
const sessionId = getConfRpcSessionId(conf);
|
|
959
|
+
session.rpcManager
|
|
960
|
+
// eslint-disable-next-line no-restricted-syntax -- a code download the track's first request would make anyway: nothing to show, and nothing a user can move on from
|
|
961
|
+
.call(sessionId, 'CoreLoadAdapterCode', {
|
|
962
|
+
adapterTypes: [...adapterTypesIn(adapterConfig, pluginManager)],
|
|
963
|
+
})
|
|
964
|
+
.catch(() => { });
|
|
965
|
+
// a source that declares its lanes reads an index per lane asked about,
|
|
966
|
+
// and only its display knows which; asked about none it would read all
|
|
967
|
+
if (assemblyName && !declaresLanes(adapterConfig, pluginManager)) {
|
|
968
|
+
session.rpcManager
|
|
969
|
+
// eslint-disable-next-line no-restricted-syntax -- an index read the track's first request would make anyway: nothing to show, and nothing a user can move on from
|
|
970
|
+
.call(sessionId, 'CoreGetRefNames', {
|
|
971
|
+
adapterConfig,
|
|
972
|
+
assemblyName,
|
|
973
|
+
signal: undefined,
|
|
974
|
+
})
|
|
975
|
+
.catch(() => { });
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
export async function launchTrackGeneric(self, trackId, initialSnapshot = {}, displayInitialSnapshot = {}, inlineConf) {
|
|
980
|
+
const { pluginManager } = getEnv(self);
|
|
981
|
+
const session = getSession(self);
|
|
982
|
+
const found = self.tracks.find(t => t.configuration.trackId === trackId);
|
|
983
|
+
if (found) {
|
|
984
|
+
let target;
|
|
985
|
+
try {
|
|
986
|
+
target = displaySwitch(self, trackId, found, displayInitialSnapshot.type);
|
|
987
|
+
if (target) {
|
|
988
|
+
await pluginManager
|
|
989
|
+
.resolveDisplayTypeRecord(target.type)
|
|
990
|
+
?.loadStateModel();
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
catch (e) {
|
|
994
|
+
session.notifyError(`${e}`, e);
|
|
995
|
+
return undefined;
|
|
996
|
+
}
|
|
997
|
+
if (!target) {
|
|
998
|
+
return restyleShown(self, trackId, found, displayInitialSnapshot);
|
|
999
|
+
}
|
|
1000
|
+
return isAlive(self) && isAlive(found)
|
|
1001
|
+
? self.showTrack?.(trackId, initialSnapshot, displayInitialSnapshot, inlineConf)
|
|
1002
|
+
: undefined;
|
|
1003
|
+
}
|
|
1004
|
+
try {
|
|
1005
|
+
const { picked } = resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot, inlineConf);
|
|
1006
|
+
await pluginManager.resolveDisplayTypeRecord(picked.type)?.loadStateModel();
|
|
1007
|
+
}
|
|
1008
|
+
catch (e) {
|
|
1009
|
+
session.notifyError(`${e}`, e);
|
|
1010
|
+
return undefined;
|
|
1011
|
+
}
|
|
1012
|
+
if (!isAlive(self)) {
|
|
1013
|
+
return undefined;
|
|
1014
|
+
}
|
|
1015
|
+
return self.showTrack?.(trackId, initialSnapshot, displayInitialSnapshot, inlineConf);
|
|
1016
|
+
}
|
|
1017
|
+
// the hide runs in the synchronous prologue, so it keeps action context
|
|
1018
|
+
export async function launchToggleTrackGeneric(self, trackId) {
|
|
1019
|
+
return hideTrackGeneric(self, trackId)
|
|
1020
|
+
? false
|
|
1021
|
+
: !!(await launchTrackGeneric(self, trackId));
|
|
1022
|
+
}
|
|
711
1023
|
/**
|
|
712
1024
|
* Every track config the session can show, connection-supplied ones included.
|
|
713
1025
|
*
|
|
@@ -726,3 +1038,41 @@ export function allSessionTracks(session) {
|
|
|
726
1038
|
? [...session.tracks, ...connectionTracks]
|
|
727
1039
|
: session.tracks;
|
|
728
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* The session's annotation for `assemblyName`, as trackIds: what a view opened
|
|
1043
|
+
* on another genome starts with. Only FeatureTracks, not everything configured
|
|
1044
|
+
* for the assembly — an alignments track turned on behind the user's back
|
|
1045
|
+
* fetches data nobody asked for, and a FeatureTrack over a few kb is one tabix
|
|
1046
|
+
* range query.
|
|
1047
|
+
*/
|
|
1048
|
+
export function annotationTrackIds(session, assemblyName) {
|
|
1049
|
+
return allSessionTracks(session).flatMap(track => readConfObject(track, 'type') === 'FeatureTrack' &&
|
|
1050
|
+
readConfObject(track, 'assemblyNames').some(name => isSameAssemblyName(name, assemblyName, session.assemblyManager))
|
|
1051
|
+
? [readConfObject(track, 'trackId')]
|
|
1052
|
+
: []);
|
|
1053
|
+
}
|
|
1054
|
+
function isNavigableView(view) {
|
|
1055
|
+
return 'navToLocString' in view;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* One assembly on its own in a linear genome view, at `loc`. Keyed on `id`:
|
|
1059
|
+
* following several alignments to one genome re-navigates the view rather than
|
|
1060
|
+
* stacking a new one each time.
|
|
1061
|
+
*/
|
|
1062
|
+
export async function openAssemblyInLinearView({ session, id, assemblyName, loc, tracks, }) {
|
|
1063
|
+
const view = session.views.find(v => v.id === id);
|
|
1064
|
+
if (view && isNavigableView(view)) {
|
|
1065
|
+
await view.navToLocString(loc, assemblyName);
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
session.addView('LinearGenomeView', {
|
|
1069
|
+
id,
|
|
1070
|
+
assembly: assemblyName,
|
|
1071
|
+
loc,
|
|
1072
|
+
tracks,
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
export function openMateLabel(assemblyName) {
|
|
1077
|
+
return `Open ${assemblyName} at the matching region`;
|
|
1078
|
+
}
|