@jbrowse/core 2.11.0 → 2.11.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.
Files changed (45) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail/index.js +10 -2
  2. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.d.ts +7 -2
  3. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.js +80 -86
  4. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +8 -0
  5. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.js +67 -0
  6. package/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.d.ts +5 -3
  7. package/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.js +7 -7
  8. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SettingsDialog.d.ts +7 -0
  9. package/BaseFeatureWidget/SequenceFeatureDetails/{SequenceFeatureSettingsDialog.js → dialogs/SettingsDialog.js} +20 -10
  10. package/BaseFeatureWidget/SequenceFeatureDetails/hooks.js +2 -8
  11. package/BaseFeatureWidget/SequenceFeatureDetails/index.d.ts +1 -3
  12. package/BaseFeatureWidget/SequenceFeatureDetails/index.js +3 -67
  13. package/BaseFeatureWidget/SequenceFeatureDetails/model.d.ts +14 -0
  14. package/BaseFeatureWidget/SequenceFeatureDetails/model.js +40 -0
  15. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDNASequence.d.ts +15 -0
  16. package/BaseFeatureWidget/SequenceFeatureDetails/{CDNASequence.js → seqtypes/CDNASequence.js} +17 -8
  17. package/BaseFeatureWidget/SequenceFeatureDetails/{CDSSequence.d.ts → seqtypes/CDSSequence.d.ts} +1 -1
  18. package/BaseFeatureWidget/SequenceFeatureDetails/{CDSSequence.js → seqtypes/CDSSequence.js} +2 -2
  19. package/BaseFeatureWidget/SequenceFeatureDetails/{GenomicSequence.js → seqtypes/GenomicSequence.js} +1 -1
  20. package/BaseFeatureWidget/SequenceFeatureDetails/{ProteinSequence.d.ts → seqtypes/ProteinSequence.d.ts} +1 -1
  21. package/BaseFeatureWidget/SequenceFeatureDetails/{ProteinSequence.js → seqtypes/ProteinSequence.js} +2 -2
  22. package/BaseFeatureWidget/stateModelFactory.d.ts +32 -0
  23. package/BaseFeatureWidget/stateModelFactory.js +5 -0
  24. package/BaseFeatureWidget/types.d.ts +2 -7
  25. package/BaseFeatureWidget/util.d.ts +4 -2
  26. package/PluginManager.d.ts +1 -1
  27. package/ReExports/modules.d.ts +1 -1
  28. package/data_adapters/CytobandAdapter/index.d.ts +1 -2
  29. package/data_adapters/CytobandAdapter/index.js +3 -2
  30. package/package.json +2 -2
  31. package/tsconfig.build.tsbuildinfo +1 -1
  32. package/ui/index.d.ts +0 -1
  33. package/ui/index.js +1 -3
  34. package/util/index.d.ts +8 -0
  35. package/util/index.js +12 -2
  36. package/util/jexl.d.ts +1 -1
  37. package/util/jexl.js +2 -2
  38. package/util/simpleFeature.d.ts +4 -0
  39. package/BaseFeatureWidget/SequenceFeatureDetails/CDNASequence.d.ts +0 -13
  40. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureSettingsDialog.d.ts +0 -9
  41. package/ui/Tooltip.d.ts +0 -11
  42. package/ui/Tooltip.js +0 -54
  43. /package/BaseFeatureWidget/SequenceFeatureDetails/{SequenceHelpDialog.d.ts → dialogs/HelpDialog.d.ts} +0 -0
  44. /package/BaseFeatureWidget/SequenceFeatureDetails/{SequenceHelpDialog.js → dialogs/HelpDialog.js} +0 -0
  45. /package/BaseFeatureWidget/SequenceFeatureDetails/{GenomicSequence.d.ts → seqtypes/GenomicSequence.d.ts} +0 -0
@@ -84,7 +84,6 @@ function Position(props) {
84
84
  '1': '+',
85
85
  };
86
86
  const str = strandMap[strand] ? `(${strandMap[strand]})` : '';
87
- // @ts-expect-error
88
87
  const loc = (0, util_1.assembleLocString)(feature);
89
88
  return react_1.default.createElement(react_1.default.Fragment, null, `${loc} ${str}`);
90
89
  }
@@ -140,7 +139,16 @@ function FeatureDetails(props) {
140
139
  mate ? (react_1.default.createElement(react_1.default.Fragment, null,
141
140
  react_1.default.createElement(material_1.Divider, null),
142
141
  react_1.default.createElement(material_1.Typography, null, "Mate details"),
143
- react_1.default.createElement(CoreDetails, { ...props, feature: { ...mate, uniqueId: uniqueId + '-mate' } }))) : null,
142
+ react_1.default.createElement(CoreDetails, { ...props, feature: {
143
+ ...mate,
144
+ // @ts-expect-error
145
+ start: mate.start,
146
+ // @ts-expect-error
147
+ end: mate.end,
148
+ // @ts-expect-error
149
+ refName: mate.refName,
150
+ uniqueId: uniqueId + '-mate',
151
+ } }))) : null,
144
152
  react_1.default.createElement(material_1.Divider, null),
