@jbrowse/plugin-breakpoint-split-view 4.1.3 → 4.1.5
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.
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { Dialog, ErrorMessage } from '@jbrowse/core/ui';
|
|
4
4
|
import { getSession, useLocalStorage } from '@jbrowse/core/util';
|
|
5
|
-
import { Button, Checkbox, CircularProgress, DialogActions, DialogContent, FormControlLabel, MenuItem, TextField, Typography, } from '@mui/material';
|
|
6
|
-
function LoadingMessage() {
|
|
7
|
-
return (_jsxs("div", { children: [_jsx(CircularProgress, { size: 20, style: { marginRight: 20 } }),
|
|
5
|
+
import { Button, Checkbox, CircularProgress, DialogActions, DialogContent, FormControlLabel, MenuItem, TextField, ToggleButton, ToggleButtonGroup, Typography, } from '@mui/material';
|
|
6
|
+
function LoadingMessage({ format }) {
|
|
7
|
+
return (_jsxs("div", { children: [_jsx(CircularProgress, { size: 20, style: { marginRight: 20 } }), _jsxs(Typography, { display: "inline", children: ["Creating ", format.toUpperCase()] })] }));
|
|
8
8
|
}
|
|
9
9
|
function TextField2({ children, ...rest }) {
|
|
10
10
|
return (_jsx("div", { children: _jsx(TextField, { ...rest, children: children }) }));
|
|
@@ -19,12 +19,23 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
19
19
|
const [showGridlines, setShowGridlines] = useSvgLocal('gridlines', false);
|
|
20
20
|
const [loading, setLoading] = useState(false);
|
|
21
21
|
const [error, setError] = useState();
|
|
22
|
+
const [format, setFormat] = useSvgLocal('format', 'svg');
|
|
22
23
|
const [filename, setFilename] = useSvgLocal('file', 'jbrowse.svg');
|
|
23
24
|
const [trackLabels, setTrackLabels] = useSvgLocal('tracklabels', 'offset');
|
|
24
25
|
const [themeName, setThemeName] = useSvgLocal('theme', session.themeName || 'default');
|
|
25
|
-
return (_jsxs(Dialog, { open: true, onClose: handleClose, title: "Export
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
return (_jsxs(Dialog, { open: true, onClose: handleClose, title: "Export image", children: [_jsxs(DialogContent, { children: [error ? (_jsx(ErrorMessage, { error: error })) : loading ? (_jsx(LoadingMessage, { format: format })) : null, _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx(TextField, { helperText: "filename", value: filename, onChange: event => {
|
|
27
|
+
setFilename(event.target.value);
|
|
28
|
+
} }), _jsxs(ToggleButtonGroup, { value: format, exclusive: true, onChange: (_event, value) => {
|
|
29
|
+
if (value) {
|
|
30
|
+
setFormat(value);
|
|
31
|
+
if (filename.endsWith('.svg') && value === 'png') {
|
|
32
|
+
setFilename(filename.replace(/\.svg$/, '.png'));
|
|
33
|
+
}
|
|
34
|
+
else if (filename.endsWith('.png') && value === 'svg') {
|
|
35
|
+
setFilename(filename.replace(/\.png$/, '.svg'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, size: "small", children: [_jsx(ToggleButton, { value: "svg", children: "SVG" }), _jsx(ToggleButton, { value: "png", children: "PNG" })] })] }), _jsxs(TextField2, { select: true, label: "Track label positioning", variant: "outlined", style: { width: 150 }, value: trackLabels, onChange: event => {
|
|
28
39
|
setTrackLabels(event.target.value);
|
|
29
40
|
}, children: [_jsx(MenuItem, { value: "offset", children: "Offset" }), _jsx(MenuItem, { value: "overlay", children: "Overlay" }), _jsx(MenuItem, { value: "left", children: "Left" }), _jsx(MenuItem, { value: "none", children: "None" })] }), _jsx("br", {}), session.allThemes ? (_jsx(TextField2, { select: true, label: "Theme", variant: "outlined", value: themeName, onChange: event => {
|
|
30
41
|
setThemeName(event.target.value);
|
|
@@ -40,6 +51,7 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
40
51
|
try {
|
|
41
52
|
await model.exportSvg({
|
|
42
53
|
rasterizeLayers,
|
|
54
|
+
format,
|
|
43
55
|
filename,
|
|
44
56
|
trackLabels,
|
|
45
57
|
themeName,
|
|
@@ -92,6 +92,8 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
92
92
|
readonly trackHeightsWithResizeHandles: number;
|
|
93
93
|
readonly height: number;
|
|
94
94
|
readonly totalBp: number;
|
|
95
|
+
getNonElidedRegionCount(bpPerPx: number): number;
|
|
96
|
+
getInterRegionPaddingPx(bpPerPx: number): number;
|
|
95
97
|
readonly maxBpPerPx: number;
|
|
96
98
|
readonly minBpPerPx: number;
|
|
97
99
|
readonly error: unknown;
|
|
@@ -150,7 +152,6 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
150
152
|
end: number;
|
|
151
153
|
}[];
|
|
152
154
|
horizontalScroll(distance: number): number;
|
|
153
|
-
center(): void;
|
|
154
155
|
showAllRegions(): void;
|
|
155
156
|
showAllRegionsInAssembly(assemblyName?: string): void;
|
|
156
157
|
setDraggingTrackId(idx?: string): void;
|
|
@@ -457,6 +458,8 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
457
458
|
readonly trackHeightsWithResizeHandles: number;
|
|
458
459
|
readonly height: number;
|
|
459
460
|
readonly totalBp: number;
|
|
461
|
+
getNonElidedRegionCount(bpPerPx: number): number;
|
|
462
|
+
getInterRegionPaddingPx(bpPerPx: number): number;
|
|
460
463
|
readonly maxBpPerPx: number;
|
|
461
464
|
readonly minBpPerPx: number;
|
|
462
465
|
readonly error: unknown;
|
|
@@ -515,7 +518,6 @@ export default function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
515
518
|
end: number;
|
|
516
519
|
}[];
|
|
517
520
|
horizontalScroll(distance: number): number;
|
|
518
|
-
center(): void;
|
|
519
521
|
showAllRegions(): void;
|
|
520
522
|
showAllRegionsInAssembly(assemblyName?: string): void;
|
|
521
523
|
setDraggingTrackId(idx?: string): void;
|
|
@@ -42,7 +42,38 @@ export default function stateModelFactory(pluginManager) {
|
|
|
42
42
|
const { renderToSvg } = await import("./svgcomponents/SVGBreakpointSplitView.js");
|
|
43
43
|
const html = await renderToSvg(self, opts);
|
|
44
44
|
const { saveAs } = await import('file-saver-es');
|
|
45
|
-
|
|
45
|
+
if (opts.format === 'png') {
|
|
46
|
+
const img = new Image();
|
|
47
|
+
const svgBlob = new Blob([html], { type: 'image/svg+xml' });
|
|
48
|
+
const url = URL.createObjectURL(svgBlob);
|
|
49
|
+
await new Promise((resolve, reject) => {
|
|
50
|
+
img.onload = () => {
|
|
51
|
+
const canvas = document.createElement('canvas');
|
|
52
|
+
canvas.width = img.width;
|
|
53
|
+
canvas.height = img.height;
|
|
54
|
+
const ctx = canvas.getContext('2d');
|
|
55
|
+
ctx.drawImage(img, 0, 0);
|
|
56
|
+
URL.revokeObjectURL(url);
|
|
57
|
+
canvas.toBlob(blob => {
|
|
58
|
+
if (blob) {
|
|
59
|
+
saveAs(blob, opts.filename || 'image.png');
|
|
60
|
+
resolve();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
reject(new Error(`Failed to create PNG. The image may be too large (${img.width}x${img.height}). Try reducing the view size or use SVG format.`));
|
|
64
|
+
}
|
|
65
|
+
}, 'image/png');
|
|
66
|
+
};
|
|
67
|
+
img.onerror = () => {
|
|
68
|
+
URL.revokeObjectURL(url);
|
|
69
|
+
reject(new Error('Failed to load SVG for PNG conversion'));
|
|
70
|
+
};
|
|
71
|
+
img.src = url;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
saveAs(new Blob([html], { type: 'image/svg+xml' }), opts.filename || 'image.svg');
|
|
76
|
+
}
|
|
46
77
|
},
|
|
47
78
|
}))
|
|
48
79
|
.views(self => ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-breakpoint-split-view",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JBrowse 2 breakpoint detail split view",
|
|
6
6
|
"keywords": [
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@gmod/vcf": "^7.0.0",
|
|
25
25
|
"@jbrowse/mobx-state-tree": "^5.5.0",
|
|
26
|
-
"@mui/icons-material": "^7.3.
|
|
27
|
-
"@mui/material": "^7.3.
|
|
26
|
+
"@mui/icons-material": "^7.3.8",
|
|
27
|
+
"@mui/material": "^7.3.8",
|
|
28
28
|
"@types/file-saver-es": "^2.0.3",
|
|
29
29
|
"file-saver-es": "^2.0.5",
|
|
30
30
|
"mobx": "^6.15.0",
|
|
31
31
|
"mobx-react": "^9.2.1",
|
|
32
|
-
"@jbrowse/
|
|
33
|
-
"@jbrowse/
|
|
32
|
+
"@jbrowse/core": "^4.1.5",
|
|
33
|
+
"@jbrowse/plugin-linear-genome-view": "^4.1.5"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=16.8.4",
|