@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.
Files changed (379) hide show
  1. package/README.md +427 -130
  2. package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.d.ts +3 -2
  3. package/esm/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +5 -3
  4. package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.d.ts +3 -5
  5. package/esm/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +8 -9
  6. package/esm/BaseFeatureWidget/BaseFeatureDetail/CoreDetails.js +8 -13
  7. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -1
  8. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.js +3 -3
  9. package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.d.ts +8 -0
  10. package/esm/BaseFeatureWidget/BaseFeatureDetail/FieldActionsButton.js +24 -0
  11. package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.d.ts +3 -2
  12. package/esm/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +5 -3
  13. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.d.ts +1 -0
  14. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +1 -4
  15. package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.d.ts +16 -0
  16. package/esm/BaseFeatureWidget/BaseFeatureDetail/jexlFilterActions.js +53 -0
  17. package/esm/BaseFeatureWidget/BaseFeatureDetail/util.d.ts +0 -8
  18. package/esm/BaseFeatureWidget/BaseFeatureDetail/util.js +0 -16
  19. package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceContents.js +7 -34
  20. package/esm/BaseFeatureWidget/configSchema.d.ts +1 -1
  21. package/esm/BaseFeatureWidget/formatDetails.d.ts +13 -29
  22. package/esm/BaseFeatureWidget/formatDetails.js +46 -79
  23. package/esm/BaseFeatureWidget/index.d.ts +1 -0
  24. package/esm/BaseFeatureWidget/stateModelFactory.d.ts +35 -28
  25. package/esm/BaseFeatureWidget/stateModelFactory.js +94 -102
  26. package/esm/BaseFeatureWidget/types.d.ts +3 -0
  27. package/esm/BaseFeatureWidget/util.d.ts +0 -3
  28. package/esm/BaseFeatureWidget/util.js +0 -17
  29. package/esm/PluginLoader.d.ts +14 -9
  30. package/esm/PluginLoader.js +34 -26
  31. package/esm/PluginManager.d.ts +4 -4
  32. package/esm/PluginManager.js +1 -1
  33. package/esm/ReExports/coreModules.generated.d.ts +2 -0
  34. package/esm/ReExports/coreModules.generated.js +492 -0
  35. package/esm/ReExports/coreWorkerModules.generated.d.ts +2 -0
  36. package/esm/ReExports/coreWorkerModules.generated.js +453 -0
  37. package/esm/ReExports/frameworkModules.d.ts +2 -0
  38. package/esm/ReExports/frameworkModules.js +67 -0
  39. package/esm/ReExports/frameworkShared.d.ts +12 -0
  40. package/esm/ReExports/frameworkShared.js +16 -0
  41. package/esm/ReExports/frameworkWorkerModules.generated.d.ts +2 -0
  42. package/esm/ReExports/frameworkWorkerModules.generated.js +130 -0
  43. package/esm/ReExports/list.js +493 -79
  44. package/esm/ReExports/modules.d.ts +1 -1
  45. package/esm/ReExports/modules.js +10 -87
  46. package/esm/ReExports/registry.d.ts +1 -0
  47. package/esm/ReExports/registry.js +23 -5
  48. package/esm/ReExports/uiStub.d.ts +2 -1
  49. package/esm/ReExports/uiStub.js +24 -2
  50. package/esm/ReExports/workerModules.js +8 -12
  51. package/esm/TextSearch/TextSearchManager.d.ts +3 -12
  52. package/esm/TextSearch/TextSearchManager.js +22 -10
  53. package/esm/assemblyManager/assembly.d.ts +10 -14
  54. package/esm/assemblyManager/assembly.js +10 -14
  55. package/esm/assemblyManager/assemblyConfigSchema.d.ts +23 -81
  56. package/esm/assemblyManager/assemblyManager.d.ts +10 -16
  57. package/esm/assemblyManager/assemblyManager.js +7 -10
  58. package/esm/assemblyManager/loadRefNameMap.js +3 -3
  59. package/esm/configuration/configurationSchema.d.ts +75 -31
  60. package/esm/configuration/configurationSchema.js +74 -40
  61. package/esm/configuration/configurationSchemaUnion.d.ts +39 -0
  62. package/esm/configuration/configurationSchemaUnion.js +59 -0
  63. package/esm/configuration/configurationSlot.d.ts +37 -12
  64. package/esm/configuration/configurationSlot.js +83 -22
  65. package/esm/configuration/formatAboutConfigSchema.d.ts +7 -21
  66. package/esm/configuration/formatDetailsConfigSchema.d.ts +11 -37
  67. package/esm/configuration/formatDetailsConfigSchema.js +10 -13
  68. package/esm/configuration/getConf.d.ts +17 -9
  69. package/esm/configuration/getConf.js +52 -7
  70. package/esm/configuration/index.d.ts +11 -4
  71. package/esm/configuration/index.js +7 -4
  72. package/esm/configuration/mergeFormatCallbacks.d.ts +6 -7
  73. package/esm/configuration/mergeFormatCallbacks.js +13 -10
  74. package/esm/configuration/readConfObject.d.ts +2 -22
  75. package/esm/configuration/readConfObject.js +15 -49
  76. package/esm/configuration/requirements.d.ts +37 -0
  77. package/esm/configuration/requirements.js +88 -0
  78. package/esm/configuration/schemaRegistry.d.ts +21 -1
  79. package/esm/configuration/schemaRegistry.js +11 -0
  80. package/esm/configuration/schemaTypes.d.ts +3 -0
  81. package/esm/configuration/schemaTypes.js +10 -0
  82. package/esm/configuration/slotFacade.d.ts +35 -4
  83. package/esm/configuration/slotFacade.js +96 -9
  84. package/esm/configuration/snapshotPreprocess.d.ts +27 -0
  85. package/esm/configuration/snapshotPreprocess.js +102 -0
  86. package/esm/configuration/types.d.ts +161 -22
  87. package/esm/data_adapters/BaseAdapter/BaseAdapter.d.ts +2 -2
  88. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +11 -2
  89. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +12 -1
  90. package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +2 -3
  91. package/esm/data_adapters/BaseAdapter/featureDensity.js +2 -3
  92. package/esm/data_adapters/BaseAdapter/index.d.ts +22 -3
  93. package/esm/data_adapters/BaseAdapter/types.d.ts +3 -4
  94. package/esm/data_adapters/BaseAdapter/zoomRange.d.ts +10 -0
  95. package/esm/data_adapters/BaseAdapter/zoomRange.js +1 -0
  96. package/esm/data_adapters/CytobandAdapter/configSchema.d.ts +9 -11
  97. package/esm/data_adapters/getSequenceSubAdapter.d.ts +1 -3
  98. package/esm/data_adapters/getSequenceSubAdapter.js +1 -3
  99. package/esm/pluggableElementTypes/AdapterType.d.ts +7 -7
  100. package/esm/pluggableElementTypes/RpcMethodType.d.ts +1 -1
  101. package/esm/pluggableElementTypes/RpcMethodType.js +3 -8
  102. package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.d.ts +1 -2
  103. package/esm/pluggableElementTypes/TextSearchAdapterType.d.ts +7 -7
  104. package/esm/pluggableElementTypes/index.d.ts +1 -1
  105. package/esm/pluggableElementTypes/index.js +1 -1
  106. package/esm/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +17 -7
  107. package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +45 -48
  108. package/esm/pluggableElementTypes/models/BaseDisplayModel.js +40 -36
  109. package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +10 -13
  110. package/esm/pluggableElementTypes/models/BaseTrackModel.js +6 -6
  111. package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +37 -17
  112. package/esm/pluggableElementTypes/models/BaseViewModel.js +25 -10
  113. package/esm/pluggableElementTypes/models/InternetAccountModel.d.ts +26 -16
  114. package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +1 -1
  115. package/esm/pluggableElementTypes/models/baseConnectionConfig.d.ts +22 -18
  116. package/esm/pluggableElementTypes/models/baseConnectionConfig.js +5 -5
  117. package/esm/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +26 -31
  118. package/esm/pluggableElementTypes/models/baseTrackConfig.d.ts +57 -141
  119. package/esm/pluggableElementTypes/models/baseTrackConfig.js +22 -26
  120. package/esm/pluggableElementTypes/models/components/SaveTrackData.js +2 -2
  121. package/esm/pluggableElementTypes/models/components/fetchTrackData.d.ts +3 -4
  122. package/esm/pluggableElementTypes/models/components/fetchTrackData.js +3 -3
  123. package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.d.ts +15 -7
  124. package/esm/pluggableElementTypes/models/expandTrackConfigShorthand.js +38 -29
  125. package/esm/pluggableElementTypes/models/index.d.ts +1 -2
  126. package/esm/pluggableElementTypes/models/index.js +1 -2
  127. package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.d.ts +3 -3
  128. package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +4 -4
  129. package/esm/pluggableElementTypes/models/saveTrackFileTypes/types.d.ts +3 -3
  130. package/esm/rpc/BaseRpcDriver.d.ts +1 -2
  131. package/esm/rpc/BaseRpcDriver.js +23 -30
  132. package/esm/rpc/MainThreadRpcDriver.d.ts +2 -2
  133. package/esm/rpc/MainThreadRpcDriver.js +13 -8
  134. package/esm/rpc/RpcClient.d.ts +17 -6
  135. package/esm/rpc/RpcClient.js +42 -12
  136. package/esm/rpc/RpcManager.d.ts +8 -10
  137. package/esm/rpc/RpcManager.js +1 -1
  138. package/esm/rpc/RpcRegistry.d.ts +8 -2
  139. package/esm/rpc/RpcServer.d.ts +3 -1
  140. package/esm/rpc/RpcServer.js +19 -12
  141. package/esm/rpc/WebWorkerRpcDriver.d.ts +3 -3
  142. package/esm/rpc/WebWorkerRpcDriver.js +9 -47
  143. package/esm/rpc/byteBudget.d.ts +3 -5
  144. package/esm/rpc/byteBudget.js +4 -4
  145. package/esm/rpc/configSchema.d.ts +7 -21
  146. package/esm/rpc/coreRpcMethods.d.ts +1 -0
  147. package/esm/rpc/coreRpcMethods.js +1 -0
  148. package/esm/rpc/methods/CoreEncodeFeatures.d.ts +6 -5
  149. package/esm/rpc/methods/CoreEncodeFeatures.js +26 -31
  150. package/esm/rpc/methods/CoreGetEncodedFeature.d.ts +13 -0
  151. package/esm/rpc/methods/CoreGetEncodedFeature.js +31 -0
  152. package/esm/rpc/methods/CoreGetExportData.js +2 -2
  153. package/esm/rpc/methods/CoreGetFeatureDensity.js +2 -2
  154. package/esm/rpc/methods/CoreGetFeatures.js +2 -2
  155. package/esm/rpc/methods/CoreGetSequence.js +2 -2
  156. package/esm/rpc/methods/layerFeatures.d.ts +26 -0
  157. package/esm/rpc/methods/layerFeatures.js +40 -0
  158. package/esm/svg/SvgExport.js +3 -4
  159. package/esm/svg/SvgThemeProviders.d.ts +12 -0
  160. package/esm/svg/SvgThemeProviders.js +15 -0
  161. package/esm/svg/exportViewSvg.d.ts +32 -0
  162. package/esm/svg/exportViewSvg.js +13 -0
  163. package/esm/svg/normalizeSvgMarkup.d.ts +7 -0
  164. package/esm/svg/normalizeSvgMarkup.js +99 -0
  165. package/esm/svg/serializeSvg.d.ts +7 -0
  166. package/esm/svg/serializeSvg.js +11 -0
  167. package/esm/svg/svgReady.d.ts +8 -7
  168. package/esm/svg/svgReady.js +8 -7
  169. package/esm/svg/trackNames.d.ts +5 -5
  170. package/esm/svg/trackNames.js +6 -6
  171. package/esm/svg/wrapSvgExport.js +6 -74
  172. package/esm/ui/CascadingMenu.js +83 -86
  173. package/esm/ui/ErrorMessageStackTraceDialog.js +0 -5
  174. package/esm/ui/FileSelector/useInternetAccounts.d.ts +156 -96
  175. package/esm/ui/HoverMenu.d.ts +1 -2
  176. package/esm/ui/HoverMenu.js +6 -3
  177. package/esm/ui/JexlFilterDialog.d.ts +13 -10
  178. package/esm/ui/JexlFilterDialog.js +122 -49
  179. package/esm/ui/JexlFilterRowEditors.d.ts +15 -0
  180. package/esm/ui/JexlFilterRowEditors.js +90 -0
  181. package/esm/ui/LazyBaseTooltip.d.ts +4 -0
  182. package/esm/ui/LazyBaseTooltip.js +9 -0
  183. package/esm/ui/LoadingOverlay.js +3 -1
  184. package/esm/ui/MonospaceTextField.d.ts +2 -1
  185. package/esm/ui/MonospaceTextField.js +21 -19
  186. package/esm/ui/PaletteContext.d.ts +7 -9
  187. package/esm/ui/PaletteContext.js +24 -10
  188. package/esm/ui/RefNameAutocomplete/index.d.ts +1 -2
  189. package/esm/ui/RefNameAutocomplete/index.js +1 -1
  190. package/esm/ui/ScrollChrome.d.ts +6 -9
  191. package/esm/ui/ScrollChrome.js +5 -6
  192. package/esm/ui/ScrollEdgeShadow.d.ts +6 -9
  193. package/esm/ui/ScrollEdgeShadow.js +9 -24
  194. package/esm/ui/SettingsChangesTable.js +3 -3
  195. package/esm/ui/VerticalScrollbar.d.ts +13 -34
  196. package/esm/ui/VerticalScrollbar.js +29 -83
  197. package/esm/ui/ViewLoadingScreen.d.ts +2 -2
  198. package/esm/ui/ViewLoadingScreen.js +3 -3
  199. package/esm/ui/colorScale.d.ts +26 -1
  200. package/esm/ui/colorScale.js +28 -5
  201. package/esm/ui/colors.d.ts +49 -1
  202. package/esm/ui/colors.js +139 -4
  203. package/esm/ui/hoverBoxStyle.d.ts +14 -2
  204. package/esm/ui/hoverBoxStyle.js +17 -2
  205. package/esm/ui/index.d.ts +5 -3
  206. package/esm/ui/index.js +9 -7
  207. package/esm/ui/launchViewMenu.js +3 -3
  208. package/esm/ui/legendSpec.d.ts +2 -0
  209. package/esm/ui/legendSpec.js +3 -0
  210. package/esm/ui/palette.d.ts +0 -1
  211. package/esm/ui/palette.js +3 -27
  212. package/esm/ui/replaceViewAction.d.ts +1 -1
  213. package/esm/ui/replaceViewAction.js +1 -1
  214. package/esm/ui/theme.d.ts +1 -1
  215. package/esm/ui/theme.js +6 -40
  216. package/esm/ui/viewHeaderHeight.d.ts +1 -0
  217. package/esm/ui/viewHeaderHeight.js +1 -0
  218. package/esm/util/Base1DUtils.d.ts +1 -1
  219. package/esm/util/Base1DUtils.js +2 -2
  220. package/esm/util/SvgCanvas.d.ts +15 -13
  221. package/esm/util/SvgCanvas.js +72 -53
  222. package/esm/util/aborting.d.ts +39 -0
  223. package/esm/util/aborting.js +84 -0
  224. package/esm/util/adapterMetadata.d.ts +1 -1
  225. package/esm/util/adapterMetadata.js +6 -6
  226. package/esm/util/addAndShowTrack.d.ts +1 -4
  227. package/esm/util/addRelativeUris.d.ts +10 -2
  228. package/esm/util/addRelativeUris.js +22 -7
  229. package/esm/util/addTrackFromWidget.d.ts +2 -5
  230. package/esm/util/animationAllowed.d.ts +9 -0
  231. package/esm/util/animationAllowed.js +13 -0
  232. package/esm/util/applyRowResizeWheel.d.ts +10 -5
  233. package/esm/util/applyRowResizeWheel.js +10 -21
  234. package/esm/util/bandLayout.d.ts +4 -4
  235. package/esm/util/bandLayout.js +4 -4
  236. package/esm/util/bezierConnector.js +5 -4
  237. package/esm/util/bgzfWorkerPool.d.ts +20 -74
  238. package/esm/util/bgzfWorkerPool.js +20 -74
  239. package/esm/util/cachedSetup.d.ts +1 -1
  240. package/esm/util/cachedSetup.js +2 -2
  241. package/esm/util/categoricalField.d.ts +37 -0
  242. package/esm/util/categoricalField.js +52 -0
  243. package/esm/util/color/cssColorsLevel4.d.ts +1 -0
  244. package/esm/util/color/cssColorsLevel4.js +1 -0
  245. package/esm/util/color/index.d.ts +5 -3
  246. package/esm/util/color/index.js +7 -4
  247. package/esm/util/colorBits.d.ts +1 -2
  248. package/esm/util/colorBits.js +17 -39
  249. package/esm/util/colorRamp.d.ts +27 -1
  250. package/esm/util/colorRamp.js +56 -2
  251. package/esm/util/colorSchemes.d.ts +9 -0
  252. package/esm/util/colorSchemes.js +7 -0
  253. package/esm/util/{createStopTokenRotation.d.ts → createAbortRotation.d.ts} +11 -14
  254. package/esm/util/{createStopTokenRotation.js → createAbortRotation.js} +14 -26
  255. package/esm/util/cssColorParse.d.ts +15 -0
  256. package/esm/util/cssColorParse.js +53 -0
  257. package/esm/util/diagonalizeRegions.d.ts +2 -3
  258. package/esm/util/diagonalizeRegions.js +7 -12
  259. package/esm/util/expandLooseSearchIndex.d.ts +7 -0
  260. package/esm/util/expandLooseSearchIndex.js +25 -0
  261. package/esm/util/featureTransforms.d.ts +30 -3
  262. package/esm/util/featureTransforms.js +233 -36
  263. package/esm/util/fetchAndMaybeUnzip.js +5 -6
  264. package/esm/util/fetchContext.d.ts +5 -6
  265. package/esm/util/fetchContext.js +1 -1
  266. package/esm/util/fetchHub.d.ts +3 -1
  267. package/esm/util/fetchHub.js +2 -2
  268. package/esm/util/fetchSeq.d.ts +2 -3
  269. package/esm/util/fetchSeq.js +2 -2
  270. package/esm/util/fieldReader.d.ts +17 -0
  271. package/esm/util/fieldReader.js +62 -0
  272. package/esm/util/groupKeys.d.ts +75 -0
  273. package/esm/util/groupKeys.js +152 -0
  274. package/esm/util/highlights.d.ts +6 -4
  275. package/esm/util/highlights.js +12 -25
  276. package/esm/util/hooks.d.ts +1 -2
  277. package/esm/util/hooks.js +1 -2
  278. package/esm/util/index.d.ts +3 -3
  279. package/esm/util/index.js +4 -3
  280. package/esm/util/indexCandidates.js +1 -1
  281. package/esm/util/installFetch.d.ts +13 -10
  282. package/esm/util/installFetch.js +11 -10
  283. package/esm/util/installPrerequisiteFetch.d.ts +5 -3
  284. package/esm/util/installPrerequisiteFetch.js +3 -4
  285. package/esm/util/io/index.js +12 -12
  286. package/esm/util/isDataCurrent.d.ts +7 -5
  287. package/esm/util/isDataCurrent.js +9 -6
  288. package/esm/util/jexl.js +24 -21
  289. package/esm/util/jexlFilterRows.d.ts +89 -0
  290. package/esm/util/jexlFilterRows.js +252 -0
  291. package/esm/util/jexlFilters.d.ts +7 -5
  292. package/esm/util/jexlStrings.d.ts +3 -4
  293. package/esm/util/jexlStrings.js +2 -3
  294. package/esm/util/legendCandidates.d.ts +31 -27
  295. package/esm/util/legendCandidates.js +79 -53
  296. package/esm/util/localStorage.js +4 -4
  297. package/esm/util/markEncoding.d.ts +32 -16
  298. package/esm/util/markEncoding.js +177 -150
  299. package/esm/util/markEncodingTypes.d.ts +137 -66
  300. package/esm/util/mstUtils.d.ts +19 -22
  301. package/esm/util/mstUtils.js +19 -22
  302. package/esm/util/numericUtils.d.ts +7 -0
  303. package/esm/util/numericUtils.js +16 -0
  304. package/esm/util/numericValue.d.ts +14 -0
  305. package/esm/util/numericValue.js +34 -0
  306. package/esm/util/openFeatureWidget.js +1 -2
  307. package/esm/util/openViews.d.ts +1 -0
  308. package/esm/util/openViews.js +3 -3
  309. package/esm/util/parseLineByLine.d.ts +3 -4
  310. package/esm/util/parseLineByLine.js +7 -13
  311. package/esm/util/progress.d.ts +21 -21
  312. package/esm/util/progress.js +27 -26
  313. package/esm/util/renameRegions.d.ts +1 -2
  314. package/esm/util/renderToStaticMarkup.js +16 -16
  315. package/esm/util/rxjs.d.ts +7 -8
  316. package/esm/util/rxjs.js +12 -15
  317. package/esm/util/simpleFeature.d.ts +0 -1
  318. package/esm/util/svgColorProps.d.ts +11 -0
  319. package/esm/util/svgColorProps.js +28 -1
  320. package/esm/util/tabix.d.ts +3 -4
  321. package/esm/util/tabix.js +6 -7
  322. package/esm/util/thresholdScale.d.ts +54 -0
  323. package/esm/util/thresholdScale.js +112 -0
  324. package/esm/util/timeGate.d.ts +4 -5
  325. package/esm/util/timeGate.js +4 -5
  326. package/esm/util/trackConfigDelta.d.ts +22 -18
  327. package/esm/util/trackConfigDelta.js +40 -38
  328. package/esm/util/tracks.d.ts +27 -4
  329. package/esm/util/tracks.js +116 -43
  330. package/esm/util/translateTranscript.d.ts +44 -0
  331. package/esm/util/translateTranscript.js +102 -0
  332. package/esm/util/types/index.d.ts +19 -7
  333. package/esm/util/types/services.d.ts +1 -1
  334. package/esm/util/unknownSnapshotKeys.d.ts +15 -0
  335. package/esm/util/unknownSnapshotKeys.js +13 -0
  336. package/esm/util/useFeatureSequence.js +4 -4
  337. package/esm/util/useFetch.d.ts +3 -4
  338. package/esm/util/useFetch.js +5 -6
  339. package/esm/util/usePanelVirtualScroll.d.ts +7 -39
  340. package/esm/util/usePanelVirtualScroll.js +9 -40
  341. package/esm/util/useRowVirtualScroll.d.ts +6 -29
  342. package/esm/util/useRowVirtualScroll.js +8 -49
  343. package/esm/util/useVirtualScrollWheel.d.ts +20 -4
  344. package/esm/util/useVirtualScrollWheel.js +40 -84
  345. package/esm/util/viewHighlights.d.ts +3 -0
  346. package/esm/util/viewHighlights.js +5 -0
  347. package/esm/util/viewStatus.d.ts +24 -15
  348. package/esm/util/viewStatus.js +17 -0
  349. package/esm/util/withLaunchInput.d.ts +1 -1
  350. package/esm/util/withLaunchInput.js +0 -4
  351. package/package.json +26 -12
  352. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.d.ts +0 -80
  353. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/DLGAP3.js +0 -583
  354. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +0 -141
  355. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.js +0 -1116
  356. package/esm/ReExports/BaseFeatureDetails.d.ts +0 -1
  357. package/esm/ReExports/BaseFeatureDetails.js +0 -10
  358. package/esm/ReExports/barrelOnlyNames.d.ts +0 -5
  359. package/esm/ReExports/barrelOnlyNames.js +0 -63
  360. package/esm/ReExports/index.d.ts +0 -1
  361. package/esm/ReExports/index.js +0 -1
  362. package/esm/ReExports/publicTracks.d.ts +0 -1
  363. package/esm/ReExports/publicTracks.js +0 -14
  364. package/esm/ReExports/publicUi.d.ts +0 -4
  365. package/esm/ReExports/publicUi.js +0 -33
  366. package/esm/ReExports/publicUtil.d.ts +0 -1
  367. package/esm/ReExports/publicUtil.js +0 -32
  368. package/esm/ReExports/sharedModules.d.ts +0 -96
  369. package/esm/ReExports/sharedModules.js +0 -66
  370. package/esm/ReExports/workerNamespaceNames.d.ts +0 -11
  371. package/esm/ReExports/workerNamespaceNames.js +0 -275
  372. package/esm/pluggableElementTypes/models/HighlightsMixin.d.ts +0 -51
  373. package/esm/pluggableElementTypes/models/HighlightsMixin.js +0 -78
  374. package/esm/ui/highlightChipReveal.d.ts +0 -32
  375. package/esm/ui/highlightChipReveal.js +0 -39
  376. package/esm/util/adapterConfigKey.d.ts +0 -12
  377. package/esm/util/adapterConfigKey.js +0 -14
  378. package/esm/util/stopToken.d.ts +0 -212
  379. package/esm/util/stopToken.js +0 -438
