@jbrowse/core 2.11.2 → 2.12.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 (127) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail/ArrayValue.js +1 -1
  2. package/BaseFeatureWidget/BaseFeatureDetail/Attributes.js +1 -1
  3. package/BaseFeatureWidget/BaseFeatureDetail/BasicValue.js +1 -1
  4. package/BaseFeatureWidget/BaseFeatureDetail/DataGridDetails.js +17 -22
  5. package/BaseFeatureWidget/BaseFeatureDetail/FieldName.js +1 -1
  6. package/BaseFeatureWidget/BaseFeatureDetail/SimpleField.js +1 -1
  7. package/BaseFeatureWidget/BaseFeatureDetail/UriField.js +1 -1
  8. package/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -6
  9. package/BaseFeatureWidget/BaseFeatureDetail/util.js +4 -5
  10. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeatureDetails.js +24 -85
  11. package/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.js +2 -2
  12. package/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.d.ts +3 -4
  13. package/BaseFeatureWidget/SequenceFeatureDetails/SequencePanel.js +55 -24
  14. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/HelpDialog.js +1 -1
  15. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceDialog.d.ts +9 -0
  16. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceDialog.js +69 -0
  17. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceFeatureMenu.d.ts +9 -0
  18. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceFeatureMenu.js +126 -0
  19. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceTypeSelector.d.ts +6 -0
  20. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SequenceTypeSelector.js +68 -0
  21. package/BaseFeatureWidget/SequenceFeatureDetails/dialogs/SettingsDialog.js +19 -10
  22. package/BaseFeatureWidget/SequenceFeatureDetails/hooks.js +1 -2
  23. package/BaseFeatureWidget/SequenceFeatureDetails/model.d.ts +47 -0
  24. package/BaseFeatureWidget/SequenceFeatureDetails/model.js +84 -11
  25. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDNASequence.d.ts +3 -1
  26. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDNASequence.js +76 -19
  27. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDSSequence.d.ts +5 -2
  28. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/CDSSequence.js +12 -3
  29. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/GenomicSequence.d.ts +7 -2
  30. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/GenomicSequence.js +51 -5
  31. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/ProteinSequence.d.ts +5 -2
  32. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/ProteinSequence.js +12 -3
  33. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/SequenceDisplay.d.ts +11 -0
  34. package/BaseFeatureWidget/SequenceFeatureDetails/seqtypes/SequenceDisplay.js +30 -0
  35. package/BaseFeatureWidget/SequenceFeatureDetails/util.d.ts +11 -0
  36. package/BaseFeatureWidget/SequenceFeatureDetails/util.js +42 -0
  37. package/BaseFeatureWidget/stateModelFactory.d.ts +26 -0
  38. package/BaseFeatureWidget/stateModelFactory.js +1 -2
  39. package/BaseFeatureWidget/util.d.ts +5 -5
  40. package/BaseFeatureWidget/util.js +6 -7
  41. package/PluginLoader.js +4 -5
  42. package/PluginManager.d.ts +7 -17
  43. package/ReExports/modules.d.ts +7 -16
  44. package/TextSearch/TextSearchManager.d.ts +6 -2
  45. package/assemblyManager/assembly.js +1 -1
  46. package/assemblyManager/assemblyManager.d.ts +9 -82
  47. package/configuration/configurationSchema.d.ts +7 -1
  48. package/configuration/configurationSchema.js +2 -3
  49. package/configuration/configurationSlot.js +1 -1
  50. package/configuration/util.d.ts +1 -1
  51. package/configuration/util.js +7 -8
  52. package/data_adapters/BaseAdapter/util.js +5 -6
  53. package/data_adapters/CytobandAdapter/CytobandAdapter.d.ts +0 -1
  54. package/data_adapters/CytobandAdapter/CytobandAdapter.js +1 -2
  55. package/data_adapters/CytobandAdapter/index.js +1 -1
  56. package/data_adapters/dataAdapterCache.js +4 -5
  57. package/package.json +4 -2
  58. package/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +1 -3
  59. package/pluggableElementTypes/models/BaseDisplayModel.d.ts +3 -3
  60. package/pluggableElementTypes/models/BaseTrackModel.d.ts +6 -2
  61. package/pluggableElementTypes/models/BaseTrackModel.js +2 -3
  62. package/pluggableElementTypes/models/InternetAccountModel.d.ts +13 -13
  63. package/pluggableElementTypes/models/baseTrackConfig.js +1 -2
  64. package/rpc/BaseRpcDriver.js +1 -2
  65. package/rpc/methods/util.js +1 -2
  66. package/rpc/remoteAbortSignals.js +5 -6
  67. package/stories/JBrowseCore.stories.d.ts +5 -0
  68. package/stories/JBrowseCore.stories.js +10 -0
  69. package/stories/examples/WithSequencePanel.d.ts +7 -0
  70. package/stories/examples/WithSequencePanel.js +42 -0
  71. package/stories/examples/index.d.ts +1 -0
  72. package/stories/examples/index.js +17 -0
  73. package/stories/examples/util.d.ts +33 -0
  74. package/stories/examples/util.js +235 -0
  75. package/tsconfig.build.tsbuildinfo +1 -1
  76. package/ui/ColorPicker.js +3 -3
  77. package/ui/Dialog.js +2 -1
  78. package/ui/ErrorMessageStackTraceDialog.js +1 -1
  79. package/ui/FactoryResetDialog.js +1 -1
  80. package/ui/FatalErrorDialog.js +1 -1
  81. package/ui/Icons.js +9 -10
  82. package/ui/LoadingEllipses.js +1 -1
  83. package/ui/Logo.js +2 -3
  84. package/ui/Menu.js +1 -2
  85. package/ui/RedErrorMessageBox.js +1 -1
  86. package/ui/SanitizedHTML.js +1 -1
  87. package/ui/SnackbarModel.js +1 -1
  88. package/ui/theme.js +3 -3
  89. package/util/Base1DUtils.d.ts +1 -1
  90. package/util/Base1DUtils.js +7 -12
  91. package/util/Base1DViewModel.d.ts +6 -17
  92. package/util/Base1DViewModel.js +6 -12
  93. package/util/aborting.js +5 -6
  94. package/util/analytics.js +3 -4
  95. package/util/blobToDataURL.js +1 -2
  96. package/util/calculateDynamicBlocks.js +1 -1
  97. package/util/calculateStaticBlocks.js +1 -1
  98. package/util/color/cssColorsLevel4.js +2 -3
  99. package/util/color/index.js +4 -4
  100. package/util/dedupe.js +1 -2
  101. package/util/formatFastaStrings.js +2 -3
  102. package/util/idMaker.js +1 -1
  103. package/util/index.d.ts +3 -3
  104. package/util/index.js +70 -71
  105. package/util/io/RemoteFileWithRangeCache.d.ts +0 -1
  106. package/util/io/RemoteFileWithRangeCache.js +2 -2
  107. package/util/io/index.js +4 -4
  108. package/util/jexl.js +1 -1
  109. package/util/jexlStrings.js +1 -2
  110. package/util/map-obj.js +1 -1
  111. package/util/mst-reflection.js +6 -7
  112. package/util/offscreenCanvasPonyfill.js +2 -2
  113. package/util/offscreenCanvasUtils.js +3 -4
  114. package/util/range.js +3 -4
  115. package/util/rxjs.js +1 -2
  116. package/util/simpleFeature.js +1 -2
  117. package/util/stats.js +5 -6
  118. package/util/tracks.d.ts +3 -2
  119. package/util/tracks.js +24 -20
  120. package/util/types/index.d.ts +4 -1
  121. package/util/types/index.js +23 -23
  122. package/util/types/mst.d.ts +0 -1
  123. package/util/useMeasure.d.ts +2 -3
  124. package/util/useMeasure.js +1 -1
  125. package/util/when.js +2 -3
  126. package/ui/useResizeBar.d.ts +0 -5
  127. package/ui/useResizeBar.js +0 -22
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = ArrayValue;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const is_object_1 = __importDefault(require("is-object"));
8
9
  const mui_1 = require("tss-react/mui");
