@jbrowse/plugin-arc 2.9.0 → 2.10.1

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.
@@ -1,14 +1,39 @@
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 (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const react_1 = __importDefault(require("react"));
29
+ const react_1 = __importStar(require("react"));
7
30
  const configuration_1 = require("@jbrowse/core/configuration");
8
31
  const util_1 = require("@jbrowse/core/util");
9
32
  const mobx_react_1 = require("mobx-react");
10
- const react_svg_tooltip_1 = require("react-svg-tooltip");
33
+ // locals
34
+ const ArcTooltip_1 = __importDefault(require("../ArcTooltip"));
11
35
  function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, feature, }) {
36
+ const [isMouseOvered, setIsMouseOvered] = (0, react_1.useState)(false);
12
37
  const [left, right] = (0, util_1.bpSpanPx)(feature.get('start'), feature.get('end'), region, bpPerPx);
13
38
  const featureId = feature.id();
14
39
  let stroke = (0, configuration_1.readConfObject)(config, 'color', { feature });
@@ -21,7 +46,6 @@ function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, featu
21
46
  const strokeWidth = (0, configuration_1.readConfObject)(config, 'thickness', { feature }) || 1;
22
47
  const height = (0, configuration_1.readConfObject)(config, 'height', { feature }) || 100;
23
48
  const ref = react_1.default.createRef();
24
- const tooltipWidth = 20 + (0, util_1.measureText)(caption === null || caption === void 0 ? void 0 : caption.toString());
25
49
  const t = 0.5;
26
50
  // formula: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B%C3%A9zier_curves
27
51
  const textYCoord = (1 - t) * (1 - t) * (1 - t) * 0 +
@@ -29,10 +53,8 @@ function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, featu
29
53
  3 * (1 - t) * (t * t) * height +
30
54
  t * t * t * 0;
31
55
  return (react_1.default.createElement("g", null,
32
- react_1.default.createElement("path", { d: `M ${left} 0 C ${left} ${height}, ${right} ${height}, ${right} 0`, stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), ref: ref, pointerEvents: "stroke" }),
33
- react_1.default.createElement(react_svg_tooltip_1.Tooltip, { triggerRef: ref },
34
- react_1.default.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
35
- react_1.default.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption)),
56
+ react_1.default.createElement("path", { d: `M ${left} 0 C ${left} ${height}, ${right} ${height}, ${right} 0`, stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), onMouseOver: () => setIsMouseOvered(true), onMouseLeave: () => setIsMouseOvered(false), ref: ref, pointerEvents: "stroke" }),
57
+ isMouseOvered ? react_1.default.createElement(ArcTooltip_1.default, { contents: caption }) : null,
36
58
  react_1.default.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: 'white', strokeWidth: '0.6em' } }, label),
37
59
  react_1.default.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: textStroke } }, label)));
38
60
  }
@@ -62,6 +84,7 @@ function describeArc(x, y, radius, startAngle, endAngle) {
62
84
  ].join(' ');
63
85
  }
64
86
  function SemiCircles({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, feature, }) {
87
+ const [isMouseOvered, setIsMouseOvered] = (0, react_1.useState)(false);
65
88
  const [left, right] = (0, util_1.bpSpanPx)(feature.get('start'), feature.get('end'), region, bpPerPx);
66
89
  const featureId = feature.id();
67
90
  let stroke = (0, configuration_1.readConfObject)(config, 'color', { feature });
@@ -73,13 +96,10 @@ function SemiCircles({ selectedFeatureId, region, bpPerPx, config, onFeatureClic
73
96
  const caption = (0, configuration_1.readConfObject)(config, 'caption', { feature });
74
97
  const strokeWidth = (0, configuration_1.readConfObject)(config, 'thickness', { feature }) || 1;
75
98
  const ref = react_1.default.createRef();
76
- const tooltipWidth = 20 + (0, util_1.measureText)(caption === null || caption === void 0 ? void 0 : caption.toString());
77
99
  const textYCoord = (right - left) / 2;
78
100
  return (react_1.default.createElement("g", null,
79
- react_1.default.createElement("path", { d: describeArc(left + (right - left) / 2, 0, (right - left) / 2, 90, 270), stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), ref: ref, pointerEvents: "stroke" }),
80
- react_1.default.createElement(react_svg_tooltip_1.Tooltip, { triggerRef: ref },
81
- react_1.default.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
82
- react_1.default.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption)),
101
+ react_1.default.createElement("path", { d: describeArc(left + (right - left) / 2, 0, (right - left) / 2, 90, 270), stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), onMouseOver: () => setIsMouseOvered(true), onMouseLeave: () => setIsMouseOvered(false), ref: ref, pointerEvents: "stroke" }),
102
+ isMouseOvered ? react_1.default.createElement(ArcTooltip_1.default, { contents: caption }) : null,
83
103
  react_1.default.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: 'white', strokeWidth: '0.6em' } }, label),
84
104
  react_1.default.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: textStroke } }, label)));