@@ -1,4 +1,3 @@
1
- import { adapterConfigKey } from './adapterConfigKey.js';
2
1
  import { installFetch } from './installFetch.js';
3
2
  /**
4
3
  * A **prerequisite read**: one RPC about the adapter itself, beside the
@@ -36,7 +35,7 @@ import { installFetch } from './installFetch.js';
36
35
  * nothing; a header is not a load.
37
36
  *
38
37
  * `createAdapterMetadataFetch` keys on the same adapter config and is
39
- * deliberately NOT one of these: no trigger, no stop token and no status,
38
+ * deliberately NOT one of these: no trigger, no signal and no status,
40
39
  * because it is fetched lazily when a details widget opens and the widget opens
41
40
  * on the result. A prerequisite read is the one a display's own fetch waits on.
42
41
  *
@@ -53,7 +52,7 @@ import { installFetch } from './installFetch.js';
53
52
  * Everything the skeleton gives it is the point of going through the skeleton:
54
53
  * the latest-wins rotation (so a superseding read aborts the one it replaced,
55
54
  * and only a superseding read does — a user cancel of the primary fetch cannot
56
- * strand the display the way sharing its token would), the clear at the start,
55
+ * strand the display the way sharing its signal would), the clear at the start,
57
56
  * the currency-guarded error rule, the unconditional `reloadCounter` read that
58
57
  * makes the chrome's Retry re-run this, and the retired status slot that keeps a
59
58
  * failed read from leaving a progress chip up for good.
@@ -65,7 +64,7 @@ export function installPrerequisiteFetch(self, { name, delay, report, gate = ()
65
64
  report,
66
65
  gate: () => !self.isMinimized && gate(),
67
66
  prepare: () => ({ adapterConfig: self.adapterConfig }),
68
- fetchKey: ({ adapterConfig }) => adapterConfigKey(adapterConfig),
67
+ fetchKey: ({ adapterConfig }) => adapterConfig,
69
68
  run: ({ adapterConfig }, ctx) => run(adapterConfig, ctx),
70
69
  commit,
71
70
  setError,
@@ -19,11 +19,14 @@ export function resolveUriLocation(location) {
19
19
  : location;
20
20
  }
21
21
  /**
22
- * The local path a `file:` URI names, or undefined for any other scheme. A
23
- * Windows URL parses as `/C:/data/x.bam`, whose leading slash is part of the URL
24
- * grammar rather than the path.
22
+ * The local path a `file:` URI or a bare absolute path names, or undefined for
23
+ * anything else. A Windows URL parses as `/C:/data/x.bam`, whose leading slash
24
+ * is part of the URL grammar rather than the path.
25
25
  */
