@teselagen/ove 0.8.17 → 0.8.19

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.
package/index.cjs.js CHANGED
@@ -8349,6 +8349,15 @@ function baseLt(value, other) {
8349
8349
  return value < other;
8350
8350
  }
8351
8351
  __name(baseLt, "baseLt");
8352
+ function mapValues$1(object3, iteratee) {
8353
+ var result = {};
8354
+ iteratee = baseIteratee(iteratee);
8355
+ baseForOwn(object3, function(value, key, object4) {
8356
+ baseAssignValue(result, key, iteratee(value, key, object4));
8357
+ });
8358
+ return result;
8359
+ }
8360
+ __name(mapValues$1, "mapValues$1");
8352
8361
  function baseExtremum(array2, iteratee, comparator) {
8353
8362
  var index2 = -1, length = array2.length;
8354
8363
  while (++index2 < length) {
@@ -13213,12 +13222,12 @@ var getComputedStyleX;
13213
13222
  if (typeof window !== "undefined") {
13214
13223
  getComputedStyleX = window.getComputedStyle ? _getComputedStyle : _getComputedStyleIE;
13215
13224
  }
13216
- function each$2(arr, fn4) {
13225
+ function each(arr, fn4) {
13217
13226
  for (var i = 0; i < arr.length; i++) {
13218
13227
  fn4(arr[i]);
13219
13228
  }
13220
13229
  }
13221
- __name(each$2, "each$2");
13230
+ __name(each, "each");
13222
13231
  function isBorderBoxFn(elem) {
13223
13232
  return getComputedStyleX(elem, "boxSizing") === "border-box";
13224
13233
  }
@@ -13273,7 +13282,7 @@ function isWindow(obj) {
13273
13282
  }
13274
13283
  __name(isWindow, "isWindow");
13275
13284
  var domUtils = {};
13276
- each$2(["Width", "Height"], function(name2) {
13285
+ each(["Width", "Height"], function(name2) {
13277
13286
  domUtils["doc".concat(name2)] = function(refWin) {
13278
13287
  var d2 = refWin.document;
13279
13288
  return Math.max(
@@ -13369,7 +13378,7 @@ function css(el, name2, v2) {
13369
13378
  return getComputedStyleX(el, name2);
13370
13379
  }
13371
13380
  __name(css, "css");
13372
- each$2(["width", "height"], function(name2) {
13381
+ each(["width", "height"], function(name2) {
13373
13382
  var first = name2.charAt(0).toUpperCase() + name2.slice(1);
13374
13383
  domUtils["outer".concat(first)] = function(el, includeMargin) {
13375
13384
  return el && getWHIgnoreDisplay(el, name2, includeMargin ? MARGIN_INDEX : BORDER_INDEX);
@@ -13420,7 +13429,7 @@ var util$2 = _objectSpread2$2({
13420
13429
  }
13421
13430
  }, "offset"),
13422
13431
  isWindow,
13423
- each: each$2,
13432
+ each,
13424
13433
  css,
13425
13434
  clone: /* @__PURE__ */ __name(function clone(obj) {
13426
13435
  var ret = {};
@@ -75209,17 +75218,25 @@ function tidyUpSequenceData(pSeqData, options = {}) {
75209
75218
  });
75210
75219
  if (!noTranslationData) {
75211
75220
  seqData.translations = flatMap(seqData.translations, (translation) => {
75221
+ var _a2, _b2;
75212
75222
  if (noCdsTranslations && translation.translationType === "CDS Feature") {
75213
75223
  return [];
75214
75224
  }
75215
- if (!translation.aminoAcids && !seqData.noSequence) {
75216
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
75225
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
75226
+ const expandedRange = expandOrContractRangeByLength(
75227
+ translation,
75228
+ -codonStart,
75229
+ true,
75230
+ seqData.sequence.length
75231
+ );
75232
+ if (!expandedRange.aminoAcids && !seqData.noSequence) {
75233
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
75217
75234
  seqData.sequence,
75218
- translation.forward,
75219
- translation
75235
+ expandedRange.forward,
75236
+ expandedRange
75220
75237
  );
75221
75238
  }
75222
- return translation;
75239
+ return expandedRange;
75223
75240
  });
75224
75241
  }
75225
75242
  if (annotationsAsObjects) {
@@ -97810,32 +97827,6 @@ const orfsSelector = createSelector(
97810
97827
  (state2) => state2.useAdditionalOrfStartCodons,
97811
97828
  findOrfsInPlasmid
97812
97829
  );
97813
- var forEach_1;
97814
- var hasRequiredForEach;
97815
- function requireForEach() {
97816
- if (hasRequiredForEach) return forEach_1;
97817
- hasRequiredForEach = 1;
97818
- var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
97819
- function forEach3(collection, iteratee) {
97820
- var func = isArray2(collection) ? arrayEach2 : baseEach2;
97821
- return func(collection, castFunction2(iteratee));
97822
- }
97823
- __name(forEach3, "forEach");
97824
- forEach_1 = forEach3;
97825
- return forEach_1;
97826
- }
97827
- __name(requireForEach, "requireForEach");
97828
- var each$1;
97829
- var hasRequiredEach;
97830
- function requireEach() {
97831
- if (hasRequiredEach) return each$1;
97832
- hasRequiredEach = 1;
97833
- each$1 = requireForEach();
97834
- return each$1;
97835
- }
97836
- __name(requireEach, "requireEach");
97837
- var eachExports = requireEach();
97838
- const each = /* @__PURE__ */ getDefaultExportFromCjs(eachExports);
97839
97830
  function translationsRawSelector(sequenceData2) {
97840
97831
  return sequenceData2.translations;
97841
97832
  }
@@ -98002,14 +97993,22 @@ function translationsSelector(isCircular, translationSearchMatches, sequence2, o
98002
97993
  },
98003
97994
  {}
98004
97995
  ));
98005
- each(translationsToPass, function(translation) {
98006
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
97996
+ return mapValues$1(translationsToPass, (translation) => {
97997
+ var _a2, _b2;
97998
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
97999
+ const expandedRange = expandOrContractRangeByLength(
98000
+ translation,
98001
+ -codonStart,
98002
+ true,
98003
+ sequence2.length
98004
+ );
98005
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
98007
98006
  sequence2,
98008
- translation.forward,
98009
- translation
98007
+ expandedRange.forward,
98008
+ expandedRange
98010
98009
  );
98010
+ return expandedRange;
98011
98011
  });
98012
- return translationsToPass;
98013
98012
  }
98014
98013
  __name(translationsSelector, "translationsSelector");
98015
98014
  const translationsSelector$1 = createSelector(
@@ -109885,6 +109884,21 @@ function Orf(props) {
109885
109884
  );
109886
109885
  }
109887
109886
  __name(Orf, "Orf");
109887
+ var forEach_1;
109888
+ var hasRequiredForEach;
109889
+ function requireForEach() {
109890
+ if (hasRequiredForEach) return forEach_1;
109891
+ hasRequiredForEach = 1;
109892
+ var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
109893
+ function forEach3(collection, iteratee) {
109894
+ var func = isArray2(collection) ? arrayEach2 : baseEach2;
109895
+ return func(collection, castFunction2(iteratee));
109896
+ }
109897
+ __name(forEach3, "forEach");
109898
+ forEach_1 = forEach3;
109899
+ return forEach_1;
109900
+ }
109901
+ __name(requireForEach, "requireForEach");
109888
109902
  var forEachExports = requireForEach();
109889
109903
  const forEach2 = /* @__PURE__ */ getDefaultExportFromCjs(forEachExports);
109890
109904
  var lib = {};
@@ -116640,7 +116654,7 @@ function showFileDialog({ multiple = false, onSelect }) {
116640
116654
  input.click();
116641
116655
  }
116642
116656
  __name(showFileDialog, "showFileDialog");
116643
- const version = "0.8.16";
116657
+ const version = "0.8.18";
116644
116658
  const packageJson = {
116645
116659
  version
116646
116660
  };
@@ -124292,6 +124306,7 @@ const __LinearView = class __LinearView extends React.Component {
124292
124306
  RowItem$1,
124293
124307
  __spreadProps(__spreadValues({}, __spreadValues(__spreadProps(__spreadValues({}, rest), {
124294
124308
  editorName,
124309
+ showAminoAcidUnitAsCodon,
124295
124310
  onScroll: /* @__PURE__ */ __name(() => {
124296
124311
  this.easyStore.viewportWidth = width;
124297
124312
  const row = this.linearView.querySelector(".veRowItemWrapper");
@@ -138096,7 +138111,7 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
138096
138111
  item: selection && selection.start > -1 ? /* @__PURE__ */ React.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size),
138097
138112
  title: "Region"
138098
138113
  }
138099
- )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Amino Acid"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
138114
+ )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
138100
138115
  return /* @__PURE__ */ React.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
138101
138116
  })));
138102
138117
  } else {
@@ -138596,7 +138611,11 @@ ${seqDataToCopy}\r
138596
138611
  }, [alignmentTracks, id2, store2]);
138597
138612
  React.useEffect(() => {
138598
138613
  const handleAlignmentCopy = /* @__PURE__ */ __name((event) => {
138614
+ var _a3, _b2, _c;
138599
138615
  if (event.key === "c" && !event.shiftKey && (event.metaKey === true || event.ctrlKey === true)) {
138616
+ if (!((_a3 = document.activeElement) == null ? void 0 : _a3.classList.contains("alignmentView"))) {
138617
+ return;
138618
+ }
138600
138619
  const input = document.createElement("textarea");
138601
138620
  document.body.appendChild(input);
138602
138621
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -138610,6 +138629,8 @@ ${seqDataToCopy}\r
138610
138629
  }
138611
138630
  document.body.removeChild(input);
138612
138631
  event.preventDefault();
138632
+ (_b2 = document.activeElement) == null ? void 0 : _b2.blur();
138633
+ (_c = document.querySelector(".alignmentView")) == null ? void 0 : _c.focus();
138613
138634
  }
138614
138635
  }, "handleAlignmentCopy");
138615
138636
  document.addEventListener("keydown", handleAlignmentCopy);
@@ -139768,6 +139789,7 @@ ${seqDataToCopy}\r
139768
139789
  position: "relative",
139769
139790
  overflowY: "auto"
139770
139791
  }, style2),
139792
+ tabIndex: 0,
139771
139793
  className: "alignmentView"
139772
139794
  },
139773
139795
  /* @__PURE__ */ React.createElement(
@@ -143607,7 +143629,7 @@ const genericAnnotationProperties = /* @__PURE__ */ __name(({
143607
143629
  this.commands = getCommands(this);
143608
143630
  }
143609
143631
  render() {
143610
- var _a2, _b2;
143632
+ var _a2, _b2, _c;
143611
143633
  const {
143612
143634
  readOnly: readOnly2,
143613
143635
  annotations = {},
@@ -143631,7 +143653,9 @@ const genericAnnotationProperties = /* @__PURE__ */ __name(({
143631
143653
  });
143632
143654
  });
143633
143655
  const keyedPartTags = (_a2 = getKeyedTagsAndTagOptions(allPartTags)) != null ? _a2 : {};
143634
- const additionalColumns = ((_b2 = PropertiesProps == null ? void 0 : PropertiesProps[annotationType]) == null ? void 0 : _b2.additionalColumns) || [];
143656
+ const additionalColumns = ((_c = (_b2 = PropertiesProps == null ? void 0 : PropertiesProps.propertiesList) == null ? void 0 : _b2.find(
143657
+ (p2) => (p2.name || p2) === (pluralize(annotationType) || "")
143658
+ )) == null ? void 0 : _c.additionalColumns) || [];
143635
143659
  this.schema = {
143636
143660
  fields: [
143637
143661
  {
package/index.es.js CHANGED
@@ -8331,6 +8331,15 @@ function baseLt(value, other) {
8331
8331
  return value < other;
8332
8332
  }
8333
8333
  __name(baseLt, "baseLt");
8334
+ function mapValues$1(object3, iteratee) {
8335
+ var result = {};
8336
+ iteratee = baseIteratee(iteratee);
8337
+ baseForOwn(object3, function(value, key, object4) {
8338
+ baseAssignValue(result, key, iteratee(value, key, object4));
8339
+ });
8340
+ return result;
8341
+ }
8342
+ __name(mapValues$1, "mapValues$1");
8334
8343
  function baseExtremum(array2, iteratee, comparator) {
8335
8344
  var index2 = -1, length = array2.length;
8336
8345
  while (++index2 < length) {
@@ -13195,12 +13204,12 @@ var getComputedStyleX;
13195
13204
  if (typeof window !== "undefined") {
13196
13205
  getComputedStyleX = window.getComputedStyle ? _getComputedStyle : _getComputedStyleIE;
13197
13206
  }
13198
- function each$2(arr, fn4) {
13207
+ function each(arr, fn4) {
13199
13208
  for (var i = 0; i < arr.length; i++) {
13200
13209
  fn4(arr[i]);
13201
13210
  }
13202
13211
  }
13203
- __name(each$2, "each$2");
13212
+ __name(each, "each");
13204
13213
  function isBorderBoxFn(elem) {
13205
13214
  return getComputedStyleX(elem, "boxSizing") === "border-box";
13206
13215
  }
@@ -13255,7 +13264,7 @@ function isWindow(obj) {
13255
13264
  }
13256
13265
  __name(isWindow, "isWindow");
13257
13266
  var domUtils = {};
13258
- each$2(["Width", "Height"], function(name2) {
13267
+ each(["Width", "Height"], function(name2) {
13259
13268
  domUtils["doc".concat(name2)] = function(refWin) {
13260
13269
  var d2 = refWin.document;
13261
13270
  return Math.max(
@@ -13351,7 +13360,7 @@ function css(el, name2, v2) {
13351
13360
  return getComputedStyleX(el, name2);
13352
13361
  }
13353
13362
  __name(css, "css");
13354
- each$2(["width", "height"], function(name2) {
13363
+ each(["width", "height"], function(name2) {
13355
13364
  var first = name2.charAt(0).toUpperCase() + name2.slice(1);
13356
13365
  domUtils["outer".concat(first)] = function(el, includeMargin) {
13357
13366
  return el && getWHIgnoreDisplay(el, name2, includeMargin ? MARGIN_INDEX : BORDER_INDEX);
@@ -13402,7 +13411,7 @@ var util$2 = _objectSpread2$2({
13402
13411
  }
13403
13412
  }, "offset"),
13404
13413
  isWindow,
13405
- each: each$2,
13414
+ each,
13406
13415
  css,
13407
13416
  clone: /* @__PURE__ */ __name(function clone(obj) {
13408
13417
  var ret = {};
@@ -75191,17 +75200,25 @@ function tidyUpSequenceData(pSeqData, options = {}) {
75191
75200
  });
75192
75201
  if (!noTranslationData) {
75193
75202
  seqData.translations = flatMap(seqData.translations, (translation) => {
75203
+ var _a2, _b2;
75194
75204
  if (noCdsTranslations && translation.translationType === "CDS Feature") {
75195
75205
  return [];
75196
75206
  }
75197
- if (!translation.aminoAcids && !seqData.noSequence) {
75198
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
75207
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
75208
+ const expandedRange = expandOrContractRangeByLength(
75209
+ translation,
75210
+ -codonStart,
75211
+ true,
75212
+ seqData.sequence.length
75213
+ );
75214
+ if (!expandedRange.aminoAcids && !seqData.noSequence) {
75215
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
75199
75216
  seqData.sequence,
75200
- translation.forward,
75201
- translation
75217
+ expandedRange.forward,
75218
+ expandedRange
75202
75219
  );
75203
75220
  }
75204
- return translation;
75221
+ return expandedRange;
75205
75222
  });
75206
75223
  }
75207
75224
  if (annotationsAsObjects) {
@@ -97792,32 +97809,6 @@ const orfsSelector = createSelector(
97792
97809
  (state2) => state2.useAdditionalOrfStartCodons,
97793
97810
  findOrfsInPlasmid
97794
97811
  );
97795
- var forEach_1;
97796
- var hasRequiredForEach;
97797
- function requireForEach() {
97798
- if (hasRequiredForEach) return forEach_1;
97799
- hasRequiredForEach = 1;
97800
- var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
97801
- function forEach3(collection, iteratee) {
97802
- var func = isArray2(collection) ? arrayEach2 : baseEach2;
97803
- return func(collection, castFunction2(iteratee));
97804
- }
97805
- __name(forEach3, "forEach");
97806
- forEach_1 = forEach3;
97807
- return forEach_1;
97808
- }
97809
- __name(requireForEach, "requireForEach");
97810
- var each$1;
97811
- var hasRequiredEach;
97812
- function requireEach() {
97813
- if (hasRequiredEach) return each$1;
97814
- hasRequiredEach = 1;
97815
- each$1 = requireForEach();
97816
- return each$1;
97817
- }
97818
- __name(requireEach, "requireEach");
97819
- var eachExports = requireEach();
97820
- const each = /* @__PURE__ */ getDefaultExportFromCjs(eachExports);
97821
97812
  function translationsRawSelector(sequenceData2) {
97822
97813
  return sequenceData2.translations;
97823
97814
  }
@@ -97984,14 +97975,22 @@ function translationsSelector(isCircular, translationSearchMatches, sequence2, o
97984
97975
  },
97985
97976
  {}
97986
97977
  ));
97987
- each(translationsToPass, function(translation) {
97988
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
97978
+ return mapValues$1(translationsToPass, (translation) => {
97979
+ var _a2, _b2;
97980
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
97981
+ const expandedRange = expandOrContractRangeByLength(
97982
+ translation,
97983
+ -codonStart,
97984
+ true,
97985
+ sequence2.length
97986
+ );
97987
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
97989
97988
  sequence2,
97990
- translation.forward,
97991
- translation
97989
+ expandedRange.forward,
97990
+ expandedRange
97992
97991
  );
97992
+ return expandedRange;
97993
97993
  });
97994
- return translationsToPass;
97995
97994
  }
97996
97995
  __name(translationsSelector, "translationsSelector");
97997
97996
  const translationsSelector$1 = createSelector(
@@ -109867,6 +109866,21 @@ function Orf(props) {
109867
109866
  );
109868
109867
  }
109869
109868
  __name(Orf, "Orf");
109869
+ var forEach_1;
109870
+ var hasRequiredForEach;
109871
+ function requireForEach() {
109872
+ if (hasRequiredForEach) return forEach_1;
109873
+ hasRequiredForEach = 1;
109874
+ var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
109875
+ function forEach3(collection, iteratee) {
109876
+ var func = isArray2(collection) ? arrayEach2 : baseEach2;
109877
+ return func(collection, castFunction2(iteratee));
109878
+ }
109879
+ __name(forEach3, "forEach");
109880
+ forEach_1 = forEach3;
109881
+ return forEach_1;
109882
+ }
109883
+ __name(requireForEach, "requireForEach");
109870
109884
  var forEachExports = requireForEach();
109871
109885
  const forEach2 = /* @__PURE__ */ getDefaultExportFromCjs(forEachExports);
109872
109886
  var lib = {};
@@ -116622,7 +116636,7 @@ function showFileDialog({ multiple = false, onSelect }) {
116622
116636
  input.click();
116623
116637
  }
116624
116638
  __name(showFileDialog, "showFileDialog");
116625
- const version = "0.8.16";
116639
+ const version = "0.8.18";
116626
116640
  const packageJson = {
116627
116641
  version
116628
116642
  };
@@ -124274,6 +124288,7 @@ const __LinearView = class __LinearView extends React__default.Component {
124274
124288
  RowItem$1,
124275
124289
  __spreadProps(__spreadValues({}, __spreadValues(__spreadProps(__spreadValues({}, rest), {
124276
124290
  editorName,
124291
+ showAminoAcidUnitAsCodon,
124277
124292
  onScroll: /* @__PURE__ */ __name(() => {
124278
124293
  this.easyStore.viewportWidth = width;
124279
124294
  const row = this.linearView.querySelector(".veRowItemWrapper");
@@ -138078,7 +138093,7 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
138078
138093
  item: selection && selection.start > -1 ? /* @__PURE__ */ React__default.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React__default.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size),
138079
138094
  title: "Region"
138080
138095
  }
138081
- )), /* @__PURE__ */ React__default.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Amino Acid"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
138096
+ )), /* @__PURE__ */ React__default.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
138082
138097
  return /* @__PURE__ */ React__default.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
138083
138098
  })));
138084
138099
  } else {
@@ -138578,7 +138593,11 @@ ${seqDataToCopy}\r
138578
138593
  }, [alignmentTracks, id2, store2]);
138579
138594
  useEffect(() => {
138580
138595
  const handleAlignmentCopy = /* @__PURE__ */ __name((event) => {
138596
+ var _a3, _b2, _c;
138581
138597
  if (event.key === "c" && !event.shiftKey && (event.metaKey === true || event.ctrlKey === true)) {
138598
+ if (!((_a3 = document.activeElement) == null ? void 0 : _a3.classList.contains("alignmentView"))) {
138599
+ return;
138600
+ }
138582
138601
  const input = document.createElement("textarea");
138583
138602
  document.body.appendChild(input);
138584
138603
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -138592,6 +138611,8 @@ ${seqDataToCopy}\r
138592
138611
  }
138593
138612
  document.body.removeChild(input);
138594
138613
  event.preventDefault();
138614
+ (_b2 = document.activeElement) == null ? void 0 : _b2.blur();
138615
+ (_c = document.querySelector(".alignmentView")) == null ? void 0 : _c.focus();
138595
138616
  }
138596
138617
  }, "handleAlignmentCopy");
138597
138618
  document.addEventListener("keydown", handleAlignmentCopy);
@@ -139750,6 +139771,7 @@ ${seqDataToCopy}\r
139750
139771
  position: "relative",
139751
139772
  overflowY: "auto"
139752
139773
  }, style2),
139774
+ tabIndex: 0,
139753
139775
  className: "alignmentView"
139754
139776
  },
139755
139777
  /* @__PURE__ */ React__default.createElement(
@@ -143589,7 +143611,7 @@ const genericAnnotationProperties = /* @__PURE__ */ __name(({
143589
143611
  this.commands = getCommands(this);
143590
143612
  }
143591
143613
  render() {
143592
- var _a2, _b2;
143614
+ var _a2, _b2, _c;
143593
143615
  const {
143594
143616
  readOnly: readOnly2,
143595
143617
  annotations = {},
@@ -143613,7 +143635,9 @@ const genericAnnotationProperties = /* @__PURE__ */ __name(({
143613
143635
  });
143614
143636
  });
143615
143637
  const keyedPartTags = (_a2 = getKeyedTagsAndTagOptions(allPartTags)) != null ? _a2 : {};
143616
- const additionalColumns = ((_b2 = PropertiesProps == null ? void 0 : PropertiesProps[annotationType]) == null ? void 0 : _b2.additionalColumns) || [];
143638
+ const additionalColumns = ((_c = (_b2 = PropertiesProps == null ? void 0 : PropertiesProps.propertiesList) == null ? void 0 : _b2.find(
143639
+ (p2) => (p2.name || p2) === (pluralize(annotationType) || "")
143640
+ )) == null ? void 0 : _c.additionalColumns) || [];
143617
143641
  this.schema = {
143618
143642
  fields: [
143619
143643
  {
package/index.umd.js CHANGED
@@ -35432,6 +35432,15 @@ ${latestSubscriptionCallbackError.current.stack}
35432
35432
  return value < other;
35433
35433
  }
35434
35434
  __name(baseLt, "baseLt");
35435
+ function mapValues$1(object2, iteratee) {
35436
+ var result = {};
35437
+ iteratee = baseIteratee(iteratee);
35438
+ baseForOwn(object2, function(value, key, object3) {
35439
+ baseAssignValue(result, key, iteratee(value, key, object3));
35440
+ });
35441
+ return result;
35442
+ }
35443
+ __name(mapValues$1, "mapValues$1");
35435
35444
  function baseExtremum(array, iteratee, comparator) {
35436
35445
  var index2 = -1, length = array.length;
35437
35446
  while (++index2 < length) {
@@ -40254,12 +40263,12 @@ ${latestSubscriptionCallbackError.current.stack}
40254
40263
  if (typeof window !== "undefined") {
40255
40264
  getComputedStyleX = window.getComputedStyle ? _getComputedStyle : _getComputedStyleIE;
40256
40265
  }
40257
- function each$2(arr, fn2) {
40266
+ function each(arr, fn2) {
40258
40267
  for (var i2 = 0; i2 < arr.length; i2++) {
40259
40268
  fn2(arr[i2]);
40260
40269
  }
40261
40270
  }
40262
- __name(each$2, "each$2");
40271
+ __name(each, "each");
40263
40272
  function isBorderBoxFn(elem) {
40264
40273
  return getComputedStyleX(elem, "boxSizing") === "border-box";
40265
40274
  }
@@ -40314,7 +40323,7 @@ ${latestSubscriptionCallbackError.current.stack}
40314
40323
  }
40315
40324
  __name(isWindow, "isWindow");
40316
40325
  var domUtils = {};
40317
- each$2(["Width", "Height"], function(name2) {
40326
+ each(["Width", "Height"], function(name2) {
40318
40327
  domUtils["doc".concat(name2)] = function(refWin) {
40319
40328
  var d2 = refWin.document;
40320
40329
  return Math.max(
@@ -40410,7 +40419,7 @@ ${latestSubscriptionCallbackError.current.stack}
40410
40419
  return getComputedStyleX(el, name2);
40411
40420
  }
40412
40421
  __name(css, "css");
40413
- each$2(["width", "height"], function(name2) {
40422
+ each(["width", "height"], function(name2) {
40414
40423
  var first = name2.charAt(0).toUpperCase() + name2.slice(1);
40415
40424
  domUtils["outer".concat(first)] = function(el, includeMargin) {
40416
40425
  return el && getWHIgnoreDisplay(el, name2, includeMargin ? MARGIN_INDEX : BORDER_INDEX);
@@ -40461,7 +40470,7 @@ ${latestSubscriptionCallbackError.current.stack}
40461
40470
  }
40462
40471
  }, "offset"),
40463
40472
  isWindow,
40464
- each: each$2,
40473
+ each,
40465
40474
  css,
40466
40475
  clone: /* @__PURE__ */ __name(function clone2(obj) {
40467
40476
  var ret = {};
@@ -104112,17 +104121,25 @@ ${latestSubscriptionCallbackError.current.stack}
104112
104121
  });
104113
104122
  if (!noTranslationData) {
104114
104123
  seqData.translations = flatMap(seqData.translations, (translation) => {
104124
+ var _a2, _b2;
104115
104125
  if (noCdsTranslations && translation.translationType === "CDS Feature") {
104116
104126
  return [];
104117
104127
  }
104118
- if (!translation.aminoAcids && !seqData.noSequence) {
104119
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
104128
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
104129
+ const expandedRange = expandOrContractRangeByLength(
104130
+ translation,
104131
+ -codonStart,
104132
+ true,
104133
+ seqData.sequence.length
104134
+ );
104135
+ if (!expandedRange.aminoAcids && !seqData.noSequence) {
104136
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
104120
104137
  seqData.sequence,
104121
- translation.forward,
104122
- translation
104138
+ expandedRange.forward,
104139
+ expandedRange
104123
104140
  );
104124
104141
  }
104125
- return translation;
104142
+ return expandedRange;
104126
104143
  });
104127
104144
  }
104128
104145
  if (annotationsAsObjects) {
@@ -125958,32 +125975,6 @@ ${seq.sequence}
125958
125975
  (state2) => state2.useAdditionalOrfStartCodons,
125959
125976
  findOrfsInPlasmid
125960
125977
  );
125961
- var forEach_1;
125962
- var hasRequiredForEach;
125963
- function requireForEach() {
125964
- if (hasRequiredForEach) return forEach_1;
125965
- hasRequiredForEach = 1;
125966
- var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
125967
- function forEach2(collection, iteratee) {
125968
- var func = isArray2(collection) ? arrayEach2 : baseEach2;
125969
- return func(collection, castFunction2(iteratee));
125970
- }
125971
- __name(forEach2, "forEach");
125972
- forEach_1 = forEach2;
125973
- return forEach_1;
125974
- }
125975
- __name(requireForEach, "requireForEach");
125976
- var each$1;
125977
- var hasRequiredEach;
125978
- function requireEach() {
125979
- if (hasRequiredEach) return each$1;
125980
- hasRequiredEach = 1;
125981
- each$1 = requireForEach();
125982
- return each$1;
125983
- }
125984
- __name(requireEach, "requireEach");
125985
- var eachExports = requireEach();
125986
- const each = /* @__PURE__ */ getDefaultExportFromCjs(eachExports);
125987
125978
  function translationsRawSelector(sequenceData2) {
125988
125979
  return sequenceData2.translations;
125989
125980
  }
@@ -126150,14 +126141,22 @@ ${seq.sequence}
126150
126141
  },
126151
126142
  {}
126152
126143
  ));
126153
- each(translationsToPass, function(translation) {
126154
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
126144
+ return mapValues$1(translationsToPass, (translation) => {
126145
+ var _a2, _b2;
126146
+ const codonStart = ((_b2 = (_a2 = translation == null ? void 0 : translation.notes) == null ? void 0 : _a2.codon_start) == null ? void 0 : _b2[0]) - 1 || 0;
126147
+ const expandedRange = expandOrContractRangeByLength(
126148
+ translation,
126149
+ -codonStart,
126150
+ true,
126151
+ sequence2.length
126152
+ );
126153
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
126155
126154
  sequence2,
126156
- translation.forward,
126157
- translation
126155
+ expandedRange.forward,
126156
+ expandedRange
126158
126157
  );
126158
+ return expandedRange;
126159
126159
  });
126160
- return translationsToPass;
126161
126160
  }
126162
126161
  __name(translationsSelector, "translationsSelector");
126163
126162
  const translationsSelector$1 = createSelector(
@@ -138033,6 +138032,21 @@ ${seq.sequence}
138033
138032
  );
138034
138033
  }
138035
138034
  __name(Orf, "Orf");
138035
+ var forEach_1;
138036
+ var hasRequiredForEach;
138037
+ function requireForEach() {
138038
+ if (hasRequiredForEach) return forEach_1;
138039
+ hasRequiredForEach = 1;
138040
+ var arrayEach2 = require_arrayEach(), baseEach2 = require_baseEach(), castFunction2 = require_castFunction(), isArray2 = requireIsArray();
138041
+ function forEach2(collection, iteratee) {
138042
+ var func = isArray2(collection) ? arrayEach2 : baseEach2;
138043
+ return func(collection, castFunction2(iteratee));
138044
+ }
138045
+ __name(forEach2, "forEach");
138046
+ forEach_1 = forEach2;
138047
+ return forEach_1;
138048
+ }
138049
+ __name(requireForEach, "requireForEach");
138036
138050
  var forEachExports = requireForEach();
138037
138051
  const forEach = /* @__PURE__ */ getDefaultExportFromCjs(forEachExports);
138038
138052
  var lib = {};
@@ -144738,7 +144752,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
144738
144752
  input.click();
144739
144753
  }
144740
144754
  __name(showFileDialog, "showFileDialog");
144741
- const version = "0.8.16";
144755
+ const version = "0.8.18";
144742
144756
  const packageJson = {
144743
144757
  version
144744
144758
  };
@@ -150788,6 +150802,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
150788
150802
  RowItem$1,
150789
150803
  __spreadProps(__spreadValues({}, __spreadValues(__spreadProps(__spreadValues({}, rest), {
150790
150804
  editorName,
150805
+ showAminoAcidUnitAsCodon,
150791
150806
  onScroll: /* @__PURE__ */ __name(() => {
150792
150807
  this.easyStore.viewportWidth = width;
150793
150808
  const row = this.linearView.querySelector(".veRowItemWrapper");
@@ -164592,7 +164607,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
164592
164607
  item: selection && selection.start > -1 ? /* @__PURE__ */ React.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size2),
164593
164608
  title: "Region"
164594
164609
  }
164595
- )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Amino Acid"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
164610
+ )), /* @__PURE__ */ React.createElement("h5", null, isProtein2 ? "Amino Acid" : "Base Pair", " Frequencies"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
164596
164611
  return /* @__PURE__ */ React.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
164597
164612
  })));
164598
164613
  } else {
@@ -165092,7 +165107,11 @@ ${seqDataToCopy}\r
165092
165107
  }, [alignmentTracks, id2, store2]);
165093
165108
  reactExports.useEffect(() => {
165094
165109
  const handleAlignmentCopy = /* @__PURE__ */ __name((event) => {
165110
+ var _a3, _b2, _c2;
165095
165111
  if (event.key === "c" && !event.shiftKey && (event.metaKey === true || event.ctrlKey === true)) {
165112
+ if (!((_a3 = document.activeElement) == null ? void 0 : _a3.classList.contains("alignmentView"))) {
165113
+ return;
165114
+ }
165096
165115
  const input = document.createElement("textarea");
165097
165116
  document.body.appendChild(input);
165098
165117
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -165106,6 +165125,8 @@ ${seqDataToCopy}\r
165106
165125
  }
165107
165126
  document.body.removeChild(input);
165108
165127
  event.preventDefault();
165128
+ (_b2 = document.activeElement) == null ? void 0 : _b2.blur();
165129
+ (_c2 = document.querySelector(".alignmentView")) == null ? void 0 : _c2.focus();
165109
165130
  }
165110
165131
  }, "handleAlignmentCopy");
165111
165132
  document.addEventListener("keydown", handleAlignmentCopy);
@@ -166264,6 +166285,7 @@ ${seqDataToCopy}\r
166264
166285
  position: "relative",
166265
166286
  overflowY: "auto"
166266
166287
  }, style2),
166288
+ tabIndex: 0,
166267
166289
  className: "alignmentView"
166268
166290
  },
166269
166291
  /* @__PURE__ */ React.createElement(
@@ -170103,7 +170125,7 @@ ${seqDataToCopy}\r
170103
170125
  this.commands = getCommands(this);
170104
170126
  }
170105
170127
  render() {
170106
- var _a2, _b2;
170128
+ var _a2, _b2, _c2;
170107
170129
  const {
170108
170130
  readOnly: readOnly2,
170109
170131
  annotations = {},
@@ -170127,7 +170149,9 @@ ${seqDataToCopy}\r
170127
170149
  });
170128
170150
  });
170129
170151
  const keyedPartTags = (_a2 = getKeyedTagsAndTagOptions(allPartTags)) != null ? _a2 : {};
170130
- const additionalColumns = ((_b2 = PropertiesProps == null ? void 0 : PropertiesProps[annotationType]) == null ? void 0 : _b2.additionalColumns) || [];
170152
+ const additionalColumns = ((_c2 = (_b2 = PropertiesProps == null ? void 0 : PropertiesProps.propertiesList) == null ? void 0 : _b2.find(
170153
+ (p2) => (p2.name || p2) === (pluralize(annotationType) || "")
170154
+ )) == null ? void 0 : _c2.additionalColumns) || [];
170131
170155
  this.schema = {
170132
170156
  fields: [
170133
170157
  {
package/ove.css CHANGED
@@ -11260,6 +11260,12 @@ path.partWithSelectedTag {
11260
11260
  height: 100% !important;
11261
11261
  overflow: hidden;
11262
11262
  }
11263
+ .alignmentView .veAlignmentSelectionLayer.veRowViewSelectionLayer {
11264
+ background: gray;
11265
+ }
11266
+ .alignmentView:focus .veAlignmentSelectionLayer.veRowViewSelectionLayer {
11267
+ background: #0099ff;
11268
+ }
11263
11269
  .alignmentView .veSelectionLayer {
11264
11270
  top: 0;
11265
11271
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teselagen/ove",
3
- "version": "0.8.17",
3
+ "version": "0.8.19",
4
4
  "main": "./src/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,4 +1,6 @@
1
- declare const _default: ((state: any) => any) & import('reselect').OutputSelectorFields<(args_0: any, args_1: unknown, args_2: any, args_3: {
1
+ declare const _default: ((state: any) => {
2
+ [x: string]: any;
3
+ }) & import('reselect').OutputSelectorFields<(args_0: any, args_1: unknown, args_2: any, args_3: {
2
4
  start: number;
3
5
  end: number;
4
6
  length: number;
@@ -8,7 +10,9 @@ declare const _default: ((state: any) => any) & import('reselect').OutputSelecto
8
10
  annotationTypePlural: string;
9
11
  isOrf: boolean;
10
12
  id: any;
11
- }[], args_4: any, args_5: any, args_6: any[], args_7: any, args_8: any, args_9: any, args_10: any, args_11: any, args_12: any) => any, {
13
+ }[], args_4: any, args_5: any, args_6: any[], args_7: any, args_8: any, args_9: any, args_10: any, args_11: any, args_12: any) => {
14
+ [x: string]: any;
15
+ }, {
12
16
  clearCache: () => void;
13
17
  }> & {
14
18
  clearCache: () => void;
@@ -211,6 +211,9 @@ export const AlignmentView = props => {
211
211
  !event.shiftKey &&
212
212
  (event.metaKey === true || event.ctrlKey === true)
213
213
  ) {
214
+ if (!document.activeElement?.classList.contains("alignmentView")) {
215
+ return; //stop early if we're not focused on the alignment view
216
+ }
214
217
  const input = document.createElement("textarea");
215
218
  document.body.appendChild(input);
216
219
  const seqDataToCopy = getAllAlignmentsFastaText();
@@ -224,6 +227,8 @@ export const AlignmentView = props => {
224
227
  }
225
228
  document.body.removeChild(input);
226
229
  event.preventDefault();
230
+ document.activeElement?.blur();
231
+ document.querySelector(".alignmentView")?.focus();
227
232
  }
228
233
  };
229
234
 
@@ -1584,6 +1589,7 @@ export const AlignmentView = props => {
1584
1589
  ...style
1585
1590
  // borderTop: "1px solid black"
1586
1591
  }}
1592
+ tabIndex={0}
1587
1593
  className="alignmentView"
1588
1594
  >
1589
1595
  <DragDropContext
@@ -73,6 +73,12 @@
73
73
  height: 100% !important;
74
74
  overflow: hidden;
75
75
  }
76
+ .alignmentView .veAlignmentSelectionLayer.veRowViewSelectionLayer {
77
+ background: gray;
78
+ }
79
+ .alignmentView:focus .veAlignmentSelectionLayer.veRowViewSelectionLayer {
80
+ background: #0099ff;
81
+ }
76
82
  .alignmentView .veSelectionLayer {
77
83
  top: 0;
78
84
  }
@@ -327,6 +327,7 @@ class _LinearView extends React.Component {
327
327
  {...{
328
328
  ...rest,
329
329
  editorName,
330
+ showAminoAcidUnitAsCodon,
330
331
  onScroll: () => {
331
332
  this.easyStore.viewportWidth = width;
332
333
  const row =
@@ -149,7 +149,9 @@ export default ({ properties, setProperties, style }) => {
149
149
  <h5>{isProtein ? "Amino Acid" : "Base Pair"} Frequencies</h5>
150
150
  <div className="sidebar-table">
151
151
  <div className="sidebar-row">
152
- <div className="sidebar-cell">Amino Acid</div>
152
+ <div className="sidebar-cell">
153
+ {isProtein ? "Amino Acid" : "Base"}
154
+ </div>
153
155
  <div className="sidebar-cell">Count</div>
154
156
  <div className="sidebar-cell">Percentage</div>
155
157
  </div>
@@ -20,6 +20,7 @@ import {
20
20
  Tooltip
21
21
  } from "@blueprintjs/core";
22
22
  import { getRangeLength } from "@teselagen/range-utils";
23
+ import pluralize from "pluralize";
23
24
  // import { Popover } from "@blueprintjs/core";
24
25
  // import ColorPicker from "./ColorPicker";
25
26
  import { connectToEditor } from "../../withEditorProps";
@@ -87,9 +88,10 @@ const genericAnnotationProperties = ({
87
88
  });
88
89
 
89
90
  const keyedPartTags = getKeyedTagsAndTagOptions(allPartTags) ?? {};
90
-
91
91
  const additionalColumns =
92
- PropertiesProps?.[annotationType]?.additionalColumns || [];
92
+ PropertiesProps?.propertiesList?.find(
93
+ p => (p.name || p) === (pluralize(annotationType) || "")
94
+ )?.additionalColumns || [];
93
95
 
94
96
  this.schema = {
95
97
  fields: [
@@ -1,14 +1,16 @@
1
- import { reduce } from "lodash-es";
1
+ import { reduce, mapValues } from "lodash-es";
2
2
  import uuid from "shortid";
3
3
  import sequenceSelector from "./sequenceSelector";
4
4
  import orfsSelector from "./orfsSelector";
5
5
  import { createSelector } from "reselect";
6
6
 
7
7
  import { getAminoAcidDataForEachBaseOfDna } from "@teselagen/sequence-utils";
8
- import each from "lodash/each";
9
8
  import translationsRawSelector from "./translationsRawSelector";
10
9
  import translationSearchMatchesSelector from "./translationSearchMatchesSelector";
11
- import { normalizePositionByRangeLength } from "@teselagen/range-utils";
10
+ import {
11
+ expandOrContractRangeByLength,
12
+ normalizePositionByRangeLength
13
+ } from "@teselagen/range-utils";
12
14
  import cdsFeaturesSelector from "./cdsFeaturesSelector";
13
15
  import circularSelector from "./circularSelector";
14
16
 
@@ -109,14 +111,21 @@ function translationsSelector(
109
111
  {}
110
112
  )
111
113
  };
112
- each(translationsToPass, function (translation) {
113
- translation.aminoAcids = getAminoAcidDataForEachBaseOfDna(
114
+ return mapValues(translationsToPass, translation => {
115
+ const codonStart = translation?.notes?.codon_start?.[0] - 1 || 0;
116
+ const expandedRange = expandOrContractRangeByLength(
117
+ translation,
118
+ -codonStart,
119
+ true,
120
+ sequence.length
121
+ );
122
+ expandedRange.aminoAcids = getAminoAcidDataForEachBaseOfDna(
114
123
  sequence,
115
- translation.forward,
116
- translation
124
+ expandedRange.forward,
125
+ expandedRange
117
126
  );
127
+ return expandedRange;
118
128
  });
119
- return translationsToPass;
120
129
  }
121
130
 
122
131
  export default createSelector(