85
105
  }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ declare const ArcTooltip: ({ contents }: {
3
+ contents?: string | undefined;
4
+ }) => React.JSX.Element | null;
5
+ export default ArcTooltip;
@@ -0,0 +1,51 @@
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
+ const react_1 = __importDefault(require("react"));
7
+ const ui_1 = require("@jbrowse/core/ui");
8
+ const mobx_react_1 = require("mobx-react");
9
+ const material_1 = require("@mui/material");
10
+ const mui_1 = require("tss-react/mui");
11
+ const react_2 = require("@floating-ui/react");
12
+ function round(value) {
13
+ return Math.round(value * 1e5) / 1e5;
14
+ }
15
+ const useStyles = (0, mui_1.makeStyles)()(theme => ({
16
+ // these styles come from
17
+ // https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Tooltip/Tooltip.js
18
+ tooltip: {
19
+ pointerEvents: 'none',
20
+ backgroundColor: (0, material_1.alpha)(theme.palette.grey[700], 0.9),
21
+ borderRadius: theme.shape.borderRadius,
22
+ color: theme.palette.common.white,
23
+ fontFamily: theme.typography.fontFamily,
24
+ padding: '4px 8px',
25
+ fontSize: theme.typography.pxToRem(12),
26
+ lineHeight: `${round(14 / 10)}em`,
27
+ maxWidth: 300,
28
+ wordWrap: 'break-word',
29
+ },
30
+ }));
31
+ const TooltipContents = react_1.default.forwardRef(function TooltipContents2({ message }, ref) {
32
+ return (react_1.default.createElement("div", { ref: ref }, react_1.default.isValidElement(message) ? (message) : message ? (react_1.default.createElement(ui_1.SanitizedHTML, { html: String(message) })) : null));
33
+ });
34
+ const ArcTooltip = (0, mobx_react_1.observer)(function ({ contents }) {
35
+ var _a, _b;
36
+ const { theme, classes } = useStyles();
37
+ const { refs, floatingStyles, context } = (0, react_2.useFloating)({
38
+ placement: 'right',
39
+ });
40
+ const clientPoint = (0, react_2.useClientPoint)(context);
41
+ const { getFloatingProps } = (0, react_2.useInteractions)([clientPoint]);
42
+ const popperTheme = (_a = theme === null || theme === void 0 ? void 0 : theme.components) === null || _a === void 0 ? void 0 : _a.MuiPopper;
43
+ return contents ? (react_1.default.createElement(material_1.Portal, { container: (_b = popperTheme === null || popperTheme === void 0 ? void 0 : popperTheme.defaultProps) === null || _b === void 0 ? void 0 : _b.container },
44
+ react_1.default.createElement("div", { className: classes.tooltip, ref: refs.setFloating, style: {
45
+ ...floatingStyles,
46
+ zIndex: 100000,
47
+ pointerEvents: 'none',
48
+ }, ...getFloatingProps() },
49
+ react_1.default.createElement(TooltipContents, { message: contents })))) : null;
50
+ });
51
+ exports.default = ArcTooltip;
@@ -2,12 +2,15 @@
2
2
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
3
3
  /**
4
4
  * #stateModel LinearArcDisplay
5
- * extends BaseLinearDisplay
5
+ * extends
6
+ * - [BaseLinearDisplay](../baselineardisplay)
6
7
  */
7
8
  export declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
8
9
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
9
10
  type: import("mobx-state-tree").ISimpleType<string>;
10
- rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
11
+ rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>; /**
12
+ * #property
13
+ */
11
14
  } & {
12
15
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
13
16
  } & {
@@ -63,25 +66,29 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
63
66
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
64
67
  maxFeatureScreenDensity: {
65
68
  type: string;
66
- description: string; /**
69
+ description: string;
70
+ defaultValue: number; /**
67
71
  * #property
68
72
  */
69
- defaultValue: number;
70
- };
73
+ }; /**
74
+ * #property
75
+ */
71
76
  fetchSizeLimit: {
72
77
  type: string;
73
78
  defaultValue: number;
74
- description: string;
79
+ description: string; /**
80
+ * #getter
81
+ */
75
82
  };
76
83
  height: {
77
84
  type: string;
78
- defaultValue: number;
85
+ defaultValue: number; /**
86
+ * #getter
87
+ */
79
88
  description: string;
80
89
  };
81
90
  mouseover: {
82
- type: string; /**
83
- * #getter
84
- */
91
+ type: string;
85
92
  description: string;
86
93
  defaultValue: string;
87
94
  contextVariable: string[];
@@ -106,9 +113,6 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
106
113
  message: string | undefined;
107
114
  } & {
108
115
  readonly RenderingComponent: import("react").FC<{
109
- /**
110
- * #property
111
- */
112
116
  model: {
113
117
  id: string;
114
118
  type: string;
@@ -164,9 +168,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
164
168
  } & {
165
169
  scrollTop: number;
166
170
  } & {
167
- readonly height: number; /**
168
- * #property
169
- */
171
+ readonly height: number;
170
172
  } & {
171
173
  setScrollTop(scrollTop: number): void;
172
174
  setHeight(displayHeight: number): number;
@@ -180,9 +182,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
180
182
  readonly currentFeatureScreenDensity: number;
181
183
  readonly maxFeatureScreenDensity: any;
182
184
  readonly featureDensityStatsReady: boolean;
183
- readonly maxAllowableBytes: number; /**
184
- * #method
185
- */
185
+ readonly maxAllowableBytes: number;
186
186
  } & {
187
187
  afterAttach(): void;
188
188
  } & {
@@ -200,7 +200,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
200
200
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react").JSX.Element | null;
201
201
  } & {
202
202
  featureIdUnderMouse: string | undefined;
203
- contextMenuFeature: import("@jbrowse/core/util").Feature | undefined;
203
+ contextMenuFeature: import("@jbrowse/core/util").Feature | undefined; /**
204
+ * #method
205
+ */
204
206
  } & {
205
207
  readonly blockType: "dynamicBlocks" | "staticBlocks";
206
208
  readonly blockDefinitions: import("@jbrowse/core/util/blockTypes").BlockSet;
@@ -286,7 +288,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
286
288
  } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
287
289
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
288
290
  type: import("mobx-state-tree").ISimpleType<string>;
289
- rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
291
+ rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>; /**
292
+ * #property
293
+ */
290
294
  } & {
291
295
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
292
296
  } & {
@@ -342,33 +346,37 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
342
346
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
343
347
  maxFeatureScreenDensity: {
344
348
  type: string;
345
- description: string; /**
349
+ description: string;
350
+ defaultValue: number; /**
346
351
  * #property
347
352
  */
348
- defaultValue: number;
349
- };
353
+ }; /**
354
+ * #property
355
+ */
350
356
  fetchSizeLimit: {
351
357
  type: string;
352
358
  defaultValue: number;
353
- description: string;
359
+ description: string; /**
360
+ * #getter
361
+ */
354
362
  };
355
363
  height: {
356
364
  type: string;
357
- defaultValue: number;
365
+ defaultValue: number; /**
366
+ * #getter
367
+ */
358
368
  description: string;
359
369
  };
360
370
  mouseover: {
361
- type: string; /**
362
- * #getter
363
- */
371
+ type: string;
364
372
  description: string;
365
373
  defaultValue: string;
366
374
  contextVariable: string[];
367
375
  };
368
376
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
369
377
  }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
370
- type: string;
371
378
  id: string;
379
+ type: string;
372
380
  configuration: import("mobx-state-tree").ModelSnapshotType<Record<string, any>>;
373
381
  rpcDriverName: string | undefined;
374
382
  heightPreConfig: number | undefined;