@@ -41,4 +42,3 @@ function ArrayValue({ name, value, description, prefix = [], }) {
41
42
  react_1.default.createElement(BasicValue_1.default, { value: val }))))));
42
43
  }
43
44
  }
44
- exports.default = ArrayValue;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = Attributes;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const is_object_1 = __importDefault(require("is-object"));
8
9
  // locals
@@ -49,4 +50,3 @@ function Attributes(props) {
49
50
  }
50
51
  })));
51
52
  }
52
- exports.default = Attributes;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = BasicValue;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const mui_1 = require("tss-react/mui");
8
9
  const is_object_1 = __importDefault(require("is-object"));
@@ -23,4 +24,3 @@ function BasicValue({ value }) {
23
24
  const isLink = `${value}`.match(/^https?:\/\//);
24
25
  return (react_1.default.createElement("div", { className: classes.fieldValue }, react_1.default.isValidElement(value) ? (value) : isLink ? (react_1.default.createElement(material_1.Link, { href: `${value}` }, `${value}`)) : (react_1.default.createElement(ui_1.SanitizedHTML, { html: (0, is_object_1.default)(value) ? JSON.stringify(value) : String(value) }))));
25
26
  }
26
- exports.default = BasicValue;
@@ -26,6 +26,7 @@ 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.default = DataGridDetails;
29
30
  const react_1 = __importStar(require("react"));
30
31
  const mui_1 = require("tss-react/mui");
31
32
  const x_data_grid_1 = require("@mui/x-data-grid");
@@ -36,8 +37,7 @@ const FieldName_1 = __importDefault(require("./FieldName"));
36
37
  const ui_1 = require("../../ui");
37
38
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
38
39
  margin: {
39
- margin: theme.spacing(1),
40
- width: '100%',
40
+ marginBottom: theme.spacing(4),
41
41
  },
42
42
  cell: {
43
43
  whiteSpace: 'nowrap',
@@ -76,29 +76,24 @@ function DataGridDetails({ value, prefix, name, }) {
76
76
  }
77
77
  const widths = colNames.map(e => (0, util_1.measureGridWidth)(rows.map(r => r[e])));
78
78
  if (unionKeys.size < keys.length + 5) {
79
- return (react_1.default.createElement(react_1.default.Fragment, null,
79
+ return (react_1.default.createElement("div", { className: classes.margin },
80
80
  react_1.default.createElement(FieldName_1.default, { prefix: prefix, name: name }),
81
81
  react_1.default.createElement(material_1.FormControlLabel, { control: react_1.default.createElement(material_1.Checkbox, { checked: checked, onChange: event => setChecked(event.target.checked) }), label: react_1.default.createElement(material_1.Typography, { variant: "body2" }, "Show options") }),
82
- react_1.default.createElement("div", { className: classes.margin },
83
- react_1.default.createElement(x_data_grid_1.DataGrid, { disableRowSelectionOnClick: true,
84
- // @ts-expect-error the rows gets confused by the renderCell of the
85
- // columns below
86
- rows: rows, rowCount: 25, rowHeight: 25, columnHeaderHeight: 35, hideFooter: rows.length < 25, slots: { toolbar: checked ? x_data_grid_1.GridToolbar : null }, slotProps: {
87
- toolbar: {
88
- printOptions: {
89
- disableToolbarButton: true,
90
- },
91
- },
92
- }, columns: colNames.map((val, index) => ({
93
- field: val,
94
- renderCell: params => {
95
- const value = params.value;
96
- return (react_1.default.createElement("div", { className: classes.cell },
97
- react_1.default.createElement(ui_1.SanitizedHTML, { html: (0, util_1.getStr)(value) })));
82
+ react_1.default.createElement(x_data_grid_1.DataGrid, { disableRowSelectionOnClick: true, rows: rows, rowCount: 25, rowHeight: 25, columnHeaderHeight: 35, hideFooter: rows.length < 25, slots: { toolbar: checked ? x_data_grid_1.GridToolbar : null }, slotProps: {
83
+ toolbar: {
84
+ printOptions: {
85
+ disableToolbarButton: true,
98
86
  },
99
- width: widths[index],
100
- })) }))));
87
+ },
88
+ }, columns: colNames.map((val, index) => ({
89
+ field: val,
90
+ renderCell: params => {
91
+ const value = params.value;
92
+ return (react_1.default.createElement("div", { className: classes.cell },
93
+ react_1.default.createElement(ui_1.SanitizedHTML, { html: (0, util_1.getStr)(value) })));
94
+ },
95
+ width: widths[index],
96
+ })) })));
101
97
  }
102
98
  return null;
103
99
  }
104
- exports.default = DataGridDetails;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = FieldName;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const material_1 = require("@mui/material");
8
9
  const mui_1 = require("tss-react/mui");
@@ -28,4 +29,3 @@ function FieldName({ description, name, width, prefix = [], }) {
28
29
  return description ? (react_1.default.createElement(material_1.Tooltip, { title: description, placement: "left" },
29
30
  react_1.default.createElement("div", { className: cx(classes.fieldDescription, classes.fieldName) }, val))) : (react_1.default.createElement("div", { className: classes.fieldName, style: { width: width } }, val));
30
31
  }
31
- exports.default = FieldName;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = SimpleField;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const mui_1 = require("tss-react/mui");
8
9
  const FieldName_1 = __importDefault(require("./FieldName"));
@@ -19,4 +20,3 @@ function SimpleField({ name, value, description, prefix, width, }) {
19
20
  react_1.default.createElement(FieldName_1.default, { prefix: prefix, description: description, name: name, width: width }),
20
21
  react_1.default.createElement(BasicValue_1.default, { value: value }))) : null;
21
22
  }
