@teselagen/ove 0.3.31 → 0.3.43

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.umd.js CHANGED
@@ -45029,25 +45029,16 @@ ${latestSubscriptionCallbackError.current.stack}
45029
45029
  var _cof = /* @__PURE__ */ __name(function(it) {
45030
45030
  return toString$4.call(it).slice(8, -1);
45031
45031
  }, "_cof");
45032
- var _iobject;
45033
- var hasRequired_iobject;
45034
- function require_iobject() {
45035
- if (hasRequired_iobject)
45036
- return _iobject;
45037
- hasRequired_iobject = 1;
45038
- var cof2 = _cof;
45039
- _iobject = Object("z").propertyIsEnumerable(0) ? Object : function(it) {
45040
- return cof2(it) == "String" ? it.split("") : Object(it);
45041
- };
45042
- return _iobject;
45043
- }
45044
- __name(require_iobject, "require_iobject");
45032
+ var cof$2 = _cof;
45033
+ var _iobject = Object("z").propertyIsEnumerable(0) ? Object : function(it) {
45034
+ return cof$2(it) == "String" ? it.split("") : Object(it);
45035
+ };
45045
45036
  var _defined = /* @__PURE__ */ __name(function(it) {
45046
45037
  if (it == void 0)
45047
45038
  throw TypeError("Can't call method on " + it);
45048
45039
  return it;
45049
45040
  }, "_defined");
45050
- var IObject = require_iobject();
45041
+ var IObject = _iobject;
45051
45042
  var defined$2 = _defined;