@@ -7,7 +7,8 @@ const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view"
7
7
  const util_1 = require("@jbrowse/core/util");
8
8
  /**
9
9
  * #stateModel LinearArcDisplay
10
- * extends BaseLinearDisplay
10
+ * extends
11
+ * - [BaseLinearDisplay](../baselineardisplay)
11
12
  */
12
13
  function stateModelFactory(configSchema) {
13
14
  return mobx_state_tree_1.types
@@ -22,79 +22,21 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  const react_1 = __importStar(require("react"));
27
30
  const mobx_react_1 = require("mobx-react");
28
31
  const util_1 = require("@jbrowse/core/util");
29
32
  const configuration_1 = require("@jbrowse/core/configuration");
30
- const vcf_1 = require("@gmod/vcf");
31
- const react_svg_tooltip_1 = require("react-svg-tooltip");
32
- function f(feature, alt) {
33
- var _a, _b, _c, _d, _e;
34
- const bnd = alt ? (0, vcf_1.parseBreakend)(alt) : undefined;
35
- let start = feature.get('start');
36
- let end = feature.get('end');
37
- const strand = feature.get('strand');
38
- const mate = feature.get('mate');
39
- const refName = feature.get('refName');
40
- let mateRefName;
41
- let mateEnd = 0;
42
- let mateStart = 0;
43
- // one sided bracket used, because there could be <INS:ME> and we just check
44
- // startswith below
45
- const symbolicAlleles = ['<TRA', '<DEL', '<INV', '<INS', '<DUP', '<CNV'];
46
- if (symbolicAlleles.some(a => alt === null || alt === void 0 ? void 0 : alt.startsWith(a))) {
47
- // END is defined to be a single value, not an array. CHR2 not defined in
48
- // VCF spec, but should be similar
49
- const e = ((_b = (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.END) === null || _b === void 0 ? void 0 : _b[0]) || feature.get('end');
50
- mateEnd = e;
51
- mateStart = e - 1;
52
- mateRefName = (_e = (_d = (_c = feature.get('INFO')) === null || _c === void 0 ? void 0 : _c.CHR2) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : refName;
53
- // re-adjust the arc to be from start to end of feature by re-assigning end
54
- // to the 'mate'
55
- start = feature.get('start');
56
- end = feature.get('start') + 1;
57
- }
58
- else if (bnd === null || bnd === void 0 ? void 0 : bnd.MatePosition) {
59
- const matePosition = bnd.MatePosition.split(':');
60
- mateEnd = +matePosition[1];
61
- mateStart = +matePosition[1] - 1;
62
- mateRefName = matePosition[0];
63
- }
64
- return {
65
- k1: { refName, start, end, strand },
66
- k2: mate !== null && mate !== void 0 ? mate : { refName: mateRefName, end: mateEnd, start: mateStart },
67
- };
68
- }
69
- function makeSummary(feature, alt) {
70
- var _a;
71
- const { k1, k2 } = f(feature, alt);
72
- return [
73
- feature.get('name'),
74
- feature.get('id'),
75
- (0, util_1.assembleLocString)(k1),
76
- (0, util_1.assembleLocString)(k2),
77
- (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.SVTYPE,
78
- alt,
79
- ]
80
- .filter(f => !!f)
81
- .join(' - ');
82
- }
83
- // conditionally rendered tooltip only on mouseover, speeds up
84
- const SvgTooltip = react_1.default.forwardRef(function SvgTooltip2({ feature, alt }, ref) {
85
- const caption = makeSummary(feature, alt);
86
- const tooltipWidth = 20 + (0, util_1.measureText)(caption);
87
- return ref !== null ? (
88
- // @ts-expect-error
89
- react_1.default.createElement(react_svg_tooltip_1.Tooltip, { triggerRef: ref },
90
- react_1.default.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
91
- react_1.default.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption))) : null;
92
- });
33
+ const ArcTooltip_1 = __importDefault(require("../../ArcTooltip"));
34
+ const util_2 = require("./util");
93
35
  const Arc = (0, mobx_react_1.observer)(function ({ model, feature, alt, assembly, view, }) {
94
36
  var _a, _b;
95
37
  const [mouseOvered, setMouseOvered] = (0, react_1.useState)(false);
96
38
  const { height } = model;
97
- const { k1, k2 } = f(feature, alt);
39
+ const { k1, k2 } = (0, util_2.makeFeaturePair)(feature, alt);
98
40
  const ref = (0, react_1.useRef)(null);
99
41
  const c = (0, configuration_1.getConf)(model, 'color', { feature, alt });
100
42
  const ra1 = assembly.getCanonicalRefName(k1.refName) || k1.refName;
@@ -111,9 +53,13 @@ const Arc = (0, mobx_react_1.observer)(function ({ model, feature, alt, assembly
111
53
  const p2 = r2 - view.offsetPx;
112
54
  const left = p1;
113
55
  const right = p2;
56
+ const col = mouseOvered ? 'black' : c;
57
+ const sw = 3;
114
58
  return absrad > 1 ? (react_1.default.createElement(react_1.default.Fragment, null,
115
- react_1.default.createElement("path", { d: `M ${left} 0 C ${left} ${destY}, ${right} ${destY}, ${right} 0`, ref: ref, stroke: mouseOvered ? 'black' : c, strokeWidth: 3, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), fill: "none", pointerEvents: "stroke" }),
116
- mouseOvered ? (react_1.default.createElement(SvgTooltip, { feature: feature, alt: alt, ref: ref })) : null)) : null;
59
+ react_1.default.createElement("path", { d: `M ${left} 0 C ${left} ${destY}, ${right} ${destY}, ${right} 0`, ref: ref, stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), fill: "none", pointerEvents: "stroke" }),
60
+ k1.mateDirection !== undefined ? (react_1.default.createElement("line", { stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), x1: left, x2: left + k1.mateDirection * 20, y1: 1.5, y2: 1.5 })) : null,
61
+ k2.mateDirection !== undefined ? (react_1.default.createElement("line", { stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), x1: right, x2: right + k2.mateDirection * 20, y1: 1.5, y2: 1.5 })) : null,
62
+ mouseOvered ? (react_1.default.createElement(ArcTooltip_1.default, { contents: (0, util_2.makeSummary)(feature, alt) })) : null)) : null;
117
63
  }
118
64
  return null;
119
65
  });