22
- exports.default = SimpleField;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = UriField;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const FieldName_1 = __importDefault(require("./FieldName"));
8
9
  const mui_1 = require("tss-react/mui");
@@ -27,4 +28,3 @@ function UriField({ value, prefix, name, }) {
27
28
  react_1.default.createElement(FieldName_1.default, { prefix: prefix, name: name }),
28
29
  react_1.default.createElement(BasicValue_1.default, { value: href })));
29
30
  }
30
- exports.default = UriField;
@@ -26,7 +26,9 @@ 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.Attributes = exports.FeatureDetails = exports.BaseAttributes = exports.BaseCoreDetails = exports.BaseCard = void 0;
29
+ exports.Attributes = exports.BaseAttributes = exports.BaseCoreDetails = void 0;
30
+ exports.BaseCard = BaseCard;
31
+ exports.FeatureDetails = FeatureDetails;
30
32
  /* eslint-disable @typescript-eslint/no-explicit-any */
31
33
  const react_1 = __importStar(require("react"));
32
34
  const react_error_boundary_1 = require("react-error-boundary");
@@ -69,12 +71,9 @@ function BaseCard({ children, title, defaultExpanded = true, }) {
69
71
  const [expanded, setExpanded] = (0, react_1.useState)(defaultExpanded);
70
72
  return (react_1.default.createElement(material_1.Accordion, { expanded: expanded, onChange: () => setExpanded(s => !s), TransitionProps: { unmountOnExit: true, timeout: 150 } },
71
73
  react_1.default.createElement(material_1.AccordionSummary, { expandIcon: react_1.default.createElement(ExpandMore_1.default, { className: classes.expandIcon }) },
72
- react_1.default.createElement(material_1.Typography, { variant: "button" },
73
- " ",
74
- title)),
74
+ react_1.default.createElement(material_1.Typography, { variant: "button" }, title)),
75
75
  react_1.default.createElement(material_1.AccordionDetails, { className: classes.expansionPanelDetails }, children)));
