react-msaview 5.9.0 → 5.10.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.
- package/bundle/index.js +76 -76
- package/bundle/index.js.map +3 -3
- package/dist/components/ConservationTrack.js +21 -16
- package/dist/components/ConservationTrack.js.map +1 -1
- package/dist/components/MSAView.js +17 -23
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/TextTrack.js +26 -21
- package/dist/components/TextTrack.js.map +1 -1
- package/dist/components/header/settingsMenuItems.js +39 -72
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +19 -16
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +13 -6
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +9 -6
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +31 -31
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/overlayColors.d.ts +2 -0
- package/dist/components/overlayColors.js +5 -0
- package/dist/components/overlayColors.js.map +1 -1
- package/dist/components/tree/TreeCanvas.js +29 -24
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +19 -12
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.d.ts +0 -38
- package/dist/components/tree/renderTreeCanvas.js +17 -17
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/model.js +82 -113
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +12 -19
- package/dist/neighborJoining.js.map +1 -1
- package/dist/parseAsn1.js +32 -43
- package/dist/parseAsn1.js.map +1 -1
- package/dist/renderToSvg.js +3 -0
- package/dist/renderToSvg.js.map +1 -1
- package/dist/seqPosToGlobalCol.d.ts +6 -19
- package/dist/seqPosToGlobalCol.js +6 -33
- package/dist/seqPosToGlobalCol.js.map +1 -1
- package/dist/useCanvasAutorun.d.ts +23 -1
- package/dist/useCanvasAutorun.js +20 -8
- package/dist/useCanvasAutorun.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +3 -3
- package/src/components/ConservationTrack.tsx +7 -5
- package/src/components/MSAView.tsx +24 -30
- package/src/components/TextTrack.tsx +7 -12
- package/src/components/header/settingsMenuItems.ts +40 -72
- package/src/components/msa/MSACanvasBlock.tsx +16 -21
- package/src/components/msa/MSAMouseoverCanvas.tsx +10 -6
- package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +51 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +13 -8
- package/src/components/msa/renderMSAMouseover.ts +37 -32
- package/src/components/overlayColors.ts +6 -0
- package/src/components/tree/TreeCanvas.tsx +6 -4
- package/src/components/tree/TreeCanvasBlock.tsx +11 -12
- package/src/components/tree/renderTreeCanvas.ts +20 -17
- package/src/model.ts +97 -130
- package/src/modelFilehandleLoaders.test.ts +137 -0
- package/src/neighborJoining.test.ts +12 -0
- package/src/neighborJoining.ts +12 -20
- package/src/parseAsn1.ts +32 -40
- package/src/{renderDomainLegendSvg.test.tsx → renderDomainsSvg.test.tsx} +44 -20
- package/src/renderToSvg.tsx +3 -0
- package/src/seqPosToGlobalCol.test.ts +39 -51
- package/src/seqPosToGlobalCol.ts +6 -41
- package/src/useCanvasAutorun.test.tsx +98 -0
- package/src/useCanvasAutorun.ts +30 -11
- package/src/version.ts +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
//
|
|
3
|
+
// Assigning width/height to a canvas resets its bitmap, and React assigns them
|
|
4
|
+
// on every commit where they changed. A draw that ran during the mobx reaction
|
|
5
|
+
// -- before React commits -- is therefore wiped by the resize that follows it,
|
|
6
|
+
// which is what used to blank the tree on a tree-area drag and the consensus
|
|
7
|
+
// tracks on a vertical zoom. So the hook has to draw again after the resize.
|
|
8
|
+
import React, { act } from 'react'
|
|
9
|
+
|
|
10
|
+
import { observable, runInAction } from 'mobx'
|
|
11
|
+
import { observer } from 'mobx-react'
|
|
12
|
+
import { createRoot } from 'react-dom/client'
|
|
13
|
+
import { afterEach, beforeAll, beforeEach, expect, test } from 'vitest'
|
|
14
|
+
|
|
15
|
+
import { useCanvasAutorun } from './useCanvasAutorun.ts'
|
|
16
|
+
|
|
17
|
+
import type { Root } from 'react-dom/client'
|
|
18
|
+
|
|
19
|
+
Reflect.set(globalThis, 'IS_REACT_ACT_ENVIRONMENT', true)
|
|
20
|
+
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
HTMLCanvasElement.prototype.getContext = function (this: HTMLCanvasElement) {
|
|
23
|
+
return { canvas: this } as unknown as CanvasRenderingContext2D
|
|
24
|
+
} as unknown as typeof HTMLCanvasElement.prototype.getContext
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const state = observable({ width: 100, color: 'red' })
|
|
28
|
+
// what each draw saw: the observables it renders from, and the size of the
|
|
29
|
+
// canvas it was drawing onto
|
|
30
|
+
let draws: { observed: number; color: string; canvas: number }[] = []
|
|
31
|
+
|
|
32
|
+
const Probe = observer(function () {
|
|
33
|
+
const ref = useCanvasAutorun({
|
|
34
|
+
draw: ctx => {
|
|
35
|
+
draws.push({
|
|
36
|
+
observed: state.width,
|
|
37
|
+
color: state.color,
|
|
38
|
+
canvas: ctx.canvas.width,
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
width: state.width,
|
|
42
|
+
height: 50,
|
|
43
|
+
deps: [],
|
|
44
|
+
})
|
|
45
|
+
return <canvas ref={ref} width={state.width} height={50} />
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
let container: HTMLElement
|
|
49
|
+
let root: Root
|
|
50
|
+
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
draws = []
|
|
53
|
+
runInAction(() => {
|
|
54
|
+
state.width = 100
|
|
55
|
+
state.color = 'red'
|
|
56
|
+
})
|
|
57
|
+
container = document.createElement('div')
|
|
58
|
+
document.body.appendChild(container)
|
|
59
|
+
root = createRoot(container)
|
|
60
|
+
act(() => {
|
|
61
|
+
root.render(<Probe />)
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
act(() => {
|
|
67
|
+
root.unmount()
|
|
68
|
+
})
|
|
69
|
+
container.remove()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('the first draw sees the canvas at its rendered size', () => {
|
|
73
|
+
expect(draws).toEqual([{ observed: 100, color: 'red', canvas: 100 }])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('a resize is followed by a draw onto the resized canvas', () => {
|
|
77
|
+
act(() => {
|
|
78
|
+
runInAction(() => {
|
|
79
|
+
state.width = 300
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(container.querySelector('canvas')!.width).toBe(300)
|
|
84
|
+
expect(draws.at(-1)).toEqual({ observed: 300, color: 'red', canvas: 300 })
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('a change that leaves the size alone draws exactly once', () => {
|
|
88
|
+
act(() => {
|
|
89
|
+
runInAction(() => {
|
|
90
|
+
state.color = 'blue'
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
expect(draws).toEqual([
|
|
95
|
+
{ observed: 100, color: 'red', canvas: 100 },
|
|
96
|
+
{ observed: 100, color: 'blue', canvas: 100 },
|
|
97
|
+
])
|
|
98
|
+
})
|
package/src/useCanvasAutorun.ts
CHANGED
|
@@ -4,18 +4,37 @@ import { autorun } from 'mobx'
|
|
|
4
4
|
|
|
5
5
|
import type React from 'react'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
/**
|
|
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.
|
|
12
|
+
*
|
|
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.
|
|
20
|
+
*
|
|
21
|
+
* `deps` covers everything else the effect should re-subscribe on, matching a
|
|
22
|
+
* normal useEffect dep array.
|
|
23
|
+
*/
|
|
24
|
+
export function useCanvasAutorun({
|
|
25
|
+
draw,
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
deps,
|
|
29
|
+
}: {
|
|
30
|
+
draw: (ctx: CanvasRenderingContext2D) => void
|
|
31
|
+
width: number
|
|
32
|
+
height: number
|
|
33
|
+
deps: React.DependencyList
|
|
34
|
+
}) {
|
|
16
35
|
const ref = useRef<HTMLCanvasElement>(null)
|
|
17
36
|
// the autorun tracks its own observable reads, so `draw` is intentionally not
|
|
18
|
-
// a dependency; `deps`
|
|
37
|
+
// a dependency; `deps` plus the canvas size control when it re-subscribes
|
|
19
38
|
useEffect(() => {
|
|
20
39
|
const ctx = ref.current?.getContext('2d')
|
|
21
40
|
return ctx
|
|
@@ -24,6 +43,6 @@ export function useCanvasAutorun(
|
|
|
24
43
|
})
|
|
25
44
|
: undefined
|
|
26
45
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
-
}, deps)
|
|
46
|
+
}, [...deps, width, height])
|
|
28
47
|
return ref
|
|
29
48
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '5.
|
|
1
|
+
export const version = '5.10.0'
|