react-msaview 8.4.0 → 9.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 +503 -89
- package/bundle/index.js.map +4 -4
- package/dist/components/MSAView.js +2 -2
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/MSAViewer.d.ts +1 -3
- package/dist/components/MSAViewer.js +1 -2
- package/dist/components/MSAViewer.js.map +1 -1
- package/dist/components/ResizeHandles.js +1 -1
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/Track.js +1 -1
- package/dist/components/Track.js.map +1 -1
- package/dist/components/dialogs/ExportSVGDialog.js +2 -2
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/header/GoToBox.d.ts +332 -0
- package/dist/components/header/GoToBox.js +14 -4
- package/dist/components/header/GoToBox.js.map +1 -1
- package/dist/components/header/settingsMenuItems.js +4 -1
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/tree/CladeLabels.js +3 -3
- package/dist/components/tree/CladeLabels.js.map +1 -1
- package/dist/components/tree/TreeCanvas.js +4 -4
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +4 -4
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeOverview.js +10 -5
- package/dist/components/tree/TreeOverview.js.map +1 -1
- package/dist/components/tree/TreePanel.js +6 -2
- package/dist/components/tree/TreePanel.js.map +1 -1
- package/dist/components/tree/TreeRuler.js +2 -2
- package/dist/components/tree/TreeRuler.js.map +1 -1
- package/dist/components/tree/cladeBrackets.d.ts +8 -10
- package/dist/components/tree/cladeBrackets.js +7 -6
- package/dist/components/tree/cladeBrackets.js.map +1 -1
- package/dist/components/tree/clickMap.d.ts +2 -0
- package/dist/components/tree/clickMap.js.map +1 -1
- package/dist/components/tree/ellipsize.d.ts +8 -0
- package/dist/components/tree/ellipsize.js +20 -0
- package/dist/components/tree/ellipsize.js.map +1 -0
- package/dist/components/tree/renderTreeCanvas.js +30 -26
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/tree/renderTreeMouseover.js +1 -1
- package/dist/components/tree/renderTreeMouseover.js.map +1 -1
- package/dist/constants.d.ts +6 -3
- package/dist/constants.js +16 -6
- package/dist/constants.js.map +1 -1
- package/dist/measureTextCanvas.js +2 -2
- package/dist/measureTextCanvas.js.map +1 -1
- package/dist/model/treeModel.d.ts +14 -20
- package/dist/model/treeModel.js +16 -23
- package/dist/model/treeModel.js.map +1 -1
- package/dist/model.d.ts +192 -213
- package/dist/model.js +112 -104
- package/dist/model.js.map +1 -1
- package/dist/renderToSvg.js +24 -22
- package/dist/renderToSvg.js.map +1 -1
- package/dist/svgTestUtil.d.ts +252 -356
- package/dist/tipLabels.d.ts +8 -0
- package/dist/tipLabels.js +46 -0
- package/dist/tipLabels.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -6
- package/src/components/MSAView.tsx +2 -2
- package/src/components/MSAViewer.tsx +1 -5
- package/src/components/ResizeHandles.tsx +1 -1
- package/src/components/Track.tsx +1 -1
- package/src/components/dialogs/ExportSVGDialog.tsx +2 -2
- package/src/components/header/GoToBox.tsx +18 -4
- package/src/components/header/settingsMenuItems.ts +8 -0
- package/src/components/tree/CladeLabels.tsx +3 -3
- package/src/components/tree/TreeCanvas.tsx +10 -4
- package/src/components/tree/TreeCanvasBlock.tsx +4 -4
- package/src/components/tree/TreeOverview.tsx +10 -5
- package/src/components/tree/TreePanel.tsx +8 -2
- package/src/components/tree/TreeRuler.tsx +7 -3
- package/src/components/tree/cladeBrackets.ts +10 -17
- package/src/components/tree/clickMap.ts +2 -0
- package/src/components/tree/ellipsize.ts +24 -0
- package/src/components/tree/renderTreeCanvas.ts +42 -30
- package/src/components/tree/renderTreeMouseover.ts +1 -1
- package/src/constants.ts +17 -6
- package/src/measureTextCanvas.ts +2 -2
- package/src/model/treeModel.ts +17 -27
- package/src/model.ts +133 -128
- package/src/renderToSvg.tsx +24 -22
- package/src/tipLabels.ts +51 -0
- package/src/version.ts +1 -1
package/dist/model.js
CHANGED
|
@@ -15,7 +15,7 @@ import { visibleColRange } from './components/msa/visibleColRange.js';
|
|
|
15
15
|
import TrackBlocks from './components/tracks/TrackBlocks.js';
|
|
16
16
|
import { cladeGutterWidth } from './components/tree/cladeBrackets.js';
|
|
17
17
|
import { scaleBarLength } from './components/tree/scaleBar.js';
|
|
18
|
-
import { cladeHighlightAlpha, cladeHighlightColor, defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultFeaturePanelWidth, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultScrollZoomAxis, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows,
|
|
18
|
+
import { cladeHighlightAlpha, cladeHighlightColor, defaultAllowedGappyness, defaultColWidth, defaultColorSchemeName, defaultCurrentAlignment, defaultDrawMsaLetters, defaultFeaturePanelWidth, defaultHeight, defaultHideGaps, defaultRowHeight, defaultScrollX, defaultScrollY, defaultScrollZoom, defaultScrollZoomAxis, defaultShowDomainLegend, defaultShowDomains, defaultSubFeatureRows, fontSizeFor, labelFitFontSize, maxCellSize, maxFitTreeWidth, maxTreeAreaShare, maxInlineSnapshotBytes as defaultMaxInlineSnapshotBytes, maxNeighborJoiningRows, minColWidth, minLetterColWidth, minLetterRowHeight, minRowHeight, minTreeWidth, pxPerTreeDepth, rowPanelHeaderHeight, rowTintAlpha, scrollZoomAxes, segmentFeatureTypes, segmentShades, treeScaleBarHeight, } from './constants.js';
|
|
19
19
|
import { createPaletteMap } from './createPaletteMap.js';
|
|
20
20
|
import { exportFileName } from './exportFileName.js';
|
|
21
21
|
import { featureField, featureName } from './featureFields.js';
|
|
@@ -23,7 +23,6 @@ import { featuresToAnnotations } from './featuresLayer.js';
|
|
|
23
23
|
import { fetchTextWithProgress, isAbortError } from './fetchUtils.js';
|
|
24
24
|
import { flatToTree } from './flatToTree.js';
|
|
25
25
|
import { calcDepthToLeaf, clusterLayout, collapse, find, forEachDescendant, hierarchy, layoutTree, leafIndex, leaves, maxLength, mrca, nodeCoveringRows, setBrLength, sort, sum as hierarchySum, } from './hierarchy.js';
|
|
26
|
-
import { measureTextCanvas } from './measureTextCanvas.js';
|
|
27
26
|
import { DataModelF } from './model/DataModel.js';
|
|
28
27
|
import { DialogQueueSessionMixin } from './model/DialogQueue.js';
|
|
29
28
|
import { MSAModelF } from './model/msaModel.js';
|
|
@@ -37,6 +36,7 @@ import { resolveScale } from './scales.js';
|
|
|
37
36
|
import { buildSeqPosIndex } from './seqPosToGlobalCol.js';
|
|
38
37
|
import { maxBitsFor } from './sequenceLogo.js';
|
|
39
38
|
import { stripDefault } from './stripDefault.js';
|
|
39
|
+
import { treeTips, widestLabel } from './tipLabels.js';
|
|
40
40
|
import { computeRowInsertions, dropBlanks, len, outlineColor, skipBlanks, withAlpha, } from './util.js';
|
|
41
41
|
import { saveAs } from './vendor/fileSaver.js';
|
|
42
42
|
import { writeNewick } from './writeNewick.js';
|
|
@@ -303,7 +303,6 @@ export const preservedOnReset = new Set([
|
|
|
303
303
|
'drawNodeLabels',
|
|
304
304
|
'showTreeOverview',
|
|
305
305
|
'overviewHeight',
|
|
306
|
-
'autoTreeAreaWidth',
|
|
307
306
|
'turnedOffTracks',
|
|
308
307
|
'trackHeights',
|
|
309
308
|
'hideGaps',
|
|
@@ -1224,25 +1223,25 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1224
1223
|
* #action
|
|
1225
1224
|
*/
|
|
1226
1225
|
setMSAFilehandle(msaFilehandle) {
|
|
1227
|
-
self.msaFilehandle = msaFilehandle;
|
|
1226
|
+
self.msaFilehandle = cast(msaFilehandle);
|
|
1228
1227
|
},
|
|
1229
1228
|
/**
|
|
1230
1229
|
* #action
|
|
1231
1230
|
*/
|
|
1232
1231
|
setTreeFilehandle(treeFilehandle) {
|
|
1233
|
-
self.treeFilehandle = treeFilehandle;
|
|
1232
|
+
self.treeFilehandle = cast(treeFilehandle);
|
|
1234
1233
|
},
|
|
1235
1234
|
/**
|
|
1236
1235
|
* #action
|
|
1237
1236
|
*/
|
|
1238
1237
|
setTreeMetadataFilehandle(treeMetadataFilehandle) {
|
|
1239
|
-
self.treeMetadataFilehandle = treeMetadataFilehandle;
|
|
1238
|
+
self.treeMetadataFilehandle = cast(treeMetadataFilehandle);
|
|
1240
1239
|
},
|
|
1241
1240
|
/**
|
|
1242
1241
|
* #action
|
|
1243
1242
|
*/
|
|
1244
1243
|
setGFFFilehandle(gffFilehandle) {
|
|
1245
|
-
self.gffFilehandle = gffFilehandle;
|
|
1244
|
+
self.gffFilehandle = cast(gffFilehandle);
|
|
1246
1245
|
},
|
|
1247
1246
|
/**
|
|
1248
1247
|
* #action
|
|
@@ -1420,10 +1419,10 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1420
1419
|
* the row table: extra fields per row, keyed by row name, which the
|
|
1421
1420
|
* `encodings` channels read. It is stored as the JSON string
|
|
1422
1421
|
* `data.treeMetadata`, the name that travels in existing links, so the
|
|
1423
|
-
* inline size limit and `treeMetadataFilehandle` cover it.
|
|
1424
|
-
* reads it on every layout, so a malformed user-supplied file
|
|
1425
|
-
* instead of throwing out of rendering, and every field is a
|
|
1426
|
-
* the time a scale sorts it.
|
|
1422
|
+
* inline size limit and `treeMetadataFilehandle` cover it. The tree area
|
|
1423
|
+
* fit reads it on every layout, so a malformed user-supplied file
|
|
1424
|
+
* returns {} instead of throwing out of rendering, and every field is a
|
|
1425
|
+
* string by the time a scale sorts it.
|
|
1427
1426
|
*/
|
|
1428
1427
|
get rowData() {
|
|
1429
1428
|
const text = self.data.treeMetadata;
|
|
@@ -1544,11 +1543,93 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1544
1543
|
* where no clade draws a bar or a label.
|
|
1545
1544
|
*/
|
|
1546
1545
|
get cladeGutterWidth() {
|
|
1547
|
-
return cladeGutterWidth(
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1546
|
+
return cladeGutterWidth(self.clades);
|
|
1547
|
+
},
|
|
1548
|
+
/**
|
|
1549
|
+
* #getter
|
|
1550
|
+
* whether a tree draws beside the labels: false for a file with no
|
|
1551
|
+
* tree, and with drawTree off
|
|
1552
|
+
*/
|
|
1553
|
+
get treeDrawn() {
|
|
1554
|
+
return self.drawTree && !this.noTree;
|
|
1555
|
+
},
|
|
1556
|
+
/**
|
|
1557
|
+
* #getter
|
|
1558
|
+
* the leaf names of the whole tree and its depth in levels. The fit
|
|
1559
|
+
* reads these, so a collapse or a focus leaves the tree area as it is
|
|
1560
|
+
*/
|
|
1561
|
+
get treeTips() {
|
|
1562
|
+
return treeTips(this.tree);
|
|
1563
|
+
},
|
|
1564
|
+
/**
|
|
1565
|
+
* #getter
|
|
1566
|
+
* the widest tip label at labelFitFontSize, measured whether or not a
|
|
1567
|
+
* zoom hides the labels
|
|
1568
|
+
*/
|
|
1569
|
+
get maxTipLabelWidth() {
|
|
1570
|
+
return widestLabel(this.treeTips.names.map(name => this.rowDataOf(name)?.genome || name), labelFitFontSize);
|
|
1571
|
+
},
|
|
1572
|
+
/**
|
|
1573
|
+
* #getter
|
|
1574
|
+
* the px the tip labels take across the tree area: the widest label at
|
|
1575
|
+
* labelFitFontSize and the gaps either side of it, or 0 with drawLabels
|
|
1576
|
+
* off
|
|
1577
|
+
*/
|
|
1578
|
+
get labelColumnWidth() {
|
|
1579
|
+
return self.drawLabels
|
|
1580
|
+
? this.maxTipLabelWidth + (this.treeDrawn ? 10 : 6)
|
|
1581
|
+
: 0;
|
|
1582
|
+
},
|
|
1583
|
+
/**
|
|
1584
|
+
* #getter
|
|
1585
|
+
* the tree area width while treeAreaWidth is undefined: the label column
|
|
1586
|
+
* beside a tree that widens with its depth, up to maxTreeAreaShare of the
|
|
1587
|
+
* view, or the room the row panels leave where there is no alignment.
|
|
1588
|
+
* Where that binds, the tree keeps minTreeWidth and the renderer
|
|
1589
|
+
* ellipsizes the labels
|
|
1590
|
+
*/
|
|
1591
|
+
get fittedTreeAreaWidth() {
|
|
1592
|
+
const chrome = self.marginLeft + this.cladeGutterWidth;
|
|
1593
|
+
const tree = this.treeDrawn
|
|
1594
|
+
? (self.treeWidth ??
|
|
1595
|
+
clamp(this.treeTips.depth * pxPerTreeDepth, minTreeWidth, maxFitTreeWidth))
|
|
1596
|
+
: 0;
|
|
1597
|
+
const fit = chrome + tree + this.labelColumnWidth;
|
|
1598
|
+
const room = self.viewInitialized
|
|
1599
|
+
? this.numColumns > 0
|
|
1600
|
+
? self.width * maxTreeAreaShare
|
|
1601
|
+
: self.width - this.rowPanelsWidth - self.resizeHandleWidth
|
|
1602
|
+
: Infinity;
|
|
1603
|
+
const cap = Math.max(room, chrome + Math.min(tree, minTreeWidth));
|
|
1604
|
+
return Math.ceil(Math.min(fit, cap));
|
|
1605
|
+
},
|
|
1606
|
+
/**
|
|
1607
|
+
* #getter
|
|
1608
|
+
* the width of the area the tree and its labels draw in, px:
|
|
1609
|
+
* treeAreaWidth where set, the fit otherwise
|
|
1610
|
+
*/
|
|
1611
|
+
get effectiveTreeAreaWidth() {
|
|
1612
|
+
return self.treeAreaWidth ?? this.fittedTreeAreaWidth;
|
|
1613
|
+
},
|
|
1614
|
+
/**
|
|
1615
|
+
* #getter
|
|
1616
|
+
* the width of the tree, px: treeWidth where set, otherwise the tree
|
|
1617
|
+
* area less the label column, which a zoom hiding the labels gives to
|
|
1618
|
+
* the tree
|
|
1619
|
+
*/
|
|
1620
|
+
get effectiveTreeWidth() {
|
|
1621
|
+
const labels = this.showTreeText ? this.labelColumnWidth : 0;
|
|
1622
|
+
return (self.treeWidth ??
|
|
1623
|
+
Math.max(minTreeWidth, Math.floor(this.effectiveTreeAreaWidth -
|
|
1624
|
+
self.marginLeft -
|
|
1625
|
+
this.cladeGutterWidth -
|
|
1626
|
+
labels)));
|
|
1627
|
+
},
|
|
1628
|
+
/**
|
|
1629
|
+
* #getter
|
|
1630
|
+
*/
|
|
1631
|
+
get showTreeText() {
|
|
1632
|
+
return self.drawLabels && self.rowHeight >= minLetterRowHeight;
|
|
1552
1633
|
},
|
|
1553
1634
|
/**
|
|
1554
1635
|
* #getter
|
|
@@ -1714,7 +1795,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1714
1795
|
*/
|
|
1715
1796
|
get msaAreaWidth() {
|
|
1716
1797
|
return (self.width -
|
|
1717
|
-
|
|
1798
|
+
this.effectiveTreeAreaWidth -
|
|
1718
1799
|
this.rowPanelsWidth -
|
|
1719
1800
|
self.resizeHandleWidth);
|
|
1720
1801
|
},
|
|
@@ -1724,7 +1805,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1724
1805
|
* margin and the bracket gutter
|
|
1725
1806
|
*/
|
|
1726
1807
|
get treeAreaWidthMinusMargin() {
|
|
1727
|
-
return
|
|
1808
|
+
return (this.effectiveTreeAreaWidth - self.marginLeft - this.cladeGutterWidth);
|
|
1728
1809
|
},
|
|
1729
1810
|
/**
|
|
1730
1811
|
* #getter
|
|
@@ -1860,7 +1941,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1860
1941
|
* #getter
|
|
1861
1942
|
*/
|
|
1862
1943
|
get fontSize() {
|
|
1863
|
-
return
|
|
1944
|
+
return fontSizeFor(self.rowHeight);
|
|
1864
1945
|
},
|
|
1865
1946
|
/**
|
|
1866
1947
|
* #getter
|
|
@@ -1959,17 +2040,18 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
1959
2040
|
/**
|
|
1960
2041
|
* #getter
|
|
1961
2042
|
* `root` laid out on new nodes in row and branch-length units, read in
|
|
1962
|
-
* pixels through `rowHeight` and `
|
|
1963
|
-
* node in it as they are, and an observer reading a node's `x`
|
|
1964
|
-
* observes the size it scales by.
|
|
2043
|
+
* pixels through `rowHeight` and `effectiveTreeWidth`. A zoom leaves it
|
|
2044
|
+
* and every node in it as they are, and an observer reading a node's `x`
|
|
2045
|
+
* or `len` observes the size it scales by.
|
|
1965
2046
|
*/
|
|
1966
2047
|
get treeLayout() {
|
|
2048
|
+
const treeWidth = () => this.effectiveTreeWidth;
|
|
1967
2049
|
return layoutTree(this.root, {
|
|
1968
2050
|
get rowHeight() {
|
|
1969
2051
|
return self.rowHeight;
|
|
1970
2052
|
},
|
|
1971
2053
|
get treeWidth() {
|
|
1972
|
-
return
|
|
2054
|
+
return treeWidth();
|
|
1973
2055
|
},
|
|
1974
2056
|
});
|
|
1975
2057
|
},
|
|
@@ -2002,11 +2084,11 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2002
2084
|
},
|
|
2003
2085
|
/**
|
|
2004
2086
|
* #getter
|
|
2005
|
-
* x-position of the farthest tip in a phylogram, px:
|
|
2006
|
-
* a tree with no branch lengths (drawn as a cladogram)
|
|
2087
|
+
* x-position of the farthest tip in a phylogram, px: effectiveTreeWidth,
|
|
2088
|
+
* or 0 for a tree with no branch lengths (drawn as a cladogram)
|
|
2007
2089
|
*/
|
|
2008
2090
|
get maxBranchLength() {
|
|
2009
|
-
return this.rootToTipLength ?
|
|
2091
|
+
return this.rootToTipLength ? this.effectiveTreeWidth : 0;
|
|
2010
2092
|
},
|
|
2011
2093
|
/**
|
|
2012
2094
|
* #getter
|
|
@@ -2015,7 +2097,9 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2015
2097
|
*/
|
|
2016
2098
|
get pxPerBranchLength() {
|
|
2017
2099
|
const max = this.rootToTipLength;
|
|
2018
|
-
return this.showBranchLenEffective && max
|
|
2100
|
+
return this.showBranchLenEffective && max
|
|
2101
|
+
? this.effectiveTreeWidth / max
|
|
2102
|
+
: 0;
|
|
2019
2103
|
},
|
|
2020
2104
|
/**
|
|
2021
2105
|
* #getter
|
|
@@ -2056,12 +2140,6 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2056
2140
|
self.colWidth >= minLetterColWidth &&
|
|
2057
2141
|
self.colWidth > self.rowHeight / 2);
|
|
2058
2142
|
},
|
|
2059
|
-
/**
|
|
2060
|
-
* #getter
|
|
2061
|
-
*/
|
|
2062
|
-
get showTreeText() {
|
|
2063
|
-
return self.drawLabels && self.rowHeight >= minLetterRowHeight;
|
|
2064
|
-
},
|
|
2065
2143
|
}))
|
|
2066
2144
|
.views(self => {
|
|
2067
2145
|
// a spec is a frozen value, so it keys its computed until setColumnTracks
|
|
@@ -2183,48 +2261,6 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2183
2261
|
};
|
|
2184
2262
|
})
|
|
2185
2263
|
.views(self => ({
|
|
2186
|
-
/**
|
|
2187
|
-
* #getter
|
|
2188
|
-
*/
|
|
2189
|
-
get labelWidthMap() {
|
|
2190
|
-
const { showTreeText, leaves } = self;
|
|
2191
|
-
// gated on the renderer's label condition, so hidden labels reserve no
|
|
2192
|
-
// gutter. Measured once at a reference size and scaled by
|
|
2193
|
-
// labelWidthScale: re-measuring per vertical-zoom frame cost ~200ms on a
|
|
2194
|
-
// 50k-leaf tree
|
|
2195
|
-
return showTreeText
|
|
2196
|
-
? new Map(leaves.map(node => {
|
|
2197
|
-
const { name } = node.data;
|
|
2198
|
-
// `||`, matching renderTreeLabels: an empty genome falls back
|
|
2199
|
-
// to the row name
|
|
2200
|
-
const displayName = self.rowDataOf(name)?.genome || name;
|
|
2201
|
-
return [
|
|
2202
|
-
name,
|
|
2203
|
-
measureTextCanvas(displayName, labelReferenceFontSize),
|
|
2204
|
-
];
|
|
2205
|
-
}))
|
|
2206
|
-
: new Map();
|
|
2207
|
-
},
|
|
2208
|
-
/**
|
|
2209
|
-
* #getter
|
|
2210
|
-
* factor turning a labelWidthMap entry into its width at the current
|
|
2211
|
-
* font size
|
|
2212
|
-
*/
|
|
2213
|
-
get labelWidthScale() {
|
|
2214
|
-
return self.fontSize / labelReferenceFontSize;
|
|
2215
|
-
},
|
|
2216
|
-
get labelsWidth() {
|
|
2217
|
-
// a loop, not Math.max(...): spreading passes one argument per leaf,
|
|
2218
|
-
// and the ~125k argument limit throws RangeError on the 230k-tip COVID
|
|
2219
|
-
// tree
|
|
2220
|
-
let max = 0;
|
|
2221
|
-
for (const width of this.labelWidthMap.values()) {
|
|
2222
|
-
if (width > max) {
|
|
2223
|
-
max = width;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
return max * this.labelWidthScale;
|
|
2227
|
-
},
|
|
2228
2264
|
/**
|
|
2229
2265
|
* #getter
|
|
2230
2266
|
*/
|
|
@@ -2663,7 +2699,7 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
2663
2699
|
* or when the tree area is too narrow for one
|
|
2664
2700
|
*/
|
|
2665
2701
|
get treeScaleBar() {
|
|
2666
|
-
return scaleBarLength(self.pxPerBranchLength, self.
|
|
2702
|
+
return scaleBarLength(self.pxPerBranchLength, self.effectiveTreeAreaWidth - self.marginLeft * 2);
|
|
2667
2703
|
},
|
|
2668
2704
|
/**
|
|
2669
2705
|
* #getter
|
|
@@ -4166,34 +4202,6 @@ function stateModelFactory({ maxInlineSnapshotBytes = defaultMaxInlineSnapshotBy
|
|
|
4166
4202
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
4167
4203
|
self.columns;
|
|
4168
4204
|
}));
|
|
4169
|
-
// with autoTreeAreaWidth and no tree drawn, size the tree area to the
|
|
4170
|
-
// labels. Gated on noTree/!drawTree so it does not loop with the
|
|
4171
|
-
// treeWidth autorun below
|
|
4172
|
-
addDisposer(self, autorun(() => {
|
|
4173
|
-
if (self.autoTreeAreaWidth &&
|
|
4174
|
-
(self.noTree || !self.drawTree) &&
|
|
4175
|
-
self.labelsWidth) {
|
|
4176
|
-
self.setTreeAreaWidth(self.labelsWidth + self.marginLeft + 12 + self.cladeGutterWidth);
|
|
4177
|
-
}
|
|
4178
|
-
}));
|
|
4179
|
-
// treeWidth follows the tree area less the labels. A non-default
|
|
4180
|
-
// snapshot treeWidth (jbrowse-plugin-msaview opens at 100 in a 200px
|
|
4181
|
-
// area) is kept until the tree area changes. Not a getter, because
|
|
4182
|
-
// labelsWidth is measured off leaves laid out against treeWidth.
|
|
4183
|
-
let pinnedAreaWidth = self.treeWidth === defaultTreeWidth ? undefined : self.treeAreaWidth;
|
|
4184
|
-
addDisposer(self, autorun(() => {
|
|
4185
|
-
const areaWidth = self.treeAreaWidth;
|
|
4186
|
-
const labelsWidth = self.labelsWidth;
|
|
4187
|
-
if (pinnedAreaWidth === areaWidth) {
|
|
4188
|
-
return;
|
|
4189
|
-
}
|
|
4190
|
-
pinnedAreaWidth = undefined;
|
|
4191
|
-
self.setTreeWidth(Math.max(50, areaWidth -
|
|
4192
|
-
labelsWidth -
|
|
4193
|
-
10 -
|
|
4194
|
-
self.marginLeft -
|
|
4195
|
-
self.cladeGutterWidth));
|
|
4196
|
-
}));
|
|
4197
4205
|
},
|
|
4198
4206
|
}))
|
|
4199
4207
|
.postProcessSnapshot(({ data, columnTracks, ...rest }) => ({
|