react-msaview 5.9.0 → 6.0.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 +99 -99
- package/bundle/index.js.map +4 -4
- package/dist/clustalX.js +22 -22
- package/dist/clustalX.js.map +1 -1
- package/dist/components/ConservationTrack.js +21 -16
- package/dist/components/ConservationTrack.js.map +1 -1
- package/dist/components/CopyButton.d.ts +9 -0
- package/dist/components/CopyButton.js +23 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/Loading.js +2 -2
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.js +18 -24
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/ResizeHandles.js +24 -40
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/ScrollbarThumb.d.ts +14 -0
- package/dist/components/ScrollbarThumb.js +28 -0
- package/dist/components/ScrollbarThumb.js.map +1 -0
- package/dist/components/SequenceTextArea.js +3 -10
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/TextTrack.js +26 -21
- package/dist/components/TextTrack.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +11 -25
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +3 -3
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/{UserProvidedDomainsDialog.d.ts → InterProScanFileDialog.d.ts} +2 -2
- package/dist/components/dialogs/{UserProvidedDomainsDialog.js → InterProScanFileDialog.js} +6 -10
- package/dist/components/dialogs/InterProScanFileDialog.js.map +1 -0
- package/dist/components/dialogs/TrackInfoDialog.d.ts +2 -4
- package/dist/components/dialogs/TrackInfoDialog.js +8 -14
- package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
- package/dist/components/header/FileMenu.js +3 -3
- package/dist/components/header/FileMenu.js.map +1 -1
- package/dist/components/header/GappynessSlider.js +1 -1
- package/dist/components/header/GappynessSlider.js.map +1 -1
- package/dist/components/header/{getDomainsMenu.d.ts → getAnnotationsMenu.d.ts} +1 -1
- package/dist/components/header/{getDomainsMenu.js → getAnnotationsMenu.js} +10 -9
- package/dist/components/header/getAnnotationsMenu.js.map +1 -0
- package/dist/components/header/settingsMenuItems.js +39 -72
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +66 -57
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/minimap/Minimap.js +11 -22
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/minimap/MinimapSVG.d.ts +2 -1
- package/dist/components/minimap/MinimapSVG.js +3 -4
- package/dist/components/minimap/MinimapSVG.js.map +1 -1
- package/dist/components/minimap/minimapLayout.d.ts +10 -1
- package/dist/components/minimap/minimapLayout.js +15 -10
- package/dist/components/minimap/minimapLayout.js.map +1 -1
- package/dist/components/msa/{DomainLegend.d.ts → AnnotationLegend.d.ts} +2 -2
- package/dist/components/msa/{DomainLegend.js → AnnotationLegend.js} +4 -4
- package/dist/components/msa/AnnotationLegend.js.map +1 -0
- package/dist/components/msa/MSACanvas.js +2 -2
- package/dist/components/msa/MSACanvas.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 +14 -8
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/MSAPanel.js +2 -2
- package/dist/components/msa/MSAPanel.js.map +1 -1
- package/dist/components/msa/domainBandCursor.d.ts +17 -0
- package/dist/components/msa/domainBandCursor.js +39 -0
- package/dist/components/msa/domainBandCursor.js.map +1 -0
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +9 -6
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +14 -20
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +32 -33
- 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/TreeRuler.js +5 -2
- package/dist/components/tree/TreeRuler.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/ggplotPalettes.d.ts +0 -1
- package/dist/ggplotPalettes.js +0 -3
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/hierarchy.d.ts +2 -6
- package/dist/hierarchy.js +4 -6
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/launchInterProScan.d.ts +0 -23
- package/dist/launchInterProScan.js +2 -5
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/measureTextCanvas.js +21 -6
- package/dist/measureTextCanvas.js.map +1 -1
- package/dist/model.d.ts +50 -100
- package/dist/model.js +209 -219
- 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 +5 -2
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +13 -17
- package/dist/rowCoordinateCalculations.js +45 -39
- package/dist/rowCoordinateCalculations.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/types.d.ts +4 -11
- 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/package.json +5 -5
- package/src/clustalX.ts +22 -22
- package/src/colSpace.test.ts +27 -0
- package/src/components/ConservationTrack.tsx +7 -5
- package/src/components/CopyButton.tsx +44 -0
- package/src/components/Loading.tsx +10 -1
- package/src/components/MSAView.tsx +25 -32
- package/src/components/ResizeHandles.tsx +60 -69
- package/src/components/ScrollbarThumb.tsx +48 -0
- package/src/components/SequenceTextArea.tsx +3 -16
- package/src/components/TextTrack.tsx +7 -12
- package/src/components/VerticalScrollbar.tsx +19 -33
- package/src/components/dialogs/FeatureDialog.tsx +3 -4
- package/src/components/dialogs/{UserProvidedDomainsDialog.tsx → InterProScanFileDialog.tsx} +6 -14
- package/src/components/dialogs/TrackInfoDialog.tsx +18 -20
- package/src/components/header/FileMenu.tsx +3 -3
- package/src/components/header/GappynessSlider.tsx +4 -1
- package/src/components/header/{getDomainsMenu.ts → getAnnotationsMenu.ts} +10 -9
- package/src/components/header/settingsMenuItems.ts +40 -72
- package/src/components/import/ImportForm.tsx +1 -1
- package/src/components/import/ImportFormExamples.tsx +82 -133
- package/src/components/minimap/Minimap.tsx +23 -31
- package/src/components/minimap/MinimapSVG.tsx +32 -31
- package/src/components/minimap/minimapLayout.test.ts +60 -0
- package/src/components/minimap/minimapLayout.ts +15 -10
- package/src/components/msa/{DomainLegend.tsx → AnnotationLegend.tsx} +7 -3
- package/src/components/msa/MSACanvas.tsx +3 -10
- package/src/components/msa/MSACanvasBlock.tsx +16 -21
- package/src/components/msa/MSAMouseoverCanvas.tsx +11 -9
- package/src/components/msa/MSAPanel.tsx +2 -2
- package/src/components/msa/domainBandCursor.ts +41 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.test.ts +51 -0
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +13 -8
- package/src/components/msa/renderMSABlock.ts +19 -23
- package/src/components/msa/renderMSAMouseover.ts +38 -35
- 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/TreeRuler.tsx +7 -2
- package/src/components/tree/renderTreeCanvas.test.ts +15 -7
- package/src/components/tree/renderTreeCanvas.ts +20 -17
- package/src/domainBands.test.ts +24 -0
- package/src/domainLetterColor.test.ts +80 -0
- package/src/ggplotPalettes.ts +0 -4
- package/src/hierarchy.test.ts +7 -7
- package/src/hierarchy.ts +6 -9
- package/src/index.ts +4 -1
- package/src/largeTree.test.ts +23 -2
- package/src/launchInterProScan.ts +3 -30
- package/src/loadErrorDisplay.test.tsx +102 -0
- package/src/measureTextCanvas.ts +22 -6
- package/src/model.ts +233 -244
- 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/renderMinimapSvg.test.tsx +109 -0
- package/src/renderToSvg.tsx +5 -2
- package/src/rowCoordinateCalculations.ts +48 -44
- package/src/seqPosToGlobalCol.test.ts +39 -51
- package/src/seqPosToGlobalCol.ts +6 -41
- package/src/types.ts +10 -15
- package/src/useCanvasAutorun.test.tsx +98 -0
- package/src/useCanvasAutorun.ts +30 -11
- package/src/version.ts +1 -1
- package/src/viewChrome.test.tsx +134 -0
- package/dist/components/dialogs/DomainDialog.d.ts +0 -6
- package/dist/components/dialogs/DomainDialog.js +0 -19
- package/dist/components/dialogs/DomainDialog.js.map +0 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +0 -1
- package/dist/components/header/SettingsMenu.d.ts +0 -6
- package/dist/components/header/SettingsMenu.js +0 -40
- package/dist/components/header/SettingsMenu.js.map +0 -1
- package/dist/components/header/getDomainsMenu.js.map +0 -1
- package/dist/components/msa/DomainLegend.js.map +0 -1
- package/src/components/dialogs/DomainDialog.tsx +0 -45
- package/src/components/header/SettingsMenu.tsx +0 -57
|
@@ -1,71 +1,59 @@
|
|
|
1
|
+
// seqPos -> global column, exercised through the model method rather than the
|
|
2
|
+
// buildSeqPosIndex primitive behind it: the method is what
|
|
3
|
+
// jbrowse-plugin-protein3d calls (see the cross-repo note in model.ts), and it
|
|
4
|
+
// owns the past-the-end answers the index alone cannot give.
|
|
1
5
|
import { describe, expect, test } from 'vitest'
|
|
2
6
|
|
|
3
|
-
import
|
|
7
|
+
import MSAModelF from './model.ts'
|
|
8
|
+
|
|
9
|
+
function colsOf(row: string, positions: number[]) {
|
|
10
|
+
const model = MSAModelF().create({
|
|
11
|
+
type: 'MsaView',
|
|
12
|
+
data: { msa: `>r\n${row}` },
|
|
13
|
+
})
|
|
14
|
+
model.setWidth(800)
|
|
15
|
+
return positions.map(pos => model.seqPosToGlobalCol('r', pos))
|
|
16
|
+
}
|
|
4
17
|
|
|
5
18
|
describe('seqPosToGlobalCol', () => {
|
|
6
|
-
test('
|
|
7
|
-
|
|
8
|
-
expect(
|
|
9
|
-
expect(seqPosToGlobalCol({ row, seqPos: 3 })).toBe(3)
|
|
10
|
-
expect(seqPosToGlobalCol({ row, seqPos: 7 })).toBe(7)
|
|
11
|
-
expect(seqPosToGlobalCol({ row, seqPos: 8 })).toBe(8) // Past end
|
|
19
|
+
test('is the identity when the row has no gaps', () => {
|
|
20
|
+
// 8 residues, so seqPos 8 is one past the end
|
|
21
|
+
expect(colsOf('ATGCATGC', [0, 3, 7, 8])).toEqual([0, 3, 7, 8])
|
|
12
22
|
})
|
|
13
23
|
|
|
14
|
-
test('
|
|
15
|
-
const row = 'A-TG-CA-TGC'
|
|
24
|
+
test('skips gap columns', () => {
|
|
16
25
|
// Global: A(0) -(1) T(2) G(3) -(4) C(5) A(6) -(7) T(8) G(9) C(10)
|
|
17
26
|
// SeqPos: A(0) T(1) G(2) C(3) A(4) T(5) G(6) C(7)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
expect(seqPosToGlobalCol({ row, seqPos: 2 })).toBe(3) // G
|
|
22
|
-
expect(seqPosToGlobalCol({ row, seqPos: 3 })).toBe(5) // C
|
|
23
|
-
expect(seqPosToGlobalCol({ row, seqPos: 4 })).toBe(6) // A
|
|
24
|
-
expect(seqPosToGlobalCol({ row, seqPos: 5 })).toBe(8) // T
|
|
25
|
-
expect(seqPosToGlobalCol({ row, seqPos: 6 })).toBe(9) // G
|
|
26
|
-
expect(seqPosToGlobalCol({ row, seqPos: 7 })).toBe(10) // C
|
|
27
|
-
expect(seqPosToGlobalCol({ row, seqPos: 8 })).toBe(11) // Past end
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test('handles empty row', () => {
|
|
31
|
-
expect(seqPosToGlobalCol({ row: '', seqPos: 0 })).toBe(0)
|
|
27
|
+
expect(colsOf('A-TG-CA-TGC', [0, 1, 2, 3, 4, 5, 6, 7, 8])).toEqual([
|
|
28
|
+
0, 2, 3, 5, 6, 8, 9, 10, 11,
|
|
29
|
+
])
|
|
32
30
|
})
|
|
33
31
|
|
|
34
|
-
test('
|
|
35
|
-
const row = '---..--'
|
|
36
|
-
expect(seqPosToGlobalCol({ row, seqPos: 0 })).toBe(0)
|
|
37
|
-
expect(seqPosToGlobalCol({ row, seqPos: 1 })).toBe(7) // Past end
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test('handles mixed gap characters (- and .)', () => {
|
|
41
|
-
const row = 'A-.G-C.'
|
|
32
|
+
test('counts both gap characters, - and .', () => {
|
|
42
33
|
// Global: A(0) -(1) .(2) G(3) -(4) C(5) .(6)
|
|
43
34
|
// SeqPos: A(0) G(1) C(2)
|
|
44
|
-
|
|
45
|
-
expect(seqPosToGlobalCol({ row, seqPos: 0 })).toBe(0) // A
|
|
46
|
-
expect(seqPosToGlobalCol({ row, seqPos: 1 })).toBe(3) // G
|
|
47
|
-
expect(seqPosToGlobalCol({ row, seqPos: 2 })).toBe(5) // C
|
|
48
|
-
expect(seqPosToGlobalCol({ row, seqPos: 3 })).toBe(7) // Past end
|
|
35
|
+
expect(colsOf('A-.G-C.', [0, 1, 2, 3])).toEqual([0, 3, 5, 7])
|
|
49
36
|
})
|
|
50
37
|
|
|
51
|
-
test('handles leading gaps', () => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
test('handles leading and trailing gaps', () => {
|
|
39
|
+
expect(colsOf('--ACG', [0, 1, 2])).toEqual([2, 3, 4])
|
|
40
|
+
expect(colsOf('ACG--', [0, 1, 2, 3])).toEqual([0, 1, 2, 5])
|
|
41
|
+
})
|
|
55
42
|
|
|
56
|
-
|
|
57
|
-
expect(
|
|
58
|
-
expect(seqPosToGlobalCol({ row, seqPos: 2 })).toBe(4) // G
|
|
43
|
+
test('an all-gap row reports position 0 at column 0', () => {
|
|
44
|
+
expect(colsOf('---..--', [0, 1])).toEqual([0, 7])
|
|
59
45
|
})
|
|
60
46
|
|
|
61
|
-
test('
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// SeqPos: A(0) C(1) G(2)
|
|
47
|
+
test('an empty row reports column 0', () => {
|
|
48
|
+
expect(colsOf('', [0])).toEqual([0])
|
|
49
|
+
})
|
|
65
50
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
test('an unknown row reports column 0', () => {
|
|
52
|
+
const model = MSAModelF().create({
|
|
53
|
+
type: 'MsaView',
|
|
54
|
+
data: { msa: '>r\nACGT' },
|
|
55
|
+
})
|
|
56
|
+
model.setWidth(800)
|
|
57
|
+
expect(model.seqPosToGlobalCol('nope', 2)).toBe(0)
|
|
70
58
|
})
|
|
71
59
|
})
|
package/src/seqPosToGlobalCol.ts
CHANGED
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
import { isBlank } from './util.ts'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The global column of every ungapped sequence position in a row, i.e.
|
|
3
|
+
* index[seqPos] is the column holding the seqPos-th non-gap character.
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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.
|
|
10
8
|
*
|
|
11
9
|
* @example
|
|
12
10
|
* // Row: "A-TG-C" (A at 0, T at 2, G at 3, C at 5)
|
|
13
|
-
*
|
|
14
|
-
* seqPosToGlobalCol({ row: "A-TG-C", seqPos: 1 }) // → 2 (T)
|
|
15
|
-
* seqPosToGlobalCol({ row: "A-TG-C", seqPos: 2 }) // → 3 (G)
|
|
16
|
-
* seqPosToGlobalCol({ row: "A-TG-C", seqPos: 3 }) // → 5 (C)
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* The global column of every ungapped sequence position in a row, i.e.
|
|
20
|
-
* index[seqPos] is the column holding the seqPos-th non-gap character. Amortizes
|
|
21
|
-
* repeated seqPosToGlobalCol lookups (the domain overlay does one per feature
|
|
22
|
-
* per row) into a single pass per row.
|
|
11
|
+
* buildSeqPosIndex('A-TG-C') // → [0, 2, 3, 5]
|
|
23
12
|
*/
|
|
24
13
|
export function buildSeqPosIndex(row: string) {
|
|
25
14
|
const index = new Int32Array(row.length)
|
|
@@ -32,27 +21,3 @@ export function buildSeqPosIndex(row: string) {
|
|
|
32
21
|
}
|
|
33
22
|
return index.subarray(0, n)
|
|
34
23
|
}
|
|
35
|
-
|
|
36
|
-
export function seqPosToGlobalCol({
|
|
37
|
-
row,
|
|
38
|
-
seqPos,
|
|
39
|
-
}: {
|
|
40
|
-
row: string
|
|
41
|
-
seqPos: number
|
|
42
|
-
}) {
|
|
43
|
-
let nonGapCount = 0
|
|
44
|
-
let globalCol = 0
|
|
45
|
-
// Find the seqPos-th non-gap character
|
|
46
|
-
while (globalCol < row.length) {
|
|
47
|
-
if (!isBlank(row[globalCol])) {
|
|
48
|
-
if (nonGapCount === seqPos) {
|
|
49
|
-
return globalCol
|
|
50
|
-
}
|
|
51
|
-
nonGapCount++
|
|
52
|
-
}
|
|
53
|
-
globalCol++
|
|
54
|
-
}
|
|
55
|
-
// If seqPos is 0 and we didn't find any non-gap character, return 0
|
|
56
|
-
// Otherwise return globalCol (which is row.length at this point)
|
|
57
|
-
return seqPos === 0 ? 0 : globalCol
|
|
58
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Annotation } from 'msa-parsers'
|
|
2
|
+
|
|
1
3
|
export interface Accession {
|
|
2
4
|
accession: string
|
|
3
5
|
name: string
|
|
@@ -26,24 +28,17 @@ export interface BasicTrack {
|
|
|
26
28
|
model: TextTrackModel & BarTrackModel
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
accession: string
|
|
35
|
-
description: string
|
|
36
|
-
featureType?: string
|
|
37
|
-
start: number
|
|
38
|
-
end: number
|
|
39
|
-
strand?: number
|
|
40
|
-
}
|
|
31
|
+
// the overlay annotation itself lives in msa-parsers, alongside the adapters
|
|
32
|
+
// that build it. TidyDomainAnnotation is its former name, kept because
|
|
33
|
+
// downstream plugins name it in their emitted declarations.
|
|
34
|
+
export type { Annotation }
|
|
35
|
+
export type TidyDomainAnnotation = Annotation
|
|
41
36
|
|
|
42
|
-
//
|
|
43
|
-
// stackIndex is its position
|
|
37
|
+
// an annotation resolved to the visible column span it is drawn across.
|
|
38
|
+
// stackIndex is its position among the bands its row actually draws, which the
|
|
44
39
|
// sub-row layout uses to stack boxes.
|
|
45
40
|
export interface DomainBand {
|
|
46
|
-
annotation:
|
|
41
|
+
annotation: Annotation
|
|
47
42
|
startCol: number
|
|
48
43
|
endCol: number
|
|
49
44
|
stackIndex: number
|
|
@@ -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 = '
|
|
1
|
+
export const version = '6.0.0'
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
//
|
|
3
|
+
// The chrome around the alignment -- the tree/height resize handles, the
|
|
4
|
+
// minimap and the vertical scrollbar -- is all built from the same
|
|
5
|
+
// mousedown-then-drag hook, and none of it is exercised by the render tests.
|
|
6
|
+
// This mounts the real view and drives one handle of each kind.
|
|
7
|
+
import React, { act } from 'react'
|
|
8
|
+
|
|
9
|
+
import { createRoot } from 'react-dom/client'
|
|
10
|
+
import { afterEach, beforeAll, beforeEach, expect, test } from 'vitest'
|
|
11
|
+
|
|
12
|
+
import MSAView from './components/Loading.tsx'
|
|
13
|
+
import MSAModelF from './model.ts'
|
|
14
|
+
|
|
15
|
+
import type { MsaViewModel } from './model.ts'
|
|
16
|
+
import type { Root } from 'react-dom/client'
|
|
17
|
+
|
|
18
|
+
Reflect.set(globalThis, 'IS_REACT_ACT_ENVIRONMENT', true)
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
HTMLCanvasElement.prototype.getContext = function (this: HTMLCanvasElement) {
|
|
22
|
+
return {
|
|
23
|
+
canvas: this,
|
|
24
|
+
font: '12px sans-serif',
|
|
25
|
+
measureText: (t: string) => ({ width: t.length * 7 }),
|
|
26
|
+
arc() {},
|
|
27
|
+
beginPath() {},
|
|
28
|
+
clearRect() {},
|
|
29
|
+
closePath() {},
|
|
30
|
+
fill() {},
|
|
31
|
+
fillRect() {},
|
|
32
|
+
fillText() {},
|
|
33
|
+
lineTo() {},
|
|
34
|
+
moveTo() {},
|
|
35
|
+
resetTransform() {},
|
|
36
|
+
scale() {},
|
|
37
|
+
setLineDash() {},
|
|
38
|
+
stroke() {},
|
|
39
|
+
strokeRect() {},
|
|
40
|
+
translate() {},
|
|
41
|
+
} as unknown as CanvasRenderingContext2D
|
|
42
|
+
} as unknown as typeof HTMLCanvasElement.prototype.getContext
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// tall and wide enough that both scrollbars are on screen
|
|
46
|
+
const names = Array.from({ length: 20 }, (_, i) => `seq${i}`)
|
|
47
|
+
const msa = names.map(name => `>${name}\n${'ACGT'.repeat(25)}`).join('\n')
|
|
48
|
+
const tree = `(${names.map(n => `${n}:0.1`).join(',')});`
|
|
49
|
+
|
|
50
|
+
let container: HTMLDivElement
|
|
51
|
+
let root: Root
|
|
52
|
+
let model: MsaViewModel
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
container = document.createElement('div')
|
|
56
|
+
document.body.append(container)
|
|
57
|
+
root = createRoot(container)
|
|
58
|
+
model = MSAModelF().create({
|
|
59
|
+
type: 'MsaView',
|
|
60
|
+
msaFormat: 'fasta',
|
|
61
|
+
height: 200,
|
|
62
|
+
data: { msa, tree },
|
|
63
|
+
})
|
|
64
|
+
model.setWidth(800)
|
|
65
|
+
act(() => {
|
|
66
|
+
root.render(<MSAView model={model} />)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
act(() => {
|
|
72
|
+
root.unmount()
|
|
73
|
+
})
|
|
74
|
+
container.remove()
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
function byCursor(cursor: string) {
|
|
78
|
+
return [...container.querySelectorAll<HTMLElement>('div')].filter(
|
|
79
|
+
el => el.style.cursor === cursor,
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// useDragScroll defers each move to an animation frame, so a drag needs one
|
|
84
|
+
// flushed frame before the model has moved
|
|
85
|
+
async function drag(el: HTMLElement, { x = 0, y = 0 }) {
|
|
86
|
+
await act(async () => {
|
|
87
|
+
el.dispatchEvent(
|
|
88
|
+
new MouseEvent('mousedown', { bubbles: true, clientX: 0, clientY: 0 }),
|
|
89
|
+
)
|
|
90
|
+
})
|
|
91
|
+
await act(async () => {
|
|
92
|
+
document.dispatchEvent(
|
|
93
|
+
new MouseEvent('mousemove', { bubbles: true, clientX: x, clientY: y }),
|
|
94
|
+
)
|
|
95
|
+
await new Promise(resolve => {
|
|
96
|
+
requestAnimationFrame(resolve)
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
await act(async () => {
|
|
100
|
+
document.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }))
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
test('the view mounts with both scrollbars', () => {
|
|
105
|
+
expect(container.querySelector('[data-testid="msa_canvas"]')).toBeTruthy()
|
|
106
|
+
expect(model.showVerticalScrollbar).toBe(true)
|
|
107
|
+
expect(model.showHorizontalScrollbar).toBe(true)
|
|
108
|
+
// one horizontal divider (tree/msa), two vertical (view height, and the
|
|
109
|
+
// conservation track's own)
|
|
110
|
+
expect(byCursor('ew-resize')).toHaveLength(1)
|
|
111
|
+
expect(byCursor('ns-resize')).toHaveLength(2)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('dragging the tree divider widens the tree area', async () => {
|
|
115
|
+
const before = model.treeAreaWidth
|
|
116
|
+
await drag(byCursor('ew-resize')[0]!, { x: 60 })
|
|
117
|
+
expect(model.treeAreaWidth).toBe(before + 60)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('dragging the view divider grows the view', async () => {
|
|
121
|
+
const before = model.height
|
|
122
|
+
// the last ns-resize handle is the one below the whole view
|
|
123
|
+
await drag(byCursor('ns-resize').at(-1)!, { y: 50 })
|
|
124
|
+
expect(model.height).toBe(before + 50)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('dragging the scrollbar thumb scrolls the alignment', async () => {
|
|
128
|
+
const thumb = container.querySelector<HTMLElement>(
|
|
129
|
+
'div[style*="cursor: pointer"]',
|
|
130
|
+
)!
|
|
131
|
+
expect(model.scrollX).toBe(0)
|
|
132
|
+
await drag(thumb, { x: 40 })
|
|
133
|
+
expect(model.scrollX).toBeLessThan(0)
|
|
134
|
+
})
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { Dialog } from '@jbrowse/core/ui';
|
|
3
|
-
import { Tab, Tabs } from '@mui/material';
|
|
4
|
-
import InterProScanPanel from './InterProScanDialog.js';
|
|
5
|
-
import UserProvidedResultPanel from './UserProvidedDomainsDialog.js';
|
|
6
|
-
export default function LaunchDomainViewDialog({ handleClose, model, }) {
|
|
7
|
-
const [choice, setChoice] = useState(0);
|
|
8
|
-
return (React.createElement(Dialog, { maxWidth: "xl", title: "Launch protein view", onClose: () => {
|
|
9
|
-
handleClose();
|
|
10
|
-
}, open: true },
|
|
11
|
-
React.createElement(Tabs, { value: choice, onChange: (_, val) => {
|
|
12
|
-
setChoice(val);
|
|
13
|
-
} },
|
|
14
|
-
React.createElement(Tab, { value: 0, label: "Automatic lookup" }),
|
|
15
|
-
React.createElement(Tab, { value: 1, label: "Manual" })),
|
|
16
|
-
choice === 0 ? (React.createElement(InterProScanPanel, { model: model, handleClose: handleClose })) : null,
|
|
17
|
-
choice === 1 ? (React.createElement(UserProvidedResultPanel, { model: model, handleClose: handleClose })) : null));
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=DomainDialog.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DomainDialog.js","sourceRoot":"","sources":["../../../src/components/dialogs/DomainDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEzC,OAAO,iBAAiB,MAAM,yBAA0B,CAAA;AACxD,OAAO,uBAAuB,MAAM,gCAAiC,CAAA;AAIrE,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,EAC7C,WAAW,EACX,KAAK,GAIN;IACC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACvC,OAAO,CACL,oBAAC,MAAM,IACL,QAAQ,EAAC,IAAI,EACb,KAAK,EAAC,qBAAqB,EAC3B,OAAO,EAAE,GAAG,EAAE;YACZ,WAAW,EAAE,CAAA;QACf,CAAC,EACD,IAAI;QAEJ,oBAAC,IAAI,IACH,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;gBACnB,SAAS,CAAC,GAAG,CAAC,CAAA;YAChB,CAAC;YAED,oBAAC,GAAG,IAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAC,kBAAkB,GAAG;YAC1C,oBAAC,GAAG,IAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAC,QAAQ,GAAG,CAC3B;QACN,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACd,oBAAC,iBAAiB,IAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,GAAI,CAC9D,CAAC,CAAC,CAAC,IAAI;QACP,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACd,oBAAC,uBAAuB,IAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,GAAI,CACpE,CAAC,CAAC,CAAC,IAAI,CACD,CACV,CAAA;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"UserProvidedDomainsDialog.js","sourceRoot":"","sources":["../../../src/components/dialogs/UserProvidedDomainsDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EACL,MAAM,EACN,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAK/C,MAAM,yBAAyB,GAAG,QAAQ,CAAC,UAAU,EACnD,WAAW,EACX,KAAK,GAIN;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,EAAQ,CAAA;IACxC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC5C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAElD,OAAO,CACL,oBAAC,MAAM,IACL,QAAQ,EAAC,IAAI,EACb,KAAK,EAAC,gCAAgC,EACtC,OAAO,EAAE,GAAG,EAAE;YACZ,WAAW,EAAE,CAAA;QACf,CAAC,EACD,IAAI;QAEJ,oBAAC,aAAa;YACZ;gBACE,oBAAC,UAAU,mGAGE;gBAEb,6BAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;oBACzC,oBAAC,WAAW,IAAC,SAAS,EAAC,UAAU;wBAC/B,oBAAC,UAAU,IACT,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,KAAK,CAAC,EAAE;gCAChB,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;4BAC/B,CAAC;4BAED,oBAAC,gBAAgB,IAAC,KAAK,EAAC,KAAK,EAAC,OAAO,EAAE,oBAAC,KAAK,OAAG,EAAE,KAAK,EAAC,KAAK,GAAG;4BAChE,oBAAC,gBAAgB,IACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,oBAAC,KAAK,OAAG,EAClB,KAAK,EAAC,MAAM,GACZ,CACS,CACD;oBACb,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CAClB;wBACE,oBAAC,UAAU,mDAEE;wBACb,oBAAC,SAAS,IACR,KAAK,EAAC,KAAK,EACX,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,KAAK,CAAC,EAAE;gCAChB,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;4BACpC,CAAC,GACD,CACE,CACP,CAAC,CAAC,CAAC,IAAI;oBACP,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CACnB,6BAAK,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;wBAC5B,oBAAC,UAAU,mEAEE;wBACb,oBAAC,MAAM,IAAC,OAAO,EAAC,UAAU,EAAC,SAAS,EAAC,OAAO;;4BAE1C,+BACE,IAAI,EAAC,MAAM,EACX,MAAM,QACN,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;oCACvB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;oCAC9B,IAAI,IAAI,EAAE,CAAC;wCACT,OAAO,CAAC,IAAI,CAAC,CAAA;oCACf,CAAC;gCACH,CAAC,GACD,CACK,CACL,CACP,CAAC,CAAC,CAAC,IAAI,CACJ,CACF,CACQ;QAChB,oBAAC,aAAa;YACZ,oBAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,GAAG,EAAE;oBACZ,mEAAmE;oBACnE,CAAC;oBAAA,CAAC,KAAK,IAAI,EAAE;wBACX,IAAI,CAAC;4BACH,MAAM,GAAG,GAAyB,IAAI;gCACpC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gCAC/B,CAAC,CAAC,MAAM,SAAS,CAAC,WAAW,CAAC,CAAA;4BAEhC,8DAA8D;4BAC9D,2DAA2D;4BAC3D,iCAAiC;4BACjC,KAAK,CAAC,UAAU,CACd,MAAM,CAAC,WAAW,CAChB,GAAG,CAAC,OAAO;iCACR,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAU,CAAC;iCACrC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CACnC,CACF,CAAA;4BACD,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CACtB,6BAA6B,EAC7B,SAAS,CACV,CAAA;wBACH,CAAC;wBAAC,OAAO,CAAC,EAAE,CAAC;4BACX,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;4BAChB,UAAU,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;wBAC1C,CAAC;gCAAS,CAAC;4BACT,KAAK,CAAC,SAAS,EAAE,CAAA;wBACnB,CAAC;oBACH,CAAC,CAAC,EAAE,CAAA;oBACJ,WAAW,EAAE,CAAA;gBACf,CAAC,mBAGM,CACK,CACT,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,yBAAyB,CAAA"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
|
|
3
|
-
import AccountTree from '@mui/icons-material/AccountTree';
|
|
4
|
-
import Palette from '@mui/icons-material/Palette';
|
|
5
|
-
import Settings from '@mui/icons-material/Settings';
|
|
6
|
-
import { observer } from 'mobx-react';
|
|
7
|
-
import colorSchemes from '../../colorSchemes.js';
|
|
8
|
-
import { msaSettingsMenuItems, treeSettingsMenuItems, } from './settingsMenuItems.js';
|
|
9
|
-
const SettingsMenu = observer(function ({ model }) {
|
|
10
|
-
const { colorSchemeName } = model;
|
|
11
|
-
return (React.createElement(CascadingMenuButton, { closeAfterItemClick: false, menuItems: [
|
|
12
|
-
{
|
|
13
|
-
label: 'Color scheme',
|
|
14
|
-
icon: Palette,
|
|
15
|
-
type: 'subMenu',
|
|
16
|
-
subMenu: Object.keys(colorSchemes).map(option => ({
|
|
17
|
-
label: option,
|
|
18
|
-
type: 'radio',
|
|
19
|
-
checked: colorSchemeName === option,
|
|
20
|
-
onClick: () => {
|
|
21
|
-
model.setColorSchemeName(option);
|
|
22
|
-
},
|
|
23
|
-
})),
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
label: 'MSA settings',
|
|
27
|
-
type: 'subMenu',
|
|
28
|
-
subMenu: msaSettingsMenuItems(model),
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
label: 'Tree settings',
|
|
32
|
-
type: 'subMenu',
|
|
33
|
-
icon: AccountTree,
|
|
34
|
-
subMenu: treeSettingsMenuItems(model),
|
|
35
|
-
},
|
|
36
|
-
] },
|
|
37
|
-
React.createElement(Settings, null)));
|
|
38
|
-
});
|
|
39
|
-
export default SettingsMenu;
|
|
40
|
-
//# sourceMappingURL=SettingsMenu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsMenu.js","sourceRoot":"","sources":["../../../src/components/header/SettingsMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,mBAAmB,MAAM,sCAAsC,CAAA;AACtE,OAAO,WAAW,MAAM,iCAAiC,CAAA;AACzD,OAAO,OAAO,MAAM,6BAA6B,CAAA;AACjD,OAAO,QAAQ,MAAM,8BAA8B,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,YAAY,MAAM,uBAAuB,CAAA;AAChD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,wBAAwB,CAAA;AAI/B,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,EAAE,KAAK,EAA2B;IACxE,MAAM,EAAE,eAAe,EAAE,GAAG,KAAK,CAAA;IACjC,OAAO,CACL,oBAAC,mBAAmB,IAClB,mBAAmB,EAAE,KAAK,EAC1B,SAAS,EAAE;YACT;gBACE,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CACpC,MAAM,CAAC,EAAE,CACP,CAAC;oBACC,KAAK,EAAE,MAAM;oBACb,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,eAAe,KAAK,MAAM;oBACnC,OAAO,EAAE,GAAG,EAAE;wBACZ,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAA;oBAClC,CAAC;iBACF,CAAU,CACd;aACF;YACD;gBACE,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC;aACrC;YACD;gBACE,KAAK,EAAE,eAAe;gBACtB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC;aACtC;SACF;QAED,oBAAC,QAAQ,OAAG,CACQ,CACvB,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,YAAY,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getDomainsMenu.js","sourceRoot":"","sources":["../../../src/components/header/getDomainsMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAE5B,OAAO,SAAS,MAAM,+BAA+B,CAAA;AACrD,OAAO,UAAU,MAAM,gCAAgC,CAAA;AACvD,OAAO,MAAM,MAAM,4BAA4B,CAAA;AAC/C,OAAO,IAAI,MAAM,0BAA0B,CAAA;AAC3C,OAAO,UAAU,MAAM,gCAAgC,CAAA;AAIvD,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,6BAA8B,CAAC,CAAC,CAAA;AAC9E,MAAM,yBAAyB,GAAG,IAAI,CACpC,GAAG,EAAE,CAAC,MAAM,CAAC,yCAA0C,CAAC,CACzD,CAAA;AACD,MAAM,kBAAkB,GAAG,IAAI,CAC7B,GAAG,EAAE,CAAC,MAAM,CAAC,kCAAmC,CAAC,CAClD,CAAA;AAED,MAAM,UAAU,aAAa,CAAC,EAAE,KAAK,EAA2B;IAC9D,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;IAC7E,OAAO;QACL;YACE,KAAK,EAAE,iBAAiB;YACxB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/B,yBAAyB;oBACzB;wBACE,WAAW;wBACX,KAAK;qBACN;iBACF,CAAC,CAAA;YACJ,CAAC;SACF;QACD;YACE,KAAK,EAAE,mCAAmC;YAC1C,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/B,kBAAkB;oBAClB;wBACE,WAAW;wBACX,KAAK;qBACN;iBACF,CAAC,CAAA;YACJ,CAAC;SACF;QACD;YACE,KAAK,EAAE,eAAe,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,EAAE;YAC/D,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,mBAAmB;YAC5B,IAAI,EAAE,UAAmB;YACzB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,cAAc,CAAC,CAAC,WAAW,CAAC,CAAA;YACpC,CAAC;SACF;QACD;YACE,KAAK,EAAE,qBAAqB,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,EAAE;YACrE,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK;YACrD,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,UAAmB;YACzB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,iBAAiB,CAAC,CAAC,cAAc,CAAC,CAAA;YAC1C,CAAC;SACF;QACD;YACE,KAAK,EAAE,iBAAiB,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,EAAE;YACjE,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,GAAG,EAAE;gBACZ,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,mBAAmB;oBACnB;wBACE,OAAO;wBACP,KAAK;qBACN;iBACF,CAAC,CAAA;YACJ,CAAC;SACF;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DomainLegend.js","sourceRoot":"","sources":["../../../src/components/msa/DomainLegend.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,UAAU,MAAM,gCAAgC,CAAA;AACvD,OAAO,UAAU,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIrC,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,EAAE,KAAK,EAA2B;IACxE,MAAM,EACJ,mBAAmB,EACnB,kBAAkB,EAAE,OAAO,EAC3B,WAAW,EACX,gBAAgB,EAAE,QAAQ,GAC3B,GAAG,KAAK,CAAA;IACT,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAA;IAErD,OAAO,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACjD,oBAAC,KAAK,IACJ,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,GAAG,EAAE,CAAC;YACN,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,GAAG;YACX,QAAQ,EAAE,GAAG;YACb,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,OAAO,EAAE,IAAI;SACd;QAED,6BACE,KAAK,EAAE;gBACL,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,QAAQ;gBACpB,cAAc,EAAE,UAAU;gBAC1B,OAAO,EAAE,iBAAiB;aAC3B;YAED,oBAAC,UAAU,IACT,IAAI,EAAC,OAAO,EACZ,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,EAC7D,OAAO,EAAE,GAAG,EAAE;oBACZ,KAAK,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,CAAA;gBACtC,CAAC;gBAED,oBAAC,UAAU,IAAC,QAAQ,EAAC,OAAO,GAAG,CACpB,CACT;QACL,QAAQ,CAAC,CAAC,CAAC,CACV,6BAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IACnD,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CACpC,6BACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,EACxD,KAAK,EAAE,SAAS;YAEhB,6BACE,KAAK,EAAE;oBACL,KAAK,EAAE,EAAE;oBACT,MAAM,EAAE,EAAE;oBACV,UAAU,EAAE,CAAC;oBACb,UAAU,EAAE,WAAW,CAAC,SAAS,CAAC;iBACnC,GACD;YACF,oBAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,MAAM,UACjC,IAAI,CACM,CACT,CACP,CAAC,CACE,CACP,CAAC,CAAC,CAAC,IAAI,CACF,CACT,CAAC,CAAC,CAAC,IAAI,CAAA;AACV,CAAC,CAAC,CAAA;AAEF,eAAe,YAAY,CAAA"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
|
|
3
|
-
import { Dialog } from '@jbrowse/core/ui'
|
|
4
|
-
import { Tab, Tabs } from '@mui/material'
|
|
5
|
-
|
|
6
|
-
import InterProScanPanel from './InterProScanDialog.tsx'
|
|
7
|
-
import UserProvidedResultPanel from './UserProvidedDomainsDialog.tsx'
|
|
8
|
-
|
|
9
|
-
import type { MsaViewModel } from '../../model.ts'
|
|
10
|
-
|
|
11
|
-
export default function LaunchDomainViewDialog({
|
|
12
|
-
handleClose,
|
|
13
|
-
model,
|
|
14
|
-
}: {
|
|
15
|
-
handleClose: () => void
|
|
16
|
-
model: MsaViewModel
|
|
17
|
-
}) {
|
|
18
|
-
const [choice, setChoice] = useState(0)
|
|
19
|
-
return (
|
|
20
|
-
<Dialog
|
|
21
|
-
maxWidth="xl"
|
|
22
|
-
title="Launch protein view"
|
|
23
|
-
onClose={() => {
|
|
24
|
-
handleClose()
|
|
25
|
-
}}
|
|
26
|
-
open
|
|
27
|
-
>
|
|
28
|
-
<Tabs
|
|
29
|
-
value={choice}
|
|
30
|
-
onChange={(_, val) => {
|
|
31
|
-
setChoice(val)
|
|
32
|
-
}}
|
|
33
|
-
>
|
|
34
|
-
<Tab value={0} label="Automatic lookup" />
|
|
35
|
-
<Tab value={1} label="Manual" />
|
|
36
|
-
</Tabs>
|
|
37
|
-
{choice === 0 ? (
|
|
38
|
-
<InterProScanPanel model={model} handleClose={handleClose} />
|
|
39
|
-
) : null}
|
|
40
|
-
{choice === 1 ? (
|
|
41
|
-
<UserProvidedResultPanel model={model} handleClose={handleClose} />
|
|
42
|
-
) : null}
|
|
43
|
-
</Dialog>
|
|
44
|
-
)
|
|
45
|
-
}
|