@@ -0,0 +1,17 @@
1
+ import { Feature } from '@jbrowse/core/util';
2
+ export declare function makeFeaturePair(feature: Feature, alt?: string): {
3
+ k1: {
4
+ refName: string;
5
+ start: number;
6
+ end: number;
7
+ strand: any;
8
+ mateDirection: number;
9
+ };
10
+ k2: {
11
+ refName: string;
12
+ start: number;
13
+ end: number;
14
+ mateDirection?: number | undefined;
15
+ };
16
+ };
17
+ export declare function makeSummary(feature: Feature, alt?: string): string;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeSummary = exports.makeFeaturePair = void 0;
4
+ const vcf_1 = require("@gmod/vcf");
5
+ const util_1 = require("@jbrowse/core/util");
6
+ function makeFeaturePair(feature, alt) {
7
+ var _a, _b, _c, _d;
8
+ const bnd = alt ? (0, vcf_1.parseBreakend)(alt) : undefined;
9
+ let start = feature.get('start');
10
+ let end = feature.get('end');
11
+ const strand = feature.get('strand');
12
+ const mate = feature.get('mate');
13
+ const refName = feature.get('refName');
14
+ let mateRefName;
15
+ let mateEnd = 0;
16
+ let mateStart = 0;
17
+ let joinDirection = 0;
18
+ let mateDirection = 0;
19
+ // one sided bracket used, because there could be <INS:ME> and we just check
20
+ // startswith below
21
+ const symbolicAlleles = ['<TRA', '<DEL', '<INV', '<INS', '<DUP', '<CNV'];
22
+ if (symbolicAlleles.some(a => alt === null || alt === void 0 ? void 0 : alt.startsWith(a))) {
23
+ // END is defined to be a single value, not an array. CHR2 not defined in
24
+ // VCF spec, but should be similar
25
+ const info = feature.get('INFO');
26
+ const e = (_b = (_a = info === null || info === void 0 ? void 0 : info.END) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : end;
27
+ mateRefName = (_d = (_c = info === null || info === void 0 ? void 0 : info.CHR2) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : refName;
28
+ mateEnd = e;
29
+ mateStart = e - 1;
30
+ // re-adjust the arc to be from start to end of feature by re-assigning end
31
+ // to the 'mate'
32
+ start = start;
33
+ end = start + 1;
34
+ }
35
+ else if (bnd === null || bnd === void 0 ? void 0 : bnd.MatePosition) {
36
+ const matePosition = bnd.MatePosition.split(':');
37
+ mateDirection = bnd.MateDirection === 'left' ? 1 : -1;
38
+ joinDirection = bnd.Join === 'left' ? -1 : 1;
39
+ mateEnd = +matePosition[1];
40
+ mateStart = +matePosition[1] - 1;
41
+ mateRefName = matePosition[0];
42
+ }
43
+ return {
44
+ k1: {
45
+ refName,
46
+ start,
47
+ end,
48
+ strand,
49
+ mateDirection,
50
+ },
51
+ k2: mate !== null && mate !== void 0 ? mate : {
52
+ refName: mateRefName,
53
+ end: mateEnd,
54
+ start: mateStart,
55
+ mateDirection: joinDirection,
56
+ },
57
+ };
58
+ }
59
+ exports.makeFeaturePair = makeFeaturePair;
60
+ function makeSummary(feature, alt) {
61
+ var _a;
62
+ const { k1, k2 } = makeFeaturePair(feature, alt);
63
+ return [
64
+ feature.get('name'),
65
+ feature.get('id'),
66
+ (0, util_1.assembleLocString)(k1),
67
+ (0, util_1.assembleLocString)(k2),
68
+ (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.SVTYPE,
69
+ alt,
70
+ ]
71
+ .filter(f => !!f)
72
+ .join(' - ');
73
+ }
74
+ exports.makeSummary = makeSummary;
@@ -4,7 +4,13 @@ import { Instance } from 'mobx-state-tree';
4
4
  import { Feature } from '@jbrowse/core/util';
5
5
  /**
6
6
  * #stateModel LinearPairedArcDisplay
7
- * extends BaseDisplay, TrackHeightMixin, FeatureDensityMixin
7
+ * this is a non-block-based track type, and can connect arcs across multiple
8
+ * displayedRegions
9
+ *
10
+ * extends
11
+ * - [BaseDisplay](../basedisplay)
12
+ * - [TrackHeightMixin](../trackheightmixin)
13
+ * - [FeatureDensityMixin](../featuredensitymixin)
8
14
  */
9
15
  export declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
10
16
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
@@ -14,7 +20,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
14
20
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
15
21
  } & {
16
22
  userBpPerPxLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
17
- userByteSizeLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
23
+ userByteSizeLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>; /**
24
+ * #property
25
+ */
18
26
  } & {
19
27
  /**
20
28
  * #property
@@ -92,13 +100,13 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
92
100
  readonly height: number;
93
101
  } & {
94
102
  setScrollTop(scrollTop: number): void;
95
- setHeight(displayHeight: number): number; /**
96
- * #property
97
- */
103
+ setHeight(displayHeight: number): number;
98
104
  resizeHeight(distance: number): number;
99
105
  } & {
100
106
  featureDensityStatsP: Promise<import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats> | undefined;
101
- featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined;
107
+ featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined; /**
108
+ * #property
109
+ */
102
110
  currStatsBpPerPx: number;
103
111
  } & {
104
112
  readonly currentBytesRequested: number;
@@ -31,7 +31,13 @@ const pluggableElementTypes_1 = require("@jbrowse/core/pluggableElementTypes");
31
31
  const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
32
32
  /**
33
33
  * #stateModel LinearPairedArcDisplay
34
- * extends BaseDisplay, TrackHeightMixin, FeatureDensityMixin
34
+ * this is a non-block-based track type, and can connect arcs across multiple
35
+ * displayedRegions
36
+ *
37
+ * extends
38
+ * - [BaseDisplay](../basedisplay)
39
+ * - [TrackHeightMixin](../trackheightmixin)
40
+ * - [FeatureDensityMixin](../featuredensitymixin)
35
41
  */
36
42
  function stateModelFactory(configSchema) {
37
43
  return mobx_state_tree_1.types
@@ -1,9 +1,11 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { readConfObject, } from '@jbrowse/core/configuration';
3
- import { bpSpanPx, measureText } from '@jbrowse/core/util';
3
+ import { bpSpanPx } from '@jbrowse/core/util';
4
4
  import { observer } from 'mobx-react';
5
- import { Tooltip } from 'react-svg-tooltip';
5
+ // locals
6
+ import ArcTooltip from '../ArcTooltip';
6
7
  function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, feature, }) {
8
+ const [isMouseOvered, setIsMouseOvered] = useState(false);
7
9
  const [left, right] = bpSpanPx(feature.get('start'), feature.get('end'), region, bpPerPx);
8
10
  const featureId = feature.id();
9
11
  let stroke = readConfObject(config, 'color', { feature });
@@ -16,7 +18,6 @@ function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, featu
16
18
  const strokeWidth = readConfObject(config, 'thickness', { feature }) || 1;
17
19
  const height = readConfObject(config, 'height', { feature }) || 100;
18
20
  const ref = React.createRef();
19
- const tooltipWidth = 20 + measureText(caption === null || caption === void 0 ? void 0 : caption.toString());
20
21
  const t = 0.5;
21
22
  // formula: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B%C3%A9zier_curves
22
23
  const textYCoord = (1 - t) * (1 - t) * (1 - t) * 0 +
@@ -24,10 +25,8 @@ function Arc({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, featu
24
25
  3 * (1 - t) * (t * t) * height +
25
26
  t * t * t * 0;
26
27
  return (React.createElement("g", null,
27
- React.createElement("path", { d: `M ${left} 0 C ${left} ${height}, ${right} ${height}, ${right} 0`, stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), ref: ref, pointerEvents: "stroke" }),
28
- React.createElement(Tooltip, { triggerRef: ref },
29
- React.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
30
- React.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption)),
28
+ React.createElement("path", { d: `M ${left} 0 C ${left} ${height}, ${right} ${height}, ${right} 0`, stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), onMouseOver: () => setIsMouseOvered(true), onMouseLeave: () => setIsMouseOvered(false), ref: ref, pointerEvents: "stroke" }),
29
+ isMouseOvered ? React.createElement(ArcTooltip, { contents: caption }) : null,
31
30
  React.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: 'white', strokeWidth: '0.6em' } }, label),
32
31
  React.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: textStroke } }, label)));
