react-msaview 8.4.1 → 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 +66 -66
- 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/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 +72 -37
- package/dist/model.js +108 -100
- 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 +36 -28
- 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 +3 -3
- 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/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 +129 -124
- package/src/renderToSvg.tsx +24 -22
- package/src/tipLabels.ts +51 -0
- package/src/version.ts +1 -1
package/dist/model.d.ts
CHANGED
|
@@ -49,11 +49,11 @@ export declare const preservedOnReset: Set<string>;
|
|
|
49
49
|
*/
|
|
50
50
|
declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
51
51
|
maxInlineSnapshotBytes?: number;
|
|
52
|
-
}): import("@jbrowse/mobx-state-tree").IModelType<Omit<Omit<Omit<{}, "
|
|
52
|
+
}): import("@jbrowse/mobx-state-tree").IModelType<Omit<Omit<Omit<{}, "drawLabels" | "drawNodeBubbles" | "drawNodeLabels" | "drawTree" | "labelsAlignRight" | "overviewHeight" | "showBranchLen" | "showTreeOverview" | "treeAreaWidth" | "treeOrder" | "treeWidth"> & {
|
|
53
53
|
drawLabels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
54
54
|
labelsAlignRight: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
55
|
-
treeAreaWidth: import("@jbrowse/mobx-state-tree").
|
|
56
|
-
treeWidth: import("@jbrowse/mobx-state-tree").
|
|
55
|
+
treeAreaWidth: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<number>>;
|
|
56
|
+
treeWidth: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<number>>;
|
|
57
57
|
showBranchLen: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
58
58
|
treeOrder: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<TreeOrder>, [undefined]>;
|
|
59
59
|
drawTree: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
@@ -61,7 +61,6 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
61
61
|
drawNodeLabels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
62
62
|
showTreeOverview: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
63
63
|
overviewHeight: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<number>, [undefined]>;
|
|
64
|
-
autoTreeAreaWidth: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
65
64
|
}, "bgColor" | "colorSchemeName" | "customColorScheme" | "msaFormat" | "showColumnStats"> & {
|
|
66
65
|
bgColor: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
67
66
|
colorSchemeName: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
@@ -643,11 +642,10 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
643
642
|
removeActiveDialog(): void;
|
|
644
643
|
queueDialog(cb: (doneCallback: () => void) => [import("@jbrowse/core/util").DialogComponentType, unknown]): void;
|
|
645
644
|
} & {
|
|
646
|
-
setTreeAreaWidth(n: number): void;
|
|
647
|
-
setTreeWidth(n: number): void;
|
|
645
|
+
setTreeAreaWidth(n: number | undefined): void;
|
|
646
|
+
setTreeWidth(n: number | undefined): void;
|
|
648
647
|
setLabelsAlignRight(arg: boolean): void;
|
|
649
648
|
setDrawTree(arg: boolean): void;
|
|
650
|
-
setAutoTreeAreaWidth(arg: boolean): void;
|
|
651
649
|
setShowBranchLen(arg: boolean): void;
|
|
652
650
|
setTreeOrder(order: TreeOrder): void;
|
|
653
651
|
setDrawNodeBubbles(arg: boolean): void;
|
|
@@ -1105,10 +1103,10 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1105
1103
|
* the row table: extra fields per row, keyed by row name, which the
|
|
1106
1104
|
* `encodings` channels read. It is stored as the JSON string
|
|
1107
1105
|
* `data.treeMetadata`, the name that travels in existing links, so the
|
|
1108
|
-
* inline size limit and `treeMetadataFilehandle` cover it.
|
|
1109
|
-
* reads it on every layout, so a malformed user-supplied file
|
|
1110
|
-
* instead of throwing out of rendering, and every field is a
|
|
1111
|
-
* the time a scale sorts it.
|
|
1106
|
+
* inline size limit and `treeMetadataFilehandle` cover it. The tree area
|
|
1107
|
+
* fit reads it on every layout, so a malformed user-supplied file
|
|
1108
|
+
* returns {} instead of throwing out of rendering, and every field is a
|
|
1109
|
+
* string by the time a scale sorts it.
|
|
1112
1110
|
*/
|
|
1113
1111
|
readonly rowData: Record<string, Record<string, string> | undefined>;
|
|
1114
1112
|
/**
|
|
@@ -1168,6 +1166,60 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1168
1166
|
* where no clade draws a bar or a label.
|
|
1169
1167
|
*/
|
|
1170
1168
|
readonly cladeGutterWidth: number;
|
|
1169
|
+
/**
|
|
1170
|
+
* #getter
|
|
1171
|
+
* whether a tree draws beside the labels: false for a file with no
|
|
1172
|
+
* tree, and with drawTree off
|
|
1173
|
+
*/
|
|
1174
|
+
readonly treeDrawn: boolean;
|
|
1175
|
+
/**
|
|
1176
|
+
* #getter
|
|
1177
|
+
* the leaf names of the whole tree and its depth in levels. The fit
|
|
1178
|
+
* reads these, so a collapse or a focus leaves the tree area as it is
|
|
1179
|
+
*/
|
|
1180
|
+
readonly treeTips: {
|
|
1181
|
+
names: string[];
|
|
1182
|
+
depth: number;
|
|
1183
|
+
};
|
|
1184
|
+
/**
|
|
1185
|
+
* #getter
|
|
1186
|
+
* the widest tip label at labelFitFontSize, measured whether or not a
|
|
1187
|
+
* zoom hides the labels
|
|
1188
|
+
*/
|
|
1189
|
+
readonly maxTipLabelWidth: number;
|
|
1190
|
+
/**
|
|
1191
|
+
* #getter
|
|
1192
|
+
* the px the tip labels take across the tree area: the widest label at
|
|
1193
|
+
* labelFitFontSize and the gaps either side of it, or 0 with drawLabels
|
|
1194
|
+
* off
|
|
1195
|
+
*/
|
|
1196
|
+
readonly labelColumnWidth: number;
|
|
1197
|
+
/**
|
|
1198
|
+
* #getter
|
|
1199
|
+
* the tree area width while treeAreaWidth is undefined: the label column
|
|
1200
|
+
* beside a tree that widens with its depth, up to maxTreeAreaShare of the
|
|
1201
|
+
* view, or the room the row panels leave where there is no alignment.
|
|
1202
|
+
* Where that binds, the tree keeps minTreeWidth and the renderer
|
|
1203
|
+
* ellipsizes the labels
|
|
1204
|
+
*/
|
|
1205
|
+
readonly fittedTreeAreaWidth: number;
|
|
1206
|
+
/**
|
|
1207
|
+
* #getter
|
|
1208
|
+
* the width of the area the tree and its labels draw in, px:
|
|
1209
|
+
* treeAreaWidth where set, the fit otherwise
|
|
1210
|
+
*/
|
|
1211
|
+
readonly effectiveTreeAreaWidth: number;
|
|
1212
|
+
/**
|
|
1213
|
+
* #getter
|
|
1214
|
+
* the width of the tree, px: treeWidth where set, otherwise the tree
|
|
1215
|
+
* area less the label column, which a zoom hiding the labels gives to
|
|
1216
|
+
* the tree
|
|
1217
|
+
*/
|
|
1218
|
+
readonly effectiveTreeWidth: number;
|
|
1219
|
+
/**
|
|
1220
|
+
* #getter
|
|
1221
|
+
*/
|
|
1222
|
+
readonly showTreeText: boolean;
|
|
1171
1223
|
/**
|
|
1172
1224
|
* #getter
|
|
1173
1225
|
*/
|
|
@@ -1357,9 +1409,9 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1357
1409
|
/**
|
|
1358
1410
|
* #getter
|
|
1359
1411
|
* `root` laid out on new nodes in row and branch-length units, read in
|
|
1360
|
-
* pixels through `rowHeight` and `
|
|
1361
|
-
* node in it as they are, and an observer reading a node's `x`
|
|
1362
|
-
* observes the size it scales by.
|
|
1412
|
+
* pixels through `rowHeight` and `effectiveTreeWidth`. A zoom leaves it
|
|
1413
|
+
* and every node in it as they are, and an observer reading a node's `x`
|
|
1414
|
+
* or `len` observes the size it scales by.
|
|
1363
1415
|
*/
|
|
1364
1416
|
readonly treeLayout: {
|
|
1365
1417
|
root: import("./hierarchy.ts").LaidOutNode<NodeWithIds>;
|
|
@@ -1387,8 +1439,8 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1387
1439
|
readonly rootToTipLength: number;
|
|
1388
1440
|
/**
|
|
1389
1441
|
* #getter
|
|
1390
|
-
* x-position of the farthest tip in a phylogram, px:
|
|
1391
|
-
* a tree with no branch lengths (drawn as a cladogram)
|
|
1442
|
+
* x-position of the farthest tip in a phylogram, px: effectiveTreeWidth,
|
|
1443
|
+
* or 0 for a tree with no branch lengths (drawn as a cladogram)
|
|
1392
1444
|
*/
|
|
1393
1445
|
readonly maxBranchLength: number;
|
|
1394
1446
|
/**
|
|
@@ -1421,10 +1473,6 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1421
1473
|
* #getter
|
|
1422
1474
|
*/
|
|
1423
1475
|
readonly showMsaLetters: boolean;
|
|
1424
|
-
/**
|
|
1425
|
-
* #getter
|
|
1426
|
-
*/
|
|
1427
|
-
readonly showTreeText: boolean;
|
|
1428
1476
|
} & {
|
|
1429
1477
|
/**
|
|
1430
1478
|
* #getter
|
|
@@ -1456,17 +1504,6 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
1456
1504
|
*/
|
|
1457
1505
|
readonly columnTrackModels: BasicTrack[];
|
|
1458
1506
|
} & {
|
|
1459
|
-
/**
|
|
1460
|
-
* #getter
|
|
1461
|
-
*/
|
|
1462
|
-
readonly labelWidthMap: Map<string, number>;
|
|
1463
|
-
/**
|
|
1464
|
-
* #getter
|
|
1465
|
-
* factor turning a labelWidthMap entry into its width at the current
|
|
1466
|
-
* font size
|
|
1467
|
-
*/
|
|
1468
|
-
readonly labelWidthScale: number;
|
|
1469
|
-
readonly labelsWidth: number;
|
|
1470
1507
|
/**
|
|
1471
1508
|
* #getter
|
|
1472
1509
|
*/
|
|
@@ -2271,8 +2308,8 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2271
2308
|
msaFormat: import("msa-parsers").MSAFormat | undefined;
|
|
2272
2309
|
drawLabels: boolean;
|
|
2273
2310
|
labelsAlignRight: boolean;
|
|
2274
|
-
treeAreaWidth: number;
|
|
2275
|
-
treeWidth: number;
|
|
2311
|
+
treeAreaWidth: number | undefined;
|
|
2312
|
+
treeWidth: number | undefined;
|
|
2276
2313
|
showBranchLen: boolean;
|
|
2277
2314
|
treeOrder: TreeOrder;
|
|
2278
2315
|
drawTree: boolean;
|
|
@@ -2280,7 +2317,6 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2280
2317
|
drawNodeLabels: boolean;
|
|
2281
2318
|
showTreeOverview: boolean;
|
|
2282
2319
|
overviewHeight: number;
|
|
2283
|
-
autoTreeAreaWidth: boolean;
|
|
2284
2320
|
columnTracks: ColumnTrackSpec[];
|
|
2285
2321
|
id: string;
|
|
2286
2322
|
showDomains: boolean;
|
|
@@ -2409,8 +2445,8 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2409
2445
|
msaFormat: import("msa-parsers").MSAFormat | undefined;
|
|
2410
2446
|
drawLabels: boolean;
|
|
2411
2447
|
labelsAlignRight: boolean;
|
|
2412
|
-
treeAreaWidth: number;
|
|
2413
|
-
treeWidth: number;
|
|
2448
|
+
treeAreaWidth: number | undefined;
|
|
2449
|
+
treeWidth: number | undefined;
|
|
2414
2450
|
showBranchLen: boolean;
|
|
2415
2451
|
treeOrder: TreeOrder;
|
|
2416
2452
|
drawTree: boolean;
|
|
@@ -2418,7 +2454,6 @@ declare function stateModelFactory({ maxInlineSnapshotBytes, }?: {
|
|
|
2418
2454
|
drawNodeLabels: boolean;
|
|
2419
2455
|
showTreeOverview: boolean;
|
|
2420
2456
|
overviewHeight: number;
|
|
2421
|
-
autoTreeAreaWidth: boolean;
|
|
2422
2457
|
columnTracks?: undefined;
|
|
2423
2458
|
id: string;
|
|
2424
2459
|
showDomains: boolean;
|
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',
|
|
@@ -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 }) => ({
|