145
153
  react_1.default.createElement(material_1.Typography, null, "Attributes"),
146
154
  react_1.default.createElement(Attributes_1.default, { attributes: feature, ...props, omit: omit, omitSingleLevel: coreDetails }),
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
- import { BaseProps } from './../types';
3
- export default function SequenceFeatureDetails({ model, feature: prefeature, }: BaseProps): React.JSX.Element;
2
+ import { SimpleFeatureSerialized } from '../../util';
3
+ import { BaseFeatureWidgetModel } from '../stateModelFactory';
4
+ declare const SequenceFeatureDetails: ({ model, feature, }: {
5
+ model: BaseFeatureWidgetModel;
6
+ feature: SimpleFeatureSerialized;
7
+ }) => React.JSX.Element;
8
+ export default SequenceFeatureDetails;
@@ -29,115 +29,109 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const react_1 = __importStar(require("react"));
30
30
  const material_1 = require("@mui/material");
31
31
  const mui_1 = require("tss-react/mui");
32
+ const mobx_react_1 = require("mobx-react");
32
33
  const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
33
34
  // locals
34
- const util_1 = require("../../util");
35
+ const hooks_1 = require("./hooks");
35
36
  const ui_1 = require("../../ui");
37
+ const util_1 = require("../../util");
36
38
  // icons
37
39
  const Settings_1 = __importDefault(require("@mui/icons-material/Settings"));
38
- const hooks_1 = require("./hooks");
39
40
  // lazies
40
- const SettingsDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequenceFeatureSettingsDialog'))));
41
41
  const SequencePanel = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequencePanel'))));
42
- const useStyles = (0, mui_1.makeStyles)()(theme => ({
43
- button: {
44
- margin: theme.spacing(1),
45
- },
42
+ const SettingsDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./dialogs/SettingsDialog'))));
43
+ const useStyles = (0, mui_1.makeStyles)()({
46
44
  formControl: {
47
45
  margin: 0,
46
+ marginLeft: 4,
48
47
  },
49
- container2: {
50
- marginTop: theme.spacing(1),
51
- },
52
- }));
48
+ });
53
49
  // set the key on this component to feature.id to clear state after new feature
54
50
  // is selected
