react-msaview 7.0.0 → 8.1.0

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 (335) hide show
  1. package/README.md +11 -10
  2. package/bundle/index.js +122 -111
  3. package/bundle/index.js.map +4 -4
  4. package/dist/calculateBlocks.js +5 -3
  5. package/dist/calculateBlocks.js.map +1 -1
  6. package/dist/colorSchemes.js +1 -2
  7. package/dist/colorSchemes.js.map +1 -1
  8. package/dist/columnStats.d.ts +28 -0
  9. package/dist/columnStats.js +34 -0
  10. package/dist/columnStats.js.map +1 -0
  11. package/dist/components/DragHandle.d.ts +3 -2
  12. package/dist/components/DragHandle.js +11 -5
  13. package/dist/components/DragHandle.js.map +1 -1
  14. package/dist/components/Loading.js +2 -8
  15. package/dist/components/Loading.js.map +1 -1
  16. package/dist/components/MSAView.js +17 -6
  17. package/dist/components/MSAView.js.map +1 -1
  18. package/dist/components/MSAViewer.d.ts +64 -7
  19. package/dist/components/MSAViewer.js +128 -23
  20. package/dist/components/MSAViewer.js.map +1 -1
  21. package/dist/components/PortalTooltip.d.ts +11 -0
  22. package/dist/components/PortalTooltip.js +29 -0
  23. package/dist/components/PortalTooltip.js.map +1 -0
  24. package/dist/components/ResizeHandles.js +11 -29
  25. package/dist/components/ResizeHandles.js.map +1 -1
  26. package/dist/components/SequenceTextArea.js +3 -4
  27. package/dist/components/SequenceTextArea.js.map +1 -1
  28. package/dist/components/Track.js +43 -24
  29. package/dist/components/Track.js.map +1 -1
  30. package/dist/components/dialogs/AboutDialog.js +6 -6
  31. package/dist/components/dialogs/AboutDialog.js.map +1 -1
  32. package/dist/components/dialogs/AnnotationFileDialog.js +5 -2
  33. package/dist/components/dialogs/AnnotationFileDialog.js.map +1 -1
  34. package/dist/components/dialogs/ExportSVGDialog.js +6 -4
  35. package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
  36. package/dist/components/dialogs/FeatureDialog.js +8 -3
  37. package/dist/components/dialogs/FeatureDialog.js.map +1 -1
  38. package/dist/components/dialogs/TrackInfoDialog.js +1 -1
  39. package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
  40. package/dist/components/header/GappynessSlider.js +6 -11
  41. package/dist/components/header/GappynessSlider.js.map +1 -1
  42. package/dist/components/header/Header.js +4 -1
  43. package/dist/components/header/Header.js.map +1 -1
  44. package/dist/components/header/LoadWarnings.js +6 -23
  45. package/dist/components/header/LoadWarnings.js.map +1 -1
  46. package/dist/components/header/ScrollZoomIcons.d.ts +6 -0
  47. package/dist/components/header/ScrollZoomIcons.js +35 -0
  48. package/dist/components/header/ScrollZoomIcons.js.map +1 -0
  49. package/dist/components/header/TreeSettingsMenu.js +1 -3
  50. package/dist/components/header/TreeSettingsMenu.js.map +1 -1
  51. package/dist/components/header/UnshareableDataWarning.js +2 -4
  52. package/dist/components/header/UnshareableDataWarning.js.map +1 -1
  53. package/dist/components/header/ZoomControls.js +49 -6
  54. package/dist/components/header/ZoomControls.js.map +1 -1
  55. package/dist/components/header/getAnnotationsMenu.js +3 -6
  56. package/dist/components/header/getAnnotationsMenu.js.map +1 -1
  57. package/dist/components/header/settingsMenuItems.js +12 -9
  58. package/dist/components/header/settingsMenuItems.js.map +1 -1
  59. package/dist/components/import/ImportForm.js +1 -1
  60. package/dist/components/import/ImportForm.js.map +1 -1
  61. package/dist/components/import/util.js +1 -2
  62. package/dist/components/import/util.js.map +1 -1
  63. package/dist/components/minimap/Minimap.js +1 -2
  64. package/dist/components/minimap/Minimap.js.map +1 -1
  65. package/dist/components/msa/AnnotationLegend.js +27 -19
  66. package/dist/components/msa/AnnotationLegend.js.map +1 -1
  67. package/dist/components/msa/MSACanvas.js +2 -4
  68. package/dist/components/msa/MSACanvas.js.map +1 -1
  69. package/dist/components/msa/MSACanvasBlock.js +13 -15
  70. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  71. package/dist/components/msa/MSAMouseoverCanvas.js +2 -1
  72. package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
  73. package/dist/components/msa/domainBandCursor.d.ts +7 -11
  74. package/dist/components/msa/domainBandCursor.js +7 -11
  75. package/dist/components/msa/domainBandCursor.js.map +1 -1
  76. package/dist/components/msa/drawFeatureSpans.d.ts +59 -0
  77. package/dist/components/msa/drawFeatureSpans.js +113 -0
  78. package/dist/components/msa/drawFeatureSpans.js.map +1 -0
  79. package/dist/components/msa/legendRows.d.ts +8 -0
  80. package/dist/components/msa/legendRows.js +16 -0
  81. package/dist/components/msa/legendRows.js.map +1 -0
  82. package/dist/components/msa/msaRaster.d.ts +24 -31
  83. package/dist/components/msa/msaRaster.js +30 -39
  84. package/dist/components/msa/msaRaster.js.map +1 -1
  85. package/dist/components/msa/packDomainLanes.d.ts +20 -0
  86. package/dist/components/msa/packDomainLanes.js +33 -0
  87. package/dist/components/msa/packDomainLanes.js.map +1 -0
  88. package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +3 -1
  89. package/dist/components/msa/renderBoxFeatureCanvasBlock.js +50 -87
  90. package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
  91. package/dist/components/msa/renderHighlights.d.ts +15 -13
  92. package/dist/components/msa/renderHighlights.js +43 -20
  93. package/dist/components/msa/renderHighlights.js.map +1 -1
  94. package/dist/components/msa/renderMSABlock.js +12 -12
  95. package/dist/components/msa/renderMSABlock.js.map +1 -1
  96. package/dist/components/msa/tileColor.js +4 -7
  97. package/dist/components/msa/tileColor.js.map +1 -1
  98. package/dist/components/msa/useMsaBlockMouse.d.ts +5 -3
  99. package/dist/components/msa/useMsaBlockMouse.js +6 -6
  100. package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
  101. package/dist/components/rowpanels/RowPanelBlock.d.ts +9 -0
  102. package/dist/components/rowpanels/RowPanelBlock.js +86 -0
  103. package/dist/components/rowpanels/RowPanelBlock.js.map +1 -0
  104. package/dist/components/rowpanels/RowPanelHeaders.d.ts +12 -0
  105. package/dist/components/rowpanels/RowPanelHeaders.js +38 -0
  106. package/dist/components/rowpanels/RowPanelHeaders.js.map +1 -0
  107. package/dist/components/{msa/ColumnStats.d.ts → rowpanels/RowPanels.d.ts} +2 -2
  108. package/dist/components/rowpanels/RowPanels.js +32 -0
  109. package/dist/components/rowpanels/RowPanels.js.map +1 -0
  110. package/dist/components/rowpanels/headerLayout.d.ts +1 -0
  111. package/dist/components/rowpanels/headerLayout.js +5 -0
  112. package/dist/components/rowpanels/headerLayout.js.map +1 -0
  113. package/dist/components/rowpanels/renderFeaturePanel.d.ts +21 -0
  114. package/dist/components/rowpanels/renderFeaturePanel.js +37 -0
  115. package/dist/components/rowpanels/renderFeaturePanel.js.map +1 -0
  116. package/dist/components/rowpanels/renderRowPanel.d.ts +23 -0
  117. package/dist/components/rowpanels/renderRowPanel.js +22 -0
  118. package/dist/components/rowpanels/renderRowPanel.js.map +1 -0
  119. package/dist/components/rowpanels/renderStrip.d.ts +20 -0
  120. package/dist/components/rowpanels/renderStrip.js +26 -0
  121. package/dist/components/rowpanels/renderStrip.js.map +1 -0
  122. package/dist/components/tracks/TrackBlocks.js +3 -5
  123. package/dist/components/tracks/TrackBlocks.js.map +1 -1
  124. package/dist/components/tracks/TrackTooltipContent.d.ts +15 -0
  125. package/dist/components/tracks/TrackTooltipContent.js +109 -0
  126. package/dist/components/tracks/TrackTooltipContent.js.map +1 -0
  127. package/dist/components/tracks/drawTracks.d.ts +4 -4
  128. package/dist/components/tracks/drawTracks.js +25 -39
  129. package/dist/components/tracks/drawTracks.js.map +1 -1
  130. package/dist/components/tracks/useTrackHover.d.ts +22 -0
  131. package/dist/components/tracks/useTrackHover.js +30 -0
  132. package/dist/components/tracks/useTrackHover.js.map +1 -0
  133. package/dist/components/tree/CladeLabels.d.ts +12 -0
  134. package/dist/components/tree/CladeLabels.js +48 -0
  135. package/dist/components/tree/CladeLabels.js.map +1 -0
  136. package/dist/components/tree/TreeBranchMenu.js +1 -1
  137. package/dist/components/tree/TreeBranchMenu.js.map +1 -1
  138. package/dist/components/tree/TreeCanvas.js +5 -4
  139. package/dist/components/tree/TreeCanvas.js.map +1 -1
  140. package/dist/components/tree/TreeCanvasBlock.js +4 -21
  141. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  142. package/dist/components/tree/TreeNodeMenu.js +1 -1
  143. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  144. package/dist/components/tree/TreeOverview.d.ts +14 -0
  145. package/dist/components/tree/TreeOverview.js +75 -0
  146. package/dist/components/tree/TreeOverview.js.map +1 -0
  147. package/dist/components/tree/TreeRuler.js +9 -13
  148. package/dist/components/tree/TreeRuler.js.map +1 -1
  149. package/dist/components/tree/cladeBrackets.d.ts +25 -0
  150. package/dist/components/tree/cladeBrackets.js +51 -0
  151. package/dist/components/tree/cladeBrackets.js.map +1 -0
  152. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +2 -2
  153. package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
  154. package/dist/components/tree/renderTreeCanvas.js +160 -25
  155. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  156. package/dist/components/tree/renderTreeOverview.d.ts +52 -0
  157. package/dist/components/tree/renderTreeOverview.js +138 -0
  158. package/dist/components/tree/renderTreeOverview.js.map +1 -0
  159. package/dist/components/tree/useTreeHover.js +2 -4
  160. package/dist/components/tree/useTreeHover.js.map +1 -1
  161. package/dist/constants.d.ts +16 -0
  162. package/dist/constants.js +52 -22
  163. package/dist/constants.js.map +1 -1
  164. package/dist/createPaletteMap.d.ts +7 -6
  165. package/dist/createPaletteMap.js +10 -9
  166. package/dist/createPaletteMap.js.map +1 -1
  167. package/dist/element.d.ts +13 -0
  168. package/dist/element.js +269 -0
  169. package/dist/element.js.map +1 -0
  170. package/dist/featureFields.d.ts +11 -0
  171. package/dist/featureFields.js +17 -0
  172. package/dist/featureFields.js.map +1 -0
  173. package/dist/flatToTree.js +1 -2
  174. package/dist/flatToTree.js.map +1 -1
  175. package/dist/ggplotPalettes.d.ts +10 -0
  176. package/dist/ggplotPalettes.js +58 -0
  177. package/dist/ggplotPalettes.js.map +1 -1
  178. package/dist/hierarchy.d.ts +27 -0
  179. package/dist/hierarchy.js +66 -9
  180. package/dist/hierarchy.js.map +1 -1
  181. package/dist/index.d.ts +9 -1
  182. package/dist/index.js +5 -3
  183. package/dist/index.js.map +1 -1
  184. package/dist/model/DataModel.js +2 -5
  185. package/dist/model/DataModel.js.map +1 -1
  186. package/dist/model/msaModel.d.ts +3 -2
  187. package/dist/model/msaModel.js +3 -2
  188. package/dist/model/msaModel.js.map +1 -1
  189. package/dist/model/treeModel.d.ts +30 -0
  190. package/dist/model/treeModel.js +37 -1
  191. package/dist/model/treeModel.js.map +1 -1
  192. package/dist/model.d.ts +549 -294
  193. package/dist/model.js +1412 -621
  194. package/dist/model.js.map +1 -1
  195. package/dist/mount.d.ts +11 -0
  196. package/dist/mount.js +22 -0
  197. package/dist/mount.js.map +1 -0
  198. package/dist/neighborJoining.js +8 -32
  199. package/dist/neighborJoining.js.map +1 -1
  200. package/dist/renderToStaticMarkup.d.ts +10 -19
  201. package/dist/renderToStaticMarkup.js +13 -24
  202. package/dist/renderToStaticMarkup.js.map +1 -1
  203. package/dist/renderToSvg.js +180 -56
  204. package/dist/renderToSvg.js.map +1 -1
  205. package/dist/rowCoordinateCalculations.d.ts +4 -6
  206. package/dist/rowCoordinateCalculations.js +4 -6
  207. package/dist/rowCoordinateCalculations.js.map +1 -1
  208. package/dist/scales.d.ts +22 -0
  209. package/dist/scales.js +30 -0
  210. package/dist/scales.js.map +1 -0
  211. package/dist/seqPosToGlobalCol.d.ts +2 -3
  212. package/dist/seqPosToGlobalCol.js +2 -3
  213. package/dist/seqPosToGlobalCol.js.map +1 -1
  214. package/dist/sequenceLogo.d.ts +6 -11
  215. package/dist/sequenceLogo.js +6 -11
  216. package/dist/sequenceLogo.js.map +1 -1
  217. package/dist/stripDefault.d.ts +7 -14
  218. package/dist/stripDefault.js +7 -14
  219. package/dist/stripDefault.js.map +1 -1
  220. package/dist/svgTestUtil.d.ts +186 -70
  221. package/dist/types.d.ts +221 -21
  222. package/dist/umd.d.ts +2 -0
  223. package/dist/umd.js +4 -2
  224. package/dist/umd.js.map +1 -1
  225. package/dist/useCanvasAutorun.d.ts +5 -10
  226. package/dist/useCanvasAutorun.js +5 -10
  227. package/dist/useCanvasAutorun.js.map +1 -1
  228. package/dist/useMsaSvgFigure.d.ts +20 -0
  229. package/dist/useMsaSvgFigure.js +46 -0
  230. package/dist/useMsaSvgFigure.js.map +1 -0
  231. package/dist/useWheelScroll.js +0 -4
  232. package/dist/useWheelScroll.js.map +1 -1
  233. package/dist/util.d.ts +5 -6
  234. package/dist/util.js +13 -6
  235. package/dist/util.js.map +1 -1
  236. package/dist/version.d.ts +1 -1
  237. package/dist/version.js +1 -1
  238. package/package.json +19 -12
  239. package/src/calculateBlocks.ts +5 -3
  240. package/src/colorSchemes.ts +1 -2
  241. package/src/columnStats.ts +58 -0
  242. package/src/components/DragHandle.tsx +18 -7
  243. package/src/components/Loading.tsx +4 -36
  244. package/src/components/MSAView.tsx +19 -5
  245. package/src/components/MSAViewer.tsx +240 -28
  246. package/src/components/PortalTooltip.tsx +47 -0
  247. package/src/components/ResizeHandles.tsx +17 -32
  248. package/src/components/SequenceTextArea.tsx +3 -4
  249. package/src/components/Track.tsx +57 -19
  250. package/src/components/dialogs/AboutDialog.tsx +35 -6
  251. package/src/components/dialogs/AnnotationFileDialog.tsx +10 -1
  252. package/src/components/dialogs/ExportSVGDialog.tsx +8 -3
  253. package/src/components/dialogs/FeatureDialog.tsx +11 -3
  254. package/src/components/dialogs/TrackInfoDialog.tsx +1 -1
  255. package/src/components/header/GappynessSlider.tsx +6 -11
  256. package/src/components/header/Header.tsx +7 -1
  257. package/src/components/header/LoadWarnings.tsx +11 -25
  258. package/src/components/header/ScrollZoomIcons.tsx +52 -0
  259. package/src/components/header/TreeSettingsMenu.tsx +1 -3
  260. package/src/components/header/UnshareableDataWarning.tsx +2 -4
  261. package/src/components/header/ZoomControls.tsx +74 -14
  262. package/src/components/header/getAnnotationsMenu.ts +3 -6
  263. package/src/components/header/settingsMenuItems.ts +13 -8
  264. package/src/components/import/ImportForm.tsx +3 -5
  265. package/src/components/import/ImportFormExamples.tsx +2 -2
  266. package/src/components/import/util.ts +1 -2
  267. package/src/components/minimap/Minimap.tsx +1 -2
  268. package/src/components/msa/AnnotationLegend.tsx +48 -38
  269. package/src/components/msa/MSACanvas.tsx +3 -8
  270. package/src/components/msa/MSACanvasBlock.tsx +13 -16
  271. package/src/components/msa/MSAMouseoverCanvas.tsx +2 -1
  272. package/src/components/msa/domainBandCursor.ts +7 -11
  273. package/src/components/msa/drawFeatureSpans.ts +205 -0
  274. package/src/components/msa/legendRows.ts +24 -0
  275. package/src/components/msa/msaRaster.ts +30 -39
  276. package/src/components/msa/packDomainLanes.ts +36 -0
  277. package/src/components/msa/renderBoxFeatureCanvasBlock.ts +67 -123
  278. package/src/components/msa/renderHighlights.ts +53 -20
  279. package/src/components/msa/renderMSABlock.ts +14 -11
  280. package/src/components/msa/tileColor.ts +4 -7
  281. package/src/components/msa/useMsaBlockMouse.ts +6 -6
  282. package/src/components/rowpanels/RowPanelBlock.tsx +139 -0
  283. package/src/components/rowpanels/RowPanelHeaders.tsx +57 -0
  284. package/src/components/rowpanels/RowPanels.tsx +77 -0
  285. package/src/components/rowpanels/headerLayout.ts +5 -0
  286. package/src/components/rowpanels/renderFeaturePanel.ts +66 -0
  287. package/src/components/rowpanels/renderRowPanel.ts +41 -0
  288. package/src/components/rowpanels/renderStrip.ts +46 -0
  289. package/src/components/tracks/TrackBlocks.tsx +3 -5
  290. package/src/components/tracks/TrackTooltipContent.tsx +156 -0
  291. package/src/components/tracks/drawTracks.ts +25 -50
  292. package/src/components/tracks/useTrackHover.ts +42 -0
  293. package/src/components/tree/CladeLabels.tsx +77 -0
  294. package/src/components/tree/TreeBranchMenu.tsx +1 -2
  295. package/src/components/tree/TreeCanvas.tsx +2 -3
  296. package/src/components/tree/TreeCanvasBlock.tsx +8 -32
  297. package/src/components/tree/TreeNodeMenu.tsx +1 -2
  298. package/src/components/tree/TreeOverview.tsx +106 -0
  299. package/src/components/tree/TreeRuler.tsx +11 -22
  300. package/src/components/tree/cladeBrackets.ts +73 -0
  301. package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +2 -2
  302. package/src/components/tree/renderTreeCanvas.ts +242 -21
  303. package/src/components/tree/renderTreeOverview.ts +212 -0
  304. package/src/components/tree/useTreeHover.ts +2 -4
  305. package/src/constants.ts +61 -22
  306. package/src/createPaletteMap.ts +10 -9
  307. package/src/element.ts +321 -0
  308. package/src/featureFields.ts +19 -0
  309. package/src/flatToTree.ts +1 -2
  310. package/src/ggplotPalettes.ts +60 -0
  311. package/src/hierarchy.ts +77 -9
  312. package/src/index.ts +31 -7
  313. package/src/model/DataModel.ts +2 -5
  314. package/src/model/msaModel.ts +3 -2
  315. package/src/model/treeModel.ts +42 -0
  316. package/src/model.ts +1677 -643
  317. package/src/mount.tsx +32 -0
  318. package/src/neighborJoining.ts +8 -32
  319. package/src/renderToStaticMarkup.ts +13 -24
  320. package/src/renderToSvg.tsx +335 -68
  321. package/src/rowCoordinateCalculations.ts +4 -6
  322. package/src/scales.ts +47 -0
  323. package/src/seqPosToGlobalCol.ts +2 -3
  324. package/src/sequenceLogo.ts +6 -11
  325. package/src/stripDefault.ts +7 -14
  326. package/src/types.ts +260 -45
  327. package/src/umd.ts +4 -2
  328. package/src/useCanvasAutorun.ts +5 -10
  329. package/src/useMsaSvgFigure.ts +72 -0
  330. package/src/useWheelScroll.ts +0 -4
  331. package/src/util.ts +15 -6
  332. package/src/version.ts +1 -1
  333. package/dist/components/msa/ColumnStats.js +0 -42
  334. package/dist/components/msa/ColumnStats.js.map +0 -1
  335. package/src/components/msa/ColumnStats.tsx +0 -54