76
76
  }
77
- exports.BaseCard = BaseCard;
78
77
  function Position(props) {
79
78
  const { feature } = props;
80
79
  const strand = feature.strand;
@@ -160,7 +159,6 @@ function FeatureDetails(props) {
160
159
  react_1.default.createElement(ExtraPanel.Component, { ...props })))) : null,
161
160
  depth < maxDepth && (subfeatures === null || subfeatures === void 0 ? void 0 : subfeatures.length) ? (react_1.default.createElement(BaseCard, { title: "Subfeatures", defaultExpanded: depth < 1 }, subfeatures.map((sub, idx) => (react_1.default.createElement(FeatureDetails, { key: JSON.stringify(sub), feature: { ...sub, uniqueId: `${uniqueId}_${idx}` }, model: model, depth: depth + 1 }))))) : null));
162
161
  }
163
- exports.FeatureDetails = FeatureDetails;
164
162
  const BaseFeatureDetail = (0, mobx_react_1.observer)(function ({ model }) {
165
163
  const { error, featureData } = model;
166
164
  if (error) {
@@ -3,24 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.accessNested = exports.generateMaxWidth = exports.generateTitle = exports.isEmpty = void 0;
6
+ exports.isEmpty = isEmpty;
7
+ exports.generateTitle = generateTitle;
8
+ exports.generateMaxWidth = generateMaxWidth;
9
+ exports.accessNested = accessNested;
7
10
  const is_object_1 = __importDefault(require("is-object"));
8
11
  const util_1 = require("../../util");
9
12
  const util_2 = require("../util");
10
13
  function isEmpty(obj) {
11
14
  return Object.keys(obj).length === 0;
12
15
  }
13
- exports.isEmpty = isEmpty;
14
16
  function generateTitle(name, id, type) {
15
17
  return [(0, util_2.ellipses)(`${name}` || `${id}`), `${type}`]
16
18
  .filter(f => !!f)
17
19
  .join(' - ');
18
20
  }
19
- exports.generateTitle = generateTitle;
20
21
  function generateMaxWidth(array, prefix) {
21
22
  return (Math.ceil((0, util_1.max)(array.map(key => (0, util_1.measureText)([...prefix, key[0]].join('.'), 12)))) + 10);
22
23
  }
23
- exports.generateMaxWidth = generateMaxWidth;
24
24
  // pick using a path from an object, similar to _.get from lodash with special
25
25
  // logic for Descriptions from e.g. VCF headers
26
26
  //
@@ -39,4 +39,3 @@ function accessNested(arr, obj = {}) {
39
39
  ? obj2.Description
40
40
  : undefined;
41
41
  }
42
- exports.accessNested = accessNested;
@@ -28,110 +28,49 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const react_1 = __importStar(require("react"));
30
30
  const material_1 = require("@mui/material");
31
- const mui_1 = require("tss-react/mui");
32
31
  const mobx_react_1 = require("mobx-react");
33
- const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
34
32
  // locals
35
33
  const hooks_1 = require("./hooks");
36
34
  const ui_1 = require("../../ui");
37
- const util_1 = require("../../util");
38
35
  // icons
39
- const Settings_1 = __importDefault(require("@mui/icons-material/Settings"));
36
+ const SequenceFeatureMenu_1 = __importDefault(require("./dialogs/SequenceFeatureMenu"));
37
+ const SequenceTypeSelector_1 = __importDefault(require("./dialogs/SequenceTypeSelector"));
40
38
  // lazies
41
39
  const SequencePanel = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SequencePanel'))));
42
- const SettingsDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./dialogs/SettingsDialog'))));
43
- const useStyles = (0, mui_1.makeStyles)()({
44
- formControl: {
45
- margin: 0,
46
- marginLeft: 4,
47
- },
48
- });
40
+ const SequenceDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./dialogs/SequenceDialog'))));
49
41
  // set the key on this component to feature.id to clear state after new feature
50
42
  // is selected
51
43
  const SequenceFeatureDetails = (0, mobx_react_1.observer)(function ({ model, feature, }) {
52
- var _a, _b;
53
44
  const { sequenceFeatureDetails } = model;
54
- const { intronBp, upDownBp } = sequenceFeatureDetails;
55
- const { classes } = useStyles();
45
+ const { upDownBp } = sequenceFeatureDetails;
56
46
  const seqPanelRef = (0, react_1.useRef)(null);
47
+ const [openInDialog, setOpenInDialog] = (0, react_1.useState)(false);
57
48
  const [force, setForce] = (0, react_1.useState)(false);
58
- const hasCDS = (_a = feature.subfeatures) === null || _a === void 0 ? void 0 : _a.some(sub => sub.type === 'CDS');
59
- const hasExon = (_b = feature.subfeatures) === null || _b === void 0 ? void 0 : _b.some(sub => sub.type === 'exon');
60
- const hasExonOrCDS = hasExon || hasCDS;
61
49
  const { sequence, error } = (0, hooks_1.useFeatureSequence)(model, feature, upDownBp, force);
62
- const [mode, setMode] = (0, react_1.useState)(hasCDS ? 'cds' : hasExon ? 'cdna' : 'genomic');
50
+ (0, react_1.useEffect)(() => {
51
+ sequenceFeatureDetails.setFeature(feature);
52
+ }, [sequenceFeatureDetails, feature]);
63
53
  return (react_1.default.createElement(react_1.default.Fragment, null,
64
54
  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: () => {
114
- const ref = seqPanelRef.current;
115
- if (ref) {
116
- (0, copy_to_clipboard_1.default)(ref.textContent || '', { format: 'text/plain' });
117
- }
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) {
122
- (0, copy_to_clipboard_1.default)(ref.innerHTML, { format: 'text/html' });
123
- }
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,
55
+ react_1.default.createElement(SequenceTypeSelector_1.default, { model: sequenceFeatureDetails }),
56
+ react_1.default.createElement(SequenceFeatureMenu_1.default, { ref: seqPanelRef, model: sequenceFeatureDetails, extraItems: [
57
+ {
58
+ label: 'Open in dialog',
59
+ onClick: () => {
60
+ // this is given a setTimeout because it allows the menu to
61
+ // close before dialog opens
62
+ setTimeout(() => setOpenInDialog(true), 1);
63
+ },
64
+ },
65
+ ] })),
66
+ openInDialog ? (react_1.default.createElement("div", null,
67
+ "Open in dialog...",
68
+ react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
69
+ react_1.default.createElement(SequenceDialog, { model: model, feature: feature, handleClose: () => setOpenInDialog(false) })))) : (react_1.default.createElement("div", null,
131
70
  feature.type === 'gene' ? (react_1.default.createElement(material_1.Typography, null, "Note: inspect subfeature sequences for protein/CDS computations")) : null,
132
71
  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
72
  react_1.default.createElement(material_1.Typography, { color: "error" }, sequence.error),
134
73
  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")))));
74
+ react_1.default.createElement(SequencePanel, { ref: seqPanelRef, feature: feature, sequence: sequence, model: sequenceFeatureDetails })))) : (react_1.default.createElement(material_1.Typography, null, "No sequence found"))))));
136
75
  });