45052
45043
  var _toIobject = /* @__PURE__ */ __name(function(it) {
45053
45044
  return IObject(defined$2(it));
@@ -45144,15 +45135,7 @@ ${latestSubscriptionCallbackError.current.stack}
45144
45135
  var _objectGops = {};
45145
45136
  _objectGops.f = Object.getOwnPropertySymbols;
45146
45137
  var _objectPie = {};
45147
- var hasRequired_objectPie;
45148
- function require_objectPie() {
45149
- if (hasRequired_objectPie)
45150
- return _objectPie;
45151
- hasRequired_objectPie = 1;
45152
- _objectPie.f = {}.propertyIsEnumerable;
45153
- return _objectPie;
45154
- }
45155
- __name(require_objectPie, "require_objectPie");
45138
+ _objectPie.f = {}.propertyIsEnumerable;
45156
45139
  var defined$1 = _defined;
45157
45140
  var _toObject = /* @__PURE__ */ __name(function(it) {
45158
45141
  return Object(defined$1(it));
@@ -45166,9 +45149,9 @@ ${latestSubscriptionCallbackError.current.stack}
45166
45149
  var DESCRIPTORS2 = require_descriptors();
45167
45150
  var getKeys2 = _objectKeys;
45168
45151
  var gOPS2 = _objectGops;
45169
- var pIE2 = require_objectPie();
45152
+ var pIE2 = _objectPie;
45170
45153
  var toObject2 = _toObject;
45171
- var IObject2 = require_iobject();
45154
+ var IObject2 = _iobject;
45172
45155
  var $assign = Object.assign;
45173
45156
  _objectAssign = !$assign || _fails(function() {
45174
45157
  var A2 = {};
@@ -45803,7 +45786,7 @@ ${latestSubscriptionCallbackError.current.stack}
45803
45786
  }, "_wksDefine");
45804
45787
  var getKeys = _objectKeys;
45805
45788
  var gOPS$1 = _objectGops;
45806
- var pIE$1 = require_objectPie();
45789
+ var pIE$1 = _objectPie;
45807
45790
  var _enumKeys = /* @__PURE__ */ __name(function(it) {
45808
45791
  var result = getKeys(it);
45809
45792
  var getSymbols2 = gOPS$1.f;
@@ -45844,7 +45827,7 @@ ${latestSubscriptionCallbackError.current.stack}
45844
45827
  return windowNames && toString$3.call(it) == "[object Window]" ? getWindowNames(it) : gOPN$1(toIObject$2(it));
45845
45828
  }, "getOwnPropertyNames");
45846
45829
  var _objectGopd = {};
45847
- var pIE = require_objectPie();
45830
+ var pIE = _objectPie;
45848
45831
  var createDesc$1 = _propertyDesc;
45849
45832
  var toIObject$1 = _toIobject;
45850
45833
  var toPrimitive$1 = _toPrimitive$1;
@@ -46024,7 +46007,7 @@ ${latestSubscriptionCallbackError.current.stack}
46024
46007
  $GOPD.f = $getOwnPropertyDescriptor;
46025
46008
  $DP.f = $defineProperty;
46026
46009
  _objectGopn.f = gOPNExt.f = $getOwnPropertyNames;
46027
- require_objectPie().f = $propertyIsEnumerable;
46010
+ _objectPie.f = $propertyIsEnumerable;
46028
46011
  $GOPS.f = $getOwnPropertySymbols;
46029
46012
  if (DESCRIPTORS && !_library) {
46030
46013
  redefine(ObjectProto, "propertyIsEnumerable", $propertyIsEnumerable);
@@ -107748,6 +107731,7 @@ ${latestSubscriptionCallbackError.current.stack}
107748
107731
  minimumOrfSizeUpdate
107749
107732
  }, Symbol.toStringTag, { value: "Module" }));
107750
107733
  const protein_letters = "ACDEFGHIKLMNPQRSTVWY";
107734
+ const protein_letters_withUandX = "ACDEFGHIKLMNPQRSTVWYUX";
107751
107735
  const extended_protein_letters = "ACDEFGHIKLMNPQRSTVWYBXZJUO.*-";
107752
107736
  const ambiguous_dna_letters = "GATCRYWSMKHBVDN";
107753
107737
  const unambiguous_dna_letters = "GATC";
@@ -107816,6 +107800,7 @@ ${latestSubscriptionCallbackError.current.stack}
107816
107800
  extended_protein_letters,
107817
107801
  extended_protein_values,
107818
107802
  protein_letters,
107803
+ protein_letters_withUandX,
107819
107804
  unambiguous_dna_letters,
107820
107805
  unambiguous_rna_letters
107821
107806
  }, Symbol.toStringTag, { value: "Module" }));
@@ -113834,20 +113819,91 @@ ${latestSubscriptionCallbackError.current.stack}
113834
113819
  "primers",
113835
113820
  "guides"
113836
113821
  ];
