@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
@@ -0,0 +1,126 @@
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 mobx_react_1 = require("mobx-react");
31
+ const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
32
+ const file_saver_1 = require("file-saver");
33
+ // locals
34
+ const CascadingMenuButton_1 = __importDefault(require("../../../ui/CascadingMenuButton"));
35
+ // icons
36
+ const MoreVert_1 = __importDefault(require("@mui/icons-material/MoreVert"));
37
+ const Settings_1 = __importDefault(require("@mui/icons-material/Settings"));
38
+ // lazies
39
+ const SequenceFeatureSettingsDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./SettingsDialog'))));
40
+ const SequenceFeatureMenu = (0, mobx_react_1.observer)(react_1.default.forwardRef(function SequenceFeatureMenu2({ model, extraItems = [] }, ref) {
41
+ if (typeof ref === 'function') {
42
+ throw new Error('needs a non function ref');
43
+ }
44
+ const [showSettings, setShowSettings] = (0, react_1.useState)(false);
45
+ const { showCoordinatesSetting, showGenomicCoordsOption } = model;
46
+ return (react_1.default.createElement(react_1.default.Fragment, null,
47
+ react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: [
48
+ {
49
+ label: 'Copy plaintext',
50
+ onClick: () => {
51
+ const r = ref === null || ref === void 0 ? void 0 : ref.current;
52
+ if (r) {
53
+ (0, copy_to_clipboard_1.default)(r.textContent || '', { format: 'text/plain' });
54
+ }
55
+ },
56
+ },
57
+ {
58
+ label: 'Copy HTML',
59
+ onClick: () => {
60
+ const r = ref === null || ref === void 0 ? void 0 : ref.current;
61
+ if (r) {
62
+ (0, copy_to_clipboard_1.default)(r.outerHTML, { format: 'text/html' });
63
+ }
64
+ },
65
+ },
66
+ {
67
+ label: 'Download plaintext',
68
+ onClick: () => {
69
+ const r = ref === null || ref === void 0 ? void 0 : ref.current;
70
+ if (r) {
71
+ (0, file_saver_1.saveAs)(new Blob([r.textContent || ''], {
72
+ type: 'text/plain;charset=utf-8',
73
+ }), 'sequence.txt');
74
+ }
75
+ },
76
+ },
77
+ {
78
+ label: 'Download HTML',
79
+ onClick: () => {
80
+ const r = ref === null || ref === void 0 ? void 0 : ref.current;
81
+ if (r) {
82
+ (0, file_saver_1.saveAs)(new Blob([r.outerHTML || ''], {
83
+ type: 'text/html;charset=utf-8',
84
+ }), 'sequence.html');
85
+ }
86
+ },
87
+ },
88
+ ...extraItems,
89
+ {
90
+ label: 'Show coordinates?',
91
+ type: 'subMenu',
92
+ subMenu: [
93
+ {
94
+ label: 'No coordinates',
95
+ type: 'radio',
96
+ checked: showCoordinatesSetting === 'none',
97
+ onClick: () => model.setShowCoordinates('none'),
98
+ },
99
+ {
100
+ label: 'Coordinates relative to feature start',
101
+ type: 'radio',
102
+ checked: showCoordinatesSetting === 'relative',
103
+ onClick: () => model.setShowCoordinates('relative'),
104
+ },
105
+ ...(showGenomicCoordsOption
106
+ ? [
107
+ {
108
+ label: 'Coordinates relative to genome (only available for continuous genome based sequence types)',
109
+ type: 'radio',
110
+ checked: showCoordinatesSetting === 'genomic',
111
+ onClick: () => model.setShowCoordinates('genomic'),
112
+ },
113
+ ]
114
+ : []),
115
+ ],
116
+ },
117
+ {
118
+ label: 'Settings',
119
+ icon: Settings_1.default,
120
+ onClick: () => setShowSettings(true),
121
+ },
122
+ ] },
123
+ react_1.default.createElement(MoreVert_1.default, null)),
124
+ showSettings ? (react_1.default.createElement(SequenceFeatureSettingsDialog, { model: model, handleClose: () => setShowSettings(false) })) : null));
125
+ }));
126
+ exports.default = SequenceFeatureMenu;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { SequenceFeatureDetailsModel } from '../model';
3
+ declare const SequenceTypeSelector: ({ model, }: {
4
+ model: SequenceFeatureDetailsModel;
5
+ }) => React.JSX.Element;
6
+ export default SequenceTypeSelector;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const material_1 = require("@mui/material");
8
+ const mobx_react_1 = require("mobx-react");
9
+ const mui_1 = require("tss-react/mui");
10
+ const useStyles = (0, mui_1.makeStyles)()({
11
+ formControl: {
12
+ margin: 0,
13
+ marginLeft: 4,
14
+ },
15
+ });
16
+ const SequenceTypeSelector = (0, mobx_react_1.observer)(function ({ model, }) {
17
+ const { classes } = useStyles();
18
+ const { intronBp, upDownBp, mode, hasCDS, hasExonOrCDS } = model;
19
+ return (react_1.default.createElement(material_1.FormControl, { className: classes.formControl },
20
+ react_1.default.createElement(material_1.Select, { size: "small", value: mode, onChange: event => model.setMode(event.target.value) }, Object.entries({
21
+ ...(hasCDS
22
+ ? {
23
+ cds: 'CDS',
24
+ }
25
+ : {}),
26
+ ...(hasCDS
27
+ ? {
28
+ protein: 'Protein',
29
+ }
30
+ : {}),
31
+ ...(hasExonOrCDS
32
+ ? {
33
+ cdna: 'cDNA',
34
+ }
35
+ : {}),
36
+ ...(hasExonOrCDS
37
+ ? {
38
+ gene: `Genomic w/ full introns`,
39
+ }
40
+ : {}),
41
+ ...(hasExonOrCDS
42
+ ? {
43
+ gene_updownstream: `Genomic w/ full introns +/- ${upDownBp}bp up+down stream`,
44
+ }
45
+ : {}),
46
+ ...(hasExonOrCDS
47
+ ? {
48
+ gene_collapsed_intron: `Genomic w/ ${intronBp}bp intron`,
49
+ }
50
+ : {}),
51
+ ...(hasExonOrCDS
52
+ ? {
53
+ gene_updownstream_collapsed_intron: `Genomic w/ ${intronBp}bp intron +/- ${upDownBp}bp up+down stream `,
54
+ }
55
+ : {}),
56
+ ...(!hasExonOrCDS
57
+ ? {
58
+ genomic: 'Genomic',
59
+ }
60
+ : {}),
61
+ ...(!hasExonOrCDS
62
+ ? {
63
+ genomic_sequence_updownstream: `Genomic +/- ${upDownBp}bp up+down stream`,
64
+ }
65
+ : {}),
66
+ }).map(([key, val]) => (react_1.default.createElement(material_1.MenuItem, { key: key, value: key }, val))))));
67
+ });
68
+ exports.default = SequenceTypeSelector;
@@ -36,25 +36,34 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
36
36
  dialogContent: {
37
37
  width: '80em',
38
38
  },