55
- function SequenceFeatureDetails({ model, feature: prefeature, }) {
51
+ const SequenceFeatureDetails = (0, mobx_react_1.observer)(function ({ model, feature, }) {
56
52
  var _a, _b;
53
+ const { sequenceFeatureDetails } = model;
54
+ const { intronBp, upDownBp } = sequenceFeatureDetails;
57
55
  const { classes } = useStyles();
58
- const feature = prefeature;
59
56
  const seqPanelRef = (0, react_1.useRef)(null);
60
- const [intronBp, setIntronBp] = (0, util_1.useLocalStorage)('intronBp', 10);
61
- const [upDownBp, setUpDownBp] = (0, util_1.useLocalStorage)('upDownBp', 500);
62
- const [copied, setCopied] = (0, react_1.useState)(false);
63
- const [copiedHtml, setCopiedHtml] = (0, react_1.useState)(false);
64
57
  const [force, setForce] = (0, react_1.useState)(false);
65
58
  const hasCDS = (_a = feature.subfeatures) === null || _a === void 0 ? void 0 : _a.some(sub => sub.type === 'CDS');
66
59
  const hasExon = (_b = feature.subfeatures) === null || _b === void 0 ? void 0 : _b.some(sub => sub.type === 'exon');
67
60
  const hasExonOrCDS = hasExon || hasCDS;
68
- const { sequence, error } = (0, hooks_1.useFeatureSequence)(model, prefeature, upDownBp, force);
61
+ const { sequence, error } = (0, hooks_1.useFeatureSequence)(model, feature, upDownBp, force);
69
62
  const [mode, setMode] = (0, react_1.useState)(hasCDS ? 'cds' : hasExon ? 'cdna' : 'genomic');
70
- const rest = {
71
- ...(hasCDS ? { cds: 'CDS' } : {}),
72
- ...(hasCDS ? { protein: 'Protein' } : {}),
73
- ...(hasExonOrCDS ? { cdna: 'cDNA' } : {}),
74
- ...(hasExonOrCDS ? { gene: `Genomic w/ full introns` } : {}),
75
- ...(hasExonOrCDS
76
- ? {
77
- gene_updownstream: `Genomic w/ full introns +/- ${upDownBp}bp up+down stream`,
78
- }
79
- : {}),
80
- ...(hasExonOrCDS
81
- ? { gene_collapsed_intron: `Genomic w/ ${intronBp}bp intron` }
82
- : {}),
83
- ...(hasExonOrCDS
84
- ? {
85
- gene_updownstream_collapsed_intron: `Genomic w/ ${intronBp}bp intron +/- ${upDownBp}bp up+down stream `,
86
- }
87
- : {}),
88
- ...(!hasExonOrCDS ? { genomic: 'Genomic' } : {}),
89
- ...(!hasExonOrCDS
90
- ? {
91
- genomic_sequence_updownstream: `Genomic +/- ${upDownBp}bp up+down stream`,
92
- }
93
- : {}),
94
- };
95
- return (react_1.default.createElement("div", { className: classes.container2 },
96
- react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
97
- react_1.default.createElement(material_1.Select, { value: mode, onChange: event => setMode(event.target.value) }, Object.entries(rest).map(([key, val]) => (react_1.default.createElement(material_1.MenuItem, { key: key, value: key }, val))))),
98
- react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
99
- react_1.default.createElement(material_1.Button, { className: classes.button, variant: "contained", onClick: () => {
63
+ return (react_1.default.createElement(react_1.default.Fragment, null,
64
+ react_1.default.createElement("div", null,
65
+ react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
66
+ react_1.default.createElement(material_1.Select, { size: "small", value: mode, onChange: event => setMode(event.target.value) }, Object.entries({
67
+ ...(hasCDS
68
+ ? {
69
+ cds: 'CDS',
70
+ }
71
+ : {}),
72
+ ...(hasCDS
73
+ ? {
74
+ protein: 'Protein',
75
+ }
76
+ : {}),
77
+ ...(hasExonOrCDS
78
+ ? {
79
+ cdna: 'cDNA',
80
+ }
81
+ : {}),
82
+ ...(hasExonOrCDS
83
+ ? {
84
+ gene: `Genomic w/ full introns`,
85
+ }
86
+ : {}),
87
+ ...(hasExonOrCDS
88
+ ? {
89
+ gene_updownstream: `Genomic w/ full introns +/- ${upDownBp}bp up+down stream`,
90
+ }
91
+ : {}),
92
+ ...(hasExonOrCDS
93
+ ? {
94
+ gene_collapsed_intron: `Genomic w/ ${intronBp}bp intron`,
95
+ }
96
+ : {}),
97
+ ...(hasExonOrCDS
98
+ ? {
99
+ gene_updownstream_collapsed_intron: `Genomic w/ ${intronBp}bp intron +/- ${upDownBp}bp up+down stream `,
100
+ }
101
+ : {}),
102
+ ...(!hasExonOrCDS
103
+ ? {
104
+ genomic: 'Genomic',
105
+ }
106
+ : {}),
107
+ ...(!hasExonOrCDS
108
+ ? {
109
+ genomic_sequence_updownstream: `Genomic +/- ${upDownBp}bp up+down stream`,
110
+ }
111
+ : {}),
112
+ }).map(([key, val]) => (react_1.default.createElement(material_1.MenuItem, { key: key, value: key }, val))))),
113
+ react_1.default.createElement(material_1.Button, { className: classes.formControl, variant: "contained", onClick: () => {
100
114
  const ref = seqPanelRef.current;
101
115
  if (ref) {
102
116
  (0, copy_to_clipboard_1.default)(ref.textContent || '', { format: 'text/plain' });
103
- setCopied(true);
104
- setTimeout(() => setCopied(false), 1000);
105
117
  }
106
- } }, copied ? 'Copied to clipboard!' : 'Copy plaintext')),
107
- react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
108
- react_1.default.createElement(material_1.Tooltip, { title: "The 'Copy HTML' function retains the colors from the sequence panel but cannot be pasted into some programs like notepad that only expect plain text" },
109
- react_1.default.createElement(material_1.Button, { className: classes.button, variant: "contained", onClick: () => {
110
- const ref = seqPanelRef.current;
111
- if (!ref) {
112
- return;
113
- }
118
+ } }, "Copy plaintext"),
119
+ react_1.default.createElement(material_1.Button, { className: classes.formControl, variant: "contained", onClick: () => {
120
+ const ref = seqPanelRef.current;
121
+ if (ref) {
114
122
  (0, copy_to_clipboard_1.default)(ref.innerHTML, { format: 'text/html' });
115
- setCopiedHtml(true);
116
- setTimeout(() => setCopiedHtml(false), 1000);
117
- } }, copiedHtml ? 'Copied to clipboard!' : 'Copy HTML'))),
118
- react_1.default.createElement(Settings, { upDownBp: upDownBp, intronBp: intronBp, setIntronBp: setIntronBp, setUpDownBp: setUpDownBp }),
119
- react_1.default.createElement("br", null),
120
- feature.type === 'gene' ? (react_1.default.createElement(material_1.Typography, null, "Note: inspect subfeature sequences for protein/CDS computations")) : null,
121
- error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : !sequence ? (react_1.default.createElement(ui_1.LoadingEllipses, null)) : sequence ? ('error' in sequence ? (react_1.default.createElement(react_1.default.Fragment, null,
122
- react_1.default.createElement(material_1.Typography, { color: "error" }, sequence.error),
123
- react_1.default.createElement(material_1.Button, { variant: "contained", color: "inherit", onClick: () => setForce(true) }, "Force load"))) : (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
124
- react_1.default.createElement(SequencePanel, { ref: seqPanelRef, feature: feature, mode: mode, sequence: sequence, intronBp: intronBp })))) : (react_1.default.createElement(material_1.Typography, null, "No sequence found"))));
125
- }
126
- exports.default = SequenceFeatureDetails;
127
- function Settings({ intronBp, upDownBp, setIntronBp, setUpDownBp, }) {
128
- const { classes } = useStyles();
129
- const [settingsDialogOpen, setSettingsDialogOpen] = (0, react_1.useState)(false);
130
- return (react_1.default.createElement(react_1.default.Fragment, null,
131
- react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
132
- react_1.default.createElement(material_1.IconButton, { onClick: () => setSettingsDialogOpen(true) },
133
- react_1.default.createElement(Settings_1.default, null))),
134
- settingsDialogOpen ? (react_1.default.createElement(react_1.Suspense, { fallback: null },
135
- react_1.default.createElement(SettingsDialog, { handleClose: arg => {
136
- if (arg) {
137
- const { upDownBp, intronBp } = arg;
138
- setIntronBp(intronBp);
139
- setUpDownBp(upDownBp);
140
123
  }
141
- setSettingsDialogOpen(false);
142
- }, upDownBp: upDownBp, intronBp: intronBp }))) : null));
143
- }
124
+ } }, "Copy HTML"),
125
+ react_1.default.createElement(material_1.IconButton, { className: classes.formControl, onClick: () => (0, util_1.getSession)(model).queueDialog(handleClose => [
126
+ SettingsDialog,
127
+ { model: sequenceFeatureDetails, handleClose },
128
+ ]) },
129
+ react_1.default.createElement(Settings_1.default, null))),
130
+ react_1.default.createElement("div", null,
131
+ feature.type === 'gene' ? (react_1.default.createElement(material_1.Typography, null, "Note: inspect subfeature sequences for protein/CDS computations")) : null,
132
+ error ? (react_1.default.createElement(ui_1.ErrorMessage, { error: error })) : !sequence ? (react_1.default.createElement(ui_1.LoadingEllipses, null)) : sequence ? ('error' in sequence ? (react_1.default.createElement(react_1.default.Fragment, null,
133
+ react_1.default.createElement(material_1.Typography, { color: "error" }, sequence.error),
134
+ react_1.default.createElement(material_1.Button, { variant: "contained", color: "inherit", onClick: () => setForce(true) }, "Force load"))) : (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
135
+ react_1.default.createElement(SequencePanel, { ref: seqPanelRef, feature: feature, mode: mode, sequence: sequence, model: sequenceFeatureDetails })))) : (react_1.default.createElement(material_1.Typography, null, "No sequence found")))));
136
+ });
137
+ exports.default = SequenceFeatureDetails;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { BaseFeatureWidgetModel } from '../stateModelFactory';
3
+ import { SimpleFeatureSerialized } from '../../util';
4
+ declare const SequenceFeaturePanel: ({ model, feature, }: {
5
+ model: BaseFeatureWidgetModel;
6
+ feature: SimpleFeatureSerialized;
7
+ }) => React.JSX.Element | null;
8
+ export default SequenceFeaturePanel;
@@ -0,0 +1,67 @@
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
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importStar(require("react"));
30
+ const material_1 = require("@mui/material");
31
+ const mobx_react_1 = require("mobx-react");
32
+ const mui_1 = require("tss-react/mui");
33
+ // locals
34
+ const ui_1 = require("../../ui");
35
+ const util_1 = require("../../util");
36
+ // icons
37
+ const Help_1 = __importDefault(require("@mui/icons-material/Help"));
38
+ // lazies
39
+ const SequenceFeatureDetails = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequenceFeatureDetails'))));
40
+ const HelpDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./dialogs/HelpDialog'))));
41
+ const useStyles = (0, mui_1.makeStyles)()(theme => ({
42
+ formControl: {
43
+ margin: 0,
44
+ },
45
+ container: {
46
+ marginTop: theme.spacing(4),
47
+ marginBottom: theme.spacing(4),
48
+ },
49
+ }));
50
+ // display the stitched-together sequence of a gene's CDS, cDNA, or protein
51
+ // sequence. this is a best effort and weird genomic phenomena could lead these
52
+ // to not be 100% accurate
53
+ const SequenceFeaturePanel = (0, mobx_react_1.observer)(function ({ model, feature, }) {
54
+ const { classes } = useStyles();
55
+ const [shown, setShown] = (0, react_1.useState)(false);
56
+ return !model ? null : (react_1.default.createElement("div", { className: classes.container },
57
+ react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
58
+ react_1.default.createElement(material_1.Button, { variant: "contained", onClick: () => setShown(!shown) }, shown ? 'Hide feature sequence' : 'Show feature sequence')),
59
+ react_1.default.createElement(material_1.IconButton, { onClick: () => (0, util_1.getSession)(model).queueDialog(handleClose => [
60
+ HelpDialog,
61
+ { handleClose },
62
+ ]) },
63
+ react_1.default.createElement(Help_1.default, null)),
64
+ shown ? (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
65
+ react_1.default.createElement(SequenceFeatureDetails, { key: feature.uniqueId, model: model, feature: feature }))) : null));
66
+ });
67
+ exports.default = SequenceFeaturePanel;
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
- import { ParentFeat, SeqState } from '../util';
2
+ import { SimpleFeatureSerialized } from '../../util';
3
+ import { SeqState } from '../util';
4
+ import { SequenceFeatureDetailsModel } from './model';
3
5
  interface SeqPanelProps {
4
6
  sequence: SeqState;
5
- feature: ParentFeat;
7
+ feature: SimpleFeatureSerialized;
6
8
  mode: string;
7
- intronBp?: number;
9
+ model: SequenceFeatureDetailsModel;
8
10
  }
