@jbrowse/plugin-sequence 2.10.2 → 2.11.0

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.
@@ -8,7 +8,10 @@ declare const DivSequenceRendering: (props: {
8
8
  };
9
9
  features: Map<string, Feature>;
10
10
  regions: Region[];
11
+ colorByCDS: boolean;
11
12
  bpPerPx: number;
13
+ rowHeight: number;
14
+ sequenceHeight: number;
12
15
  config: AnyConfigurationModel;
13
16
  theme?: Theme;
14
17
  showForward?: boolean;
@@ -7,42 +7,54 @@ const react_1 = __importDefault(require("react"));
7
7
  const ui_1 = require("@jbrowse/core/ui");
8
8
  const mobx_react_1 = require("mobx-react");
9
9
  const util_1 = require("@jbrowse/core/util");
10
- function Translation(props) {
11
- const { codonTable, seq, frame, bpPerPx, region, height, y, reverse = false, theme, } = props;
12
- const scale = bpPerPx;
13
- // the tilt variable normalizes the frame to where we are starting from,
14
- // which increases consistency across blocks
15
- const tilt = 3 - (region.start % 3);
16
- // the effectiveFrame incorporates tilt and the frame to say what the
17
- // effective frame that is plotted. The +3 is for when frame is -2 and this
18
- // can otherwise result in effectiveFrame -1
19
- const effectiveFrame = (frame + tilt + 3) % 3;
20
- const seqSliced = seq.slice(effectiveFrame);
10
+ function Translation({ codonTable, seq, frame, bpPerPx, colorByCDS, region, seqStart, height, y, reverse = false, theme, }) {
11
+ var _a, _b;
12
+ const normalizedFrame = Math.abs(frame) - 1;
13
+ const seqFrame = seqStart % 3;
14
+ const frameShift = (normalizedFrame - seqFrame + 3) % 3;
15
+ const frameShiftAdjustedSeqLength = seq.length - frameShift;
16
+ const multipleOfThreeLength = frameShiftAdjustedSeqLength - (frameShiftAdjustedSeqLength % 3);
17
+ const seqSliced = seq.slice(frameShift, frameShift + multipleOfThreeLength);
21
18
  const translated = [];
22
19
  for (let i = 0; i < seqSliced.length; i += 3) {
23
20
  const codon = seqSliced.slice(i, i + 3);
24
21
  const normalizedCodon = reverse ? (0, util_1.revcom)(codon) : codon;
25
22
  const aminoAcid = codonTable[normalizedCodon] || '';
26
- translated.push({ letter: aminoAcid, codon: normalizedCodon.toUpperCase() });
23
+ translated.push({
24
+ letter: aminoAcid,
25
+ codon: normalizedCodon.toUpperCase(),
26
+ });
27
27
  }
28
- const w = (1 / scale) * 3;
29
- const drop = region.start === 0 ? 0 : w;
30
- const render = 1 / bpPerPx >= 12;
31
28
  const width = (region.end - region.start) / bpPerPx;
32
- const map = ['#d8d8d8', '#adadad', '#8f8f8f'].reverse();
33
- return (react_1.default.createElement(react_1.default.Fragment, null, translated.map((element, index) => {
34
- const x = region.reversed
35
- ? width - (w * (index + 1) + effectiveFrame / scale - drop)
36
- : w * index + effectiveFrame / scale - drop;
37
- const { letter, codon } = element;
38
- return (react_1.default.createElement(react_1.default.Fragment, { key: `${index}-${letter}` },
39
- react_1.default.createElement("rect", { x: x, y: y, width: render ? w : w + 0.7 /* small fudge factor when zoomed out*/, height: height, stroke: render ? '#555' : 'none', fill: util_1.defaultStarts.includes(codon)
40
- ? theme === null || theme === void 0 ? void 0 : theme.palette.startCodon
41
- : util_1.defaultStops.includes(codon)
42
- ? theme === null || theme === void 0 ? void 0 : theme.palette.stopCodon
43
- : map[Math.abs(frame)] }),
44
- render ? (react_1.default.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle" }, letter)) : null));
45
- })));
29
+ const codonWidth = (1 / bpPerPx) * 3;
30
+ const renderLetter = 1 / bpPerPx >= 12;
31
+ const frameOffset = frameShift / bpPerPx;
32
+ const startOffset = (region.start - seqStart) / bpPerPx;
33
+ const offset = frameOffset - startOffset;
34
+ const defaultFill = colorByCDS
35
+ ? (_a = theme === null || theme === void 0 ? void 0 : theme.palette.framesCDS.at(frame)) === null || _a === void 0 ? void 0 : _a.main
36
+ : (_b = theme === null || theme === void 0 ? void 0 : theme.palette.frames.at(frame)) === null || _b === void 0 ? void 0 : _b.main;
37
+ return (react_1.default.createElement(react_1.default.Fragment, null,
38
+ react_1.default.createElement("rect", { x: 0, y: y, width: width, height: height, fill: defaultFill }),
39
+ translated.map((element, index) => {
40
+ const x = region.reversed
41
+ ? width - (index + 1) * codonWidth - offset
42
+ : codonWidth * index + offset;
43
+ const { letter, codon } = element;
44
+ const codonFill = util_1.defaultStarts.includes(codon)
45
+ ? theme === null || theme === void 0 ? void 0 : theme.palette.startCodon
46
+ : util_1.defaultStops.includes(codon)
47
+ ? theme === null || theme === void 0 ? void 0 : theme.palette.stopCodon
48
+ : undefined;
49
+ if (!(renderLetter || codonFill)) {
50
+ return null;
51
+ }
52
+ return (react_1.default.createElement(react_1.default.Fragment, { key: `${index}-${letter}` },
53
+ react_1.default.createElement("rect", { x: x, y: y, width: renderLetter
54
+ ? codonWidth
55
+ : codonWidth + 0.7 /* small fudge factor when zoomed out*/, height: height, stroke: renderLetter ? '#555' : 'none', fill: codonFill || 'none' }),
56
+ renderLetter ? (react_1.default.createElement("text", { x: x + codonWidth / 2, fontSize: height - 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle" }, letter)) : null));
57
+ })));
46
58
  }
47
59
  function DNA(props) {
48
60
  const { bpPerPx, region, feature, theme, height, seq, y } = props;
@@ -57,14 +69,13 @@ function DNA(props) {
57
69
  const x = reverse ? rightPx - (index + 1) * w : leftPx + index * w;
58
70
  return (react_1.default.createElement(react_1.default.Fragment, { key: index },
59
71
  react_1.default.createElement("rect", { x: x, y: y, width: w, height: height, fill: color ? color.main : '#aaa', stroke: render ? '#555' : 'none' }),
60
- render ? (react_1.default.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle", fill: color ? theme.palette.getContrastText(color.main) : 'black' }, letter)) : null));
72
+ render ? (react_1.default.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle", fontSize: height - 2, fill: color ? theme.palette.getContrastText(color.main) : 'black' }, letter)) : null));
61
73
  })));
62
74
  }
63
- function SequenceSVG({ regions, theme: configTheme, features = new Map(), showReverse = true, showForward = true, showTranslation = true, bpPerPx, }) {
75
+ function SequenceSVG({ regions, theme: configTheme, colorByCDS, features = new Map(), showReverse = true, showForward = true, showTranslation = true, bpPerPx, rowHeight, }) {
64
76
  const [region] = regions;
65
77
  const theme = (0, ui_1.createJBrowseTheme)(configTheme);
66
78
  const codonTable = (0, util_1.generateCodonTable)(util_1.defaultCodonTable);
67
- const height = 20;
68
79
  const [feature] = [...features.values()];
69
80
  if (!feature) {
70
81
  return null;
@@ -75,26 +86,34 @@ function SequenceSVG({ regions, theme: configTheme, features = new Map(), showRe
75
86
  }
76
87
  // incrementer for the y-position of the current sequence being rendered
77
88
  // (applies to both translation rows and dna rows)
78
- let currY = -20;
89
+ let currY = -rowHeight;
90
+ const showDNA = bpPerPx <= 1;
91
+ const forwardFrames = showTranslation && showForward ? [3, 2, 1] : [];
92
+ const reverseFrames = showTranslation && showReverse ? [-1, -2, -3] : [];
93
+ // if region.reversed, the forward translation is on bottom, reverse on top
94
+ const [topFrames, bottomFrames] = region.reversed
95
+ ? [reverseFrames.toReversed(), forwardFrames.toReversed()]
96
+ : [forwardFrames, reverseFrames];
79
97
  return (react_1.default.createElement(react_1.default.Fragment, null,
80
- showTranslation && (region.reversed ? showReverse : showForward)
81
- ? [2, 1, 0].map(index => (react_1.default.createElement(Translation, { key: `translation-${index}`, seq: seq, y: (currY += 20), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, theme: theme, height: height, reverse: region.reversed })))
82
- : null,
83
- showForward ? (react_1.default.createElement(DNA, { height: height, y: (currY += 20), feature: feature, region: region, seq: region.reversed ? (0, util_1.complement)(seq) : seq, bpPerPx: bpPerPx, theme: theme })) : null,
84
- showReverse ? (react_1.default.createElement(DNA, { height: height, y: (currY += 20), feature: feature, region: region, seq: region.reversed ? seq : (0, util_1.complement)(seq), bpPerPx: bpPerPx, theme: theme })) : null,
85
- showTranslation && (region.reversed ? showForward : showReverse)
86
- ? [0, -1, -2].map(index => (react_1.default.createElement(Translation, { key: `rev-translation-${index}`, seq: seq, y: (currY += 20), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, theme: theme, height: height, reverse: !region.reversed })))
87
- : null));
98
+ topFrames.map(index => (react_1.default.createElement(Translation, { key: `translation-${index}`, colorByCDS: colorByCDS, seq: seq, y: (currY += rowHeight), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, seqStart: feature.get('start'), theme: theme, height: rowHeight, reverse: region.reversed }))),
99
+ showForward && showDNA ? (react_1.default.createElement(DNA, { height: rowHeight, y: (currY += rowHeight), feature: feature, region: region, seq: region.reversed ? (0, util_1.complement)(seq) : seq, bpPerPx: bpPerPx, theme: theme })) : null,
100
+ showReverse && showDNA ? (react_1.default.createElement(DNA, { height: rowHeight, y: (currY += rowHeight), feature: feature, region: region, seq: region.reversed ? seq : (0, util_1.complement)(seq), bpPerPx: bpPerPx, theme: theme })) : null,
101
+ bottomFrames.map(index => (react_1.default.createElement(Translation, { key: `rev-translation-${index}`, colorByCDS: colorByCDS, seq: seq, y: (currY += rowHeight), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, seqStart: feature.get('start'), theme: theme, height: rowHeight, reverse: !region.reversed })))));
88
102
  }
89
103
  function Wrapper({ exportSVG, width, totalHeight, children, }) {
90
- return exportSVG ? (react_1.default.createElement(react_1.default.Fragment, null, children)) : (react_1.default.createElement("svg", { "data-testid": "sequence_track", width: width, height: totalHeight, style: { width, height: totalHeight, userSelect: 'none' } }, children));
104
+ return exportSVG ? (children) : (react_1.default.createElement("svg", { "data-testid": "sequence_track", width: width, height: totalHeight, style: {
105
+ // use block because svg by default is inline, which adds a margin
106
+ display: 'block',
107
+ width,
108
+ height: totalHeight,
109
+ userSelect: 'none',
110
+ } }, children));
91
111
  }
92
112
  const DivSequenceRendering = (0, mobx_react_1.observer)(function (props) {
93
- const { regions, bpPerPx } = props;
113
+ const { regions, bpPerPx, sequenceHeight } = props;
94
114
  const [region] = regions;
95
115
  const width = (region.end - region.start) / bpPerPx;
96
- const totalHeight = 200;
97
- return (react_1.default.createElement(Wrapper, { ...props, totalHeight: totalHeight, width: width },
116
+ return (react_1.default.createElement(Wrapper, { ...props, totalHeight: sequenceHeight, width: width },
98
117
  react_1.default.createElement(SequenceSVG, { ...props })));
99
118
  });
100
119
  exports.default = DivSequenceRendering;
@@ -31,9 +31,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
31
31
  isRightEndOfDisplayedRegion: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
32
32
  }, {
33
33
  renderInProgress: AbortController | undefined;
34
- /**
35
- * #method
36
- */
37
34
  filled: boolean;
38
35
  reactElement: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
39
36
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
@@ -43,8 +40,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
43
40
  message: string | undefined;
44
41
  maxHeightReached: boolean;
45
42
  ReactComponent: ({ model, }: {
46
- model: any;
47
- }) => any;
43
+ model: {
44
+ error?: unknown;
45
+ reload: () => void;
46
+ message: import("react").ReactNode;
47
+ filled?: boolean | undefined;
48
+ status?: string | undefined;
49
+ reactElement?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
50
+ };
51
+ }) => import("react").JSX.Element | undefined;
48
52
  renderProps: any;
49
53
  } & {
50
54
  doReload(): void;
@@ -66,22 +70,31 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
66
70
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
67
71
  maxFeatureScreenDensity: {
68
72
  type: string;
69
- description: string;
73
+ description: string; /**
74
+ * #property
75
+ */
70
76
  defaultValue: number;
71
77
  };
72
78
  fetchSizeLimit: {
73
- type: string;
79
+ type: string; /**
80
+ * #property
81
+ */
74
82
  defaultValue: number;
75
83
  description: string;
76
84
  };
77
85
  height: {
78
86
  type: string;
79
- defaultValue: number;
87
+ defaultValue: number; /**
88
+ * #property
89
+ */
80
90
  description: string;
81
91
  };
82
92
  mouseover: {
83
93
  type: string;
84
94
  description: string;
95
+ /**
96
+ * #getter
97
+ */
85
98
  defaultValue: string;
86
99
  contextVariable: string[];
87
100
  };
@@ -101,13 +114,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
101
114
  model: {
102
115
  id: string;
103
116
  type: string;
104
- rpcDriverName: string | undefined;
105
- } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
106
- rendererTypeName: string; /**
117
+ rpcDriverName: string | undefined; /**
107
118
  * #property
108
119
  */
120
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
121
+ rendererTypeName: string;
109
122
  error: unknown;
110
- message: string | undefined;
123
+ message: string | undefined; /**
124
+ * #property
125
+ */
111
126
  } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
112
127
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
113
128
  type: import("mobx-state-tree").ISimpleType<string>;
@@ -122,9 +137,7 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
122
137
  }>;
123
138
  readonly DisplayBlurb: import("react").FC<{
124
139
  model: {
125
- id: string; /**
126
- * #action
127
- */
140
+ id: string;
128
141
  type: string;
129
142
  rpcDriverName: string | undefined;
130
143
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -141,9 +154,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
141
154
  message: string | undefined;
142
155
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
143
156
  }> | null;
144
- /**
145
- * #method
146
- */
147
157
  readonly adapterConfig: any;
148
158
  readonly parentTrack: any;
149
159
  renderProps(): any;
@@ -160,13 +170,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
160
170
  } & {
161
171
  scrollTop: number;
162
172
  } & {
163
- readonly height: number;
164
- } & {
165
- setScrollTop(scrollTop: number): void; /**
173
+ readonly height: number; /**
166
174
  * #property
167
175
  */
176
+ } & {
177
+ setScrollTop(scrollTop: number): void;
168
178
  setHeight(displayHeight: number): number;
169
- resizeHeight(distance: number): number;
179
+ resizeHeight(distance: number): number; /**
180
+ * #getter
181
+ */
170
182
  } & {
171
183
  featureDensityStatsP: Promise<import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats> | undefined;
172
184
  featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined;
@@ -174,7 +186,9 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
174
186
  } & {
175
187
  readonly currentBytesRequested: number;
176
188
  readonly currentFeatureScreenDensity: number;
177
- readonly maxFeatureScreenDensity: any;
189
+ readonly maxFeatureScreenDensity: any; /**
190
+ * #method
191
+ */
178
192
  readonly featureDensityStatsReady: boolean;
179
193
  readonly maxAllowableBytes: number;
180
194
  } & {
@@ -225,6 +239,16 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
225
239
  } & {
226
240
  renderSvg(opts: import("@jbrowse/plugin-linear-genome-view").ExportSvgDisplayOptions): Promise<import("react").JSX.Element>;
227
241
  afterAttach(): void;
242
+ } & {
243
+ /**
244
+ * #property
245
+ */
246
+ rowHeight: number;
247
+ } & {
248
+ /**
249
+ * #getter
250
+ */
251
+ readonly sequenceHeight: number;
228
252
  } & {
229
253
  /**
230
254
  * #method
@@ -292,9 +316,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
292
316
  isRightEndOfDisplayedRegion: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
293
317
  }, {
294
318
  renderInProgress: AbortController | undefined;
295
- /**
296
- * #method
297
- */
298
319
  filled: boolean;
299
320
  reactElement: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
300
321
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
@@ -304,8 +325,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
304
325
  message: string | undefined;
305
326
  maxHeightReached: boolean;
306
327
  ReactComponent: ({ model, }: {
307
- model: any;
308
- }) => any;
328
+ model: {
329
+ error?: unknown;
330
+ reload: () => void;
331
+ message: import("react").ReactNode;
332
+ filled?: boolean | undefined;
333
+ status?: string | undefined;
334
+ reactElement?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
335
+ };
336
+ }) => import("react").JSX.Element | undefined;
309
337
  renderProps: any;
310
338
  } & {
311
339
  doReload(): void;
@@ -327,22 +355,31 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
327
355
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
328
356
  maxFeatureScreenDensity: {
329
357
  type: string;
330
- description: string;
358
+ description: string; /**
359
+ * #property
360
+ */
331
361
  defaultValue: number;
332
362
  };
333
363
  fetchSizeLimit: {
334
- type: string;
364
+ type: string; /**
365
+ * #property
366
+ */
335
367
  defaultValue: number;
336
368
  description: string;
337
369
  };
338
370
  height: {
339
371
  type: string;
340
- defaultValue: number;
372
+ defaultValue: number; /**
373
+ * #property
374
+ */
341
375
  description: string;
342
376
  };
343
377
  mouseover: {
344
378
  type: string;
345
379
  description: string;
380
+ /**
381
+ * #getter
382
+ */
346
383
  defaultValue: string;
347
384
  contextVariable: string[];
348
385
  };
@@ -4,6 +4,7 @@ exports.modelFactory = void 0;
4
4
  const mobx_state_tree_1 = require("mobx-state-tree");
5
5
  const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
6
6
  const configuration_1 = require("@jbrowse/core/configuration");
7
+ const tracks_1 = require("@jbrowse/core/util/tracks");
7
8
  const util_1 = require("@jbrowse/core/util");
8
9
  const mobx_1 = require("mobx");
9
10
  /**
@@ -33,6 +34,26 @@ function modelFactory(configSchema) {
33
34
  * #property
34
35
  */
35
36
  showTranslation: true,
37
+ }))
38
+ .volatile(() => ({
39
+ /**
40
+ * #property
41
+ */
42
+ rowHeight: 15,
43
+ }))
44
+ .views(self => ({
45
+ /**
46
+ * #getter
47
+ */
48
+ get sequenceHeight() {
49
+ const { showTranslation, showReverse, showForward } = self;
50
+ const r1 = showReverse && showTranslation ? self.rowHeight * 3 : 0;
51
+ const r2 = showForward && showTranslation ? self.rowHeight * 3 : 0;
52
+ const t = r1 + r2;
53
+ const r = showReverse ? self.rowHeight : 0;
54
+ const s = showForward ? self.rowHeight : 0;
55
+ return t + r + s;
56
+ },
36
57
  }))
37
58
  .views(self => {
38
59
  const { renderProps: superRenderProps } = self;
@@ -41,14 +62,17 @@ function modelFactory(configSchema) {
41
62
  * #method
42
63
  */
43
64
  renderProps() {
44
- const { showForward, rpcDriverName, showReverse, showTranslation } = self;
65
+ const { showForward, rpcDriverName, showReverse, showTranslation, rowHeight, sequenceHeight, } = self;
45
66
  return {
46
67
  ...superRenderProps(),
68
+ ...(0, tracks_1.getParentRenderProps)(self),
47
69
  config: self.configuration.renderer,
48
70
  rpcDriverName,
49
71
  showForward,
50
72
  showReverse,
51
73
  showTranslation,
74
+ rowHeight,
75
+ sequenceHeight,
52
76
  };
53
77
  },
54
78
  };
@@ -59,7 +83,7 @@ function modelFactory(configSchema) {
59
83
  */
60
84
  regionCannotBeRendered( /* region */) {
61
85
  const view = (0, util_1.getContainingView)(self);
62
- return (view === null || view === void 0 ? void 0 : view.bpPerPx) >= 1 ? 'Zoom in to see sequence' : undefined;
86
+ return (view === null || view === void 0 ? void 0 : view.bpPerPx) > 3 ? 'Zoom in to see sequence' : undefined;
63
87
  },
64
88
  /**
65
89
  * #getter
@@ -90,17 +114,11 @@ function modelFactory(configSchema) {
90
114
  afterAttach() {
91
115
  (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
92
116
  const view = (0, util_1.getContainingView)(self);
93
- if ((view === null || view === void 0 ? void 0 : view.bpPerPx) >= 1) {
117
+ if ((view === null || view === void 0 ? void 0 : view.bpPerPx) > 3) {
94
118
  self.setHeight(50);
95
119
  }
96
120
  else {
97
- const { showTranslation, showReverse, showForward } = self;
98
- const r1 = showReverse && showTranslation ? 60 : 0;
99
- const r2 = showForward && showTranslation ? 60 : 0;
100
- const t = r1 + r2;
101
- const r = showReverse ? 20 : 0;
102
- const s = showForward ? 20 : 0;
103
- self.setHeight(t + r + s);
121
+ self.setHeight(self.sequenceHeight);
104
122
  }
105
123
  }));
106
124
  },
@@ -8,7 +8,10 @@ declare const DivSequenceRendering: (props: {
8
8
  };
9
9
  features: Map<string, Feature>;
10
10
  regions: Region[];
11
+ colorByCDS: boolean;
11
12
  bpPerPx: number;
13
+ rowHeight: number;
14
+ sequenceHeight: number;
12
15
  config: AnyConfigurationModel;
13
16
  theme?: Theme;
14
17
  showForward?: boolean;
@@ -2,42 +2,54 @@ import React from 'react';
2
2
  import { createJBrowseTheme } from '@jbrowse/core/ui';
3
3
  import { observer } from 'mobx-react';
4
4
  import { bpSpanPx, revcom, complement, defaultStarts, defaultStops, defaultCodonTable, generateCodonTable, } from '@jbrowse/core/util';
5
- function Translation(props) {
6
- const { codonTable, seq, frame, bpPerPx, region, height, y, reverse = false, theme, } = props;
7
- const scale = bpPerPx;
8
- // the tilt variable normalizes the frame to where we are starting from,
9
- // which increases consistency across blocks
10
- const tilt = 3 - (region.start % 3);
11
- // the effectiveFrame incorporates tilt and the frame to say what the
12
- // effective frame that is plotted. The +3 is for when frame is -2 and this
13
- // can otherwise result in effectiveFrame -1
14
- const effectiveFrame = (frame + tilt + 3) % 3;
15
- const seqSliced = seq.slice(effectiveFrame);
5
+ function Translation({ codonTable, seq, frame, bpPerPx, colorByCDS, region, seqStart, height, y, reverse = false, theme, }) {
6
+ var _a, _b;
7
+ const normalizedFrame = Math.abs(frame) - 1;
8
+ const seqFrame = seqStart % 3;
9
+ const frameShift = (normalizedFrame - seqFrame + 3) % 3;
10
+ const frameShiftAdjustedSeqLength = seq.length - frameShift;
11
+ const multipleOfThreeLength = frameShiftAdjustedSeqLength - (frameShiftAdjustedSeqLength % 3);
12
+ const seqSliced = seq.slice(frameShift, frameShift + multipleOfThreeLength);
16
13
  const translated = [];
17
14
  for (let i = 0; i < seqSliced.length; i += 3) {
18
15
  const codon = seqSliced.slice(i, i + 3);
19
16
  const normalizedCodon = reverse ? revcom(codon) : codon;
20
17
  const aminoAcid = codonTable[normalizedCodon] || '';
21
- translated.push({ letter: aminoAcid, codon: normalizedCodon.toUpperCase() });
18
+ translated.push({
19
+ letter: aminoAcid,
20
+ codon: normalizedCodon.toUpperCase(),
21
+ });
22
22
  }
23
- const w = (1 / scale) * 3;
24
- const drop = region.start === 0 ? 0 : w;
25
- const render = 1 / bpPerPx >= 12;
26
23
  const width = (region.end - region.start) / bpPerPx;
27
- const map = ['#d8d8d8', '#adadad', '#8f8f8f'].reverse();
28
- return (React.createElement(React.Fragment, null, translated.map((element, index) => {
29
- const x = region.reversed
30
- ? width - (w * (index + 1) + effectiveFrame / scale - drop)
31
- : w * index + effectiveFrame / scale - drop;
32
- const { letter, codon } = element;
33
- return (React.createElement(React.Fragment, { key: `${index}-${letter}` },
34
- React.createElement("rect", { x: x, y: y, width: render ? w : w + 0.7 /* small fudge factor when zoomed out*/, height: height, stroke: render ? '#555' : 'none', fill: defaultStarts.includes(codon)
35
- ? theme === null || theme === void 0 ? void 0 : theme.palette.startCodon
36
- : defaultStops.includes(codon)
37
- ? theme === null || theme === void 0 ? void 0 : theme.palette.stopCodon
38
- : map[Math.abs(frame)] }),
39
- render ? (React.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle" }, letter)) : null));
40
- })));
24
+ const codonWidth = (1 / bpPerPx) * 3;
25
+ const renderLetter = 1 / bpPerPx >= 12;
26
+ const frameOffset = frameShift / bpPerPx;
27
+ const startOffset = (region.start - seqStart) / bpPerPx;
28
+ const offset = frameOffset - startOffset;
29
+ const defaultFill = colorByCDS
30
+ ? (_a = theme === null || theme === void 0 ? void 0 : theme.palette.framesCDS.at(frame)) === null || _a === void 0 ? void 0 : _a.main
31
+ : (_b = theme === null || theme === void 0 ? void 0 : theme.palette.frames.at(frame)) === null || _b === void 0 ? void 0 : _b.main;
32
+ return (React.createElement(React.Fragment, null,
33
+ React.createElement("rect", { x: 0, y: y, width: width, height: height, fill: defaultFill }),
34
+ translated.map((element, index) => {
35
+ const x = region.reversed
36
+ ? width - (index + 1) * codonWidth - offset
37
+ : codonWidth * index + offset;
38
+ const { letter, codon } = element;
39
+ const codonFill = defaultStarts.includes(codon)
40
+ ? theme === null || theme === void 0 ? void 0 : theme.palette.startCodon
41
+ : defaultStops.includes(codon)
42
+ ? theme === null || theme === void 0 ? void 0 : theme.palette.stopCodon
43
+ : undefined;
44
+ if (!(renderLetter || codonFill)) {
45
+ return null;
46
+ }
47
+ return (React.createElement(React.Fragment, { key: `${index}-${letter}` },
48
+ React.createElement("rect", { x: x, y: y, width: renderLetter
49
+ ? codonWidth
50
+ : codonWidth + 0.7 /* small fudge factor when zoomed out*/, height: height, stroke: renderLetter ? '#555' : 'none', fill: codonFill || 'none' }),
51
+ renderLetter ? (React.createElement("text", { x: x + codonWidth / 2, fontSize: height - 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle" }, letter)) : null));
52
+ })));
41
53
  }
42
54
  function DNA(props) {
43
55
  const { bpPerPx, region, feature, theme, height, seq, y } = props;
@@ -52,14 +64,13 @@ function DNA(props) {
52
64
  const x = reverse ? rightPx - (index + 1) * w : leftPx + index * w;
53
65
  return (React.createElement(React.Fragment, { key: index },
54
66
  React.createElement("rect", { x: x, y: y, width: w, height: height, fill: color ? color.main : '#aaa', stroke: render ? '#555' : 'none' }),
55
- render ? (React.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle", fill: color ? theme.palette.getContrastText(color.main) : 'black' }, letter)) : null));
67
+ render ? (React.createElement("text", { x: x + w / 2, y: y + height / 2, dominantBaseline: "middle", textAnchor: "middle", fontSize: height - 2, fill: color ? theme.palette.getContrastText(color.main) : 'black' }, letter)) : null));
56
68
  })));
57
69
  }
58
- function SequenceSVG({ regions, theme: configTheme, features = new Map(), showReverse = true, showForward = true, showTranslation = true, bpPerPx, }) {
70
+ function SequenceSVG({ regions, theme: configTheme, colorByCDS, features = new Map(), showReverse = true, showForward = true, showTranslation = true, bpPerPx, rowHeight, }) {
59
71
  const [region] = regions;
60
72
  const theme = createJBrowseTheme(configTheme);
61
73
  const codonTable = generateCodonTable(defaultCodonTable);
62
- const height = 20;
63
74
  const [feature] = [...features.values()];
64
75
  if (!feature) {
65
76
  return null;
@@ -70,26 +81,34 @@ function SequenceSVG({ regions, theme: configTheme, features = new Map(), showRe
70
81
  }
71
82
  // incrementer for the y-position of the current sequence being rendered
72
83
  // (applies to both translation rows and dna rows)
73
- let currY = -20;
84
+ let currY = -rowHeight;
85
+ const showDNA = bpPerPx <= 1;
86
+ const forwardFrames = showTranslation && showForward ? [3, 2, 1] : [];
87
+ const reverseFrames = showTranslation && showReverse ? [-1, -2, -3] : [];
88
+ // if region.reversed, the forward translation is on bottom, reverse on top
89
+ const [topFrames, bottomFrames] = region.reversed
90
+ ? [reverseFrames.toReversed(), forwardFrames.toReversed()]
91
+ : [forwardFrames, reverseFrames];
74
92
  return (React.createElement(React.Fragment, null,
75
- showTranslation && (region.reversed ? showReverse : showForward)
76
- ? [2, 1, 0].map(index => (React.createElement(Translation, { key: `translation-${index}`, seq: seq, y: (currY += 20), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, theme: theme, height: height, reverse: region.reversed })))
77
- : null,
78
- showForward ? (React.createElement(DNA, { height: height, y: (currY += 20), feature: feature, region: region, seq: region.reversed ? complement(seq) : seq, bpPerPx: bpPerPx, theme: theme })) : null,
79
- showReverse ? (React.createElement(DNA, { height: height, y: (currY += 20), feature: feature, region: region, seq: region.reversed ? seq : complement(seq), bpPerPx: bpPerPx, theme: theme })) : null,
80
- showTranslation && (region.reversed ? showForward : showReverse)
81
- ? [0, -1, -2].map(index => (React.createElement(Translation, { key: `rev-translation-${index}`, seq: seq, y: (currY += 20), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, theme: theme, height: height, reverse: !region.reversed })))
82
- : null));
93
+ topFrames.map(index => (React.createElement(Translation, { key: `translation-${index}`, colorByCDS: colorByCDS, seq: seq, y: (currY += rowHeight), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, seqStart: feature.get('start'), theme: theme, height: rowHeight, reverse: region.reversed }))),
94
+ showForward && showDNA ? (React.createElement(DNA, { height: rowHeight, y: (currY += rowHeight), feature: feature, region: region, seq: region.reversed ? complement(seq) : seq, bpPerPx: bpPerPx, theme: theme })) : null,
95
+ showReverse && showDNA ? (React.createElement(DNA, { height: rowHeight, y: (currY += rowHeight), feature: feature, region: region, seq: region.reversed ? seq : complement(seq), bpPerPx: bpPerPx, theme: theme })) : null,
96
+ bottomFrames.map(index => (React.createElement(Translation, { key: `rev-translation-${index}`, colorByCDS: colorByCDS, seq: seq, y: (currY += rowHeight), codonTable: codonTable, frame: index, bpPerPx: bpPerPx, region: region, seqStart: feature.get('start'), theme: theme, height: rowHeight, reverse: !region.reversed })))));
83
97
  }
84
98
  function Wrapper({ exportSVG, width, totalHeight, children, }) {
85
- return exportSVG ? (React.createElement(React.Fragment, null, children)) : (React.createElement("svg", { "data-testid": "sequence_track", width: width, height: totalHeight, style: { width, height: totalHeight, userSelect: 'none' } }, children));
99
+ return exportSVG ? (children) : (React.createElement("svg", { "data-testid": "sequence_track", width: width, height: totalHeight, style: {
100
+ // use block because svg by default is inline, which adds a margin
101
+ display: 'block',
102
+ width,
103
+ height: totalHeight,
104
+ userSelect: 'none',
105
+ } }, children));
86
106
  }
87
107
  const DivSequenceRendering = observer(function (props) {
88
- const { regions, bpPerPx } = props;
108
+ const { regions, bpPerPx, sequenceHeight } = props;
89
109
  const [region] = regions;
90
110
  const width = (region.end - region.start) / bpPerPx;
91
- const totalHeight = 200;
92
- return (React.createElement(Wrapper, { ...props, totalHeight: totalHeight, width: width },
111
+ return (React.createElement(Wrapper, { ...props, totalHeight: sequenceHeight, width: width },
93
112
  React.createElement(SequenceSVG, { ...props })));
94
113
  });
95
114
  export default DivSequenceRendering;
@@ -31,9 +31,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
31
31
  isRightEndOfDisplayedRegion: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
32
32
  }, {
33
33
  renderInProgress: AbortController | undefined;
34
- /**
35
- * #method
36
- */
37
34
  filled: boolean;
38
35
  reactElement: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
39
36
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
@@ -43,8 +40,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
43
40
  message: string | undefined;
44
41
  maxHeightReached: boolean;
45
42
  ReactComponent: ({ model, }: {
46
- model: any;
47
- }) => any;
43
+ model: {
44
+ error?: unknown;
45
+ reload: () => void;
46
+ message: import("react").ReactNode;
47
+ filled?: boolean | undefined;
48
+ status?: string | undefined;
49
+ reactElement?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
50
+ };
51
+ }) => import("react").JSX.Element | undefined;
48
52
  renderProps: any;
49
53
  } & {
50
54
  doReload(): void;
@@ -66,22 +70,31 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
66
70
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
67
71
  maxFeatureScreenDensity: {
68
72
  type: string;
69
- description: string;
73
+ description: string; /**
74
+ * #property
75
+ */
70
76
  defaultValue: number;
71
77
  };
72
78
  fetchSizeLimit: {
73
- type: string;
79
+ type: string; /**
80
+ * #property
81
+ */
74
82
  defaultValue: number;
75
83
  description: string;
76
84
  };
77
85
  height: {
78
86
  type: string;
79
- defaultValue: number;
87
+ defaultValue: number; /**
88
+ * #property
89
+ */
80
90
  description: string;
81
91
  };
82
92
  mouseover: {
83
93
  type: string;
84
94
  description: string;
95
+ /**
96
+ * #getter
97
+ */
85
98
  defaultValue: string;
86
99
  contextVariable: string[];
87
100
  };
@@ -101,13 +114,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
101
114
  model: {
102
115
  id: string;
103
116
  type: string;
104
- rpcDriverName: string | undefined;
105
- } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
106
- rendererTypeName: string; /**
117
+ rpcDriverName: string | undefined; /**
107
118
  * #property
108
119
  */
120
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
121
+ rendererTypeName: string;
109
122
  error: unknown;
110
- message: string | undefined;
123
+ message: string | undefined; /**
124
+ * #property
125
+ */
111
126
  } & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
112
127
  id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
113
128
  type: import("mobx-state-tree").ISimpleType<string>;
@@ -122,9 +137,7 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
122
137
  }>;
123
138
  readonly DisplayBlurb: import("react").FC<{
124
139
  model: {
125
- id: string; /**
126
- * #action
127
- */
140
+ id: string;
128
141
  type: string;
129
142
  rpcDriverName: string | undefined;
130
143
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -141,9 +154,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
141
154
  message: string | undefined;
142
155
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
143
156
  }> | null;
144
- /**
145
- * #method
146
- */
147
157
  readonly adapterConfig: any;
148
158
  readonly parentTrack: any;
149
159
  renderProps(): any;
@@ -160,13 +170,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
160
170
  } & {
161
171
  scrollTop: number;
162
172
  } & {
163
- readonly height: number;
164
- } & {
165
- setScrollTop(scrollTop: number): void; /**
173
+ readonly height: number; /**
166
174
  * #property
167
175
  */
176
+ } & {
177
+ setScrollTop(scrollTop: number): void;
168
178
  setHeight(displayHeight: number): number;
169
- resizeHeight(distance: number): number;
179
+ resizeHeight(distance: number): number; /**
180
+ * #getter
181
+ */
170
182
  } & {
171
183
  featureDensityStatsP: Promise<import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats> | undefined;
172
184
  featureDensityStats: import("@jbrowse/core/data_adapters/BaseAdapter").FeatureDensityStats | undefined;
@@ -174,7 +186,9 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
174
186
  } & {
175
187
  readonly currentBytesRequested: number;
176
188
  readonly currentFeatureScreenDensity: number;
177
- readonly maxFeatureScreenDensity: any;
189
+ readonly maxFeatureScreenDensity: any; /**
190
+ * #method
191
+ */
178
192
  readonly featureDensityStatsReady: boolean;
179
193
  readonly maxAllowableBytes: number;
180
194
  } & {
@@ -225,6 +239,16 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
225
239
  } & {
226
240
  renderSvg(opts: import("@jbrowse/plugin-linear-genome-view").ExportSvgDisplayOptions): Promise<import("react").JSX.Element>;
227
241
  afterAttach(): void;
242
+ } & {
243
+ /**
244
+ * #property
245
+ */
246
+ rowHeight: number;
247
+ } & {
248
+ /**
249
+ * #getter
250
+ */
251
+ readonly sequenceHeight: number;
228
252
  } & {
229
253
  /**
230
254
  * #method
@@ -292,9 +316,6 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
292
316
  isRightEndOfDisplayedRegion: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
293
317
  }, {
294
318
  renderInProgress: AbortController | undefined;
295
- /**
296
- * #method
297
- */
298
319
  filled: boolean;
299
320
  reactElement: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
300
321
  features: Map<string, import("@jbrowse/core/util").Feature> | undefined;
@@ -304,8 +325,15 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
304
325
  message: string | undefined;
305
326
  maxHeightReached: boolean;
306
327
  ReactComponent: ({ model, }: {
307
- model: any;
308
- }) => any;
328
+ model: {
329
+ error?: unknown;
330
+ reload: () => void;
331
+ message: import("react").ReactNode;
332
+ filled?: boolean | undefined;
333
+ status?: string | undefined;
334
+ reactElement?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | undefined;
335
+ };
336
+ }) => import("react").JSX.Element | undefined;
309
337
  renderProps: any;
310
338
  } & {
311
339
  doReload(): void;
@@ -327,22 +355,31 @@ export declare function modelFactory(configSchema: AnyConfigurationSchemaType):
327
355
  configuration: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
328
356
  maxFeatureScreenDensity: {
329
357
  type: string;
330
- description: string;
358
+ description: string; /**
359
+ * #property
360
+ */
331
361
  defaultValue: number;
332
362
  };
333
363
  fetchSizeLimit: {
334
- type: string;
364
+ type: string; /**
365
+ * #property
366
+ */
335
367
  defaultValue: number;
336
368
  description: string;
337
369
  };
338
370
  height: {
339
371
  type: string;
340
- defaultValue: number;
372
+ defaultValue: number; /**
373
+ * #property
374
+ */
341
375
  description: string;
342
376
  };
343
377
  mouseover: {
344
378
  type: string;
345
379
  description: string;
380
+ /**
381
+ * #getter
382
+ */
346
383
  defaultValue: string;
347
384
  contextVariable: string[];
348
385
  };
@@ -1,6 +1,7 @@
1
1
  import { addDisposer, types } from 'mobx-state-tree';
2
2
  import { BaseLinearDisplay, } from '@jbrowse/plugin-linear-genome-view';
3
3
  import { ConfigurationReference, } from '@jbrowse/core/configuration';
4
+ import { getParentRenderProps } from '@jbrowse/core/util/tracks';
4
5
  import { getContainingView } from '@jbrowse/core/util';
5
6
  import { autorun } from 'mobx';
6
7
  /**
@@ -30,6 +31,26 @@ export function modelFactory(configSchema) {
30
31
  * #property
31
32
  */
32
33
  showTranslation: true,
34
+ }))
35
+ .volatile(() => ({
36
+ /**
37
+ * #property
38
+ */
39
+ rowHeight: 15,
40
+ }))
41
+ .views(self => ({
42
+ /**
43
+ * #getter
44
+ */
45
+ get sequenceHeight() {
46
+ const { showTranslation, showReverse, showForward } = self;
47
+ const r1 = showReverse && showTranslation ? self.rowHeight * 3 : 0;
48
+ const r2 = showForward && showTranslation ? self.rowHeight * 3 : 0;
49
+ const t = r1 + r2;
50
+ const r = showReverse ? self.rowHeight : 0;
51
+ const s = showForward ? self.rowHeight : 0;
52
+ return t + r + s;
53
+ },
33
54
  }))
34
55
  .views(self => {
35
56
  const { renderProps: superRenderProps } = self;
@@ -38,14 +59,17 @@ export function modelFactory(configSchema) {
38
59
  * #method
39
60
  */
40
61
  renderProps() {
41
- const { showForward, rpcDriverName, showReverse, showTranslation } = self;
62
+ const { showForward, rpcDriverName, showReverse, showTranslation, rowHeight, sequenceHeight, } = self;
42
63
  return {
43
64
  ...superRenderProps(),
65
+ ...getParentRenderProps(self),
44
66
  config: self.configuration.renderer,
45
67
  rpcDriverName,
46
68
  showForward,
47
69
  showReverse,
48
70
  showTranslation,
71
+ rowHeight,
72
+ sequenceHeight,
49
73
  };
50
74
  },
51
75
  };
@@ -56,7 +80,7 @@ export function modelFactory(configSchema) {
56
80
  */
57
81
  regionCannotBeRendered( /* region */) {
58
82
  const view = getContainingView(self);
59
- return (view === null || view === void 0 ? void 0 : view.bpPerPx) >= 1 ? 'Zoom in to see sequence' : undefined;
83
+ return (view === null || view === void 0 ? void 0 : view.bpPerPx) > 3 ? 'Zoom in to see sequence' : undefined;
60
84
  },
61
85
  /**
62
86
  * #getter
@@ -87,17 +111,11 @@ export function modelFactory(configSchema) {
87
111
  afterAttach() {
88
112
  addDisposer(self, autorun(() => {
89
113
  const view = getContainingView(self);
90
- if ((view === null || view === void 0 ? void 0 : view.bpPerPx) >= 1) {
114
+ if ((view === null || view === void 0 ? void 0 : view.bpPerPx) > 3) {
91
115
  self.setHeight(50);
92
116
  }
93
117
  else {
94
- const { showTranslation, showReverse, showForward } = self;
95
- const r1 = showReverse && showTranslation ? 60 : 0;
96
- const r2 = showForward && showTranslation ? 60 : 0;
97
- const t = r1 + r2;
98
- const r = showReverse ? 20 : 0;
99
- const s = showForward ? 20 : 0;
100
- self.setHeight(t + r + s);
118
+ self.setHeight(self.sequenceHeight);
101
119
  }
102
120
  }));
103
121
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-sequence",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "JBrowse 2 sequence adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -57,5 +57,5 @@
57
57
  "distModule": "esm/index.js",
58
58
  "srcModule": "src/index.ts",
59
59
  "module": "esm/index.js",
60
- "gitHead": "7ca3b7db337ebd88853e2d96cdab940ed550c4fb"
60
+ "gitHead": "3d43a820b9274a6160aa4dc15616147f390d9094"
61
61
  }