26
- function fileUrlToLocalPath(uri) {
26
+ function uriToLocalPath(uri) {
27
+ if (uri.startsWith('/') || /^[a-z]:[\\/]/i.test(uri)) {
28
+ return uri;
29
+ }
27
30
  if (!uri.startsWith('file:')) {
28
31
  return undefined;
29
32
  }
@@ -82,14 +85,11 @@ export function openLocation(location, pluginManager) {
82
85
  // a config that names its files relative to itself found no account at all
83
86
  // and read every one of them unauthenticated.
84
87
  const absoluteLocation = resolveUriLocation(location);
85
- // A file: URI names a path on this machine, not something to fetch. Desktop
86
- // reaches this by way of the shorthand forms: a config.json opened from disk
87
- // carries a baseUri of its own directory, so `{ type: 'BamAdapter', uri:
88
- // 'reads.bam' }` resolves here as file:///dir/reads.bam — and so does every
89
- // sibling the shorthand derived from it (.bai, .fai, .gzi). Reading them as
90
- // localPath keeps that whole chain on the one code path that can open a
91
- // local file, instead of a fetch that no range request survives.
92
- const localPath = fileUrlToLocalPath(absoluteLocation.uri);
88
+ // A file: URI or a bare absolute path names a file on this machine. A
89
+ // config.json opened from disk resolves `uri: 'reads.bam'` against its own
90
+ // directory to file:///dir/reads.bam, and a session built over MCP writes
91
+ // `uri: '/dir/reads.bam'` with no baseUri at all; fetched, either is a 404.
92
+ const localPath = uriToLocalPath(absoluteLocation.uri);
93
93
  if (localPath !== undefined && (isNode || isElectron)) {
94
94
  return openLocation({ localPath, locationType: 'LocalPathLocation' });
95
95
  }
@@ -1,7 +1,9 @@
1
1
  /**
2
- * The signature-based analog of the spatial `viewportWithinLoadedData`
3
- * (MultiRegionDisplayMixin) freshness check, for a display whose liveness is one
4
- * string rather than a per-region coverage map. An `undefined` loaded signature
5
- * is nothing fetched yet, so never current.
2
+ * Whether the key held data was committed under still equals the key a fetch
3
+ * issued now would carry. Keys are values compared structurally, so a stamp
4
+ * that kept its identity short-circuits on `===`, and an `undefined`-valued
5
+ * field or a fieldless class instance is still a distinct state — the two
6
+ * shapes `JSON.stringify` flattened. An `undefined` loaded key is nothing
7
+ * fetched yet, so never current.
6
8
  */
7
- export declare function isDataCurrent(loadedSignature: string | undefined, currentSignature: string | undefined): boolean;
9
+ export declare function isDataCurrent(loaded: unknown, current: unknown): boolean;
@@ -1,9 +1,12 @@
1
+ import { compareStructural } from 'mobx';
1
2
  /**
2
- * The signature-based analog of the spatial `viewportWithinLoadedData`
3
- * (MultiRegionDisplayMixin) freshness check, for a display whose liveness is one
4
- * string rather than a per-region coverage map. An `undefined` loaded signature
5
- * is nothing fetched yet, so never current.
3
+ * Whether the key held data was committed under still equals the key a fetch
4
+ * issued now would carry. Keys are values compared structurally, so a stamp
5
+ * that kept its identity short-circuits on `===`, and an `undefined`-valued
6
+ * field or a fieldless class instance is still a distinct state — the two
7
+ * shapes `JSON.stringify` flattened. An `undefined` loaded key is nothing
8
+ * fetched yet, so never current.
6
9
  */
7
- export function isDataCurrent(loadedSignature, currentSignature) {
8
- return loadedSignature !== undefined && loadedSignature === currentSignature;
10
+ export function isDataCurrent(loaded, current) {
11
+ return loaded !== undefined && compareStructural(loaded, current);
9
12
  }
package/esm/util/jexl.js CHANGED
@@ -1,23 +1,10 @@
1
1
  import { Jexl } from '@jbrowse/jexl';
2
+ import { categoricalColor } from '../ui/colors.js';
2
3
  import { randomColor } from './color/index.js';
3
4
  import { colord } from './colord.js';
4
5
  import { jexlFeatureProxy, unwrapFeature } from './simpleFeature.js';
5
6
  export default function JexlF( /* config?: any*/) {
6
7
  const j = new Jexl();
7
- // Memoize compilation on the instance itself. A compiled Expression closes
8
- // over this instance's grammar (its registered functions), so the cache
9
- // belongs here and is naturally per-instance — there is no shared cache that
10
- // could bind an expression to the wrong instance's functions.
11
- const rawCompile = j.compile.bind(j);
12
- const cache = new Map();
13
- j.compile = (code) => {
14
- let expr = cache.get(code);
15
- if (expr === undefined) {
16
- expr = rawCompile(code);
17
- cache.set(code, expr);
18
- }
19
- return expr;
20
- };
21
8
  // someday will make sure all of configs callbacks are added in, including
22
9
  // ones passed in
23
10
  // below are core functions
@@ -31,15 +18,29 @@ export default function JexlF( /* config?: any*/) {
31
18
  return p ? jexlFeatureProxy(p) : undefined;
32
19
  });
33
20
  j.addFunction('id', (feature) => unwrapFeature(feature).id());
21
+ /**
22
+ * #jexlFunction Feature operations - getInherited | getInherited(feature, 'gene_biotype') | the attribute from the feature, or from its nearest ancestor that has it, so a CDS reads its gene's value
23
+ */
24
+ j.addFunction('getInherited', (feature, name) => {
25
+ let cur = unwrapFeature(feature);
26
+ while (cur !== undefined) {
27
+ const value = cur.get(name);
28
+ if (value !== undefined) {
29
+ return value;
30
+ }
31
+ cur = cur.parent?.();
32
+ }
33
+ return undefined;
34
+ });
34
35
  // let user cast a jexl type into a javascript type
35
36
  j.addFunction('cast', (arg) => arg);
36
- // math
37
- // addfunction added in jexl 2.3 but types/jexl still on 2.2
38
- /** #jexlFunction Math functions | max(0, 2) */
39
- j.addFunction('max', Math.max);
40
- /** #jexlFunction Math functions | min(0, 2) */
41
- j.addFunction('min', Math.min);
42
- /** #jexlFunction Math functions | sqrt(4) */
37
+ // jexl's own list-aware min and max take varargs too; a Math.min
38
+ // registration would replace them
39
+ /**
40
+ * #jexlFunction Math functions | max(0, 2)
41
+ * #jexlFunction Math functions | min(feature.INFO.AF)
42
+ * #jexlFunction Math functions | sqrt(4)
43
+ */
43
44
  j.addFunction('sqrt', Math.sqrt);
44
45
  /** #jexlFunction Math functions | ceil(0.5) */
45
46
  j.addFunction('ceil', Math.ceil);
@@ -148,6 +149,8 @@ export default function JexlF( /* config?: any*/) {
148
149
  // color helpers
149
150
  /** #jexlFunction Color functions | randomColor(feature.type) | deterministic color from a string (e.g. a feature type) */
150
151
  j.addFunction('randomColor', randomColor);
152
+ /** #jexlFunction Color functions | categoricalColor(getInherited(feature, 'biotype'), ['protein_coding']) | a palette color per value: the values listed take the palette (an optional third argument) in order, any other value a stable color no listed value paints, a missing one grey */
153
+ j.addFunction('categoricalColor', categoricalColor);
151
154
  // These take and return CSS color *strings*, not Colord objects: a config
152
155
  // `jexl:` expression has no way to construct a Colord, and a color slot
153
156
  // holding one resolves to the invalid-color sentinel rather than a color. So
@@ -0,0 +1,89 @@
1
+ import type { AstNode, Subject } from '@jbrowse/jexl';
2
+ export type JexlFilterFieldType = 'number' | 'text' | 'flag';
3
+ export type JexlFilterField = {
4
+ label: string;
5
+ /** unset for a field whose values may be numbers or text */
6
+ type?: JexlFilterFieldType;
7
+ group?: string;
8
+ description?: string;
9
+ /** holds several values per feature, so a comparison asks whether any does */
10
+ multi?: boolean;
11
+ values?: string[];
12
+ } & ({
13
+ path: string[];
14
+ } | {
15
+ call: string;
16
+ });
17
+ export interface FieldChoice {
18
+ key: string;
19
+ label: string;
20
+ type?: JexlFilterFieldType;
21
+ subject: Subject;
22
+ group?: string;
23
+ description?: string;
24
+ multi?: boolean;
25
+ values?: string[];
26
+ }
27
+ export type RowOp = '>' | '>=' | '<' | '<=' | '==' | '!=' | 'in' | '~' | 'set' | '!set';
28
+ export declare const OPERATORS: Record<JexlFilterFieldType | 'any', {
29
+ op: RowOp;
30
+ label: string;
31
+ }[]>;
32
+ export interface ConditionRow {
33
+ kind: 'condition';
34
+ id: number;
35
+ line?: number;
36
+ field?: FieldChoice;
37
+ op: RowOp;
38
+ value: string | string[];
39
+ }
40
+ export interface TextRow {
41
+ kind: 'text';
42
+ id: number;
43
+ line?: number;
44
+ text: string;
45
+ }
46
+ export type FilterRow = ConditionRow | TextRow;
47
+ /**
48
+ * Rows keep the index of the stored line they came from until one of that
49
+ * line's rows changes, so an untouched line is written back byte-identical.
50
+ */
51
+ export interface FilterRows {
52
+ lines: readonly string[];
53
+ rows: FilterRow[];
54
+ }
55
+ interface Parser {
56
+ parse: (text: string) => AstNode | null;
57
+ }
58
+ export declare function resolveFields(fields: readonly JexlFilterField[]): {
59
+ key: string;
60
+ label: string;
61
+ type: JexlFilterFieldType | undefined;
62
+ group: string | undefined;
63
+ description: string | undefined;
64
+ multi: boolean | undefined;
65
+ values: string[] | undefined;
66
+ subject: Subject;
67
+ }[];
68
+ /**
69
+ * The columns an adapter's metadata describes as `{column: description}`, as
70
+ * a BigBed's autoSql does, less those `fields` already lists. Any other
71
+ * metadata describes none.
72
+ */
73
+ export declare function describedColumns(metadata: unknown, fields: readonly JexlFilterField[]): JexlFilterField[];
74
+ /** A field typed into the picker rather than chosen, read as a dotted path. */
75
+ export declare function typedField(text: string): FieldChoice;
76
+ export declare function stripJexlPrefix(line: string): string;
77
+ export declare function readFilterRows(lines: readonly string[], parser: Parser, choices: readonly FieldChoice[]): FilterRows;
78
+ export declare function addRow(state: FilterRows): FilterRows;
79
+ export declare function replaceRow(state: FilterRows, row: FilterRow): FilterRows;
80
+ export declare function removeRow(state: FilterRows, id: number): FilterRows;
81
+ export declare function withField(row: ConditionRow, field: FieldChoice): ConditionRow;
82
+ export declare function withOp(row: ConditionRow, op: RowOp): ConditionRow;
83
+ /**
84
+ * The stored filters: an untouched line as it was, and every row of an edited
85
+ * line as a line of its own, which is equivalent because lines AND together.
86
+ * Rows left incomplete are dropped.
87
+ */
88
+ export declare function writeFilterRows({ lines, rows }: FilterRows): string[];
89
+ export {};
@@ -0,0 +1,252 @@
1
+ import { callSubject, conditions, pathSubject, print, printCondition, } from '@jbrowse/jexl';
2
+ import { JEXL_PREFIX, ensureJexlPrefix, isJexl } from './jexlStrings.js';
3
+ export const OPERATORS = {
4
+ number: [
5
+ { op: '>', label: '>' },
6
+ { op: '>=', label: '≥' },
7
+ { op: '<', label: '<' },
8
+ { op: '<=', label: '≤' },
9
+ { op: '==', label: '=' },
10
+ { op: '!=', label: '≠' },
11
+ ],
12
+ text: [
13
+ { op: '==', label: 'is' },
14
+ { op: '!=', label: 'is not' },
15
+ { op: 'in', label: 'is one of' },
16
+ { op: '~', label: 'matches' },
17
+ ],
18
+ flag: [
19
+ { op: 'set', label: 'is set' },
20
+ { op: '!set', label: 'is not set' },
21
+ ],
22
+ any: [
23
+ { op: '==', label: 'is' },
24
+ { op: '!=', label: 'is not' },
25
+ { op: '>', label: '>' },
26
+ { op: '>=', label: '≥' },
27
+ { op: '<', label: '<' },
28
+ { op: '<=', label: '≤' },
29
+ { op: 'in', label: 'is one of' },
30
+ { op: '~', label: 'matches' },
31
+ ],
32
+ };
33
+ const ROW = 'feature';
34
+ function subjectKey(subject) {
35
+ return JSON.stringify(subject.kind === 'path'
36
+ ? ['path', ...subject.path]
37
+ : ['call', subject.name, ...subject.args]);
38
+ }
39
+ export function resolveFields(fields) {
40
+ return fields.map(({ label, type, group, description, multi, values, ...source }) => {
41
+ const subject = 'call' in source
42
+ ? callSubject(ROW, source.call)
43
+ : pathSubject(ROW, source.path);
44
+ return {
45
+ key: subjectKey(subject),
46
+ label,
47
+ type,
48
+ group,
49
+ description,
50
+ multi,
51
+ values,
52
+ subject,
53
+ };
54
+ });
55
+ }
56
+ // a feature carries these as refName, start and end
57
+ const BED_LOCUS_COLUMNS = new Set(['chrom', 'chromStart', 'chromEnd']);
58
+ /**
59
+ * The columns an adapter's metadata describes as `{column: description}`, as
60
+ * a BigBed's autoSql does, less those `fields` already lists. Any other
61
+ * metadata describes none.
62
+ */
63
+ export function describedColumns(metadata, fields) {
64
+ const entries = metadata && typeof metadata === 'object' ? Object.entries(metadata) : [];
65
+ const listed = new Set(fields.map(field => field.label));
66
+ return entries.every((entry) => typeof entry[1] === 'string')
67
+ ? entries
68
+ .filter(([name]) => !listed.has(name) && !BED_LOCUS_COLUMNS.has(name))
69
+ .map(([name, description]) => ({
70
+ label: name,
71
+ path: [name],
72
+ description: description || undefined,
73
+ }))
74
+ : [];
75
+ }
76
+ /** A field typed into the picker rather than chosen, read as a dotted path. */
77
+ export function typedField(text) {
78
+ const subject = pathSubject(ROW, text.split('.'));
79
+ return { key: subjectKey(subject), label: text, subject };
80
+ }
81
+ export function stripJexlPrefix(line) {
82
+ return isJexl(line) ? line.slice(JEXL_PREFIX.length) : line;
83
+ }
84
+ /** A field of no known type writes a value that reads as a number as one. */
85
+ function scalar(type, text) {
86
+ const number = Number(text);
87
+ return type === 'number' ||
88
+ (!type && text.trim() !== '' && Number.isFinite(number))
89
+ ? number
90
+ : text;
91
+ }
92
+ function subjectLabel(subject) {
93
+ return subject.kind === 'path'
94
+ ? subject.path
95
+ .map((key, i) => typeof key === 'number' ? `[${key}]` : i === 0 ? key : `.${key}`)
96
+ .join('')
97
+ : print(subject.node);
98
+ }
99
+ function conditionRow(c, choices, id, line) {
100
+ const value = 'value' in c ? c.value : undefined;
101
+ const key = subjectKey(c.subject);
102
+ const field = choices.find(f => f.key === key) ?? {
103
+ key,
104
+ label: subjectLabel(c.subject),
105
+ type: value === undefined ? 'flag' : undefined,
106
+ subject: c.subject,
107
+ };
108
+ const op = c.op;
109
+ const values = value === undefined ? [] : [value].flat();
110
+ const writesBack = (v) => op === '~' ? typeof v === 'string' : scalar(field.type, String(v)) === v;
111
+ return OPERATORS[field.type ?? 'any'].some(o => o.op === op) &&
112
+ values.every(writesBack)
113
+ ? {
114
+ kind: 'condition',
115
+ id,
116
+ line,
117
+ field,
118
+ op,
119
+ value: Array.isArray(value) ? value.map(String) : String(value ?? ''),
120
+ }
121
+ : undefined;
122
+ }
123
+ function parseConditions(text, parser, calls) {
124
+ try {
125
+ return conditions(parser.parse(text), {
126
+ row: ROW,
127
+ accessors: { get: [] },
128
+ calls,
129
+ });
130
+ }
131
+ catch {
132
+ return undefined;
133
+ }
134
+ }
135
+ export function readFilterRows(lines, parser, choices) {
136
+ const calls = choices.flatMap(f => f.subject.kind === 'call' ? [f.subject.name] : []);
137
+ const rows = [];
138
+ for (const [line, stored] of lines.entries()) {
139
+ const text = stripJexlPrefix(stored);
140
+ const id = rows.length;
141
+ const read = parseConditions(text, parser, calls)?.map((c, i) => conditionRow(c, choices, id + i, line));
142
+ rows.push(...(read?.every(row => row !== undefined)
143
+ ? read
144
+ : [{ kind: 'text', id, line, text: text.trim() }]));
145
+ }
146
+ return { lines, rows };
147
+ }
148
+ function nextId(rows) {
149
+ return rows.reduce((max, row) => Math.max(max, row.id + 1), 0);
150
+ }
151
+ function emptyRow(id) {
152
+ return { kind: 'condition', id, op: '==', value: '' };
153
+ }
154
+ export function addRow(state) {
155
+ return { ...state, rows: [...state.rows, emptyRow(nextId(state.rows))] };
156
+ }
157
+ function detach(rows, id) {
158
+ const line = rows.find(row => row.id === id)?.line;
159
+ return line === undefined
160
+ ? rows
161
+ : rows.map(row => (row.line === line ? { ...row, line: undefined } : row));
162
+ }
163
+ export function replaceRow(state, row) {
164
+ return {
165
+ ...state,
166
+ rows: detach(state.rows, row.id).map(r => r.id === row.id ? { ...row, line: undefined } : r),
167
+ };
168
+ }
169
+ export function removeRow(state, id) {
170
+ return {
171
+ ...state,
172
+ rows: detach(state.rows, id).filter(row => row.id !== id),
173
+ };
174
+ }
175
+ export function withField(row, field) {
176
+ const sameType = row.field?.type === field.type;
177
+ const ops = OPERATORS[field.type ?? 'any'];
178
+ return {
179
+ ...row,
180
+ field,
181
+ op: sameType ? row.op : ops[0].op,
182
+ value: sameType ? row.value : '',
183
+ };
184
+ }
185
+ export function withOp(row, op) {
186
+ const { value } = row;
187
+ return {
188
+ ...row,
189
+ op,
190
+ value: op === 'in'
191
+ ? Array.isArray(value)
192
+ ? value
193
+ : value
194
+ ? [value]
195
+ : []
196
+ : Array.isArray(value)
197
+ ? (value[0] ?? '')
198
+ : value,
199
+ };
200
+ }
201
+ function writeCondition({ field, op, value }) {
202
+ if (!field) {
203
+ return undefined;
204
+ }
205
+ const { subject, type } = field;
206
+ const usable = (v) => v.trim() !== '' && (type !== 'number' || Number.isFinite(Number(v)));
207
+ if (op === 'set' || op === '!set') {
208
+ return printCondition({ subject, op });
209
+ }
210
+ if (op === 'in') {
211
+ const list = [value].flat().filter(usable);
212
+ return list.length > 0
213
+ ? printCondition({
214
+ subject,
215
+ op,
216
+ value: list.map(v => scalar(type, v)),
217
+ })
218
+ : undefined;
219
+ }
220
+ const text = [value].flat()[0] ?? '';
221
+ return !usable(text)
222
+ ? undefined
223
+ : op === '~'
224
+ ? printCondition({ subject, op, value: text })
225
+ : printCondition({ subject, op, value: scalar(type, text) });
226
+ }
227
+ function writeRow(row) {
228
+ const text = row.kind === 'text' ? row.text.trim() || undefined : writeCondition(row);
229
+ return text === undefined ? undefined : ensureJexlPrefix(text);
230
+ }
231
+ /**
232
+ * The stored filters: an untouched line as it was, and every row of an edited
233
+ * line as a line of its own, which is equivalent because lines AND together.
234
+ * Rows left incomplete are dropped.
235
+ */
236
+ export function writeFilterRows({ lines, rows }) {
237
+ const out = [];
238
+ let previous;
239
+ for (const row of rows) {
240
+ if (row.line === undefined) {
241
+ const text = writeRow(row);
242
+ if (text !== undefined) {
243
+ out.push(text);
244
+ }
245
+ }
246
+ else if (row.line !== previous) {
247
+ out.push(lines[row.line]);
248
+ }
249
+ previous = row.line;
250
+ }
251
+ return out;
252
+ }
@@ -4,11 +4,13 @@ import type { Reversible } from '../ui/filterMenuItems.ts';
4
4
  * The two-tier feature-filter contract, shared by every display offering a
5
5
  * "Filter by..." row. Two tiers because the setting has two authors:
6
6
  *
7
- * - the **`jexlFilters` config slot** on `baseLinearDisplayConfigSchema`, which
8
- * an admin declares in a track config. It stores expressions **unprefixed**,
9
- * because config-slot values are deferred-evaluation and a stored `jexl:` is
10
- * what marks a slot as a callback — so the prefix goes on at read time, in
11
- * `configuredJexlFilters`.
7
+ * - the **`jexlFilters` config slot**, which an admin declares in a track
8
+ * config. It stores expressions **unprefixed**, because config-slot values
9
+ * are deferred-evaluation and a stored `jexl:` is what marks a slot as a
10
+ * callback — so the prefix goes on at read time, in `configuredJexlFilters`.
11
+ * The slot is `jexlFilterConfigSchemaFields` in display-kit, spread by the
12
+ * canvas base display schema, the mark display schema and the shared
13
+ * multi-sample variant schema — the three whose models read it.
12
14
  * - the **`jexlFiltersSetting` display property**, which the dialog writes and
13
15
  * which stores them already prefixed (the runtime convention). Set — *even to
14
16
  * an empty list* — it replaces the config tier entirely, which is what makes
@@ -1,6 +1,6 @@
1
1
  export interface JexlExpression {
2
2
  eval(context?: Record<string, unknown>): unknown;
3
- _exprStr?: string;
3
+ readonly source?: string;
4
4
  }
5
5
  export interface JexlInstance {
6
6
  compile(code: string): JexlExpression;
@@ -11,9 +11,8 @@ export declare function isJexl(str: unknown): str is string;
11
11
  /** Add the `jexl:` prefix unless the string already carries it. */
12
12
  export declare function ensureJexlPrefix(code: string): string;
13
13
  /**
14
- * Compile a `jexl:...` string to an Expression. Compilation is memoized on the
15
- * jexl instance (see `createJexlInstance`), so this is a thin prefix-stripping
16
- * wrapper.
14
+ * Compile a `jexl:...` string to an Expression. The jexl instance caches
15
+ * compilation, so this only strips the prefix.
17
16
  *
18
17
  * @param str - string of code like `jexl:...`
19
18
  * @param jexl - the instance whose registered functions the expression may call
@@ -8,9 +8,8 @@ export function ensureJexlPrefix(code) {
8
8
  return isJexl(code) ? code : `${JEXL_PREFIX}${code}`;
9
9
  }
10
10
  /**
11
- * Compile a `jexl:...` string to an Expression. Compilation is memoized on the
12
- * jexl instance (see `createJexlInstance`), so this is a thin prefix-stripping
13
- * wrapper.
11
+ * Compile a `jexl:...` string to an Expression. The jexl instance caches
12
+ * compilation, so this only strips the prefix.
14
13
  *
15
14
  * @param str - string of code like `jexl:...`
16
15
  * @param jexl - the instance whose registered functions the expression may call
@@ -1,31 +1,26 @@
1
+ import type { ColorScale } from '../ui/colorScale.ts';
2
+ import type { CategoricalField } from './categoricalField.ts';
1
3
  export interface LegendCandidate {
2
4
  rowIndex: number;
3
- label: string;
5
+ value: string;
4
6
  color: number;
5
7
  }
6
8
  export interface LegendEntry {
7
- label: string;
9
+ values: string[];
8
10
  color: number;
9
11
  }
10
12
  export declare const MAX_LEGEND_ENTRIES = 30;
11
13
  export declare const MAX_LEGEND_CANDIDATES = 1024;
12
14
  /**
13
- * Accumulator for the distinct (row, name, color) combinations a packer walks
14
- * past, in first-seen order and bounded — the small list `unionLegendCandidates`
15
- * derives a key from, so the main thread never re-walks the features. Fed scalar
16
- * by scalar, from the loop that already holds the three values.
17
- *
18
- * Deduped on the whole triple rather than on (row, color): the union takes the
19
- * first NAME it sees for a color, so where that name is already spoken for, the
20
- * second name on that color has to still be in the list to carry it.
21
- *
22
- * A nameless feature contributes nothing, which is the union's rule too — so a
23
- * track whose features have no names ships an empty list rather than one entry
24
- * per feature.
15
+ * Accumulator for the distinct (row, value, color) combinations a packer walks
16
+ * past, in first-seen order and bounded, so the main thread never re-walks the
17
+ * features. Deduped on the whole triple: a row of the union lists every value
18
+ * painted in its color, so a second value on that color has to still be in the
19
+ * list to reach it.
25
20
  */
26
21
  export declare function createLegendCandidateCollector(maxCandidates?: number): {
27
22
  candidates: LegendCandidate[];
28
- add(rowIndex: number, label: string, color: number): void;
23
+ add(rowIndex: number, value: string, color: number): void;
29
24
  };
30
25
  export interface LegendCandidateSource {
31
26
  candidates: readonly LegendCandidate[];
@@ -33,18 +28,27 @@ export interface LegendCandidateSource {
33
28
  }
34
29
  /**
35
30
  * The categorical color key over any number of packed regions: one entry per
36
- * distinct color, labeled by the first name seen in that color, in first-seen
37
- * order.
38
- *
39
- * Keyed by color rather than by name, so each key row is 1:1 with a color — a
40
- * row is normally a toggle and hiding a category hides features BY color, so two
41
- * names sharing one color must collapse to a single row. A name reused across
42
- * two colors keeps its first-seen color.
31
+ * distinct color listing every value painted in it, colors in first-seen
32
+ * order. Keyed by color rather than by value because hiding a category hides
33
+ * features BY color, so two values sharing one color are one row that names
34
+ * both; a value met in two colors stays with the first.
43
35
  *
44
- * `[]` when the data carries no categorical signal: nothing named, or more than
45
- * `maxEntries` distinct colors.
46
- *
47
- * `regions` is consumed lazily, so a caller able to answer without reading any
48
- * of them can pass a generator and have none of them touched.
36
+ * `[]` when there are more than `maxEntries` distinct colors, where the data is
37
+ * not a categorical vocabulary. `regions` is consumed lazily.
49
38
  */
50
39
  export declare function unionLegendCandidates<T>(regions: Iterable<T>, resolve: (region: T) => LegendCandidateSource, maxEntries?: number): LegendEntry[];
40
+ /**
41
+ * The one categorical key a color channel derives from what a worker painted:
42
+ * the union above over the loaded regions, each row a painted color naming
43
+ * every value in it through `field` and ordered by it, and nothing where the
44
+ * rows would say nothing (`legendIsReadable`). A display resolving its own colors hands the
45
+ * candidates its packer recorded; one resolved by `encodeFeatures` hands the
46
+ * entries of the scale tables that came back. Either way the key lists what
47
+ * the painting holds, and a `closed` field's domain besides once anything
48
+ * painted.
49
+ */
50
+ export declare function derivedColorScale<T>(regions: Iterable<T>, resolve: (region: T) => LegendCandidateSource, { id, field, maxItems, }: {
51
+ id: string;
52
+ field: CategoricalField;
53
+ maxItems?: number;
54
+ }): ColorScale[];