@jbrowse/plugin-variants 2.10.0 → 2.10.2

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.
Files changed (39) hide show
  1. package/dist/StructuralVariantChordRenderer/Chord.d.ts +1 -1
  2. package/dist/StructuralVariantChordRenderer/Chord.js +1 -1
  3. package/dist/StructuralVariantChordRenderer/ReactComponent.js +5 -17
  4. package/dist/VariantFeatureWidget/BreakendOptionDialog.d.ts +4 -2
  5. package/dist/VariantFeatureWidget/BreakendOptionDialog.js +30 -18
  6. package/dist/VariantFeatureWidget/BreakendPanel.d.ts +3 -2
  7. package/dist/VariantFeatureWidget/BreakendPanel.js +35 -31
  8. package/dist/VariantFeatureWidget/VariantFeatureWidget.d.ts +2 -5
  9. package/dist/VariantFeatureWidget/VariantFeatureWidget.js +2 -13
  10. package/dist/VariantFeatureWidget/configSchema.d.ts +1 -0
  11. package/dist/VariantFeatureWidget/configSchema.js +5 -0
  12. package/dist/VariantFeatureWidget/index.d.ts +0 -49
  13. package/dist/VariantFeatureWidget/index.js +4 -15
  14. package/dist/VariantFeatureWidget/stateModelFactory.d.ts +52 -0
  15. package/dist/VariantFeatureWidget/stateModelFactory.js +13 -0
  16. package/dist/VariantFeatureWidget/variantFieldDescriptions.d.ts +9 -0
  17. package/dist/VariantFeatureWidget/variantFieldDescriptions.js +12 -0
  18. package/dist/VcfAdapter/VcfAdapter.d.ts +4 -3
  19. package/dist/VcfAdapter/VcfAdapter.js +14 -17
  20. package/esm/StructuralVariantChordRenderer/Chord.d.ts +1 -1
  21. package/esm/StructuralVariantChordRenderer/Chord.js +1 -1
  22. package/esm/StructuralVariantChordRenderer/ReactComponent.js +5 -17
  23. package/esm/VariantFeatureWidget/BreakendOptionDialog.d.ts +4 -2
  24. package/esm/VariantFeatureWidget/BreakendOptionDialog.js +30 -18
  25. package/esm/VariantFeatureWidget/BreakendPanel.d.ts +3 -2
  26. package/esm/VariantFeatureWidget/BreakendPanel.js +37 -30
  27. package/esm/VariantFeatureWidget/VariantFeatureWidget.d.ts +2 -5
  28. package/esm/VariantFeatureWidget/VariantFeatureWidget.js +3 -14
  29. package/esm/VariantFeatureWidget/configSchema.d.ts +1 -0
  30. package/esm/VariantFeatureWidget/configSchema.js +2 -0
  31. package/esm/VariantFeatureWidget/index.d.ts +0 -49
  32. package/esm/VariantFeatureWidget/index.js +3 -12
  33. package/esm/VariantFeatureWidget/stateModelFactory.d.ts +52 -0
  34. package/esm/VariantFeatureWidget/stateModelFactory.js +9 -0
  35. package/esm/VariantFeatureWidget/variantFieldDescriptions.d.ts +9 -0
  36. package/esm/VariantFeatureWidget/variantFieldDescriptions.js +9 -0
  37. package/esm/VcfAdapter/VcfAdapter.d.ts +4 -3
  38. package/esm/VcfAdapter/VcfAdapter.js +14 -17
  39. package/package.json +2 -2
@@ -25,6 +25,6 @@ declare const Chord: ({ feature, blocksForRefs, radius, config, bezierRadius, se
25
25
  config: AnyConfigurationModel;
26
26
  bezierRadius: number;
27
27
  selected: boolean;
28
- onClick: (feature: Feature, reg: AnyRegion, endBlock: AnyRegion, evt: unknown) => void;
28
+ onClick: (feat: Feature, reg: AnyRegion, end: AnyRegion, evt: unknown) => void;
29
29
  }) => React.JSX.Element | null;
30
30
  export default Chord;
