@jbrowse/plugin-circular-view 2.17.0 → 3.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/dist/BaseChordDisplay/components/BaseChordDisplay.d.ts +1 -2
- package/dist/BaseChordDisplay/components/BaseChordDisplay.js +8 -7
- package/dist/BaseChordDisplay/components/DisplayError.d.ts +1 -2
- package/dist/BaseChordDisplay/components/DisplayError.js +2 -11
- package/dist/BaseChordDisplay/components/Loading.d.ts +1 -2
- package/dist/BaseChordDisplay/components/Loading.js +4 -34
- package/dist/BaseChordDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -3
- package/dist/BaseChordDisplay/{models/configSchema.js → configSchema.js} +1 -10
- package/dist/BaseChordDisplay/index.d.ts +2 -2
- package/dist/BaseChordDisplay/index.js +2 -2
- package/{esm/BaseChordDisplay/models → dist/BaseChordDisplay}/model.d.ts +12 -54
- package/dist/BaseChordDisplay/{models/model.js → model.js} +31 -94
- package/dist/BaseChordDisplay/renderReaction.d.ts +27 -0
- package/dist/BaseChordDisplay/{models/renderReaction.js → renderReaction.js} +5 -13
- package/dist/CircularView/components/CircularView.d.ts +2 -3
- package/dist/CircularView/components/CircularView.js +22 -31
- package/dist/CircularView/components/Controls.d.ts +2 -3
- package/dist/CircularView/components/Controls.js +33 -70
- package/dist/CircularView/components/ExportSvgDialog.d.ts +2 -3
- package/dist/CircularView/components/ExportSvgDialog.js +32 -67
- package/dist/CircularView/components/ImportForm.d.ts +2 -3
- package/dist/CircularView/components/ImportForm.js +12 -42
- package/dist/CircularView/components/Ruler.d.ts +3 -4
- package/dist/CircularView/components/Ruler.js +18 -37
- package/dist/CircularView/index.d.ts +1 -1
- package/dist/CircularView/index.js +18 -8
- package/dist/CircularView/{models/model.d.ts → model.d.ts} +9 -158
- package/dist/CircularView/{models/model.js → model.js} +25 -224
- package/dist/CircularView/{models/slices.d.ts → slices.d.ts} +1 -1
- package/dist/CircularView/svgcomponents/SVGBackground.d.ts +1 -2
- package/dist/CircularView/svgcomponents/SVGBackground.js +3 -6
- package/dist/CircularView/svgcomponents/SVGCircularView.d.ts +1 -1
- package/dist/CircularView/svgcomponents/SVGCircularView.js +5 -17
- package/dist/CircularView/{models/viewportVisibleRegion.js → viewportVisibleRegion.js} +0 -70
- package/dist/LaunchCircularView/index.d.ts +1 -1
- package/dist/LaunchCircularView/index.js +1 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -7
- package/esm/BaseChordDisplay/components/BaseChordDisplay.d.ts +1 -2
- package/esm/BaseChordDisplay/components/BaseChordDisplay.js +8 -7
- package/esm/BaseChordDisplay/components/DisplayError.d.ts +1 -2
- package/esm/BaseChordDisplay/components/DisplayError.js +2 -8
- package/esm/BaseChordDisplay/components/Loading.d.ts +1 -2
- package/esm/BaseChordDisplay/components/Loading.js +4 -11
- package/esm/BaseChordDisplay/{models/configSchema.d.ts → configSchema.d.ts} +0 -3
- package/esm/BaseChordDisplay/{models/configSchema.js → configSchema.js} +1 -10
- package/esm/BaseChordDisplay/index.d.ts +2 -2
- package/esm/BaseChordDisplay/index.js +2 -2
- package/{dist/BaseChordDisplay/models → esm/BaseChordDisplay}/model.d.ts +12 -54
- package/esm/BaseChordDisplay/{models/model.js → model.js} +32 -92
- package/esm/BaseChordDisplay/renderReaction.d.ts +27 -0
- package/esm/BaseChordDisplay/{models/renderReaction.js → renderReaction.js} +5 -10
- package/esm/CircularView/components/CircularView.d.ts +2 -3
- package/esm/CircularView/components/CircularView.js +22 -31
- package/esm/CircularView/components/Controls.d.ts +2 -3
- package/esm/CircularView/components/Controls.js +33 -47
- package/esm/CircularView/components/ExportSvgDialog.d.ts +2 -3
- package/esm/CircularView/components/ExportSvgDialog.js +32 -44
- package/esm/CircularView/components/ImportForm.d.ts +2 -3
- package/esm/CircularView/components/ImportForm.js +12 -19
- package/esm/CircularView/components/Ruler.d.ts +3 -4
- package/esm/CircularView/components/Ruler.js +19 -35
- package/esm/CircularView/index.d.ts +1 -1
- package/esm/CircularView/index.js +1 -1
- package/esm/CircularView/{models/model.d.ts → model.d.ts} +9 -158
- package/esm/CircularView/{models/model.js → model.js} +9 -218
- package/esm/CircularView/{models/slices.d.ts → slices.d.ts} +1 -1
- package/esm/CircularView/{models/slices.js → slices.js} +1 -1
- package/esm/CircularView/svgcomponents/SVGBackground.d.ts +1 -2
- package/esm/CircularView/svgcomponents/SVGBackground.js +3 -3
- package/esm/CircularView/svgcomponents/SVGCircularView.d.ts +1 -1
- package/esm/CircularView/svgcomponents/SVGCircularView.js +5 -17
- package/esm/CircularView/{models/viewportVisibleRegion.js → viewportVisibleRegion.js} +0 -70
- package/esm/LaunchCircularView/index.d.ts +1 -1
- package/esm/LaunchCircularView/index.js +1 -3
- package/esm/index.d.ts +3 -3
- package/esm/index.js +3 -5
- package/package.json +2 -3
- package/dist/BaseChordDisplay/models/renderReaction.d.ts +0 -45
- package/esm/BaseChordDisplay/models/renderReaction.d.ts +0 -45
- /package/dist/CircularView/{models/slices.js → slices.js} +0 -0
- /package/dist/CircularView/{models/viewportVisibleRegion.d.ts → viewportVisibleRegion.d.ts} +0 -0
- /package/esm/CircularView/{models/viewportVisibleRegion.d.ts → viewportVisibleRegion.d.ts} +0 -0
|
@@ -1,39 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import clone from 'clone';
|
|
3
|
-
import { getParent, isAlive, types } from 'mobx-state-tree';
|
|
4
|
-
// jbrowse
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
2
|
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration';
|
|
6
3
|
import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes/models';
|
|
7
|
-
import
|
|
8
|
-
import { getContainingView, getSession, getEnv, isFeature, makeAbortableReaction, ReactRendering, } from '@jbrowse/core/util';
|
|
4
|
+
import { ReactRendering, getContainingView, getEnv, getSession, isFeature, makeAbortableReaction, } from '@jbrowse/core/util';
|
|
9
5
|
import { getParentRenderProps, getRpcSessionId, getTrackAssemblyNames, } from '@jbrowse/core/util/tracks';
|
|
10
|
-
|
|
11
|
-
import { renderReactionData, renderReactionEffect } from './renderReaction';
|
|
6
|
+
import { getParent, isAlive, types } from 'mobx-state-tree';
|
|
12
7
|
import { baseChordDisplayConfig } from './configSchema';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* extends
|
|
16
|
-
* - [BaseDisplay](../basedisplay)
|
|
17
|
-
*/
|
|
18
|
-
function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
8
|
+
import { renderReactionData, renderReactionEffect } from './renderReaction';
|
|
9
|
+
function x() { }
|
|
19
10
|
export const BaseChordDisplayModel = types
|
|
20
11
|
.compose('BaseChordDisplay', BaseDisplay, types.model({
|
|
21
|
-
/**
|
|
22
|
-
* #property
|
|
23
|
-
*/
|
|
24
12
|
bezierRadiusRatio: 0.1,
|
|
25
|
-
/**
|
|
26
|
-
* #property
|
|
27
|
-
*/
|
|
28
13
|
assemblyName: types.maybe(types.string),
|
|
29
|
-
/**
|
|
30
|
-
* #property
|
|
31
|
-
*/
|
|
32
14
|
configuration: ConfigurationReference(baseChordDisplayConfig),
|
|
33
15
|
}))
|
|
34
16
|
.volatile(() => ({
|
|
35
|
-
// NOTE: all this volatile stuff has to be filled in at once
|
|
36
|
-
// so that it stays consistent
|
|
37
17
|
filled: false,
|
|
38
18
|
reactElement: undefined,
|
|
39
19
|
data: undefined,
|
|
@@ -46,42 +26,32 @@ export const BaseChordDisplayModel = types
|
|
|
46
26
|
const { pluginManager } = getEnv(self);
|
|
47
27
|
const track = self;
|
|
48
28
|
return {
|
|
49
|
-
/**
|
|
50
|
-
* #action
|
|
51
|
-
*/
|
|
52
29
|
onChordClick(feature) {
|
|
53
30
|
getConf(self, 'onChordClick', { feature, track, pluginManager });
|
|
54
31
|
},
|
|
55
32
|
};
|
|
56
33
|
})
|
|
57
34
|
.views(self => ({
|
|
58
|
-
/**
|
|
59
|
-
* #getter
|
|
60
|
-
*/
|
|
61
35
|
get blockDefinitions() {
|
|
62
36
|
const view = getContainingView(self);
|
|
63
37
|
const origSlices = view.staticSlices;
|
|
64
38
|
if (!self.refNameMap) {
|
|
65
39
|
return origSlices;
|
|
66
40
|
}
|
|
67
|
-
const slices =
|
|
68
|
-
|
|
41
|
+
const slices = structuredClone(origSlices);
|
|
42
|
+
for (const slice of slices) {
|
|
69
43
|
const regions = slice.region.elided
|
|
70
44
|
? slice.region.regions
|
|
71
45
|
: [slice.region];
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const renamed = (_a = self.refNameMap) === null || _a === void 0 ? void 0 : _a[region.refName];
|
|
46
|
+
for (const region of regions) {
|
|
47
|
+
const renamed = self.refNameMap[region.refName];
|
|
75
48
|
if (renamed && region.refName !== renamed) {
|
|
76
49
|
region.refName = renamed;
|
|
77
50
|
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
80
53
|
return slices;
|
|
81
54
|
},
|
|
82
|
-
/**
|
|
83
|
-
* #method
|
|
84
|
-
*/
|
|
85
55
|
renderProps() {
|
|
86
56
|
const view = getContainingView(self);
|
|
87
57
|
return {
|
|
@@ -93,41 +63,18 @@ export const BaseChordDisplayModel = types
|
|
|
93
63
|
onChordClick: self.onChordClick,
|
|
94
64
|
};
|
|
95
65
|
},
|
|
96
|
-
/**
|
|
97
|
-
* #getter
|
|
98
|
-
* the pluggable element type object for this display's renderer
|
|
99
|
-
*/
|
|
100
66
|
get rendererType() {
|
|
101
67
|
return getEnv(self).pluginManager.getRendererType(self.rendererTypeName);
|
|
102
68
|
},
|
|
103
|
-
/**
|
|
104
|
-
* #method
|
|
105
|
-
*/
|
|
106
|
-
isCompatibleWithRenderer(renderer) {
|
|
107
|
-
return !!(renderer instanceof CircularChordRendererType);
|
|
108
|
-
},
|
|
109
|
-
/**
|
|
110
|
-
* #getter
|
|
111
|
-
* returns a string feature ID if the globally-selected object
|
|
112
|
-
* is probably a feature
|
|
113
|
-
*/
|
|
114
69
|
get selectedFeatureId() {
|
|
115
70
|
if (!isAlive(self)) {
|
|
116
71
|
return undefined;
|
|
117
72
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
// does it quack like a feature?
|
|
121
|
-
if (isFeature(selection)) {
|
|
122
|
-
return selection.id();
|
|
123
|
-
}
|
|
124
|
-
return undefined;
|
|
73
|
+
const { selection } = getSession(self);
|
|
74
|
+
return isFeature(selection) ? selection.id() : undefined;
|
|
125
75
|
},
|
|
126
76
|
}))
|
|
127
77
|
.actions(self => ({
|
|
128
|
-
/**
|
|
129
|
-
* #action
|
|
130
|
-
*/
|
|
131
78
|
renderStarted() {
|
|
132
79
|
self.filled = false;
|
|
133
80
|
self.message = '';
|
|
@@ -137,9 +84,6 @@ export const BaseChordDisplayModel = types
|
|
|
137
84
|
self.error = undefined;
|
|
138
85
|
self.renderingComponent = undefined;
|
|
139
86
|
},
|
|
140
|
-
/**
|
|
141
|
-
* #action
|
|
142
|
-
*/
|
|
143
87
|
renderSuccess({ message, data, reactElement, html, renderingComponent, }) {
|
|
144
88
|
if (message) {
|
|
145
89
|
self.filled = false;
|
|
@@ -160,12 +104,8 @@ export const BaseChordDisplayModel = types
|
|
|
160
104
|
self.renderingComponent = renderingComponent;
|
|
161
105
|
}
|
|
162
106
|
},
|
|
163
|
-
/**
|
|
164
|
-
* #action
|
|
165
|
-
*/
|
|
166
107
|
renderError(error) {
|
|
167
108
|
console.error(error);
|
|
168
|
-
// the rendering failed for some reason
|
|
169
109
|
self.filled = false;
|
|
170
110
|
self.message = '';
|
|
171
111
|
self.reactElement = undefined;
|
|
@@ -174,33 +114,36 @@ export const BaseChordDisplayModel = types
|
|
|
174
114
|
self.error = error;
|
|
175
115
|
self.renderingComponent = undefined;
|
|
176
116
|
},
|
|
177
|
-
/**
|
|
178
|
-
* #action
|
|
179
|
-
*/
|
|
180
117
|
setRefNameMap(refNameMap) {
|
|
181
118
|
self.refNameMap = refNameMap;
|
|
182
119
|
},
|
|
183
120
|
}))
|
|
184
121
|
.actions(self => ({
|
|
185
122
|
afterAttach() {
|
|
186
|
-
makeAbortableReaction(self, renderReactionData,
|
|
187
|
-
// @ts-expect-error
|
|
188
|
-
renderReactionEffect, {
|
|
123
|
+
makeAbortableReaction(self, renderReactionData, renderReactionEffect, {
|
|
189
124
|
name: `${self.type} ${self.id} rendering`,
|
|
190
|
-
// delay: self.renderDelay || 300,
|
|
191
125
|
fireImmediately: true,
|
|
192
126
|
}, self.renderStarted, self.renderSuccess, self.renderError);
|
|
193
|
-
makeAbortableReaction(self, () =>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
127
|
+
makeAbortableReaction(self, () => {
|
|
128
|
+
return {
|
|
129
|
+
assemblyNames: getTrackAssemblyNames(self.parentTrack),
|
|
130
|
+
adapter: getConf(getParent(self, 2), 'adapter'),
|
|
131
|
+
assemblyManager: getSession(self).assemblyManager,
|
|
132
|
+
};
|
|
133
|
+
}, async (args, stopToken) => {
|
|
134
|
+
return args
|
|
135
|
+
? args.assemblyManager.getRefNameMapForAdapter(args.adapter, args.assemblyNames[0], {
|
|
136
|
+
stopToken,
|
|
137
|
+
sessionId: getRpcSessionId(self),
|
|
138
|
+
})
|
|
139
|
+
: undefined;
|
|
199
140
|
}, {
|
|
200
141
|
name: `${self.type} ${self.id} getting refNames`,
|
|
201
142
|
fireImmediately: true,
|
|
202
143
|
}, () => { }, refNameMap => {
|
|
203
|
-
|
|
144
|
+
if (refNameMap) {
|
|
145
|
+
self.setRefNameMap(refNameMap);
|
|
146
|
+
}
|
|
204
147
|
}, error => {
|
|
205
148
|
console.error(error);
|
|
206
149
|
self.setError(error);
|
|
@@ -208,16 +151,13 @@ export const BaseChordDisplayModel = types
|
|
|
208
151
|
},
|
|
209
152
|
}))
|
|
210
153
|
.views(self => ({
|
|
211
|
-
/**
|
|
212
|
-
* #method
|
|
213
|
-
*/
|
|
214
154
|
async renderSvg(opts) {
|
|
215
155
|
const data = renderReactionData(self);
|
|
216
156
|
const rendering = await renderReactionEffect({
|
|
217
157
|
...data,
|
|
218
158
|
exportSVG: opts,
|
|
219
159
|
theme: opts.theme || data.renderProps.theme,
|
|
220
|
-
}
|
|
221
|
-
return
|
|
160
|
+
});
|
|
161
|
+
return _jsx(ReactRendering, { rendering: rendering });
|
|
222
162
|
},
|
|
223
163
|
}));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare function renderReactionData(self: any): {
|
|
2
|
+
rendererType: any;
|
|
3
|
+
rpcManager: import("@jbrowse/core/rpc/RpcManager").default;
|
|
4
|
+
renderProps: any;
|
|
5
|
+
renderArgs: {
|
|
6
|
+
assemblyName: string;
|
|
7
|
+
adapterConfig: any;
|
|
8
|
+
rendererType: any;
|
|
9
|
+
regions: import("@jbrowse/core/util").Region[] & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[], import("@jbrowse/core/util").Region[]>, [undefined]>>;
|
|
10
|
+
blockDefinitions: any;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
timeout: number;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare function renderReactionEffect(props?: any, stopToken?: string): Promise<{
|
|
16
|
+
message: any;
|
|
17
|
+
html?: undefined;
|
|
18
|
+
data?: undefined;
|
|
19
|
+
reactElement?: undefined;
|
|
20
|
+
renderingComponent?: undefined;
|
|
21
|
+
} | {
|
|
22
|
+
html: any;
|
|
23
|
+
data: any;
|
|
24
|
+
reactElement: any;
|
|
25
|
+
renderingComponent: any;
|
|
26
|
+
message?: undefined;
|
|
27
|
+
}>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getContainingView, getSession } from '@jbrowse/core/util';
|
|
2
2
|
import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
3
|
-
import { getSession, getContainingView } from '@jbrowse/core/util';
|
|
4
3
|
export function renderReactionData(self) {
|
|
5
4
|
const view = getContainingView(self);
|
|
6
5
|
const { rendererType } = self;
|
|
@@ -11,16 +10,16 @@ export function renderReactionData(self) {
|
|
|
11
10
|
renderProps: self.renderProps(),
|
|
12
11
|
renderArgs: {
|
|
13
12
|
assemblyName: view.displayedRegions[0].assemblyName,
|
|
14
|
-
adapterConfig:
|
|
13
|
+
adapterConfig: structuredClone(self.adapterConfig),
|
|
15
14
|
rendererType: rendererType.name,
|
|
16
|
-
regions:
|
|
15
|
+
regions: structuredClone(view.displayedRegions),
|
|
17
16
|
blockDefinitions: self.blockDefinitions,
|
|
18
17
|
sessionId: getRpcSessionId(self),
|
|
19
18
|
timeout: 1000000,
|
|
20
19
|
},
|
|
21
20
|
};
|
|
22
21
|
}
|
|
23
|
-
export async function renderReactionEffect(props,
|
|
22
|
+
export async function renderReactionEffect(props, stopToken) {
|
|
24
23
|
var _a;
|
|
25
24
|
if (!props) {
|
|
26
25
|
throw new Error('cannot render with no props');
|
|
@@ -29,18 +28,14 @@ export async function renderReactionEffect(props, signal, self) {
|
|
|
29
28
|
if (cannotBeRenderedReason) {
|
|
30
29
|
return { message: cannotBeRenderedReason };
|
|
31
30
|
}
|
|
32
|
-
// don't try to render 0 or NaN radius or no regions
|
|
33
31
|
if (!renderProps.radius || !((_a = renderArgs.regions) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
34
32
|
return { message: 'Skipping render' };
|
|
35
33
|
}
|
|
36
|
-
// check renderertype compatibility
|
|
37
|
-
if (!self.isCompatibleWithRenderer(rendererType)) {
|
|
38
|
-
throw new Error(`renderer ${rendererType.name} is not compatible with this display type`);
|
|
39
|
-
}
|
|
40
34
|
const { html, ...data } = await rendererType.renderInClient(rpcManager, {
|
|
41
35
|
...renderArgs,
|
|
42
36
|
...renderProps,
|
|
43
37
|
exportSVG,
|
|
38
|
+
stopToken,
|
|
44
39
|
});
|
|
45
40
|
return {
|
|
46
41
|
html,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CircularViewModel } from '../models/model';
|
|
1
|
+
import type { CircularViewModel } from '../model';
|
|
3
2
|
declare const CircularView: ({ model }: {
|
|
4
3
|
model: CircularViewModel;
|
|
5
|
-
}) =>
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
6
5
|
export default CircularView;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { observer } from 'mobx-react';
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
2
|
import { ResizeHandle } from '@jbrowse/core/ui';
|
|
4
3
|
import { assembleLocString } from '@jbrowse/core/util';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
5
|
import { makeStyles } from 'tss-react/mui';
|
|
6
|
-
// locals
|
|
7
|
-
import Ruler from './Ruler';
|
|
8
6
|
import Controls from './Controls';
|
|
9
7
|
import ImportForm from './ImportForm';
|
|
8
|
+
import Ruler from './Ruler';
|
|
10
9
|
const dragHandleHeight = 3;
|
|
11
10
|
const useStyles = makeStyles()(theme => ({
|
|
12
11
|
root: {
|
|
@@ -19,12 +18,10 @@ const useStyles = makeStyles()(theme => ({
|
|
|
19
18
|
},
|
|
20
19
|
}));
|
|
21
20
|
const Slices = observer(({ model }) => {
|
|
22
|
-
return (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return (React.createElement(display.RenderingComponent, { key: display.id, display: display, view: model }));
|
|
27
|
-
})));
|
|
21
|
+
return (_jsxs(_Fragment, { children: [model.staticSlices.map(slice => (_jsx(Ruler, { model: model, slice: slice }, assembleLocString(slice.region.elided ? slice.region.regions[0] : slice.region)))), model.tracks.map(track => {
|
|
22
|
+
const display = track.displays[0];
|
|
23
|
+
return (_jsx(display.RenderingComponent, { display: display, view: model }, display.id));
|
|
24
|
+
})] }));
|
|
28
25
|
});
|
|
29
26
|
const CircularView = observer(({ model }) => {
|
|
30
27
|
const initialized = !!model.displayedRegions.length &&
|
|
@@ -33,32 +30,26 @@ const CircularView = observer(({ model }) => {
|
|
|
33
30
|
model.initialized;
|
|
34
31
|
const showImportForm = !initialized && !model.disableImportForm;
|
|
35
32
|
const showFigure = initialized && !showImportForm;
|
|
36
|
-
return showImportForm || model.error ? (
|
|
33
|
+
return showImportForm || model.error ? (_jsx(ImportForm, { model: model })) : showFigure ? (_jsx(CircularViewLoaded, { model: model })) : null;
|
|
37
34
|
});
|
|
38
35
|
const CircularViewLoaded = observer(function ({ model, }) {
|
|
39
36
|
const { width, height, id, offsetRadians, centerXY, figureWidth, figureHeight, hideVerticalResizeHandle, } = model;
|
|
40
37
|
const { classes } = useStyles();
|
|
41
|
-
return (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
return (_jsxs("div", { className: classes.root, style: { width, height }, "data-testid": id, children: [_jsx("div", { className: classes.scroller, style: { width, height }, children: _jsx("svg", { style: {
|
|
39
|
+
transform: `rotate(${offsetRadians}rad)`,
|
|
40
|
+
transition: 'transform 0.5s',
|
|
41
|
+
transformOrigin: centerXY.map(x => `${x}px`).join(' '),
|
|
42
|
+
position: 'absolute',
|
|
43
|
+
left: 0,
|
|
44
|
+
top: 0,
|
|
45
|
+
}, width: figureWidth, height: figureHeight, children: _jsx("g", { transform: `translate(${centerXY})`, children: _jsx(Slices, { model: model }) }) }) }), _jsx(Controls, { model: model }), hideVerticalResizeHandle ? null : (_jsx(ResizeHandle, { onDrag: model.resizeHeight, style: {
|
|
46
|
+
height: dragHandleHeight,
|
|
47
47
|
position: 'absolute',
|
|
48
|
+
bottom: 0,
|
|
48
49
|
left: 0,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
React.createElement(Controls, { model: model }),
|
|
54
|
-
hideVerticalResizeHandle ? null : (React.createElement(ResizeHandle, { onDrag: model.resizeHeight, style: {
|
|
55
|
-
height: dragHandleHeight,
|
|
56
|
-
position: 'absolute',
|
|
57
|
-
bottom: 0,
|
|
58
|
-
left: 0,
|
|
59
|
-
background: '#ccc',
|
|
60
|
-
boxSizing: 'border-box',
|
|
61
|
-
borderTop: '1px solid #fafafa',
|
|
62
|
-
} }))));
|
|
50
|
+
background: '#ccc',
|
|
51
|
+
boxSizing: 'border-box',
|
|
52
|
+
borderTop: '1px solid #fafafa',
|
|
53
|
+
} }))] }));
|
|
63
54
|
});
|
|
64
55
|
export default CircularView;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CircularViewModel } from '../models/model';
|
|
1
|
+
import type { CircularViewModel } from '../model';
|
|
3
2
|
declare const Controls: ({ model }: {
|
|
4
3
|
model: CircularViewModel;
|
|
5
|
-
}) =>
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export default Controls;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { makeStyles } from 'tss-react/mui';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons';
|
|
5
4
|
import JBrowseMenu from '@jbrowse/core/ui/Menu';
|
|
6
|
-
|
|
7
|
-
import ZoomOutIcon from '@mui/icons-material/ZoomOut';
|
|
8
|
-
import ZoomInIcon from '@mui/icons-material/ZoomIn';
|
|
9
|
-
import RotateLeftIcon from '@mui/icons-material/RotateLeft';
|
|
10
|
-
import RotateRightIcon from '@mui/icons-material/RotateRight';
|
|
11
|
-
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
|
5
|
+
import { getSession } from '@jbrowse/core/util';
|
|
12
6
|
import LockIcon from '@mui/icons-material/Lock';
|
|
13
|
-
import
|
|
7
|
+
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
|
14
8
|
import MoreVert from '@mui/icons-material/MoreVert';
|
|
15
|
-
import
|
|
16
|
-
import
|
|
9
|
+
import PhotoCamera from '@mui/icons-material/PhotoCamera';
|
|
10
|
+
import RotateLeftIcon from '@mui/icons-material/RotateLeft';
|
|
11
|
+
import RotateRightIcon from '@mui/icons-material/RotateRight';
|
|
12
|
+
import ZoomInIcon from '@mui/icons-material/ZoomIn';
|
|
13
|
+
import ZoomOutIcon from '@mui/icons-material/ZoomOut';
|
|
14
|
+
import { IconButton } from '@mui/material';
|
|
15
|
+
import { observer } from 'mobx-react';
|
|
16
|
+
import { makeStyles } from 'tss-react/mui';
|
|
17
17
|
import ExportSvgDialog from './ExportSvgDialog';
|
|
18
18
|
const useStyles = makeStyles()(theme => ({
|
|
19
19
|
controls: {
|
|
@@ -27,40 +27,26 @@ const useStyles = makeStyles()(theme => ({
|
|
|
27
27
|
const Controls = observer(function ({ model }) {
|
|
28
28
|
const { classes } = useStyles();
|
|
29
29
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
30
|
-
return (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} },
|
|
45
|
-
React.createElement(MoreVert, null)),
|
|
46
|
-
model.hideTrackSelectorButton ? null : (React.createElement(IconButton, { onClick: model.activateTrackSelector, title: "Open track selector", "data-testid": "circular_track_select" },
|
|
47
|
-
React.createElement(TrackSelectorIcon, null))),
|
|
48
|
-
anchorEl ? (React.createElement(JBrowseMenu, { anchorEl: anchorEl, menuItems: [
|
|
49
|
-
{
|
|
50
|
-
label: 'Export SVG',
|
|
51
|
-
icon: PhotoCamera,
|
|
52
|
-
onClick: () => {
|
|
53
|
-
getSession(model).queueDialog(handleClose => [
|
|
54
|
-
ExportSvgDialog,
|
|
55
|
-
{ model, handleClose },
|
|
56
|
-
]);
|
|
30
|
+
return (_jsxs("div", { className: classes.controls, children: [_jsx(IconButton, { onClick: model.zoomOutButton, title: model.lockedFitToWindow ? 'unlock to zoom out' : 'zoom out', disabled: model.atMaxBpPerPx || model.lockedFitToWindow, children: _jsx(ZoomOutIcon, {}) }), _jsx(IconButton, { onClick: model.zoomInButton, disabled: model.atMinBpPerPx, title: "zoom in", children: _jsx(ZoomInIcon, {}) }), _jsx(IconButton, { onClick: model.rotateCounterClockwiseButton, title: "rotate counter-clockwise", children: _jsx(RotateLeftIcon, {}) }), _jsx(IconButton, { onClick: model.rotateClockwiseButton, title: "rotate clockwise", children: _jsx(RotateRightIcon, {}) }), _jsx(IconButton, { onClick: model.toggleFitToWindowLock, title: model.lockedFitToWindow
|
|
31
|
+
? 'locked model to window size'
|
|
32
|
+
: 'unlocked model to zoom further', disabled: model.tooSmallToLock, children: model.lockedFitToWindow ? _jsx(LockIcon, {}) : _jsx(LockOpenIcon, {}) }), _jsx(IconButton, { onClick: event => {
|
|
33
|
+
setAnchorEl(event.currentTarget);
|
|
34
|
+
}, children: _jsx(MoreVert, {}) }), model.hideTrackSelectorButton ? null : (_jsx(IconButton, { onClick: model.activateTrackSelector, title: "Open track selector", "data-testid": "circular_track_select", children: _jsx(TrackSelectorIcon, {}) })), anchorEl ? (_jsx(JBrowseMenu, { anchorEl: anchorEl, menuItems: [
|
|
35
|
+
{
|
|
36
|
+
label: 'Export SVG',
|
|
37
|
+
icon: PhotoCamera,
|
|
38
|
+
onClick: () => {
|
|
39
|
+
getSession(model).queueDialog(handleClose => [
|
|
40
|
+
ExportSvgDialog,
|
|
41
|
+
{ model, handleClose },
|
|
42
|
+
]);
|
|
43
|
+
},
|
|
57
44
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} })) : null));
|
|
45
|
+
], onMenuItemClick: (_event, callback) => {
|
|
46
|
+
callback();
|
|
47
|
+
setAnchorEl(null);
|
|
48
|
+
}, open: Boolean(anchorEl), onClose: () => {
|
|
49
|
+
setAnchorEl(null);
|
|
50
|
+
} })) : null] }));
|
|
65
51
|
});
|
|
66
52
|
export default Controls;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ExportSvgOptions } from '../models/model';
|
|
1
|
+
import type { ExportSvgOptions } from '../model';
|
|
3
2
|
export default function ExportSvgDialog({ model, handleClose, }: {
|
|
4
3
|
model: {
|
|
5
4
|
exportSvg(opts: ExportSvgOptions): Promise<void>;
|
|
6
5
|
};
|
|
7
6
|
handleClose: () => void;
|
|
8
|
-
}):
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
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';
|
|
5
6
|
function LoadingMessage() {
|
|
6
|
-
return (
|
|
7
|
-
React.createElement(CircularProgress, { size: 20, style: { marginRight: 20 } }),
|
|
8
|
-
React.createElement(Typography, { display: "inline" }, "Creating SVG")));
|
|
7
|
+
return (_jsxs("div", { children: [_jsx(CircularProgress, { size: 20, style: { marginRight: 20 } }), _jsx(Typography, { display: "inline", children: "Creating SVG" })] }));
|
|
9
8
|
}
|
|
10
9
|
function TextField2({ children, ...rest }) {
|
|
11
|
-
return (
|
|
12
|
-
React.createElement(TextField, { ...rest }, children)));
|
|
10
|
+
return (_jsx("div", { children: _jsx(TextField, { ...rest, children: children }) }));
|
|
13
11
|
}
|
|
14
12
|
function useSvgLocal(key, val) {
|
|
15
13
|
return useLocalStorage(`svg-${key}`, val);
|
|
@@ -22,41 +20,31 @@ export default function ExportSvgDialog({ model, handleClose, }) {
|
|
|
22
20
|
const [error, setError] = useState();
|
|
23
21
|
const [filename, setFilename] = useSvgLocal('file', 'jbrowse.svg');
|
|
24
22
|
const [themeName, setThemeName] = useSvgLocal('theme', session.themeName || 'default');
|
|
25
|
-
return (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
handleClose();
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
console.error(e);
|
|
56
|
-
setError(e);
|
|
57
|
-
}
|
|
58
|
-
finally {
|
|
59
|
-
setLoading(false);
|
|
60
|
-
}
|
|
61
|
-
} }, "Submit"))));
|
|
23
|
+
return (_jsxs(Dialog, { open: true, onClose: handleClose, title: "Export SVG", children: [_jsxs(DialogContent, { children: [error ? (_jsx(ErrorMessage, { error: error })) : loading ? (_jsx(LoadingMessage, {})) : null, _jsx(TextField2, { helperText: "filename", value: filename, onChange: event => {
|
|
24
|
+
setFilename(event.target.value);
|
|
25
|
+
} }), session.allThemes ? (_jsx(TextField2, { select: true, label: "Theme", value: themeName, onChange: event => {
|
|
26
|
+
setThemeName(event.target.value);
|
|
27
|
+
}, children: Object.entries(session.allThemes()).map(([key, val]) => (_jsx(MenuItem, { value: key, children: val.name || '(Unknown name)' }, key))) })) : null, offscreenCanvas ? (_jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: rasterizeLayers, onChange: () => {
|
|
28
|
+
setRasterizeLayers(val => !val);
|
|
29
|
+
} }), label: "Rasterize canvas based tracks? File may be much larger if this is turned off" })) : (_jsx(Typography, { children: "Note: rasterizing layers not yet supported in this browser, so SVG size may be large" }))] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
30
|
+
handleClose();
|
|
31
|
+
}, children: "Cancel" }), _jsx(Button, { variant: "contained", color: "primary", type: "submit", onClick: async () => {
|
|
32
|
+
setLoading(true);
|
|
33
|
+
setError(undefined);
|
|
34
|
+
try {
|
|
35
|
+
await model.exportSvg({
|
|
36
|
+
rasterizeLayers,
|
|
37
|
+
filename,
|
|
38
|
+
themeName,
|
|
39
|
+
});
|
|
40
|
+
handleClose();
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
console.error(e);
|
|
44
|
+
setError(e);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}, children: "Submit" })] })] }));
|
|
62
50
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CircularViewModel } from '../models/model';
|
|
1
|
+
import type { CircularViewModel } from '../model';
|
|
3
2
|
declare const ImportForm: ({ model }: {
|
|
4
3
|
model: CircularViewModel;
|
|
5
|
-
}) =>
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export default ImportForm;
|