137
76
  exports.default = SequenceFeatureDetails;
@@ -53,7 +53,7 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
53
53
  const SequenceFeaturePanel = (0, mobx_react_1.observer)(function ({ model, feature, }) {
54
54
  const { classes } = useStyles();
55
55
  const [shown, setShown] = (0, react_1.useState)(false);
56
- return !model ? null : (react_1.default.createElement("div", { className: classes.container },
56
+ return model ? (react_1.default.createElement("div", { className: classes.container },
57
57
  react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
58
58
  react_1.default.createElement(material_1.Button, { variant: "contained", onClick: () => setShown(!shown) }, shown ? 'Hide feature sequence' : 'Show feature sequence')),
59
59
  react_1.default.createElement(material_1.IconButton, { onClick: () => (0, util_1.getSession)(model).queueDialog(handleClose => [
@@ -62,6 +62,6 @@ const SequenceFeaturePanel = (0, mobx_react_1.observer)(function ({ model, featu
62
62
  ]) },
63
63
  react_1.default.createElement(Help_1.default, null)),
64
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));
65
+ react_1.default.createElement(SequenceFeatureDetails, { key: feature.uniqueId, model: model, feature: feature }))) : null)) : null;
66
66
  });
67
67
  exports.default = SequenceFeaturePanel;
