@jbrowse/plugin-linear-comparative-view 3.5.0 → 3.6.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/LGVSyntenyDisplay/model.d.ts +4 -7
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +4 -0
- package/dist/LinearComparativeDisplay/stateModelFactory.js +14 -7
- package/dist/LinearComparativeView/components/HeaderSearchBoxes.js +2 -2
- package/dist/LinearComparativeView/components/Rubberband.d.ts +2 -2
- package/dist/LinearComparativeView/components/Rubberband.js +16 -154
- package/dist/LinearComparativeView/components/RubberbandSpan.d.ts +15 -0
- package/dist/LinearComparativeView/components/RubberbandSpan.js +38 -0
- package/dist/LinearComparativeView/components/RubberbandTooltip.d.ts +5 -0
- package/dist/LinearComparativeView/components/RubberbandTooltip.js +20 -0
- package/dist/LinearComparativeView/components/useRangeSelect.d.ts +59 -0
- package/dist/LinearComparativeView/components/useRangeSelect.js +128 -0
- package/dist/LinearComparativeView/components/util.d.ts +4 -0
- package/dist/LinearComparativeView/components/util.js +6 -0
- package/dist/LinearComparativeView/model.d.ts +2 -0
- package/dist/LinearSyntenyDisplay/components/BlockError.d.ts +3 -0
- package/dist/LinearSyntenyDisplay/components/BlockError.js +16 -0
- package/dist/LinearSyntenyDisplay/components/BlockMessage.d.ts +3 -0
- package/dist/LinearSyntenyDisplay/components/BlockMessage.js +24 -0
- package/dist/LinearSyntenyDisplay/components/Component.js +11 -50
- package/dist/LinearSyntenyDisplay/components/LoadingMessage.d.ts +3 -0
- package/dist/LinearSyntenyDisplay/components/LoadingMessage.js +21 -0
- package/dist/LinearSyntenyDisplay/model.d.ts +4 -0
- package/dist/LinearSyntenyView/components/ImportForm/ImportSyntenyOpenCustomTrack.js +2 -51
- package/dist/LinearSyntenyView/components/ImportForm/selectors/AnchorsSelector.d.ts +3 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/AnchorsSelector.js +13 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/PifGzSelector.d.ts +3 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/PifGzSelector.js +13 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/SelectorTypes.d.ts +19 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/SelectorTypes.js +10 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/StandardFormatSelector.d.ts +3 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/StandardFormatSelector.js +20 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/SwapAssemblies.d.ts +13 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/SwapAssemblies.js +32 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/index.d.ts +4 -0
- package/dist/LinearSyntenyView/components/ImportForm/selectors/index.js +27 -0
- package/dist/LinearSyntenyView/model.d.ts +2 -0
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +1 -1
- package/esm/LGVSyntenyDisplay/model.d.ts +4 -7
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +4 -0
- package/esm/LinearComparativeDisplay/stateModelFactory.js +14 -7
- package/esm/LinearComparativeView/components/HeaderSearchBoxes.js +2 -2
- package/esm/LinearComparativeView/components/Rubberband.d.ts +2 -2
- package/esm/LinearComparativeView/components/Rubberband.js +17 -155
- package/esm/LinearComparativeView/components/RubberbandSpan.d.ts +15 -0
- package/esm/LinearComparativeView/components/RubberbandSpan.js +32 -0
- package/esm/LinearComparativeView/components/RubberbandTooltip.d.ts +5 -0
- package/esm/LinearComparativeView/components/RubberbandTooltip.js +17 -0
- package/esm/LinearComparativeView/components/useRangeSelect.d.ts +59 -0
- package/esm/LinearComparativeView/components/useRangeSelect.js +125 -0
- package/esm/LinearComparativeView/components/util.d.ts +4 -0
- package/esm/LinearComparativeView/components/util.js +3 -0
- package/esm/LinearComparativeView/model.d.ts +2 -0
- package/esm/LinearSyntenyDisplay/components/BlockError.d.ts +3 -0
- package/esm/LinearSyntenyDisplay/components/BlockError.js +13 -0
- package/esm/LinearSyntenyDisplay/components/BlockMessage.d.ts +3 -0
- package/esm/LinearSyntenyDisplay/components/BlockMessage.js +21 -0
- package/esm/LinearSyntenyDisplay/components/Component.js +9 -48
- package/esm/LinearSyntenyDisplay/components/LoadingMessage.d.ts +3 -0
- package/esm/LinearSyntenyDisplay/components/LoadingMessage.js +18 -0
- package/esm/LinearSyntenyDisplay/model.d.ts +4 -0
- package/esm/LinearSyntenyView/components/ImportForm/ImportSyntenyOpenCustomTrack.js +3 -49
- package/esm/LinearSyntenyView/components/ImportForm/selectors/AnchorsSelector.d.ts +3 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/AnchorsSelector.js +8 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/PifGzSelector.d.ts +3 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/PifGzSelector.js +8 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/SelectorTypes.d.ts +19 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/SelectorTypes.js +7 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/StandardFormatSelector.d.ts +3 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/StandardFormatSelector.js +15 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/SwapAssemblies.d.ts +13 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/SwapAssemblies.js +27 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/index.d.ts +4 -0
- package/esm/LinearSyntenyView/components/ImportForm/selectors/index.js +4 -0
- package/esm/LinearSyntenyView/model.d.ts +2 -0
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +1 -1
- package/package.json +5 -5
|
@@ -192,6 +192,7 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
192
192
|
readonly renderDelay: number;
|
|
193
193
|
readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
|
|
194
194
|
readonly selectedFeatureId: string | undefined;
|
|
195
|
+
copyInfoToClipboard(feature: Feature): void;
|
|
195
196
|
} & {
|
|
196
197
|
readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
|
|
197
198
|
readonly featureUnderMouse: Feature | undefined;
|
|
@@ -234,12 +235,12 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
234
235
|
updateColorTagMap(uniqueTag: string[]): void;
|
|
235
236
|
setFeatureUnderMouse(feat?: Feature): void;
|
|
236
237
|
selectFeature(feature: Feature): void;
|
|
237
|
-
copyFeatureToClipboard(feature: Feature): void;
|
|
238
238
|
setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
|
|
239
239
|
setFilterBy(filter: import("@jbrowse/plugin-alignments/src/shared/types").FilterBy): void;
|
|
240
240
|
setJexlFilters(filters: string[]): void;
|
|
241
241
|
setHideSmallIndels(arg: boolean): void;
|
|
242
242
|
} & {
|
|
243
|
+
copyFeatureToClipboard(feature: Feature): void;
|
|
243
244
|
readonly rendererConfig: {
|
|
244
245
|
[x: string]: any;
|
|
245
246
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
@@ -259,17 +260,13 @@ declare function stateModelFactory(schema: AnyConfigurationSchemaType): import("
|
|
|
259
260
|
readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
|
|
260
261
|
} & {
|
|
261
262
|
readonly rendererTypeName: string;
|
|
262
|
-
contextMenuItems():
|
|
263
|
+
contextMenuItems(): {
|
|
263
264
|
label: string;
|
|
264
265
|
icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
265
266
|
muiName: string;
|
|
266
267
|
};
|
|
267
268
|
onClick: () => void;
|
|
268
|
-
}
|
|
269
|
-
label: string;
|
|
270
|
-
icon: typeof import("@jbrowse/core/ui/Icons").ContentCopy;
|
|
271
|
-
onClick: () => void;
|
|
272
|
-
})[];
|
|
269
|
+
}[];
|
|
273
270
|
readonly DisplayBlurb: ({ model, }: {
|
|
274
271
|
model: {
|
|
275
272
|
sortedBy?: import("@jbrowse/plugin-alignments/src/shared/types").SortedBy;
|
|
@@ -70,6 +70,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
70
70
|
renderInProgress: string | undefined;
|
|
71
71
|
features: Feature[] | undefined;
|
|
72
72
|
message: string | undefined;
|
|
73
|
+
loadingStatus: string | undefined;
|
|
73
74
|
} & {
|
|
74
75
|
readonly level: number;
|
|
75
76
|
readonly height: number;
|
|
@@ -152,6 +153,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
152
153
|
renderInProgress: string | undefined;
|
|
153
154
|
features: Feature[] | undefined;
|
|
154
155
|
message: string | undefined;
|
|
156
|
+
loadingStatus: string | undefined;
|
|
155
157
|
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
156
158
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
157
159
|
type: import("mobx-state-tree").ISimpleType<string>;
|
|
@@ -221,12 +223,14 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
221
223
|
renderInProgress: string | undefined;
|
|
222
224
|
features: Feature[] | undefined;
|
|
223
225
|
message: string | undefined;
|
|
226
|
+
loadingStatus: string | undefined;
|
|
224
227
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
225
228
|
highResolutionScaling: number;
|
|
226
229
|
};
|
|
227
230
|
} & {
|
|
228
231
|
setLoading(newStopToken: string): void;
|
|
229
232
|
setMessage(messageText: string): void;
|
|
233
|
+
setLoadingStatus(messageText: string): void;
|
|
230
234
|
setRendered(args?: {
|
|
231
235
|
features: Feature[];
|
|
232
236
|
}): void;
|
|
@@ -16,6 +16,7 @@ function stateModelFactory(configSchema) {
|
|
|
16
16
|
renderInProgress: undefined,
|
|
17
17
|
features: undefined,
|
|
18
18
|
message: undefined,
|
|
19
|
+
loadingStatus: undefined,
|
|
19
20
|
}))
|
|
20
21
|
.views(self => ({
|
|
21
22
|
get level() {
|
|
@@ -45,6 +46,9 @@ function stateModelFactory(configSchema) {
|
|
|
45
46
|
self.error = undefined;
|
|
46
47
|
stopToken = undefined;
|
|
47
48
|
},
|
|
49
|
+
setLoadingStatus(messageText) {
|
|
50
|
+
self.loadingStatus = messageText;
|
|
51
|
+
},
|
|
48
52
|
setRendered(args) {
|
|
49
53
|
if (!args) {
|
|
50
54
|
return;
|
|
@@ -110,6 +114,7 @@ function renderBlockData(self) {
|
|
|
110
114
|
rpcManager,
|
|
111
115
|
renderProps: {
|
|
112
116
|
...display.renderProps(),
|
|
117
|
+
model: display,
|
|
113
118
|
level,
|
|
114
119
|
view: parent,
|
|
115
120
|
adapterConfig,
|
|
@@ -125,15 +130,17 @@ async function renderBlockEffect(props) {
|
|
|
125
130
|
return;
|
|
126
131
|
}
|
|
127
132
|
const { rpcManager, renderProps } = props;
|
|
128
|
-
const { adapterConfig, level } = renderProps;
|
|
133
|
+
const { model, sessionId, adapterConfig, level } = renderProps;
|
|
129
134
|
const view = renderProps.view.views[level];
|
|
130
|
-
const features = (await rpcManager.call('getFeats', 'CoreGetFeatures', {
|
|
131
|
-
regions: view.staticBlocks.contentBlocks,
|
|
132
|
-
sessionId: 'getFeats',
|
|
133
|
-
adapterConfig,
|
|
134
|
-
}));
|
|
135
135
|
return {
|
|
136
|
-
features: (0, util_1.dedupe)(
|
|
136
|
+
features: (0, util_1.dedupe)((await rpcManager.call('getFeats', 'CoreGetFeatures', {
|
|
137
|
+
regions: view.staticBlocks.contentBlocks,
|
|
138
|
+
sessionId,
|
|
139
|
+
adapterConfig,
|
|
140
|
+
statusCallback: (arg) => {
|
|
141
|
+
model.setLoadingStatus(arg);
|
|
142
|
+
},
|
|
143
|
+
})), f => f.id()),
|
|
137
144
|
};
|
|
138
145
|
}
|
|
139
146
|
exports.default = stateModelFactory;
|
|
@@ -18,7 +18,7 @@ const useStyles = (0, mui_1.makeStyles)()(() => ({
|
|
|
18
18
|
}));
|
|
19
19
|
const HeaderSearchBoxes = (0, mobx_react_1.observer)(function ({ view, }) {
|
|
20
20
|
const { classes } = useStyles();
|
|
21
|
-
const {
|
|
22
|
-
return ((0, jsx_runtime_1.jsxs)("span", { className: classes.searchBox, children: [(0, jsx_runtime_1.jsx)(plugin_linear_genome_view_1.SearchBox, { model: view, showHelp: false }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", color: "textSecondary", className: classes.bp, children: [
|
|
21
|
+
const { assemblyDisplayNames, coarseTotalBp } = view;
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: classes.searchBox, children: [(0, jsx_runtime_1.jsx)(plugin_linear_genome_view_1.SearchBox, { model: view, showHelp: false }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "body2", color: "textSecondary", className: classes.bp, children: [assemblyDisplayNames.join(','), " ", (0, util_1.getBpDisplayStr)(coarseTotalBp)] })] }));
|
|
23
23
|
});
|
|
24
24
|
exports.default = HeaderSearchBoxes;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LinearComparativeViewModel } from '../model';
|
|
2
2
|
type LCV = LinearComparativeViewModel;
|
|
3
|
-
declare const
|
|
3
|
+
declare const Rubberband: ({ model, ControlComponent, }: {
|
|
4
4
|
model: LCV;
|
|
5
5
|
ControlComponent?: React.ReactElement;
|
|
6
6
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
-
export default
|
|
7
|
+
export default Rubberband;
|
|
@@ -6,165 +6,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const ui_1 = require("@jbrowse/core/ui");
|
|
9
|
-
const util_1 = require("@jbrowse/core/util");
|
|
10
|
-
const material_1 = require("@mui/material");
|
|
11
|
-
const mobx_1 = require("mobx");
|
|
12
9
|
const mobx_react_1 = require("mobx-react");
|
|
13
10
|
const mui_1 = require("tss-react/mui");
|
|
11
|
+
const RubberbandSpan_1 = __importDefault(require("./RubberbandSpan"));
|
|
14
12
|
const VerticalGuide_1 = __importDefault(require("./VerticalGuide"));
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
rubberbandControl: {
|
|
26
|
-
cursor: 'crosshair',
|
|
27
|
-
width: '100%',
|
|
28
|
-
minHeight: 8,
|
|
29
|
-
},
|
|
30
|
-
rubberbandText: {
|
|
31
|
-
color: theme.palette.tertiary.contrastText,
|
|
32
|
-
},
|
|
33
|
-
popover: {
|
|
34
|
-
mouseEvents: 'none',
|
|
35
|
-
cursor: 'crosshair',
|
|
36
|
-
},
|
|
37
|
-
paper: {
|
|
38
|
-
paddingLeft: theme.spacing(1),
|
|
39
|
-
paddingRight: theme.spacing(1),
|
|
40
|
-
},
|
|
41
|
-
};
|
|
13
|
+
const useRangeSelect_1 = require("./useRangeSelect");
|
|
14
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
15
|
+
rubberbandControl: {
|
|
16
|
+
cursor: 'crosshair',
|
|
17
|
+
width: '100%',
|
|
18
|
+
minHeight: 8,
|
|
19
|
+
position: 'relative',
|
|
20
|
+
zIndex: 900,
|
|
21
|
+
},
|
|
42
22
|
});
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const [currentX, setCurrentX] = (0, react_1.useState)();
|
|
46
|
-
const [anchorPosition, setAnchorPosition] = (0, react_1.useState)();
|
|
47
|
-
const [guideX, setGuideX] = (0, react_1.useState)();
|
|
48
|
-
const controlsRef = (0, react_1.useRef)(null);
|
|
49
|
-
const rubberbandRef = (0, react_1.useRef)(null);
|
|
23
|
+
const Rubberband = (0, mobx_react_1.observer)(function ({ model, ControlComponent = (0, jsx_runtime_1.jsx)("div", {}), }) {
|
|
24
|
+
const ref = (0, react_1.useRef)(null);
|
|
50
25
|
const { classes } = useStyles();
|
|
51
|
-
const
|
|
52
|
-
(0,
|
|
53
|
-
function computeOffsets(offsetX, view) {
|
|
54
|
-
if (startX === undefined) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
let leftPx = startX;
|
|
58
|
-
let rightPx = offsetX;
|
|
59
|
-
if (rightPx < leftPx) {
|
|
60
|
-
;
|
|
61
|
-
[leftPx, rightPx] = [rightPx, leftPx];
|
|
62
|
-
}
|
|
63
|
-
const leftOffset = view.pxToBp(leftPx);
|
|
64
|
-
const rightOffset = view.pxToBp(rightPx);
|
|
65
|
-
return { leftOffset, rightOffset };
|
|
66
|
-
}
|
|
67
|
-
function globalMouseMove(event) {
|
|
68
|
-
if (controlsRef.current && mouseDragging) {
|
|
69
|
-
const relativeX = event.clientX - controlsRef.current.getBoundingClientRect().left;
|
|
70
|
-
setCurrentX(relativeX);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
function globalMouseUp(event) {
|
|
74
|
-
if (startX !== undefined && controlsRef.current) {
|
|
75
|
-
const { clientX, clientY } = event;
|
|
76
|
-
const ref = controlsRef.current;
|
|
77
|
-
const offsetX = clientX - ref.getBoundingClientRect().left;
|
|
78
|
-
setAnchorPosition({
|
|
79
|
-
offsetX,
|
|
80
|
-
clientX,
|
|
81
|
-
clientY,
|
|
82
|
-
});
|
|
83
|
-
(0, mobx_1.transaction)(() => {
|
|
84
|
-
for (const view of model.views) {
|
|
85
|
-
const args = computeOffsets(offsetX, view);
|
|
86
|
-
if (args) {
|
|
87
|
-
const { leftOffset, rightOffset } = args;
|
|
88
|
-
view.setOffsets(leftOffset, rightOffset);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
setGuideX(undefined);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (mouseDragging) {
|
|
96
|
-
window.addEventListener('mousemove', globalMouseMove);
|
|
97
|
-
window.addEventListener('mouseup', globalMouseUp);
|
|
98
|
-
return () => {
|
|
99
|
-
window.removeEventListener('mousemove', globalMouseMove);
|
|
100
|
-
window.removeEventListener('mouseup', globalMouseUp);
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return () => { };
|
|
104
|
-
}, [startX, mouseDragging, model]);
|
|
105
|
-
(0, react_1.useEffect)(() => {
|
|
106
|
-
if (!mouseDragging &&
|
|
107
|
-
currentX !== undefined &&
|
|
108
|
-
startX !== undefined &&
|
|
109
|
-
Math.abs(currentX - startX) <= 3) {
|
|
110
|
-
handleClose();
|
|
111
|
-
}
|
|
112
|
-
}, [mouseDragging, currentX, startX]);
|
|
113
|
-
function mouseDown(event) {
|
|
114
|
-
event.preventDefault();
|
|
115
|
-
event.stopPropagation();
|
|
116
|
-
const relativeX = event.clientX -
|
|
117
|
-
event.target.getBoundingClientRect().left;
|
|
118
|
-
setStartX(relativeX);
|
|
119
|
-
setCurrentX(relativeX);
|
|
120
|
-
}
|
|
121
|
-
function mouseMove(event) {
|
|
122
|
-
const target = event.target;
|
|
123
|
-
setGuideX(event.clientX - target.getBoundingClientRect().left);
|
|
124
|
-
}
|
|
125
|
-
function mouseOut() {
|
|
126
|
-
setGuideX(undefined);
|
|
127
|
-
(0, mobx_1.transaction)(() => {
|
|
128
|
-
for (const view of model.views) {
|
|
129
|
-
view.setOffsets(undefined, undefined);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function handleClose() {
|
|
134
|
-
setAnchorPosition(undefined);
|
|
135
|
-
setStartX(undefined);
|
|
136
|
-
setCurrentX(undefined);
|
|
137
|
-
}
|
|
138
|
-
const open = Boolean(anchorPosition);
|
|
139
|
-
function handleMenuItemClick(_, callback) {
|
|
140
|
-
callback();
|
|
141
|
-
handleClose();
|
|
142
|
-
}
|
|
143
|
-
if (startX === undefined) {
|
|
144
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [guideX !== undefined ? ((0, jsx_runtime_1.jsx)(VerticalGuide_1.default, { model: model, coordX: guideX })) : null, (0, jsx_runtime_1.jsx)("div", { ref: controlsRef, className: classes.rubberbandControl, onMouseDown: mouseDown, onMouseOut: mouseOut, onMouseMove: mouseMove, children: ControlComponent })] }));
|
|
145
|
-
}
|
|
146
|
-
const right = anchorPosition ? anchorPosition.offsetX : currentX || 0;
|
|
147
|
-
const left = Math.min(right, startX);
|
|
148
|
-
const width = Math.abs(right - startX);
|
|
149
|
-
const { views } = model;
|
|
150
|
-
const leftBpOffset = views.map(view => view.pxToBp(left));
|
|
151
|
-
const rightBpOffset = views.map(view => view.pxToBp(left + width));
|
|
152
|
-
const numOfBpSelected = views.map(view => Math.ceil(width * view.bpPerPx));
|
|
153
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [rubberbandRef.current ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Popover, { className: classes.popover, classes: { paper: classes.paper }, open: true, anchorEl: rubberbandRef.current, anchorOrigin: {
|
|
154
|
-
vertical: 'top',
|
|
155
|
-
horizontal: 'left',
|
|
156
|
-
}, transformOrigin: {
|
|
157
|
-
vertical: 'bottom',
|
|
158
|
-
horizontal: 'right',
|
|
159
|
-
}, keepMounted: true, disableRestoreFocus: true, children: leftBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)(material_1.Typography, { children: (0, util_1.stringify)(l, true) }, [JSON.stringify(l), idx, 'left'].join('-')))) }), (0, jsx_runtime_1.jsx)(material_1.Popover, { className: classes.popover, classes: { paper: classes.paper }, open: true, anchorEl: rubberbandRef.current, anchorOrigin: {
|
|
160
|
-
vertical: 'top',
|
|
161
|
-
horizontal: 'right',
|
|
162
|
-
}, transformOrigin: {
|
|
163
|
-
vertical: 'bottom',
|
|
164
|
-
horizontal: 'left',
|
|
165
|
-
}, keepMounted: true, disableRestoreFocus: true, children: rightBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)(material_1.Typography, { children: (0, util_1.stringify)(l, true) }, [JSON.stringify(l), idx, 'right'].join('-')))) })] })) : null, (0, jsx_runtime_1.jsx)("div", { ref: rubberbandRef, className: classes.rubberband, style: { left, width }, children: (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", className: classes.rubberbandText, children: numOfBpSelected.map((n, i) => ((0, jsx_runtime_1.jsx)(material_1.Typography, { children: `${n.toLocaleString('en-US')}bp` }, `${n}_${i}`))) }) }), (0, jsx_runtime_1.jsx)("div", { className: classes.rubberbandControl, ref: controlsRef, onMouseDown: mouseDown, onMouseOut: mouseOut, onMouseMove: mouseMove, children: ControlComponent }), anchorPosition ? ((0, jsx_runtime_1.jsx)(ui_1.Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
26
|
+
const { guideX, rubberbandOn, leftBpOffset, rightBpOffset, numOfBpSelected, width, left, anchorPosition, open, handleMenuItemClick, handleClose, mouseMove, mouseDown, mouseOut, } = (0, useRangeSelect_1.useRangeSelect)(ref, model);
|
|
27
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [guideX !== undefined ? ((0, jsx_runtime_1.jsx)(VerticalGuide_1.default, { model: model, coordX: guideX })) : rubberbandOn ? ((0, jsx_runtime_1.jsx)(RubberbandSpan_1.default, { leftBpOffset: leftBpOffset, rightBpOffset: rightBpOffset, numOfBpSelected: numOfBpSelected, width: width, left: left })) : null, anchorPosition ? ((0, jsx_runtime_1.jsx)(ui_1.Menu, { anchorReference: "anchorPosition", anchorPosition: {
|
|
166
28
|
left: anchorPosition.clientX,
|
|
167
29
|
top: anchorPosition.clientY,
|
|
168
|
-
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null] }));
|
|
30
|
+
}, onMenuItemClick: handleMenuItemClick, open: open, onClose: handleClose, menuItems: model.rubberBandMenuItems() })) : null, (0, jsx_runtime_1.jsx)("div", { "data-testid": "rubberband_controls", className: classes.rubberbandControl, ref: ref, onMouseDown: mouseDown, onMouseMove: mouseMove, onMouseOut: mouseOut, children: ControlComponent })] }));
|
|
169
31
|
});
|
|
170
|
-
exports.default =
|
|
32
|
+
exports.default = Rubberband;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Offset {
|
|
2
|
+
coord: number;
|
|
3
|
+
refName?: string;
|
|
4
|
+
oob?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export default function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top, sticky, }: {
|
|
7
|
+
leftBpOffset: Offset[];
|
|
8
|
+
rightBpOffset: Offset[];
|
|
9
|
+
numOfBpSelected?: number[];
|
|
10
|
+
left: number;
|
|
11
|
+
width: number;
|
|
12
|
+
top?: number;
|
|
13
|
+
sticky?: boolean;
|
|
14
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = RubberbandSpan;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const util_1 = require("@jbrowse/core/util");
|
|
10
|
+
const material_1 = require("@mui/material");
|
|
11
|
+
const mui_1 = require("tss-react/mui");
|
|
12
|
+
const RubberbandTooltip_1 = __importDefault(require("./RubberbandTooltip"));
|
|
13
|
+
const useStyles = (0, mui_1.makeStyles)()(theme => {
|
|
14
|
+
const { tertiary } = theme.palette;
|
|
15
|
+
const background = (0, material_1.alpha)(tertiary.light, 0.7);
|
|
16
|
+
return {
|
|
17
|
+
rubberband: {
|
|
18
|
+
height: '100%',
|
|
19
|
+
background,
|
|
20
|
+
position: 'absolute',
|
|
21
|
+
zIndex: 830,
|
|
22
|
+
textAlign: 'center',
|
|
23
|
+
},
|
|
24
|
+
rubberbandText: {
|
|
25
|
+
color: theme.palette.tertiary.contrastText,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
function RubberbandSpan({ leftBpOffset, rightBpOffset, numOfBpSelected, left, width, top = 0, sticky = false, }) {
|
|
30
|
+
const { classes } = useStyles();
|
|
31
|
+
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [anchorEl ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(RubberbandTooltip_1.default, { side: "left", anchorEl: anchorEl, text: leftBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.stringify)(l, true) }, `JSON.stringify(l)-${idx}`))) }), (0, jsx_runtime_1.jsx)(RubberbandTooltip_1.default, { side: "right", anchorEl: anchorEl, text: rightBpOffset.map((l, idx) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.stringify)(l, true) }, `JSON.stringify(l)-${idx}`))) })] })) : null, (0, jsx_runtime_1.jsx)("div", { className: classes.rubberband, style: { left, width }, children: numOfBpSelected ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { ref: el => {
|
|
33
|
+
setAnchorEl(el);
|
|
34
|
+
}, variant: "h6", className: classes.rubberbandText, style: {
|
|
35
|
+
top,
|
|
36
|
+
position: sticky ? 'sticky' : undefined,
|
|
37
|
+
}, children: numOfBpSelected.map((n, i) => ((0, jsx_runtime_1.jsx)("div", { children: (0, util_1.getBpDisplayStr)(n) }, i))) })) : null })] }));
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = RubberbandTooltip;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const material_1 = require("@mui/material");
|
|
6
|
+
function RubberbandTooltip({ anchorEl, side, text, }) {
|
|
7
|
+
return ((0, jsx_runtime_1.jsx)(material_1.Tooltip, { title: text, open: true, placement: side === 'left' ? 'left-start' : 'right-start', slotProps: {
|
|
8
|
+
popper: {
|
|
9
|
+
anchorEl,
|
|
10
|
+
modifiers: [
|
|
11
|
+
{
|
|
12
|
+
name: 'offset',
|
|
13
|
+
options: {
|
|
14
|
+
offset: [-30, -10],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
}, children: (0, jsx_runtime_1.jsx)("span", {}) }));
|
|
20
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { LinearComparativeViewModel } from '../model';
|
|
3
|
+
interface AnchorPosition {
|
|
4
|
+
offsetX: number;
|
|
5
|
+
clientX: number;
|
|
6
|
+
clientY: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function useRangeSelect(ref: React.RefObject<HTMLDivElement | null>, model: LinearComparativeViewModel): {
|
|
9
|
+
open: boolean;
|
|
10
|
+
guideX: number | undefined;
|
|
11
|
+
mouseDown: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
12
|
+
mouseMove: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
13
|
+
mouseOut: () => void;
|
|
14
|
+
handleMenuItemClick: (_: unknown, callback: () => void) => void;
|
|
15
|
+
rubberbandOn?: undefined;
|
|
16
|
+
handleClose?: undefined;
|
|
17
|
+
leftBpOffset?: undefined;
|
|
18
|
+
rightBpOffset?: undefined;
|
|
19
|
+
anchorPosition?: undefined;
|
|
20
|
+
numOfBpSelected?: undefined;
|
|
21
|
+
width?: undefined;
|
|
22
|
+
left?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
open: boolean;
|
|
25
|
+
rubberbandOn: boolean;
|
|
26
|
+
mouseDown: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
27
|
+
mouseMove: (event: React.MouseEvent<HTMLDivElement>) => void;
|
|
28
|
+
mouseOut: () => void;
|
|
29
|
+
handleClose: () => void;
|
|
30
|
+
handleMenuItemClick: (_: unknown, callback: () => void) => void;
|
|
31
|
+
leftBpOffset: {
|
|
32
|
+
coord: number;
|
|
33
|
+
index: number;
|
|
34
|
+
refName: string;
|
|
35
|
+
oob: boolean;
|
|
36
|
+
assemblyName: string;
|
|
37
|
+
offset: number;
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
reversed?: boolean;
|
|
41
|
+
}[];
|
|
42
|
+
rightBpOffset: {
|
|
43
|
+
coord: number;
|
|
44
|
+
index: number;
|
|
45
|
+
refName: string;
|
|
46
|
+
oob: boolean;
|
|
47
|
+
assemblyName: string;
|
|
48
|
+
offset: number;
|
|
49
|
+
start: number;
|
|
50
|
+
end: number;
|
|
51
|
+
reversed?: boolean;
|
|
52
|
+
}[];
|
|
53
|
+
anchorPosition: AnchorPosition | undefined;
|
|
54
|
+
numOfBpSelected: number[];
|
|
55
|
+
width: number;
|
|
56
|
+
left: number;
|
|
57
|
+
guideX?: undefined;
|
|
58
|
+
};
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useRangeSelect = useRangeSelect;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const mobx_1 = require("mobx");
|
|
6
|
+
const util_1 = require("./util");
|
|
7
|
+
function useRangeSelect(ref, model) {
|
|
8
|
+
const [startX, setStartX] = (0, react_1.useState)();
|
|
9
|
+
const [currentX, setCurrentX] = (0, react_1.useState)();
|
|
10
|
+
const [anchorPosition, setAnchorPosition] = (0, react_1.useState)();
|
|
11
|
+
const [guideX, setGuideX] = (0, react_1.useState)();
|
|
12
|
+
const mouseDragging = startX !== undefined && anchorPosition === undefined;
|
|
13
|
+
(0, react_1.useEffect)(() => {
|
|
14
|
+
function computeOffsets(offsetX) {
|
|
15
|
+
if (startX === undefined) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const leftPx = Math.min(startX, offsetX);
|
|
19
|
+
const rightPx = Math.max(startX, offsetX);
|
|
20
|
+
return model.views.map(view => ({
|
|
21
|
+
leftOffset: view.pxToBp(leftPx),
|
|
22
|
+
rightOffset: view.pxToBp(rightPx),
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
function globalMouseMove(event) {
|
|
26
|
+
if (ref.current && mouseDragging) {
|
|
27
|
+
const relativeX = (0, util_1.getRelativeX)(event, ref.current);
|
|
28
|
+
setCurrentX(relativeX);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function globalMouseUp(event) {
|
|
32
|
+
if (startX !== undefined && ref.current) {
|
|
33
|
+
const { clientX, clientY } = event;
|
|
34
|
+
const offsetX = (0, util_1.getRelativeX)(event, ref.current);
|
|
35
|
+
setAnchorPosition({
|
|
36
|
+
offsetX,
|
|
37
|
+
clientX,
|
|
38
|
+
clientY,
|
|
39
|
+
});
|
|
40
|
+
const offsets = computeOffsets(offsetX);
|
|
41
|
+
if (offsets) {
|
|
42
|
+
(0, mobx_1.transaction)(() => {
|
|
43
|
+
for (const [idx, elt] of offsets.entries()) {
|
|
44
|
+
model.views[idx].setOffsets(elt.leftOffset, elt.rightOffset);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
setGuideX(undefined);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (mouseDragging) {
|
|
52
|
+
window.addEventListener('mousemove', globalMouseMove);
|
|
53
|
+
window.addEventListener('mouseup', globalMouseUp);
|
|
54
|
+
return () => {
|
|
55
|
+
window.removeEventListener('mousemove', globalMouseMove);
|
|
56
|
+
window.removeEventListener('mouseup', globalMouseUp);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return () => { };
|
|
60
|
+
}, [startX, mouseDragging, model, ref]);
|
|
61
|
+
(0, react_1.useEffect)(() => {
|
|
62
|
+
if (!mouseDragging &&
|
|
63
|
+
currentX !== undefined &&
|
|
64
|
+
startX !== undefined &&
|
|
65
|
+
Math.abs(currentX - startX) <= 3) {
|
|
66
|
+
handleClose();
|
|
67
|
+
}
|
|
68
|
+
}, [mouseDragging, currentX, startX]);
|
|
69
|
+
function mouseDown(event) {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
event.stopPropagation();
|
|
72
|
+
const relativeX = (0, util_1.getRelativeX)(event, ref.current);
|
|
73
|
+
setStartX(relativeX);
|
|
74
|
+
setCurrentX(relativeX);
|
|
75
|
+
}
|
|
76
|
+
function mouseMove(event) {
|
|
77
|
+
setGuideX((0, util_1.getRelativeX)(event, ref.current));
|
|
78
|
+
}
|
|
79
|
+
function mouseOut() {
|
|
80
|
+
setGuideX(undefined);
|
|
81
|
+
(0, mobx_1.transaction)(() => {
|
|
82
|
+
for (const view of model.views) {
|
|
83
|
+
view.setOffsets(undefined, undefined);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function handleClose() {
|
|
88
|
+
setAnchorPosition(undefined);
|
|
89
|
+
setStartX(undefined);
|
|
90
|
+
setCurrentX(undefined);
|
|
91
|
+
}
|
|
92
|
+
function handleMenuItemClick(_, callback) {
|
|
93
|
+
callback();
|
|
94
|
+
handleClose();
|
|
95
|
+
}
|
|
96
|
+
const open = Boolean(anchorPosition);
|
|
97
|
+
if (startX === undefined) {
|
|
98
|
+
return {
|
|
99
|
+
open,
|
|
100
|
+
guideX,
|
|
101
|
+
mouseDown,
|
|
102
|
+
mouseMove,
|
|
103
|
+
mouseOut,
|
|
104
|
+
handleMenuItemClick,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const right = anchorPosition ? anchorPosition.offsetX : currentX || 0;
|
|
108
|
+
const left = Math.min(right, startX);
|
|
109
|
+
const width = Math.abs(right - startX);
|
|
110
|
+
const leftBpOffset = model.views.map(view => view.pxToBp(left));
|
|
111
|
+
const rightBpOffset = model.views.map(view => view.pxToBp(left + width));
|
|
112
|
+
const numOfBpSelected = model.views.map(view => Math.ceil(width * view.bpPerPx));
|
|
113
|
+
return {
|
|
114
|
+
open,
|
|
115
|
+
rubberbandOn: true,
|
|
116
|
+
mouseDown,
|
|
117
|
+
mouseMove,
|
|
118
|
+
mouseOut,
|
|
119
|
+
handleClose,
|
|
120
|
+
handleMenuItemClick,
|
|
121
|
+
leftBpOffset,
|
|
122
|
+
rightBpOffset,
|
|
123
|
+
anchorPosition,
|
|
124
|
+
numOfBpSelected,
|
|
125
|
+
width,
|
|
126
|
+
left,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRelativeX = getRelativeX;
|
|
4
|
+
function getRelativeX(event, element) {
|
|
5
|
+
return event.clientX - ((element === null || element === void 0 ? void 0 : element.getBoundingClientRect().left) || 0);
|
|
6
|
+
}
|
|
@@ -77,6 +77,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
77
77
|
readonly width: number;
|
|
78
78
|
readonly interRegionPaddingWidth: number;
|
|
79
79
|
readonly assemblyNames: string[];
|
|
80
|
+
readonly assemblyDisplayNames: string[];
|
|
80
81
|
readonly isTopLevelView: import("@jbrowse/core/util").AbstractViewModel | undefined;
|
|
81
82
|
readonly stickyViewHeaders: boolean | undefined;
|
|
82
83
|
readonly rubberbandTop: number;
|
|
@@ -393,6 +394,7 @@ declare function stateModelFactory(pluginManager: PluginManager): import("mobx-s
|
|
|
393
394
|
readonly width: number;
|
|
394
395
|
readonly interRegionPaddingWidth: number;
|
|
395
396
|
readonly assemblyNames: string[];
|
|
397
|
+
readonly assemblyDisplayNames: string[];
|
|
396
398
|
readonly isTopLevelView: import("@jbrowse/core/util").AbstractViewModel | undefined;
|
|
397
399
|
readonly stickyViewHeaders: boolean | undefined;
|
|
398
400
|
readonly rubberbandTop: number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = BlockError;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const mui_1 = require("tss-react/mui");
|
|
6
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
7
|
+
blockError: {
|
|
8
|
+
background: '#f1f1f1',
|
|
9
|
+
padding: 10,
|
|
10
|
+
color: 'red',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
function BlockError({ error }) {
|
|
14
|
+
const { classes } = useStyles();
|
|
15
|
+
return (0, jsx_runtime_1.jsx)("div", { className: classes.blockError, children: `${error}` });
|
|
16
|
+
}
|