react-msaview 8.2.0 → 8.4.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 +77 -300
- package/bundle/index.js.map +4 -4
- package/dist/blockFasta.d.ts +6 -0
- package/dist/blockFasta.js +12 -0
- package/dist/blockFasta.js.map +1 -0
- package/dist/colorSchemes.d.ts +7 -0
- package/dist/colorSchemes.js +15 -0
- package/dist/colorSchemes.js.map +1 -1
- package/dist/columnCounts.d.ts +4 -3
- package/dist/columnCounts.js +11 -6
- package/dist/columnCounts.js.map +1 -1
- package/dist/components/CopyButton.d.ts +1 -1
- package/dist/components/CopyButton.js +1 -1
- package/dist/components/CopyButton.js.map +1 -1
- package/dist/components/DragHandle.js +14 -2
- package/dist/components/DragHandle.js.map +1 -1
- package/dist/components/Loading.js +10 -11
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.js +15 -9
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +39 -7
- package/dist/components/MSAViewer.js +72 -22
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/MetadataTable.d.ts +5 -0
- package/dist/components/MetadataTable.js +29 -0
- package/dist/components/MetadataTable.js.map +1 -0
- package/dist/components/SequenceTextArea.d.ts +11 -0
- package/dist/components/SequenceTextArea.js +40 -8
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/StatusMessage.d.ts +12 -0
- package/dist/components/StatusMessage.js +43 -0
- package/dist/components/StatusMessage.js.map +1 -0
- package/dist/components/Track.js +13 -4
- package/dist/components/Track.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +6 -1
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/ExportSVGDialog.d.ts +3 -2
- package/dist/components/dialogs/ExportSVGDialog.js +4 -2
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +15 -10
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/MetadataDialog.js +5 -6
- package/dist/components/dialogs/MetadataDialog.js.map +1 -1
- package/dist/components/getVisibleLeaves.d.ts +1 -1
- package/dist/components/header/ColorSchemeMenu.d.ts +6 -0
- package/dist/components/header/ColorSchemeMenu.js +23 -5
- package/dist/components/header/ColorSchemeMenu.js.map +1 -1
- package/dist/components/header/FileMenu.js +9 -0
- package/dist/components/header/FileMenu.js.map +1 -1
- package/dist/components/header/GappynessSlider.js +15 -3
- package/dist/components/header/GappynessSlider.js.map +1 -1
- package/dist/components/header/{HeaderStatusArea.d.ts → GoToBox.d.ts} +2 -2
- package/dist/components/header/GoToBox.js +21 -0
- package/dist/components/header/GoToBox.js.map +1 -0
- package/dist/components/header/Header.js +8 -7
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/SelectionMenu.d.ts +12 -0
- package/dist/components/header/SelectionMenu.js +72 -0
- package/dist/components/header/SelectionMenu.js.map +1 -0
- package/dist/components/header/goTo.d.ts +20 -0
- package/dist/components/header/goTo.js +69 -0
- package/dist/components/header/goTo.js.map +1 -0
- package/dist/components/header/settingsMenuItems.js +57 -1
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/import/ImportForm.js +10 -4
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +19 -27
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/minimap/Minimap.js +6 -1
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/AnnotationLegend.js +11 -5
- package/dist/components/msa/AnnotationLegend.js.map +1 -1
- package/dist/components/msa/MSACanvas.js +17 -1
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +6 -6
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/msaKeys.d.ts +5 -0
- package/dist/components/msa/msaKeys.js +41 -0
- package/dist/components/msa/msaKeys.js.map +1 -0
- package/dist/components/msa/msaRaster.js +1 -0
- package/dist/components/msa/msaRaster.js.map +1 -1
- package/dist/components/msa/renderHighlights.d.ts +14 -3
- package/dist/components/msa/renderHighlights.js +29 -4
- package/dist/components/msa/renderHighlights.js.map +1 -1
- package/dist/components/msa/tileColor.js +9 -8
- package/dist/components/msa/tileColor.js.map +1 -1
- package/dist/components/msa/useMsaBlockMouse.d.ts +2 -4
- package/dist/components/msa/useMsaBlockMouse.js +34 -14
- package/dist/components/msa/useMsaBlockMouse.js.map +1 -1
- package/dist/components/overlayColors.d.ts +2 -0
- package/dist/components/overlayColors.js +3 -0
- package/dist/components/overlayColors.js.map +1 -1
- package/dist/components/rowpanels/RowPanelBlock.js +10 -14
- package/dist/components/rowpanels/RowPanelBlock.js.map +1 -1
- package/dist/components/selectionDrag.d.ts +17 -0
- package/dist/components/selectionDrag.js +30 -0
- package/dist/components/selectionDrag.js.map +1 -0
- package/dist/components/tracks/drawTracks.d.ts +1 -0
- package/dist/components/tracks/drawTracks.js +14 -2
- package/dist/components/tracks/drawTracks.js.map +1 -1
- package/dist/components/tracks/useTrackHover.d.ts +4 -6
- package/dist/components/tracks/useTrackHover.js +30 -10
- package/dist/components/tracks/useTrackHover.js.map +1 -1
- package/dist/components/tree/ScaleBarSVG.d.ts +14 -0
- package/dist/components/tree/ScaleBarSVG.js +11 -0
- package/dist/components/tree/ScaleBarSVG.js.map +1 -0
- package/dist/components/tree/TreeCanvas.js +8 -26
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +11 -20
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/{TreeBranchMenu.d.ts → TreeMenu.d.ts} +5 -4
- package/dist/components/tree/TreeMenu.js +48 -0
- package/dist/components/tree/TreeMenu.js.map +1 -0
- package/dist/components/tree/TreeRuler.js +3 -3
- package/dist/components/tree/TreeRuler.js.map +1 -1
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +9 -8
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +19 -9
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/tree/renderTreeMouseover.d.ts +5 -0
- package/dist/components/tree/renderTreeMouseover.js +20 -0
- package/dist/components/tree/renderTreeMouseover.js.map +1 -0
- package/dist/components/tree/useTreeHover.d.ts +3 -8
- package/dist/components/tree/useTreeHover.js +8 -10
- package/dist/components/tree/useTreeHover.js.map +1 -1
- package/dist/components/useHoverAnchor.d.ts +19 -0
- package/dist/components/useHoverAnchor.js +18 -0
- package/dist/components/useHoverAnchor.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +12 -3
- package/dist/constants.js.map +1 -1
- package/dist/element.d.ts +7 -3
- package/dist/element.js +32 -4
- package/dist/element.js.map +1 -1
- package/dist/expandSpec.js +3 -3
- package/dist/expandSpec.js.map +1 -1
- package/dist/exportFileName.d.ts +3 -3
- package/dist/exportFileName.js +4 -4
- package/dist/exportFileName.js.map +1 -1
- package/dist/featuresLayer.d.ts +8 -0
- package/dist/featuresLayer.js +42 -0
- package/dist/featuresLayer.js.map +1 -0
- package/dist/hierarchy.d.ts +51 -0
- package/dist/hierarchy.js +125 -0
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/model/DataModel.d.ts +1 -1
- package/dist/model/DataModel.js +3 -3
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/msaModel.d.ts +14 -1
- package/dist/model/msaModel.js +17 -1
- package/dist/model/msaModel.js.map +1 -1
- package/dist/model/treeModel.d.ts +12 -0
- package/dist/model/treeModel.js +14 -1
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +285 -53
- package/dist/model.js +693 -231
- package/dist/model.js.map +1 -1
- package/dist/renderToSvg.js +2 -4
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rerootTree.d.ts +33 -0
- package/dist/rerootTree.js +144 -0
- package/dist/rerootTree.js.map +1 -0
- package/dist/svgTestUtil.d.ts +172 -26
- package/dist/types.d.ts +75 -12
- package/dist/useMsaSvgFigure.d.ts +2 -1
- package/dist/useMsaSvgFigure.js +11 -4
- package/dist/useMsaSvgFigure.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/writeNewick.d.ts +8 -0
- package/dist/writeNewick.js +34 -0
- package/dist/writeNewick.js.map +1 -0
- package/package.json +3 -3
- package/src/blockFasta.ts +18 -0
- package/src/colorSchemes.ts +20 -0
- package/src/columnCounts.ts +14 -6
- package/src/components/CopyButton.tsx +2 -2
- package/src/components/DragHandle.tsx +21 -1
- package/src/components/Loading.tsx +14 -30
- package/src/components/MSAView.tsx +16 -9
- package/src/components/MSAViewer.tsx +121 -26
- package/src/components/MetadataTable.tsx +55 -0
- package/src/components/SequenceTextArea.tsx +54 -8
- package/src/components/StatusMessage.tsx +70 -0
- package/src/components/Track.tsx +21 -4
- package/src/components/VerticalScrollbar.tsx +7 -0
- package/src/components/dialogs/ExportSVGDialog.tsx +5 -2
- package/src/components/dialogs/FeatureDialog.tsx +59 -38
- package/src/components/dialogs/MetadataDialog.tsx +9 -8
- package/src/components/header/ColorSchemeMenu.tsx +31 -12
- package/src/components/header/FileMenu.tsx +9 -0
- package/src/components/header/GappynessSlider.tsx +17 -4
- package/src/components/header/GoToBox.tsx +50 -0
- package/src/components/header/Header.tsx +11 -8
- package/src/components/header/SelectionMenu.tsx +117 -0
- package/src/components/header/goTo.ts +75 -0
- package/src/components/header/settingsMenuItems.ts +66 -0
- package/src/components/import/ImportForm.tsx +14 -7
- package/src/components/import/ImportFormExamples.tsx +20 -28
- package/src/components/minimap/Minimap.tsx +7 -0
- package/src/components/msa/AnnotationLegend.tsx +12 -6
- package/src/components/msa/MSACanvas.tsx +19 -1
- package/src/components/msa/MSACanvasBlock.tsx +9 -11
- package/src/components/msa/msaKeys.ts +45 -0
- package/src/components/msa/msaRaster.ts +1 -0
- package/src/components/msa/renderHighlights.ts +46 -4
- package/src/components/msa/tileColor.ts +9 -8
- package/src/components/msa/useMsaBlockMouse.ts +44 -31
- package/src/components/overlayColors.ts +4 -0
- package/src/components/rowpanels/RowPanelBlock.tsx +16 -23
- package/src/components/selectionDrag.ts +42 -0
- package/src/components/tracks/drawTracks.ts +15 -2
- package/src/components/tracks/useTrackHover.ts +32 -10
- package/src/components/tree/ScaleBarSVG.tsx +30 -0
- package/src/components/tree/TreeCanvas.tsx +9 -40
- package/src/components/tree/TreeCanvasBlock.tsx +19 -39
- package/src/components/tree/TreeMenu.tsx +129 -0
- package/src/components/tree/TreeRuler.tsx +7 -13
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +14 -16
- package/src/components/tree/renderTreeCanvas.ts +20 -8
- package/src/components/tree/renderTreeMouseover.ts +41 -0
- package/src/components/tree/useTreeHover.ts +8 -17
- package/src/components/useHoverAnchor.ts +31 -0
- package/src/constants.ts +14 -3
- package/src/element.ts +45 -5
- package/src/expandSpec.ts +3 -3
- package/src/exportFileName.ts +4 -3
- package/src/featuresLayer.ts +48 -0
- package/src/hierarchy.ts +151 -4
- package/src/index.ts +8 -1
- package/src/model/DataModel.ts +3 -3
- package/src/model/msaModel.ts +19 -1
- package/src/model/treeModel.ts +22 -0
- package/src/model.ts +841 -272
- package/src/renderToSvg.tsx +6 -9
- package/src/rerootTree.ts +172 -0
- package/src/types.ts +92 -12
- package/src/useMsaSvgFigure.ts +11 -4
- package/src/version.ts +1 -1
- package/src/writeNewick.ts +38 -0
- package/dist/components/PortalTooltip.d.ts +0 -11
- package/dist/components/PortalTooltip.js +0 -29
- package/dist/components/PortalTooltip.js.map +0 -1
- package/dist/components/header/HeaderStatusArea.js +0 -21
- package/dist/components/header/HeaderStatusArea.js.map +0 -1
- package/dist/components/tree/TreeBranchMenu.js +0 -29
- package/dist/components/tree/TreeBranchMenu.js.map +0 -1
- package/dist/components/tree/TreeNodeMenu.d.ts +0 -13
- package/dist/components/tree/TreeNodeMenu.js +0 -41
- package/dist/components/tree/TreeNodeMenu.js.map +0 -1
- package/src/components/PortalTooltip.tsx +0 -47
- package/src/components/header/HeaderStatusArea.tsx +0 -32
- package/src/components/tree/TreeBranchMenu.tsx +0 -68
- package/src/components/tree/TreeNodeMenu.tsx +0 -95
package/dist/types.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ export type TrackKind = 'text' | 'bar' | 'logo' | 'arc' | 'ruler';
|
|
|
12
12
|
* graphics draws between a shape's interior and its own ink.
|
|
13
13
|
*/
|
|
14
14
|
export type ResidueEncoding = 'fill' | 'color';
|
|
15
|
+
/**
|
|
16
|
+
* The residue colors: a scheme name from the built-in table, or a scale's
|
|
17
|
+
* `{map}` of letter to color, which leaves every letter it does not list
|
|
18
|
+
* uncolored
|
|
19
|
+
*/
|
|
20
|
+
export type ColorScheme = string | Required<Pick<ScaleSpec, 'map'>>;
|
|
15
21
|
export interface BasicTrackModel {
|
|
16
22
|
id: string;
|
|
17
23
|
name: string;
|
|
@@ -266,13 +272,49 @@ export interface Highlight {
|
|
|
266
272
|
label?: string;
|
|
267
273
|
color?: string;
|
|
268
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* A feature on one row as data, the JSON form of a GFF line: `start` and `end`
|
|
277
|
+
* are residues of `row`, 1-based and inclusive. `name` is the key the legend,
|
|
278
|
+
* the palette and the filter dialog group features by, `color` overrides the
|
|
279
|
+
* palette and any scale, and a `strand` draws the span as an arrow. Every other
|
|
280
|
+
* field is a column the `featureFill` and `featureLabel` encodings can read.
|
|
281
|
+
*/
|
|
282
|
+
export interface Feature {
|
|
283
|
+
row: string;
|
|
284
|
+
start: number;
|
|
285
|
+
end: number;
|
|
286
|
+
name?: string;
|
|
287
|
+
description?: string;
|
|
288
|
+
/** a GFF feature type; `exon`, `CDS` and the UTRs draw as numbered segments */
|
|
289
|
+
type?: string;
|
|
290
|
+
strand?: '+' | '-';
|
|
291
|
+
color?: string;
|
|
292
|
+
[field: string]: string | number | undefined;
|
|
293
|
+
}
|
|
269
294
|
/**
|
|
270
295
|
* What the viewer draws over a clade. `highlight` fills the rows behind it,
|
|
271
296
|
* across the tree and the alignment. `bracket` draws a bar and the clade's
|
|
272
|
-
* `label` in the gutter right of the tip labels. `collapse
|
|
273
|
-
* the collapsed list
|
|
297
|
+
* `label` in the gutter right of the tip labels. `collapse`, `focus` and
|
|
298
|
+
* `rotate` seed the collapsed list, the subtree in focus and the rotated nodes
|
|
299
|
+
* at load.
|
|
300
|
+
*/
|
|
301
|
+
export type CladeMark = 'highlight' | 'bracket' | 'collapse' | 'focus' | 'rotate';
|
|
302
|
+
/**
|
|
303
|
+
* The order each node's children draw in, top to bottom. `branchLength` puts
|
|
304
|
+
* the shortest branch first, `input` keeps the file's order, `ladderize` puts
|
|
305
|
+
* the clade with the fewest tips first, so the deep clades step down toward
|
|
306
|
+
* the bottom, and `ladderizeReverse` puts the one with the most tips first.
|
|
274
307
|
*/
|
|
275
|
-
export type
|
|
308
|
+
export type TreeOrder = 'branchLength' | 'input' | 'ladderize' | 'ladderizeReverse';
|
|
309
|
+
/**
|
|
310
|
+
* Where the tree is rooted: `midpoint` halfway along the longest path between
|
|
311
|
+
* two tips, and `{outgroup}` on the branch above those tips' most recent common
|
|
312
|
+
* ancestor, or above the rest of the tips' where the outgroup straddles the
|
|
313
|
+
* root the file gives.
|
|
314
|
+
*/
|
|
315
|
+
export type TreeRoot = 'midpoint' | {
|
|
316
|
+
outgroup: string[];
|
|
317
|
+
};
|
|
276
318
|
/**
|
|
277
319
|
* A clade of the tree and the mark drawn over it. `mrca` names tips whose most
|
|
278
320
|
* recent common ancestor is the clade; `range` names the first and last tip of
|
|
@@ -313,11 +355,31 @@ export interface Region {
|
|
|
313
355
|
start: number;
|
|
314
356
|
end: number;
|
|
315
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* A block of the alignment the reader selected: columns `start` to `end` of the
|
|
360
|
+
* file, 1-based and inclusive like a Highlight without a row, across the rows
|
|
361
|
+
* `rows` names, or across every row where `rows` is absent.
|
|
362
|
+
*/
|
|
363
|
+
export interface MsaSelection {
|
|
364
|
+
start: number;
|
|
365
|
+
end: number;
|
|
366
|
+
rows?: string[];
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* An MsaSelection resolved to what is on screen: the visible columns it covers
|
|
370
|
+
* and its rows as runs of consecutive row indices, top to bottom
|
|
371
|
+
*/
|
|
372
|
+
export interface ResolvedSelection {
|
|
373
|
+
startCol: number;
|
|
374
|
+
endCol: number;
|
|
375
|
+
rowRuns: [number, number][];
|
|
376
|
+
}
|
|
316
377
|
/**
|
|
317
378
|
* A cell of the alignment in the host's coordinates, 1-based like Highlight:
|
|
318
379
|
* `column` counts every column of the file, hidden gappy ones included, and
|
|
319
|
-
* `residue` counts the row's own letters, absent on a gap.
|
|
320
|
-
*
|
|
380
|
+
* `residue` counts the row's own letters, absent on a gap. `letter` is the
|
|
381
|
+
* character in the cell, the gap character (`-` or `.`) on a gap. A pointer
|
|
382
|
+
* over a track has a column and no row.
|
|
321
383
|
*/
|
|
322
384
|
export interface Cell {
|
|
323
385
|
column: number;
|
|
@@ -330,6 +392,12 @@ export interface Viewport {
|
|
|
330
392
|
startColumn: number;
|
|
331
393
|
endColumn: number;
|
|
332
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* A row table as a host passes it: fields per row name. A number or a boolean
|
|
397
|
+
* reads as its string, the way a GFF value does, and the viewer leaves out any
|
|
398
|
+
* other value. See docs/layers.md
|
|
399
|
+
*/
|
|
400
|
+
export type RowDataInput = Record<string, Record<string, string | number | boolean | null>>;
|
|
333
401
|
/**
|
|
334
402
|
* A channel of a mark the viewer always draws. `tipLabel` colors each tip label
|
|
335
403
|
* in the tree, `rowTint` washes the row across the tree gutter and the
|
|
@@ -369,10 +437,5 @@ export interface NodeWithIds {
|
|
|
369
437
|
length?: number;
|
|
370
438
|
noTree?: boolean;
|
|
371
439
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
name: string;
|
|
375
|
-
children: NodeWithIdsAndLength[];
|
|
376
|
-
noTree?: boolean;
|
|
377
|
-
length: number;
|
|
378
|
-
}
|
|
440
|
+
/** @deprecated the same type as `NodeWithIds` */
|
|
441
|
+
export type NodeWithIdsAndLength = NodeWithIds;
|
|
@@ -8,7 +8,8 @@ export interface MsaSvgFigure {
|
|
|
8
8
|
/**
|
|
9
9
|
* The viewer's SVG export of its viewport, as markup for the page to insert.
|
|
10
10
|
* It redraws after the view settles: `delay` ms after the last scroll, zoom,
|
|
11
|
-
* resize or change to the snapshot. A draw a later one overtakes is
|
|
11
|
+
* resize, highlight or change to the snapshot. A draw a later one overtakes is
|
|
12
|
+
* dropped.
|
|
12
13
|
*
|
|
13
14
|
* The figure's row names and letters are SVG text, so the browser's find
|
|
14
15
|
* locates them, a reader can select them, and print stylesheets apply.
|
package/dist/useMsaSvgFigure.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { createJBrowseTheme } from '@jbrowse/core/ui/theme';
|
|
3
3
|
import { getSnapshot } from '@jbrowse/mobx-state-tree';
|
|
4
|
-
import {
|
|
4
|
+
import { compareShallow, reaction } from 'mobx';
|
|
5
5
|
import { renderToSvg } from './renderToSvg.js';
|
|
6
6
|
/**
|
|
7
7
|
* The viewer's SVG export of its viewport, as markup for the page to insert.
|
|
8
8
|
* It redraws after the view settles: `delay` ms after the last scroll, zoom,
|
|
9
|
-
* resize or change to the snapshot. A draw a later one overtakes is
|
|
9
|
+
* resize, highlight or change to the snapshot. A draw a later one overtakes is
|
|
10
|
+
* dropped.
|
|
10
11
|
*
|
|
11
12
|
* The figure's row names and letters are SVG text, so the browser's find
|
|
12
13
|
* locates them, a reader can select them, and print stylesheets apply.
|
|
@@ -16,7 +17,13 @@ export function useMsaSvgFigure(model, { theme, includeTracks = false, delay = 3
|
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
let latest = 0;
|
|
18
19
|
const dispose = reaction(() => model.viewInitialized && model.dataInitialized
|
|
19
|
-
? [
|
|
20
|
+
? [
|
|
21
|
+
getSnapshot(model),
|
|
22
|
+
model.width,
|
|
23
|
+
model.height,
|
|
24
|
+
model.resolvedHighlights,
|
|
25
|
+
model.highlightedColumnRuns,
|
|
26
|
+
]
|
|
20
27
|
: undefined, key => {
|
|
21
28
|
if (!key) {
|
|
22
29
|
return;
|
|
@@ -35,7 +42,7 @@ export function useMsaSvgFigure(model, { theme, includeTracks = false, delay = 3
|
|
|
35
42
|
setFigure({ error });
|
|
36
43
|
}
|
|
37
44
|
});
|
|
38
|
-
}, { delay, fireImmediately: true, equals:
|
|
45
|
+
}, { delay, fireImmediately: true, equals: compareShallow });
|
|
39
46
|
return () => {
|
|
40
47
|
latest = -1;
|
|
41
48
|
dispose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMsaSvgFigure.js","sourceRoot":"","sources":["../src/useMsaSvgFigure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useMsaSvgFigure.js","sourceRoot":"","sources":["../src/useMsaSvgFigure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAmB,CAAA;AAW/C;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAmB,EACnB,EACE,KAAK,EACL,aAAa,GAAG,KAAK,EACrB,KAAK,GAAG,GAAG,GACZ,GAA+D,EAAE;IAElE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAA;IACtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,MAAM,OAAO,GAAG,QAAQ,CACtB,GAAG,EAAE,CACH,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe;YAC5C,CAAC,CAAC;gBACE,WAAW,CAAC,KAAK,CAAC;gBAClB,KAAK,CAAC,KAAK;gBACX,KAAK,CAAC,MAAM;gBACZ,KAAK,CAAC,kBAAkB;gBACxB,KAAK,CAAC,qBAAqB;aAC5B;YACH,CAAC,CAAC,SAAS,EACf,GAAG,CAAC,EAAE;YACJ,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAM;YACR,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,MAAM,CAAA;YACrB,WAAW,CAAC,KAAK,EAAE;gBACjB,KAAK,EAAE,KAAK,IAAI,kBAAkB,EAAE;gBACpC,UAAU,EAAE,UAAU;gBACtB,aAAa;aACd,CAAC,CAAC,IAAI,CACL,GAAG,CAAC,EAAE;gBACJ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;gBACpB,CAAC;YACH,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;gBACjB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpB,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;gBACtB,CAAC;YACH,CAAC,CACF,CAAA;QACH,CAAC,EACD,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CACzD,CAAA;QACD,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,CAAC,CAAC,CAAA;YACX,OAAO,EAAE,CAAA;QACX,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC,CAAA;IACxC,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "8.
|
|
1
|
+
export declare const version = "8.4.0";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = '8.
|
|
1
|
+
export const version = '8.4.0';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HierarchyNode } from './hierarchy.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The tree as Newick, in the order it is drawn. An internal node whose name is
|
|
4
|
+
* only its generated id goes unnamed. Each subtree's string is dropped once its
|
|
5
|
+
* parent takes it in, since a caterpillar tree is as deep as it has tips and
|
|
6
|
+
* keeping every one is quadratic.
|
|
7
|
+
*/
|
|
8
|
+
export declare function writeNewick(root: HierarchyNode): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { descendants } from './hierarchy.js';
|
|
2
|
+
// a name holding any of these reads back as grammar unless it is quoted
|
|
3
|
+
const needsQuotes = /[\s(),:;[\]']/;
|
|
4
|
+
function quote(name) {
|
|
5
|
+
return needsQuotes.test(name) ? `'${name.replaceAll("'", "''")}'` : name;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The tree as Newick, in the order it is drawn. An internal node whose name is
|
|
9
|
+
* only its generated id goes unnamed. Each subtree's string is dropped once its
|
|
10
|
+
* parent takes it in, since a caterpillar tree is as deep as it has tips and
|
|
11
|
+
* keeping every one is quadratic.
|
|
12
|
+
*/
|
|
13
|
+
export function writeNewick(root) {
|
|
14
|
+
const written = new Map();
|
|
15
|
+
for (const node of descendants(root).reverse()) {
|
|
16
|
+
const { id, name, length } = node.data;
|
|
17
|
+
let text = '';
|
|
18
|
+
if (node.children) {
|
|
19
|
+
text = `(${node.children.map(c => written.get(c)).join(',')})`;
|
|
20
|
+
for (const child of node.children) {
|
|
21
|
+
written.delete(child);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!(node.children && name === id)) {
|
|
25
|
+
text += quote(name);
|
|
26
|
+
}
|
|
27
|
+
if (length !== undefined) {
|
|
28
|
+
text += `:${length}`;
|
|
29
|
+
}
|
|
30
|
+
written.set(node, text);
|
|
31
|
+
}
|
|
32
|
+
return `${written.get(root)};`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=writeNewick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeNewick.js","sourceRoot":"","sources":["../src/writeNewick.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAI5C,wEAAwE;AACxE,MAAM,WAAW,GAAG,eAAe,CAAA;AAEnC,SAAS,KAAK,CAAC,IAAY;IACzB,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC7C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAA;IAChD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAA;QACtC,IAAI,IAAI,GAAG,EAAE,CAAA;QACb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAA;YAC/D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC;YACpC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAA;QACrB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,IAAI,IAAI,MAAM,EAAE,CAAA;QACtB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACzB,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAE,GAAG,CAAA;AACjC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-msaview",
|
|
3
3
|
"author": "Colin",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.4.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@gmod/newick": "^1.0.3",
|
|
53
|
-
"@jbrowse/svgcanvas": "8.
|
|
53
|
+
"@jbrowse/svgcanvas": "8.4.0",
|
|
54
54
|
"colord": "^2.10.0",
|
|
55
55
|
"flatbush": "^4.6.2",
|
|
56
|
-
"msa-parsers": "8.
|
|
56
|
+
"msa-parsers": "8.4.0"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {
|
|
59
59
|
"clean": "rimraf dist bundle",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FASTA for a block of the alignment: each row's letters from column `start`
|
|
3
|
+
* to `end`, 1-based and inclusive, under its name. Gaps stay in, and a row that
|
|
4
|
+
* ends before `end` is padded with gaps, so every record is the block's width.
|
|
5
|
+
*/
|
|
6
|
+
export function blockFasta(
|
|
7
|
+
rows: readonly (readonly [string, string])[],
|
|
8
|
+
start: number,
|
|
9
|
+
end: number,
|
|
10
|
+
) {
|
|
11
|
+
const width = Math.max(0, end - start + 1)
|
|
12
|
+
return rows
|
|
13
|
+
.map(
|
|
14
|
+
([name, seq]) =>
|
|
15
|
+
`>${name}\n${seq.slice(start - 1, end).padEnd(width, '-')}\n`,
|
|
16
|
+
)
|
|
17
|
+
.join('')
|
|
18
|
+
}
|
package/src/colorSchemes.ts
CHANGED
|
@@ -359,3 +359,23 @@ export default transform(colorSchemes, ([key, val]) => [
|
|
|
359
359
|
key,
|
|
360
360
|
transform(val, ([letter, color]) => [letter, colord(color).toHex()]),
|
|
361
361
|
])
|
|
362
|
+
|
|
363
|
+
const letterTables = new WeakMap<
|
|
364
|
+
Record<string, string>,
|
|
365
|
+
Record<string, string>
|
|
366
|
+
>()
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* A letter map as the renderer looks letters up. The model upper-cases every
|
|
370
|
+
* row before coloring it, so a table keys its letters in upper case and a map
|
|
371
|
+
* may key them in either. The table is cached per map, so its identity is
|
|
372
|
+
* stable enough for the raster cache to key on.
|
|
373
|
+
*/
|
|
374
|
+
export function letterColorTable(map: Record<string, string>) {
|
|
375
|
+
let table = letterTables.get(map)
|
|
376
|
+
if (!table) {
|
|
377
|
+
table = transform(map, ([letter, color]) => [letter.toUpperCase(), color])
|
|
378
|
+
letterTables.set(map, table)
|
|
379
|
+
}
|
|
380
|
+
return table
|
|
381
|
+
}
|
package/src/columnCounts.ts
CHANGED
|
@@ -63,15 +63,21 @@ export class ColumnCounts {
|
|
|
63
63
|
this.totals = new Uint32Array(numColumns)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/** tallies a row, counting the columns past a short row's end as gaps */
|
|
66
67
|
addRow(row: string) {
|
|
67
|
-
const { counts, totals, slotTotals } = this
|
|
68
|
-
const n = Math.min(row.length,
|
|
68
|
+
const { counts, totals, slotTotals, numColumns } = this
|
|
69
|
+
const n = Math.min(row.length, numColumns)
|
|
69
70
|
for (let col = 0; col < n; col++) {
|
|
70
71
|
const slot = slotOf(row.charCodeAt(col))
|
|
71
72
|
counts[col * SLOTS + slot]!++
|
|
72
73
|
totals[col]!++
|
|
73
74
|
slotTotals[slot]!++
|
|
74
75
|
}
|
|
76
|
+
for (let col = n; col < numColumns; col++) {
|
|
77
|
+
counts[col * SLOTS + DASH]!++
|
|
78
|
+
totals[col]!++
|
|
79
|
+
}
|
|
80
|
+
slotTotals[DASH]! += numColumns - n
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
add(col: number, letter: string) {
|
|
@@ -161,11 +167,13 @@ export const numResidueSlots = SLOTS
|
|
|
161
167
|
|
|
162
168
|
/**
|
|
163
169
|
* Tally counts from alignment rows (gapped sequence strings, one per row). The
|
|
164
|
-
* column count
|
|
165
|
-
*
|
|
170
|
+
* column count defaults to the longest row, and a shorter row counts as gapped
|
|
171
|
+
* to the end.
|
|
166
172
|
*/
|
|
167
|
-
export function columnCountsFromRows(
|
|
168
|
-
|
|
173
|
+
export function columnCountsFromRows(
|
|
174
|
+
rows: string[],
|
|
175
|
+
numColumns = rows.reduce((max, row) => Math.max(max, row.length), 0),
|
|
176
|
+
) {
|
|
169
177
|
const counts = new ColumnCounts(numColumns)
|
|
170
178
|
for (const row of rows) {
|
|
171
179
|
counts.addRow(row)
|
|
@@ -12,7 +12,7 @@ export default function CopyButton({
|
|
|
12
12
|
text,
|
|
13
13
|
label = 'Copy to clipboard',
|
|
14
14
|
}: {
|
|
15
|
-
text: string
|
|
15
|
+
text: string | (() => string)
|
|
16
16
|
label?: string
|
|
17
17
|
}) {
|
|
18
18
|
const [copied, setCopied] = useState(false)
|
|
@@ -30,7 +30,7 @@ export default function CopyButton({
|
|
|
30
30
|
variant="contained"
|
|
31
31
|
color="primary"
|
|
32
32
|
onClick={() => {
|
|
33
|
-
copy(text)
|
|
33
|
+
copy(typeof text === 'string' ? text : text())
|
|
34
34
|
setCopied(true)
|
|
35
35
|
clearTimeout(timer.current)
|
|
36
36
|
timer.current = setTimeout(() => {
|
|
@@ -8,6 +8,10 @@ import type { Theme } from '@mui/material'
|
|
|
8
8
|
|
|
9
9
|
export const scrollbarThumbFill = 'rgba(66,119,127,0.3)'
|
|
10
10
|
|
|
11
|
+
// the model's resizeHandleWidth feeds the layout, so a divider keeps its drawn
|
|
12
|
+
// width and widens its target with this much invisible margin each side
|
|
13
|
+
const hitSlop = 4
|
|
14
|
+
|
|
11
15
|
// The scroll thumbs (minimap, vertical scrollbar) and the resize dividers are
|
|
12
16
|
// one widget -- press, drag along an axis, report the pixel delta -- differing
|
|
13
17
|
// only in the affordance they present, so the variant carries the whole
|
|
@@ -71,6 +75,10 @@ export default function DragHandle({
|
|
|
71
75
|
|
|
72
76
|
return (
|
|
73
77
|
<div
|
|
78
|
+
{...(variant === 'resizer' && {
|
|
79
|
+
role: 'separator',
|
|
80
|
+
'aria-orientation': axis === 'x' ? 'vertical' : 'horizontal',
|
|
81
|
+
})}
|
|
74
82
|
onMouseEnter={() => {
|
|
75
83
|
setHovered(true)
|
|
76
84
|
}}
|
|
@@ -87,6 +95,18 @@ export default function DragHandle({
|
|
|
87
95
|
background: hovered ? fillHovered(theme) : fill(theme),
|
|
88
96
|
...style,
|
|
89
97
|
}}
|
|
90
|
-
|
|
98
|
+
>
|
|
99
|
+
{variant === 'resizer' ? (
|
|
100
|
+
<div
|
|
101
|
+
style={{
|
|
102
|
+
position: 'absolute',
|
|
103
|
+
zIndex: 101,
|
|
104
|
+
...(axis === 'x'
|
|
105
|
+
? { top: 0, bottom: 0, left: -hitSlop, right: -hitSlop }
|
|
106
|
+
: { left: 0, right: 0, top: -hitSlop, bottom: -hitSlop }),
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
) : null}
|
|
110
|
+
</div>
|
|
91
111
|
)
|
|
92
112
|
}
|
|
@@ -2,35 +2,15 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { ErrorMessage } from '@jbrowse/core/ui'
|
|
4
4
|
import { ErrorBoundary } from '@jbrowse/core/ui/ErrorBoundary'
|
|
5
|
-
import { Button
|
|
5
|
+
import { Button } from '@mui/material'
|
|
6
6
|
import { observer } from 'mobx-react'
|
|
7
7
|
|
|
8
8
|
import MSAView from './MSAView.tsx'
|
|
9
|
+
import StatusMessage from './StatusMessage.tsx'
|
|
9
10
|
import ImportForm from './import/ImportForm.tsx'
|
|
10
11
|
|
|
11
12
|
import type { MsaViewModel } from '../model.ts'
|
|
12
13
|
|
|
13
|
-
const LoadingSpinner = observer(function ({ model }: { model: MsaViewModel }) {
|
|
14
|
-
const { status } = model
|
|
15
|
-
return (
|
|
16
|
-
<div
|
|
17
|
-
style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 20 }}
|
|
18
|
-
>
|
|
19
|
-
<CircularProgress size={24} />
|
|
20
|
-
<Typography variant="h6">{status?.msg ?? 'Loading...'}</Typography>
|
|
21
|
-
{status?.onCancel ? (
|
|
22
|
-
<Button
|
|
23
|
-
variant="outlined"
|
|
24
|
-
size="small"
|
|
25
|
-
onClick={() => status.onCancel?.()}
|
|
26
|
-
>
|
|
27
|
-
Cancel
|
|
28
|
-
</Button>
|
|
29
|
-
) : null}
|
|
30
|
-
</div>
|
|
31
|
-
)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
14
|
const Reset = observer(function ({
|
|
35
15
|
model,
|
|
36
16
|
error,
|
|
@@ -58,12 +38,15 @@ const Loading = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
58
38
|
const {
|
|
59
39
|
isLoading,
|
|
60
40
|
dataInitialized,
|
|
41
|
+
data,
|
|
61
42
|
error,
|
|
62
43
|
resetCount,
|
|
63
44
|
msaFilehandle,
|
|
64
45
|
treeFilehandle,
|
|
65
46
|
} = model
|
|
66
|
-
const
|
|
47
|
+
const hasData = !!(data.msa || data.tree)
|
|
48
|
+
// a failed load keeps its filehandle, so the error outranks the spinner
|
|
49
|
+
const loading = !error && !!(msaFilehandle || treeFilehandle || isLoading)
|
|
67
50
|
|
|
68
51
|
return (
|
|
69
52
|
<div>
|
|
@@ -76,18 +59,19 @@ const Loading = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
76
59
|
>
|
|
77
60
|
{dataInitialized ? (
|
|
78
61
|
isLoading ? (
|
|
79
|
-
<
|
|
62
|
+
<StatusMessage model={model} variant="page" />
|
|
80
63
|
) : (
|
|
81
64
|
<MSAView model={model} />
|
|
82
65
|
)
|
|
83
|
-
) :
|
|
84
|
-
// checked before the spinner: a failed load keeps its filehandle
|
|
85
|
-
// (only an abort clears it), so hasPendingFilehandle stays true
|
|
66
|
+
) : hasData ? (
|
|
86
67
|
<Reset model={model} error={error} />
|
|
87
|
-
) : hasPendingFilehandle || isLoading ? (
|
|
88
|
-
<LoadingSpinner model={model} />
|
|
89
68
|
) : (
|
|
90
|
-
|
|
69
|
+
<>
|
|
70
|
+
{loading ? <StatusMessage model={model} variant="page" /> : null}
|
|
71
|
+
<div style={{ display: loading ? 'none' : undefined }}>
|
|
72
|
+
<ImportForm model={model} />
|
|
73
|
+
</div>
|
|
74
|
+
</>
|
|
91
75
|
)}
|
|
92
76
|
</ErrorBoundary>
|
|
93
77
|
</div>
|
|
@@ -11,7 +11,7 @@ import VerticalScrollbar from './VerticalScrollbar.tsx'
|
|
|
11
11
|
import Header from './header/Header.tsx'
|
|
12
12
|
import Minimap from './minimap/Minimap.tsx'
|
|
13
13
|
import MSAPanel from './msa/MSAPanel.tsx'
|
|
14
|
-
import { clickColor, hoverColor } from './overlayColors.ts'
|
|
14
|
+
import { clickColor, hoverColor, selectionFill } from './overlayColors.ts'
|
|
15
15
|
import RowPanelHeaders from './rowpanels/RowPanelHeaders.tsx'
|
|
16
16
|
import RowPanels from './rowpanels/RowPanels.tsx'
|
|
17
17
|
import TreeOverview from './tree/TreeOverview.tsx'
|
|
@@ -53,12 +53,19 @@ const TrackColumnIndicator = observer(function ({
|
|
|
53
53
|
resizeHandleWidth,
|
|
54
54
|
totalTrackAreaHeight,
|
|
55
55
|
msaCanvasWidth,
|
|
56
|
+
resolvedSelection,
|
|
56
57
|
} = model
|
|
57
58
|
|
|
58
|
-
// hovered column, then the pinned one, matching
|
|
59
|
+
// the selected columns, the hovered column, then the pinned one, matching
|
|
60
|
+
// the alignment's own overlay
|
|
59
61
|
const bands = [
|
|
60
|
-
{
|
|
61
|
-
|
|
62
|
+
{
|
|
63
|
+
start: resolvedSelection?.startCol,
|
|
64
|
+
end: resolvedSelection?.endCol,
|
|
65
|
+
color: selectionFill,
|
|
66
|
+
},
|
|
67
|
+
{ start: mouseCol, end: mouseCol, color: hoverColor },
|
|
68
|
+
{ start: mouseClickCol, end: mouseClickCol, color: clickColor },
|
|
62
69
|
]
|
|
63
70
|
|
|
64
71
|
return (
|
|
@@ -73,15 +80,15 @@ const TrackColumnIndicator = observer(function ({
|
|
|
73
80
|
pointerEvents: 'none',
|
|
74
81
|
}}
|
|
75
82
|
>
|
|
76
|
-
{bands.map(({
|
|
77
|
-
|
|
83
|
+
{bands.map(({ start, end, color }) =>
|
|
84
|
+
start === undefined || end === undefined ? null : (
|
|
78
85
|
<div
|
|
79
86
|
key={color}
|
|
80
87
|
style={{
|
|
81
88
|
position: 'absolute',
|
|
82
|
-
left:
|
|
89
|
+
left: start * colWidth + scrollX,
|
|
83
90
|
top: 0,
|
|
84
|
-
width: colWidth,
|
|
91
|
+
width: (end - start + 1) * colWidth,
|
|
85
92
|
height: totalTrackAreaHeight,
|
|
86
93
|
backgroundColor: color,
|
|
87
94
|
zIndex: 100,
|
|
@@ -140,7 +147,7 @@ const MSAView = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
140
147
|
<div>
|
|
141
148
|
{viewInitialized ? (
|
|
142
149
|
<>
|
|
143
|
-
<div style={{ height, overflow: '
|
|
150
|
+
<div style={{ height, overflow: 'clip' }}>
|
|
144
151
|
{hideHeader ? null : <Header model={model} />}
|
|
145
152
|
<View model={model} />
|
|
146
153
|
</div>
|