33
32
  }
@@ -57,6 +56,7 @@ function describeArc(x, y, radius, startAngle, endAngle) {
57
56
  ].join(' ');
58
57
  }
59
58
  function SemiCircles({ selectedFeatureId, region, bpPerPx, config, onFeatureClick, feature, }) {
59
+ const [isMouseOvered, setIsMouseOvered] = useState(false);
60
60
  const [left, right] = bpSpanPx(feature.get('start'), feature.get('end'), region, bpPerPx);
61
61
  const featureId = feature.id();
62
62
  let stroke = readConfObject(config, 'color', { feature });
@@ -68,13 +68,10 @@ function SemiCircles({ selectedFeatureId, region, bpPerPx, config, onFeatureClic
68
68
  const caption = readConfObject(config, 'caption', { feature });
69
69
  const strokeWidth = readConfObject(config, 'thickness', { feature }) || 1;
70
70
  const ref = React.createRef();
71
- const tooltipWidth = 20 + measureText(caption === null || caption === void 0 ? void 0 : caption.toString());
72
71
  const textYCoord = (right - left) / 2;
73
72
  return (React.createElement("g", null,
74
- React.createElement("path", { d: describeArc(left + (right - left) / 2, 0, (right - left) / 2, 90, 270), stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), ref: ref, pointerEvents: "stroke" }),
75
- React.createElement(Tooltip, { triggerRef: ref },
76
- React.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
77
- React.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption)),
73
+ React.createElement("path", { d: describeArc(left + (right - left) / 2, 0, (right - left) / 2, 90, 270), stroke: stroke, strokeWidth: strokeWidth, fill: "transparent", onClick: e => onFeatureClick === null || onFeatureClick === void 0 ? void 0 : onFeatureClick(e, featureId), onMouseOver: () => setIsMouseOvered(true), onMouseLeave: () => setIsMouseOvered(false), ref: ref, pointerEvents: "stroke" }),
74
+ isMouseOvered ? React.createElement(ArcTooltip, { contents: caption }) : null,
78
75
  React.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: 'white', strokeWidth: '0.6em' } }, label),
79
76
  React.createElement("text", { x: left + (right - left) / 2, y: textYCoord + 3, style: { stroke: textStroke } }, label)));
80
77
  }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ declare const ArcTooltip: ({ contents }: {
3
+ contents?: string | undefined;
4
+ }) => React.JSX.Element | null;
5
+ export default ArcTooltip;
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { SanitizedHTML } from '@jbrowse/core/ui';
3
+ import { observer } from 'mobx-react';
4
+ import { Portal, alpha } from '@mui/material';
5
+ import { makeStyles } from 'tss-react/mui';
6
+ import { useClientPoint, useFloating, useInteractions, } from '@floating-ui/react';
7
+ function round(value) {
8
+ return Math.round(value * 1e5) / 1e5;
9
+ }
10
+ const useStyles = makeStyles()(theme => ({
11
+ // these styles come from
12
+ // https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Tooltip/Tooltip.js
13
+ tooltip: {
14
+ pointerEvents: 'none',
15
+ backgroundColor: alpha(theme.palette.grey[700], 0.9),
16
+ borderRadius: theme.shape.borderRadius,
17
+ color: theme.palette.common.white,
18
+ fontFamily: theme.typography.fontFamily,
19
+ padding: '4px 8px',
20
+ fontSize: theme.typography.pxToRem(12),
21
+ lineHeight: `${round(14 / 10)}em`,
22
+ maxWidth: 300,
23
+ wordWrap: 'break-word',
24
+ },
25
+ }));
26
+ const TooltipContents = React.forwardRef(function TooltipContents2({ message }, ref) {
27
+ return (React.createElement("div", { ref: ref }, React.isValidElement(message) ? (message) : message ? (React.createElement(SanitizedHTML, { html: String(message) })) : null));
28
+ });
29
+ const ArcTooltip = observer(function ({ contents }) {
30
+ var _a, _b;
31
+ const { theme, classes } = useStyles();
32
+ const { refs, floatingStyles, context } = useFloating({
33
+ placement: 'right',
34
+ });
35
+ const clientPoint = useClientPoint(context);
36
+ const { getFloatingProps } = useInteractions([clientPoint]);
37
+ const popperTheme = (_a = theme === null || theme === void 0 ? void 0 : theme.components) === null || _a === void 0 ? void 0 : _a.MuiPopper;
38
+ return contents ? (React.createElement(Portal, { container: (_b = popperTheme === null || popperTheme === void 0 ? void 0 : popperTheme.defaultProps) === null || _b === void 0 ? void 0 : _b.container },
39
+ React.createElement("div", { className: classes.tooltip, ref: refs.setFloating, style: {
40
+ ...floatingStyles,
41
+ zIndex: 100000,
42
+ pointerEvents: 'none',
43
+ }, ...getFloatingProps() },
44
+ React.createElement(TooltipContents, { message: contents })))) : null;
45
+ });
46
+ export default ArcTooltip;
@@ -2,12 +2,15 @@
2
2
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
3
3
  /**
4
4
  * #stateModel LinearArcDisplay
5
- * extends BaseLinearDisplay
5
+ * extends
6
+ * - [BaseLinearDisplay](../baselineardisplay)
6
7
  */