@@ -2,11 +2,10 @@ import React from 'react';
2
2
  import { SimpleFeatureSerialized } from '../../util';
3
3
  import { SeqState } from '../util';
4
4
  import { SequenceFeatureDetailsModel } from './model';
5
- interface SeqPanelProps {
5
+ interface SequencePanelProps {
6
6
  sequence: SeqState;
7
7
  feature: SimpleFeatureSerialized;
8
- mode: string;
9
8
  model: SequenceFeatureDetailsModel;
10
9
  }
11
- declare const SeqPanel: React.ForwardRefExoticComponent<SeqPanelProps & React.RefAttributes<HTMLDivElement>>;
12
- export default SeqPanel;
10
+ declare const SequencePanel: React.ForwardRefExoticComponent<SequencePanelProps & React.RefAttributes<HTMLDivElement>>;
11
+ export default SequencePanel;
@@ -4,14 +4,48 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
+ const mobx_react_1 = require("mobx-react");
8
+ // locals
7
9
  const util_1 = require("../../util");
8
10
  const util_2 = require("../util");
11
+ // panel types
9
12
  const CDNASequence_1 = __importDefault(require("./seqtypes/CDNASequence"));
10
13
  const ProteinSequence_1 = __importDefault(require("./seqtypes/ProteinSequence"));
11
14
  const GenomicSequence_1 = __importDefault(require("./seqtypes/GenomicSequence"));
12
15
  const CDSSequence_1 = __importDefault(require("./seqtypes/CDSSequence"));
13
- const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
14
- const { model, feature, mode } = props;
16
+ function getStrand(strand) {
17
+ if (strand === -1) {
18
+ return '(-)';
19
+ }
20
+ else if (strand === 1) {
21
+ return '(+)';
22
+ }
23
+ else {
24
+ return '';
25
+ }
26
+ }
27
+ function WordWrap({ children }) {
28
+ return (react_1.default.createElement("pre", { style: {
29
+ /* raw styles instead of className so that html copy works */
30
+ fontFamily: 'monospace',
31
+ color: 'black',
32
+ fontSize: 11,
33
+ } }, children));
34
+ }
35
+ function NoWordWrap({ children }) {
36
+ return (react_1.default.createElement("div", { style: {
37
+ /* raw styles instead of className so that html copy works */
38
+ fontFamily: 'monospace',
39
+ color: 'black',
40
+ fontSize: 11,
41
+ maxWidth: 600,
42
+ whiteSpace: 'wrap',
43
+ wordBreak: 'break-all',
44
+ } }, children));
45
+ }
46
+ const SequencePanel = (0, mobx_react_1.observer)(react_1.default.forwardRef(function S(props, ref) {
47
+ const { model, feature } = props;
48
+ const { showCoordinates, mode } = model;
15
49
  let { sequence: { seq, upstream = '', downstream = '' }, } = props;
16
50
  const { subfeatures = [] } = feature;
17
51
  const children = subfeatures
@@ -21,10 +55,10 @@ const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
21
55
  start: sub.start - feature.start,
22
56
  end: sub.end - feature.start,
23
57
  }));
24
- // we filter duplicate entries in cds and exon lists duplicate entries may be
25
- // rare but was seen in Gencode v36 track NCList, likely a bug on GFF3 or
26
- // probably worth ignoring here (produces broken protein translations if
27
- // included)
58
+ // we filter duplicate entries in cds and exon lists duplicate entries
59
+ // may be rare but was seen in Gencode v36 track NCList, likely a bug
60
+ // on GFF3 or probably worth ignoring here (produces broken protein
61
+ // translations if included)
28
62
  //
29
63
  // position 1:224,800,006..225,203,064 gene ENSG00000185842.15 first
30
64
  // transcript ENST00000445597.6
@@ -57,21 +91,18 @@ const SeqPanel = react_1.default.forwardRef(function SeqPanel2(props, ref) {
57
91
  utr = (0, util_2.revlist)(utr, seq.length);
58
92
  }
59
93
  const codonTable = (0, util_1.generateCodonTable)(util_1.defaultCodonTable);
60
- return (react_1.default.createElement("div", { ref: ref, "data-testid": "sequence_panel" },
61
- react_1.default.createElement("div", { style: {
62
- /* raw styles instead of className so that html copy works */
63
- fontFamily: 'monospace',
64
- wordWrap: 'break-word',
65
- overflow: 'auto',
66
- color: 'black',
67
- fontSize: 12,
68
- maxWidth: 600,
69
- maxHeight: 300,
70
- } },
71
- react_1.default.createElement("span", { style: { background: 'white' } }, `>${feature.name ||
72
- feature.id ||
73
- `${feature.refName}:${feature.start + 1}-${feature.end}`}-${mode}\n`),
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, { 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
- });
77
- exports.default = SeqPanel;
94
+ const Container = showCoordinates ? WordWrap : NoWordWrap;
95
+ return (react_1.default.createElement("div", { "data-testid": "sequence_panel", ref: ref, style: { maxHeight: 300, overflow: 'auto' } },
96
+ react_1.default.createElement(Container, null,
97
+ react_1.default.createElement("div", { style: { background: 'white' } }, `>${[
98
+ (feature.name || feature.id) + '-' + mode,
99
+ `${feature.refName}:${(0, util_1.toLocale)(feature.start + 1)}-${(0, util_1.toLocale)(feature.end)}${getStrand(feature.strand)}`,
100
+ mode.endsWith('updownstream')
101
+ ? `+/- ${(0, util_1.toLocale)(model.upDownBp)} up/downstream bp`
102
+ : '',
103
+ ]
104
+ .filter(f => !!f)
105
+ .join(' ')}\n`),
106
+ mode === 'genomic' ? (react_1.default.createElement(GenomicSequence_1.default, { feature: feature, model: model, sequence: seq })) : mode === 'genomic_sequence_updownstream' ? (react_1.default.createElement(GenomicSequence_1.default, { model: model, feature: feature, sequence: seq, upstream: upstream, downstream: downstream })) : mode === 'cds' ? (react_1.default.createElement(CDSSequence_1.default, { model: model, cds: cds, sequence: seq })) : mode === 'cdna' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, feature: feature, cds: cds, utr: utr, sequence: seq })) : mode === 'protein' ? (react_1.default.createElement(ProteinSequence_1.default, { model: model, cds: cds, codonTable: codonTable, sequence: seq })) : mode === 'gene' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, feature: feature, cds: cds, utr: utr, sequence: seq, includeIntrons: true })) : mode === 'gene_collapsed_intron' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, feature: feature, cds: cds, sequence: seq, utr: utr, includeIntrons: true, collapseIntron: true })) : mode === 'gene_updownstream' ? (react_1.default.createElement(CDNASequence_1.default, { model: model, exons: exons, feature: feature, 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, feature: feature, cds: cds, sequence: seq, utr: utr, upstream: upstream, downstream: downstream, includeIntrons: true, collapseIntron: true })) : (react_1.default.createElement("div", null, "Unknown type")))));
107
+ }));
108
+ exports.default = SequencePanel;
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = HelpDialog;
6
7
  const react_1 = __importDefault(require("react"));