39
+ root: {
40
+ padding: 4,
41
+ },
39
42
  }));
43
+ function TextField2(props) {
44
+ return (react_1.default.createElement("div", null,
45
+ react_1.default.createElement(material_1.TextField, { ...props })));
46
+ }
47
+ function FormControl2({ children }) {
48
+ return (react_1.default.createElement("div", null,
49
+ react_1.default.createElement(material_1.FormControl, null, children)));
50
+ }
40
51
  const SequenceFeatureSettingsDialog = (0, mobx_react_1.observer)(function ({ handleClose, model, }) {
41
52
  const { classes } = useStyles();
53
+ const { upperCaseCDS } = model;
42
54
  const [intronBp, setIntronBp] = (0, react_1.useState)(`${model.intronBp}`);
43
55
  const [upDownBp, setUpDownBp] = (0, react_1.useState)(`${model.upDownBp}`);
44
56
  const intronBpValid = !Number.isNaN(+intronBp);
45
57
  const upDownBpValid = !Number.isNaN(+upDownBp);
46
58
  return (react_1.default.createElement(ui_1.Dialog, { maxWidth: "xl", open: true, onClose: () => handleClose(), title: "Feature sequence settings" },
47
59
  react_1.default.createElement(material_1.DialogContent, { className: classes.dialogContent },
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" }))))),
60
+ react_1.default.createElement(TextField2, { 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) }),
61
+ react_1.default.createElement(TextField2, { 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) }),
62
+ react_1.default.createElement(FormControl2, null,
63
+ react_1.default.createElement(material_1.FormLabel, null, "Sequence capitalization"),
64
+ react_1.default.createElement(material_1.RadioGroup, { value: upperCaseCDS ? 'cds' : 'unchanged', onChange: e => model.setUpperCaseCDS(e.target.value === 'cds') },
65
+ react_1.default.createElement(material_1.FormControlLabel, { value: "cds", control: react_1.default.createElement(material_1.Radio, { className: classes.root, size: "small" }), label: "Capitalize CDS and lower case everything else" }),
66
+ react_1.default.createElement(material_1.FormControlLabel, { value: "unchanged", control: react_1.default.createElement(material_1.Radio, { className: classes.root, size: "small" }), label: "Capitalization from reference genome sequence" })))),
58
67
  react_1.default.createElement(material_1.DialogActions, null,
59
68
  react_1.default.createElement(material_1.Button, { onClick: () => {
60
69
  model.setIntronBp(+intronBp);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useFeatureSequence = void 0;
3
+ exports.useFeatureSequence = useFeatureSequence;
4
4
  const react_1 = require("react");
5
5
  const util_1 = require("../../util");
6
6
  const configuration_1 = require("../../configuration");
@@ -64,4 +64,3 @@ function useFeatureSequence(model, feature, upDownBp, forceLoad) {
64
64
  }, [feature, model, upDownBp, forceLoad]);
65
65
  return { sequence, error };
66
66
  }
67
- exports.useFeatureSequence = useFeatureSequence;
@@ -1,12 +1,59 @@
1
1
  import { Instance } from 'mobx-state-tree';
2
+ import { SimpleFeatureSerialized } from '../../util';
2
3
  export declare function SequenceFeatureDetailsF(): import("mobx-state-tree").IModelType<{}, {
4
+ showCoordinatesSetting: string;
3
5
  intronBp: number;
4
6
  upDownBp: number;
5
7
  upperCaseCDS: boolean;
8
+ charactersPerRow: number;
9
+ feature: SimpleFeatureSerialized | undefined;
10
+ mode: string;
6
11
  } & {
12
+ /**
13
+ * #action
14
+ */
15
+ setFeature(f: SimpleFeatureSerialized): void;
16
+ /**
17
+ * #action
18
+ */
7
19
  setUpDownBp(f: number): void;
20
+ /**
21
+ * #action
22
+ */
8
23
  setIntronBp(f: number): void;
24
+ /**
25
+ * #action
26
+ */
9
27
  setUpperCaseCDS(f: boolean): void;
28
+ /**
29
+ * #action
30
+ */
31
+ setShowCoordinates(f: "none" | "relative" | "genomic"): void;
32
+ /**
33
+ * #action
34
+ */
35
+ setMode(mode: string): void;
36
+ } & {
37
+ /**
38
+ * #getter
39
+ */
40
+ readonly showCoordinates: boolean;
41
+ /**
42
+ * #getter
43
+ */
44
+ readonly showGenomicCoordsOption: boolean;
45
+ /**
46
+ * #getter
47
+ */
48
+ readonly hasCDS: boolean | undefined;
49
+ /**
50
+ * #getter
51
+ */
52
+ readonly hasExon: boolean | undefined;
53
+ /**
54
+ * #getter
55
+ */
56
+ readonly hasExonOrCDS: boolean | undefined;
10
57
  } & {
11
58
  afterAttach(): void;
12
59
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -1,31 +1,101 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SequenceFeatureDetailsF = void 0;
3
+ exports.SequenceFeatureDetailsF = SequenceFeatureDetailsF;
4
4
  const mobx_state_tree_1 = require("mobx-state-tree");
5
5
  const mobx_1 = require("mobx");
6
6
  // locals
7
7
  const util_1 = require("../../util");
8
+ function localStorageGetNumber(key, defaultVal) {
9
+ var _a;
10
+ return +((_a = (0, util_1.localStorageGetItem)(key)) !== null && _a !== void 0 ? _a : defaultVal);
11
+ }
8
12
  function SequenceFeatureDetailsF() {
9
13
  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
- })
14
+ .model('SequenceFeatureDetails')
15
+ .volatile(() => ({
16
+ showCoordinatesSetting: (0, util_1.localStorageGetItem)('sequenceFeatureDetails-showCoordinatesSetting') ||
17
+ 'none',
18
+ intronBp: localStorageGetNumber('sequenceFeatureDetails-intronBp', 10),
19
+ upDownBp: localStorageGetNumber('sequenceFeatureDetails-upDownBp', 100),
20
+ upperCaseCDS: Boolean(JSON.parse((0, util_1.localStorageGetItem)('sequenceFeatureDetails-upperCaseCDS') || 'true')),
21
+ charactersPerRow: 100,
22
+ feature: undefined,
23
+ mode: '',
24
+ }))
19
25
  .actions(self => ({
26
+ /**
27
+ * #action
28
+ */
29
+ setFeature(f) {
30
+ self.feature = f;
31
+ },
32
+ /**
33
+ * #action
34
+ */
20
35
  setUpDownBp(f) {
21
36
  self.upDownBp = f;
22
37
  },
38
+ /**
39
+ * #action
40
+ */
23
41
  setIntronBp(f) {
24
42
  self.intronBp = f;
25
43
  },
44
+ /**
45
+ * #action
46
+ */
26
47
  setUpperCaseCDS(f) {
27
48
  self.upperCaseCDS = f;
28
49
  },
50
+ /**
51
+ * #action
52
+ */
53
+ setShowCoordinates(f) {
54
+ self.showCoordinatesSetting = f;
55
+ },
56
+ /**
57
+ * #action
58
+ */
59
+ setMode(mode) {
60
+ self.mode = mode;
61
+ },
62
+ }))
63
+ .views(self => ({
64
+ /**
65
+ * #getter
66
+ */
67
+ get showCoordinates() {
68
+ return self.showCoordinatesSetting !== 'none';
69
+ },
70
+ /**
71
+ * #getter
72
+ */
73
+ get showGenomicCoordsOption() {
74
+ return (self.mode === 'gene' ||
75
+ self.mode === 'gene_updownstream' ||
76
+ self.mode === 'genomic' ||
77
+ self.mode === 'genomic_sequence_updownstream');
78
+ },
79
+ /**
80
+ * #getter
81
+ */
82
+ get hasCDS() {
83
+ var _a, _b;
84
+ return (_b = (_a = self.feature) === null || _a === void 0 ? void 0 : _a.subfeatures) === null || _b === void 0 ? void 0 : _b.some(sub => sub.type === 'CDS');
85
+ },
86
+ /**
87
+ * #getter
88
+ */
89
+ get hasExon() {
90
+ var _a, _b;
91
+ return (_b = (_a = self.feature) === null || _a === void 0 ? void 0 : _a.subfeatures) === null || _b === void 0 ? void 0 : _b.some(sub => sub.type === 'exon');
92
+ },
93
+ /**
94
+ * #getter
95
+ */
96
+ get hasExonOrCDS() {
97
+ return this.hasExon || this.hasCDS;
98
+ },
29
99
  }))
30
100
  .actions(self => ({
31
101
  afterAttach() {
@@ -33,8 +103,11 @@ function SequenceFeatureDetailsF() {
33
103
  (0, util_1.localStorageSetItem)('sequenceFeatureDetails-upDownBp', JSON.stringify(self.upDownBp));
34
104
  (0, util_1.localStorageSetItem)('sequenceFeatureDetails-intronBp', JSON.stringify(self.intronBp));
35
105
  (0, util_1.localStorageSetItem)('sequenceFeatureDetails-upperCaseCDS', JSON.stringify(self.upperCaseCDS));
106
+ (0, util_1.localStorageSetItem)('sequenceFeatureDetails-showCoordinatesSetting', self.showCoordinatesSetting);
107
+ }));
108
+ (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
109
+ self.setMode(self.hasCDS ? 'cds' : self.hasExon ? 'cdna' : 'genomic');
36
110
  }));
37
111
  },
38
112
  }));