package/src/scales.ts ADDED
@@ -0,0 +1,47 @@
1
+ import { createPaletteMap } from './createPaletteMap.ts'
2
+ import { paletteNamed } from './ggplotPalettes.ts'
3
+
4
+ import type { LegendEntry } from './types.ts'
5
+
6
+ /** how a channel reads a field: a palette by name, or a color per value */
7
+ export interface ScaleSpec {
8
+ palette?: string
9
+ map?: Record<string, string>
10
+ }
11
+
12
+ export interface ResolvedScale {
13
+ kind: 'categorical'
14
+ colorOf: (value: string) => string | undefined
15
+ legend: LegendEntry[]
16
+ }
17
+
18
+ /**
19
+ * The scale a channel reads its field through. `values` are the field's values,
20
+ * in any order and with repeats; the domain is their distinct values sorted, so
21
+ * a value keeps its color when rows are re-ordered, collapsed or filtered.
22
+ *
23
+ * `{map}` colors the values the producer named and leaves the rest uncolored.
24
+ * `{palette}` takes the colors of a named palette, and a spec with neither
25
+ * takes the ggplot palette of the domain's size. Every scale is categorical
26
+ * today; a continuous one waits for a caller.
27
+ */
28
+ export function resolveScale(
29
+ spec: ScaleSpec | undefined,
30
+ values: Iterable<string>,
31
+ ): ResolvedScale {
32
+ const domain = [...new Set(values)].sort((a, b) => a.localeCompare(b))
33
+ const { map, palette } = spec ?? {}
34
+ const colors = map ?? createPaletteMap(domain, paletteNamed(palette))
35
+ const present = new Set(domain)
36
+ const labels = map ? Object.keys(map).filter(v => present.has(v)) : domain
37
+ return {
38
+ kind: 'categorical',
39
+ colorOf: (value: string) => colors[value],
40
+ // a categorical value is its own label, and the id a legend keys on
41
+ legend: labels.map(value => ({
42
+ id: value,
43
+ label: value,
44
+ color: colors[value]!,
45
+ })),
46
+ }
47
+ }
@@ -2,9 +2,8 @@
2
2
  * The global column of every ungapped sequence position in a row, i.e.
