@jbrowse/core 5.0.0-beta.8 → 5.0.0-beta.9
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 +427 -130
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +5 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -5
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +8 -9
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +8 -13
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +3 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +8 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +24 -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 +1 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +1 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.d.ts +16 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +53 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.d.ts +0 -8
- package/esm/BaseFeatureWidget/BaseFeatureDetail/util.js +0 -16
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceContents.js +7 -34
- package/esm/BaseFeatureWidget/configSchema.d.ts +1 -1
- package/esm/BaseFeatureWidget/formatDetails.d.ts +13 -29
- package/esm/BaseFeatureWidget/formatDetails.js +46 -79
- package/esm/BaseFeatureWidget/index.d.ts +1 -0
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +35 -28
- package/esm/BaseFeatureWidget/stateModelFactory.js +94 -102
- package/esm/BaseFeatureWidget/types.d.ts +3 -0
- package/esm/BaseFeatureWidget/util.d.ts +0 -3
- package/esm/BaseFeatureWidget/util.js +0 -17
- package/esm/PluginLoader.d.ts +14 -9
- package/esm/PluginLoader.js +34 -26
- package/esm/PluginManager.d.ts +4 -4
- package/esm/PluginManager.js +1 -1
- package/esm/ReExports/coreModules.generated.d.ts +2 -0
- package/esm/ReExports/coreModules.generated.js +492 -0
- package/esm/ReExports/coreWorkerModules.generated.d.ts +2 -0
- package/esm/ReExports/coreWorkerModules.generated.js +453 -0
- package/esm/ReExports/frameworkModules.d.ts +2 -0
- package/esm/ReExports/frameworkModules.js +67 -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 +493 -79
- package/esm/ReExports/modules.d.ts +1 -1
- package/esm/ReExports/modules.js +10 -87
- package/esm/ReExports/registry.d.ts +1 -0
- package/esm/ReExports/registry.js +23 -5
- package/esm/ReExports/uiStub.d.ts +2 -1
- package/esm/ReExports/uiStub.js +24 -2
- package/esm/ReExports/workerModules.js +8 -12
- package/esm/TextSearch/TextSearchManager.d.ts +3 -12
- package/esm/TextSearch/TextSearchManager.js +22 -10
- package/esm/assemblyManager/assembly.d.ts +10 -14
- package/esm/assemblyManager/assembly.js +10 -14
- package/esm/assemblyManager/assemblyConfigSchema.d.ts +23 -81
- package/esm/assemblyManager/assemblyManager.d.ts +10 -16
- package/esm/assemblyManager/assemblyManager.js +7 -10
- package/esm/assemblyManager/loadRefNameMap.js +3 -3
- package/esm/configuration/configurationSchema.d.ts +75 -31
- package/esm/configuration/configurationSchema.js +74 -40
- package/esm/configuration/configurationSchemaUnion.d.ts +39 -0
- package/esm/configuration/configurationSchemaUnion.js +59 -0
- package/esm/configuration/configurationSlot.d.ts +37 -12
- package/esm/configuration/configurationSlot.js +83 -22
- 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/getConf.d.ts +17 -9
- package/esm/configuration/getConf.js +52 -7
- package/esm/configuration/index.d.ts +11 -4
- package/esm/configuration/index.js +7 -4
- package/esm/configuration/mergeFormatCallbacks.d.ts +6 -7
- package/esm/configuration/mergeFormatCallbacks.js +13 -10
- package/esm/configuration/readConfObject.d.ts +2 -22
- package/esm/configuration/readConfObject.js +15 -49
- package/esm/configuration/requirements.d.ts +37 -0
- package/esm/configuration/requirements.js +88 -0
- package/esm/configuration/schemaRegistry.d.ts +21 -1
- package/esm/configuration/schemaRegistry.js +11 -0
- package/esm/configuration/schemaTypes.d.ts +3 -0
- package/esm/configuration/schemaTypes.js +10 -0
- package/esm/configuration/slotFacade.d.ts +35 -4
- package/esm/configuration/slotFacade.js +96 -9
- package/esm/configuration/snapshotPreprocess.d.ts +27 -0
- package/esm/configuration/snapshotPreprocess.js +102 -0
- package/esm/configuration/types.d.ts +161 -22
- package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +11 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +12 -1
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +2 -3
- package/esm/data_adapters/BaseAdapter/featureDensity.js +2 -3
- package/esm/data_adapters/BaseAdapter/index.d.ts +22 -3
- package/esm/data_adapters/BaseAdapter/types.d.ts +3 -4
- package/esm/data_adapters/BaseAdapter/zoomRange.d.ts +10 -0
- package/esm/data_adapters/BaseAdapter/zoomRange.js +1 -0
- package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +9 -11
- package/esm/data_adapters/getSequenceSubAdapter.d.ts +1 -3
- package/esm/data_adapters/getSequenceSubAdapter.js +1 -3
- package/esm/pluggableElementTypes/AdapterType.d.ts +7 -7
- package/esm/pluggableElementTypes/RpcMethodType.d.ts +1 -1
- package/esm/pluggableElementTypes/RpcMethodType.js +3 -8
- package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.d.ts +1 -2
- package/esm/pluggableElementTypes/TextSearchAdapterType.d.ts +7 -7
- package/esm/pluggableElementTypes/index.d.ts +1 -1
- package/esm/pluggableElementTypes/index.js +1 -1
- package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +17 -7
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +45 -48
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +40 -36
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +10 -13
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +6 -6
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +37 -17
- package/esm/pluggableElementTypes/models/BaseViewModel.js +25 -10
- package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +26 -16
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +1 -1
- 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 +57 -141
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +22 -26
- package/esm/pluggableElementTypes/models/components/SaveTrackData.js +2 -2
- 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 +15 -7
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +38 -29
- package/esm/pluggableElementTypes/models/index.d.ts +1 -2
- package/esm/pluggableElementTypes/models/index.js +1 -2
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.d.ts +3 -3
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +4 -4
- package/esm/pluggableElementTypes/models/saveTrackFileTypes/types.d.ts +3 -3
- package/esm/rpc/BaseRpcDriver.d.ts +1 -2
- package/esm/rpc/BaseRpcDriver.js +23 -30
- package/esm/rpc/MainThreadRpcDriver.d.ts +2 -2
- package/esm/rpc/MainThreadRpcDriver.js +13 -8
- package/esm/rpc/RpcClient.d.ts +17 -6
- package/esm/rpc/RpcClient.js +42 -12
- package/esm/rpc/RpcManager.d.ts +8 -10
- package/esm/rpc/RpcManager.js +1 -1
- package/esm/rpc/RpcRegistry.d.ts +8 -2
- package/esm/rpc/RpcServer.d.ts +3 -1
- package/esm/rpc/RpcServer.js +19 -12
- package/esm/rpc/WebWorkerRpcDriver.d.ts +3 -3
- package/esm/rpc/WebWorkerRpcDriver.js +9 -47
- package/esm/rpc/byteBudget.d.ts +3 -5
- package/esm/rpc/byteBudget.js +4 -4
- package/esm/rpc/configSchema.d.ts +7 -21
- package/esm/rpc/coreRpcMethods.d.ts +1 -0
- package/esm/rpc/coreRpcMethods.js +1 -0
- package/esm/rpc/methods/CoreEncodeFeatures.d.ts +6 -5
- package/esm/rpc/methods/CoreEncodeFeatures.js +26 -31
- package/esm/rpc/methods/CoreGetEncodedFeature.d.ts +13 -0
- package/esm/rpc/methods/CoreGetEncodedFeature.js +31 -0
- package/esm/rpc/methods/CoreGetExportData.js +2 -2
- package/esm/rpc/methods/CoreGetFeatureDensity.js +2 -2
- package/esm/rpc/methods/CoreGetFeatures.js +2 -2
- package/esm/rpc/methods/CoreGetSequence.js +2 -2
- package/esm/rpc/methods/layerFeatures.d.ts +26 -0
- package/esm/rpc/methods/layerFeatures.js +40 -0
- package/esm/svg/SvgExport.js +3 -4
- package/esm/svg/SvgThemeProviders.d.ts +12 -0
- package/esm/svg/SvgThemeProviders.js +15 -0
- package/esm/svg/exportViewSvg.d.ts +32 -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/svgReady.d.ts +8 -7
- package/esm/svg/svgReady.js +8 -7
- package/esm/svg/trackNames.d.ts +5 -5
- package/esm/svg/trackNames.js +6 -6
- package/esm/svg/wrapSvgExport.js +6 -74
- package/esm/ui/CascadingMenu.js +83 -86
- package/esm/ui/ErrorMessageStackTraceDialog.js +0 -5
- 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 -49
- 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/LoadingOverlay.js +3 -1
- package/esm/ui/MonospaceTextField.d.ts +2 -1
- package/esm/ui/MonospaceTextField.js +21 -19
- package/esm/ui/PaletteContext.d.ts +7 -9
- package/esm/ui/PaletteContext.js +24 -10
- package/esm/ui/RefNameAutocomplete/index.d.ts +1 -2
- package/esm/ui/RefNameAutocomplete/index.js +1 -1
- package/esm/ui/ScrollChrome.d.ts +6 -9
- package/esm/ui/ScrollChrome.js +5 -6
- package/esm/ui/ScrollEdgeShadow.d.ts +6 -9
- package/esm/ui/ScrollEdgeShadow.js +9 -24
- package/esm/ui/SettingsChangesTable.js +3 -3
- package/esm/ui/VerticalScrollbar.d.ts +13 -34
- package/esm/ui/VerticalScrollbar.js +29 -83
- package/esm/ui/ViewLoadingScreen.d.ts +2 -2
- package/esm/ui/ViewLoadingScreen.js +3 -3
- package/esm/ui/colorScale.d.ts +26 -1
- package/esm/ui/colorScale.js +28 -5
- package/esm/ui/colors.d.ts +49 -1
- package/esm/ui/colors.js +139 -4
- package/esm/ui/hoverBoxStyle.d.ts +14 -2
- package/esm/ui/hoverBoxStyle.js +17 -2
- package/esm/ui/index.d.ts +5 -3
- package/esm/ui/index.js +9 -7
- package/esm/ui/launchViewMenu.js +3 -3
- package/esm/ui/legendSpec.d.ts +2 -0
- package/esm/ui/legendSpec.js +3 -0
- package/esm/ui/palette.d.ts +0 -1
- package/esm/ui/palette.js +3 -27
- package/esm/ui/replaceViewAction.d.ts +1 -1
- package/esm/ui/replaceViewAction.js +1 -1
- package/esm/ui/theme.d.ts +1 -1
- package/esm/ui/theme.js +6 -40
- package/esm/ui/viewHeaderHeight.d.ts +1 -0
- package/esm/ui/viewHeaderHeight.js +1 -0
- package/esm/util/Base1DUtils.d.ts +1 -1
- package/esm/util/Base1DUtils.js +2 -2
- package/esm/util/SvgCanvas.d.ts +15 -13
- package/esm/util/SvgCanvas.js +72 -53
- package/esm/util/aborting.d.ts +39 -0
- package/esm/util/aborting.js +84 -0
- package/esm/util/adapterMetadata.d.ts +1 -1
- package/esm/util/adapterMetadata.js +6 -6
- package/esm/util/addAndShowTrack.d.ts +1 -4
- package/esm/util/addRelativeUris.d.ts +10 -2
- package/esm/util/addRelativeUris.js +22 -7
- package/esm/util/addTrackFromWidget.d.ts +2 -5
- 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/bandLayout.d.ts +4 -4
- package/esm/util/bandLayout.js +4 -4
- package/esm/util/bezierConnector.js +5 -4
- package/esm/util/bgzfWorkerPool.d.ts +20 -74
- package/esm/util/bgzfWorkerPool.js +20 -74
- package/esm/util/cachedSetup.d.ts +1 -1
- package/esm/util/cachedSetup.js +2 -2
- package/esm/util/categoricalField.d.ts +37 -0
- package/esm/util/categoricalField.js +52 -0
- 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 +1 -2
- package/esm/util/colorBits.js +17 -39
- package/esm/util/colorRamp.d.ts +27 -1
- package/esm/util/colorRamp.js +56 -2
- package/esm/util/colorSchemes.d.ts +9 -0
- package/esm/util/colorSchemes.js +7 -0
- package/esm/util/{createStopTokenRotation.d.ts → createAbortRotation.d.ts} +11 -14
- package/esm/util/{createStopTokenRotation.js → createAbortRotation.js} +14 -26
- 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 +7 -12
- package/esm/util/expandLooseSearchIndex.d.ts +7 -0
- package/esm/util/expandLooseSearchIndex.js +25 -0
- package/esm/util/featureTransforms.d.ts +30 -3
- package/esm/util/featureTransforms.js +233 -36
- package/esm/util/fetchAndMaybeUnzip.js +5 -6
- package/esm/util/fetchContext.d.ts +5 -6
- package/esm/util/fetchContext.js +1 -1
- package/esm/util/fetchHub.d.ts +3 -1
- package/esm/util/fetchHub.js +2 -2
- 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/groupKeys.d.ts +75 -0
- package/esm/util/groupKeys.js +152 -0
- package/esm/util/highlights.d.ts +6 -4
- package/esm/util/highlights.js +12 -25
- package/esm/util/hooks.d.ts +1 -2
- package/esm/util/hooks.js +1 -2
- package/esm/util/index.d.ts +3 -3
- package/esm/util/index.js +4 -3
- package/esm/util/indexCandidates.js +1 -1
- package/esm/util/installFetch.d.ts +13 -10
- package/esm/util/installFetch.js +11 -10
- package/esm/util/installPrerequisiteFetch.d.ts +5 -3
- package/esm/util/installPrerequisiteFetch.js +3 -4
- package/esm/util/io/index.js +12 -12
- package/esm/util/isDataCurrent.d.ts +7 -5
- package/esm/util/isDataCurrent.js +9 -6
- 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 +7 -5
- package/esm/util/jexlStrings.d.ts +3 -4
- package/esm/util/jexlStrings.js +2 -3
- package/esm/util/legendCandidates.d.ts +31 -27
- package/esm/util/legendCandidates.js +79 -53
- package/esm/util/localStorage.js +4 -4
- package/esm/util/markEncoding.d.ts +32 -16
- package/esm/util/markEncoding.js +177 -150
- package/esm/util/markEncodingTypes.d.ts +137 -66
- package/esm/util/mstUtils.d.ts +19 -22
- package/esm/util/mstUtils.js +19 -22
- 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.js +1 -2
- package/esm/util/openViews.d.ts +1 -0
- package/esm/util/openViews.js +3 -3
- package/esm/util/parseLineByLine.d.ts +3 -4
- package/esm/util/parseLineByLine.js +7 -13
- package/esm/util/progress.d.ts +21 -21
- package/esm/util/progress.js +27 -26
- package/esm/util/renameRegions.d.ts +1 -2
- package/esm/util/renderToStaticMarkup.js +16 -16
- package/esm/util/rxjs.d.ts +7 -8
- package/esm/util/rxjs.js +12 -15
- package/esm/util/simpleFeature.d.ts +0 -1
- package/esm/util/svgColorProps.d.ts +11 -0
- package/esm/util/svgColorProps.js +28 -1
- package/esm/util/tabix.d.ts +3 -4
- package/esm/util/tabix.js +6 -7
- package/esm/util/thresholdScale.d.ts +54 -0
- package/esm/util/thresholdScale.js +112 -0
- package/esm/util/timeGate.d.ts +4 -5
- package/esm/util/timeGate.js +4 -5
- package/esm/util/trackConfigDelta.d.ts +22 -18
- package/esm/util/trackConfigDelta.js +40 -38
- package/esm/util/tracks.d.ts +27 -4
- package/esm/util/tracks.js +116 -43
- package/esm/util/translateTranscript.d.ts +44 -0
- package/esm/util/translateTranscript.js +102 -0
- package/esm/util/types/index.d.ts +19 -7
- package/esm/util/types/services.d.ts +1 -1
- package/esm/util/unknownSnapshotKeys.d.ts +15 -0
- package/esm/util/unknownSnapshotKeys.js +13 -0
- package/esm/util/useFeatureSequence.js +4 -4
- package/esm/util/useFetch.d.ts +3 -4
- package/esm/util/useFetch.js +5 -6
- package/esm/util/usePanelVirtualScroll.d.ts +7 -39
- package/esm/util/usePanelVirtualScroll.js +9 -40
- 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 -84
- package/esm/util/viewHighlights.d.ts +3 -0
- package/esm/util/viewHighlights.js +5 -0
- package/esm/util/viewStatus.d.ts +24 -15
- package/esm/util/viewStatus.js +17 -0
- package/esm/util/withLaunchInput.d.ts +1 -1
- package/esm/util/withLaunchInput.js +0 -4
- package/package.json +26 -12
- 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/barrelOnlyNames.d.ts +0 -5
- package/esm/ReExports/barrelOnlyNames.js +0 -63
- package/esm/ReExports/index.d.ts +0 -1
- package/esm/ReExports/index.js +0 -1
- package/esm/ReExports/publicTracks.d.ts +0 -1
- package/esm/ReExports/publicTracks.js +0 -14
- package/esm/ReExports/publicUi.d.ts +0 -4
- package/esm/ReExports/publicUi.js +0 -33
- package/esm/ReExports/publicUtil.d.ts +0 -1
- package/esm/ReExports/publicUtil.js +0 -32
- package/esm/ReExports/sharedModules.d.ts +0 -96
- package/esm/ReExports/sharedModules.js +0 -66
- package/esm/ReExports/workerNamespaceNames.d.ts +0 -11
- package/esm/ReExports/workerNamespaceNames.js +0 -275
- package/esm/pluggableElementTypes/models/HighlightsMixin.d.ts +0 -51
- package/esm/pluggableElementTypes/models/HighlightsMixin.js +0 -78
- package/esm/ui/highlightChipReveal.d.ts +0 -32
- package/esm/ui/highlightChipReveal.js +0 -39
- package/esm/util/adapterConfigKey.d.ts +0 -12
- package/esm/util/adapterConfigKey.js +0 -14
- package/esm/util/stopToken.d.ts +0 -212
- package/esm/util/stopToken.js +0 -438
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { categoricalPalette } from '../ui/colors.js';
|
|
2
|
+
import { NO_VALUE_LABEL } from './categoricalField.js';
|
|
3
|
+
import { MISCONFIGURED_COLOR, NO_CATEGORY_COLOR } from './color/index.js';
|
|
4
|
+
import { groupKeyComparator, valueText } from './groupKeys.js';
|
|
5
|
+
import { numericValue } from './numericValue.js';
|
|
6
|
+
/**
|
|
7
|
+
* #api
|
|
8
|
+
* A domain written as strings — the shared `domain` slot is a `stringArray` —
|
|
9
|
+
* read back as the numbers it names. A member that is not a number reads NaN,
|
|
10
|
+
* which every comparison against it declines.
|
|
11
|
+
*/
|
|
12
|
+
export function numericDomain(domain) {
|
|
13
|
+
return domain.map(Number);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* #api
|
|
17
|
+
* A threshold scale's cut points as {@link thresholdIndex} walks them: the
|
|
18
|
+
* numbers the domain names, ascending. Cuts written high to low, as p-value
|
|
19
|
+
* thresholds often are, left the middle interval unreachable, the walk stopping
|
|
20
|
+
* at the first cut a value is under.
|
|
21
|
+
*/
|
|
22
|
+
export function thresholdCuts(domain) {
|
|
23
|
+
return numericDomain(domain)
|
|
24
|
+
.filter(cut => Number.isFinite(cut))
|
|
25
|
+
.sort((a, b) => a - b);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* #api
|
|
29
|
+
* The bin a value falls in: how many of the ascending cut points it is at or
|
|
30
|
+
* past, so a palette with one more entry than the domain paints it as
|
|
31
|
+
* `palette[thresholdIndex(value, domain)]`. A value that is not a finite
|
|
32
|
+
* number is in no bin and answers -1.
|
|
33
|
+
*/
|
|
34
|
+
export function thresholdIndex(value, domain) {
|
|
35
|
+
const v = numericValue(value);
|
|
36
|
+
if (!Number.isFinite(v)) {
|
|
37
|
+
return -1;
|
|
38
|
+
}
|
|
39
|
+
let i = 0;
|
|
40
|
+
while (i < domain.length && v >= domain[i]) {
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
return i;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* #api
|
|
47
|
+
* The colour of each interval, in order: the declared palette, and the
|
|
48
|
+
* default categorical palette where it runs out.
|
|
49
|
+
*/
|
|
50
|
+
export function thresholdPalette(bins, palette = []) {
|
|
51
|
+
return Array.from({ length: bins }, (_, i) => palette[i] ?? categoricalPalette[i % categoricalPalette.length]);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* #api
|
|
55
|
+
* What a threshold scale's bins are called in a key, one label per palette
|
|
56
|
+
* entry: `< a` below the first cut, `a – b` between two, `≥ b` past the last.
|
|
57
|
+
*/
|
|
58
|
+
export function thresholdLabels(domain) {
|
|
59
|
+
if (domain.length === 0) {
|
|
60
|
+
return ['any value'];
|
|
61
|
+
}
|
|
62
|
+
return [
|
|
63
|
+
`< ${domain[0]}`,
|
|
64
|
+
...domain.slice(1).map((cut, i) => `${domain[i]} – ${cut}`),
|
|
65
|
+
`≥ ${domain.at(-1)}`,
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* #api
|
|
70
|
+
* The key a value holding text that is no number files under on a threshold
|
|
71
|
+
* scale, painted the misconfiguration grey rather than passing for a missing
|
|
72
|
+
* value.
|
|
73
|
+
*/
|
|
74
|
+
export const NOT_A_NUMBER_LABEL = '(not a number)';
|
|
75
|
+
// A VCF's `AF=.` arrives as `[undefined]`, which is no value rather than text
|
|
76
|
+
// that fails to parse.
|
|
77
|
+
function isMissing(value) {
|
|
78
|
+
return Array.isArray(value)
|
|
79
|
+
? value.every(v => v === undefined || v === null)
|
|
80
|
+
: valueText(value) === '';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* #api
|
|
84
|
+
* A threshold scale read the way every categorical channel reads its field: a
|
|
85
|
+
* value files under the label of the bin it falls in, a feature with no value
|
|
86
|
+
* under `''`, and text that is no number under {@link NOT_A_NUMBER_LABEL}.
|
|
87
|
+
* The bins are the whole domain, so a key lists each one.
|
|
88
|
+
*/
|
|
89
|
+
export function thresholdField(field, { domain = [], range = [], } = {}) {
|
|
90
|
+
const cuts = thresholdCuts(domain);
|
|
91
|
+
const labels = thresholdLabels(cuts);
|
|
92
|
+
const palette = thresholdPalette(labels.length, range);
|
|
93
|
+
const colorOf = new Map(labels.map((label, i) => [label, palette[i]]));
|
|
94
|
+
return {
|
|
95
|
+
field,
|
|
96
|
+
domain: labels,
|
|
97
|
+
closed: true,
|
|
98
|
+
key: value => {
|
|
99
|
+
if (isMissing(value)) {
|
|
100
|
+
return '';
|
|
101
|
+
}
|
|
102
|
+
const bin = thresholdIndex(value, cuts);
|
|
103
|
+
return bin < 0 ? NOT_A_NUMBER_LABEL : labels[bin];
|
|
104
|
+
},
|
|
105
|
+
compare: groupKeyComparator([...labels, NOT_A_NUMBER_LABEL]),
|
|
106
|
+
label: key => (key === '' ? NO_VALUE_LABEL : key),
|
|
107
|
+
sectionLabel: key => `${field}: ${key === '' ? 'none' : key}`,
|
|
108
|
+
color: key => key === ''
|
|
109
|
+
? NO_CATEGORY_COLOR
|
|
110
|
+
: (colorOf.get(key) ?? MISCONFIGURED_COLOR),
|
|
111
|
+
};
|
|
112
|
+
}
|
package/esm/util/timeGate.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* `Date.now()` costs ~40ns, invisible until the loop is a 666k-read pileup —
|
|
7
7
|
* there it measured ~28ms per gated callsite, and the alignments worker has two
|
|
8
|
-
* of them (the progress emit in `createProgressReporter` and the
|
|
9
|
-
*
|
|
8
|
+
* of them (the progress emit in `createProgressReporter` and the yield in
|
|
9
|
+
* `createAbortBreakpoint`). Both previously read the clock per call, on the
|
|
10
10
|
* documented reasoning that it was negligible next to the per-item work; at
|
|
11
11
|
* this item count it measurably isn't.
|
|
12
12
|
*
|
|
@@ -18,9 +18,8 @@
|
|
|
18
18
|
* measure a low rate and hold a stride of 1, gating on time alone as before,
|
|
19
19
|
* while a millions-of-calls loop thins itself out.
|
|
20
20
|
*
|
|
21
|
-
* `intervalMs` is per call rather than fixed at construction
|
|
22
|
-
*
|
|
23
|
-
* linearly over a long loop. Both current callers pass a constant.
|
|
21
|
+
* `intervalMs` is per call rather than fixed at construction; both current
|
|
22
|
+
* callers pass a constant.
|
|
24
23
|
*/
|
|
25
24
|
export declare function createTimeGate(): (intervalMs: number) => boolean;
|
|
26
25
|
export type TimeGate = ReturnType<typeof createTimeGate>;
|
package/esm/util/timeGate.js
CHANGED
|
@@ -24,8 +24,8 @@ const STRIDE_GROWTH_LIMIT = 8;
|
|
|
24
24
|
*
|
|
25
25
|
* `Date.now()` costs ~40ns, invisible until the loop is a 666k-read pileup —
|
|
26
26
|
* there it measured ~28ms per gated callsite, and the alignments worker has two
|
|
27
|
-
* of them (the progress emit in `createProgressReporter` and the
|
|
28
|
-
*
|
|
27
|
+
* of them (the progress emit in `createProgressReporter` and the yield in
|
|
28
|
+
* `createAbortBreakpoint`). Both previously read the clock per call, on the
|
|
29
29
|
* documented reasoning that it was negligible next to the per-item work; at
|
|
30
30
|
* this item count it measurably isn't.
|
|
31
31
|
*
|
|
@@ -37,9 +37,8 @@ const STRIDE_GROWTH_LIMIT = 8;
|
|
|
37
37
|
* measure a low rate and hold a stride of 1, gating on time alone as before,
|
|
38
38
|
* while a millions-of-calls loop thins itself out.
|
|
39
39
|
*
|
|
40
|
-
* `intervalMs` is per call rather than fixed at construction
|
|
41
|
-
*
|
|
42
|
-
* linearly over a long loop. Both current callers pass a constant.
|
|
40
|
+
* `intervalMs` is per call rather than fixed at construction; both current
|
|
41
|
+
* callers pass a constant.
|
|
43
42
|
*/
|
|
44
43
|
export function createTimeGate() {
|
|
45
44
|
let stride = 1;
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
* - `diffTrackConfig(base, edited)` — the minimal delta
|
|
13
13
|
* - `mergeTrackConfig(base, delta)` — reconstruct the effective config
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
15
|
+
* A delta is a JSON Merge Patch (RFC 7396) over the base, so a `null` member is
|
|
16
|
+
* a reset: the merge removes the member and the schema's default applies. That
|
|
17
|
+
* is ADR-146's spelling of a reset, and the diff writes one wherever the base
|
|
18
|
+
* sets a member the edited config lacks — a slot put back to its default, or a
|
|
19
|
+
* list emptied, since `stripDefault` drops both from a snapshot. Where the edit
|
|
20
|
+
* left a whole namespace at its default, the nulls land on the members the base
|
|
21
|
+
* set inside it rather than on the namespace, so a member the admin adds there
|
|
22
|
+
* later still flows through. The inference
|
|
23
|
+
* is exact only because both sides are post-`stripDefault` snapshots: a member
|
|
24
|
+
* the admin wrote at its default is absent from both, where a `null` for it
|
|
25
|
+
* would block a later admin value. As in RFC 7396, a delta cannot set a member
|
|
26
|
+
* to a literal `null`; null and absent are one state.
|
|
27
27
|
*
|
|
28
28
|
* `displays` is merged by `displayId` so an edit to one display doesn't pin the
|
|
29
29
|
* others. Nested config objects (e.g. `adapter`) recurse. Any other array (value
|
|
@@ -42,18 +42,22 @@ type Json = string | number | boolean | null | undefined | Json[] | {
|
|
|
42
42
|
[key: string]: Json;
|
|
43
43
|
};
|
|
44
44
|
/**
|
|
45
|
-
* Minimal delta of `edited` against `base
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* self-identifying.
|
|
45
|
+
* Minimal delta of `edited` against `base`, both post-stripDefault snapshots. A
|
|
46
|
+
* member `base` sets and `edited` lacks is a `null` (see the module note).
|
|
47
|
+
* Always retains `trackId` so the delta is self-identifying.
|
|
49
48
|
*/
|
|
50
49
|
export declare function diffTrackConfig(base: Record<string, unknown>, edited: Record<string, unknown>): Record<string, unknown>;
|
|
51
50
|
/**
|
|
52
51
|
* Reconstruct the effective config by layering `delta` over the live `base`.
|
|
53
|
-
*
|
|
52
|
+
* A `null` removes the member it names, and one naming something the base no
|
|
53
|
+
* longer has is dropped, so no `null` member reaches the config a track
|
|
54
|
+
* hydrates from.
|
|
54
55
|
*/
|
|
55
56
|
export declare function mergeTrackConfig(base: Record<string, unknown>, delta: Record<string, unknown>): Record<string, unknown>;
|
|
56
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* A single overridden slot: the dotted `path`, its base `from` and edited `to`,
|
|
59
|
+
* which is `undefined` for a reset.
|
|
60
|
+
*/
|
|
57
61
|
export interface TrackConfigChange {
|
|
58
62
|
/**
|
|
59
63
|
* Where the setting lives. A producer that wants a friendlier heading sets
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
* - `diffTrackConfig(base, edited)` — the minimal delta
|
|
13
13
|
* - `mergeTrackConfig(base, delta)` — reconstruct the effective config
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
15
|
+
* A delta is a JSON Merge Patch (RFC 7396) over the base, so a `null` member is
|
|
16
|
+
* a reset: the merge removes the member and the schema's default applies. That
|
|
17
|
+
* is ADR-146's spelling of a reset, and the diff writes one wherever the base
|
|
18
|
+
* sets a member the edited config lacks — a slot put back to its default, or a
|
|
19
|
+
* list emptied, since `stripDefault` drops both from a snapshot. Where the edit
|
|
20
|
+
* left a whole namespace at its default, the nulls land on the members the base
|
|
21
|
+
* set inside it rather than on the namespace, so a member the admin adds there
|
|
22
|
+
* later still flows through. The inference
|
|
23
|
+
* is exact only because both sides are post-`stripDefault` snapshots: a member
|
|
24
|
+
* the admin wrote at its default is absent from both, where a `null` for it
|
|
25
|
+
* would block a later admin value. As in RFC 7396, a delta cannot set a member
|
|
26
|
+
* to a literal `null`; null and absent are one state.
|
|
27
27
|
*
|
|
28
28
|
* `displays` is merged by `displayId` so an edit to one display doesn't pin the
|
|
29
29
|
* others. Nested config objects (e.g. `adapter`) recurse. Any other array (value
|
|
@@ -49,10 +49,14 @@ function isDisplayArray(v) {
|
|
|
49
49
|
v.length > 0 &&
|
|
50
50
|
v.every(e => isPlainObject(e) && typeof e.displayId === 'string'));
|
|
51
51
|
}
|
|
52
|
-
// Sentinel returned by diffValue when a value is unchanged, so callers can tell
|
|
53
|
-
// "no delta" apart from a legitimate `undefined` slot value.
|
|
54
52
|
const UNCHANGED = Symbol('unchanged');
|
|
55
53
|
function diffValue(base, edited) {
|
|
54
|
+
if (edited == null) {
|
|
55
|
+
if (base == null) {
|
|
56
|
+
return UNCHANGED;
|
|
57
|
+
}
|
|
58
|
+
return isPlainObject(base) ? diffValue(base, {}) : null;
|
|
59
|
+
}
|
|
56
60
|
if (deepEqual(base, edited)) {
|
|
57
61
|
return UNCHANGED;
|
|
58
62
|
}
|
|
@@ -65,13 +69,10 @@ function diffValue(base, edited) {
|
|
|
65
69
|
if (baseDisplay) {
|
|
66
70
|
const d = diffValue(baseDisplay, editedDisplay);
|
|
67
71
|
if (d !== UNCHANGED) {
|
|
68
|
-
// always re-key the delta entry by displayId so merge can realign it
|
|
69
72
|
out.push({ ...d, displayId: id });
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
else {
|
|
73
|
-
// a display present only in the edited config (e.g. an added display):
|
|
74
|
-
// carry it whole
|
|
75
76
|
out.push(editedDisplay);
|
|
76
77
|
}
|
|
77
78
|
}
|
|
@@ -79,25 +80,20 @@ function diffValue(base, edited) {
|
|
|
79
80
|
}
|
|
80
81
|
if (isPlainObject(edited) && isPlainObject(base)) {
|
|
81
82
|
const out = {};
|
|
82
|
-
for (const
|
|
83
|
-
const d = diffValue(base[k],
|
|
83
|
+
for (const k of new Set([...Object.keys(base), ...Object.keys(edited)])) {
|
|
84
|
+
const d = diffValue(base[k], edited[k]);
|
|
84
85
|
if (d !== UNCHANGED) {
|
|
85
86
|
out[k] = d;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
// an object whose only difference from base is dropped keys (a reset the
|
|
89
|
-
// delta can't express, see module note) yields no adds/changes: treat it as
|
|
90
|
-
// unchanged rather than emitting a content-free entry
|
|
91
89
|
return Object.keys(out).length > 0 ? out : UNCHANGED;
|
|
92
90
|
}
|
|
93
|
-
// scalar, or an object/array replacing a scalar (or a value array): replace
|
|
94
91
|
return edited;
|
|
95
92
|
}
|
|
96
93
|
/**
|
|
97
|
-
* Minimal delta of `edited` against `base
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* self-identifying.
|
|
94
|
+
* Minimal delta of `edited` against `base`, both post-stripDefault snapshots. A
|
|
95
|
+
* member `base` sets and `edited` lacks is a `null` (see the module note).
|
|
96
|
+
* Always retains `trackId` so the delta is self-identifying.
|
|
101
97
|
*/
|
|
102
98
|
export function diffTrackConfig(base, edited) {
|
|
103
99
|
const d = diffValue(base, edited);
|
|
@@ -106,34 +102,40 @@ export function diffTrackConfig(base, edited) {
|
|
|
106
102
|
return { ...delta, trackId };
|
|
107
103
|
}
|
|
108
104
|
function mergeValue(base, delta) {
|
|
109
|
-
if (isDisplayArray(delta)
|
|
105
|
+
if (isDisplayArray(delta)) {
|
|
106
|
+
const baseDisplays = isDisplayArray(base) ? base : [];
|
|
110
107
|
const deltaById = new Map(delta.map(d => [d.displayId, d]));
|
|
111
|
-
const merged =
|
|
108
|
+
const merged = baseDisplays.map(baseDisplay => {
|
|
112
109
|
const d = deltaById.get(baseDisplay.displayId);
|
|
113
110
|
return d ? mergeValue(baseDisplay, d) : baseDisplay;
|
|
114
111
|
});
|
|
115
|
-
|
|
116
|
-
const baseIds = new Set(base.map(d => d.displayId));
|
|
112
|
+
const baseIds = new Set(baseDisplays.map(d => d.displayId));
|
|
117
113
|
for (const d of delta) {
|
|
118
114
|
if (!baseIds.has(d.displayId)) {
|
|
119
|
-
merged.push(d);
|
|
115
|
+
merged.push(mergeValue(undefined, d));
|
|
120
116
|
}
|
|
121
117
|
}
|
|
122
118
|
return merged;
|
|
123
119
|
}
|
|
124
|
-
if (isPlainObject(delta)
|
|
125
|
-
const out = { ...base };
|
|
120
|
+
if (isPlainObject(delta)) {
|
|
121
|
+
const out = isPlainObject(base) ? { ...base } : {};
|
|
126
122
|
for (const [k, v] of Object.entries(delta)) {
|
|
127
|
-
|
|
123
|
+
if (v === null) {
|
|
124
|
+
delete out[k];
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
out[k] = mergeValue(out[k], v);
|
|
128
|
+
}
|
|
128
129
|
}
|
|
129
130
|
return out;
|
|
130
131
|
}
|
|
131
|
-
// scalar / value array / type mismatch: delta wins
|
|
132
132
|
return delta;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
135
|
* Reconstruct the effective config by layering `delta` over the live `base`.
|
|
136
|
-
*
|
|
136
|
+
* A `null` removes the member it names, and one naming something the base no
|
|
137
|
+
* longer has is dropped, so no `null` member reaches the config a track
|
|
138
|
+
* hydrates from.
|
|
137
139
|
*/
|
|
138
140
|
export function mergeTrackConfig(base, delta) {
|
|
139
141
|
return mergeValue(base, delta);
|
|
@@ -172,7 +174,7 @@ function walkDelta(base, delta, path, out, identityKeys = IDENTITY_KEYS) {
|
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
else {
|
|
175
|
-
out.push({ path, from: base, to: delta });
|
|
177
|
+
out.push({ path, from: base, to: delta ?? undefined });
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
/**
|
package/esm/util/tracks.d.ts
CHANGED
|
@@ -223,6 +223,7 @@ export declare function guessTrackType(adapterType: string, model?: IAnyStateTre
|
|
|
223
223
|
export interface LooseTrackInput {
|
|
224
224
|
uri: string;
|
|
225
225
|
index?: string;
|
|
226
|
+
baseUri?: string;
|
|
226
227
|
[key: string]: unknown;
|
|
227
228
|
}
|
|
228
229
|
/**
|
|
@@ -383,6 +384,31 @@ export declare function viewDisplayNames(pluginManager: PluginManager, viewType:
|
|
|
383
384
|
* so the pickers agree on it.
|
|
384
385
|
*/
|
|
385
386
|
export declare function viewCanDisplayTrack(pluginManager: PluginManager, viewDisplays: Set<string>, trackType: string): boolean;
|
|
387
|
+
/**
|
|
388
|
+
* The tracks a view can be offered: those that support every assembly it
|
|
389
|
+
* displays, and that declare a display it can draw. The track selector's tree
|
|
390
|
+
* and every other picker that opens a track into a view read this one answer,
|
|
391
|
+
* or one of them offers a track the next hides.
|
|
392
|
+
*/
|
|
393
|
+
export declare function filterTracks(tracks: AnyConfigurationModel[], self: {
|
|
394
|
+
view?: IStateTreeNode & {
|
|
395
|
+
type: string;
|
|
396
|
+
};
|
|
397
|
+
assemblyNames: string[];
|
|
398
|
+
}): AnyConfigurationModel[];
|
|
399
|
+
/**
|
|
400
|
+
* Every track config a view can be offered, each assembly's sequence track
|
|
401
|
+
* first and then {@link filterTracks} over the list handed in. The track
|
|
402
|
+
* selector's tree and the close-up dialog are both this, so a track one
|
|
403
|
+
* offers and the other hides would have to be a difference in the assemblies
|
|
404
|
+
* they were asked about.
|
|
405
|
+
*/
|
|
406
|
+
export declare function offeredTracks(tracks: AnyConfigurationModel[], self: {
|
|
407
|
+
view?: IStateTreeNode & {
|
|
408
|
+
type: string;
|
|
409
|
+
};
|
|
410
|
+
assemblyNames: string[];
|
|
411
|
+
}): AnyConfigurationModel[];
|
|
386
412
|
export declare function pickDisplayForView({ declaredDisplays, requestedType, trackDisplayTypes, viewDisplayTypes, preferredDisplayTypes, }: {
|
|
387
413
|
declaredDisplays: DisplayConfSnapshot[];
|
|
388
414
|
requestedType: string | undefined;
|
|
@@ -447,10 +473,7 @@ export declare function allSessionTracks(session: {
|
|
|
447
473
|
connectionInstances?: {
|
|
448
474
|
tracks: AnyConfigurationModel[];
|
|
449
475
|
}[];
|
|
450
|
-
}):
|
|
451
|
-
setSubschema(slotName: string, data: Record<string, unknown>): any;
|
|
452
|
-
setSlot(slotName: string, value: unknown): void;
|
|
453
|
-
} & IStateTreeNode<import("../configuration/types.ts").AnyConfigurationSchemaType>)[];
|
|
476
|
+
}): AnyConfigurationModel[];
|
|
454
477
|
/**
|
|
455
478
|
* The session's annotation for `assemblyName`, as trackIds: what a view opened
|
|
456
479
|
* on another genome starts with. Only FeatureTracks, not everything configured
|
package/esm/util/tracks.js
CHANGED
|
@@ -8,13 +8,14 @@ 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
|
-
import { getParent, getSnapshot, hasParent, isAlive, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
|
|
11
|
+
import { getParent, getSnapshot, getType, hasParent, isAlive, isModelType, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
|
|
12
12
|
import { observable, runInAction, untracked } from 'mobx';
|
|
13
13
|
import { readConfObject } from '../configuration/index.js';
|
|
14
14
|
import { getFileHandle, storeFileHandle, verifyPermission, } from './fileHandleStore.js';
|
|
15
15
|
import { getFileName } from './getFileName.js';
|
|
16
16
|
import { getContainingView, getEnv, getSession, objectHash, } from './mstUtils.js';
|
|
17
17
|
import { isViewModel } from './types/index.js';
|
|
18
|
+
import { setterOnlyMessage, unknownKeysMessage } from './unknownSnapshotKeys.js';
|
|
18
19
|
// Deliberately uncached. This used to memoize on a permanent WeakMap keyed by
|
|
19
20
|
// track, but every caller reads it from inside a reactive getter or autorun: the
|
|
20
21
|
// memo meant the reaction never subscribed to the config, so editing
|
|
@@ -405,9 +406,10 @@ export function guessTrackType(adapterType, model, file) {
|
|
|
405
406
|
* the caller can ask for a full config instead.
|
|
406
407
|
*/
|
|
407
408
|
export function guessTrackConf(input, pluginManager, assemblyName) {
|
|
408
|
-
const { uri, index, ...extra } = typeof input === 'string' ? { uri: input } : input;
|
|
409
|
+
const { uri, index, baseUri, ...extra } = typeof input === 'string' ? { uri: input } : input;
|
|
410
|
+
const base = baseUri ? { baseUri } : {};
|
|
409
411
|
return {
|
|
410
|
-
...guessTrackConfForLocation({ uri, locationType: 'UriLocation' }, index ? { uri: index, locationType: 'UriLocation' } : undefined, pluginManager, assemblyName),
|
|
412
|
+
...guessTrackConfForLocation({ uri, locationType: 'UriLocation', ...base }, index ? { uri: index, locationType: 'UriLocation', ...base } : undefined, pluginManager, assemblyName),
|
|
411
413
|
...extra,
|
|
412
414
|
};
|
|
413
415
|
}
|
|
@@ -501,6 +503,43 @@ export function getTrackName(conf, session) {
|
|
|
501
503
|
: (conf.trackId ?? '');
|
|
502
504
|
return trackName || trackId;
|
|
503
505
|
}
|
|
506
|
+
// The first-show path spreads the same settings into the display's `create()`
|
|
507
|
+
// snapshot, so a DECLARED PROP (`resolution` on the wiggle displays) has
|
|
508
|
+
// already landed by the time applyDisplaySettings reports it took no slot.
|
|
509
|
+
// Only a declared prop: MST restores nothing else from a snapshot, so a
|
|
510
|
+
// volatile or a getter of the same name (`scrollTop`) did not land and the
|
|
511
|
+
// caller has to hear about it.
|
|
512
|
+
function didNotLand(unapplied, display) {
|
|
513
|
+
const type = display ? getType(display) : undefined;
|
|
514
|
+
const props = type && isModelType(type) ? Object.keys(type.properties) : [];
|
|
515
|
+
return unapplied.filter(entry => !props.includes(entry.key));
|
|
516
|
+
}
|
|
517
|
+
function notifySettingsReport(session, trackId, displayType, unapplied, failed) {
|
|
518
|
+
const label = `${displayType} for track "${trackId}"`;
|
|
519
|
+
const keys = (of) => of.map(entry => entry.key);
|
|
520
|
+
const setterOnly = unapplied.filter(e => e.reason === 'setter-only');
|
|
521
|
+
const unknown = unapplied.filter(e => e.reason !== 'setter-only');
|
|
522
|
+
if (unknown.length) {
|
|
523
|
+
session.notifyError(unknownKeysMessage(label, keys(unknown)));
|
|
524
|
+
}
|
|
525
|
+
if (setterOnly.length) {
|
|
526
|
+
session.notifyError(setterOnlyMessage(label, keys(setterOnly)));
|
|
527
|
+
}
|
|
528
|
+
if (failed.length) {
|
|
529
|
+
session.notifyError(`Track "${trackId}" rejected ${failed.map(f => `${f.key}: ${f.error}`).join('; ')}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// `type` picks a display for a new track and means nothing to a shown one.
|
|
533
|
+
function restyleShown(self, trackId, found, { type: _type, ...settings }) {
|
|
534
|
+
const track = found;
|
|
535
|
+
if (Object.keys(settings).length && track.applyDisplaySettings) {
|
|
536
|
+
const report = track.applyDisplaySettings(settings);
|
|
537
|
+
// no `didNotLand` here: this path spreads no snapshot, so every entry
|
|
538
|
+
// applyDisplaySettings reports really did write nothing
|
|
539
|
+
notifySettingsReport(getSession(self), trackId, track.activeDisplay.type, report.unapplied, report.failed);
|
|
540
|
+
}
|
|
541
|
+
return found;
|
|
542
|
+
}
|
|
504
543
|
/**
|
|
505
544
|
* Which display a track opens with in a given view, and the display config that
|
|
506
545
|
* display must use: `{ type, conf }`, or undefined when the view supports none
|
|
@@ -564,6 +603,74 @@ export function viewCanDisplayTrack(pluginManager, viewDisplays, trackType) {
|
|
|
564
603
|
.getTrackType(trackType)
|
|
565
604
|
.displayTypes.some(d => viewDisplays.has(d.name)));
|
|
566
605
|
}
|
|
606
|
+
/**
|
|
607
|
+
* Whether every name in `subset` appears in `superset`. An absent superset
|
|
608
|
+
* contains nothing; an absent subset is contained by anything.
|
|
609
|
+
*/
|
|
610
|
+
function containsAll(superset = [], subset = []) {
|
|
611
|
+
const s = new Set(superset);
|
|
612
|
+
return subset.every(x => s.has(x));
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* The tracks a view can be offered: those that support every assembly it
|
|
616
|
+
* displays, and that declare a display it can draw. The track selector's tree
|
|
617
|
+
* and every other picker that opens a track into a view read this one answer,
|
|
618
|
+
* or one of them offers a track the next hides.
|
|
619
|
+
*/
|
|
620
|
+
export function filterTracks(tracks, self) {
|
|
621
|
+
const { view } = self;
|
|
622
|
+
if (!view) {
|
|
623
|
+
return [];
|
|
624
|
+
}
|
|
625
|
+
const { assemblyManager } = getSession(view);
|
|
626
|
+
const { pluginManager } = getEnv(view);
|
|
627
|
+
const canonical = (names) => canonicalAssemblyNames(names, assemblyManager);
|
|
628
|
+
const viewAssemblyNames = canonical(self.assemblyNames);
|
|
629
|
+
const viewDisplays = viewDisplayNames(pluginManager, view.type);
|
|
630
|
+
return tracks.filter(c => {
|
|
631
|
+
const trackAssemblyNames = readConfObject(c, 'assemblyNames');
|
|
632
|
+
return (
|
|
633
|
+
// a view that declares no assemblies (one still initializing) constrains
|
|
634
|
+
// nothing; otherwise the track must cover every one of them
|
|
635
|
+
(viewAssemblyNames.length === 0 ||
|
|
636
|
+
containsAll(trackAssemblyNames && canonical(trackAssemblyNames), viewAssemblyNames)) &&
|
|
637
|
+
viewCanDisplayTrack(pluginManager, viewDisplays, c.type));
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* The assembly's own sequence track, when the view can draw one. It is in no
|
|
642
|
+
* track list — the config lives on the assembly (see {@link getConfAssemblyNames}
|
|
643
|
+
* on why a sequence track's assembly is positional) — so a picker that walks
|
|
644
|
+
* `session.tracks` alone cannot offer the track most views open first.
|
|
645
|
+
*/
|
|
646
|
+
function refSeqTrackConf(assemblyName, view) {
|
|
647
|
+
const { assemblyManager } = getSession(view);
|
|
648
|
+
const { pluginManager } = getEnv(view);
|
|
649
|
+
const conf = assemblyManager.get(assemblyName)?.configuration.sequence;
|
|
650
|
+
// the same display-compatibility question filterTracks asks of every other
|
|
651
|
+
// track, so a view that cannot draw a sequence is not offered one
|
|
652
|
+
return conf &&
|
|
653
|
+
viewCanDisplayTrack(pluginManager, viewDisplayNames(pluginManager, view.type), conf.type)
|
|
654
|
+
? conf
|
|
655
|
+
: undefined;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Every track config a view can be offered, each assembly's sequence track
|
|
659
|
+
* first and then {@link filterTracks} over the list handed in. The track
|
|
660
|
+
* selector's tree and the close-up dialog are both this, so a track one
|
|
661
|
+
* offers and the other hides would have to be a difference in the assemblies
|
|
662
|
+
* they were asked about.
|
|
663
|
+
*/
|
|
664
|
+
export function offeredTracks(tracks, self) {
|
|
665
|
+
const { view, assemblyNames } = self;
|
|
666
|
+
if (!view) {
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
return [
|
|
670
|
+
...assemblyNames.map(name => refSeqTrackConf(name, view)),
|
|
671
|
+
...filterTracks(tracks, self),
|
|
672
|
+
].filter(conf => conf !== undefined);
|
|
673
|
+
}
|
|
567
674
|
export function pickDisplayForView({ declaredDisplays, requestedType, trackDisplayTypes, viewDisplayTypes, preferredDisplayTypes = new Set(), }) {
|
|
568
675
|
const supported = new Set(viewDisplayTypes);
|
|
569
676
|
// A requested type is CHECKED, not taken on faith. It used to pass straight
|
|
@@ -634,6 +741,9 @@ function resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot, inline
|
|
|
634
741
|
throw new Error(`Could not resolve identifier "${trackId}"`);
|
|
635
742
|
}
|
|
636
743
|
const confSnapshot = structuredClone(isStateTreeNode(rawConf) ? getSnapshot(rawConf) : rawConf);
|
|
744
|
+
// `& { type: string }` because `rawConf` unions a live node with a loose
|
|
745
|
+
// `Record<string, unknown>`, and the node's `type: string` widens back to
|
|
746
|
+
// `unknown` across that union
|
|
637
747
|
const conf = pluginManager.evaluateExtensionPoint('Core-preProcessTrackConfig', confSnapshot);
|
|
638
748
|
const trackType = pluginManager.getTrackType(conf.type);
|
|
639
749
|
// Validate only a conf that is not already in the tree. `configSchema.create`
|
|
@@ -706,7 +816,7 @@ inlineConf) {
|
|
|
706
816
|
const session = getSession(self);
|
|
707
817
|
const found = self.tracks.find(t => t.configuration.trackId === trackId);
|
|
708
818
|
if (found) {
|
|
709
|
-
return found;
|
|
819
|
+
return restyleShown(self, trackId, found, displayInitialSnapshot);
|
|
710
820
|
}
|
|
711
821
|
// Single choke point for all "open a track" paths — errors surface as
|
|
712
822
|
// snackbars. Config is validated before the push so the open set never holds
|
|
@@ -756,47 +866,10 @@ inlineConf) {
|
|
|
756
866
|
// reference can resolve. Slots only, deliberately: this is the
|
|
757
867
|
// declarative surface, and `allowSetters` stays off so a spec key cannot
|
|
758
868
|
// reach internal display actions.
|
|
759
|
-
//
|
|
760
|
-
// `type` is dropped first because this function already consumed it
|
|
761
|
-
// (pickDisplayForView above), and only `failed` — a key whose write threw —
|
|
762
|
-
// is notified: `unapplied` here also holds the MST display props the
|
|
763
|
-
// snapshot spread above already applied, so notifying on it would report a
|
|
764
|
-
// correct call as broken. A throwing slot value used to reach the outer
|
|
765
|
-
// catch and raise a snackbar; per-key catching kept the track intact but
|
|
766
|
-
// took the message away with it.
|
|
767
869
|
const displaySettings = Object.fromEntries(Object.entries(displayInitialSnapshot).filter(([key]) => key !== 'type'));
|
|
768
870
|
const report = track.applyDisplaySettings(displaySettings);
|
|
769
|
-
// A key that reached NOTHING, told apart from the ones `unapplied` holds
|
|
770
|
-
// legitimately. `unapplied` means "not a config slot", which covers both an
|
|
771
|
-
// MST display prop the snapshot spread above already applied and a
|
|
772
|
-
// misspelling that did nothing at all — so reporting the list wholesale
|
|
773
|
-
// called a correct spec broken, and reporting none of it let
|
|
774
|
-
// `{ trackId, colorSchem: 'x' }` load a plausible track with the setting
|
|
775
|
-
// silently missing. The display's own model type says which is which.
|
|
776
|
-
// Asked of the display NODE, not of its model type: `type.properties` sees
|
|
777
|
-
// declared props and misses everything else a key can legitimately reach —
|
|
778
|
-
// a volatile the snapshot spread above just set (`resolution` on the GC
|
|
779
|
-
// content display is one) reads as unreached and gets reported over a
|
|
780
|
-
// correct call.
|
|
781
|
-
// `unapplied` holds three kinds of entry, and only one of them means the
|
|
782
|
-
// key did nothing at all: applyDisplaySettings annotates `type` and the
|
|
783
|
-
// "a setter exists, pass allowSetters" case in parentheses, and pushes a
|
|
784
|
-
// BARE key when the display has neither a slot nor a setter for it. So the
|
|
785
|
-
// bare ones are the candidates, and the node itself settles the rest — the
|
|
786
|
-
// snapshot spread above may already have landed the key as a prop or a
|
|
787
|
-
// volatile, which is what `resolution` on the GC content display is.
|
|
788
871
|
const drawn = track.displays[0];
|
|
789
|
-
|
|
790
|
-
? report.unapplied.filter(entry => !entry.includes(' (') && !(entry in drawn))
|
|
791
|
-
: [];
|
|
792
|
-
if (reachedNothing.length > 0) {
|
|
793
|
-
session.notifyError(`Track "${trackId}" ignored ${reachedNothing.join(', ')}: neither a setting the ${displayType} accepts nor one of its properties`);
|
|
794
|
-
}
|
|
795
|
-
if (report.failed.length) {
|
|
796
|
-
session.notifyError(`Track "${trackId}" rejected ${report.failed
|
|
797
|
-
.map(f => `${f.key}: ${f.error}`)
|
|
798
|
-
.join('; ')}`);
|
|
799
|
-
}
|
|
872
|
+
notifySettingsReport(session, trackId, displayType, didNotLand(report.unapplied, drawn), report.failed);
|
|
800
873
|
// if this track came from a connection, persist its config so it survives
|
|
801
874
|
// reload without re-establishing the connection (no-op otherwise)
|
|
802
875
|
session.captureConnectionTrack?.(trackId);
|
|
@@ -840,7 +913,7 @@ export async function launchTrackGeneric(self, trackId, initialSnapshot = {}, di
|
|
|
840
913
|
const session = getSession(self);
|
|
841
914
|
const found = self.tracks.find(t => t.configuration.trackId === trackId);
|
|
842
915
|
if (found) {
|
|
843
|
-
return found;
|
|
916
|
+
return restyleShown(self, trackId, found, displayInitialSnapshot);
|
|
844
917
|
}
|
|
845
918
|
try {
|
|
846
919
|
const { picked } = resolveTrackDisplayChoice(self, trackId, displayInitialSnapshot, inlineConf);
|