7
8
  export declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
8
9
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
9
10
  type: import("mobx-state-tree").ISimpleType<string>;
10
- rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
11
+ rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>; /**
12
+ * #property
13
+ */
11
14
  } & {
12
15
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
13
16
  } & {
@@ -63,25 +66,29 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
63
66
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
64
67
  maxFeatureScreenDensity: {
65
68
  type: string;
66
- description: string; /**
69
+ description: string;
70
+ defaultValue: number; /**
67
71
  * #property
68
72
  */
69
- defaultValue: number;
70
- };
73
+ }; /**
74
+ * #property
75
+ */
71
76
  fetchSizeLimit: {
72
77
  type: string;
73
78
  defaultValue: number;
74
- description: string;
79
+ description: string; /**
80
+ * #getter
81
+ */
75
82
  };
76
83
  height: {
77
84
  type: string;
78
- defaultValue: number;
85
+ defaultValue: number; /**
86
+ * #getter
87
+ */
79
88
  description: string;
80
89
  };
81
90
  mouseover: {
82
- type: string; /**
83
- * #getter
84
- */
91
+ type: string;
85
92
  description: string;
86
93
  defaultValue: string;
87
94
  contextVariable: string[];
@@ -106,9 +113,6 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
106
113
  message: string | undefined;
107
114
  } & {
108
115
  readonly RenderingComponent: import("react").FC<{
109
- /**
110
- * #property
111
- */
112
116
  model: {
113
117
  id: string;
114
118
  type: string;
@@ -164,9 +168,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
164
168
  } & {
165
169
  scrollTop: number;
166
170
  } & {
167
- readonly height: number; /**
168
- * #property
169
- */
171
+ readonly height: number;
170
172
  } & {
171
173
  setScrollTop(scrollTop: number): void;
172
174
  setHeight(displayHeight: number): number;
@@ -180,9 +182,7 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
180
182
  readonly currentFeatureScreenDensity: number;
181
183
  readonly maxFeatureScreenDensity: any;
182
184
  readonly featureDensityStatsReady: boolean;
183
- readonly maxAllowableBytes: number; /**
184
- * #method
185
- */
185
+ readonly maxAllowableBytes: number;
186
186
  } & {
187
187
  afterAttach(): void;
188
188
  } & {
@@ -200,7 +200,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
200
200
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react").JSX.Element | null;
201
201
  } & {
202
202
  featureIdUnderMouse: string | undefined;
203
- contextMenuFeature: import("@jbrowse/core/util").Feature | undefined;
203
+ contextMenuFeature: import("@jbrowse/core/util").Feature | undefined; /**
204
+ * #method
205
+ */
204
206
  } & {
205
207
  readonly blockType: "dynamicBlocks" | "staticBlocks";
206
208
  readonly blockDefinitions: import("@jbrowse/core/util/blockTypes").BlockSet;
@@ -286,7 +288,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
286
288
  } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
287
289
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
288
290
  type: import("mobx-state-tree").ISimpleType<string>;
289
- rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
291
+ rpcDriverName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>; /**
292
+ * #property
293
+ */
290
294
  } & {
291
295
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
292
296
  } & {
@@ -342,33 +346,37 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
342
346
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
343
347
  maxFeatureScreenDensity: {
344
348
  type: string;
345
- description: string; /**
349
+ description: string;
350
+ defaultValue: number; /**
346
351
  * #property
347
352
  */
348
- defaultValue: number;
349
- };
353
+ }; /**
354
+ * #property
355
+ */
350
356
  fetchSizeLimit: {
351
357
  type: string;
352
358
  defaultValue: number;
353
- description: string;
359
+ description: string; /**
360
+ * #getter
361
+ */
354
362
  };
355
363
  height: {
356
364
  type: string;
357
- defaultValue: number;
365
+ defaultValue: number; /**
366
+ * #getter
367
+ */
358
368
  description: string;
359
369
  };
360
370
  mouseover: {
361
- type: string; /**
362
- * #getter
363
- */
371
+ type: string;
364
372
  description: string;
365
373
  defaultValue: string;
366
374
  contextVariable: string[];
367
375
  };
368
376
  }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>;
369
377
  }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
370
- type: string;
371
378
  id: string;
379
+ type: string;
372
380
  configuration: import("mobx-state-tree").ModelSnapshotType<Record<string, any>>;
373
381
  rpcDriverName: string | undefined;
374
382
  heightPreConfig: number | undefined;
@@ -4,7 +4,8 @@ import { BaseLinearDisplay } from '@jbrowse/plugin-linear-genome-view';
4
4
  import { getEnv } from '@jbrowse/core/util';
5
5
  /**
6
6
  * #stateModel LinearArcDisplay
7
- * extends BaseLinearDisplay
7
+ * extends
8
+ * - [BaseLinearDisplay](../baselineardisplay)
8
9
  */