9
11
  declare const SeqPanel: React.ForwardRefExoticComponent<SeqPanelProps & React.RefAttributes<HTMLDivElement>>;
10
12
  export default SeqPanel;
@@ -6,12 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const util_1 = require("../../util");
8
8
  const util_2 = require("../util");
9
- const CDNASequence_1 = __importDefault(require("./CDNASequence"));
10
- const ProteinSequence_1 = __importDefault(require("./ProteinSequence"));
11
- const GenomicSequence_1 = __importDefault(require("./GenomicSequence"));
12
- const CDSSequence_1 = __importDefault(require("./CDSSequence"));
9
+ const CDNASequence_1 = __importDefault(require("./seqtypes/CDNASequence"));
10
+ const ProteinSequence_1 = __importDefault(require("./seqtypes/ProteinSequence"));
11
+ const GenomicSequence_1 = __importDefault(require("./seqtypes/GenomicSequence"));
12
+ const CDSSequence_1 = __importDefault(require("./seqtypes/CDSSequence"));
13
13
  const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
14
- const { feature, mode, intronBp = 10 } = props;
14
+ const { model, feature, mode } = props;
15
15
  let { sequence: { seq, upstream = '', downstream = '' }, } = props;
16
16
  const { subfeatures = [] } = feature;
17
17
  const children = subfeatures