39
113
  }
40
- exports.SequenceFeatureDetailsF = SequenceFeatureDetailsF;
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
2
  import { Feat } from '../../util';
3
3
  import { SequenceFeatureDetailsModel } from '../model';
4
- declare const CDNASequence: ({ utr, cds, exons, sequence, upstream, downstream, includeIntrons, collapseIntron, model, }: {
4
+ import { SimpleFeatureSerialized } from '../../../util';
5
+ declare const CDNASequence: ({ utr, cds, exons, sequence, upstream, downstream, feature, includeIntrons, collapseIntron, model, }: {
5
6
  utr: Feat[];
6
7
  cds: Feat[];
7
8
  exons: Feat[];
8
9
  sequence: string;
9
10
  upstream?: string;
10
11
  downstream?: string;
12
+ feature: SimpleFeatureSerialized;
11
13
  includeIntrons?: boolean;
12
14
  collapseIntron?: boolean;
13
15
  model: SequenceFeatureDetailsModel;
@@ -6,29 +6,86 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const mobx_react_1 = require("mobx-react");
8
8
  const util_1 = require("../util");
9
- const CDNASequence = (0, mobx_react_1.observer)(function ({ utr, cds, exons, sequence, upstream, downstream, includeIntrons, collapseIntron, model, }) {
10
- const { upperCaseCDS, intronBp } = model;
9
+ const SequenceDisplay_1 = __importDefault(require("./SequenceDisplay"));
10
+ const CDNASequence = (0, mobx_react_1.observer)(function ({ utr, cds, exons, sequence, upstream, downstream, feature, includeIntrons, collapseIntron, model, }) {
11
+ var _a;
12
+ const { upperCaseCDS, intronBp, charactersPerRow, showCoordinates, showCoordinatesSetting, } = model;
11
13
  const hasCds = cds.length > 0;
12
14
  const chunks = (cds.length ? [...cds, ...utr].sort((a, b) => a.start - b.start) : exons).filter(f => f.start !== f.end);
13
15
  const toLower = (s) => (upperCaseCDS ? s.toLowerCase() : s);
14
16
  const toUpper = (s) => (upperCaseCDS ? s.toUpperCase() : s);
17
+ const strand = feature.strand === -1 ? -1 : 1;
18
+ const fullGenomicCoordinates = showCoordinatesSetting === 'genomic' && includeIntrons && !collapseIntron;
19
+ const mult = fullGenomicCoordinates ? strand : 1;
20
+ let coordStart = fullGenomicCoordinates
21
+ ? strand > 0
22
+ ? feature.start + 1 - ((upstream === null || upstream === void 0 ? void 0 : upstream.length) || 0)
23
+ : feature.end + ((upstream === null || upstream === void 0 ? void 0 : upstream.length) || 0)
24
+ : 0;
25
+ let currStart = 0;
26
+ let currRemainder = 0;
27
+ let upstreamChunk = null;
28
+ if (upstream) {
29
+ const { segments, remainder } = (0, util_1.splitString)({
30
+ str: toLower(upstream),
31
+ charactersPerRow,
32
+ showCoordinates,
33
+ });
34
+ upstreamChunk = (react_1.default.createElement(SequenceDisplay_1.default, { model: model, color: util_1.updownstreamColor, strand: mult, start: currStart, coordStart: coordStart, chunks: segments }));
35
+ currRemainder = remainder;
36
+ currStart = currStart + upstream.length * mult;
37
+ coordStart = coordStart + upstream.length * mult;
38
+ }
39
+ const middleChunks = [];
40
+ for (let idx = 0; idx < chunks.length; idx++) {
41
+ const chunk = chunks[idx];
42
+ const intron = sequence.slice(chunk.end, (_a = chunks[idx + 1]) === null || _a === void 0 ? void 0 : _a.start);
43
+ const s = sequence.slice(chunk.start, chunk.end);
44
+ const { segments, remainder } = (0, util_1.splitString)({
45
+ str: hasCds
46
+ ? chunk.type === 'CDS'
47
+ ? toUpper(s)
48
+ : toLower(s)
49
+ : toUpper(s),
50
+ charactersPerRow,
51
+ currRemainder,
52
+ showCoordinates,
53
+ });
54
+ middleChunks.push(react_1.default.createElement(SequenceDisplay_1.default, { key: JSON.stringify(chunk) + '-mid', model: model, color: chunk.type === 'CDS' ? util_1.cdsColor : util_1.utrColor, strand: mult, start: currStart, coordStart: coordStart, chunks: segments }));
55
+ currRemainder = remainder;
56
+ currStart = currStart + s.length * mult;
57
+ coordStart = coordStart + s.length * mult;
58
+ if (intron && includeIntrons && idx < chunks.length - 1) {
59
+ const str = toLower(collapseIntron && intron.length > intronBp * 2
60
+ ? `${intron.slice(0, intronBp)}...${intron.slice(-intronBp)}`
61
+ : intron);
62
+ const { segments, remainder } = (0, util_1.splitString)({
63
+ str,
64
+ charactersPerRow,
65
+ currRemainder,
66
+ showCoordinates,
67
+ });
68
+ if (segments.length) {
69
+ middleChunks.push(react_1.default.createElement(SequenceDisplay_1.default, { key: JSON.stringify(chunk) + '-intron', model: model, strand: mult, coordStart: coordStart, start: currStart, chunks: segments }));
70
+ currRemainder = remainder;
71
+ currStart = currStart + str.length * mult;
72
+ coordStart = coordStart + str.length * mult;
73
+ }
74
+ }
75
+ }
76
+ let downstreamChunk = null;
77
+ if (downstream) {
78
+ const { segments } = (0, util_1.splitString)({
79
+ str: toLower(downstream),
80
+ charactersPerRow,
81
+ currRemainder,
82
+ showCoordinates,
83
+ });
84
+ downstreamChunk = (react_1.default.createElement(SequenceDisplay_1.default, { start: currStart, model: model, strand: mult, chunks: segments, coordStart: coordStart, color: util_1.updownstreamColor }));
85
+ }
15
86
  return (react_1.default.createElement(react_1.default.Fragment, null,
16
- upstream ? (react_1.default.createElement("span", { style: { background: util_1.updownstreamColor } }, toLower(upstream))) : null,
17
- chunks.map((chunk, idx) => {
18
- var _a;
19
- const intron = sequence.slice(chunk.end, (_a = chunks[idx + 1]) === null || _a === void 0 ? void 0 : _a.start);
20
- return (react_1.default.createElement(react_1.default.Fragment, { key: JSON.stringify(chunk) },
21
- react_1.default.createElement("span", { style: {
22
- background: chunk.type === 'CDS' ? util_1.cdsColor : util_1.utrColor,
23
- } }, hasCds
24
- ? chunk.type === 'CDS'
25
- ? toUpper(sequence.slice(chunk.start, chunk.end))
26
- : toLower(sequence.slice(chunk.start, chunk.end))
27
- : toUpper(sequence.slice(chunk.start, chunk.end))),
28
- includeIntrons && idx < chunks.length - 1 ? (react_1.default.createElement("span", { style: { background: util_1.intronColor } }, toLower(collapseIntron && intron.length > intronBp * 2
29
- ? `${intron.slice(0, intronBp)}...${intron.slice(-intronBp)}`
30
- : intron))) : null));
31
- }),
32
- downstream ? (react_1.default.createElement("span", { style: { background: util_1.updownstreamColor } }, toLower(downstream))) : null));
87
+ upstreamChunk,
88
+ middleChunks,
89
+ downstreamChunk));
33
90
  });
34
91
  exports.default = CDNASequence;
@@ -1,6 +1,9 @@
1
1
  import React from 'react';
2
2
  import { Feat } from '../../util';
3
- export default function CDSSequence({ cds, sequence, }: {
3
+ import { SequenceFeatureDetailsModel } from '../model';
4
+ declare const CDSSequence: ({ cds, sequence, model, }: {
4
5
  cds: Feat[];
5
6
  sequence: string;
6
- }): React.JSX.Element;
7
+ model: SequenceFeatureDetailsModel;
8
+ }) => React.JSX.Element;
9
+ export default CDSSequence;
@@ -4,9 +4,18 @@ 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");
9
- function CDSSequence({ cds, sequence, }) {
10
- return react_1.default.createElement("span", { style: { background: util_1.cdsColor } }, (0, util_2.stitch)(cds, sequence));
11
- }
11
+ const SequenceDisplay_1 = __importDefault(require("./SequenceDisplay"));
12
+ const CDSSequence = (0, mobx_react_1.observer)(function ({ cds, sequence, model, }) {
13
+ const { charactersPerRow, showCoordinates } = model;
14
+ const { segments } = (0, util_1.splitString)({
15
+ str: (0, util_2.stitch)(cds, sequence),
16
+ charactersPerRow,
17
+ showCoordinates,
18
+ });
19
+ return (react_1.default.createElement(SequenceDisplay_1.default, { model: model, color: util_1.cdsColor, chunks: segments, start: 0 }));
20
+ });
12
21
  exports.default = CDSSequence;
@@ -1,6 +1,11 @@
1
1
  import React from 'react';
2
- export default function GenomicSequence({ sequence, upstream, downstream, }: {
2
+ import { SequenceFeatureDetailsModel } from '../model';
3
+ import { SimpleFeatureSerialized } from '../../../util';
4
+ declare const GenomicSequence: ({ sequence, upstream, feature, downstream, model, }: {
3
5
  sequence: string;
6
+ feature: SimpleFeatureSerialized;
4
7
  upstream?: string;
5
8
  downstream?: string;
6
- }): React.JSX.Element;
9
+ model: SequenceFeatureDetailsModel;
10
+ }) => React.JSX.Element;
11
+ export default GenomicSequence;