9
10
  export function stateModelFactory(configSchema) {
10
11
  return types
@@ -1,75 +1,14 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import { observer } from 'mobx-react';
3
- import { assembleLocString, getContainingView, getSession, measureText, } from '@jbrowse/core/util';
3
+ import { getContainingView, getSession, } from '@jbrowse/core/util';
4
4
  import { getConf } from '@jbrowse/core/configuration';
5
- import { parseBreakend } from '@gmod/vcf';
6
- import { Tooltip } from 'react-svg-tooltip';
7
- function f(feature, alt) {
8
- var _a, _b, _c, _d, _e;
9
- const bnd = alt ? parseBreakend(alt) : undefined;
10
- let start = feature.get('start');
11
- let end = feature.get('end');
12
- const strand = feature.get('strand');
13
- const mate = feature.get('mate');
14
- const refName = feature.get('refName');
15
- let mateRefName;
16
- let mateEnd = 0;
17
- let mateStart = 0;
18
- // one sided bracket used, because there could be <INS:ME> and we just check
19
- // startswith below
20
- const symbolicAlleles = ['<TRA', '<DEL', '<INV', '<INS', '<DUP', '<CNV'];
21
- if (symbolicAlleles.some(a => alt === null || alt === void 0 ? void 0 : alt.startsWith(a))) {
22
- // END is defined to be a single value, not an array. CHR2 not defined in
23
- // VCF spec, but should be similar
24
- const e = ((_b = (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.END) === null || _b === void 0 ? void 0 : _b[0]) || feature.get('end');
25
- mateEnd = e;
26
- mateStart = e - 1;
27
- mateRefName = (_e = (_d = (_c = feature.get('INFO')) === null || _c === void 0 ? void 0 : _c.CHR2) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : refName;
28
- // re-adjust the arc to be from start to end of feature by re-assigning end
29
- // to the 'mate'
30
- start = feature.get('start');
31
- end = feature.get('start') + 1;
32
- }
33
- else if (bnd === null || bnd === void 0 ? void 0 : bnd.MatePosition) {
34
- const matePosition = bnd.MatePosition.split(':');
35
- mateEnd = +matePosition[1];
36
- mateStart = +matePosition[1] - 1;
37
- mateRefName = matePosition[0];
38
- }
39
- return {
40
- k1: { refName, start, end, strand },
41
- k2: mate !== null && mate !== void 0 ? mate : { refName: mateRefName, end: mateEnd, start: mateStart },
42
- };
43
- }
44
- function makeSummary(feature, alt) {
45
- var _a;
46
- const { k1, k2 } = f(feature, alt);
47
- return [
48
- feature.get('name'),
49
- feature.get('id'),
50
- assembleLocString(k1),
51
- assembleLocString(k2),
52
- (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.SVTYPE,
53
- alt,
54
- ]
55
- .filter(f => !!f)
56
- .join(' - ');
57
- }
58
- // conditionally rendered tooltip only on mouseover, speeds up
59
- const SvgTooltip = React.forwardRef(function SvgTooltip2({ feature, alt }, ref) {
60
- const caption = makeSummary(feature, alt);
61
- const tooltipWidth = 20 + measureText(caption);
62
- return ref !== null ? (
63
- // @ts-expect-error
64
- React.createElement(Tooltip, { triggerRef: ref },
65
- React.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
66
- React.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption))) : null;
67
- });
5
+ import ArcTooltip from '../../ArcTooltip';
6
+ import { makeFeaturePair, makeSummary } from './util';
68
7
  const Arc = observer(function ({ model, feature, alt, assembly, view, }) {
69
8
  var _a, _b;
70
9
  const [mouseOvered, setMouseOvered] = useState(false);
71
10
  const { height } = model;
72
- const { k1, k2 } = f(feature, alt);
11
+ const { k1, k2 } = makeFeaturePair(feature, alt);
73
12
  const ref = useRef(null);
74
13
  const c = getConf(model, 'color', { feature, alt });
75
14
  const ra1 = assembly.getCanonicalRefName(k1.refName) || k1.refName;
@@ -86,9 +25,13 @@ const Arc = observer(function ({ model, feature, alt, assembly, view, }) {
86
25
  const p2 = r2 - view.offsetPx;
87
26
  const left = p1;
88
27
  const right = p2;
28
+ const col = mouseOvered ? 'black' : c;
29
+ const sw = 3;
89
30
  return absrad > 1 ? (React.createElement(React.Fragment, null,
90
- React.createElement("path", { d: `M ${left} 0 C ${left} ${destY}, ${right} ${destY}, ${right} 0`, ref: ref, stroke: mouseOvered ? 'black' : c, strokeWidth: 3, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), fill: "none", pointerEvents: "stroke" }),
91
- mouseOvered ? (React.createElement(SvgTooltip, { feature: feature, alt: alt, ref: ref })) : null)) : null;
31
+ React.createElement("path", { d: `M ${left} 0 C ${left} ${destY}, ${right} ${destY}, ${right} 0`, ref: ref, stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), fill: "none", pointerEvents: "stroke" }),
32
+ k1.mateDirection !== undefined ? (React.createElement("line", { stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), x1: left, x2: left + k1.mateDirection * 20, y1: 1.5, y2: 1.5 })) : null,
33
+ k2.mateDirection !== undefined ? (React.createElement("line", { stroke: col, strokeWidth: sw, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), x1: right, x2: right + k2.mateDirection * 20, y1: 1.5, y2: 1.5 })) : null,
34
+ mouseOvered ? (React.createElement(ArcTooltip, { contents: makeSummary(feature, alt) })) : null)) : null;
92
35
  }
93
36
  return null;
94
37
  });