113837
- function filterSequenceString(sequenceString, additionalValidChars = "", charOverrides) {
113838
- if (sequenceString) {
113839
- return sequenceString.replace(
113840
- new RegExp(
113841
- `[^${charOverrides || `atgcyrswkmbvdhnu${additionalValidChars.split("").join("\\")}`}]`,
113842
- "gi"
113843
- ),
113844
- ""
113822
+ function filterSequenceString(sequenceString, {
113823
+ additionalValidChars = "",
113824
+ isOligo: isOligo2,
113825
+ name: name2,
113826
+ isProtein: isProtein2,
113827
+ isRna: isRna2,
113828
+ isMixedRnaAndDna,
113829
+ includeStopCodon
113830
+ } = {}) {
113831
+ const acceptedChars = getAcceptedChars({
113832
+ isOligo: isOligo2,
113833
+ isProtein: isProtein2,
113834
+ isRna: isRna2,
113835
+ isMixedRnaAndDna,
113836
+ includeStopCodon
113837
+ });
113838
+ const replaceChars = getReplaceChars({
113839
+ isOligo: isOligo2,
113840
+ isProtein: isProtein2,
113841
+ isRna: isRna2,
113842
+ isMixedRnaAndDna
113843
+ });
113844
+ let sanitizedVal = "";
113845
+ const invalidChars = [];
113846
+ const chars2 = `${acceptedChars}${additionalValidChars.split("").join("\\")}`;
113847
+ const warnings = [];
113848
+ const replaceCount = {};
113849
+ sequenceString.split("").forEach((letter) => {
113850
+ const lowerLetter = letter.toLowerCase();
113851
+ if (replaceChars && replaceChars[lowerLetter]) {
113852
+ if (!replaceCount[lowerLetter]) {
113853
+ replaceCount[lowerLetter] = 0;
113854
+ }
113855
+ replaceCount[lowerLetter]++;
113856
+ const isUpper = lowerLetter !== letter;
113857
+ sanitizedVal += isUpper ? replaceChars[lowerLetter].toUpperCase() : replaceChars[lowerLetter];
113858
+ } else if (chars2.includes(lowerLetter)) {
113859
+ sanitizedVal += letter;
113860
+ } else {
113861
+ invalidChars.push(letter);
113862
+ }
113863
+ });
113864
+ Object.keys(replaceCount).forEach((letter) => {
113865
+ warnings.push(
113866
+ `Replaced "${letter}" with "${replaceChars[letter]}"${replaceCount[letter] > 1 ? ` ${replaceCount[letter]} times` : ""}`
113845
113867
  );
113846
- } else {
113847
- return sequenceString;
113868
+ });
113869
+ if (sequenceString.length !== sanitizedVal.length) {
113870
+ warnings.push(
113871
+ `${name2 ? `Sequence ${name2}: ` : ""}Invalid character(s) detected and removed: ${invalidChars.slice(0, 100).join(", ")} `
113872
+ );
113873
+ }
113874
+ if (typeof window !== "undefined" && window.toastr && warnings.length) {
113875
+ warnings.forEach((warning2) => {
113876
+ window.toastr.warning(warning2);
113877
+ });
113848
113878
  }
113879
+ return [sanitizedVal, warnings];
113849
113880
  }
113850
113881
  __name(filterSequenceString, "filterSequenceString");
113882
+ function getAcceptedChars({
113883
+ isOligo: isOligo2,
113884
+ isProtein: isProtein2,
113885
+ isRna: isRna2,
113886
+ isMixedRnaAndDna,
113887
+ includeStopCodon
113888
+ } = {}) {
113889
+ return isProtein2 ? `${protein_letters_withUandX.toLowerCase()}${includeStopCodon ? "*." : ""}}` : isOligo2 ? ambiguous_rna_letters.toLowerCase() + "t" : isRna2 ? ambiguous_rna_letters.toLowerCase() + "t" : isMixedRnaAndDna ? ambiguous_rna_letters.toLowerCase() + ambiguous_dna_letters.toLowerCase() : (
113890
+ //just plain old dna
113891
+ ambiguous_rna_letters.toLowerCase() + ambiguous_dna_letters.toLowerCase()
113892
+ );
113893
+ }
113894
+ __name(getAcceptedChars, "getAcceptedChars");
113895
+ function getReplaceChars({
113896
+ isOligo: isOligo2,
113897
+ isProtein: isProtein2,
113898
+ isRna: isRna2,
113899
+ isMixedRnaAndDna
113900
+ } = {}) {
113901
+ return isProtein2 ? {} : isOligo2 ? {} : isRna2 ? { t: "u" } : isMixedRnaAndDna ? {} : (
113902
+ //just plain old dna
113903
+ {}
113904
+ );
113905
+ }
113906
+ __name(getReplaceChars, "getReplaceChars");
113851
113907
  function tidyUpAnnotation(_annotation, {
113852
113908
  sequenceData: sequenceData2 = {},
113853
113909
  convertAnnotationsFromAAIndices,
@@ -113976,14 +114032,6 @@ ${latestSubscriptionCallbackError.current.stack}
113976
114032
  }
113977
114033
  }
113978
114034
  __name(coerceLocation, "coerceLocation");
113979
- function filterAminoAcidSequenceString(sequenceString, options) {
113980
- options = options || {};
113981
- if (options.includeStopCodon) {
113982
- return sequenceString == null ? void 0 : sequenceString.replace(/[^xtgalmfwkqespvicyhrndu.*]/gi, "");
113983
- }
113984
- return sequenceString == null ? void 0 : sequenceString.replace(/[^xtgalmfwkqespvicyhrndu]/gi, "");
113985
- }
113986
- __name(filterAminoAcidSequenceString, "filterAminoAcidSequenceString");
113987
114035
  function getDegenerateDnaStringFromAAString(aaString) {
113988
114036
  return aaString.split("").map((char2) => aminoAcidToDegenerateDnaMap[char2.toLowerCase()] || "nnn").join("");
113989
114037
  }
@@ -113995,11 +114043,10 @@ ${latestSubscriptionCallbackError.current.stack}
113995
114043
  removeUnwantedChars,
113996
114044
  additionalValidChars,
113997
114045
  noTranslationData,
113998
- charOverrides,
113999
114046
  doNotProvideIdsForAnnotations,
114000
- proteinFilterOptions,
114001
114047
  noCdsTranslations,
114002
- convertAnnotationsFromAAIndices
114048
+ convertAnnotationsFromAAIndices,
114049
+ topLevelSeqData
114003
114050
  } = options;
114004
114051
  let seqData = lodashExports.cloneDeep(pSeqData);
114005
114052
  const response = {
@@ -114029,16 +114076,15 @@ ${latestSubscriptionCallbackError.current.stack}
114029
114076
  }
114030
114077
  if (removeUnwantedChars) {
114031
114078
  if (seqData.isProtein) {
114032
- seqData.proteinSequence = filterAminoAcidSequenceString(
114033
- seqData.proteinSequence,
114034
- __spreadValues({ includeStopCodon: true }, proteinFilterOptions)
114035
- );
114079
+ const [newSeq] = filterSequenceString(seqData.proteinSequence, __spreadValues({
114080
+ includeStopCodon: true
114081
+ }, topLevelSeqData || seqData));
114082
+ seqData.proteinSequence = newSeq;
114036
114083
  } else {
114037
- seqData.sequence = filterSequenceString(
114038
- seqData.sequence,
114039
- `${additionalValidChars || ""}${seqData.isRna || seqData.isMixedRnaAndDna ? "u" : ""}`,
114040
- charOverrides
114041
- );
114084
+ const [newSeq] = filterSequenceString(seqData.sequence, __spreadValues({
114085
+ additionalValidChars
114086
+ }, topLevelSeqData || seqData));
114087
+ seqData.sequence = newSeq;
114042
114088
  }
114043
114089
  }
114044
114090
  if (seqData.isProtein) {
@@ -123385,7 +123431,8 @@ ${latestSubscriptionCallbackError.current.stack}
123385
123431
  inclusive1BasedEnd,
123386
123432
  additionalValidChars,
123387
123433
  allowOverflowAnnotations,
123388
- coerceFeatureTypes
123434
+ coerceFeatureTypes,
123435
+ includeStopCodon
123389
123436
  } = options;
123390
123437
  [
123391
123438
  "isDNA",
@@ -123435,7 +123482,6 @@ ${latestSubscriptionCallbackError.current.stack}
123435
123482
  response.messages.push("No sequence detected");
123436
123483
  sequence2.sequence = "";
123437
123484
  }
123438
- let validChars;
123439
123485
  if (sequence2.isProtein === void 0 && guessIfProtein) {
123440
123486
  sequence2.isProtein = !guessIfSequenceIsDnaAndNotProtein(
123441
123487
  sequence2.sequence,
@@ -123443,12 +123489,15 @@ ${latestSubscriptionCallbackError.current.stack}
123443
123489
  );
123444
123490
  }
123445
123491
  if (sequence2.isProtein) {
123446
- validChars = filterAminoAcidSequenceString(sequence2.sequence);
123492
+ const [validChars, warnings] = filterSequenceString(sequence2.sequence, {
123493
+ name: sequence2.name,
123494
+ isProtein: true,
123495
+ additionalValidChars,
123496
+ includeStopCodon
123497
+ });
123447
123498
  if (validChars !== sequence2.sequence) {
123448
123499
  sequence2.sequence = validChars;
123449
- response.messages.push(
123450
- "Import Error: Illegal character(s) detected and removed from amino acid sequence. Allowed characters are: xtgalmfwkqespvicyhrndu"
123451
- );
123500
+ response.messages.push(...warnings);
123452
123501
  }
123453
123502
  sequence2.type = "PROTEIN";
123454
123503
  sequence2.isProtein = true;
@@ -123470,12 +123519,12 @@ ${latestSubscriptionCallbackError.current.stack}
123470
123519
  } else {
123471
123520
  sequence2.type = "DNA";
123472
123521
  }
123473
- validChars = filterSequenceString(sequence2.sequence, additionalValidChars);
123522
+ const [validChars, warnings] = filterSequenceString(sequence2.sequence, __spreadValues({
123523
+ additionalValidChars
123524
+ }, sequence2));
123474
123525
  if (validChars !== sequence2.sequence) {
123475
123526
  sequence2.sequence = validChars;
123476
- response.messages.push(
123477
- "Import Error: Illegal character(s) detected and removed from sequence. Allowed characters are: atgcyrswkmbvdhn"
123478
- );
123527
+ response.messages.push(...warnings);
123479
123528
  }
123480
123529
  }
123481
123530
  if (!sequence2.size) {
@@ -138363,18 +138412,6 @@ ${seq.sequence}
138363
138412
  return selToUse;
138364
138413
  }
138365
138414
  __name(getSelFromWrappedAddon, "getSelFromWrappedAddon");
138366
- function getAcceptedChars({
138367
- isOligo: isOligo2,
138368
- isProtein: isProtein2,
138369
- isRna: isRna2,
138370
- isMixedRnaAndDna
138371
- } = {}) {
138372
- return isProtein2 ? extended_protein_letters.toLowerCase() : isOligo2 ? ambiguous_rna_letters.toLowerCase() + "t" : isRna2 ? ambiguous_rna_letters.toLowerCase() : isMixedRnaAndDna ? ambiguous_rna_letters.toLowerCase() + ambiguous_dna_letters.toLowerCase() : (
138373
- //just plain old dna
138374
- ambiguous_dna_letters.toLowerCase()
138375
- );
138376
- }
138377
- __name(getAcceptedChars, "getAcceptedChars");
138378
138415
  function getStripedPattern({ color: color2 }) {
138379
138416
  return /* @__PURE__ */ React$2.createElement(
138380
138417
  "pattern",
@@ -154960,7 +154997,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
154960
154997
  }
154961
154998
  __name(showFileDialog, "showFileDialog");
154962
154999
  const name = "@teselagen/ove";
154963
- const version = "0.3.30";
155000
+ const version = "0.3.42";
154964
155001
  const main = "./src/index.js";
154965
155002
  const exports$1 = {
154966
155003
  ".": {
@@ -157107,9 +157144,8 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
157107
157144
  selectionLayer: selectionLayer2,
157108
157145
  sequenceLength,
157109
157146
  isProtein: isProtein2,
157110
- replaceChars,
157111
157147
  caretPosition: caretPosition2,
157112
- acceptedChars,
157148
+ sequenceData: sequenceData2,
157113
157149
  maxInsertSize
157114
157150
  } = this.props;
157115
157151
  const { charsToInsert, hasTempError } = this.state;
@@ -157142,17 +157178,13 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
157142
157178
  autoFocus: true,
157143
157179
  style: hasTempError ? { borderColor: "red" } : {},
157144
157180
  onChange: (e2) => {
157145
- let sanitizedVal = "";
157146
- e2.target.value.split("").forEach((letter) => {
157147
- const lowerLetter = letter.toLowerCase();
157148
- if (replaceChars && replaceChars[lowerLetter]) {
157149
- const isUpper = lowerLetter !== letter;
157150
- sanitizedVal += isUpper ? replaceChars[lowerLetter].toUpperCase() : replaceChars[lowerLetter];
157151
- } else if (acceptedChars.includes(lowerLetter)) {
157152
- sanitizedVal += letter;
157153
- }
157154
- });
157155
- if (e2.target.value.length !== sanitizedVal.length) {
157181
+ const [sanitizedVal, warnings] = filterSequenceString(
157182
+ e2.target.value,
157183
+ __spreadProps(__spreadValues({}, sequenceData2), {
157184
+ name: void 0
157185
+ })
157186
+ );
157187
+ if (warnings.length) {
157156
157188
  this.setState({
157157
157189
  hasTempError: true
157158
157190
  });
@@ -158027,7 +158059,8 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
158027
158059
  selectionLayer: selectionLayer2 = { start: -1, end: -1 },
158028
158060
  readOnly: readOnly2,
158029
158061
  onPaste,
158030
- disableBpEditing
158062
+ disableBpEditing,
158063
+ sequenceData: sequenceData2
158031
158064
  } = this.props;
158032
158065
  if (disableBpEditing) {
158033
158066
  return window.toastr.warning("Sorry the underlying sequence is locked");
@@ -158052,6 +158085,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
158052
158085
  };
158053
158086
  }
158054
158087
  seqDataToInsert = tidyUpSequenceData(seqDataToInsert, {
158088
+ topLevelSeqData: sequenceData2,
158055
158089
  provideNewIdsForAnnotations: true,
158056
158090
  annotationsAsObjects: true,
158057
158091
  removeUnwantedChars: true,
@@ -158147,8 +158181,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
158147
158181
  createSequenceInputPopup({
158148
158182
  useEventPositioning,
158149
158183
  isReplace,
158150
- replaceChars: sequenceData2.isRna ? { t: "u" } : void 0,
158151
- acceptedChars: getAcceptedChars(sequenceData2),
158184
+ sequenceData: sequenceData2,
158152
158185
  isProtein: sequenceData2.isProtein,
158153
158186
  selectionLayer: selectionLayer2,
158154
158187
  sequenceLength,
@@ -169641,14 +169674,8 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
169641
169674
  const newVal2 = e2.target.innerText;
169642
169675
  const savedCaretPosition = EditCaretPositioning.saveSelection(e2.currentTarget);
169643
169676
  setCaretPosition(savedCaretPosition);
169644
- const acceptedChars = getAcceptedChars(sequenceData2);
169645
- let newBases = "";
169646
- newVal2.split("").forEach((letter) => {
169647
- if (acceptedChars.includes(letter.toLowerCase())) {
169648
- newBases += letter;
169649
- }
169650
- });
169651
- if (newVal2.length !== newBases.length) {
169677
+ const [newBases, warnings] = filterSequenceString(newVal2, sequenceData2);
169678
+ if (warnings.length) {
169652
169679
  setTempError(true);
169653
169680
  setTimeout(() => {
169654
169681
  setTempError(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teselagen/ove",
3
- "version": "0.3.31",
3
+ "version": "0.3.43",
4
4
  "main": "./src/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -13,12 +13,12 @@
13
13
  "node": "16.20.2"
14
14
  },
15
15
  "dependencies": {
16
- "@teselagen/sequence-utils": "0.3.8",
16
+ "@teselagen/sequence-utils": "0.3.9",
17
17
  "@teselagen/range-utils": "0.3.7",
18
- "@teselagen/ui": "0.3.30",
18
+ "@teselagen/ui": "0.3.32",
19
19
  "@teselagen/file-utils": "0.3.9",
20
20
  "@teselagen/bounce-loader": "0.3.11",
21
- "@teselagen/bio-parsers": "0.3.10",
21
+ "@teselagen/bio-parsers": "0.4.1",
22
22
  "@blueprintjs/core": "3.52.0",
23
23
  "@blueprintjs/datetime": "3.23.19",
24
24
  "@blueprintjs/icons": "3.33.0",
@@ -6,11 +6,13 @@ import {
6
6
  generateField,
7
7
  RadioGroupField
8
8
  } from "@teselagen/ui";
9
- import { getReverseComplementSequenceString } from "@teselagen/sequence-utils";
9
+ import {
10
+ filterSequenceString,
11
+ getReverseComplementSequenceString
12
+ } from "@teselagen/sequence-utils";
10
13
 
11
14
  import AddOrEditAnnotationDialog from "../AddOrEditAnnotationDialog";
12
15
  import { convertRangeTo0Based } from "@teselagen/range-utils";
13
- import { getAcceptedChars } from "../../utils/editorUtils";
14
16
  import classNames from "classnames";
15
17
  import "./style.css";
16
18
  import { getSequenceWithinRange } from "@teselagen/range-utils";
@@ -42,14 +44,9 @@ const CustomContentEditable = generateField(function CustomContentEditable({
42
44
  const newVal = e.target.innerText;
43
45
  const savedCaretPosition = CaretPositioning.saveSelection(e.currentTarget);
44
46
  setCaretPosition(savedCaretPosition);
45
- const acceptedChars = getAcceptedChars(sequenceData);
46
- let newBases = "";
47
- newVal.split("").forEach(letter => {
48
- if (acceptedChars.includes(letter.toLowerCase())) {
49
- newBases += letter;
50
- }
51
- });
52
- if (newVal.length !== newBases.length) {
47
+ const [newBases, warnings] = filterSequenceString(newVal, sequenceData);
48
+
49
+ if (warnings.length) {
53
50
  setTempError(true);
54
51
  setTimeout(() => {
55
52
  setTempError(false);
@@ -4,7 +4,6 @@ import { divideBy3 } from "./proteinUtils";
4
4
  import {
5
5
  getInsertBetweenVals,
6
6
  calculatePercentGC,
7
- bioData,
8
7
  aliasedEnzymesByName
9
8
  } from "@teselagen/sequence-utils";
10
9
  import { get, sortBy } from "lodash";
@@ -172,24 +171,6 @@ export function getSelFromWrappedAddon(selectionLayer, sequenceLength) {
172
171
  return selToUse;
173
172
  }
174
173
 
175
- export function getAcceptedChars({
176
- isOligo,
177
- isProtein,
178
- isRna,
179
- isMixedRnaAndDna
180
- } = {}) {
181
- return isProtein
182
- ? bioData.extended_protein_letters.toLowerCase()
183
- : isOligo
184
- ? bioData.ambiguous_rna_letters.toLowerCase() + "t"
185
- : isRna
186
- ? bioData.ambiguous_rna_letters.toLowerCase()
187
- : isMixedRnaAndDna
188
- ? bioData.ambiguous_rna_letters.toLowerCase() +
189
- bioData.ambiguous_dna_letters.toLowerCase()
190
- : //just plain old dna
191
- bioData.ambiguous_dna_letters.toLowerCase();
192
- }
193
174
  export function getStripedPattern({ color }) {
194
175
  return (
195
176
  <pattern
@@ -6,7 +6,8 @@ import Popper from "popper.js";
6
6
 
7
7
  import {
8
8
  getInsertBetweenVals,
9
- convertDnaCaretPositionOrRangeToAA
9
+ convertDnaCaretPositionOrRangeToAA,
10
+ filterSequenceString
10
11
  } from "@teselagen/sequence-utils";
11
12
  import React from "react";
12
13
  import { divideBy3 } from "../utils/proteinUtils";
@@ -77,9 +78,8 @@ class SequenceInputNoHotkeys extends React.Component {
77
78
  selectionLayer,
78
79
  sequenceLength,
79
80
  isProtein,
80
- replaceChars,
81
81
  caretPosition,
82
- acceptedChars,
82
+ sequenceData,
83
83
  maxInsertSize
84
84
  } = this.props;
85
85
  const { charsToInsert, hasTempError } = this.state;
@@ -136,19 +136,14 @@ class SequenceInputNoHotkeys extends React.Component {
136
136
  autoFocus
137
137
  style={hasTempError ? { borderColor: "red" } : {}}
138
138
  onChange={e => {
139
- let sanitizedVal = "";
140
- e.target.value.split("").forEach(letter => {
141
- const lowerLetter = letter.toLowerCase();
142
- if (replaceChars && replaceChars[lowerLetter]) {
143
- const isUpper = lowerLetter !== letter;
144
- sanitizedVal += isUpper
145
- ? replaceChars[lowerLetter].toUpperCase()
146
- : replaceChars[lowerLetter];
147
- } else if (acceptedChars.includes(lowerLetter)) {
148
- sanitizedVal += letter;
139
+ const [sanitizedVal, warnings] = filterSequenceString(
140
+ e.target.value,
141
+ {
142
+ ...sequenceData,
143
+ name: undefined
149
144
  }
150
- });
151
- if (e.target.value.length !== sanitizedVal.length) {
145
+ );
146
+ if (warnings.length) {
152
147
  this.setState({
153
148
  hasTempError: true
154
149
  });
@@ -165,7 +160,6 @@ class SequenceInputNoHotkeys extends React.Component {
165
160
  );
166
161
  }
167
162
  e.target.value = sanitizedVal;
168
-
169
163
  this.setState({ charsToInsert: sanitizedVal });
170
164
  }}
171
165
  />
@@ -41,11 +41,7 @@ import {
41
41
  createNewAnnotationMenu
42
42
  } from "../MenuBar/defaultConfig";
43
43
  import { fullSequenceTranslationMenu } from "../MenuBar/viewSubmenu";
44
- import {
45
- getAcceptedChars,
46
- getNodeToRefocus,
47
- getSelFromWrappedAddon
48
- } from "../utils/editorUtils";
44
+ import { getNodeToRefocus, getSelFromWrappedAddon } from "../utils/editorUtils";
49
45
 
50
46
  import {
51
47
  showAddOrEditAnnotationDialog,
@@ -212,7 +208,8 @@ function VectorInteractionHOC(Component /* options */) {
212
208
  selectionLayer = { start: -1, end: -1 },
213
209
  readOnly,
214
210
  onPaste,
215
- disableBpEditing
211
+ disableBpEditing,
212
+ sequenceData
216
213
  } = this.props;
217
214
 
218
215
  if (disableBpEditing) {
@@ -240,6 +237,7 @@ function VectorInteractionHOC(Component /* options */) {
240
237
  }
241
238
 
242
239
  seqDataToInsert = tidyUpSequenceData(seqDataToInsert, {
240
+ topLevelSeqData: sequenceData,
243
241
  provideNewIdsForAnnotations: true,
244
242
  annotationsAsObjects: true,
245
243
  removeUnwantedChars: true,
@@ -360,8 +358,7 @@ function VectorInteractionHOC(Component /* options */) {
360
358
  createSequenceInputPopup({
361
359
  useEventPositioning,
362
360
  isReplace,
363
- replaceChars: sequenceData.isRna ? { t: "u" } : undefined,
364
- acceptedChars: getAcceptedChars(sequenceData),
361
+ sequenceData,
365
362
  isProtein: sequenceData.isProtein,
366
363
  selectionLayer,
367
364
  sequenceLength,