@jbrowse/plugin-linear-genome-view 4.1.1 → 4.1.4
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/esm/BaseLinearDisplay/components/FloatingLabels.js +3 -4
- package/esm/BaseLinearDisplay/components/LinearBlocks.js +3 -1
- package/esm/BaseLinearDisplay/components/LoadingOverlay.d.ts +2 -1
- package/esm/BaseLinearDisplay/components/LoadingOverlay.js +2 -2
- package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.d.ts +1 -0
- package/esm/BaseLinearDisplay/components/NonBlockCanvasDisplayComponent.js +2 -2
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.d.ts +1 -0
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +1 -1
- package/esm/BaseLinearDisplay/components/util.d.ts +8 -8
- package/esm/BaseLinearDisplay/components/util.js +25 -35
- package/esm/BaseLinearDisplay/model.d.ts +19 -9
- package/esm/BaseLinearDisplay/models/SvgFloatingLabels.d.ts +8 -0
- package/esm/BaseLinearDisplay/models/SvgFloatingLabels.js +19 -0
- package/esm/BaseLinearDisplay/models/configSchema.d.ts +2 -2
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -0
- package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +3 -0
- package/esm/BaseLinearDisplay/models/util.d.ts +0 -13
- package/esm/BaseLinearDisplay/renderSvg.js +8 -4
- package/esm/BaseLinearDisplay/types.d.ts +0 -4
- package/esm/BasicTrack/configSchema.d.ts +8 -8
- package/esm/FeatureTrack/configSchema.d.ts +8 -8
- package/esm/LinearBareDisplay/configSchema.d.ts +3 -3
- package/esm/LinearBareDisplay/model.d.ts +19 -9
- package/esm/LinearBasicDisplay/configSchema.d.ts +3 -3
- package/esm/LinearBasicDisplay/model.d.ts +18 -8
- package/esm/LinearFeatureDisplay/configSchema.d.ts +3 -3
- package/esm/LinearFeatureDisplay/model.d.ts +22 -10
- package/esm/LinearGenomeView/components/ExportSvgDialog.js +18 -6
- package/esm/LinearGenomeView/components/Gridlines.js +3 -2
- package/esm/LinearGenomeView/components/Scalebar.js +3 -2
- package/esm/LinearGenomeView/components/ScalebarRefNameLabels.js +2 -2
- package/esm/LinearGenomeView/components/SearchResultsTable.js +2 -7
- package/esm/LinearGenomeView/components/TracksContainer.js +1 -1
- package/esm/LinearGenomeView/lazyDialogs.d.ts +23 -0
- package/esm/LinearGenomeView/lazyDialogs.js +5 -0
- package/esm/LinearGenomeView/menuItems.js +1 -5
- package/esm/LinearGenomeView/model.d.ts +2 -1
- package/esm/LinearGenomeView/model.js +64 -13
- package/esm/LinearGenomeView/types.d.ts +1 -0
- package/esm/index.d.ts +24 -13
- package/esm/index.js +1 -0
- package/esm/searchUtils.js +4 -1
- package/package.json +5 -5
- package/esm/BaseLinearDisplay/models/calculateLabelPositions.d.ts +0 -24
- package/esm/BaseLinearDisplay/models/calculateLabelPositions.js +0 -60
- package/esm/BaseLinearDisplay/models/renderSvg.d.ts +0 -3
- package/esm/BaseLinearDisplay/models/renderSvg.js +0 -55
|
@@ -31,8 +31,8 @@ const FixedLabel = memo(function FixedLabel({ text, color, isOverlay, featureLef
|
|
|
31
31
|
transform: `translate(calc(${featureLeftPx}px - var(--offset-px)), ${y}px)`,
|
|
32
32
|
}, children: text }));
|
|
33
33
|
});
|
|
34
|
-
function FloatingLabel({ text, color, isOverlay, featureLeftPx, featureRightPx, featureId, subfeatureId, labelWidth, y, offsetPx,
|
|
35
|
-
const x = calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx
|
|
34
|
+
function FloatingLabel({ text, color, isOverlay, featureLeftPx, featureRightPx, featureId, subfeatureId, labelWidth, y, offsetPx, tooltip, labelClass, overlayClass, }) {
|
|
35
|
+
const x = calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx);
|
|
36
36
|
return (_jsx("div", { "data-feature-id": featureId, "data-subfeature-id": subfeatureId, "data-tooltip": tooltip, className: isOverlay ? `${labelClass} ${overlayClass}` : labelClass, style: { color, transform: `translate(${x}px,${y}px)` }, children: text }));
|
|
37
37
|
}
|
|
38
38
|
const FloatingLabels = observer(function FloatingLabels({ model, }) {
|
|
@@ -43,7 +43,6 @@ const FloatingLabels = observer(function FloatingLabels({ model, }) {
|
|
|
43
43
|
const { onFeatureClick, onFeatureContextMenu, onMouseMove } = model.renderingProps();
|
|
44
44
|
const fixedLabels = [];
|
|
45
45
|
const floatingLabels = [];
|
|
46
|
-
const viewportLeft = Math.max(0, offsetPx);
|
|
47
46
|
for (const [key, { leftPx, topPx, totalFeatureHeight, floatingLabels: labelData, featureWidth, },] of featureLabels.entries()) {
|
|
48
47
|
const featureVisualBottom = topPx + totalFeatureHeight;
|
|
49
48
|
const featureRightPx = leftPx + featureWidth;
|
|
@@ -57,7 +56,7 @@ const FloatingLabels = observer(function FloatingLabels({ model, }) {
|
|
|
57
56
|
fixedLabels.push(_jsx(FixedLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureId: featureId, subfeatureId: subfeatureId, y: y, tooltip: tooltip, labelClass: classes.label, overlayClass: classes.overlay }, labelKey));
|
|
58
57
|
}
|
|
59
58
|
else {
|
|
60
|
-
floatingLabels.push(_jsx(FloatingLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureRightPx: featureRightPx, featureId: featureId, subfeatureId: subfeatureId, labelWidth: labelWidth, y: y, offsetPx: offsetPx,
|
|
59
|
+
floatingLabels.push(_jsx(FloatingLabel, { text: text, color: color, isOverlay: isOverlay ?? false, featureLeftPx: leftPx, featureRightPx: featureRightPx, featureId: featureId, subfeatureId: subfeatureId, labelWidth: labelWidth, y: y, offsetPx: offsetPx, tooltip: tooltip, labelClass: classes.label, overlayClass: classes.overlay }, labelKey));
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getContainingView } from '@jbrowse/core/util';
|
|
2
3
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
3
4
|
import { observer } from 'mobx-react';
|
|
4
5
|
import RenderedBlocks from "./RenderedBlocks.js";
|
|
@@ -14,8 +15,9 @@ const useStyles = makeStyles()({
|
|
|
14
15
|
const LinearBlocks = observer(function LinearBlocks({ model, }) {
|
|
15
16
|
const { classes } = useStyles();
|
|
16
17
|
const { blockDefinitions } = model;
|
|
18
|
+
const viewModel = getContainingView(model);
|
|
17
19
|
return (_jsx("div", { className: classes.linearBlocks, style: {
|
|
18
|
-
left:
|
|
20
|
+
left: blockDefinitions.offsetPx - viewModel.offsetPx,
|
|
19
21
|
}, children: _jsx(RenderedBlocks, { model: model }) }));
|
|
20
22
|
});
|
|
21
23
|
export default LinearBlocks;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export default function LoadingOverlay({ statusMessage, children, }: {
|
|
1
|
+
export default function LoadingOverlay({ statusMessage, children, height, }: {
|
|
2
2
|
statusMessage?: string;
|
|
3
3
|
children?: React.ReactNode;
|
|
4
|
+
height?: number;
|
|
4
5
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -42,8 +42,8 @@ const useStyles = makeStyles()({
|
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
|
-
export default function LoadingOverlay({ statusMessage, children, }) {
|
|
45
|
+
export default function LoadingOverlay({ statusMessage, children, height, }) {
|
|
46
46
|
const { classes } = useStyles();
|
|
47
47
|
const isLoading = !!statusMessage;
|
|
48
|
-
return (_jsxs("div", { className: classes.container, children: [children, _jsx("span", { className: cx(classes.overlay, isLoading && classes.visible), "data-testid": isLoading ? 'loading-overlay' : undefined, children: _jsx("span", { className: classes.dots, children: statusMessage || 'Loading' }) })] }));
|
|
48
|
+
return (_jsxs("div", { className: classes.container, style: height ? { height } : undefined, children: [children, _jsx("span", { className: cx(classes.overlay, isLoading && classes.visible), "data-testid": isLoading ? 'loading-overlay' : undefined, children: _jsx("span", { className: classes.dots, children: statusMessage || 'Loading' }) })] }));
|
|
49
49
|
}
|
|
@@ -12,6 +12,7 @@ export interface NonBlockCanvasDisplayModel {
|
|
|
12
12
|
statusMessage?: string;
|
|
13
13
|
showLegend?: boolean;
|
|
14
14
|
legendItems?: () => LegendItem[];
|
|
15
|
+
height: number;
|
|
15
16
|
}
|
|
16
17
|
declare const NonBlockCanvasDisplayComponent: ({ model, children, }: {
|
|
17
18
|
model: NonBlockCanvasDisplayModel;
|
|
@@ -31,14 +31,14 @@ const NonBlockCanvasDisplayComponent = observer(function NonBlockCanvasDisplayCo
|
|
|
31
31
|
return error ? (_jsx(BlockErrorMessage, { model: model })) : regionTooLarge ? (model.regionCannotBeRendered()) : (_jsx(DataDisplay, { model: model, children: children }));
|
|
32
32
|
});
|
|
33
33
|
const DataDisplay = observer(function DataDisplay({ model, children, }) {
|
|
34
|
-
const { drawn, loading, showLegend, legendItems, lastDrawnBpPerPx } = model;
|
|
34
|
+
const { drawn, loading, showLegend, legendItems, lastDrawnBpPerPx, height } = model;
|
|
35
35
|
const view = getContainingView(model);
|
|
36
36
|
const items = legendItems?.() ?? [];
|
|
37
37
|
const hasZoomed = lastDrawnBpPerPx !== undefined && lastDrawnBpPerPx !== view.bpPerPx;
|
|
38
38
|
const calculatedLeft = hasZoomed
|
|
39
39
|
? 0
|
|
40
40
|
: (model.lastDrawnOffsetPx ?? 0) - view.offsetPx;
|
|
41
|
-
return (_jsxs("div", { "data-testid": `drawn-${drawn}`, children: [_jsx("div", { style: {
|
|
41
|
+
return (_jsxs("div", { "data-testid": `drawn-${drawn}`, style: { position: 'relative', height }, children: [_jsx("div", { style: {
|
|
42
42
|
position: 'absolute',
|
|
43
43
|
left: calculatedLeft,
|
|
44
44
|
visibility: hasZoomed ? 'hidden' : undefined,
|
|
@@ -6,6 +6,7 @@ declare const ServerSideRenderedBlockContent: ({ model, }: {
|
|
|
6
6
|
statusMessage?: string;
|
|
7
7
|
reactElement?: React.ReactElement;
|
|
8
8
|
isRenderingPending?: boolean;
|
|
9
|
+
displayHeight?: number;
|
|
9
10
|
};
|
|
10
11
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
11
12
|
export default ServerSideRenderedBlockContent;
|
|
@@ -12,7 +12,7 @@ const ServerSideRenderedBlockContent = observer(function ServerSideRenderedBlock
|
|
|
12
12
|
return isValidElement(model.message) ? (model.message) : (_jsx(BlockMsg, { message: `${model.message}`, severity: "info" }));
|
|
13
13
|
}
|
|
14
14
|
else {
|
|
15
|
-
return (_jsx(LoadingOverlay, { statusMessage: model.statusMessage, children: model.reactElement }));
|
|
15
|
+
return (_jsx(LoadingOverlay, { statusMessage: model.statusMessage, height: model.displayHeight, children: model.reactElement }));
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
export default ServerSideRenderedBlockContent;
|
|
@@ -3,19 +3,19 @@ import type { FloatingLabelData, LayoutRecord } from '../types.ts';
|
|
|
3
3
|
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
|
|
4
4
|
export interface FeatureLabelData {
|
|
5
5
|
leftPx: number;
|
|
6
|
-
rightPx: number;
|
|
7
6
|
topPx: number;
|
|
8
7
|
totalFeatureHeight: number;
|
|
9
8
|
floatingLabels: FloatingLabelData[];
|
|
10
9
|
featureWidth: number;
|
|
11
|
-
totalLayoutWidth: number;
|
|
12
10
|
}
|
|
11
|
+
interface RenderingWithLayout {
|
|
12
|
+
layout?: {
|
|
13
|
+
getRectangles?: () => Map<string, LayoutRecord>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function collectLayoutsFromRenderings(renderings: readonly (readonly [unknown, RenderingWithLayout])[]): Map<string, LayoutRecord>[];
|
|
13
17
|
export declare function deduplicateFeatureLabels(layoutFeatures: {
|
|
14
18
|
entries(): IterableIterator<readonly [string, LayoutRecord | undefined]>;
|
|
15
19
|
}, view: LinearGenomeViewModel, assembly: Assembly | undefined, bpPerPx: number): Map<string, FeatureLabelData>;
|
|
16
|
-
export declare function
|
|
17
|
-
export
|
|
18
|
-
leftPx: number;
|
|
19
|
-
rightPx: number;
|
|
20
|
-
};
|
|
21
|
-
export declare function calculateFloatingLabelPosition(featureLeftPx: number, featureRightPx: number, labelWidth: number, offsetPx: number, viewportLeft: number): number;
|
|
20
|
+
export declare function calculateFloatingLabelPosition(featureLeftPx: number, featureRightPx: number, labelWidth: number, offsetPx: number): number;
|
|
21
|
+
export {};
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { clamp } from '@jbrowse/core/util';
|
|
2
|
-
function
|
|
2
|
+
export function collectLayoutsFromRenderings(renderings) {
|
|
3
|
+
const layoutMaps = [];
|
|
4
|
+
for (const [, rendering] of renderings) {
|
|
5
|
+
if (rendering.layout?.getRectangles) {
|
|
6
|
+
layoutMaps.push(rendering.layout.getRectangles());
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return layoutMaps;
|
|
10
|
+
}
|
|
11
|
+
function calculateFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) {
|
|
3
12
|
const canonicalRefName = assembly?.getCanonicalRefName(refName) || refName;
|
|
4
13
|
const leftBpPx = view.bpToPx({
|
|
5
14
|
refName: canonicalRefName,
|
|
@@ -11,28 +20,21 @@ function calculateFeaturePixelPositions(view, assembly, refName, left, right, bp
|
|
|
11
20
|
})?.offsetPx;
|
|
12
21
|
if (leftBpPx !== undefined) {
|
|
13
22
|
const rightEstimate = rightBpPx !== undefined ? rightBpPx : leftBpPx + (right - left) / bpPerPx;
|
|
14
|
-
return
|
|
15
|
-
leftPx: Math.min(leftBpPx, rightEstimate),
|
|
16
|
-
rightPx: Math.max(leftBpPx, rightEstimate),
|
|
17
|
-
};
|
|
23
|
+
return Math.min(leftBpPx, rightEstimate);
|
|
18
24
|
}
|
|
19
25
|
else if (rightBpPx !== undefined) {
|
|
20
26
|
const leftEstimate = rightBpPx - (right - left) / bpPerPx;
|
|
21
|
-
return
|
|
22
|
-
leftPx: Math.min(leftEstimate, rightBpPx),
|
|
23
|
-
rightPx: Math.max(leftEstimate, rightBpPx),
|
|
24
|
-
};
|
|
27
|
+
return Math.min(leftEstimate, rightBpPx);
|
|
25
28
|
}
|
|
26
29
|
return undefined;
|
|
27
30
|
}
|
|
28
|
-
function
|
|
31
|
+
function calculateMultiRegionLeftPx(view, assembly, refName, left, right) {
|
|
29
32
|
const canonicalRefName = assembly?.getCanonicalRefName(refName) || refName;
|
|
30
33
|
const visibleRegions = view.displayedRegions.filter(r => r.refName === canonicalRefName && r.start < right && r.end > left);
|
|
31
34
|
if (visibleRegions.length === 0) {
|
|
32
35
|
return undefined;
|
|
33
36
|
}
|
|
34
37
|
let minLeftPx = Infinity;
|
|
35
|
-
let maxRightPx = -Infinity;
|
|
36
38
|
for (const region of visibleRegions) {
|
|
37
39
|
const regionStart = Math.max(left, region.start);
|
|
38
40
|
const regionEnd = Math.min(right, region.end);
|
|
@@ -46,16 +48,16 @@ function calculateMultiRegionPositions(view, assembly, refName, left, right) {
|
|
|
46
48
|
})?.offsetPx;
|
|
47
49
|
if (startPx !== undefined && endPx !== undefined) {
|
|
48
50
|
minLeftPx = Math.min(minLeftPx, startPx, endPx);
|
|
49
|
-
maxRightPx = Math.max(maxRightPx, startPx, endPx);
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
if (minLeftPx === Infinity
|
|
53
|
+
if (minLeftPx === Infinity) {
|
|
53
54
|
return undefined;
|
|
54
55
|
}
|
|
55
|
-
return
|
|
56
|
+
return minLeftPx;
|
|
56
57
|
}
|
|
57
|
-
function
|
|
58
|
-
return (
|
|
58
|
+
function getFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) {
|
|
59
|
+
return (calculateFeatureLeftPx(view, assembly, refName, left, right, bpPerPx) ??
|
|
60
|
+
calculateMultiRegionLeftPx(view, assembly, refName, left, right));
|
|
59
61
|
}
|
|
60
62
|
export function deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx) {
|
|
61
63
|
const featureLabels = new Map();
|
|
@@ -64,51 +66,39 @@ export function deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx
|
|
|
64
66
|
continue;
|
|
65
67
|
}
|
|
66
68
|
const [, topPx, , , feature] = val;
|
|
67
|
-
const { refName, floatingLabels, totalFeatureHeight, actualTopPx, featureWidth,
|
|
69
|
+
const { refName, floatingLabels, totalFeatureHeight, actualTopPx, featureWidth, featureStartBp, featureEndBp, } = feature;
|
|
68
70
|
const effectiveTopPx = actualTopPx ?? topPx;
|
|
69
71
|
if (!floatingLabels ||
|
|
70
72
|
floatingLabels.length === 0 ||
|
|
71
73
|
!totalFeatureHeight ||
|
|
72
74
|
featureWidth === undefined ||
|
|
73
|
-
totalLayoutWidth === undefined ||
|
|
74
75
|
featureStartBp === undefined ||
|
|
75
76
|
featureEndBp === undefined) {
|
|
76
77
|
continue;
|
|
77
78
|
}
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
79
|
+
const leftPx = getFeatureLeftPx(view, assembly, refName, featureStartBp, featureEndBp, bpPerPx);
|
|
80
|
+
if (leftPx === undefined) {
|
|
80
81
|
continue;
|
|
81
82
|
}
|
|
82
83
|
const existing = featureLabels.get(key);
|
|
83
|
-
if (!existing ||
|
|
84
|
+
if (!existing || leftPx < existing.leftPx) {
|
|
84
85
|
featureLabels.set(key, {
|
|
85
|
-
leftPx
|
|
86
|
-
rightPx: positions.rightPx,
|
|
86
|
+
leftPx,
|
|
87
87
|
topPx: effectiveTopPx,
|
|
88
88
|
totalFeatureHeight,
|
|
89
89
|
floatingLabels,
|
|
90
90
|
featureWidth,
|
|
91
|
-
totalLayoutWidth,
|
|
92
91
|
});
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
return featureLabels;
|
|
96
95
|
}
|
|
97
|
-
export function
|
|
98
|
-
return Math.max(0, offsetPx);
|
|
99
|
-
}
|
|
100
|
-
export function clampToViewport(featureLeftPx, featureRightPx, offsetPx) {
|
|
101
|
-
const viewportLeft = getViewportLeftEdge(offsetPx);
|
|
102
|
-
return {
|
|
103
|
-
leftPx: Math.max(featureLeftPx, viewportLeft),
|
|
104
|
-
rightPx: Math.max(featureRightPx, viewportLeft),
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
export function calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx, viewportLeft) {
|
|
96
|
+
export function calculateFloatingLabelPosition(featureLeftPx, featureRightPx, labelWidth, offsetPx) {
|
|
108
97
|
const featureWidth = featureRightPx - featureLeftPx;
|
|
109
98
|
if (labelWidth > featureWidth) {
|
|
110
99
|
return featureLeftPx - offsetPx;
|
|
111
100
|
}
|
|
101
|
+
const viewportLeft = Math.max(0, offsetPx);
|
|
112
102
|
const leftPx = Math.max(featureLeftPx, viewportLeft);
|
|
113
103
|
const naturalX = leftPx - offsetPx;
|
|
114
104
|
const maxX = featureRightPx - offsetPx - labelWidth;
|
|
@@ -41,6 +41,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
41
41
|
statusMessage?: string;
|
|
42
42
|
reactElement?: React.ReactElement;
|
|
43
43
|
isRenderingPending?: boolean;
|
|
44
|
+
displayHeight?: number;
|
|
44
45
|
};
|
|
45
46
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
46
47
|
renderProps: any;
|
|
@@ -59,10 +60,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
59
60
|
beforeDestroy(): void;
|
|
60
61
|
} & {
|
|
61
62
|
readonly statusMessage: any;
|
|
63
|
+
readonly displayHeight: number | undefined;
|
|
62
64
|
} & {
|
|
63
65
|
afterAttach(): void;
|
|
64
66
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
|
|
65
|
-
configuration: import("
|
|
67
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
66
68
|
maxFeatureScreenDensity: {
|
|
67
69
|
type: string;
|
|
68
70
|
description: string;
|
|
@@ -89,7 +91,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
89
91
|
description: string;
|
|
90
92
|
defaultValue: never[];
|
|
91
93
|
};
|
|
92
|
-
}, import("
|
|
94
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
|
|
93
95
|
showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
94
96
|
showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
95
97
|
}, {
|
|
@@ -380,6 +382,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
380
382
|
statusMessage?: string;
|
|
381
383
|
reactElement?: React.ReactElement;
|
|
382
384
|
isRenderingPending?: boolean;
|
|
385
|
+
displayHeight?: number;
|
|
383
386
|
};
|
|
384
387
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
385
388
|
renderProps: any;
|
|
@@ -398,6 +401,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
398
401
|
beforeDestroy(): void;
|
|
399
402
|
} & {
|
|
400
403
|
readonly statusMessage: any;
|
|
404
|
+
readonly displayHeight: number | undefined;
|
|
401
405
|
} & {
|
|
402
406
|
afterAttach(): void;
|
|
403
407
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>> & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/mobx-state-tree").IMapType<import("@jbrowse/mobx-state-tree").IModelType<{
|
|
@@ -424,6 +428,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
424
428
|
statusMessage?: string;
|
|
425
429
|
reactElement?: React.ReactElement;
|
|
426
430
|
isRenderingPending?: boolean;
|
|
431
|
+
displayHeight?: number;
|
|
427
432
|
};
|
|
428
433
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
429
434
|
renderProps: any;
|
|
@@ -442,6 +447,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
442
447
|
beforeDestroy(): void;
|
|
443
448
|
} & {
|
|
444
449
|
readonly statusMessage: any;
|
|
450
|
+
readonly displayHeight: number | undefined;
|
|
445
451
|
} & {
|
|
446
452
|
afterAttach(): void;
|
|
447
453
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>>;
|
|
@@ -455,7 +461,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
455
461
|
[x: string]: any;
|
|
456
462
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
457
463
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
458
|
-
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("
|
|
464
|
+
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
459
465
|
maxFeatureScreenDensity: {
|
|
460
466
|
type: string;
|
|
461
467
|
description: string;
|
|
@@ -482,7 +488,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
482
488
|
description: string;
|
|
483
489
|
defaultValue: never[];
|
|
484
490
|
};
|
|
485
|
-
}, import("
|
|
491
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>>;
|
|
486
492
|
showLegend: boolean | undefined;
|
|
487
493
|
showTooltips: boolean | undefined;
|
|
488
494
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
@@ -772,6 +778,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
772
778
|
statusMessage?: string;
|
|
773
779
|
reactElement?: React.ReactElement;
|
|
774
780
|
isRenderingPending?: boolean;
|
|
781
|
+
displayHeight?: number;
|
|
775
782
|
};
|
|
776
783
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
777
784
|
renderProps: any;
|
|
@@ -790,10 +797,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
790
797
|
beforeDestroy(): void;
|
|
791
798
|
} & {
|
|
792
799
|
readonly statusMessage: any;
|
|
800
|
+
readonly displayHeight: number | undefined;
|
|
793
801
|
} & {
|
|
794
802
|
afterAttach(): void;
|
|
795
803
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
|
|
796
|
-
configuration: import("
|
|
804
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
797
805
|
maxFeatureScreenDensity: {
|
|
798
806
|
type: string;
|
|
799
807
|
description: string;
|
|
@@ -820,7 +828,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
820
828
|
description: string;
|
|
821
829
|
defaultValue: never[];
|
|
822
830
|
};
|
|
823
|
-
}, import("
|
|
831
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
|
|
824
832
|
showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
825
833
|
showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
826
834
|
}, {
|
|
@@ -1119,6 +1127,7 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
1119
1127
|
statusMessage?: string;
|
|
1120
1128
|
reactElement?: React.ReactElement;
|
|
1121
1129
|
isRenderingPending?: boolean;
|
|
1130
|
+
displayHeight?: number;
|
|
1122
1131
|
};
|
|
1123
1132
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
1124
1133
|
renderProps: any;
|
|
@@ -1137,10 +1146,11 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
1137
1146
|
beforeDestroy(): void;
|
|
1138
1147
|
} & {
|
|
1139
1148
|
readonly statusMessage: any;
|
|
1149
|
+
readonly displayHeight: number | undefined;
|
|
1140
1150
|
} & {
|
|
1141
1151
|
afterAttach(): void;
|
|
1142
1152
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>>;
|
|
1143
|
-
configuration: import("
|
|
1153
|
+
configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
1144
1154
|
maxFeatureScreenDensity: {
|
|
1145
1155
|
type: string;
|
|
1146
1156
|
description: string;
|
|
@@ -1167,12 +1177,12 @@ export declare const BaseLinearDisplay: import("@jbrowse/mobx-state-tree").IMode
|
|
|
1167
1177
|
description: string;
|
|
1168
1178
|
defaultValue: never[];
|
|
1169
1179
|
};
|
|
1170
|
-
}, import("
|
|
1180
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
|
|
1171
1181
|
showLegend: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
1172
1182
|
showTooltips: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>>;
|
|
1173
1183
|
}>>, {
|
|
1174
|
-
id: string;
|
|
1175
1184
|
type: string;
|
|
1185
|
+
id: string;
|
|
1176
1186
|
configuration: import("@jbrowse/mobx-state-tree").ModelSnapshotType<Record<string, any>>;
|
|
1177
1187
|
rpcDriverName: string | undefined;
|
|
1178
1188
|
heightPreConfig: number | undefined;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type FeatureLabelData } from '../components/util.ts';
|
|
2
|
+
interface Props {
|
|
3
|
+
featureLabels: Map<string, FeatureLabelData>;
|
|
4
|
+
offsetPx: number;
|
|
5
|
+
viewWidth: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function SvgFloatingLabels({ featureLabels, offsetPx, viewWidth, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { calculateFloatingLabelPosition, } from "../components/util.js";
|
|
3
|
+
export function SvgFloatingLabels({ featureLabels, offsetPx, viewWidth, }) {
|
|
4
|
+
const elements = [];
|
|
5
|
+
for (const [key, { leftPx, topPx, totalFeatureHeight, floatingLabels, featureWidth },] of featureLabels.entries()) {
|
|
6
|
+
const featureVisualBottom = topPx + totalFeatureHeight;
|
|
7
|
+
const featureRightPx = leftPx + featureWidth;
|
|
8
|
+
for (const [i, { text, relativeY, color, textWidth, isOverlay },] of floatingLabels.entries()) {
|
|
9
|
+
const y = featureVisualBottom + relativeY;
|
|
10
|
+
const x = calculateFloatingLabelPosition(leftPx, featureRightPx, textWidth, offsetPx);
|
|
11
|
+
if (x < 0 || x > viewWidth) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const fontSize = 11;
|
|
15
|
+
elements.push(_jsxs("g", { transform: `translate(${x}, ${y})`, children: [isOverlay ? (_jsx("rect", { x: -1, y: 0, width: textWidth + 2, height: fontSize + 1, fill: "rgba(255, 255, 255, 0.8)" })) : null, _jsx("text", { x: 0, y: fontSize, fontSize: fontSize, fill: color, style: { pointerEvents: 'none' }, children: text })] }, `${key}-${i}`));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return _jsx(_Fragment, { children: elements });
|
|
19
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const baseLinearDisplayConfigSchema: import("
|
|
1
|
+
declare const baseLinearDisplayConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
2
|
maxFeatureScreenDensity: {
|
|
3
3
|
type: string;
|
|
4
4
|
description: string;
|
|
@@ -25,5 +25,5 @@ declare const baseLinearDisplayConfigSchema: import("node_modules/@jbrowse/core/
|
|
|
25
25
|
description: string;
|
|
26
26
|
defaultValue: never[];
|
|
27
27
|
};
|
|
28
|
-
}, import("
|
|
28
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
|
|
29
29
|
export default baseLinearDisplayConfigSchema;
|
|
@@ -35,6 +35,7 @@ declare const blockState: import("@jbrowse/mobx-state-tree").IModelType<{
|
|
|
35
35
|
statusMessage?: string;
|
|
36
36
|
reactElement?: React.ReactElement;
|
|
37
37
|
isRenderingPending?: boolean;
|
|
38
|
+
displayHeight?: number;
|
|
38
39
|
};
|
|
39
40
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
40
41
|
renderProps: any;
|
|
@@ -53,6 +54,7 @@ declare const blockState: import("@jbrowse/mobx-state-tree").IModelType<{
|
|
|
53
54
|
beforeDestroy(): void;
|
|
54
55
|
} & {
|
|
55
56
|
readonly statusMessage: any;
|
|
57
|
+
readonly displayHeight: number | undefined;
|
|
56
58
|
} & {
|
|
57
59
|
afterAttach(): void;
|
|
58
60
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
2
|
import type { FeatureDensityStats } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
3
|
-
export interface RenderProps {
|
|
4
|
-
rendererType: any;
|
|
5
|
-
renderArgs: Record<string, any>;
|
|
6
|
-
renderProps: Record<string, any>;
|
|
7
|
-
displayError: unknown;
|
|
8
|
-
rpcManager: {
|
|
9
|
-
call: (...args: unknown[]) => void;
|
|
10
|
-
};
|
|
11
|
-
cannotBeRenderedReason: string;
|
|
12
|
-
}
|
|
13
|
-
export interface ErrorProps {
|
|
14
|
-
displayError: string;
|
|
15
|
-
}
|
|
16
3
|
export declare function getDisplayStr(totalBytes: number): string;
|
|
17
4
|
export declare function getId(id: string, index: string | number): string;
|
|
18
5
|
export declare function getFeatureDensityStatsPre(self: {
|
|
@@ -2,11 +2,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Fragment } from 'react';
|
|
3
3
|
import { createJBrowseTheme } from '@jbrowse/core/ui';
|
|
4
4
|
import { ReactRendering, getContainingView, getSession, } from '@jbrowse/core/util';
|
|
5
|
+
import CompositeMap from '@jbrowse/core/util/compositeMap';
|
|
5
6
|
import SVGLegend from "./SVGLegend.js";
|
|
7
|
+
import { collectLayoutsFromRenderings, deduplicateFeatureLabels, } from "./components/util.js";
|
|
8
|
+
import { SvgFloatingLabels } from "./models/SvgFloatingLabels.js";
|
|
6
9
|
import BlockState, { renderBlockData, } from "./models/serverSideRenderedBlock.js";
|
|
7
10
|
import { getId } from "./models/util.js";
|
|
8
11
|
import { ErrorBox } from "../LinearGenomeView/SVGErrorBox.js";
|
|
9
|
-
import { calculateLabelPositions } from "./models/calculateLabelPositions.js";
|
|
10
12
|
export async function renderBaseLinearDisplaySvg(self, opts) {
|
|
11
13
|
const { height, id } = self;
|
|
12
14
|
const { overrideHeight } = opts;
|
|
@@ -42,11 +44,13 @@ export async function renderBaseLinearDisplaySvg(self, opts) {
|
|
|
42
44
|
}),
|
|
43
45
|
];
|
|
44
46
|
}));
|
|
47
|
+
const layoutMaps = collectLayoutsFromRenderings(renderings);
|
|
48
|
+
const layoutFeatures = new CompositeMap(layoutMaps);
|
|
45
49
|
const { assemblyManager } = getSession(self);
|
|
46
|
-
const { offsetPx } = view;
|
|
50
|
+
const { offsetPx, bpPerPx } = view;
|
|
47
51
|
const assemblyName = view.assemblyNames[0];
|
|
48
52
|
const assembly = assemblyName ? assemblyManager.get(assemblyName) : undefined;
|
|
49
|
-
const
|
|
53
|
+
const featureLabels = deduplicateFeatureLabels(layoutFeatures, view, assembly, bpPerPx);
|
|
50
54
|
const labelsClipId = getId(id, 'labels');
|
|
51
55
|
const theme = createJBrowseTheme(opts.theme);
|
|
52
56
|
const legendItems = self.showLegend ? self.legendItems(theme) : [];
|
|
@@ -55,5 +59,5 @@ export async function renderBaseLinearDisplaySvg(self, opts) {
|
|
|
55
59
|
const offset = offsetPx - viewOffsetPx;
|
|
56
60
|
const clipid = getId(id, index);
|
|
57
61
|
return (_jsxs(Fragment, { children: [_jsx("defs", { children: _jsx("clipPath", { id: clipid, children: _jsx("rect", { x: 0, y: 0, width: widthPx, height: overrideHeight || height }) }) }), _jsx("g", { transform: `translate(${offset} 0)`, children: _jsx("g", { clipPath: `url(#${clipid})`, children: _jsx(ReactRendering, { rendering: rendering }) }) })] }, `frag-${index}`));
|
|
58
|
-
}), _jsx("defs", { children: _jsx("clipPath", { id: labelsClipId, children: _jsx("rect", { x: 0, y: 0, width: width, height: overrideHeight || height }) }) }), _jsx("g", { clipPath: `url(#${labelsClipId})`, children:
|
|
62
|
+
}), _jsx("defs", { children: _jsx("clipPath", { id: labelsClipId, children: _jsx("rect", { x: 0, y: 0, width: width, height: overrideHeight || height }) }) }), _jsx("g", { clipPath: `url(#${labelsClipId})`, children: _jsx(SvgFloatingLabels, { featureLabels: featureLabels, offsetPx: offsetPx, viewWidth: width }) }), legendItems.length > 0 ? (_jsx(SVGLegend, { items: legendItems, width: width, legendAreaWidth: opts.legendWidth })) : null] }));
|
|
59
63
|
}
|
|
@@ -18,12 +18,9 @@ export interface FloatingLabelData {
|
|
|
18
18
|
tooltip?: string;
|
|
19
19
|
}
|
|
20
20
|
export interface LayoutFeatureMetadata {
|
|
21
|
-
label?: string;
|
|
22
|
-
description?: string;
|
|
23
21
|
refName: string;
|
|
24
22
|
floatingLabels?: FloatingLabelData[];
|
|
25
23
|
totalFeatureHeight?: number;
|
|
26
|
-
totalLayoutWidth?: number;
|
|
27
24
|
featureWidth?: number;
|
|
28
25
|
actualTopPx?: number;
|
|
29
26
|
featureStartBp?: number;
|
|
@@ -33,7 +30,6 @@ export declare function createSubfeatureLabelMetadata(args: {
|
|
|
33
30
|
refName: string;
|
|
34
31
|
floatingLabels: FloatingLabelData[];
|
|
35
32
|
totalFeatureHeight: number;
|
|
36
|
-
totalLayoutWidth: number;
|
|
37
33
|
featureWidth: number;
|
|
38
34
|
actualTopPx: number;
|
|
39
35
|
featureStartBp: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
|
-
declare const configSchema: (pluginManager: PluginManager) => import("
|
|
2
|
+
declare const configSchema: (pluginManager: PluginManager) => import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
3
3
|
name: {
|
|
4
4
|
description: string;
|
|
5
5
|
type: string;
|
|
@@ -31,7 +31,7 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
|
|
|
31
31
|
defaultValue: string;
|
|
32
32
|
};
|
|
33
33
|
adapter: import("@jbrowse/mobx-state-tree").IAnyModelType;
|
|
34
|
-
textSearching: import("
|
|
34
|
+
textSearching: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
35
35
|
indexingAttributes: {
|
|
36
36
|
type: string;
|
|
37
37
|
description: string;
|
|
@@ -43,9 +43,9 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
|
|
|
43
43
|
defaultValue: string[];
|
|
44
44
|
};
|
|
45
45
|
textSearchAdapter: import("@jbrowse/mobx-state-tree").IAnyModelType;
|
|
46
|
-
}, import("
|
|
46
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
47
47
|
displays: import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IAnyModelType>;
|
|
48
|
-
formatDetails: import("
|
|
48
|
+
formatDetails: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
49
49
|
feature: {
|
|
50
50
|
type: string;
|
|
51
51
|
description: string;
|
|
@@ -68,8 +68,8 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
|
|
|
68
68
|
defaultValue: number;
|
|
69
69
|
description: string;
|
|
70
70
|
};
|
|
71
|
-
}, import("
|
|
72
|
-
formatAbout: import("
|
|
71
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
72
|
+
formatAbout: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
73
73
|
config: {
|
|
74
74
|
type: string;
|
|
75
75
|
description: string;
|
|
@@ -80,6 +80,6 @@ declare const configSchema: (pluginManager: PluginManager) => import("node_modul
|
|
|
80
80
|
type: string;
|
|
81
81
|
defaultValue: boolean;
|
|
82
82
|
};
|
|
83
|
-
}, import("
|
|
84
|
-
}, import("
|
|
83
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
|
|
84
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "trackId">>, "trackId">>;
|
|
85
85
|
export default configSchema;
|