@@ -0,0 +1,17 @@
1
+ import { Feature } from '@jbrowse/core/util';
2
+ export declare function makeFeaturePair(feature: Feature, alt?: string): {
3
+ k1: {
4
+ refName: string;
5
+ start: number;
6
+ end: number;
7
+ strand: any;
8
+ mateDirection: number;
9
+ };
10
+ k2: {
11
+ refName: string;
12
+ start: number;
13
+ end: number;
14
+ mateDirection?: number | undefined;
15
+ };
16
+ };
17
+ export declare function makeSummary(feature: Feature, alt?: string): string;
@@ -0,0 +1,69 @@
1
+ import { parseBreakend } from '@gmod/vcf';
2
+ import { assembleLocString } from '@jbrowse/core/util';
3
+ export function makeFeaturePair(feature, alt) {
4
+ var _a, _b, _c, _d;
5
+ const bnd = alt ? parseBreakend(alt) : undefined;
6
+ let start = feature.get('start');
7
+ let end = feature.get('end');
8
+ const strand = feature.get('strand');
9
+ const mate = feature.get('mate');
10
+ const refName = feature.get('refName');
11
+ let mateRefName;
12
+ let mateEnd = 0;
13
+ let mateStart = 0;
14
+ let joinDirection = 0;
15
+ let mateDirection = 0;
16
+ // one sided bracket used, because there could be <INS:ME> and we just check
17
+ // startswith below
18
+ const symbolicAlleles = ['<TRA', '<DEL', '<INV', '<INS', '<DUP', '<CNV'];
19
+ if (symbolicAlleles.some(a => alt === null || alt === void 0 ? void 0 : alt.startsWith(a))) {
20
+ // END is defined to be a single value, not an array. CHR2 not defined in
21
+ // VCF spec, but should be similar
22
+ const info = feature.get('INFO');
23
+ const e = (_b = (_a = info === null || info === void 0 ? void 0 : info.END) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : end;
24
+ mateRefName = (_d = (_c = info === null || info === void 0 ? void 0 : info.CHR2) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : refName;
25
+ mateEnd = e;
26
+ mateStart = e - 1;
27
+ // re-adjust the arc to be from start to end of feature by re-assigning end
28
+ // to the 'mate'
29
+ start = start;
30
+ end = start + 1;
31
+ }
32
+ else if (bnd === null || bnd === void 0 ? void 0 : bnd.MatePosition) {
33
+ const matePosition = bnd.MatePosition.split(':');
34
+ mateDirection = bnd.MateDirection === 'left' ? 1 : -1;
35
+ joinDirection = bnd.Join === 'left' ? -1 : 1;
36
+ mateEnd = +matePosition[1];
37
+ mateStart = +matePosition[1] - 1;
38
+ mateRefName = matePosition[0];
39
+ }
40
+ return {
41
+ k1: {
42
+ refName,
43
+ start,
44
+ end,
45
+ strand,
46
+ mateDirection,
47
+ },
48
+ k2: mate !== null && mate !== void 0 ? mate : {
49
+ refName: mateRefName,
50
+ end: mateEnd,
51
+ start: mateStart,
52
+ mateDirection: joinDirection,
53
+ },
54
+ };
55
+ }
56
+ export function makeSummary(feature, alt) {
57
+ var _a;
58
+ const { k1, k2 } = makeFeaturePair(feature, alt);
59
+ return [
60
+ feature.get('name'),
61
+ feature.get('id'),
62
+ assembleLocString(k1),
63
+ assembleLocString(k2),
64
+ (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.SVTYPE,
65
+ alt,
66
+ ]
67
+ .filter(f => !!f)
68
+ .join(' - ');
69
+ }
@@ -4,7 +4,13 @@ import { Instance } from 'mobx-state-tree';
4
4
  import { Feature } from '@jbrowse/core/util';
5
5
  /**
6
6
  * #stateModel LinearPairedArcDisplay
7
- * extends BaseDisplay, TrackHeightMixin, FeatureDensityMixin
7
+ * this is a non-block-based track type, and can connect arcs across multiple
8
+ * displayedRegions
9
+ *
10
+ * extends
11
+ * - [BaseDisplay](../basedisplay)
12
+ * - [TrackHeightMixin](../trackheightmixin)
13
+ * - [FeatureDensityMixin](../featuredensitymixin)
8
14
  */
9
15
  export declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): import("mobx-state-tree").IModelType<{
10
16
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
@@ -14,7 +20,9 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
14
20
  heightPreConfig: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
15
21
  } & {
16
22
  userBpPerPxLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
17
- userByteSizeLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
23
+ userByteSizeLimit: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>; /**
24
+ * #property
25
+ */
18
26
  } & {
19
27
  /**
20
28
  * #property
@@ -92,13 +100,13 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
92
100
  readonly height: number;
93
101
  } & {
94
102
  setScrollTop(scrollTop: number): void;
95
- setHeight(displayHeight: number): number; /**
96
- * #property
97
- */
103
+ setHeight(displayHeight: number): number;
98
104
  resizeHeight(distance: number): number;
99
105
  } & {
100
106
  featureDensityStatsP: Promise<import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats> | undefined;
101
- featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined;
107
+ featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined; /**
108
+ * #property
109
+ */
102
110
  currStatsBpPerPx: number;
103
111
  } & {
104
112
  readonly currentBytesRequested: number;
@@ -5,7 +5,13 @@ import { BaseDisplay } from '@jbrowse/core/pluggableElementTypes';
5
5
  import { FeatureDensityMixin, TrackHeightMixin, } from '@jbrowse/plugin-linear-genome-view';
6
6
  /**
7
7
  * #stateModel LinearPairedArcDisplay
8
- * extends BaseDisplay, TrackHeightMixin, FeatureDensityMixin
8
+ * this is a non-block-based track type, and can connect arcs across multiple
9
+ * displayedRegions
10
+ *
11
+ * extends
12
+ * - [BaseDisplay](../basedisplay)
13
+ * - [TrackHeightMixin](../trackheightmixin)
14
+ * - [FeatureDensityMixin](../featuredensitymixin)
9
15
  */
10
16
  export function stateModelFactory(configSchema) {
11
17
  return types
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-arc",
3
- "version": "2.9.0",
3
+ "version": "2.10.1",
4
4
  "description": "JBrowse 2 arc adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -35,9 +35,6 @@
35
35
  "build:commonjs": "tsc --build tsconfig.build.commonjs.json",
36
36
  "clean": "rimraf dist esm *.tsbuildinfo"
37
37
  },
38
- "dependencies": {
39
- "react-svg-tooltip": "^0.0.11"
40
- },
41
38
  "peerDependencies": {
42
39
  "@jbrowse/core": "^2.0.0",
43
40
  "@jbrowse/plugin-linear-genome-view": "^2.0.0",
@@ -56,5 +53,5 @@
56
53
  "publishConfig": {
57
54
  "access": "public"
58
55
  },
59
- "gitHead": "a50b6f67cf8c8f3c65a7b8cd858de2fcca1f2909"
56
+ "gitHead": "442b5f87efddfdf4ccf520b4d9dd01ddd370cb07"
60
57
  }