@jbrowse/core 5.0.0-beta.13 → 5.0.0-beta.14
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 +365 -69
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseAttributes.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseAttributes.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseCard.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseCard.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseCoreDetails.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BaseCoreDetails.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BasicValue.d.ts +5 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/BasicValue.js +6 -4
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.d.ts +2 -1
- package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/DataGridDetails.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/DataGridDetails.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +2 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureWash.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureWash.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldName.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldName.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Formatter.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/Formatter.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +4 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/UriField.d.ts +3 -2
- package/esm/BaseFeatureWidget/BaseFeatureDetail/UriField.js +4 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceBody.d.ts +3 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceBody.js +4 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.d.ts +1 -1
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.js +10 -19
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceLegend.d.ts +3 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceLegend.js +4 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.js +4 -4
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/HelpDialog.d.ts +3 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/HelpDialog.js +4 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceDialog.d.ts +1 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceDialog.js +2 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceTypeSelector.d.ts +1 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceTypeSelector.js +15 -36
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/TranscriptSelector.d.ts +3 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/dialogs/TranscriptSelector.js +4 -2
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/featureTypeUtil.d.ts +2 -1
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/featureTypeUtil.js +22 -6
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/model.d.ts +13 -1
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/model.js +28 -1
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/SequenceDisplay.js +2 -2
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +2 -0
- package/esm/PluginManager.d.ts +1 -0
- package/esm/PluginManager.js +6 -0
- package/esm/ReExports/coreModules.generated.js +538 -524
- package/esm/ReExports/coreWorkerModules.generated.js +454 -441
- package/esm/ReExports/lazify.js +3 -2
- package/esm/ReExports/list.js +15 -6
- package/esm/ReExports/names.d.ts +1 -0
- package/esm/ReExports/names.generated.d.ts +2 -0
- package/esm/ReExports/names.generated.js +566 -0
- package/esm/ReExports/names.js +3 -0
- package/esm/assemblyManager/assembly.d.ts +9 -0
- package/esm/assemblyManager/assembly.js +13 -0
- package/esm/assemblyManager/assemblyConfigSchema.d.ts +6 -1
- package/esm/assemblyManager/assemblyConfigSchema.js +23 -22
- package/esm/assemblyManager/assemblyManager.d.ts +11 -0
- package/esm/assemblyManager/assemblyManager.js +2 -0
- package/esm/assemblyManager/expandAssemblyConfigShorthand.d.ts +9 -0
- package/esm/assemblyManager/expandAssemblyConfigShorthand.js +23 -0
- package/esm/checkPlugins.js +10 -4
- package/esm/configuration/configurationSchema.d.ts +18 -5
- package/esm/configuration/configurationSchema.js +9 -7
- package/esm/configuration/configurationSchemaUnion.d.ts +2 -1
- package/esm/configuration/configurationSchemaUnion.js +2 -1
- package/esm/configuration/configurationSlot.js +4 -4
- package/esm/configuration/fillLocations.d.ts +4 -2
- package/esm/configuration/fillLocations.js +9 -3
- package/esm/configuration/formatAboutConfigSchema.d.ts +2 -2
- package/esm/configuration/formatAboutConfigSchema.js +2 -2
- package/esm/configuration/formatDetailsConfigSchema.d.ts +2 -2
- package/esm/configuration/formatDetailsConfigSchema.js +5 -5
- package/esm/configuration/getConf.js +13 -4
- package/esm/configuration/index.d.ts +1 -1
- package/esm/configuration/index.js +1 -1
- package/esm/configuration/plot.d.ts +2 -2
- package/esm/configuration/plot.js +32 -18
- package/esm/configuration/schemaRegistry.d.ts +0 -2
- package/esm/configuration/slotFacade.js +2 -2
- package/esm/configuration/snapshotPreprocess.d.ts +42 -18
- package/esm/configuration/snapshotPreprocess.js +94 -34
- package/esm/configuration/tabixShorthand.js +1 -3
- package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +7 -0
- package/esm/data_adapters/BaseAdapter/BaseAdapter.js +7 -0
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +0 -22
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +0 -55
- package/esm/data_adapters/BaseAdapter/index.d.ts +0 -1
- package/esm/data_adapters/BaseAdapter/index.js +0 -1
- package/esm/data_adapters/BaseAdapter/rowSources.d.ts +2 -2
- package/esm/data_adapters/BaseAdapter/types.d.ts +1 -0
- package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +2 -0
- package/esm/data_adapters/CytobandAdapter/configSchema.js +5 -0
- package/esm/data_adapters/dataAdapterCache.d.ts +25 -13
- package/esm/data_adapters/dataAdapterCache.js +68 -24
- package/esm/data_adapters/getFeatureAdapter.d.ts +9 -0
- package/esm/data_adapters/getFeatureAdapter.js +17 -0
- package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +2 -0
- package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.js +2 -0
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +40 -6
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +56 -8
- package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +3 -3
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +7 -6
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +2 -0
- package/esm/pluggableElementTypes/models/BaseViewModel.js +2 -0
- package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +3 -0
- package/esm/pluggableElementTypes/models/InternetAccountModel.js +3 -0
- package/esm/pluggableElementTypes/models/baseConnectionConfig.d.ts +3 -0
- package/esm/pluggableElementTypes/models/baseConnectionConfig.js +3 -0
- package/esm/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +3 -1
- package/esm/pluggableElementTypes/models/baseInternetAccountConfig.js +3 -1
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +9 -1
- package/esm/pluggableElementTypes/models/components/SaveTrackData.js +2 -2
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.d.ts +1 -1
- package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +1 -1
- package/esm/pluginDefinitions.d.ts +7 -0
- package/esm/pluginDefinitions.js +20 -0
- package/esm/rpc/RpcRegistry.d.ts +0 -10
- package/esm/rpc/byteBudget.d.ts +8 -0
- package/esm/rpc/byteBudget.js +13 -0
- package/esm/rpc/configSchema.d.ts +2 -0
- package/esm/rpc/configSchema.js +3 -1
- package/esm/rpc/coreRpcMethods.d.ts +0 -1
- package/esm/rpc/coreRpcMethods.js +0 -1
- package/esm/rpc/methods/CoreGetEncodedLayers.d.ts +2 -2
- package/esm/rpc/methods/CoreGetEncodedLayers.js +7 -5
- package/esm/rpc/methods/layerFeatures.d.ts +9 -6
- package/esm/rpc/methods/layerFeatures.js +21 -5
- package/esm/ui/ActionLink.d.ts +3 -2
- package/esm/ui/ActionLink.js +4 -2
- package/esm/ui/AddCustomPluginDialog.d.ts +3 -2
- package/esm/ui/AddCustomPluginDialog.js +6 -4
- package/esm/ui/BaseTooltip.d.ts +3 -2
- package/esm/ui/BaseTooltip.js +4 -2
- package/esm/ui/CascadingMenu.js +14 -12
- package/esm/ui/CascadingMenuButton.d.ts +2 -2
- package/esm/ui/CascadingMenuButton.js +5 -4
- package/esm/ui/CascadingMenuHelpDialog.d.ts +3 -2
- package/esm/ui/CascadingMenuHelpDialog.js +4 -2
- package/esm/ui/CascadingMenuHelpIconButton.d.ts +4 -3
- package/esm/ui/CascadingMenuHelpIconButton.js +9 -5
- package/esm/ui/ColorPicker.d.ts +5 -4
- package/esm/ui/ColorPicker.js +6 -4
- package/esm/ui/ContextMenu.d.ts +1 -1
- package/esm/ui/ContextMenu.js +1 -1
- package/esm/ui/CopyToClipboardButton.d.ts +3 -2
- package/esm/ui/CopyToClipboardButton.js +4 -2
- package/esm/ui/Crosshairs.js +13 -10
- package/esm/ui/DOMPurifySanitizedHTML.d.ts +3 -2
- package/esm/ui/DOMPurifySanitizedHTML.js +4 -2
- package/esm/ui/DataGridFlexContainer.d.ts +3 -2
- package/esm/ui/DataGridFlexContainer.js +4 -2
- package/esm/ui/Dialog.d.ts +1 -1
- package/esm/ui/Dialog.js +5 -4
- package/esm/ui/DropDownMenu.js +2 -2
- package/esm/ui/EditableTypography.d.ts +1 -1
- package/esm/ui/EditableTypography.js +3 -2
- package/esm/ui/ErrorActions.d.ts +3 -2
- package/esm/ui/ErrorActions.js +4 -2
- package/esm/ui/ErrorBanner.d.ts +2 -2
- package/esm/ui/ErrorBanner.js +3 -2
- package/esm/ui/ErrorBar.d.ts +3 -2
- package/esm/ui/ErrorBar.js +4 -2
- package/esm/ui/ErrorMessage.d.ts +3 -2
- package/esm/ui/ErrorMessage.js +4 -2
- package/esm/ui/ErrorMessageStackTraceContents.d.ts +3 -2
- package/esm/ui/ErrorMessageStackTraceContents.js +4 -2
- package/esm/ui/ErrorMessageStackTraceDialog.d.ts +3 -2
- package/esm/ui/ErrorMessageStackTraceDialog.js +4 -2
- package/esm/ui/ErrorOverlay.d.ts +3 -2
- package/esm/ui/ErrorOverlay.js +4 -2
- package/esm/ui/ExportSvgDialog.d.ts +3 -2
- package/esm/ui/ExportSvgDialog.js +4 -2
- package/esm/ui/ExternalLink.d.ts +2 -1
- package/esm/ui/ExternalLink.js +4 -2
- package/esm/ui/FactoryResetDialog.d.ts +3 -2
- package/esm/ui/FactoryResetDialog.js +4 -2
- package/esm/ui/FatalErrorDialog.d.ts +3 -2
- package/esm/ui/FatalErrorDialog.js +6 -4
- package/esm/ui/FileDropZone.d.ts +3 -2
- package/esm/ui/FileDropZone.js +4 -2
- package/esm/ui/FileSelector/LocalFileChooser.js +4 -4
- package/esm/ui/FileSelector/LocationInput.d.ts +3 -2
- package/esm/ui/FileSelector/LocationInput.js +4 -2
- package/esm/ui/FileSelector/SourceTypeSelector.d.ts +3 -2
- package/esm/ui/FileSelector/SourceTypeSelector.js +8 -6
- package/esm/ui/GpuFallbackButton.d.ts +3 -2
- package/esm/ui/GpuFallbackButton.js +4 -2
- package/esm/ui/HoverMenu.d.ts +2 -2
- package/esm/ui/HoverMenu.js +7 -3
- package/esm/ui/HoverTooltip.d.ts +3 -2
- package/esm/ui/HoverTooltip.js +4 -2
- package/esm/ui/Icons.d.ts +5 -5
- package/esm/ui/Icons.js +11 -10
- package/esm/ui/InlineMenuControls.d.ts +2 -2
- package/esm/ui/InlineMenuControls.js +4 -3
- package/esm/ui/JexlFilterRowEditors.d.ts +4 -4
- package/esm/ui/JexlFilterRowEditors.js +9 -8
- package/esm/ui/LabeledCheckbox.d.ts +3 -2
- package/esm/ui/LabeledCheckbox.js +4 -2
- package/esm/ui/LazyBaseTooltip.d.ts +12 -3
- package/esm/ui/LazyBaseTooltip.js +4 -2
- package/esm/ui/LegendSwatchGlyph.js +1 -0
- package/esm/ui/LoadingDots.d.ts +2 -1
- package/esm/ui/LoadingDots.js +4 -2
- package/esm/ui/LoadingEllipses.d.ts +5 -2
- package/esm/ui/LoadingEllipses.js +5 -3
- package/esm/ui/LoadingOverlay.d.ts +3 -2
- package/esm/ui/LoadingOverlay.js +4 -2
- package/esm/ui/LoadingProgress.d.ts +3 -2
- package/esm/ui/LoadingProgress.js +4 -2
- package/esm/ui/Logo.d.ts +2 -2
- package/esm/ui/Logo.js +9 -8
- package/esm/ui/MenuItemChevron.d.ts +2 -2
- package/esm/ui/MenuItemChevron.js +3 -2
- package/esm/ui/MenuItemEndDecoration.d.ts +2 -2
- package/esm/ui/MenuItemEndDecoration.js +3 -2
- package/esm/ui/MenuItemTrailing.d.ts +2 -2
- package/esm/ui/MenuItemTrailing.js +7 -6
- package/esm/ui/MenuTypes.d.ts +21 -1
- package/esm/ui/MenuTypes.js +20 -0
- package/esm/ui/MonospaceTextField.d.ts +3 -2
- package/esm/ui/MonospaceTextField.js +4 -2
- package/esm/ui/NumberTextField.d.ts +2 -2
- package/esm/ui/NumberTextField.js +4 -2
- package/esm/ui/PaletteContext.d.ts +11 -9
- package/esm/ui/PaletteContext.js +33 -18
- package/esm/ui/PluginStoreCard.d.ts +3 -2
- package/esm/ui/PluginStoreCard.js +4 -2
- package/esm/ui/PopoverPicker.d.ts +3 -2
- package/esm/ui/PopoverPicker.js +4 -2
- package/esm/ui/PrerenderedCanvas.d.ts +2 -2
- package/esm/ui/PrerenderedCanvas.js +3 -2
- package/esm/ui/RedErrorMessageBox.d.ts +3 -2
- package/esm/ui/RedErrorMessageBox.js +4 -2
- package/esm/ui/RefNameAutocomplete/EndAdornment.d.ts +3 -2
- package/esm/ui/RefNameAutocomplete/EndAdornment.js +4 -2
- package/esm/ui/RefNameAutocomplete/HelpDialog.d.ts +3 -2
- package/esm/ui/RefNameAutocomplete/HelpDialog.js +4 -2
- package/esm/ui/ReplaceCurrentViewButton.d.ts +3 -2
- package/esm/ui/ReplaceCurrentViewButton.js +4 -2
- package/esm/ui/ResizeHandle.d.ts +2 -2
- package/esm/ui/ResizeHandle.js +3 -2
- package/esm/ui/SanitizedHTML.d.ts +3 -2
- package/esm/ui/SanitizedHTML.js +6 -4
- package/esm/ui/ScrollChrome.d.ts +3 -2
- package/esm/ui/ScrollChrome.js +4 -2
- package/esm/ui/ScrollEdgeShadow.d.ts +2 -2
- package/esm/ui/ScrollEdgeShadow.js +2 -2
- package/esm/ui/SessionJsonPanel.d.ts +3 -2
- package/esm/ui/SessionJsonPanel.js +4 -2
- package/esm/ui/ShareLinkField.d.ts +3 -2
- package/esm/ui/ShareLinkField.js +4 -2
- package/esm/ui/SingleSlider.d.ts +2 -2
- package/esm/ui/SingleSlider.js +4 -2
- package/esm/ui/SliderTooltip.d.ts +2 -1
- package/esm/ui/SliderTooltip.js +4 -2
- package/esm/ui/SnackbarContents.d.ts +3 -2
- package/esm/ui/SnackbarContents.js +4 -2
- package/esm/ui/SnackbarModel.d.ts +2 -0
- package/esm/ui/SnackbarModel.js +2 -0
- package/esm/ui/StackTraceButton.d.ts +3 -2
- package/esm/ui/StackTraceButton.js +4 -2
- package/esm/ui/StatusProgressBar.d.ts +3 -2
- package/esm/ui/StatusProgressBar.js +4 -2
- package/esm/ui/SubmitForm.d.ts +2 -1
- package/esm/ui/SubmitForm.js +4 -2
- package/esm/ui/SvgColorLegend.d.ts +3 -4
- package/esm/ui/SvgColorLegend.js +27 -18
- package/esm/ui/TagTextField.d.ts +2 -2
- package/esm/ui/TagTextField.js +4 -2
- package/esm/ui/ViewLoadingScreen.d.ts +3 -2
- package/esm/ui/ViewLoadingScreen.js +4 -2
- package/esm/ui/colorScale.d.ts +5 -1
- package/esm/ui/colorScale.js +12 -10
- package/esm/ui/colors.d.ts +3 -3
- package/esm/ui/colors.js +7 -7
- package/esm/ui/filterMenuItems.d.ts +10 -31
- package/esm/ui/filterMenuItems.js +13 -14
- package/esm/ui/index.d.ts +1 -1
- package/esm/ui/index.js +1 -1
- package/esm/ui/launchTargetsMenuItem.js +9 -13
- package/esm/ui/legendMenuItem.d.ts +4 -4
- package/esm/ui/legendMenuItem.js +4 -4
- package/esm/ui/menuItemAdornment.d.ts +1 -1
- package/esm/ui/menuItemAdornment.js +1 -1
- package/esm/ui/menuItems.d.ts +1 -1
- package/esm/ui/menuItems.js +1 -1
- package/esm/ui/menuLabels.d.ts +2 -2
- package/esm/ui/menuLabels.js +2 -2
- package/esm/ui/palette.d.ts +2 -2
- package/esm/ui/palette.js +10 -10
- package/esm/ui/radioSubMenu.d.ts +5 -3
- package/esm/ui/radioSubMenu.js +2 -2
- package/esm/ui/rampKey.d.ts +15 -0
- package/esm/ui/rampKey.js +17 -0
- package/esm/ui/showSubMenu.d.ts +0 -5
- package/esm/ui/showSubMenu.js +6 -15
- package/esm/ui/theme.d.ts +2 -2
- package/esm/ui/theme.js +1 -1
- package/esm/ui/useAssemblySelection.d.ts +2 -0
- package/esm/ui/useMouseTracking.d.ts +8 -20
- package/esm/ui/useMouseTracking.js +23 -62
- package/esm/ui/usePlacedMenuFocus.d.ts +19 -0
- package/esm/ui/usePlacedMenuFocus.js +28 -0
- package/esm/util/Base1DViewModel.d.ts +5 -3
- package/esm/util/Base1DViewModel.js +5 -3
- package/esm/util/SvgCanvas.js +1 -1
- package/esm/util/aggregateFieldName.d.ts +1 -10
- package/esm/util/aggregateFieldName.js +1 -8
- package/esm/util/analytics.d.ts +4 -6
- package/esm/util/analytics.js +143 -12
- package/esm/util/bezierConnector.d.ts +20 -0
- package/esm/util/bezierConnector.js +34 -100
- package/esm/util/cacheBudgets.d.ts +3 -0
- package/esm/util/cacheBudgets.js +3 -0
- package/esm/util/categoricalField.d.ts +2 -2
- package/esm/util/categoricalField.js +3 -3
- package/esm/util/color/index.d.ts +1 -1
- package/esm/util/color/index.js +2 -2
- package/esm/util/color-bits/bit.js +1 -1
- package/esm/util/color-bits/parse.js +6 -6
- package/esm/util/colorBits.d.ts +15 -4
- package/esm/util/colorBits.js +38 -15
- package/esm/util/colorRamp.d.ts +3 -3
- package/esm/util/colorRamp.js +14 -2
- package/esm/util/colorScale.d.ts +114 -20
- package/esm/util/colorScale.js +124 -26
- package/esm/util/colorSchemes.d.ts +6 -4
- package/esm/util/colorSchemes.js +6 -3
- package/esm/util/createSvgRasterCanvas.d.ts +14 -1
- package/esm/util/createSvgRasterCanvas.js +36 -12
- package/esm/util/diagonalizeRegions.js +18 -9
- package/esm/util/featureTransforms.d.ts +2 -2
- package/esm/util/featureTransforms.js +85 -135
- package/esm/util/fileHandleStore.js +5 -0
- package/esm/util/groupKeys.d.ts +5 -4
- package/esm/util/groupKeys.js +15 -9
- package/esm/util/index.js +1 -1
- package/esm/util/installFetch.d.ts +2 -2
- package/esm/util/installPrerequisiteFetch.d.ts +8 -3
- package/esm/util/installPrerequisiteFetch.js +9 -7
- package/esm/util/io/RemoteFileWithRangeCache.d.ts +1 -1
- package/esm/util/io/RemoteFileWithRangeCache.js +1 -1
- package/esm/util/jexl.js +1 -1
- package/esm/util/layouts/GranularRectLayout.d.ts +19 -3
- package/esm/util/layouts/GranularRectLayout.js +57 -34
- package/esm/util/leadingEdgeAutorun.d.ts +9 -1
- package/esm/util/leadingEdgeAutorun.js +5 -2
- package/esm/util/markEncoding.d.ts +10 -8
- package/esm/util/markEncoding.js +50 -12
- package/esm/util/markEncodingTypes.d.ts +74 -20
- package/esm/util/originCut.d.ts +14 -0
- package/esm/util/originCut.js +19 -0
- package/esm/util/paintLayer.d.ts +1 -1
- package/esm/util/paintLayer.js +4 -3
- package/esm/util/pathSeries.d.ts +18 -0
- package/esm/util/pathSeries.js +143 -0
- package/esm/util/pressOwner.d.ts +20 -0
- package/esm/util/pressOwner.js +26 -0
- package/esm/util/quantileExtent.d.ts +3 -3
- package/esm/util/quantileExtent.js +3 -3
- package/esm/util/rowStackGeometry.d.ts +1 -1
- package/esm/util/rowStackGeometry.js +1 -1
- package/esm/util/sessionActivity.d.ts +36 -0
- package/esm/util/sessionActivity.js +88 -0
- package/esm/util/stepOutputs.d.ts +165 -0
- package/esm/util/stepOutputs.js +201 -0
- package/esm/util/stepTables.d.ts +7 -3
- package/esm/util/stepTables.js +86 -3
- package/esm/util/thresholdScale.d.ts +1 -1
- package/esm/util/thresholdScale.js +1 -1
- package/esm/util/tracks.js +1 -1
- package/esm/util/usePanZoom.js +4 -10
- package/esm/util/windowStep.d.ts +6 -0
- package/esm/util/windowStep.js +153 -0
- package/package.json +23 -15
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +0 -40
- package/esm/data_adapters/BaseAdapter/featureDensity.js +0 -31
- package/esm/rpc/methods/CoreGetFeatureDensity.d.ts +0 -11
- package/esm/rpc/methods/CoreGetFeatureDensity.js +0 -22
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { cssColorToHex } from '../util/colorBits.js';
|
|
2
|
+
import { rampLabels } from './colorScale.js';
|
|
3
|
+
/**
|
|
4
|
+
* A ramp's bar as columns, for a host that draws the key itself, such as R
|
|
5
|
+
* through V8: each stop's `offset`, `#rrggbb` `color` and `opacity`, and the
|
|
6
|
+
* end labels the on-screen bar prints.
|
|
7
|
+
*/
|
|
8
|
+
export function rampKeyOf(scale) {
|
|
9
|
+
return {
|
|
10
|
+
id: scale.id,
|
|
11
|
+
title: scale.title ?? '',
|
|
12
|
+
...rampLabels(scale),
|
|
13
|
+
offset: scale.stops.map(stop => stop.offset),
|
|
14
|
+
color: scale.stops.map(stop => cssColorToHex(stop.color)),
|
|
15
|
+
opacity: scale.stops.map(stop => stop.opacity ?? 1),
|
|
16
|
+
};
|
|
17
|
+
}
|
package/esm/ui/showSubMenu.d.ts
CHANGED
|
@@ -6,11 +6,6 @@ import type { MenuItem } from './MenuTypes.ts';
|
|
|
6
6
|
* multi-row painting with no legend) drops the row rather than opening an empty
|
|
7
7
|
* submenu.
|
|
8
8
|
*
|
|
9
|
-
* One helper because this was eleven hand-written literals that had already
|
|
10
|
-
* drifted three ways: the wiggle family said `'Show'` where everyone else said
|
|
11
|
-
* `'Show...'`, only some set the redundant `type: 'subMenu'`, and only the
|
|
12
|
-
* wiggle family omitted the empty submenu.
|
|
13
|
-
*
|
|
14
9
|
* Not exported from `ui/menuItems.ts`: the icon is a value import, and that
|
|
15
10
|
* entry is the React-free one (see its header). Import this module directly —
|
|
16
11
|
* `@jbrowse/core/ui/showSubMenu` — which costs one icon rather than the
|
package/esm/ui/showSubMenu.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
|
2
|
+
import { subMenuIfAny } from './MenuTypes.js';
|
|
2
3
|
/**
|
|
3
4
|
* The "Show..." submenu every display groups its visibility toggles under, and
|
|
4
5
|
* the empty-omit that goes with it: a display whose toggles are all
|
|
@@ -6,25 +7,15 @@ import VisibilityIcon from '@mui/icons-material/Visibility';
|
|
|
6
7
|
* multi-row painting with no legend) drops the row rather than opening an empty
|
|
7
8
|
* submenu.
|
|
8
9
|
*
|
|
9
|
-
* One helper because this was eleven hand-written literals that had already
|
|
10
|
-
* drifted three ways: the wiggle family said `'Show'` where everyone else said
|
|
11
|
-
* `'Show...'`, only some set the redundant `type: 'subMenu'`, and only the
|
|
12
|
-
* wiggle family omitted the empty submenu.
|
|
13
|
-
*
|
|
14
10
|
* Not exported from `ui/menuItems.ts`: the icon is a value import, and that
|
|
15
11
|
* entry is the React-free one (see its header). Import this module directly —
|
|
16
12
|
* `@jbrowse/core/ui/showSubMenu` — which costs one icon rather than the
|
|
17
13
|
* `@jbrowse/core/ui` barrel's ~80 Material components.
|
|
18
14
|
*/
|
|
19
15
|
export function makeShowSubMenu(items) {
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
type: 'subMenu',
|
|
26
|
-
subMenu: items,
|
|
27
|
-
},
|
|
28
|
-
]
|
|
29
|
-
: [];
|
|
16
|
+
return subMenuIfAny({
|
|
17
|
+
label: 'Show...',
|
|
18
|
+
icon: VisibilityIcon,
|
|
19
|
+
subMenu: items,
|
|
20
|
+
});
|
|
30
21
|
}
|
package/esm/ui/theme.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ type FramesOptions = FrameTuple<PaletteColorOptions>;
|
|
|
14
14
|
declare module '@mui/material/styles' {
|
|
15
15
|
interface Palette extends StringColors {
|
|
16
16
|
/**
|
|
17
|
-
* The primary
|
|
17
|
+
* The primary color where it marks something on the page's own ground,
|
|
18
18
|
* such as a checked box or a selected row. `primary.main` in light mode,
|
|
19
|
-
* and the secondary text
|
|
19
|
+
* and the secondary text color in dark mode, where a midnight primary
|
|
20
20
|
* vanishes
|
|
21
21
|
*/
|
|
22
22
|
accent: string;
|
package/esm/ui/theme.js
CHANGED
|
@@ -67,7 +67,7 @@ const baseThemeOptions = {
|
|
|
67
67
|
components: {
|
|
68
68
|
MuiAppBar: {
|
|
69
69
|
// JBrowse's header keeps its brand in dark mode; MUI's default is to
|
|
70
|
-
// flatten it to the paper
|
|
70
|
+
// flatten it to the paper color. A property of the app rather than of
|
|
71
71
|
// one palette — it used to sit on `darkStock` alone, so the theme a
|
|
72
72
|
// reader reaches by picking Dark over the default palette lost the
|
|
73
73
|
// header the old dark theme had. MUI reads this only in dark mode.
|
|
@@ -74,6 +74,7 @@ export declare function useAssemblySelection(session: AbstractSessionModel, loca
|
|
|
74
74
|
getCanonicalRefName2(refName: string): string;
|
|
75
75
|
isValidRefName(refName: string): boolean;
|
|
76
76
|
} & {
|
|
77
|
+
isCircularRefName(refName: string): boolean;
|
|
77
78
|
getRefNamePosition(refName: string): number | undefined;
|
|
78
79
|
getAliasesForRefName(refName: string): string[];
|
|
79
80
|
getRefNameMapForAdapter(adapterConf: {
|
|
@@ -141,6 +142,7 @@ export declare function useAssemblySelection(session: AbstractSessionModel, loca
|
|
|
141
142
|
getCanonicalRefName2(refName: string): string;
|
|
142
143
|
isValidRefName(refName: string): boolean;
|
|
143
144
|
} & {
|
|
145
|
+
isCircularRefName(refName: string): boolean;
|
|
144
146
|
getRefNamePosition(refName: string): number | undefined;
|
|
145
147
|
getAliasesForRefName(refName: string): string[];
|
|
146
148
|
getRefNameMapForAdapter(adapterConf: {
|
|
@@ -20,28 +20,16 @@ export declare function useClearTrackedPointer(): () => void;
|
|
|
20
20
|
* Container-relative mouse position for the overlays that follow the pointer
|
|
21
21
|
* (`Crosshairs`, tooltips), coalesced to one update per frame.
|
|
22
22
|
*
|
|
23
|
-
* The position is measured against the box of
|
|
24
|
-
* bound to, which is what the overlays are positioned in
|
|
25
|
-
* so there is no ref to pass and no way to bind the two to different elements.
|
|
23
|
+
* The position is measured against the box of the element the handlers are
|
|
24
|
+
* bound to, off `currentTarget`, which is what the overlays are positioned in.
|
|
26
25
|
* A display that also hit-tests takes `onMove`, so its hit and its guides come
|
|
27
|
-
* off one measurement in one frame
|
|
28
|
-
* agree.
|
|
26
|
+
* off one measurement in one frame.
|
|
29
27
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* object, all three overlays, and only then the body that actually wanted the
|
|
36
|
-
* coordinate. That is a whole display's chrome repainting because the cursor
|
|
37
|
-
* moved a pixel over it; it cost a full document `Layout` plus three `Paint`s
|
|
38
|
-
* per mousemove on the wiggle displays, back when each display called this hook
|
|
39
|
-
* itself and every one of them had it.
|
|
40
|
-
*
|
|
41
|
-
* So the position is published instead, and whoever wants it calls
|
|
42
|
-
* `useMouseState(mouseTracker)` — from inside the chrome's body, where the
|
|
43
|
-
* overlays live. Re-rendering then starts at the component that reads it.
|
|
44
|
-
* Passing the tracker down a prop is free; passing `mouseState` down is the bug.
|
|
28
|
+
* It returns a `mouseTracker` and not the position: the caller is
|
|
29
|
+
* `DisplayChromeBase`, and position held as state there would re-render the
|
|
30
|
+
* whole chrome on every mouse move. Whoever draws at the cursor calls
|
|
31
|
+
* `useMouseState(mouseTracker)`, so re-rendering starts at that component.
|
|
32
|
+
* Pass the tracker down, never the position.
|
|
45
33
|
*/
|
|
46
34
|
export declare function useMouseTracking(onMove?: (state?: MouseState) => void): {
|
|
47
35
|
mouseTracker: MouseTracker;
|
|
@@ -27,16 +27,11 @@ function createMouseStore() {
|
|
|
27
27
|
/**
|
|
28
28
|
* Drop the tracked pointer, published by whoever bound the handlers.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* at the coordinate the pointer had when the menu opened, wherever the pointer
|
|
36
|
-
* has since gone.
|
|
37
|
-
*
|
|
38
|
-
* `ContextMenu` calls this on close, which is why the default is a no-op: a menu
|
|
39
|
-
* raised outside a display's chrome has no tracked pointer to drop.
|
|
30
|
+
* A menu portalled to the body opens under the cursor with no move, and
|
|
31
|
+
* closing it detaches the hover chain, so the display it covered never gets a
|
|
32
|
+
* `mouseleave` and its overlays keep drawing where the menu opened.
|
|
33
|
+
* `ContextMenu` calls this on close; the default is a no-op for a menu raised
|
|
34
|
+
* outside a display's chrome.
|
|
40
35
|
*/
|
|
41
36
|
const ClearTrackedPointerContext = createContext(() => { });
|
|
42
37
|
export const ClearTrackedPointerProvider = ClearTrackedPointerContext.Provider;
|
|
@@ -47,44 +42,25 @@ export function useClearTrackedPointer() {
|
|
|
47
42
|
* Container-relative mouse position for the overlays that follow the pointer
|
|
48
43
|
* (`Crosshairs`, tooltips), coalesced to one update per frame.
|
|
49
44
|
*
|
|
50
|
-
* The position is measured against the box of
|
|
51
|
-
* bound to, which is what the overlays are positioned in
|
|
52
|
-
* so there is no ref to pass and no way to bind the two to different elements.
|
|
45
|
+
* The position is measured against the box of the element the handlers are
|
|
46
|
+
* bound to, off `currentTarget`, which is what the overlays are positioned in.
|
|
53
47
|
* A display that also hit-tests takes `onMove`, so its hit and its guides come
|
|
54
|
-
* off one measurement in one frame
|
|
55
|
-
* agree.
|
|
56
|
-
*
|
|
57
|
-
* **It returns a `mouseTracker` rather than the position, and that is the
|
|
58
|
-
* load-bearing part.** Its one caller is `DisplayChromeBase`, which owns the
|
|
59
|
-
* container the handlers bind to — so if the position were state here, every
|
|
60
|
-
* mouse move would re-render the chrome itself (re-running
|
|
61
|
-
* `useRenderingBackend`), the status container with a fresh inline `style`
|
|
62
|
-
* object, all three overlays, and only then the body that actually wanted the
|
|
63
|
-
* coordinate. That is a whole display's chrome repainting because the cursor
|
|
64
|
-
* moved a pixel over it; it cost a full document `Layout` plus three `Paint`s
|
|
65
|
-
* per mousemove on the wiggle displays, back when each display called this hook
|
|
66
|
-
* itself and every one of them had it.
|
|
48
|
+
* off one measurement in one frame.
|
|
67
49
|
*
|
|
68
|
-
*
|
|
69
|
-
* `
|
|
70
|
-
*
|
|
71
|
-
*
|
|
50
|
+
* It returns a `mouseTracker` and not the position: the caller is
|
|
51
|
+
* `DisplayChromeBase`, and position held as state there would re-render the
|
|
52
|
+
* whole chrome on every mouse move. Whoever draws at the cursor calls
|
|
53
|
+
* `useMouseState(mouseTracker)`, so re-rendering starts at that component.
|
|
54
|
+
* Pass the tracker down, never the position.
|
|
72
55
|
*/
|
|
73
56
|
export function useMouseTracking(onMove) {
|
|
74
57
|
const rafRef = useRef(undefined);
|
|
75
58
|
const storeRef = useRef(undefined);
|
|
76
59
|
storeRef.current ??= createMouseStore();
|
|
77
60
|
const store = storeRef.current;
|
|
78
|
-
// Reached through a ref
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
// Reading the latest is also the better answer for the frame callback, which
|
|
82
|
-
// runs after the render whose closure scheduled it.
|
|
83
|
-
//
|
|
84
|
-
// Written in an effect rather than during render: a render React discards must
|
|
85
|
-
// not leave this pointing at a callback from it. Nothing can read it before
|
|
86
|
-
// the first commit — both users are event/effect callbacks — and `useRef`'s
|
|
87
|
-
// initial value covers the first commit itself.
|
|
61
|
+
// Reached through a ref so `handleMouseLeave` is identity-stable (an effect
|
|
62
|
+
// depends on it), and written in an effect so a render React discards cannot
|
|
63
|
+
// leave it pointing at that render's callback.
|
|
88
64
|
const onMoveRef = useRef(onMove);
|
|
89
65
|
useEffect(() => {
|
|
90
66
|
onMoveRef.current = onMove;
|
|
@@ -92,11 +68,10 @@ export function useMouseTracking(onMove) {
|
|
|
92
68
|
/**
|
|
93
69
|
* Drop the published position and tell `onMove` the pointer is gone.
|
|
94
70
|
*
|
|
95
|
-
* Bound as the container's `onMouseLeave
|
|
96
|
-
* cases `mouseleave` cannot report: the container being
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* Identity-stable for both.
|
|
71
|
+
* Bound as the container's `onMouseLeave`, and called directly for the three
|
|
72
|
+
* cases `mouseleave` cannot report: the container being removed, a portalled
|
|
73
|
+
* menu closing over it, and the pointer moving onto a portalled overlay.
|
|
74
|
+
* `DisplayChromeBase` makes all three calls. Identity-stable.
|
|
100
75
|
*/
|
|
101
76
|
const handleMouseLeave = useCallback(() => {
|
|
102
77
|
if (rafRef.current) {
|
|
@@ -107,28 +82,14 @@ export function useMouseTracking(onMove) {
|
|
|
107
82
|
onMoveRef.current?.(undefined);
|
|
108
83
|
}, [store]);
|
|
109
84
|
const handleMouseMove = (event) => {
|
|
110
|
-
// An overlay portaled out of the container still *bubbles* its React events
|
|
111
|
-
// here, even though its DOM node is not a descendant — so the coordinate
|
|
112
|
-
// would be measured against a box the pointer isn't in. HiC guarded this by
|
|
113
|
-
// hand (its resolution dropdown and legend portal); it is a hazard for any
|
|
114
|
-
// display with a portaled overlay, and several have one, so the guard lives
|
|
115
|
-
// here and applies to all of them. Treated as a leave: the pointer is over
|
|
116
|
-
// something else, and the guides should drop rather than freeze.
|
|
117
|
-
const { target } = event;
|
|
118
|
-
if (target instanceof Node && !event.currentTarget.contains(target)) {
|
|
119
|
-
handleMouseLeave();
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
85
|
if (rafRef.current) {
|
|
123
86
|
cancelAnimationFrame(rafRef.current);
|
|
124
87
|
}
|
|
125
88
|
const clientX = event.clientX;
|
|
126
89
|
const clientY = event.clientY;
|
|
127
|
-
// Captured here
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
// measures as a zero rect, and would publish the client point as if the
|
|
131
|
-
// pointer were at the origin of a box that is gone.
|
|
90
|
+
// Captured here: React clears `currentTarget` once the handler returns. A
|
|
91
|
+
// display unmounted before the frame measures as a zero rect, hence the
|
|
92
|
+
// `isConnected` check.
|
|
132
93
|
const container = event.currentTarget;
|
|
133
94
|
rafRef.current = requestAnimationFrame(() => {
|
|
134
95
|
if (container.isConnected) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PopoverActions } from '@mui/material';
|
|
2
|
+
/**
|
|
3
|
+
* Props that move a MUI Menu's opening focus to after the menu is placed.
|
|
4
|
+
*
|
|
5
|
+
* MUI focuses the first row while the menu mounts, before Popover writes the
|
|
6
|
+
* paper's position, so the focused row still sits at the viewport's top-left.
|
|
7
|
+
* Firefox scrolls every enclosing frame to reveal a focused element, so a page
|
|
8
|
+
* that embeds JBrowse in an iframe jumped to the frame's top whenever a menu
|
|
9
|
+
* opened with that top scrolled out of view.
|
|
10
|
+
*
|
|
11
|
+
* The `onEntering` returned here places the paper through Popover's
|
|
12
|
+
* `updatePosition`, then focuses the first row without scrolling anything.
|
|
13
|
+
*/
|
|
14
|
+
export declare function usePlacedMenuFocus(): {
|
|
15
|
+
action: import("react").RefObject<PopoverActions | null>;
|
|
16
|
+
autoFocus: boolean;
|
|
17
|
+
disableAutoFocus: boolean;
|
|
18
|
+
onEntering: (paper: HTMLElement) => void;
|
|
19
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
const FIRST_ROW = '[role^="menuitem"]:not(.Mui-disabled)';
|
|
3
|
+
/**
|
|
4
|
+
* Props that move a MUI Menu's opening focus to after the menu is placed.
|
|
5
|
+
*
|
|
6
|
+
* MUI focuses the first row while the menu mounts, before Popover writes the
|
|
7
|
+
* paper's position, so the focused row still sits at the viewport's top-left.
|
|
8
|
+
* Firefox scrolls every enclosing frame to reveal a focused element, so a page
|
|
9
|
+
* that embeds JBrowse in an iframe jumped to the frame's top whenever a menu
|
|
10
|
+
* opened with that top scrolled out of view.
|
|
11
|
+
*
|
|
12
|
+
* The `onEntering` returned here places the paper through Popover's
|
|
13
|
+
* `updatePosition`, then focuses the first row without scrolling anything.
|
|
14
|
+
*/
|
|
15
|
+
export function usePlacedMenuFocus() {
|
|
16
|
+
const action = useRef(null);
|
|
17
|
+
return {
|
|
18
|
+
action,
|
|
19
|
+
autoFocus: false,
|
|
20
|
+
disableAutoFocus: true,
|
|
21
|
+
onEntering: (paper) => {
|
|
22
|
+
action.current?.updatePosition();
|
|
23
|
+
paper
|
|
24
|
+
.querySelector(FIRST_ROW)
|
|
25
|
+
?.focus({ preventScroll: true });
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -4,9 +4,11 @@ import type { Instance } from '@jbrowse/mobx-state-tree';
|
|
|
4
4
|
/**
|
|
5
5
|
* #stateModel Base1DView
|
|
6
6
|
* #category general
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Holds a one-dimensional axis of displayed regions, with its zoom and scroll
|
|
8
|
+
* offset, for views other than the linear genome view, such as the two axes of
|
|
9
|
+
* the dotplot.
|
|
10
|
+
*
|
|
11
|
+
* Its page sits under General because it is not a pluggable view type.
|
|
10
12
|
*/
|
|
11
13
|
declare const Base1DView: import("@jbrowse/mobx-state-tree").IModelType<{
|
|
12
14
|
id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
@@ -7,9 +7,11 @@ import { ElementId } from './types/mst.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* #stateModel Base1DView
|
|
9
9
|
* #category general
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Holds a one-dimensional axis of displayed regions, with its zoom and scroll
|
|
11
|
+
* offset, for views other than the linear genome view, such as the two axes of
|
|
12
|
+
* the dotplot.
|
|
13
|
+
*
|
|
14
|
+
* Its page sits under General because it is not a pluggable view type.
|
|
13
15
|
*/
|
|
14
16
|
const Base1DView = types
|
|
15
17
|
.model('Base1DView', {
|
package/esm/util/SvgCanvas.js
CHANGED
|
@@ -175,7 +175,7 @@ export class SvgCanvas {
|
|
|
175
175
|
// treats as the same rect anchored at `x-w`) is NOT normalized here — SVG
|
|
176
176
|
// would emit `width="-w"` and silently not render. Callers must pass a
|
|
177
177
|
// non-negative size; spans resolve both edges and take
|
|
178
|
-
// `left = min(x1,x2)` / `w = abs(x2-x1)
|
|
178
|
+
// `left = min(x1,x2)` / `w = abs(x2-x1)`, the
|
|
179
179
|
// same convention that keeps reversed blocks correct.
|
|
180
180
|
transformRect(x, y, w, h) {
|
|
181
181
|
const [tx, ty] = this.transformPoint(this.a < 0 ? x + w : x, this.d < 0 ? y + h : y);
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* The field an aggregate op writes: `as` where named, else `count` for a
|
|
3
|
-
* count, else `<op>_<field>`. Imports nothing, so the validator's copy of the
|
|
4
|
-
* mark rule list carries it unchanged.
|
|
5
|
-
*/
|
|
6
|
-
export declare function aggregateFieldName({ op, field, as, }: {
|
|
7
|
-
op: string;
|
|
8
|
-
field?: string;
|
|
9
|
-
as?: string;
|
|
10
|
-
}): string;
|
|
1
|
+
export { aggregateFieldName } from './stepOutputs.ts';
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* The field an aggregate op writes: `as` where named, else `count` for a
|
|
3
|
-
* count, else `<op>_<field>`. Imports nothing, so the validator's copy of the
|
|
4
|
-
* mark rule list carries it unchanged.
|
|
5
|
-
*/
|
|
6
|
-
export function aggregateFieldName({ op, field, as, }) {
|
|
7
|
-
return as || (op === 'count' || !field ? op : `${op}_${field}`);
|
|
8
|
-
}
|
|
1
|
+
export { aggregateFieldName } from './stepOutputs.js';
|
package/esm/util/analytics.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyConfigurationModel, TrackConfigEntry } from '../configuration/index.ts';
|
|
2
|
+
import type { ActivitySession } from './sessionActivity.ts';
|
|
2
3
|
declare global {
|
|
3
4
|
interface Window {
|
|
4
5
|
ga?: (...args: unknown[]) => void;
|
|
@@ -12,14 +13,10 @@ interface AnalyticsRootModel {
|
|
|
12
13
|
name?: string;
|
|
13
14
|
}[];
|
|
14
15
|
};
|
|
15
|
-
session?:
|
|
16
|
-
sessionTracks: {
|
|
17
|
-
type: string;
|
|
18
|
-
}[];
|
|
19
|
-
views: unknown[];
|
|
20
|
-
};
|
|
16
|
+
session?: ActivitySession;
|
|
21
17
|
version: string;
|
|
22
18
|
}
|
|
19
|
+
export declare function urlParamNames(search: string): string;
|
|
23
20
|
type AnalyticsRootModelWithConfig = AnalyticsRootModel & {
|
|
24
21
|
jbrowse: {
|
|
25
22
|
configuration: AnyConfigurationModel;
|
|
@@ -27,5 +24,6 @@ type AnalyticsRootModelWithConfig = AnalyticsRootModel & {
|
|
|
27
24
|
};
|
|
28
25
|
export declare function writeAWSAnalytics(rootModel: AnalyticsRootModel, initialTimestamp: number, sessionQuery?: string | null): Promise<void>;
|
|
29
26
|
export declare function writeGAAnalytics(rootModel: AnalyticsRootModel, initialTimestamp: number): Promise<void>;
|
|
27
|
+
export declare function writeAWSSessionEnd(): Promise<void>;
|
|
30
28
|
export declare function doAnalytics(rootModel: AnalyticsRootModelWithConfig | undefined, initialTimestamp: number, initialSessionQuery: string | null | undefined): void;
|
|
31
29
|
export {};
|
package/esm/util/analytics.js
CHANGED
|
@@ -1,14 +1,58 @@
|
|
|
1
1
|
import { effectiveRenderer, getGraphicsCapabilities, } from '@jbrowse/render-core/graphicsCapabilities';
|
|
2
2
|
import { readConfObject } from '../configuration/index.js';
|
|
3
3
|
import { isElectron, rIC } from '../util/index.js';
|
|
4
|
+
import { createSessionActivity, describeSession, tallyTypes, } from './sessionActivity.js';
|
|
4
5
|
import { getConfAssemblyNamesOrNone } from './tracks.js';
|
|
6
|
+
const analyticsUrl = 'https://analytics.jbrowse.org/api/v1';
|
|
7
|
+
// Ties a page load's end reports to its start report. It lives in memory only,
|
|
8
|
+
// so a reload gets a new one and nothing follows a user from load to load.
|
|
9
|
+
let pageLoadId;
|
|
10
|
+
function getPageLoadId() {
|
|
11
|
+
pageLoadId ??=
|
|
12
|
+
typeof crypto.randomUUID === 'function'
|
|
13
|
+
? crypto.randomUUID()
|
|
14
|
+
: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
15
|
+
return pageLoadId;
|
|
16
|
+
}
|
|
17
|
+
// Names only, and only JBrowse's own: says whether a load was a link to a
|
|
18
|
+
// location or a set of tracks without saying which. Read when this module
|
|
19
|
+
// loads, because jbrowse-web folds `loc`, `tracks` and `assembly` into a
|
|
20
|
+
// `session` parameter before the report goes out.
|
|
21
|
+
const knownUrlParams = [
|
|
22
|
+
'assembly',
|
|
23
|
+
'config',
|
|
24
|
+
'highlight',
|
|
25
|
+
'loc',
|
|
26
|
+
'nav',
|
|
27
|
+
'session',
|
|
28
|
+
'sessionName',
|
|
29
|
+
'sessionTracks',
|
|
30
|
+
'tracklist',
|
|
31
|
+
'tracks',
|
|
32
|
+
];
|
|
33
|
+
export function urlParamNames(search) {
|
|
34
|
+
const params = new URLSearchParams(search);
|
|
35
|
+
return knownUrlParams.filter(name => params.has(name)).join(',');
|
|
36
|
+
}
|
|
37
|
+
const initialUrlParams = typeof window === 'undefined' ? '' : urlParamNames(window.location.search);
|
|
38
|
+
function sessionTrackTypeCounts(session) {
|
|
39
|
+
const counts = {};
|
|
40
|
+
for (const track of session?.sessionTracks ?? []) {
|
|
41
|
+
const key = `sessionTrack-types-${track.type}`;
|
|
42
|
+
counts[key] = (counts[key] ?? 0) + 1;
|
|
43
|
+
}
|
|
44
|
+
return counts;
|
|
45
|
+
}
|
|
46
|
+
async function send(stats, init) {
|
|
47
|
+
const qs = new URLSearchParams(Object.entries(stats).map(([key, value]) => [key, String(value)])).toString();
|
|
48
|
+
await fetch(`${analyticsUrl}?${qs}`, init);
|
|
49
|
+
}
|
|
5
50
|
// Both writers are fire-and-forget from several call sites, so they swallow
|
|
6
51
|
// their own failures rather than rejecting: a floating rejected promise trips
|
|
7
52
|
// the webpack-dev-server overlay (it listens for unhandledrejection), and an
|
|
8
53
|
// analytics ping is never worth interrupting a session for.
|
|
9
54
|
export async function writeAWSAnalytics(rootModel, initialTimestamp, sessionQuery) {
|
|
10
55
|
try {
|
|
11
|
-
const url = 'https://analytics.jbrowse.org/api/v1';
|
|
12
56
|
const multiAssemblyTracks = rootModel.jbrowse.tracks.filter(track => getConfAssemblyNamesOrNone(track).length > 1).length;
|
|
13
57
|
// The rung createGpuHal built where a display has built one by idle time,
|
|
14
58
|
// else the ladder's prediction with any page-wide pin applied — so a
|
|
@@ -25,8 +69,11 @@ export async function writeAWSAnalytics(rootModel, initialTimestamp, sessionQuer
|
|
|
25
69
|
const softwareRendering = capabilities.softwareWebgl ?? 'unknown';
|
|
26
70
|
const { jbrowse: config, session, version: ver } = rootModel;
|
|
27
71
|
const { tracks, assemblies, plugins } = config;
|
|
72
|
+
const shape = describeSession(session);
|
|
28
73
|
// stats to be recorded in db
|
|
29
74
|
const stats = {
|
|
75
|
+
event: 'start',
|
|
76
|
+
sid: getPageLoadId(),
|
|
30
77
|
ver,
|
|
31
78
|
'plugins-count': plugins?.length ?? 0,
|
|
32
79
|
'plugin-names': plugins?.map(p => p.name).join(','),
|
|
@@ -34,6 +81,9 @@ export async function writeAWSAnalytics(rootModel, initialTimestamp, sessionQuer
|
|
|
34
81
|
'tracks-count': tracks.length,
|
|
35
82
|
'session-tracks-count': session?.sessionTracks.length ?? 0,
|
|
36
83
|
'open-views': session?.views.length ?? 0,
|
|
84
|
+
'view-types': tallyTypes(shape.viewTypes),
|
|
85
|
+
'open-track-types': tallyTypes(shape.trackTypes),
|
|
86
|
+
'url-params': initialUrlParams,
|
|
37
87
|
'synteny-tracks-count': multiAssemblyTracks,
|
|
38
88
|
// No `saved-sessions-count`: it counted localStorage keys matching
|
|
39
89
|
// `localSaved-`, a format nothing has written since autosaved sessions
|
|
@@ -62,14 +112,8 @@ export async function writeAWSAnalytics(rootModel, initialTimestamp, sessionQuer
|
|
|
62
112
|
const key = `track-types-${track.type}`;
|
|
63
113
|
trackTypeCounts[key] = (trackTypeCounts[key] ?? 0) + 1;
|
|
64
114
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const key = `sessionTrack-types-${track.type}`;
|
|
68
|
-
sessionTrackTypeCounts[key] = (sessionTrackTypeCounts[key] ?? 0) + 1;
|
|
69
|
-
}
|
|
70
|
-
Object.assign(stats, trackTypeCounts, sessionTrackTypeCounts);
|
|
71
|
-
const qs = new URLSearchParams(Object.entries(stats).map(([key, value]) => [key, String(value)])).toString();
|
|
72
|
-
await fetch(`${url}?${qs}`);
|
|
115
|
+
Object.assign(stats, trackTypeCounts, sessionTrackTypeCounts(session));
|
|
116
|
+
await send(stats);
|
|
73
117
|
}
|
|
74
118
|
catch (e) {
|
|
75
119
|
console.warn('Failed to write analytics to AWS.', e);
|
|
@@ -109,6 +153,83 @@ export async function writeGAAnalytics(rootModel, initialTimestamp) {
|
|
|
109
153
|
console.warn('Failed to write analytics to GA.', e);
|
|
110
154
|
}
|
|
111
155
|
}
|
|
156
|
+
// What the page load's sessions held while in use, for the end report.
|
|
157
|
+
const activity = createSessionActivity();
|
|
158
|
+
let latestRootModel;
|
|
159
|
+
let endReportsInstalled = false;
|
|
160
|
+
let endReportsSent = 0;
|
|
161
|
+
let lastEndSignature;
|
|
162
|
+
let visibleMs = 0;
|
|
163
|
+
let visibleSince;
|
|
164
|
+
let visibleMsAtLastEnd = 0;
|
|
165
|
+
const maxEndReports = 10;
|
|
166
|
+
const resendAfterVisibleMs = 60_000;
|
|
167
|
+
// The end report says what a session came to hold: the view, track and widget
|
|
168
|
+
// types open when the tab was hidden and those opened at any point before.
|
|
169
|
+
// A tab is hidden many times before it closes and the close itself is not
|
|
170
|
+
// reliably observable, so each hide sends one, numbered by `seq`, when the
|
|
171
|
+
// session changed or another minute was spent on the page. The last one for a
|
|
172
|
+
// `sid` is the session's end.
|
|
173
|
+
export async function writeAWSSessionEnd() {
|
|
174
|
+
try {
|
|
175
|
+
if (!activity.watching || endReportsSent >= maxEndReports) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const seen = activity.stats();
|
|
179
|
+
const signature = JSON.stringify(seen);
|
|
180
|
+
if (signature === lastEndSignature &&
|
|
181
|
+
visibleMs - visibleMsAtLastEnd < resendAfterVisibleMs) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
lastEndSignature = signature;
|
|
185
|
+
visibleMsAtLastEnd = visibleMs;
|
|
186
|
+
endReportsSent += 1;
|
|
187
|
+
const stats = {
|
|
188
|
+
event: 'end',
|
|
189
|
+
sid: getPageLoadId(),
|
|
190
|
+
seq: endReportsSent,
|
|
191
|
+
duration: Math.round(performance.now() / 1000),
|
|
192
|
+
'visible-time': Math.round(visibleMs / 1000),
|
|
193
|
+
...seen,
|
|
194
|
+
electron: isElectron,
|
|
195
|
+
jb2: true,
|
|
196
|
+
};
|
|
197
|
+
try {
|
|
198
|
+
const { session, version } = latestRootModel ?? {};
|
|
199
|
+
stats.ver = version;
|
|
200
|
+
stats['session-tracks-count'] = session?.sessionTracks.length ?? 0;
|
|
201
|
+
Object.assign(stats, sessionTrackTypeCounts(session));
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// root model left its state tree; the accumulated types still go out
|
|
205
|
+
}
|
|
206
|
+
// keepalive lets the request outlive the page it was sent from
|
|
207
|
+
await send(stats, { keepalive: true });
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
console.warn('Failed to write analytics to AWS.', e);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function installEndReports() {
|
|
214
|
+
if (!endReportsInstalled) {
|
|
215
|
+
endReportsInstalled = true;
|
|
216
|
+
if (document.visibilityState === 'visible') {
|
|
217
|
+
visibleSince = performance.now();
|
|
218
|
+
}
|
|
219
|
+
document.addEventListener('visibilitychange', () => {
|
|
220
|
+
if (document.visibilityState === 'hidden') {
|
|
221
|
+
if (visibleSince !== undefined) {
|
|
222
|
+
visibleMs += performance.now() - visibleSince;
|
|
223
|
+
visibleSince = undefined;
|
|
224
|
+
}
|
|
225
|
+
void writeAWSSessionEnd();
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
visibleSince = performance.now();
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
112
233
|
// One pageview per page load, not per pluginManager. jbrowse-web rebuilds the
|
|
113
234
|
// whole pluginManager (and rootModel) whenever plugins change, and StrictMode
|
|
114
235
|
// builds it twice on mount — without this guard each rebuild re-pings AWS and
|
|
@@ -116,9 +237,19 @@ export async function writeGAAnalytics(rootModel, initialTimestamp) {
|
|
|
116
237
|
// growing the document on every plugin install.
|
|
117
238
|
let analyticsSent = false;
|
|
118
239
|
export function doAnalytics(rootModel, initialTimestamp, initialSessionQuery) {
|
|
119
|
-
if (rootModel
|
|
120
|
-
|
|
121
|
-
|
|
240
|
+
if (!rootModel) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// a config that opts out stops the end reports too, whichever config or
|
|
244
|
+
// session started them
|
|
245
|
+
if (readConfObject(rootModel.jbrowse.configuration, 'disableAnalytics')) {
|
|
246
|
+
activity.stop();
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
latestRootModel = rootModel;
|
|
250
|
+
activity.watch(() => rootModel.session);
|
|
251
|
+
installEndReports();
|
|
252
|
+
if (!analyticsSent) {
|
|
122
253
|
analyticsSent = true;
|
|
123
254
|
// writeGAAnalytics injects Google's scripts and writeAWSAnalytics probes
|
|
124
255
|
// graphics capabilities, hundreds of ms of main-thread work together. Idle
|