@@ -31,7 +31,7 @@ const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
31
31
  //
32
32
  // http://localhost:3000/?config=test_data%2Fconfig.json&session=share-FUl7G1isvF&password=HXh5Y
33
33
  let cds = (0, util_2.dedupe)(children.filter(sub => sub.type === 'CDS'));
34
- let utr = (0, util_2.dedupe)(children.filter(sub => sub.type.match(/utr/i)));
34
+ let utr = (0, util_2.dedupe)(children.filter(sub => { var _a; return (_a = sub.type) === null || _a === void 0 ? void 0 : _a.match(/utr/i); }));
35
35
  let exons = (0, util_2.dedupe)(children.filter(sub => sub.type === 'exon'));
36
36
  if (!utr.length && cds.length && exons.length) {
37
37
  utr = (0, util_2.calculateUTRs)(cds, exons);
@@ -72,6 +72,6 @@ const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
72
72
  feature.id ||
73
73
  `${feature.refName}:${feature.start + 1}-${feature.end}`}-${mode}\n`),
74
74
  react_1.default.createElement("br", null),
75
- mode === 'genomic' ? (react_1.default.createElement(GenomicSequence_1.default, { sequence: seq })) : mode === 'genomic_sequence_updownstream' ? (react_1.default.createElement(GenomicSequence_1.default, { sequence: seq, upstream: upstream, downstream: downstream })) : mode === 'cds' ? (react_1.default.createElement(CDSSequence_1.default, { cds: cds, sequence: seq })) : mode === 'cdna' ? (react_1.default.createElement(CDNASequence_1.default, { exons: exons, cds: cds, utr: utr, sequence: seq, intronBp: intronBp })) : mode === 'protein' ? (react_1.default.createElement(ProteinSequence_1.default, { cds: cds, codonTable: codonTable, sequence: seq })) : mode === 'gene' ? (react_1.default.createElement(CDNASequence_1.default, { exons: exons, cds: cds, utr: utr, sequence: seq, includeIntrons: true, intronBp: intronBp })) : mode === 'gene_collapsed_intron' ? (react_1.default.createElement(CDNASequence_1.default, { exons: exons, cds: cds, sequence: seq, utr: utr, includeIntrons: true, collapseIntron: true, intronBp: intronBp })) : mode === 'gene_updownstream' ? (react_1.default.createElement(CDNASequence_1.default, { exons: exons, cds: cds, sequence: seq, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true, intronBp: intronBp })) : mode === 'gene_updownstream_collapsed_intron' ? (react_1.default.createElement(CDNASequence_1.default, { exons: exons, cds: cds, sequence: seq, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true, collapseIntron: true, intronBp: intronBp })) : (react_1.default.createElement("div", null, "Unknown type")))));
75
+ mode === 'genomic' ? (react_1.default.createElement(GenomicSequence_1.default, { sequence: seq })) : mode === 'genomic_sequence_updownstream' ? (react_1.default.createElement(GenomicSequence_1.default, { sequence: seq, upstream: upstream, downstream: downstream })) : mode === 'cds' ? (react_1.default.createElement(CDSSequence_1.default, { cds: cds, sequence: seq })) : mode === 'cdna' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, cds: cds, utr: utr, sequence: seq })) : mode === 'protein' ? (react_1.default.createElement(ProteinSequence_1.default, { cds: cds, codonTable: codonTable, sequence: seq })) : mode === 'gene' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, cds: cds, utr: utr, sequence: seq, includeIntrons: true })) : mode === 'gene_collapsed_intron' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, cds: cds, sequence: seq, utr: utr, includeIntrons: true, collapseIntron: true })) : mode === 'gene_updownstream' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, cds: cds, sequence: seq, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true })) : mode === 'gene_updownstream_collapsed_intron' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, cds: cds, sequence: seq, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true, collapseIntron: true })) : (react_1.default.createElement("div", null, "Unknown type")))));
76
76
  });
77
77
  exports.default = SeqPanel;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { SequenceFeatureDetailsModel } from '../model';
3
+ declare const SequenceFeatureSettingsDialog: ({ handleClose, model, }: {
4
+ handleClose: () => void;
5
+ model: SequenceFeatureDetailsModel;
6
+ }) => React.JSX.Element;
7
+ export default SequenceFeatureSettingsDialog;
@@ -27,6 +27,7 @@ const react_1 = __importStar(require("react"));
27
27
  const material_1 = require("@mui/material");
28
28
  const ui_1 = require("@jbrowse/core/ui");
29
29
  const mui_1 = require("tss-react/mui");
30
+ const mobx_react_1 = require("mobx-react");
30
31
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
31
32
  formElt: {
32
33
  margin: theme.spacing(3),
@@ -36,21 +37,30 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
36
37
  width: '80em',
37
38
  },
38
39
  }));
39
- function SequenceFeatureSettingsDialog({ handleClose, intronBp: intronBpArg, upDownBp: upDownBpArg, }) {
40
+ const SequenceFeatureSettingsDialog = (0, mobx_react_1.observer)(function ({ handleClose, model, }) {
40
41
  const { classes } = useStyles();
41
- const [intronBp, setIntronBp] = (0, react_1.useState)(`${intronBpArg}`);
42
- const [upDownBp, setUpDownBp] = (0, react_1.useState)(`${upDownBpArg}`);
42
+ const [intronBp, setIntronBp] = (0, react_1.useState)(`${model.intronBp}`);
43
+ const [upDownBp, setUpDownBp] = (0, react_1.useState)(`${model.upDownBp}`);
43
44
  const intronBpValid = !Number.isNaN(+intronBp);
44
45
  const upDownBpValid = !Number.isNaN(+upDownBp);
45
46
  return (react_1.default.createElement(ui_1.Dialog, { maxWidth: "xl", open: true, onClose: () => handleClose(), title: "Feature sequence settings" },
46
47
  react_1.default.createElement(material_1.DialogContent, { className: classes.dialogContent },
47
- react_1.default.createElement(material_1.TextField, { label: "Number of intronic bases around splice site to display", className: classes.formElt, value: intronBp, helperText: !intronBpValid ? 'Not a number' : '', error: !intronBpValid, onChange: event => setIntronBp(event.target.value) }),
48
- react_1.default.createElement(material_1.TextField, { label: "Number of bases up/down stream of feature to display", className: classes.formElt, value: upDownBp, helperText: !upDownBpValid ? 'Not a number' : '', error: !upDownBpValid, onChange: event => setUpDownBp(event.target.value) })),
48
+ react_1.default.createElement("div", null,
49
+ react_1.default.createElement(material_1.TextField, { label: "Number of intronic bases around splice site to display", className: classes.formElt, value: intronBp, helperText: !intronBpValid ? 'Not a number' : '', error: !intronBpValid, onChange: event => setIntronBp(event.target.value) })),
50
+ react_1.default.createElement("div", null,
51
+ react_1.default.createElement(material_1.TextField, { label: "Number of bases up/down stream of feature to display", className: classes.formElt, value: upDownBp, helperText: !upDownBpValid ? 'Not a number' : '', error: !upDownBpValid, onChange: event => setUpDownBp(event.target.value) })),
52
+ react_1.default.createElement("div", null,
53
+ react_1.default.createElement(material_1.FormControl, null,
54
+ react_1.default.createElement(material_1.FormLabel, null, "Sequence capitalization"),
55
+ react_1.default.createElement(material_1.RadioGroup, { value: model.upperCaseCDS ? 'cds' : 'unchanged', onChange: e => model.setUpperCaseCDS(e.target.value === 'cds') },
56
+ react_1.default.createElement(material_1.FormControlLabel, { value: "cds", control: react_1.default.createElement(material_1.Radio, null), label: "Capitalize CDS and lower case everything else" }),
57
+ react_1.default.createElement(material_1.FormControlLabel, { value: "unchanged", control: react_1.default.createElement(material_1.Radio, null), label: "Capitalization from reference genome sequence" }))))),
49
58
  react_1.default.createElement(material_1.DialogActions, null,
50
- react_1.default.createElement(material_1.Button, { onClick: () => handleClose({
51
- upDownBp: +upDownBp,
52
- intronBp: +intronBp,
53
- }), disabled: !intronBpValid || !upDownBpValid, color: "primary", variant: "contained" }, "Submit"),
59
+ react_1.default.createElement(material_1.Button, { onClick: () => {
60
+ model.setIntronBp(+intronBp);
61
+ model.setUpDownBp(+upDownBp);
62
+ handleClose();
63
+ }, disabled: !intronBpValid || !upDownBpValid, color: "primary", variant: "contained" }, "Submit"),
54
64
  react_1.default.createElement(material_1.Button, { onClick: () => handleClose(), color: "secondary", autoFocus: true, variant: "contained" }, "Cancel"))));
55
- }
65
+ });
56
66
  exports.default = SequenceFeatureSettingsDialog;
@@ -10,9 +10,8 @@ function useFeatureSequence(model, feature, upDownBp, forceLoad) {
10
10
  const [error, setError] = (0, react_1.useState)();
11
11
  (0, react_1.useEffect)(() => {
12
12
  var _a;
13
- let finished = false;
14
13
  if (!model) {
15
- return () => { };
14
+ return;
16
15
  }
17
16
  const { assemblyManager, rpcManager } = (0, util_1.getSession)(model);
18
17
  const [assemblyName] = ((_a = model.view) === null || _a === void 0 ? void 0 : _a.assemblyNames) || [];
@@ -54,9 +53,7 @@ function useFeatureSequence(model, feature, upDownBp, forceLoad) {
54
53
  const seq = await fetchSeq(start, end, refName);
55
54
  const up = await fetchSeq(Math.max(0, b), start, refName);
56
55
  const down = await fetchSeq(end, e, refName);
57
- if (!finished) {
58
- setSequence({ seq, upstream: up, downstream: down });
59
- }
56
+ setSequence({ seq, upstream: up, downstream: down });
60
57
  }
61
58
  }
62
59
  catch (e) {
@@ -64,9 +61,6 @@ function useFeatureSequence(model, feature, upDownBp, forceLoad) {
64
61
  setError(e);
65
62
  }
66
63
  })();
67
- return () => {
68
- finished = true;
69
- };
70
64
  }, [feature, model, upDownBp, forceLoad]);
71
65
  return { sequence, error };
72
66
  }
@@ -1,3 +1 @@
1
- import React from 'react';
2
- import { BaseProps } from './../types';
3
- export default function SequenceFeaturePanel({ model, feature }: BaseProps): React.JSX.Element | null;
1
+ export { default } from './SequenceFeaturePanel';
@@ -1,72 +1,8 @@
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
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const react_1 = __importStar(require("react"));
30
- const material_1 = require("@mui/material");
31
- const mui_1 = require("tss-react/mui");
32
- const mobx_react_1 = require("mobx-react");
33
- const ui_1 = require("../../ui");
34
- const util_1 = require("../../util");
35
- // icons
36
- const Help_1 = __importDefault(require("@mui/icons-material/Help"));
37
- // lazies
38
- const HelpDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequenceHelpDialog'))));
39
- const SequenceFeatureDetails = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequenceFeatureDetails'))));
40
- const useStyles = (0, mui_1.makeStyles)()(theme => ({
41
- formControl: {
42
- margin: 0,
43
- },
44
- container: {
45
- marginTop: theme.spacing(4),
46
- marginBottom: theme.spacing(4),
47
- },
48
- }));
49
- const SequenceFeatureDetailsHelpButton = (0, mobx_react_1.observer)(function ({ model, }) {
50
- const { classes } = useStyles();
51
- const session = (0, util_1.getSession)(model);
52
- return (react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
53
- react_1.default.createElement(material_1.IconButton, { onClick: () => session.queueDialog(handleClose => [HelpDialog, { handleClose }]) },
54
- react_1.default.createElement(Help_1.default, null))));
55
- });
56
- // display the stitched-together sequence of a gene's CDS, cDNA, or protein
57
- // sequence. this is a best effort and weird genomic phenomena could lead these
58
- // to not be 100% accurate
59
- function SequenceFeaturePanel({ model, feature }) {
60
- const { classes } = useStyles();
61
- const [shown, setShown] = (0, react_1.useState)(false);
62
- return !model ? null : (react_1.default.createElement("div", { className: classes.container },
63
- react_1.default.createElement(material_1.Button, { variant: "contained", onClick: () => setShown(!shown) }, shown ? 'Hide feature sequence' : 'Show feature sequence'),
64
- react_1.default.createElement(SequenceFeatureDetailsHelpButton, { model: model }),
65
- shown ? (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
66
- react_1.default.createElement(SequenceFeatureDetails
67
- /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion */
68
- , {
69
- /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion */
70
- key: feature.uniqueId, model: model, feature: feature }))) : null));
71
- }
72
- exports.default = SequenceFeaturePanel;
6
+ exports.default = void 0;
7
+ var SequenceFeaturePanel_1 = require("./SequenceFeaturePanel");
8
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(SequenceFeaturePanel_1).default; } });
@@ -0,0 +1,14 @@
1
+ import { Instance } from 'mobx-state-tree';
2
+ export declare function SequenceFeatureDetailsF(): import("mobx-state-tree").IModelType<{}, {
3
+ intronBp: number;
4
+ upDownBp: number;
5
+ upperCaseCDS: boolean;
6
+ } & {
7
+ setUpDownBp(f: number): void;
8
+ setIntronBp(f: number): void;
9
+ setUpperCaseCDS(f: boolean): void;
10
+ } & {
11
+ afterAttach(): void;
12
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
13
+ export type SequenceFeatureDetailsStateModel = ReturnType<typeof SequenceFeatureDetailsF>;
14
+ export type SequenceFeatureDetailsModel = Instance<SequenceFeatureDetailsStateModel>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SequenceFeatureDetailsF = void 0;
4
+ const mobx_state_tree_1 = require("mobx-state-tree");
5
+ const mobx_1 = require("mobx");
6
+ // locals
7
+ const util_1 = require("../../util");
8
+ function SequenceFeatureDetailsF() {
9
+ return mobx_state_tree_1.types
10
+ .model('SequenceFeatureDetails', {})
11
+ .volatile(() => {
12
+ var _a, _b;
13
+ return ({
14
+ intronBp: +((_a = (0, util_1.localStorageGetItem)('sequenceFeatureDetails-intronBp')) !== null && _a !== void 0 ? _a : 10),
15
+ upDownBp: +((_b = (0, util_1.localStorageGetItem)('sequenceFeatureDetails-upDownBp')) !== null && _b !== void 0 ? _b : 100),
16
+ upperCaseCDS: Boolean(JSON.parse((0, util_1.localStorageGetItem)('sequenceFeatureDetails-upperCaseCDS') || 'true')),
17
+ });
18
+ })
19
+ .actions(self => ({
20
+ setUpDownBp(f) {
21
+ self.upDownBp = f;
22
+ },
23
+ setIntronBp(f) {
24
+ self.intronBp = f;
25
+ },
26
+ setUpperCaseCDS(f) {
27
+ self.upperCaseCDS = f;
28
+ },
29
+ }))
30
+ .actions(self => ({
31
+ afterAttach() {
32
+ (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
33
+ (0, util_1.localStorageSetItem)('sequenceFeatureDetails-upDownBp', JSON.stringify(self.upDownBp));
34
+ (0, util_1.localStorageSetItem)('sequenceFeatureDetails-intronBp', JSON.stringify(self.intronBp));
35
+ (0, util_1.localStorageSetItem)('sequenceFeatureDetails-upperCaseCDS', JSON.stringify(self.upperCaseCDS));
36
+ }));
37
+ },
38
+ }));
39
+ }
40
+ exports.SequenceFeatureDetailsF = SequenceFeatureDetailsF;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { Feat } from '../../util';
3
+ import { SequenceFeatureDetailsModel } from '../model';
4
+ declare const CDNASequence: ({ utr, cds, exons, sequence, upstream, downstream, includeIntrons, collapseIntron, model, }: {
5
+ utr: Feat[];
6
+ cds: Feat[];
7
+ exons: Feat[];
8
+ sequence: string;
9
+ upstream?: string;
10
+ downstream?: string;
11
+ includeIntrons?: boolean;
12
+ collapseIntron?: boolean;
13
+ model: SequenceFeatureDetailsModel;
14
+ }) => React.JSX.Element;
15
+ export default CDNASequence;