3
3
  * index[seqPos] is the column holding the seqPos-th non-gap character.
4
4
  *
5
- * A row is indexed once and then answers seqPos -> column by lookup, which is
6
- * what makes the domain overlay affordable: it resolves one position per feature
7
- * per row on every redraw, and scanning the row for each would be quadratic.
5
+ * The domain overlay resolves one position per feature per row on every redraw,
6
+ * and scanning the row for each would be quadratic.
8
7
  *
9
8
  * @example
10
9
  * // Row: "A-TG-C" (A at 0, T at 2, G at 3, C at 5)
@@ -19,18 +19,13 @@ export function maxBitsFor(sequenceType: 'dna' | 'rna' | 'amino') {
19
19
  * stack bottom-up in array order.
20
20
  *
21
21
  * Heights follow Schneider & Stephens: the column's information content is
22
- * `log2(alphabet) - H` bits, and each residue takes the share of that its own
23
- * frequency earns. Frequencies come from the non-gap residues only, so a column
24
- * of two residues and eight gaps is read as a two-way choice rather than a
25
- * ten-way one -- otherwise every gappy column would look uninformative for the
26
- * wrong reason.
22
+ * `log2(alphabet) - H` bits, split among residues by frequency. Frequencies
23
+ * count non-gap residues only, so two residues and eight gaps form a two-way
24
+ * choice.
27
25
  *
28
- * The whole stack is then scaled by the non-gap fraction, which plain WebLogo
29
- * does not do. Here it earns its place: the track sits directly under an
30
- * alignment where the gaps are visible, and a column that is 90% gap drawing a
31
- * full-height stack off its one remaining pair of residues reads as a conserved
32
- * site. Scaling makes stack height mean "how much this column tells you about
33
- * the family", matching what the conservation track above it already plots.
26
+ * Unlike plain WebLogo, the stack is then scaled by the non-gap fraction, so a
27
+ * 90%-gap column with one conserved pair does not draw a full-height stack, and
28
+ * stack height matches the conservation track.
34
29
  */
35
30
  export function columnLogoStack(
36
31
  colStats: ColumnCounts,
@@ -9,21 +9,14 @@ import type {
9
9
  /**
10
10
  * `types.stripDefault`, degrading to `types.optional` on hosts that lack it.
11
11
  *
12
- * stripDefault keeps defaulted properties out of snapshots, but it exists only
13
- * in the mobx-state-tree that ships with unreleased @jbrowse/core. This package
14
- * declares `@jbrowse/mobx-state-tree: ^5.0.0`, and inside jbrowse-web the host
15
- * supplies its own copy at runtime -- the plugin bundle externalizes it -- so we
16
- * genuinely do not know which version we are calling until we are running.
12
+ * stripDefault keeps defaulted properties out of snapshots, and only the
13
+ * mobx-state-tree in unreleased @jbrowse/core has it. The plugin bundle
14
+ * externalizes mobx-state-tree, so the host's copy is known only at runtime, and
15
+ * calling a missing stripDefault during model construction makes PluginLoader
16
+ * reject and the whole app show its error page.
17
17
  *
18
- * Calling it where it is absent throws while the model is being constructed,
19
- * which in a plugin bundle means PluginLoader rejects and the entire app renders
20
- * its error page. Losing minimal snapshots is a far better failure than losing
21
- * the session, so this degrades instead.
22
- *
23
- * The two signatures are identical, so behaviour differs only in that defaults
24
- * reappear in snapshots on older hosts (bigger session snapshots and shared
25
- * URLs, nothing incorrect). stripDefaultSnapshot.test.ts still pins the stripped
26
- * behaviour, since dev runs against a version that has it.
18
+ * The signatures are identical; on older hosts, defaults reappear in snapshots
19
+ * and shared URLs. stripDefaultSnapshot.test.ts pins the stripped behaviour.
27
20
  */
28
21
  export function stripDefault<IT extends IAnyType>(
29
22
  type: IT,
package/src/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ResolvedScale, ScaleSpec } from './scales.ts'
1
2
  import type { Annotation } from 'msa-parsers'
2
3
 
3
4
  export interface Accession {
@@ -5,17 +6,26 @@ export interface Accession {
5
6
  name: string
6
7
  description: string
7
8
  }
8
- // which renderer draws a track's content. Every track kind draws into the same
9
- // per-column coordinate space, so the kind picks the draw function rather than
10
- // the geometry -- see drawTracks.ts, which dispatches on it.
9
+ // every kind draws into the same per-column space; drawTracks.ts dispatches on
10
+ // it to pick the draw function
11
11
  export type TrackKind = 'text' | 'bar' | 'logo' | 'arc' | 'ruler'
12
12
 
13
+ /**
14
+ * Which channel the color scheme paints. `fill` colors the cell a residue sits
15
+ * in, `color` colors the letter itself, the same distinction a grammar of
16
+ * graphics draws between a shape's interior and its own ink.
17
+ */
18
+ export type ResidueEncoding = 'fill' | 'color'
19
+
13
20
  export interface BasicTrackModel {
14
21
  id: string
15
22
  name: string
16
23
  associatedRowName?: string
17
24
  height: number
18
25
  kind: TrackKind
26
+ // the model height this track's divider writes, shared with every track
27
+ // carrying the same key. Absent on a track no divider resizes.
28
+ heightKey?: string
19
29
  // hidden until the user asks for it, unless they have already chosen
20
30
  defaultOff?: boolean
21
31
  }
@@ -31,8 +41,8 @@ export interface BarTrackModel extends BasicTrackModel {
31
41
  barColor?: string
32
42
  }
33
43
 
34
- // a pair of columns joined by an arc, already resolved to 0-based visible
35
- // columns -- what the renderer consumes
44
+ // a pair of columns joined by an arc, resolved to 0-based visible columns for
45
+ // the renderer
36
46
  export interface Arc {
37
47
  start: number
38
48
  end: number
@@ -77,11 +87,108 @@ export interface ColumnTrackSpec {
77
87
  height?: number
78
88
  }
79
89
 
80
- // One contiguous run where a row's residues and a structure's line up 1:1.
81
- // Segment-shaped because SIFTS is: a dozen numbers cover what a per-residue
82
- // array would spend kilobytes on, and it makes the refusal rule structural
83
- // rather than a vocabulary -- a position no segment covers is unmapped, and
84
- // there is no status field to disagree with.
90
+ /**
91
+ * A strip panel: one cell per row, colored from a `rowData` field through
92
+ * `scale`, which is ggtree's `gheatmap`. `width` is in pixels and defaults to
93
+ * the row height, and `header` labels the column and defaults to the field.
94
+ * `legend` titles the strip's legend and defaults to the field, and strips
95
+ * naming one title share one legend.
96
+ */
97
+ export interface RowStripSpec {
98
+ kind: 'strip'
99
+ field: string
100
+ scale?: ScaleSpec
101
+ width?: number
102
+ header?: string
103
+ legend?: string
104
+ }
105
+
106
+ /** the channels a `features` panel reads off the feature table */
107
+ export interface FeatureEncodingSpec {
108
+ color?: { field: string; scale?: ScaleSpec }
109
+ label?: string
110
+ }
111
+
112
+ /**
113
+ * Shifts each row so that the first feature named `on` starts at zero, which
114
+ * is gggenes' `make_alignment_dummies`. Only `x: "position"` reads it.
115
+ */
116
+ export interface AlignTransform {
117
+ type: 'align'
118
+ on: string
119
+ }
120
+
121
+ /**
122
+ * A features panel: the GFF's spans per row, as arrows where they carry a
123
+ * strand. `x: "column"` draws them in the alignment's columns, and
124
+ * `x: "position"` in each row's own residue positions on one linear scale, so
125
+ * a genome with no alignment has an x.
126
+ */
127
+ export interface RowFeaturesSpec {
128
+ kind: 'features'
129
+ x: 'column' | 'position'
130
+ width?: number
131
+ header?: string
132
+ encoding?: FeatureEncodingSpec
133
+ transform?: AlignTransform[]
134
+ /** how overlapping features share the row's height; see docs/layers.md */
135
+ position?: 'identity' | 'strandpile'
136
+ }
137
+
138
+ /**
139
+ * A panel left of the alignment on the row scale, the counterpart of
140
+ * ColumnTrackSpec on the column scale. See docs/layers.md
141
+ */
142
+ export type RowPanelSpec = RowStripSpec | RowFeaturesSpec
143
+
144
+ interface ResolvedPanelBase {
145
+ id: string
146
+ header: string
147
+ width: number
148
+ offsetX: number
149
+ legend: LegendEntry[]
150
+ /** the legend this panel's entries go under; absent means the domain key */
151
+ legendTitle?: string
152
+ }
153
+
154
+ /**
155
+ * A strip with its scale resolved: the color each row takes, keyed by row
156
+ * name, and the pixel column the panel draws in.
157
+ */
158
+ export interface ResolvedStripPanel extends ResolvedPanelBase {
159
+ kind: 'strip'
160
+ field: string
161
+ colors: Map<string, string>
162
+ }
163
+
164
+ /** one feature of a features panel, at its pixel span inside the panel */
165
+ export interface RowPanelSpan {
166
+ annotation: Annotation
167
+ xStart: number
168
+ xEnd: number
169
+ lane: number
170
+ laneCount: number
171
+ }
172
+
173
+ /**
174
+ * A features panel with its x mapping and its scale resolved: the spans per
175
+ * row name in panel pixels, the fill and outline of each feature, and the
176
+ * label its `label` channel draws. `field` is the field its color scale reads,
177
+ * which its legend is titled by.
178
+ */
179
+ export interface ResolvedFeaturePanel extends ResolvedPanelBase {
180
+ kind: 'features'
181
+ x: 'column' | 'position'
182
+ field?: string
183
+ spans: Map<string, RowPanelSpan[]>
184
+ colors: Map<Annotation, { fill: string; stroke: string }>
185
+ labels?: Map<Annotation, string>
186
+ }
187
+
188
+ export type ResolvedRowPanel = ResolvedStripPanel | ResolvedFeaturePanel
189
+
190
+ // One contiguous run where a row's residues and a structure's line up 1:1, as
191
+ // SIFTS reports them. A position no segment covers is unmapped.
85
192
  export interface ResidueSegment {
86
193
  rowStart: number
87
194
  rowEnd: number
@@ -90,8 +197,8 @@ export interface ResidueSegment {
90
197
  }
91
198
 
92
199
  // the structure half of a mapping. `id` is whatever the producer calls the
93
- // entry (a PDB id, an AlphaFold accession); `asymId` names the chain, which is
94
- // what distinguishes two mappings onto the same entry
200
+ // entry (a PDB id, an AlphaFold accession); `asymId` names the chain and
201
+ // distinguishes two mappings onto the same entry
95
202
  export interface MappedStructure {
96
203
  id: string
97
204
  kind?: 'experimental' | 'predicted'
@@ -100,21 +207,16 @@ export interface MappedStructure {
100
207
  }
101
208
 
102
209
  /**
103
- * Which residue of which structure a row's residue is, as data. Computed by
104
- * whatever knows how -- SIFTS, an AlphaFold model, a curator -- and carried in
105
- * the snapshot, because the viewer cannot work it out: matching a row to a
106
- * structure by sequence equality fails for a construct with an expression tag,
107
- * a truncation, an engineered residue, or a row that is a subsequence of the
108
- * entry, and it fails in the direction that looks like it worked.
210
+ * The structure residue for each residue of a row, computed outside the viewer
211
+ * (SIFTS, an AlphaFold model, a curator). Sequence equality misplaces tagged
212
+ * constructs, truncations and subsequence rows; see docs/layers.md.
109
213
  *
110
214
  * Positions are 1-based and inclusive on both sides, as GFF and `highlights`
111
215
  * are. Structure positions are `label_seq_id`, the index into the entity's
112
- * SEQRES; author numbering carries insertion codes and stays out.
216
+ * SEQRES; author numbering carries insertion codes and is not used.
113
217
  *
114
218
  * `unobserved` is in structure positions: present in SEQRES with no
115
- * coordinates. Worth distinguishing from unmapped, because "the
116
- * crystallographer could not see it" and "this protein does not have that
117
- * residue" mean different things to a reader.
219
+ * coordinates, as distinct from a residue the structure lacks.
118
220
  */
119
221
  export interface ResidueMapping {
120
222
  row: string
@@ -123,11 +225,9 @@ export interface ResidueMapping {
123
225
  segments: ResidueSegment[]
124
226
  unobserved?: [number, number][]
125
227
  /**
126
- * ungapped length of the row this was computed against. Optional, and worth
127
- * setting: a mapping outlives the alignment it was made for, and pointing at
128
- * residue 58 of a sequence that has since been re-aligned, revised or swapped
129
- * is the failure this whole layer exists to avoid. Declared here, the viewer
130
- * can notice and refuse instead of answering from stale arithmetic.
228
+ * ungapped length of the row this was computed against. When set, the viewer
229
+ * ignores the mapping if the loaded row's length differs, as it does after a
230
+ * re-alignment, revision or swapped sequence.
131
231
  */
132
232
  rowLength?: number
133
233
  generated?: {
@@ -137,25 +237,21 @@ export interface ResidueMapping {
137
237
  }
138
238
  }
139
239
 
140
- // why a mapping, or one segment of it, is not being used. Refusing silently
141
- // leaves a host unable to tell "no structure for this row" from "the mapping
142
- // no longer matches what is loaded", which are different problems with
143
- // different fixes.
240
+ // why a mapping, or one segment of it, is ignored, so a host can tell "no
241
+ // structure for this row" from "the mapping no longer matches what is loaded"
144
242
  export interface ResidueMappingProblem {
145
243
  row: string
146
244
  structureId: string
147
245
  /**
148
- * `mapping` means the whole mapping is out: the evidence is about the row it
149
- * claims, so nothing it says can be trusted. `segment` takes only that
150
- * segment, since the rest of the mapping still describes residues that exist.
246
+ * `mapping` ignores the whole mapping, because the problem concerns its row.
247
+ * `segment` ignores only that segment and keeps the rest.
151
248
  */
152
249
  scope: 'mapping' | 'segment'
153
250
  reason: string
154
251
  }
155
252
 
156
- // what a lookup gives back: the structure residue a row residue is, or the row
157
- // residue a structure residue is. `observed` is false for a residue the
158
- // structure declares but did not resolve.
253
+ // a lookup result in either direction. `observed` is false for a residue in
254
+ // SEQRES with no coordinates.
159
255
  export interface StructureResidue {
160
256
  structure: MappedStructure
161
257
  position: number
@@ -168,29 +264,50 @@ export interface RowResidue {
168
264
  }
169
265
 
170
266
  /**
171
- * One loaded document that the snapshot leaves behind, and how big it is.
172
- * `what` names it the way the import form does, since that is where the reader
173
- * would go to load it differently.
267
+ * One loaded document that the snapshot omits, and its size. `what` uses the
268
+ * import form's names for the documents.
174
269
  */
175
270
  export interface UnshareableData {
176
271
  what: 'alignment' | 'tree' | 'annotations' | 'row metadata' | 'data tracks'
177
272
  bytes: number
178
273
  }
179
274
 
180
- // the overlay annotation itself lives in msa-parsers, alongside the adapters
181
- // that build it. TidyDomainAnnotation is its former name, kept because
182
- // downstream plugins name it in their emitted declarations.
275
+ // Annotation is defined in msa-parsers. Downstream plugins' emitted
276
+ // declarations still name TidyDomainAnnotation.
183
277
  export type { Annotation }
184
278
  export type TidyDomainAnnotation = Annotation
185
279
 
186
280
  // an annotation resolved to the visible column span it is drawn across.
187
- // stackIndex is its position among the bands its row actually draws, which the
188
- // sub-row layout uses to stack boxes.
281
+ // stackIndex is its position in its row's paint order; lane is the sub-row it
282
+ // occupies, out of the laneCount the row's overlaps need.
189
283
  export interface DomainBand {
190
284
  annotation: Annotation
191
285
  startCol: number
192
286
  endCol: number
193
287
  stackIndex: number
288
+ lane: number
289
+ laneCount: number
290
+ }
291
+
292
+ /**
293
+ * One swatch of a categorical color key. `id` is the value the scale read, and
294
+ * `label` is the text drawn beside the swatch.
295
+ */
296
+ export interface LegendEntry {
297
+ id: string
298
+ label: string
299
+ color: string
300
+ }
301
+
302
+ /**
303
+ * A categorical color key, drawn by the on-screen overlay and reserved as a
304
+ * column in the SVG export. `title` names the legend where the viewer draws
305
+ * more than one.
306
+ */
307
+ export interface Legend {
308
+ id: string
309
+ title: string
310
+ entries: LegendEntry[]
194
311
  }
195
312
 
196
313
  /**
@@ -207,6 +324,104 @@ export interface Highlight {
207
324
  color?: string
208
325
  }
209
326
 
327
+ /**
328
+ * What the viewer draws over a clade. `highlight` fills the rows behind it,
329
+ * across the tree and the alignment. `bracket` draws a bar and the clade's
330
+ * `label` in the gutter right of the tip labels. `collapse` and `focus` seed
331
+ * the collapsed list and the subtree in focus at load.
332
+ */
333
+ export type CladeMark = 'highlight' | 'bracket' | 'collapse' | 'focus'
334
+
335
+ /**
336
+ * A clade of the tree and the mark drawn over it. `mrca` names tips whose most
337
+ * recent common ancestor is the clade; `range` names the first and last tip of
338
+ * a run in display order, in either order. `tips` is the leaf count the
339
+ * producer measured, and a clade that resolves to a different count is dropped.
340
+ * `label` names the clade beside a bracket, and a highlight carrying one draws
341
+ * the label without the bar. See docs/layers.md
342
+ */
343
+ export interface Clade {
344
+ mrca?: string[]
345
+ range?: [string, string]
346
+ tips: number
347
+ mark: CladeMark
348
+ color?: string
349
+ label?: string
350
+ }
351
+
352
+ /**
353
+ * A Clade resolved to the rows it covers, with its fill color settled. `color`
354
+ * is the highlight fill; `markColor` is the producer's own color for a bracket
355
+ * bar and its label, unset where the theme's text color stands. `nodeId` is the
356
+ * node an `mrca` resolved to, which `collapse` and `focus` seed themselves
357
+ * with, and a `range` record has none.
358
+ */
359
+ export interface ResolvedClade {
360
+ rows: [number, number]
361
+ mark: CladeMark
362
+ color: string
363
+ markColor?: string
364
+ label?: string
365
+ nodeId?: string
366
+ }
367
+
368
+ /**
369
+ * A span in Highlight coordinates: 1-based inclusive residues of `row`, or
370
+ * columns of the file without it
371
+ */
372
+ export interface Region {
373
+ row?: string
374
+ start: number
375
+ end: number
376
+ }
377
+
378
+ /**
379
+ * A cell of the alignment in the host's coordinates, 1-based like Highlight:
380
+ * `column` counts every column of the file, hidden gappy ones included, and
381
+ * `residue` counts the row's own letters, absent on a gap. A pointer over a
382
+ * track has a column and no row.
383
+ */
384
+ export interface Cell {
385
+ column: number
386
+ row?: string
387
+ residue?: number
388
+ letter?: string
389
+ }
390
+
391
+ /** the alignment columns on screen, 1-based and inclusive */
392
+ export interface Viewport {
393
+ startColumn: number
394
+ endColumn: number
395
+ }
396
+
397
+ /**
398
+ * A channel of a mark the viewer always draws. `tipLabel` colors each tip label
399
+ * in the tree, `rowTint` washes the row across the tree gutter and the
400
+ * alignment, and `branch` colors a tree edge whose tips all share one value;
401
+ * all three read a field of `rowData`. `featureFill` colors each span of the
402
+ * annotation overlay and `featureLabel` names the field drawn inside a span,
403
+ * both from a field of the feature table.
404
+ */
405
+ export type EncodingChannel =
406
+ | 'tipLabel'
407
+ | 'rowTint'
408
+ | 'branch'
409
+ | 'featureFill'
410
+ | 'featureLabel'
411
+
412
+ /**
413
+ * A channel, the field feeding it, and the scale it reads that field through.
414
+ * See docs/layers.md
415
+ */
416
+ export interface Encoding {
417
+ channel: EncodingChannel
418
+ field: string
419
+ scale?: ScaleSpec
420
+ }
421
+
422
+ /** an Encoding with its scale resolved against the values in the table */
423
+ export type ResolvedEncoding = Encoding & ResolvedScale
424
+
210
425
  /** a Highlight resolved to visible column indices and row indices */
211
426
  export interface ResolvedHighlight {
212
427
  startCol?: number
package/src/umd.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as React from 'react'
2
2
 
3
- // a host that swaps models (the R htmlwidget on re-render) has to destroy the
4
- // old one, or the disposers its autoruns registered never run
3
+ // a page that builds models with MSAModelF destroys each one it replaces, so
4
+ // the disposers its autoruns registered run
5
5
  export { destroy } from '@jbrowse/mobx-state-tree'
6
6
  export { default as MSAView } from './components/Loading.tsx'
7
+ export { mount } from './mount.tsx'
8
+ export { defineMsaElement } from './element.ts'
7
9
  export { type MsaViewModel, default as MSAModelF } from './model.ts'
8
10
 
9
11
  export * from 'react-dom/client'
@@ -6,17 +6,12 @@ import type React from 'react'
6
6
 
7
7
  /**
8
8
  * Wires a canvas ref to a mobx autorun: grabs the 2d context once the canvas
9
- * mounts and re-runs `draw` whenever any observable it reads changes. Collapses
10
- * the getContext/null-guard/autorun-dispose boilerplate repeated by every canvas
11
- * block host.
9
+ * mounts and re-runs `draw` whenever any observable it reads changes.
12
10
  *
13
- * `width`/`height` are the canvas *backing store* size the caller renders onto
14
- * the element (logical size times the high-res scale factor), and they are load
15
- * bearing rather than informational. Assigning either resets the canvas bitmap,
16
- * and React assigns them on every commit where they changed -- which lands
17
- * *after* the mobx reaction that already redrew at the old size. Without a redraw
18
- * on the far side of that commit the canvas is left blank: it is what blanked the
19
- * tree on a tree-area resize and the consensus tracks on a vertical zoom.
11
+ * `width`/`height` are the canvas backing store size (logical size times the
12
+ * high-res scale factor). Assigning either clears the bitmap, and React assigns
13
+ * them after the mobx reaction has drawn at the old size, so the effect redraws
14
+ * when they change.
20
15
  *
21
16
  * `deps` covers everything else the effect should re-subscribe on, matching a
22
17
  * normal useEffect dep array.
@@ -0,0 +1,72 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ import { createJBrowseTheme } from '@jbrowse/core/ui/theme'
4
+ import { getSnapshot } from '@jbrowse/mobx-state-tree'
5
+ import { compareStructural, reaction } from 'mobx'
6
+
7
+ import { renderToSvg } from './renderToSvg.tsx'
8
+
9
+ import type { MsaViewModel } from './model.ts'
10
+ import type { Theme } from '@mui/material'
11
+
12
+ export interface MsaSvgFigure {
13
+ /** the SVG document for what is on screen, once the first draw finishes */
14
+ svg?: string
15
+ error?: unknown
16
+ }
17
+
18
+ /**
19
+ * The viewer's SVG export of its viewport, as markup for the page to insert.
20
+ * It redraws after the view settles: `delay` ms after the last scroll, zoom,
21
+ * resize or change to the snapshot. A draw a later one overtakes is dropped.
22
+ *
23
+ * The figure's row names and letters are SVG text, so the browser's find
24
+ * locates them, a reader can select them, and print stylesheets apply.
25
+ */
26
+ export function useMsaSvgFigure(
27
+ model: MsaViewModel,
28
+ {
29
+ theme,
30
+ includeTracks = false,
31
+ delay = 300,
32
+ }: { theme?: Theme; includeTracks?: boolean; delay?: number } = {},
33
+ ) {
34
+ const [figure, setFigure] = useState<MsaSvgFigure>({})
35
+ useEffect(() => {
36
+ let latest = 0
37
+ const dispose = reaction(
38
+ () =>
39
+ model.viewInitialized && model.dataInitialized
40
+ ? [getSnapshot(model), model.width, model.height]
41
+ : undefined,
42
+ key => {
43
+ if (!key) {
44
+ return
45
+ }
46
+ const draw = ++latest
47
+ renderToSvg(model, {
48
+ theme: theme ?? createJBrowseTheme(),
49
+ exportType: 'viewport',
50
+ includeTracks,
51
+ }).then(
52
+ svg => {
53
+ if (draw === latest) {
54
+ setFigure({ svg })
55
+ }
56
+ },
57
+ (error: unknown) => {
58
+ if (draw === latest) {
59
+ setFigure({ error })
60
+ }
61
+ },
62
+ )
63
+ },
64
+ { delay, fireImmediately: true, equals: compareStructural },
65
+ )
66
+ return () => {
67
+ latest = -1
68
+ dispose()
69
+ }
70
+ }, [model, theme, includeTracks, delay])
71
+ return figure
72
+ }
@@ -147,10 +147,6 @@ export function useWheelScroll({
147
147
  }, [mouseDragging, onScrollX, onScrollY])
148
148
 
149
149
  function onMouseDown(event: React.MouseEvent) {
150
- const target = event.target as HTMLElement
151
- if (target.draggable || target.dataset.resizer) {
152
- return
153
- }
154
150
  if (event.button === 0) {
155
151
  prevX.current = event.clientX
156
152
  prevY.current = event.clientY