@@ -87,7 +87,7 @@ const Chord = (0, mobx_react_1.observer)(function Chord({ feature, blocksForRefs
87
87
  const hoverStrokeColor = (0, configuration_1.readConfObject)(config, 'strokeColorHover', {
88
88
  feature,
89
89
  });
90
- return (react_1.default.createElement("path", { "data-testid": `chord-${feature.id()}`, d: ['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' '), stroke: hovered ? hoverStrokeColor : strokeColor, strokeWidth: hovered ? 3 : 1, onClick: evt => {
90
+ return (react_1.default.createElement("path", { "data-testid": `chord-${feature.id()}`, cursor: "crosshair", fill: "none", d: ['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' '), stroke: hovered ? hoverStrokeColor : strokeColor, strokeWidth: hovered ? 3 : 1, onClick: evt => {
91
91
  if (endBlock && startBlock) {
92
92
  onClick(feature, startBlock.region, endBlock.region, evt);
93
93
  }
@@ -44,22 +44,10 @@ const StructuralVariantChordsReactComponent = (0, mobx_react_1.observer)(functio
44
44
  }
45
45
  return blocksForRefs;
46
46
  }, [blockDefinitions]);
47
- const trackStyleId = `chords-${typeof jest !== 'undefined' ? 'test' : displayModel.id}`;
48
- return (react_1.default.createElement("g", { id: trackStyleId, "data-testid": "structuralVariantChordRenderer" },
49
- react_1.default.createElement("style", {
50
- // eslint-disable-next-line react/no-danger
51
- dangerouslySetInnerHTML: {
52
- __html: `
53
- #${trackStyleId} > path {
54
- cursor: crosshair;
55
- fill: none;
56
- }
57
- `,
58
- } }),
59
- [...features.values()].map(feature => {
60
- const id = feature.id();
61
- const selected = String(selectedFeatureId) === String(id);
62
- return (react_1.default.createElement(Chord_1.default, { key: id, feature: feature, config: config, radius: radius, bezierRadius: bezierRadius, blocksForRefs: blocksForRefsMemo, selected: selected, onClick: onChordClick }));
63
- })));
47
+ return (react_1.default.createElement("g", { id: `chords-${typeof jest !== 'undefined' ? 'test' : displayModel.id}`, "data-testid": "structuralVariantChordRenderer" }, [...features.values()].map(feature => {
48
+ const id = feature.id();
49
+ const selected = String(selectedFeatureId) === String(id);
50
+ return (react_1.default.createElement(Chord_1.default, { key: id, feature: feature, config: config, radius: radius, bezierRadius: bezierRadius, blocksForRefs: blocksForRefsMemo, selected: selected, onClick: onChordClick }));
51
+ })));
64
52
  });
65
53
  exports.default = StructuralVariantChordsReactComponent;
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { Feature } from '@jbrowse/core/util';
3
+ import { ViewType } from '@jbrowse/core/pluggableElementTypes';
4
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
5
  declare const BreakendOptionDialog: ({ model, handleClose, feature, viewType, }: {
4
- model: any;
6
+ model: VariantFeatureWidgetModel;
5
7
  handleClose: () => void;
6
8
  feature: Feature;
7
- viewType: any;
9
+ viewType: ViewType;
8
10
  }) => React.JSX.Element;
9
11
  export default BreakendOptionDialog;
@@ -23,13 +23,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- /* eslint-disable @typescript-eslint/no-explicit-any */
27
26
  const react_1 = __importStar(require("react"));
28
27
  const mobx_react_1 = require("mobx-react");
29
28
  const material_1 = require("@mui/material");
30
29
  const mui_1 = require("tss-react/mui");
31
30
  const mobx_state_tree_1 = require("mobx-state-tree");
32
- // jbrowse
33
31
  const ui_1 = require("@jbrowse/core/ui");
34
32
  const util_1 = require("@jbrowse/core/util");
35
33
  const useStyles = (0, mui_1.makeStyles)()({
@@ -37,34 +35,48 @@ const useStyles = (0, mui_1.makeStyles)()({
37
35
  display: 'block',
38
36
  },
39
37
  });
40
- const BreakendOptionDialog = (0, mobx_react_1.observer)(function ({ model, handleClose, feature, viewType, }) {
38
+ function stripIds(arr) {
39
+ return arr.map(({ id, displays, ...rest }) => ({
40
+ ...rest,
41
+ displays: displays.map(({ id, ...rest }) => rest),
42
+ }));
43
+ }
44
+ function Checkbox2({ checked, label, onChange, }) {
41
45
  const { classes } = useStyles();
46
+ return (react_1.default.createElement(material_1.FormControlLabel, { className: classes.block, control: react_1.default.createElement(material_1.Checkbox, { checked: checked, onChange: onChange }), label: label }));
47
+ }
48
+ const BreakendOptionDialog = (0, mobx_react_1.observer)(function ({ model, handleClose, feature, viewType, }) {
42
49
  const [copyTracks, setCopyTracks] = (0, react_1.useState)(true);
43
- const [mirrorTracks, setMirrorTracks] = (0, react_1.useState)(true);
50
+ const [mirror, setMirror] = (0, react_1.useState)(true);
44
51
  return (react_1.default.createElement(ui_1.Dialog, { open: true, onClose: handleClose, title: "Breakpoint split view options" },
45
52
  react_1.default.createElement(material_1.DialogContent, null,
46
- react_1.default.createElement(material_1.FormControlLabel, { className: classes.block, control: react_1.default.createElement(material_1.Checkbox, { checked: copyTracks, onChange: event => setCopyTracks(event.target.checked) }), label: "Copy tracks into the new view" }),
47
- react_1.default.createElement(material_1.FormControlLabel, { className: classes.block, control: react_1.default.createElement(material_1.Checkbox, { checked: mirrorTracks, onChange: event => setMirrorTracks(event.target.checked) }), label: "Mirror tracks vertically in vertically stacked view" })),
53
+ react_1.default.createElement(Checkbox2, { checked: copyTracks, onChange: event => setCopyTracks(event.target.checked), label: "Copy tracks into the new view" }),
54
+ react_1.default.createElement(Checkbox2, { checked: mirror, onChange: event => setMirror(event.target.checked), label: "Mirror tracks vertically in vertically stacked view" })),
48
55
  react_1.default.createElement(material_1.DialogActions, null,
49
56
  react_1.default.createElement(material_1.Button, { onClick: () => {
50
57
  const { view } = model;
51
58
  const session = (0, util_1.getSession)(model);
52
59
  try {
60
+ // @ts-expect-error
53
61
  const viewSnapshot = viewType.snapshotFromBreakendFeature(feature, view);
54
- function remapIds(arr) {
55
- return arr.map(v => ({
56
- ...v,
57
- id: `${v.trackId}-${Math.random()}`,
58
- }));
59
- }
60
- viewSnapshot.views[0].offsetPx -= view.width / 2 + 100;
61
- viewSnapshot.views[1].offsetPx -= view.width / 2 + 100;
62
- viewSnapshot.featureData = feature;
62
+ const [view1, view2] = viewSnapshot.views;
63
63
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
64
64
  const viewTracks = (0, mobx_state_tree_1.getSnapshot)(view.tracks);
65
- viewSnapshot.views[0].tracks = remapIds(viewTracks);
66
- viewSnapshot.views[1].tracks = remapIds(mirrorTracks ? [...viewTracks].reverse() : viewTracks);
67
- session.addView('BreakpointSplitView', viewSnapshot);
65
+ session.addView('BreakpointSplitView', {
66
+ ...viewSnapshot,
67
+ views: [
68
+ {
69
+ ...view1,
70
+ tracks: stripIds(viewTracks),
71
+ offsetPx: view1.offsetPx - view.width / 2 + 100,
72
+ },
73
+ {
74
+ ...view2,
75
+ tracks: stripIds(mirror ? [...viewTracks].reverse() : viewTracks),
76
+ offsetPx: view2.offsetPx - view.width / 2 + 100,
77
+ },
78
+ ],
79
+ });
68
80
  }
69
81
  catch (e) {
70
82
  console.error(e);
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { SimpleFeatureSerialized } from '@jbrowse/core/util/simpleFeature';
2
+ import { SimpleFeatureSerialized } from '@jbrowse/core/util';
3
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
4
  export default function BreakendPanel(props: {
4
5
  locStrings: string[];
5
- model: any;
6
+ model: VariantFeatureWidgetModel;
6
7
  feature: SimpleFeatureSerialized;
7
8
  }): React.JSX.Element;
@@ -22,33 +22,18 @@ 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
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
- /* eslint-disable @typescript-eslint/no-explicit-any */
30
26
  const react_1 = __importStar(require("react"));
31
27
  const material_1 = require("@mui/material");
32
- const simpleFeature_1 = __importDefault(require("@jbrowse/core/util/simpleFeature"));
33
28
  const util_1 = require("@jbrowse/core/util");
34
29
  const BaseFeatureDetail_1 = require("@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail");
35
- const BreakendOptionDialog_1 = __importDefault(require("./BreakendOptionDialog"));
36
- function BreakendPanel(props) {
37
- const { model, locStrings, feature } = props;
30
+ // lazies
31
+ const BreakendOptionDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./BreakendOptionDialog'))));
32
+ function LocStringList({ locStrings, model, }) {
38
33
  const session = (0, util_1.getSession)(model);
39
- const { pluginManager } = (0, util_1.getEnv)(session);
40
- const [breakpointDialog, setBreakpointDialog] = (0, react_1.useState)(false);
41
- let viewType;
42
- try {
43
- viewType = pluginManager.getViewType('BreakpointSplitView');
44
- }
45
- catch (e) {
46
- // ignore
47
- }
48
- const simpleFeature = new simpleFeature_1.default(feature);
49
- return (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { ...props, title: "Breakends" },
34
+ return (react_1.default.createElement("div", null,
50
35
  react_1.default.createElement(material_1.Typography, null, "Link to linear view of breakend endpoints"),
51
- react_1.default.createElement("ul", null, locStrings.map(locString => (react_1.default.createElement("li", { key: `${JSON.stringify(locString)}` },
36
+ react_1.default.createElement("ul", null, locStrings.map((locString, index) => (react_1.default.createElement("li", { key: `${locString}-${index}` },
52
37
  react_1.default.createElement(material_1.Link, { href: "#", onClick: event => {
53
38
  var _a;
54
39
  event.preventDefault();
@@ -65,16 +50,35 @@ function BreakendPanel(props) {
65
50
  console.error(e);
66
51
  session.notify(`${e}`);
67
52
  }
68
- } }, `LGV - ${locString}`))))),
69
- viewType ? (react_1.default.createElement("div", null,
70
- react_1.default.createElement(material_1.Typography, null, "Launch split views with breakend source and target"),
71
- react_1.default.createElement("ul", null, locStrings.map(locString => (react_1.default.createElement("li", { key: `${JSON.stringify(locString)}` },
72
- react_1.default.createElement(material_1.Link, { href: "#", onClick: event => {
73
- event.preventDefault();
74
- setBreakpointDialog(true);
75
- } }, `${feature.refName}:${feature.start} // ${locString} (split view)`))))),
76
- breakpointDialog ? (react_1.default.createElement(BreakendOptionDialog_1.default, { model: model, feature: simpleFeature, viewType: viewType, handleClose: () => {
77
- setBreakpointDialog(false);
78
- } })) : null)) : null));
53
+ } }, `LGV - ${locString}`)))))));
54
+ }
55
+ function LaunchBreakpointSplitViewPanel({ locStrings, model, feature, viewType, }) {
56
+ const session = (0, util_1.getSession)(model);
57
+ const simpleFeature = new util_1.SimpleFeature(feature);
58
+ return (react_1.default.createElement("div", null,
59
+ react_1.default.createElement(material_1.Typography, null, "Launch split views with breakend source and target"),
60
+ react_1.default.createElement("ul", null, locStrings.map(locString => (react_1.default.createElement("li", { key: `${JSON.stringify(locString)}` },
61
+ react_1.default.createElement(material_1.Link, { href: "#", onClick: event => {
62
+ event.preventDefault();
63
+ session.queueDialog(handleClose => [
64
+ BreakendOptionDialog,
65
+ { handleClose, model, feature: simpleFeature, viewType },
66
+ ]);
67
+ } }, `${feature.refName}:${feature.start} // ${locString} (split view)`)))))));
68
+ }
69
+ function BreakendPanel(props) {
70
+ const { model, locStrings, feature } = props;
71
+ const session = (0, util_1.getSession)(model);
72
+ const { pluginManager } = (0, util_1.getEnv)(session);
73
+ let viewType;
74
+ try {
75
+ viewType = pluginManager.getViewType('BreakpointSplitView');
76
+ }
77
+ catch (e) {
78
+ // ignore
79
+ }
80
+ return (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { ...props, title: "Breakends" },
81
+ react_1.default.createElement(LocStringList, { model: model, locStrings: locStrings }),
82
+ viewType ? (react_1.default.createElement(LaunchBreakpointSplitViewPanel, { viewType: viewType, model: model, locStrings: locStrings, feature: feature })) : null));
79
83
  }
80
84
  exports.default = BreakendPanel;
@@ -1,9 +1,6 @@
1
1
  import React from 'react';
2
- import { SimpleFeatureSerialized } from '@jbrowse/core/util';
2
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
3
  declare const VariantFeatureWidget: (props: {
4
- model: {
5
- featureData: SimpleFeatureSerialized;
6
- descriptions: Record<string, string>;
7
- };
4
+ model: VariantFeatureWidgetModel;
8
5
  }) => React.JSX.Element;
9
6
  export default VariantFeatureWidget;
@@ -12,15 +12,7 @@ const vcf_1 = require("@gmod/vcf");
12
12
  const VariantSampleGrid_1 = __importDefault(require("./VariantSampleGrid"));
13
13
  const BreakendPanel_1 = __importDefault(require("./BreakendPanel"));
14
14
  const VariantAnnotationTable_1 = __importDefault(require("./VariantAnnotationTable"));
15
- const basicDescriptions = {
16
- CHROM: 'chromosome: An identifier from the reference genome',
17
- POS: 'position: The reference position, with the 1st base having position 1',
18
- ID: 'identifier: Semi-colon separated list of unique identifiers where available',
19
- REF: 'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
20
- ALT: 'alternate base(s): Comma-separated list of alternate non-reference alleles',
21
- QUAL: 'quality: Phred-scaled quality score for the assertion made in ALT',
22
- FILTER: 'filter status: PASS if this position has passed all filters, otherwise a semicolon-separated list of codes for filters that fail',
23
- };
15
+ const variantFieldDescriptions_1 = require("./variantFieldDescriptions");
24
16
  function AnnPanel({ descriptions, feature, }) {
25
17
  var _a, _b, _c, _d;
26
18
  const annDesc = (_b = (_a = descriptions === null || descriptions === void 0 ? void 0 : descriptions.INFO) === null || _a === void 0 ? void 0 : _a.ANN) === null || _b === void 0 ? void 0 : _b.Description;
@@ -41,12 +33,9 @@ const VariantFeatureWidget = (0, mobx_react_1.observer)(function (props) {
41
33
  const feat = JSON.parse(JSON.stringify(featureData));
42
34
  const { samples, ...rest } = feat;
43
35
  return (react_1.default.createElement(material_1.Paper, { "data-testid": "variant-side-drawer" },
44
- react_1.default.createElement(BaseFeatureDetail_1.FeatureDetails, { feature: rest, descriptions: { ...basicDescriptions, ...descriptions }, ...props }),
45
- react_1.default.createElement(material_1.Divider, null),
36
+ react_1.default.createElement(BaseFeatureDetail_1.FeatureDetails, { feature: rest, descriptions: { ...variantFieldDescriptions_1.variantFieldDescriptions, ...descriptions }, ...props }),
46
37
  react_1.default.createElement(CsqPanel, { feature: rest, descriptions: descriptions }),
47
- react_1.default.createElement(material_1.Divider, null),
48
38
  react_1.default.createElement(AnnPanel, { feature: rest, descriptions: descriptions }),
49
- react_1.default.createElement(material_1.Divider, null),
50
39
  feat.type === 'breakend' ? (react_1.default.createElement(BreakendPanel_1.default, { feature: feat, locStrings: feat.ALT.map((alt) => { var _a; return ((_a = (0, vcf_1.parseBreakend)(alt)) === null || _a === void 0 ? void 0 : _a.MatePosition) || ''; }), model: model })) : null,
51
40
  feat.type === 'translocation' ? (react_1.default.createElement(BreakendPanel_1.default, { feature: feat, model: model, locStrings: [`${feat.INFO.CHR2[0]}:${feat.INFO.END}`] })) : null,
52
41
  react_1.default.createElement(VariantSampleGrid_1.default, { feature: feat, ...props, descriptions: descriptions })));
@@ -0,0 +1 @@
1
+ export declare const configSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configSchema = void 0;
4
+ const configuration_1 = require("@jbrowse/core/configuration");
5
+ exports.configSchema = (0, configuration_1.ConfigurationSchema)('VariantFeatureWidget', {});
@@ -1,52 +1,3 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager';
2
- export declare const configSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
3
- export declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
4
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
5
- type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
6
- featureData: import("mobx-state-tree").IType<any, any, any>;
7
- formattedFields: import("mobx-state-tree").IType<any, any, any>;
8
- unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
9
- view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
10
- track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
11
- trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
- trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
13
- maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
14
- } & {
15
- type: import("mobx-state-tree").ISimpleType<"VariantFeatureWidget">;
16
- descriptions: import("mobx-state-tree").IType<any, any, any>;
17
- }, {
18
- error: unknown;
19
- } & {
20
- setFeatureData(featureData: Record<string, unknown>): void;
21
- clearFeatureData(): void;
22
- setFormattedData(feat: Record<string, unknown>): void;
23
- setExtra(type?: string | undefined, trackId?: string | undefined, maxDepth?: number | undefined): void;
24
- setError(e: unknown): void;
25
- } & {
26
- afterCreate(): void;
27
- }, {
28
- type: "BaseFeatureWidget";
29
- } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
30
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
31
- type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
32
- featureData: import("mobx-state-tree").IType<any, any, any>;
33
- formattedFields: import("mobx-state-tree").IType<any, any, any>;
34
- unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
35
- view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
36
- track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
37
- trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
38
- trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
39
- maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
40
- }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
41
- type: "BaseFeatureWidget";
42
- id: string;
43
- track: import("mobx-state-tree").ReferenceIdentifier | undefined;
44
- view: import("mobx-state-tree").ReferenceIdentifier | undefined;
45
- trackId: string | undefined;
46
- trackType: string | undefined;
47
- maxDepth: number | undefined;
48
- formattedFields: any;
49
- finalizedFeatureData: any;
50
- } & import("mobx-state-tree")._NotCustomized>;
51
2
  declare const _default: (pluginManager: PluginManager) => void;
52
3
  export default _default;
@@ -26,27 +26,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.stateModelFactory = exports.configSchema = void 0;
30
29
  const react_1 = require("react");
31
- const configuration_1 = require("@jbrowse/core/configuration");
32
30
  const WidgetType_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/WidgetType"));
33
- const mobx_state_tree_1 = require("mobx-state-tree");
34
- const BaseFeatureWidget_1 = require("@jbrowse/core/BaseFeatureWidget");
35
- exports.configSchema = (0, configuration_1.ConfigurationSchema)('VariantFeatureWidget', {});
36
- function stateModelFactory(pluginManager) {
37
- const baseModel = (0, BaseFeatureWidget_1.stateModelFactory)(pluginManager);
38
- return mobx_state_tree_1.types.compose(baseModel, mobx_state_tree_1.types.model('VariantFeatureWidget', {
39
- type: mobx_state_tree_1.types.literal('VariantFeatureWidget'),
40
- descriptions: mobx_state_tree_1.types.frozen(),
41
- }));
42
- }
43
- exports.stateModelFactory = stateModelFactory;
31
+ const stateModelFactory_1 = require("./stateModelFactory");
32
+ const configSchema_1 = require("./configSchema");
44
33
  exports.default = (pluginManager) => {
45
34
  pluginManager.addWidgetType(() => new WidgetType_1.default({
46
35
  name: 'VariantFeatureWidget',
47
36
  heading: 'Feature details',
48
- configSchema: exports.configSchema,
49
- stateModel: stateModelFactory(pluginManager),
37
+ configSchema: configSchema_1.configSchema,
38
+ stateModel: (0, stateModelFactory_1.stateModelFactory)(pluginManager),
50
39
  ReactComponent: (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./VariantFeatureWidget')))),
51
40
  }));
52
41
  };
@@ -0,0 +1,52 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager';
2
+ import { Instance } from 'mobx-state-tree';
3
+ export declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
4
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
5
+ type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
6
+ featureData: import("mobx-state-tree").IType<any, any, any>;
7
+ formattedFields: import("mobx-state-tree").IType<any, any, any>;
8
+ unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
9
+ view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
10
+ track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
11
+ trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
+ trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
13
+ maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
14
+ } & {
15
+ type: import("mobx-state-tree").ISimpleType<"VariantFeatureWidget">;
16
+ descriptions: import("mobx-state-tree").IType<any, any, any>;
17
+ }, {
18
+ error: unknown;
19
+ } & {
20
+ setFeatureData(featureData: Record<string, unknown>): void;
21
+ clearFeatureData(): void;
22
+ setFormattedData(feat: Record<string, unknown>): void;
23
+ setExtra(type?: string | undefined, trackId?: string | undefined, maxDepth?: number | undefined): void;
24
+ setError(e: unknown): void;
25
+ } & {
26
+ afterCreate(): void;
27
+ }, {
28
+ type: "BaseFeatureWidget";
29
+ } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
30
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
31
+ type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
32
+ featureData: import("mobx-state-tree").IType<any, any, any>;
33
+ formattedFields: import("mobx-state-tree").IType<any, any, any>;
34
+ unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
35
+ view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
36
+ track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
37
+ trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
38
+ trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
39
+ maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
40
+ }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
41
+ type: "BaseFeatureWidget";
42
+ id: string;
43
+ track: import("mobx-state-tree").ReferenceIdentifier | undefined;
44
+ view: import("mobx-state-tree").ReferenceIdentifier | undefined;
45
+ trackId: string | undefined;
46
+ trackType: string | undefined;
47
+ maxDepth: number | undefined;
48
+ formattedFields: any;
49
+ finalizedFeatureData: any;
50
+ } & import("mobx-state-tree")._NotCustomized>;
51
+ export type VariantFeatureWidgetStateModel = ReturnType<typeof stateModelFactory>;
52
+ export type VariantFeatureWidgetModel = Instance<VariantFeatureWidgetStateModel>;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stateModelFactory = void 0;
4
+ const mobx_state_tree_1 = require("mobx-state-tree");
5
+ const BaseFeatureWidget_1 = require("@jbrowse/core/BaseFeatureWidget");
6
+ function stateModelFactory(pluginManager) {
7
+ const baseModel = (0, BaseFeatureWidget_1.stateModelFactory)(pluginManager);
8
+ return mobx_state_tree_1.types.compose(baseModel, mobx_state_tree_1.types.model('VariantFeatureWidget', {
9
+ type: mobx_state_tree_1.types.literal('VariantFeatureWidget'),
10
+ descriptions: mobx_state_tree_1.types.frozen(),
11
+ }));
12
+ }
13
+ exports.stateModelFactory = stateModelFactory;
@@ -0,0 +1,9 @@
1
+ export declare const variantFieldDescriptions: {
2
+ CHROM: string;
3
+ POS: string;
4
+ ID: string;
5
+ REF: string;
6
+ ALT: string;
7
+ QUAL: string;
8
+ FILTER: string;
9
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.variantFieldDescriptions = void 0;
4
+ exports.variantFieldDescriptions = {
5
+ CHROM: 'chromosome: An identifier from the reference genome',
6
+ POS: 'position: The reference position, with the 1st base having position 1',
7
+ ID: 'identifier: Semi-colon separated list of unique identifiers where available',
8
+ REF: 'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
9
+ ALT: 'alternate base(s): Comma-separated list of alternate non-reference alleles',
10
+ QUAL: 'quality: Phred-scaled quality score for the assertion made in ALT',
11
+ FILTER: 'filter status: PASS if this position has passed all filters, otherwise a semicolon-separated list of codes for filters that fail',
12
+ };
@@ -1,21 +1,22 @@
1
1
  import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
2
  import { Region, Feature } from '@jbrowse/core/util';
3
3
  import IntervalTree from '@flatten-js/interval-tree';
4
+ import VcfFeature from '../VcfFeature';
4
5
  export default class VcfAdapter extends BaseFeatureDataAdapter {
5
6
  static capabilities: string[];
6
7
  protected vcfFeatures?: Promise<{
7
8
  header: string;
8
- intervalTree: Record<string, IntervalTree>;
9
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
9
10
  }>;
10
11
  getHeader(): Promise<string>;
11
12
  getMetadata(): Promise<any>;
12
13
  setupP(): Promise<{
13
14
  header: string;
14
- intervalTree: Record<string, IntervalTree<any>>;
15
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
15
16
  }>;
16
17
  setup(): Promise<{
17
18
  header: string;
18
- intervalTree: Record<string, IntervalTree<any>>;
19
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
19
20
  }>;
20
21
  getRefNames(_?: BaseOptions): Promise<string[]>;
21
22
  getFeatures(region: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
@@ -52,19 +52,19 @@ class VcfAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
52
52
  const str = new TextDecoder().decode(buffer);
53
53
  const { header, lines } = readVcf(str);
54
54
  const intervalTree = {};
55
- for (const obj of lines.map((line, id) => {
56
- var _a;
57
- const [refName, startP, , ref, , , , info] = line.split('\t');
58
- const start = +startP - 1;
59
- const def = start + ref.length;
60
- const end = +(((_a = info.match(/END=(\d+)/)) === null || _a === void 0 ? void 0 : _a[1].trim()) || def);
61
- return { line, refName, start, end, id };
62
- })) {
63
- const key = obj.refName;
55
+ const parser = new vcf_1.default({ header });
56
+ let idx = 0;
57
+ for (const line of lines) {
58
+ const f = new VcfFeature_1.default({
59
+ variant: parser.parseLine(line),
60
+ parser,
61
+ id: `${this.id}-${idx++}`,
62
+ });
63
+ const key = f.get('refName');
64
64
  if (!intervalTree[key]) {
65
65
  intervalTree[key] = new interval_tree_1.default();
66
66
  }
67
- intervalTree[key].insert([obj.start, obj.end], obj);
67
+ intervalTree[key].insert([f.get('start'), f.get('end')], f);
68
68
  }
69
69
  return { header, intervalTree };
70
70
  }
@@ -86,13 +86,10 @@ class VcfAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
86
86
  var _a;
87
87
  try {
88
88
  const { start, end, refName } = region;
89
- const { header, intervalTree } = await this.setup();
90
- const parser = new vcf_1.default({ header });
91
- (_a = intervalTree[refName]) === null || _a === void 0 ? void 0 : _a.search([start, end]).forEach(f => observer.next(new VcfFeature_1.default({
92
- variant: parser.parseLine(f.line),
93
- parser,
94
- id: `${this.id}-${f.id}`,
95
- })));
89
+ const { intervalTree } = await this.setup();
90
+ (_a = intervalTree[refName]) === null || _a === void 0 ? void 0 : _a.search([start, end]).forEach((f) => {
91
+ observer.next(f);
92
+ });
96
93
  observer.complete();
97
94
  }
98
95
  catch (e) {
@@ -25,6 +25,6 @@ declare const Chord: ({ feature, blocksForRefs, radius, config, bezierRadius, se
25
25
  config: AnyConfigurationModel;
26
26
  bezierRadius: number;
27
27
  selected: boolean;
28
- onClick: (feature: Feature, reg: AnyRegion, endBlock: AnyRegion, evt: unknown) => void;
28
+ onClick: (feat: Feature, reg: AnyRegion, end: AnyRegion, evt: unknown) => void;
29
29
  }) => React.JSX.Element | null;
30
30
  export default Chord;
@@ -62,7 +62,7 @@ const Chord = observer(function Chord({ feature, blocksForRefs, radius, config,
62
62
  const hoverStrokeColor = readConfObject(config, 'strokeColorHover', {
63
63
  feature,
64
64
  });
65
- return (React.createElement("path", { "data-testid": `chord-${feature.id()}`, d: ['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' '), stroke: hovered ? hoverStrokeColor : strokeColor, strokeWidth: hovered ? 3 : 1, onClick: evt => {
65
+ return (React.createElement("path", { "data-testid": `chord-${feature.id()}`, cursor: "crosshair", fill: "none", d: ['M', ...startXY, 'Q', ...controlXY, ...endXY].join(' '), stroke: hovered ? hoverStrokeColor : strokeColor, strokeWidth: hovered ? 3 : 1, onClick: evt => {
66
66
  if (endBlock && startBlock) {
67
67
  onClick(feature, startBlock.region, endBlock.region, evt);
68
68
  }
@@ -16,22 +16,10 @@ const StructuralVariantChordsReactComponent = observer(function ({ features, con
16
16
  }
17
17
  return blocksForRefs;
18
18
  }, [blockDefinitions]);
19
- const trackStyleId = `chords-${typeof jest !== 'undefined' ? 'test' : displayModel.id}`;
20
- return (React.createElement("g", { id: trackStyleId, "data-testid": "structuralVariantChordRenderer" },
21
- React.createElement("style", {
22
- // eslint-disable-next-line react/no-danger
23
- dangerouslySetInnerHTML: {
24
- __html: `
25
- #${trackStyleId} > path {
26
- cursor: crosshair;
27
- fill: none;
28
- }
29
- `,
30
- } }),
31
- [...features.values()].map(feature => {
32
- const id = feature.id();
33
- const selected = String(selectedFeatureId) === String(id);
34
- return (React.createElement(Chord, { key: id, feature: feature, config: config, radius: radius, bezierRadius: bezierRadius, blocksForRefs: blocksForRefsMemo, selected: selected, onClick: onChordClick }));
35
- })));
19
+ return (React.createElement("g", { id: `chords-${typeof jest !== 'undefined' ? 'test' : displayModel.id}`, "data-testid": "structuralVariantChordRenderer" }, [...features.values()].map(feature => {
20
+ const id = feature.id();
21
+ const selected = String(selectedFeatureId) === String(id);
22
+ return (React.createElement(Chord, { key: id, feature: feature, config: config, radius: radius, bezierRadius: bezierRadius, blocksForRefs: blocksForRefsMemo, selected: selected, onClick: onChordClick }));
23
+ })));
36
24
  });
37
25
  export default StructuralVariantChordsReactComponent;
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { Feature } from '@jbrowse/core/util';
3
+ import { ViewType } from '@jbrowse/core/pluggableElementTypes';
4
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
5
  declare const BreakendOptionDialog: ({ model, handleClose, feature, viewType, }: {
4
- model: any;
6
+ model: VariantFeatureWidgetModel;
5
7
  handleClose: () => void;
6
8
  feature: Feature;
7
- viewType: any;
9
+ viewType: ViewType;
8
10
  }) => React.JSX.Element;
9
11
  export default BreakendOptionDialog;
@@ -1,10 +1,8 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
1
  import React, { useState } from 'react';
3
2
  import { observer } from 'mobx-react';
4
3
  import { Button, Checkbox, DialogActions, DialogContent, FormControlLabel, } from '@mui/material';
5
4
  import { makeStyles } from 'tss-react/mui';
6
5
  import { getSnapshot } from 'mobx-state-tree';
7
- // jbrowse
8
6
  import { Dialog } from '@jbrowse/core/ui';
9
7
  import { getSession } from '@jbrowse/core/util';
10
8
  const useStyles = makeStyles()({
@@ -12,34 +10,48 @@ const useStyles = makeStyles()({
12
10
  display: 'block',
13
11
  },
14
12
  });
15
- const BreakendOptionDialog = observer(function ({ model, handleClose, feature, viewType, }) {
13
+ function stripIds(arr) {
14
+ return arr.map(({ id, displays, ...rest }) => ({
15
+ ...rest,
16
+ displays: displays.map(({ id, ...rest }) => rest),
17
+ }));
18
+ }
19
+ function Checkbox2({ checked, label, onChange, }) {
16
20
  const { classes } = useStyles();
21
+ return (React.createElement(FormControlLabel, { className: classes.block, control: React.createElement(Checkbox, { checked: checked, onChange: onChange }), label: label }));
22
+ }
23
+ const BreakendOptionDialog = observer(function ({ model, handleClose, feature, viewType, }) {
17
24
  const [copyTracks, setCopyTracks] = useState(true);
18
- const [mirrorTracks, setMirrorTracks] = useState(true);
25
+ const [mirror, setMirror] = useState(true);
19
26
  return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Breakpoint split view options" },
20
27
  React.createElement(DialogContent, null,
21
- React.createElement(FormControlLabel, { className: classes.block, control: React.createElement(Checkbox, { checked: copyTracks, onChange: event => setCopyTracks(event.target.checked) }), label: "Copy tracks into the new view" }),
22
- React.createElement(FormControlLabel, { className: classes.block, control: React.createElement(Checkbox, { checked: mirrorTracks, onChange: event => setMirrorTracks(event.target.checked) }), label: "Mirror tracks vertically in vertically stacked view" })),
28
+ React.createElement(Checkbox2, { checked: copyTracks, onChange: event => setCopyTracks(event.target.checked), label: "Copy tracks into the new view" }),
29
+ React.createElement(Checkbox2, { checked: mirror, onChange: event => setMirror(event.target.checked), label: "Mirror tracks vertically in vertically stacked view" })),
23
30
  React.createElement(DialogActions, null,
24
31
  React.createElement(Button, { onClick: () => {
25
32
  const { view } = model;
26
33
  const session = getSession(model);
27
34
  try {
35
+ // @ts-expect-error
28
36
  const viewSnapshot = viewType.snapshotFromBreakendFeature(feature, view);
29
- function remapIds(arr) {
30
- return arr.map(v => ({
31
- ...v,
32
- id: `${v.trackId}-${Math.random()}`,
33
- }));
34
- }
35
- viewSnapshot.views[0].offsetPx -= view.width / 2 + 100;
36
- viewSnapshot.views[1].offsetPx -= view.width / 2 + 100;
37
- viewSnapshot.featureData = feature;
37
+ const [view1, view2] = viewSnapshot.views;
38
38
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
39
39
  const viewTracks = getSnapshot(view.tracks);
40
- viewSnapshot.views[0].tracks = remapIds(viewTracks);
41
- viewSnapshot.views[1].tracks = remapIds(mirrorTracks ? [...viewTracks].reverse() : viewTracks);
42
- session.addView('BreakpointSplitView', viewSnapshot);
40
+ session.addView('BreakpointSplitView', {
41
+ ...viewSnapshot,
42
+ views: [
43
+ {
44
+ ...view1,
45
+ tracks: stripIds(viewTracks),
46
+ offsetPx: view1.offsetPx - view.width / 2 + 100,
47
+ },
48
+ {
49
+ ...view2,
50
+ tracks: stripIds(mirror ? [...viewTracks].reverse() : viewTracks),
51
+ offsetPx: view2.offsetPx - view.width / 2 + 100,
52
+ },
53
+ ],
54
+ });
43
55
  }
44
56
  catch (e) {
45
57
  console.error(e);
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { SimpleFeatureSerialized } from '@jbrowse/core/util/simpleFeature';
2
+ import { SimpleFeatureSerialized } from '@jbrowse/core/util';
3
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
4
  export default function BreakendPanel(props: {
4
5
  locStrings: string[];
5
- model: any;
6
+ model: VariantFeatureWidgetModel;
6
7
  feature: SimpleFeatureSerialized;
7
8
  }): React.JSX.Element;
@@ -1,26 +1,14 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import React, { useState } from 'react';
1
+ import React, { lazy } from 'react';
3
2
  import { Link, Typography } from '@mui/material';
4
- import SimpleFeature from '@jbrowse/core/util/simpleFeature';
5
- import { getEnv, getSession } from '@jbrowse/core/util';
3
+ import { getEnv, getSession, SimpleFeature, } from '@jbrowse/core/util';
6
4
  import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail';
7
- import BreakendOptionDialog from './BreakendOptionDialog';
8
- export default function BreakendPanel(props) {
9
- const { model, locStrings, feature } = props;
5
+ // lazies
6
+ const BreakendOptionDialog = lazy(() => import('./BreakendOptionDialog'));
7
+ function LocStringList({ locStrings, model, }) {
10
8
  const session = getSession(model);
11
- const { pluginManager } = getEnv(session);
12
- const [breakpointDialog, setBreakpointDialog] = useState(false);
13
- let viewType;
14
- try {
15
- viewType = pluginManager.getViewType('BreakpointSplitView');
16
- }
17
- catch (e) {
18
- // ignore
19
- }
20
- const simpleFeature = new SimpleFeature(feature);
21
- return (React.createElement(BaseCard, { ...props, title: "Breakends" },
9
+ return (React.createElement("div", null,
22
10
  React.createElement(Typography, null, "Link to linear view of breakend endpoints"),
23
- React.createElement("ul", null, locStrings.map(locString => (React.createElement("li", { key: `${JSON.stringify(locString)}` },
11
+ React.createElement("ul", null, locStrings.map((locString, index) => (React.createElement("li", { key: `${locString}-${index}` },
24
12
  React.createElement(Link, { href: "#", onClick: event => {
25
13
  var _a;
26
14
  event.preventDefault();
@@ -37,15 +25,34 @@ export default function BreakendPanel(props) {
37
25
  console.error(e);
38
26
  session.notify(`${e}`);
39
27
  }
40
- } }, `LGV - ${locString}`))))),
41
- viewType ? (React.createElement("div", null,
42
- React.createElement(Typography, null, "Launch split views with breakend source and target"),
43
- React.createElement("ul", null, locStrings.map(locString => (React.createElement("li", { key: `${JSON.stringify(locString)}` },
44
- React.createElement(Link, { href: "#", onClick: event => {
45
- event.preventDefault();
46
- setBreakpointDialog(true);
47
- } }, `${feature.refName}:${feature.start} // ${locString} (split view)`))))),
48
- breakpointDialog ? (React.createElement(BreakendOptionDialog, { model: model, feature: simpleFeature, viewType: viewType, handleClose: () => {
49
- setBreakpointDialog(false);
50
- } })) : null)) : null));
28
+ } }, `LGV - ${locString}`)))))));
29
+ }
30
+ function LaunchBreakpointSplitViewPanel({ locStrings, model, feature, viewType, }) {
31
+ const session = getSession(model);
32
+ const simpleFeature = new SimpleFeature(feature);
33
+ return (React.createElement("div", null,
34
+ React.createElement(Typography, null, "Launch split views with breakend source and target"),
35
+ React.createElement("ul", null, locStrings.map(locString => (React.createElement("li", { key: `${JSON.stringify(locString)}` },
36
+ React.createElement(Link, { href: "#", onClick: event => {
37
+ event.preventDefault();
38
+ session.queueDialog(handleClose => [
39
+ BreakendOptionDialog,
40
+ { handleClose, model, feature: simpleFeature, viewType },
41
+ ]);
42
+ } }, `${feature.refName}:${feature.start} // ${locString} (split view)`)))))));
43
+ }
44
+ export default function BreakendPanel(props) {
45
+ const { model, locStrings, feature } = props;
46
+ const session = getSession(model);
47
+ const { pluginManager } = getEnv(session);
48
+ let viewType;
49
+ try {
50
+ viewType = pluginManager.getViewType('BreakpointSplitView');
51
+ }
52
+ catch (e) {
53
+ // ignore
54
+ }
55
+ return (React.createElement(BaseCard, { ...props, title: "Breakends" },
56
+ React.createElement(LocStringList, { model: model, locStrings: locStrings }),
57
+ viewType ? (React.createElement(LaunchBreakpointSplitViewPanel, { viewType: viewType, model: model, locStrings: locStrings, feature: feature })) : null));
51
58
  }
@@ -1,9 +1,6 @@
1
1
  import React from 'react';
2
- import { SimpleFeatureSerialized } from '@jbrowse/core/util';
2
+ import { VariantFeatureWidgetModel } from './stateModelFactory';
3
3
  declare const VariantFeatureWidget: (props: {
4
- model: {
5
- featureData: SimpleFeatureSerialized;
6
- descriptions: Record<string, string>;
7
- };
4
+ model: VariantFeatureWidgetModel;
8
5
  }) => React.JSX.Element;
9
6
  export default VariantFeatureWidget;
@@ -1,21 +1,13 @@
1
1
  import React from 'react';
2
2
  import { observer } from 'mobx-react';
3
- import { Divider, Paper } from '@mui/material';
3
+ import { Paper } from '@mui/material';
4
4
  import { FeatureDetails } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail';
5
5
  import { parseBreakend } from '@gmod/vcf';
6
6
  // locals
7
7
  import VariantSampleGrid from './VariantSampleGrid';
8
8
  import BreakendPanel from './BreakendPanel';
9
9
  import VariantAnnotationTable from './VariantAnnotationTable';
10
- const basicDescriptions = {
11
- CHROM: 'chromosome: An identifier from the reference genome',
12
- POS: 'position: The reference position, with the 1st base having position 1',
13
- ID: 'identifier: Semi-colon separated list of unique identifiers where available',
14
- REF: 'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
15
- ALT: 'alternate base(s): Comma-separated list of alternate non-reference alleles',
16
- QUAL: 'quality: Phred-scaled quality score for the assertion made in ALT',
17
- FILTER: 'filter status: PASS if this position has passed all filters, otherwise a semicolon-separated list of codes for filters that fail',
18
- };
10
+ import { variantFieldDescriptions } from './variantFieldDescriptions';
19
11
  function AnnPanel({ descriptions, feature, }) {
20
12
  var _a, _b, _c, _d;
21
13
  const annDesc = (_b = (_a = descriptions === null || descriptions === void 0 ? void 0 : descriptions.INFO) === null || _a === void 0 ? void 0 : _a.ANN) === null || _b === void 0 ? void 0 : _b.Description;
@@ -36,12 +28,9 @@ const VariantFeatureWidget = observer(function (props) {
36
28
  const feat = JSON.parse(JSON.stringify(featureData));
37
29
  const { samples, ...rest } = feat;
38
30
  return (React.createElement(Paper, { "data-testid": "variant-side-drawer" },
39
- React.createElement(FeatureDetails, { feature: rest, descriptions: { ...basicDescriptions, ...descriptions }, ...props }),
40
- React.createElement(Divider, null),
31
+ React.createElement(FeatureDetails, { feature: rest, descriptions: { ...variantFieldDescriptions, ...descriptions }, ...props }),
41
32
  React.createElement(CsqPanel, { feature: rest, descriptions: descriptions }),
42
- React.createElement(Divider, null),
43
33
  React.createElement(AnnPanel, { feature: rest, descriptions: descriptions }),
44
- React.createElement(Divider, null),
45
34
  feat.type === 'breakend' ? (React.createElement(BreakendPanel, { feature: feat, locStrings: feat.ALT.map((alt) => { var _a; return ((_a = parseBreakend(alt)) === null || _a === void 0 ? void 0 : _a.MatePosition) || ''; }), model: model })) : null,
46
35
  feat.type === 'translocation' ? (React.createElement(BreakendPanel, { feature: feat, model: model, locStrings: [`${feat.INFO.CHR2[0]}:${feat.INFO.END}`] })) : null,
47
36
  React.createElement(VariantSampleGrid, { feature: feat, ...props, descriptions: descriptions })));
@@ -0,0 +1 @@
1
+ export declare const configSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
@@ -0,0 +1,2 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration';
2
+ export const configSchema = ConfigurationSchema('VariantFeatureWidget', {});
@@ -1,52 +1,3 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager';
2
- export declare const configSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
3
- export declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
4
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
5
- type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
6
- featureData: import("mobx-state-tree").IType<any, any, any>;
7
- formattedFields: import("mobx-state-tree").IType<any, any, any>;
8
- unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
9
- view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
10
- track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
11
- trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
- trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
13
- maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
14
- } & {
15
- type: import("mobx-state-tree").ISimpleType<"VariantFeatureWidget">;
16
- descriptions: import("mobx-state-tree").IType<any, any, any>;
17
- }, {
18
- error: unknown;
19
- } & {
20
- setFeatureData(featureData: Record<string, unknown>): void;
21
- clearFeatureData(): void;
22
- setFormattedData(feat: Record<string, unknown>): void;
23
- setExtra(type?: string | undefined, trackId?: string | undefined, maxDepth?: number | undefined): void;
24
- setError(e: unknown): void;
25
- } & {
26
- afterCreate(): void;
27
- }, {
28
- type: "BaseFeatureWidget";
29
- } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
30
- id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
31
- type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
32
- featureData: import("mobx-state-tree").IType<any, any, any>;
33
- formattedFields: import("mobx-state-tree").IType<any, any, any>;
34
- unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
35
- view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
36
- track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
37
- trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
38
- trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
39
- maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
40
- }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
41
- type: "BaseFeatureWidget";
42
- id: string;
43
- track: import("mobx-state-tree").ReferenceIdentifier | undefined;
44
- view: import("mobx-state-tree").ReferenceIdentifier | undefined;
45
- trackId: string | undefined;
46
- trackType: string | undefined;
47
- maxDepth: number | undefined;
48
- formattedFields: any;
49
- finalizedFeatureData: any;
50
- } & import("mobx-state-tree")._NotCustomized>;
51
2
  declare const _default: (pluginManager: PluginManager) => void;
52
3
  export default _default;
@@ -1,21 +1,12 @@
1
1
  import { lazy } from 'react';
2
- import { ConfigurationSchema } from '@jbrowse/core/configuration';
3
2
  import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType';
4
- import { types } from 'mobx-state-tree';
5
- import { stateModelFactory as baseModelFactory } from '@jbrowse/core/BaseFeatureWidget';
6
- export const configSchema = ConfigurationSchema('VariantFeatureWidget', {});
7
- export function stateModelFactory(pluginManager) {
8
- const baseModel = baseModelFactory(pluginManager);
9
- return types.compose(baseModel, types.model('VariantFeatureWidget', {
10
- type: types.literal('VariantFeatureWidget'),
11
- descriptions: types.frozen(),
12
- }));
13
- }
3
+ import { stateModelFactory } from './stateModelFactory';
4
+ import { configSchema } from './configSchema';
14
5
  export default (pluginManager) => {
15
6
  pluginManager.addWidgetType(() => new WidgetType({
16
7
  name: 'VariantFeatureWidget',
17
8
  heading: 'Feature details',
18
- configSchema,
9
+ configSchema: configSchema,
19
10
  stateModel: stateModelFactory(pluginManager),
20
11
  ReactComponent: lazy(() => import('./VariantFeatureWidget')),
21
12
  }));
@@ -0,0 +1,52 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager';
2
+ import { Instance } from 'mobx-state-tree';
3
+ export declare function stateModelFactory(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
4
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
5
+ type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
6
+ featureData: import("mobx-state-tree").IType<any, any, any>;
7
+ formattedFields: import("mobx-state-tree").IType<any, any, any>;
8
+ unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
9
+ view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
10
+ track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
11
+ trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
12
+ trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
13
+ maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
14
+ } & {
15
+ type: import("mobx-state-tree").ISimpleType<"VariantFeatureWidget">;
16
+ descriptions: import("mobx-state-tree").IType<any, any, any>;
17
+ }, {
18
+ error: unknown;
19
+ } & {
20
+ setFeatureData(featureData: Record<string, unknown>): void;
21
+ clearFeatureData(): void;
22
+ setFormattedData(feat: Record<string, unknown>): void;
23
+ setExtra(type?: string | undefined, trackId?: string | undefined, maxDepth?: number | undefined): void;
24
+ setError(e: unknown): void;
25
+ } & {
26
+ afterCreate(): void;
27
+ }, {
28
+ type: "BaseFeatureWidget";
29
+ } & Partial<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
30
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
31
+ type: import("mobx-state-tree").ISimpleType<"BaseFeatureWidget">;
32
+ featureData: import("mobx-state-tree").IType<any, any, any>;
33
+ formattedFields: import("mobx-state-tree").IType<any, any, any>;
34
+ unformattedFeatureData: import("mobx-state-tree").IType<any, any, any>;
35
+ view: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
36
+ track: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IReferenceType<import("mobx-state-tree").IAnyType>>;
37
+ trackId: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
38
+ trackType: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
39
+ maxDepth: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<number>>;
40
+ }>> & import("mobx-state-tree/dist/internal").NonEmptyObject & import("mobx-state-tree")._NotCustomized, {
41
+ type: "BaseFeatureWidget";
42
+ id: string;
43
+ track: import("mobx-state-tree").ReferenceIdentifier | undefined;
44
+ view: import("mobx-state-tree").ReferenceIdentifier | undefined;
45
+ trackId: string | undefined;
46
+ trackType: string | undefined;
47
+ maxDepth: number | undefined;
48
+ formattedFields: any;
49
+ finalizedFeatureData: any;
50
+ } & import("mobx-state-tree")._NotCustomized>;
51
+ export type VariantFeatureWidgetStateModel = ReturnType<typeof stateModelFactory>;
52
+ export type VariantFeatureWidgetModel = Instance<VariantFeatureWidgetStateModel>;
@@ -0,0 +1,9 @@
1
+ import { types } from 'mobx-state-tree';
2
+ import { stateModelFactory as baseModelFactory } from '@jbrowse/core/BaseFeatureWidget';
3
+ export function stateModelFactory(pluginManager) {
4
+ const baseModel = baseModelFactory(pluginManager);
5
+ return types.compose(baseModel, types.model('VariantFeatureWidget', {
6
+ type: types.literal('VariantFeatureWidget'),
7
+ descriptions: types.frozen(),
8
+ }));
9
+ }
@@ -0,0 +1,9 @@
1
+ export declare const variantFieldDescriptions: {
2
+ CHROM: string;
3
+ POS: string;
4
+ ID: string;
5
+ REF: string;
6
+ ALT: string;
7
+ QUAL: string;
8
+ FILTER: string;
9
+ };
@@ -0,0 +1,9 @@
1
+ export const variantFieldDescriptions = {
2
+ CHROM: 'chromosome: An identifier from the reference genome',
3
+ POS: 'position: The reference position, with the 1st base having position 1',
4
+ ID: 'identifier: Semi-colon separated list of unique identifiers where available',
5
+ REF: 'reference base(s): Each base must be one of A,C,G,T,N (case insensitive).',
6
+ ALT: 'alternate base(s): Comma-separated list of alternate non-reference alleles',
7
+ QUAL: 'quality: Phred-scaled quality score for the assertion made in ALT',
8
+ FILTER: 'filter status: PASS if this position has passed all filters, otherwise a semicolon-separated list of codes for filters that fail',
9
+ };
@@ -1,21 +1,22 @@
1
1
  import { BaseFeatureDataAdapter, BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter';
2
2
  import { Region, Feature } from '@jbrowse/core/util';
3
3
  import IntervalTree from '@flatten-js/interval-tree';
4
+ import VcfFeature from '../VcfFeature';
4
5
  export default class VcfAdapter extends BaseFeatureDataAdapter {
5
6
  static capabilities: string[];
6
7
  protected vcfFeatures?: Promise<{
7
8
  header: string;
8
- intervalTree: Record<string, IntervalTree>;
9
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
9
10
  }>;
10
11
  getHeader(): Promise<string>;
11
12
  getMetadata(): Promise<any>;
12
13
  setupP(): Promise<{
13
14
  header: string;
14
- intervalTree: Record<string, IntervalTree<any>>;
15
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
15
16
  }>;
16
17
  setup(): Promise<{
17
18
  header: string;
18
- intervalTree: Record<string, IntervalTree<any>>;
19
+ intervalTree: Record<string, IntervalTree<VcfFeature>>;
19
20
  }>;
20
21
  getRefNames(_?: BaseOptions): Promise<string[]>;
21
22
  getFeatures(region: Region, opts?: BaseOptions): import("rxjs").Observable<Feature>;
@@ -47,19 +47,19 @@ class VcfAdapter extends BaseFeatureDataAdapter {
47
47
  const str = new TextDecoder().decode(buffer);
48
48
  const { header, lines } = readVcf(str);
49
49
  const intervalTree = {};
50
- for (const obj of lines.map((line, id) => {
51
- var _a;
52
- const [refName, startP, , ref, , , , info] = line.split('\t');
53
- const start = +startP - 1;
54
- const def = start + ref.length;
55
- const end = +(((_a = info.match(/END=(\d+)/)) === null || _a === void 0 ? void 0 : _a[1].trim()) || def);
56
- return { line, refName, start, end, id };
57
- })) {
58
- const key = obj.refName;
50
+ const parser = new VCF({ header });
51
+ let idx = 0;
52
+ for (const line of lines) {
53
+ const f = new VcfFeature({
54
+ variant: parser.parseLine(line),
55
+ parser,
56
+ id: `${this.id}-${idx++}`,
57
+ });
58
+ const key = f.get('refName');
59
59
  if (!intervalTree[key]) {
60
60
  intervalTree[key] = new IntervalTree();
61
61
  }
62
- intervalTree[key].insert([obj.start, obj.end], obj);
62
+ intervalTree[key].insert([f.get('start'), f.get('end')], f);
63
63
  }
64
64
  return { header, intervalTree };
65
65
  }
@@ -81,13 +81,10 @@ class VcfAdapter extends BaseFeatureDataAdapter {
81
81
  var _a;
82
82
  try {
83
83
  const { start, end, refName } = region;
84
- const { header, intervalTree } = await this.setup();
85
- const parser = new VCF({ header });
86
- (_a = intervalTree[refName]) === null || _a === void 0 ? void 0 : _a.search([start, end]).forEach(f => observer.next(new VcfFeature({
87
- variant: parser.parseLine(f.line),
88
- parser,
89
- id: `${this.id}-${f.id}`,
90
- })));
84
+ const { intervalTree } = await this.setup();
85
+ (_a = intervalTree[refName]) === null || _a === void 0 ? void 0 : _a.search([start, end]).forEach((f) => {
86
+ observer.next(f);
87
+ });
91
88
  observer.complete();
92
89
  }
93
90
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-variants",
3
- "version": "2.10.0",
3
+ "version": "2.10.2",
4
4
  "description": "JBrowse 2 variant adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -63,5 +63,5 @@
63
63
  "distModule": "esm/index.js",
64
64
  "srcModule": "src/index.ts",
65
65
  "module": "esm/index.js",
66
- "gitHead": "223d8bfb68fd1bacaf22852639ad5920f1b7f43b"
66
+ "gitHead": "7ca3b7db337ebd88853e2d96cdab940ed550c4fb"
67
67
  }