7
8
  const material_1 = require("@mui/material");
8
9
  const ui_1 = require("@jbrowse/core/ui");
@@ -29,4 +30,3 @@ function HelpDialog({ handleClose, }) {
29
30
  react_1.default.createElement(material_1.DialogActions, null,
30
31
  react_1.default.createElement(material_1.Button, { onClick: () => handleClose(), autoFocus: true, variant: "contained" }, "Close"))));
31
32
  }
32
- exports.default = HelpDialog;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { SimpleFeatureSerialized } from '../../../util';
3
+ import { BaseFeatureWidgetModel } from '../../stateModelFactory';
4
+ declare const SequenceDialog: ({ handleClose, model, feature, }: {
5
+ handleClose: () => void;
6
+ feature: SimpleFeatureSerialized;
7
+ model: BaseFeatureWidgetModel;
8
+ }) => React.JSX.Element;
9
+ export default SequenceDialog;
@@ -0,0 +1,69 @@
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 ui_1 = require("@jbrowse/core/ui");
32
+ const mui_1 = require("tss-react/mui");
33
+ const mobx_react_1 = require("mobx-react");
34
+ // locals
35
+ const hooks_1 = require("../hooks");
36
+ const SequencePanel_1 = __importDefault(require("../SequencePanel"));
37
+ const SequenceFeatureMenu_1 = __importDefault(require("./SequenceFeatureMenu"));
38
+ const SequenceTypeSelector_1 = __importDefault(require("./SequenceTypeSelector"));
39
+ const useStyles = (0, mui_1.makeStyles)()({
40
+ dialogContent: {
41
+ width: '80em',
42
+ },
43
+ formControl: {
44
+ margin: 0,
45
+ marginLeft: 4,
46
+ },
47
+ });
48
+ const SequenceDialog = (0, mobx_react_1.observer)(function ({ handleClose, model, feature, }) {
49
+ const { sequenceFeatureDetails } = model;
50
+ const { upDownBp } = sequenceFeatureDetails;
51
+ const { classes } = useStyles();
52
+ const seqPanelRef = (0, react_1.useRef)(null);
53
+ const [force, setForce] = (0, react_1.useState)(false);
54
+ const { sequence, error } = (0, hooks_1.useFeatureSequence)(model, feature, upDownBp, force);
55
+ return (react_1.default.createElement(ui_1.Dialog, { maxWidth: "xl", open: true, onClose: () => handleClose(), title: "Sequence view" },
56
+ react_1.default.createElement(material_1.DialogContent, { className: classes.dialogContent },
57
+ react_1.default.createElement("div", null,
58
+ react_1.default.createElement(SequenceTypeSelector_1.default, { model: sequenceFeatureDetails }),
59
+ react_1.default.createElement(SequenceFeatureMenu_1.default, { ref: seqPanelRef, model: sequenceFeatureDetails })),
60
+ react_1.default.createElement("div", null,
61
+ feature.type === 'gene' ? (react_1.default.createElement(material_1.Typography, null, "Note: inspect subfeature sequences for protein/CDS computations")) : null,
62
+ 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,
63
+ react_1.default.createElement(material_1.Typography, { color: "error" }, sequence.error),
64
+ 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) },
65
+ react_1.default.createElement(SequencePanel_1.default, { ref: seqPanelRef, feature: feature, sequence: sequence, model: sequenceFeatureDetails })))) : (react_1.default.createElement(material_1.Typography, null, "No sequence found")))),
66
+ react_1.default.createElement(material_1.DialogActions, null,
67
+ react_1.default.createElement(material_1.Button, { onClick: () => handleClose(), variant: "contained" }, "Close"))));
68
+ });
69
+ exports.default = SequenceDialog;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { SequenceFeatureDetailsModel } from '../model';
3
+ import { MenuItem } from '../../../ui';
4
+ interface Props {
5
+ model: SequenceFeatureDetailsModel;
6
+ extraItems?: MenuItem[];
7
+ }
8
+ declare const SequenceFeatureMenu: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
9
+ export default SequenceFeatureMenu;