@jbrowse/plugin-lollipop 3.0.4 → 3.1.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/LollipopRenderer/Layout.d.ts +3 -1
- package/dist/LollipopRenderer/Layout.js +25 -16
- package/dist/LollipopRenderer/components/Lollipop.js +63 -34
- package/dist/LollipopRenderer/components/LollipopRendering.js +8 -4
- package/dist/LollipopRenderer/components/ScoreText.js +5 -1
- package/dist/LollipopRenderer/index.js +2 -35
- package/esm/LollipopRenderer/Layout.d.ts +3 -1
- package/esm/LollipopRenderer/Layout.js +25 -16
- package/esm/LollipopRenderer/components/Lollipop.js +63 -34
- package/esm/LollipopRenderer/components/LollipopRendering.js +10 -6
- package/esm/LollipopRenderer/components/ScoreText.js +5 -1
- package/esm/LollipopRenderer/index.js +2 -2
- package/package.json +4 -4
|
@@ -16,12 +16,13 @@ type LayoutMap = Map<string, LayoutEntry>;
|
|
|
16
16
|
export declare class FloatingLayout {
|
|
17
17
|
width: number;
|
|
18
18
|
totalHeight: number;
|
|
19
|
+
rectangles: Map<any, any>;
|
|
19
20
|
constructor({ width }: {
|
|
20
21
|
width: number;
|
|
21
22
|
});
|
|
23
|
+
discardRange(): void;
|
|
22
24
|
items: LayoutItem[];
|
|
23
25
|
layout: LayoutMap;
|
|
24
|
-
layoutDirty: boolean;
|
|
25
26
|
add(uniqueId: string, anchorLocation: number, width: number, height: number, data: {
|
|
26
27
|
score: number;
|
|
27
28
|
}): void;
|
|
@@ -47,6 +48,7 @@ export declare class PrecomputedFloatingLayout {
|
|
|
47
48
|
add(uniqueId: string): void;
|
|
48
49
|
getLayout(): LayoutMap;
|
|
49
50
|
getTotalHeight(): number;
|
|
51
|
+
discardRange(): void;
|
|
50
52
|
static fromJSON(json: ConstructorParameters<typeof PrecomputedFloatingLayout>[0]): PrecomputedFloatingLayout;
|
|
51
53
|
}
|
|
52
54
|
export {};
|
|
@@ -6,24 +6,31 @@ const range_1 = require("@jbrowse/core/util/range");
|
|
|
6
6
|
class FloatingLayout {
|
|
7
7
|
constructor({ width }) {
|
|
8
8
|
this.totalHeight = 0;
|
|
9
|
+
this.rectangles = new Map();
|
|
9
10
|
this.items = [];
|
|
10
11
|
this.layout = new Map();
|
|
11
|
-
this.layoutDirty = false;
|
|
12
12
|
if (!width) {
|
|
13
13
|
throw new Error('width required to make a new FloatingLayout');
|
|
14
14
|
}
|
|
15
15
|
this.width = width;
|
|
16
16
|
}
|
|
17
|
+
discardRange() {
|
|
18
|
+
this.items = [];
|
|
19
|
+
this.layout = new Map();
|
|
20
|
+
this.totalHeight = 0;
|
|
21
|
+
}
|
|
17
22
|
add(uniqueId, anchorLocation, width, height, data) {
|
|
18
|
-
this.items.push({
|
|
19
|
-
|
|
23
|
+
this.items.push({
|
|
24
|
+
uniqueId,
|
|
25
|
+
anchorLocation,
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
data,
|
|
29
|
+
});
|
|
20
30
|
}
|
|
21
31
|
getLayout(configuration) {
|
|
22
|
-
if (!this.layoutDirty) {
|
|
23
|
-
return this.layout;
|
|
24
|
-
}
|
|
25
32
|
if (!configuration) {
|
|
26
|
-
|
|
33
|
+
return this.layout;
|
|
27
34
|
}
|
|
28
35
|
const minY = (0, configuration_1.readConfObject)(configuration, 'minStickLength');
|
|
29
36
|
const sorted = this.items.sort((a, b) => a.data.score - b.data.score);
|
|
@@ -50,7 +57,11 @@ class FloatingLayout {
|
|
|
50
57
|
}
|
|
51
58
|
layoutEntries[i] = [
|
|
52
59
|
currentItem.uniqueId,
|
|
53
|
-
{
|
|
60
|
+
{
|
|
61
|
+
...currentItem,
|
|
62
|
+
x: start,
|
|
63
|
+
y: top,
|
|
64
|
+
},
|
|
54
65
|
];
|
|
55
66
|
if (bottom > maxBottom) {
|
|
56
67
|
maxBottom = bottom;
|
|
@@ -58,23 +69,19 @@ class FloatingLayout {
|
|
|
58
69
|
}
|
|
59
70
|
this.totalHeight = maxBottom;
|
|
60
71
|
this.layout = new Map(layoutEntries);
|
|
61
|
-
this.layoutDirty = false;
|
|
62
72
|
return this.layout;
|
|
63
73
|
}
|
|
64
74
|
getTotalHeight() {
|
|
65
|
-
if (this.layoutDirty) {
|
|
66
|
-
throw new Error('getTotalHeight does not work when the layout is dirty.');
|
|
67
|
-
}
|
|
68
75
|
return this.totalHeight;
|
|
69
76
|
}
|
|
70
77
|
serializeRegion() {
|
|
71
78
|
return this.toJSON();
|
|
72
79
|
}
|
|
73
80
|
toJSON() {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
return {
|
|
82
|
+
pairs: [...this.getLayout()],
|
|
83
|
+
totalHeight: this.getTotalHeight(),
|
|
84
|
+
};
|
|
78
85
|
}
|
|
79
86
|
static fromJSON() {
|
|
80
87
|
throw new Error('not supported');
|
|
@@ -97,6 +104,8 @@ class PrecomputedFloatingLayout {
|
|
|
97
104
|
getTotalHeight() {
|
|
98
105
|
return this.totalHeight;
|
|
99
106
|
}
|
|
107
|
+
discardRange() {
|
|
108
|
+
}
|
|
100
109
|
static fromJSON(json) {
|
|
101
110
|
return new PrecomputedFloatingLayout(json);
|
|
102
111
|
}
|
|
@@ -10,39 +10,6 @@ const ScoreText_1 = __importDefault(require("./ScoreText"));
|
|
|
10
10
|
const Lollipop = (0, mobx_react_1.observer)(function Lollipop(props) {
|
|
11
11
|
const { feature, config, layoutRecord, selectedFeatureId } = props;
|
|
12
12
|
const { anchorLocation, y, data: { radiusPx }, } = layoutRecord;
|
|
13
|
-
const onFeatureMouseDown = (event) => {
|
|
14
|
-
const { onFeatureMouseDown: handler, feature } = props;
|
|
15
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
16
|
-
};
|
|
17
|
-
const onFeatureMouseEnter = (event) => {
|
|
18
|
-
const { onFeatureMouseEnter: handler, feature } = props;
|
|
19
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
20
|
-
};
|
|
21
|
-
const onFeatureMouseOut = (event) => {
|
|
22
|
-
const { onFeatureMouseOut: handler, feature } = props;
|
|
23
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
24
|
-
};
|
|
25
|
-
const onFeatureMouseOver = (event) => {
|
|
26
|
-
const { onFeatureMouseOver: handler, feature } = props;
|
|
27
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
28
|
-
};
|
|
29
|
-
const onFeatureMouseUp = (event) => {
|
|
30
|
-
const { onFeatureMouseUp: handler, feature } = props;
|
|
31
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
32
|
-
};
|
|
33
|
-
const onFeatureMouseLeave = (event) => {
|
|
34
|
-
const { onFeatureMouseLeave: handler, feature } = props;
|
|
35
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
36
|
-
};
|
|
37
|
-
const onFeatureMouseMove = (event) => {
|
|
38
|
-
const { onFeatureMouseMove: handler, feature } = props;
|
|
39
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
40
|
-
};
|
|
41
|
-
const onFeatureClick = (event) => {
|
|
42
|
-
const { onFeatureClick: handler, feature } = props;
|
|
43
|
-
event.stopPropagation();
|
|
44
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
45
|
-
};
|
|
46
13
|
const styleOuter = {
|
|
47
14
|
fill: (0, configuration_1.readConfObject)(config, 'strokeColor', { feature }),
|
|
48
15
|
};
|
|
@@ -53,6 +20,68 @@ const Lollipop = (0, mobx_react_1.observer)(function Lollipop(props) {
|
|
|
53
20
|
fill: (0, configuration_1.readConfObject)(config, 'innerColor', { feature }),
|
|
54
21
|
};
|
|
55
22
|
const strokeWidth = (0, configuration_1.readConfObject)(config, 'strokeWidth', { feature });
|
|
56
|
-
return ((0, jsx_runtime_1.jsxs)("g", { "data-testid": feature.id(), children: [(0, jsx_runtime_1.jsx)("title", { children: (0, configuration_1.readConfObject)(config, 'caption', { feature }) }), (0, jsx_runtime_1.jsx)("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx, style: styleOuter, onMouseDown:
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)("g", { "data-testid": feature.id(), children: [(0, jsx_runtime_1.jsx)("title", { children: (0, configuration_1.readConfObject)(config, 'caption', { feature }) }), (0, jsx_runtime_1.jsx)("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx, style: styleOuter, onMouseDown: (event) => {
|
|
24
|
+
const { onFeatureMouseDown: handler, feature } = props;
|
|
25
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
26
|
+
}, onMouseEnter: (event) => {
|
|
27
|
+
const { onFeatureMouseEnter: handler, feature } = props;
|
|
28
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
29
|
+
}, onMouseOut: (event) => {
|
|
30
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
31
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
32
|
+
}, onMouseOver: (event) => {
|
|
33
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
34
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
35
|
+
}, onMouseUp: (event) => {
|
|
36
|
+
const { onFeatureMouseUp: handler, feature } = props;
|
|
37
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
38
|
+
}, onMouseLeave: (event) => {
|
|
39
|
+
const { onFeatureMouseLeave: handler, feature } = props;
|
|
40
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
41
|
+
}, onMouseMove: (event) => {
|
|
42
|
+
const { onFeatureMouseMove: handler, feature } = props;
|
|
43
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
44
|
+
}, onClick: (event) => {
|
|
45
|
+
const { onFeatureClick: handler, feature } = props;
|
|
46
|
+
event.stopPropagation();
|
|
47
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
48
|
+
}, onFocus: (event) => {
|
|
49
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
50
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
51
|
+
}, onBlur: (event) => {
|
|
52
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
53
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
54
|
+
} }), radiusPx - strokeWidth <= 2 ? null : ((0, jsx_runtime_1.jsx)("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx - strokeWidth, style: styleInner, onMouseDown: (event) => {
|
|
55
|
+
const { onFeatureMouseDown: handler, feature } = props;
|
|
56
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
57
|
+
}, onMouseEnter: (event) => {
|
|
58
|
+
const { onFeatureMouseEnter: handler, feature } = props;
|
|
59
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
60
|
+
}, onMouseOut: (event) => {
|
|
61
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
62
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
63
|
+
}, onMouseOver: (event) => {
|
|
64
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
65
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
66
|
+
}, onMouseUp: (event) => {
|
|
67
|
+
const { onFeatureMouseUp: handler, feature } = props;
|
|
68
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
69
|
+
}, onMouseLeave: (event) => {
|
|
70
|
+
const { onFeatureMouseLeave: handler, feature } = props;
|
|
71
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
72
|
+
}, onMouseMove: (event) => {
|
|
73
|
+
const { onFeatureMouseMove: handler, feature } = props;
|
|
74
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
75
|
+
}, onClick: (event) => {
|
|
76
|
+
const { onFeatureClick: handler, feature } = props;
|
|
77
|
+
event.stopPropagation();
|
|
78
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
79
|
+
}, onFocus: (event) => {
|
|
80
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
81
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
82
|
+
}, onBlur: (event) => {
|
|
83
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
84
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
85
|
+
} })), (0, jsx_runtime_1.jsx)(ScoreText_1.default, { feature: feature, config: config, layoutRecord: layoutRecord })] }));
|
|
57
86
|
});
|
|
58
87
|
exports.default = Lollipop;
|
|
@@ -54,6 +54,10 @@ const LollipopRendering = (0, mobx_react_1.observer)(function (props) {
|
|
|
54
54
|
const { onClick: handler } = props;
|
|
55
55
|
return handler === null || handler === void 0 ? void 0 : handler(event);
|
|
56
56
|
};
|
|
57
|
+
const [client, setClient] = (0, react_1.useState)(false);
|
|
58
|
+
(0, react_1.useEffect)(() => {
|
|
59
|
+
setClient(true);
|
|
60
|
+
}, []);
|
|
57
61
|
const { regions, bpPerPx, layout, config, features = new Map(), displayModel = {}, } = props;
|
|
58
62
|
const { selectedFeatureId } = displayModel;
|
|
59
63
|
const region = regions[0];
|
|
@@ -69,9 +73,9 @@ const LollipopRendering = (0, mobx_react_1.observer)(function (props) {
|
|
|
69
73
|
const width = (region.end - region.start) / bpPerPx;
|
|
70
74
|
const records = [...layout.getLayout(config).values()];
|
|
71
75
|
const height = layout.getTotalHeight();
|
|
72
|
-
return ((0, jsx_runtime_1.jsx)("svg", { width: width, height: height, style: { position: 'relative' }, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseEnter, onBlur: onMouseLeave, onClick: onClick, children: records.map(layoutRecord => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
return ((0, jsx_runtime_1.jsx)("svg", { width: width, height: height, style: { position: 'relative' }, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseEnter, onBlur: onMouseLeave, onClick: onClick, children: client ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: records.map(layoutRecord => {
|
|
77
|
+
const feature = features.get(layoutRecord.data.featureId);
|
|
78
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Stick_1.default, { ...props, config: config, layoutRecord: layoutRecord, feature: feature }, `stick-${feature.id()}`), (0, jsx_runtime_1.jsx)(Lollipop_1.default, { ...props, layoutRecord: layoutRecord, feature: feature, selectedFeatureId: selectedFeatureId }, `body-${feature.id()}`)] }, feature.id()));
|
|
79
|
+
}) })) : null }));
|
|
76
80
|
});
|
|
77
81
|
exports.default = LollipopRendering;
|
|
@@ -12,5 +12,9 @@ function ScoreText({ feature, config, layoutRecord: { y, data: { anchorX, radius
|
|
|
12
12
|
if (fontHeight < 12) {
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
|
-
return ((0, jsx_runtime_1.jsx)("text", { style: {
|
|
15
|
+
return ((0, jsx_runtime_1.jsx)("text", { style: {
|
|
16
|
+
pointerEvents: 'none',
|
|
17
|
+
fontSize: fontHeight,
|
|
18
|
+
fill: (0, color_1.contrastingTextColor)(innerColor),
|
|
19
|
+
}, x: anchorX, y: y + radiusPx - fontHeight / 2.4, textAnchor: "middle", dominantBaseline: "hanging", children: scoreString }));
|
|
16
20
|
}
|
|
@@ -1,49 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
38
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
6
|
exports.default = LollipopRendererF;
|
|
40
|
-
const react_1 = require("react");
|
|
41
7
|
const LollipopRenderer_1 = __importDefault(require("./LollipopRenderer"));
|
|
8
|
+
const LollipopRendering_1 = __importDefault(require("./components/LollipopRendering"));
|
|
42
9
|
const configSchema_1 = __importDefault(require("./configSchema"));
|
|
43
10
|
function LollipopRendererF(pluginManager) {
|
|
44
11
|
pluginManager.addRendererType(() => new LollipopRenderer_1.default({
|
|
45
12
|
name: 'LollipopRenderer',
|
|
46
|
-
ReactComponent:
|
|
13
|
+
ReactComponent: LollipopRendering_1.default,
|
|
47
14
|
configSchema: configSchema_1.default,
|
|
48
15
|
pluginManager,
|
|
49
16
|
}));
|
|
@@ -16,12 +16,13 @@ type LayoutMap = Map<string, LayoutEntry>;
|
|
|
16
16
|
export declare class FloatingLayout {
|
|
17
17
|
width: number;
|
|
18
18
|
totalHeight: number;
|
|
19
|
+
rectangles: Map<any, any>;
|
|
19
20
|
constructor({ width }: {
|
|
20
21
|
width: number;
|
|
21
22
|
});
|
|
23
|
+
discardRange(): void;
|
|
22
24
|
items: LayoutItem[];
|
|
23
25
|
layout: LayoutMap;
|
|
24
|
-
layoutDirty: boolean;
|
|
25
26
|
add(uniqueId: string, anchorLocation: number, width: number, height: number, data: {
|
|
26
27
|
score: number;
|
|
27
28
|
}): void;
|
|
@@ -47,6 +48,7 @@ export declare class PrecomputedFloatingLayout {
|
|
|
47
48
|
add(uniqueId: string): void;
|
|
48
49
|
getLayout(): LayoutMap;
|
|
49
50
|
getTotalHeight(): number;
|
|
51
|
+
discardRange(): void;
|
|
50
52
|
static fromJSON(json: ConstructorParameters<typeof PrecomputedFloatingLayout>[0]): PrecomputedFloatingLayout;
|
|
51
53
|
}
|
|
52
54
|
export {};
|
|
@@ -3,24 +3,31 @@ import { doesIntersect2 } from '@jbrowse/core/util/range';
|
|
|
3
3
|
export class FloatingLayout {
|
|
4
4
|
constructor({ width }) {
|
|
5
5
|
this.totalHeight = 0;
|
|
6
|
+
this.rectangles = new Map();
|
|
6
7
|
this.items = [];
|
|
7
8
|
this.layout = new Map();
|
|
8
|
-
this.layoutDirty = false;
|
|
9
9
|
if (!width) {
|
|
10
10
|
throw new Error('width required to make a new FloatingLayout');
|
|
11
11
|
}
|
|
12
12
|
this.width = width;
|
|
13
13
|
}
|
|
14
|
+
discardRange() {
|
|
15
|
+
this.items = [];
|
|
16
|
+
this.layout = new Map();
|
|
17
|
+
this.totalHeight = 0;
|
|
18
|
+
}
|
|
14
19
|
add(uniqueId, anchorLocation, width, height, data) {
|
|
15
|
-
this.items.push({
|
|
16
|
-
|
|
20
|
+
this.items.push({
|
|
21
|
+
uniqueId,
|
|
22
|
+
anchorLocation,
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
data,
|
|
26
|
+
});
|
|
17
27
|
}
|
|
18
28
|
getLayout(configuration) {
|
|
19
|
-
if (!this.layoutDirty) {
|
|
20
|
-
return this.layout;
|
|
21
|
-
}
|
|
22
29
|
if (!configuration) {
|
|
23
|
-
|
|
30
|
+
return this.layout;
|
|
24
31
|
}
|
|
25
32
|
const minY = readConfObject(configuration, 'minStickLength');
|
|
26
33
|
const sorted = this.items.sort((a, b) => a.data.score - b.data.score);
|
|
@@ -47,7 +54,11 @@ export class FloatingLayout {
|
|
|
47
54
|
}
|
|
48
55
|
layoutEntries[i] = [
|
|
49
56
|
currentItem.uniqueId,
|
|
50
|
-
{
|
|
57
|
+
{
|
|
58
|
+
...currentItem,
|
|
59
|
+
x: start,
|
|
60
|
+
y: top,
|
|
61
|
+
},
|
|
51
62
|
];
|
|
52
63
|
if (bottom > maxBottom) {
|
|
53
64
|
maxBottom = bottom;
|
|
@@ -55,23 +66,19 @@ export class FloatingLayout {
|
|
|
55
66
|
}
|
|
56
67
|
this.totalHeight = maxBottom;
|
|
57
68
|
this.layout = new Map(layoutEntries);
|
|
58
|
-
this.layoutDirty = false;
|
|
59
69
|
return this.layout;
|
|
60
70
|
}
|
|
61
71
|
getTotalHeight() {
|
|
62
|
-
if (this.layoutDirty) {
|
|
63
|
-
throw new Error('getTotalHeight does not work when the layout is dirty.');
|
|
64
|
-
}
|
|
65
72
|
return this.totalHeight;
|
|
66
73
|
}
|
|
67
74
|
serializeRegion() {
|
|
68
75
|
return this.toJSON();
|
|
69
76
|
}
|
|
70
77
|
toJSON() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
return {
|
|
79
|
+
pairs: [...this.getLayout()],
|
|
80
|
+
totalHeight: this.getTotalHeight(),
|
|
81
|
+
};
|
|
75
82
|
}
|
|
76
83
|
static fromJSON() {
|
|
77
84
|
throw new Error('not supported');
|
|
@@ -93,6 +100,8 @@ export class PrecomputedFloatingLayout {
|
|
|
93
100
|
getTotalHeight() {
|
|
94
101
|
return this.totalHeight;
|
|
95
102
|
}
|
|
103
|
+
discardRange() {
|
|
104
|
+
}
|
|
96
105
|
static fromJSON(json) {
|
|
97
106
|
return new PrecomputedFloatingLayout(json);
|
|
98
107
|
}
|
|
@@ -5,39 +5,6 @@ import ScoreText from './ScoreText';
|
|
|
5
5
|
const Lollipop = observer(function Lollipop(props) {
|
|
6
6
|
const { feature, config, layoutRecord, selectedFeatureId } = props;
|
|
7
7
|
const { anchorLocation, y, data: { radiusPx }, } = layoutRecord;
|
|
8
|
-
const onFeatureMouseDown = (event) => {
|
|
9
|
-
const { onFeatureMouseDown: handler, feature } = props;
|
|
10
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
11
|
-
};
|
|
12
|
-
const onFeatureMouseEnter = (event) => {
|
|
13
|
-
const { onFeatureMouseEnter: handler, feature } = props;
|
|
14
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
15
|
-
};
|
|
16
|
-
const onFeatureMouseOut = (event) => {
|
|
17
|
-
const { onFeatureMouseOut: handler, feature } = props;
|
|
18
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
19
|
-
};
|
|
20
|
-
const onFeatureMouseOver = (event) => {
|
|
21
|
-
const { onFeatureMouseOver: handler, feature } = props;
|
|
22
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
23
|
-
};
|
|
24
|
-
const onFeatureMouseUp = (event) => {
|
|
25
|
-
const { onFeatureMouseUp: handler, feature } = props;
|
|
26
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
27
|
-
};
|
|
28
|
-
const onFeatureMouseLeave = (event) => {
|
|
29
|
-
const { onFeatureMouseLeave: handler, feature } = props;
|
|
30
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
31
|
-
};
|
|
32
|
-
const onFeatureMouseMove = (event) => {
|
|
33
|
-
const { onFeatureMouseMove: handler, feature } = props;
|
|
34
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
35
|
-
};
|
|
36
|
-
const onFeatureClick = (event) => {
|
|
37
|
-
const { onFeatureClick: handler, feature } = props;
|
|
38
|
-
event.stopPropagation();
|
|
39
|
-
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
40
|
-
};
|
|
41
8
|
const styleOuter = {
|
|
42
9
|
fill: readConfObject(config, 'strokeColor', { feature }),
|
|
43
10
|
};
|
|
@@ -48,6 +15,68 @@ const Lollipop = observer(function Lollipop(props) {
|
|
|
48
15
|
fill: readConfObject(config, 'innerColor', { feature }),
|
|
49
16
|
};
|
|
50
17
|
const strokeWidth = readConfObject(config, 'strokeWidth', { feature });
|
|
51
|
-
return (_jsxs("g", { "data-testid": feature.id(), children: [_jsx("title", { children: readConfObject(config, 'caption', { feature }) }), _jsx("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx, style: styleOuter, onMouseDown:
|
|
18
|
+
return (_jsxs("g", { "data-testid": feature.id(), children: [_jsx("title", { children: readConfObject(config, 'caption', { feature }) }), _jsx("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx, style: styleOuter, onMouseDown: (event) => {
|
|
19
|
+
const { onFeatureMouseDown: handler, feature } = props;
|
|
20
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
21
|
+
}, onMouseEnter: (event) => {
|
|
22
|
+
const { onFeatureMouseEnter: handler, feature } = props;
|
|
23
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
24
|
+
}, onMouseOut: (event) => {
|
|
25
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
26
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
27
|
+
}, onMouseOver: (event) => {
|
|
28
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
29
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
30
|
+
}, onMouseUp: (event) => {
|
|
31
|
+
const { onFeatureMouseUp: handler, feature } = props;
|
|
32
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
33
|
+
}, onMouseLeave: (event) => {
|
|
34
|
+
const { onFeatureMouseLeave: handler, feature } = props;
|
|
35
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
36
|
+
}, onMouseMove: (event) => {
|
|
37
|
+
const { onFeatureMouseMove: handler, feature } = props;
|
|
38
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
39
|
+
}, onClick: (event) => {
|
|
40
|
+
const { onFeatureClick: handler, feature } = props;
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
43
|
+
}, onFocus: (event) => {
|
|
44
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
45
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
46
|
+
}, onBlur: (event) => {
|
|
47
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
48
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
49
|
+
} }), radiusPx - strokeWidth <= 2 ? null : (_jsx("circle", { cx: anchorLocation, cy: y + radiusPx, r: radiusPx - strokeWidth, style: styleInner, onMouseDown: (event) => {
|
|
50
|
+
const { onFeatureMouseDown: handler, feature } = props;
|
|
51
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
52
|
+
}, onMouseEnter: (event) => {
|
|
53
|
+
const { onFeatureMouseEnter: handler, feature } = props;
|
|
54
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
55
|
+
}, onMouseOut: (event) => {
|
|
56
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
57
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
58
|
+
}, onMouseOver: (event) => {
|
|
59
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
60
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
61
|
+
}, onMouseUp: (event) => {
|
|
62
|
+
const { onFeatureMouseUp: handler, feature } = props;
|
|
63
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
64
|
+
}, onMouseLeave: (event) => {
|
|
65
|
+
const { onFeatureMouseLeave: handler, feature } = props;
|
|
66
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
67
|
+
}, onMouseMove: (event) => {
|
|
68
|
+
const { onFeatureMouseMove: handler, feature } = props;
|
|
69
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
70
|
+
}, onClick: (event) => {
|
|
71
|
+
const { onFeatureClick: handler, feature } = props;
|
|
72
|
+
event.stopPropagation();
|
|
73
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
74
|
+
}, onFocus: (event) => {
|
|
75
|
+
const { onFeatureMouseOver: handler, feature } = props;
|
|
76
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
77
|
+
}, onBlur: (event) => {
|
|
78
|
+
const { onFeatureMouseOut: handler, feature } = props;
|
|
79
|
+
return handler === null || handler === void 0 ? void 0 : handler(event, feature.id());
|
|
80
|
+
} })), _jsx(ScoreText, { feature: feature, config: config, layoutRecord: layoutRecord })] }));
|
|
52
81
|
});
|
|
53
82
|
export default Lollipop;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment } from 'react';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, useEffect, useState } from 'react';
|
|
3
3
|
import { readConfObject } from '@jbrowse/core/configuration';
|
|
4
4
|
import { bpToPx } from '@jbrowse/core/util';
|
|
5
5
|
import { observer } from 'mobx-react';
|
|
@@ -49,6 +49,10 @@ const LollipopRendering = observer(function (props) {
|
|
|
49
49
|
const { onClick: handler } = props;
|
|
50
50
|
return handler === null || handler === void 0 ? void 0 : handler(event);
|
|
51
51
|
};
|
|
52
|
+
const [client, setClient] = useState(false);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
setClient(true);
|
|
55
|
+
}, []);
|
|
52
56
|
const { regions, bpPerPx, layout, config, features = new Map(), displayModel = {}, } = props;
|
|
53
57
|
const { selectedFeatureId } = displayModel;
|
|
54
58
|
const region = regions[0];
|
|
@@ -64,9 +68,9 @@ const LollipopRendering = observer(function (props) {
|
|
|
64
68
|
const width = (region.end - region.start) / bpPerPx;
|
|
65
69
|
const records = [...layout.getLayout(config).values()];
|
|
66
70
|
const height = layout.getTotalHeight();
|
|
67
|
-
return (_jsx("svg", { width: width, height: height, style: { position: 'relative' }, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseEnter, onBlur: onMouseLeave, onClick: onClick, children: records.map(layoutRecord => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
return (_jsx("svg", { width: width, height: height, style: { position: 'relative' }, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseEnter, onBlur: onMouseLeave, onClick: onClick, children: client ? (_jsx(_Fragment, { children: records.map(layoutRecord => {
|
|
72
|
+
const feature = features.get(layoutRecord.data.featureId);
|
|
73
|
+
return (_jsxs(Fragment, { children: [_jsx(Stick, { ...props, config: config, layoutRecord: layoutRecord, feature: feature }, `stick-${feature.id()}`), _jsx(Lollipop, { ...props, layoutRecord: layoutRecord, feature: feature, selectedFeatureId: selectedFeatureId }, `body-${feature.id()}`)] }, feature.id()));
|
|
74
|
+
}) })) : null }));
|
|
71
75
|
});
|
|
72
76
|
export default LollipopRendering;
|
|
@@ -9,5 +9,9 @@ export default function ScoreText({ feature, config, layoutRecord: { y, data: {
|
|
|
9
9
|
if (fontHeight < 12) {
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
return (_jsx("text", { style: {
|
|
12
|
+
return (_jsx("text", { style: {
|
|
13
|
+
pointerEvents: 'none',
|
|
14
|
+
fontSize: fontHeight,
|
|
15
|
+
fill: contrastingTextColor(innerColor),
|
|
16
|
+
}, x: anchorX, y: y + radiusPx - fontHeight / 2.4, textAnchor: "middle", dominantBaseline: "hanging", children: scoreString }));
|
|
13
17
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { lazy } from 'react';
|
|
2
1
|
import LollipopRenderer from './LollipopRenderer';
|
|
2
|
+
import ReactComponent from './components/LollipopRendering';
|
|
3
3
|
import configSchema from './configSchema';
|
|
4
4
|
export default function LollipopRendererF(pluginManager) {
|
|
5
5
|
pluginManager.addRendererType(() => new LollipopRenderer({
|
|
6
6
|
name: 'LollipopRenderer',
|
|
7
|
-
ReactComponent
|
|
7
|
+
ReactComponent,
|
|
8
8
|
configSchema,
|
|
9
9
|
pluginManager,
|
|
10
10
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-lollipop",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "JBrowse 2 plugin for lollipops",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"clean": "rimraf dist esm *.tsbuildinfo"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@jbrowse/core": "^3.0
|
|
40
|
-
"@jbrowse/plugin-linear-genome-view": "^3.0
|
|
39
|
+
"@jbrowse/core": "^3.1.0",
|
|
40
|
+
"@jbrowse/plugin-linear-genome-view": "^3.1.0",
|
|
41
41
|
"@mui/material": "^6.0.0",
|
|
42
42
|
"mobx": "^6.0.0",
|
|
43
43
|
"mobx-react": "^9.0.0",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "91492049ddea0aed90eb24d3c066c2d9f5a6b189"
|
|
56
56
|
}
|