@teselagen/ove 0.8.40 → 0.8.42

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.es.js CHANGED
@@ -90296,17 +90296,20 @@ function snapgeneToJson(_0) {
90296
90296
  const b3 = new fxpExports.XMLParser({
90297
90297
  ignoreAttributes: false,
90298
90298
  attributeNamePrefix: "",
90299
- isArray: /* @__PURE__ */ __name((name2) => name2 === "Feature" || name2 === "Segment", "isArray")
90299
+ isArray: /* @__PURE__ */ __name((name2) => ["Feature", "Segment", "Q", "V"].includes(name2), "isArray")
90300
90300
  }).parse(xml2);
90301
90301
  const { Features: { Feature: Feature2 = [] } = {} } = b3;
90302
90302
  data.features = [];
90303
90303
  Feature2.forEach((feat) => {
90304
+ var _a2, _b2, _c, _d;
90304
90305
  const { directionality, Segment = [], name: name2, type: type2 } = feat;
90306
+ let color2;
90305
90307
  let maxStart = 0;
90306
90308
  let maxEnd = 0;
90307
90309
  const locations = Segment && Segment.map((seg) => {
90308
90310
  if (!seg) throw new Error("invalid feature definition");
90309
90311
  const { range: range2 } = seg;
90312
+ if (seg.color) color2 = seg.color;
90310
90313
  let { start: start2, end: end2 } = getStartAndEndFromRangeString(range2);
90311
90314
  start2 = isProtein2 ? start2 * 3 : start2;
90312
90315
  end2 = isProtein2 ? end2 * 3 + 2 : end2;
@@ -90317,6 +90320,10 @@ function snapgeneToJson(_0) {
90317
90320
  end: end2
90318
90321
  };
90319
90322
  });
90323
+ const colorQual = (_a2 = feat.Q) == null ? void 0 : _a2.find((q2) => q2.name === "color");
90324
+ if (colorQual) {
90325
+ color2 = ((_c = (_b2 = colorQual.V) == null ? void 0 : _b2[0]) == null ? void 0 : _c.text) || ((_d = colorQual.V) == null ? void 0 : _d[0]);
90326
+ }
90320
90327
  data.features.push(__spreadProps(__spreadValues({
90321
90328
  name: name2,
90322
90329
  type: type2
@@ -90324,8 +90331,8 @@ function snapgeneToJson(_0) {
90324
90331
  strand: directionality ? strand_dict[directionality][0] : 1,
90325
90332
  arrowheadType: directionality ? strand_dict[directionality][1] : "NONE",
90326
90333
  start: maxStart,
90327
- end: maxEnd
90328
- // color,
90334
+ end: maxEnd,
90335
+ color: color2
90329
90336
  }));
90330
90337
  });
90331
90338
  } else if (ord(next_byte) === 6) {
@@ -95492,14 +95499,34 @@ function addHighlightedDifferences(alignmentTracks) {
95492
95499
  track.alignmentData.sequence
95493
95500
  );
95494
95501
  const mismatches = matchHighlightRanges.filter(({ isMatch }) => !isMatch);
95502
+ const alignedSeq = track.alignmentData.sequence;
95503
+ const seqLen = alignedSeq.length;
95504
+ const startIndex = seqLen - alignedSeq.replace(/^-+/, "").length;
95505
+ const endIndex = alignedSeq.replace(/-+$/, "").length;
95506
+ const gapRanges = [
95507
+ startIndex > 0 && {
95508
+ start: 0,
95509
+ end: startIndex - 1,
95510
+ differenceType: "gap"
95511
+ },
95512
+ endIndex < seqLen && {
95513
+ start: endIndex,
95514
+ end: seqLen - 1,
95515
+ differenceType: "gap"
95516
+ }
95517
+ ].filter(Boolean);
95495
95518
  return __spreadProps(__spreadValues({}, track), {
95496
95519
  sequenceData: sequenceData2,
95497
95520
  matchHighlightRanges,
95498
- additionalSelectionLayers: matchHighlightRanges.filter(({ isMatch }) => !isMatch).map((range2) => {
95499
- return __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
95521
+ additionalSelectionLayers: [
95522
+ ...matchHighlightRanges.filter(({ isMatch }) => !isMatch).map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
95500
95523
  className: "veAlignmentMismatch"
95501
- });
95502
- }),
95524
+ })),
95525
+ ...gapRanges.map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
95526
+ className: "veAlignmentMismatch"
95527
+ }))
95528
+ ],
95529
+ gapRanges,
95503
95530
  mismatches
95504
95531
  });
95505
95532
  });
@@ -95633,23 +95660,30 @@ function getRangeMatchesBetweenTemplateAndNonTemplate(tempSeq, nonTempSeq) {
95633
95660
  const startIndex = seqLength - nonTempSeqWithoutLeadingDashes.length;
95634
95661
  const endIndex = seqLength - (seqLength - nonTempSeqWithoutTrailingDashes.length);
95635
95662
  for (let index2 = startIndex; index2 < endIndex; index2++) {
95636
- const isMatch = tempSeq[index2].toLowerCase() === nonTempSeq[index2].toLowerCase();
95637
- const previousRange = ranges[ranges.length - 1];
95638
- if (previousRange) {
95639
- if (previousRange.isMatch === isMatch) {
95640
- previousRange.end++;
95663
+ const tempBase = tempSeq[index2].toLowerCase();
95664
+ const nonTempBase = nonTempSeq[index2].toLowerCase();
95665
+ const isMatch = tempBase === nonTempBase;
95666
+ let differenceType = null;
95667
+ if (!isMatch) {
95668
+ if (tempBase === "-") {
95669
+ differenceType = "insertion";
95670
+ } else if (nonTempBase === "-") {
95671
+ differenceType = "deletion";
95641
95672
  } else {
95642
- ranges.push({
95643
- start: index2,
95644
- end: index2,
95645
- isMatch
95646
- });
95673
+ differenceType = "mismatch";
95647
95674
  }
95675
+ }
95676
+ const previousRange = ranges[ranges.length - 1];
95677
+ if (previousRange && previousRange.isMatch === isMatch && previousRange.differenceType === differenceType) {
95678
+ previousRange.end++;
95679
+ } else if (previousRange) {
95680
+ ranges.push({ start: index2, end: index2, isMatch, differenceType });
95648
95681
  } else {
95649
95682
  ranges.push({
95650
95683
  start: startIndex,
95651
95684
  end: startIndex,
95652
- isMatch
95685
+ isMatch,
95686
+ differenceType
95653
95687
  });
95654
95688
  }
95655
95689
  }
@@ -117227,7 +117261,7 @@ function showFileDialog({ multiple = false, onSelect }) {
117227
117261
  input.click();
117228
117262
  }
117229
117263
  __name(showFileDialog, "showFileDialog");
117230
- const version = "0.8.40";
117264
+ const version = "0.8.42";
117231
117265
  const packageJson = {
117232
117266
  version
117233
117267
  };
@@ -125096,11 +125130,13 @@ const _Minimap = class _Minimap extends React__default.Component {
125096
125130
  dimensions: { width = 200 },
125097
125131
  laneHeight,
125098
125132
  laneSpacing = 1,
125099
- isTrackSelected = []
125133
+ isTrackSelected = [],
125134
+ activeFilterType = "all"
125100
125135
  } = this.props;
125101
125136
  const charWidth2 = this.getCharWidth();
125102
125137
  const {
125103
125138
  matchHighlightRanges: _matchHighlightRanges,
125139
+ gapRanges = [],
125104
125140
  alignmentData: { trimmedRange } = {}
125105
125141
  } = alignmentTracks[i];
125106
125142
  const matchHighlightRanges = !trimmedRange ? _matchHighlightRanges : flatMap(_matchHighlightRanges, (r2) => {
@@ -125127,10 +125163,19 @@ const _Minimap = class _Minimap extends React__default.Component {
125127
125163
  charWidth2
125128
125164
  );
125129
125165
  const toAdd = `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
125130
- if (!range2.isMatch) {
125166
+ if (!range2.isMatch && (activeFilterType === "all" || range2.differenceType === activeFilterType)) {
125131
125167
  redPath += toAdd;
125132
125168
  }
125133
125169
  });
125170
+ if (activeFilterType === "gap") {
125171
+ gapRanges.forEach((range2) => {
125172
+ const { xStart, width: width2 } = getXStartAndWidthFromNonCircularRange(
125173
+ range2,
125174
+ charWidth2
125175
+ );
125176
+ redPath += `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
125177
+ });
125178
+ }
125134
125179
  return /* @__PURE__ */ React__default.createElement(
125135
125180
  "div",
125136
125181
  {
@@ -125160,7 +125205,8 @@ const _Minimap = class _Minimap extends React__default.Component {
125160
125205
  "scrollAlignmentView",
125161
125206
  "laneHeight",
125162
125207
  "laneSpacing",
125163
- "isTrackSelected"
125208
+ "isTrackSelected",
125209
+ "activeFilterType"
125164
125210
  ].some((key) => props[key] !== newProps[key]))
125165
125211
  return true;
125166
125212
  return false;
@@ -125438,6 +125484,66 @@ function getTrimmedRangesToDisplay({ trimmedRange, seqLen }) {
125438
125484
  return splitRangeIntoTwoPartsIfItIsCircular(inverted, seqLen);
125439
125485
  }
125440
125486
  __name(getTrimmedRangesToDisplay, "getTrimmedRangesToDisplay");
125487
+ function groupConsecutiveDifferences(differences) {
125488
+ const grouped = [];
125489
+ for (const diff of differences) {
125490
+ if (diff.type === "mismatch") {
125491
+ grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
125492
+ continue;
125493
+ }
125494
+ const last2 = grouped[grouped.length - 1];
125495
+ if (last2 && last2.type === diff.type && last2.end === diff.position - 1) {
125496
+ grouped[grouped.length - 1] = __spreadProps(__spreadValues({}, last2), { end: diff.position });
125497
+ } else {
125498
+ grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
125499
+ }
125500
+ }
125501
+ return grouped;
125502
+ }
125503
+ __name(groupConsecutiveDifferences, "groupConsecutiveDifferences");
125504
+ function findAlignmentDifferences(alignedSeqs) {
125505
+ var _a2;
125506
+ if (alignedSeqs.length < 2 || !((_a2 = alignedSeqs[0]) == null ? void 0 : _a2.length)) return [];
125507
+ const template = alignedSeqs[0].toLowerCase();
125508
+ const nonTemplates = alignedSeqs.slice(1).map((s2) => s2.toLowerCase());
125509
+ const trackBounds = nonTemplates.map((seq) => {
125510
+ const withoutLeading = seq.replace(/^-+/, "");
125511
+ const withoutTrailing = seq.replace(/-+$/, "");
125512
+ const start2 = seq.length - withoutLeading.length;
125513
+ const end2 = seq.length - (seq.length - withoutTrailing.length);
125514
+ return { start: start2, end: end2 };
125515
+ });
125516
+ const differences = [];
125517
+ for (let i = 0; i < template.length; i++) {
125518
+ const templateBase = template[i];
125519
+ const allNonTemplateBases = nonTemplates.map((seq) => seq[i]);
125520
+ const bases = [templateBase, ...allNonTemplateBases];
125521
+ const alignedIndices = trackBounds.reduce((acc, { start: start2, end: end2 }, idx) => {
125522
+ if (i >= start2 && i < end2) acc.push(idx);
125523
+ return acc;
125524
+ }, []);
125525
+ if (alignedIndices.length === 0) {
125526
+ differences.push({ position: i, type: "gap", bases });
125527
+ continue;
125528
+ }
125529
+ const alignedBases = alignedIndices.map((idx) => allNonTemplateBases[idx]);
125530
+ const templateIsGap = templateBase === "-";
125531
+ const nonTemplateHasBase = alignedBases.some((b3) => b3 !== "-");
125532
+ const nonTemplateHasGap = alignedBases.some((b3) => b3 === "-");
125533
+ if (templateIsGap && nonTemplateHasBase) {
125534
+ differences.push({ position: i, type: "insertion", bases });
125535
+ } else if (!templateIsGap && nonTemplateHasGap) {
125536
+ differences.push({ position: i, type: "deletion", bases });
125537
+ } else if (!templateIsGap) {
125538
+ const uniqueBases = /* @__PURE__ */ new Set([templateBase, ...alignedBases]);
125539
+ if (uniqueBases.size > 1) {
125540
+ differences.push({ position: i, type: "mismatch", bases });
125541
+ }
125542
+ }
125543
+ }
125544
+ return differences;
125545
+ }
125546
+ __name(findAlignmentDifferences, "findAlignmentDifferences");
125441
125547
  function scrollToAlignmentSelection() {
125442
125548
  const el = document.querySelector(".veCaret");
125443
125549
  if (el) {
@@ -125451,159 +125557,145 @@ function updateCaretPosition({ start: start2, end: end2 }) {
125451
125557
  }
125452
125558
  }
125453
125559
  __name(updateCaretPosition, "updateCaretPosition");
125560
+ const FILTER_OPTIONS = [
125561
+ { value: "all", label: "All" },
125562
+ { value: "mismatch", label: "Mismatches" },
125563
+ { value: "insertion", label: "Insertions" },
125564
+ { value: "deletion", label: "Deletions" },
125565
+ { value: "gap", label: "Gaps" }
125566
+ ];
125454
125567
  function FindMismatches(props) {
125455
- const { alignmentJson, id: id2 } = props;
125568
+ var _a2;
125569
+ const { alignmentJson, id: id2, onFilterChange } = props;
125456
125570
  const alignedSeqs = useMemo$1(
125457
125571
  () => alignmentJson.map((t2) => {
125458
- var _a2;
125459
- return ((_a2 = t2.alignmentData) == null ? void 0 : _a2.sequence) || "";
125572
+ var _a3;
125573
+ return ((_a3 = t2.alignmentData) == null ? void 0 : _a3.sequence) || "";
125460
125574
  }),
125461
125575
  [alignmentJson]
125462
125576
  );
125463
- const mismatches = useMemo$1(() => {
125464
- const result = [{ position: 0, bases: [""] }];
125465
- if (alignedSeqs.length > 1 && alignedSeqs[0].length) {
125466
- for (let i = 0; i < alignedSeqs[0].length; i++) {
125467
- const bases = alignedSeqs.map((seq) => seq[i]);
125468
- const uniqueBases = new Set(bases);
125469
- if (uniqueBases.size > 1 && !uniqueBases.has("-")) {
125470
- result.push({ position: i, bases });
125471
- }
125472
- }
125473
- }
125474
- return result;
125475
- }, [alignedSeqs]);
125577
+ const [activeFilter, setActiveFilter] = React__default.useState("all");
125578
+ const allDifferences = useMemo$1(
125579
+ () => groupConsecutiveDifferences(findAlignmentDifferences(alignedSeqs)),
125580
+ [alignedSeqs]
125581
+ );
125582
+ const countsByType = useMemo$1(() => {
125583
+ const counts = { all: 0, mismatch: 0, insertion: 0, deletion: 0, gap: 0 };
125584
+ allDifferences.forEach((d2) => {
125585
+ counts[d2.type] = (counts[d2.type] || 0) + 1;
125586
+ counts.all++;
125587
+ });
125588
+ return counts;
125589
+ }, [allDifferences]);
125590
+ const differences = useMemo$1(() => {
125591
+ const filtered = activeFilter === "all" ? allDifferences : allDifferences.filter((d2) => d2.type === activeFilter);
125592
+ return [{ position: -1, start: -1, end: -1, bases: [""] }, ...filtered];
125593
+ }, [allDifferences, activeFilter]);
125476
125594
  const currentCaretPosition = useSelector(
125477
125595
  (state2) => {
125478
- var _a2;
125479
- return (_a2 = state2.VectorEditor.__allEditorsOptions.alignments[id2]) == null ? void 0 : _a2.caretPosition;
125596
+ var _a3;
125597
+ return (_a3 = state2.VectorEditor.__allEditorsOptions.alignments[id2]) == null ? void 0 : _a3.caretPosition;
125480
125598
  }
125481
125599
  );
125482
125600
  const [currentIdx, setCurrentIdx] = React__default.useState(0);
125483
- const [disablePrev, setDisablePrev] = React__default.useState(true);
125484
- const [disableNext, setDisableNext] = React__default.useState(false);
125485
- const currentMismatch = mismatches[currentIdx];
125486
- const handleButtonsState = useCallback$1(
125487
- (caret) => {
125488
- if (mismatches.length <= 1) {
125489
- setDisablePrev(true);
125490
- setDisableNext(true);
125491
- return;
125492
- }
125493
- const firstMismatchPos = mismatches[1].position;
125494
- const lastMismatchPos = mismatches[mismatches.length - 1].position;
125495
- setDisablePrev(caret <= firstMismatchPos);
125496
- setDisableNext(caret >= lastMismatchPos);
125497
- },
125498
- [mismatches]
125499
- );
125601
+ const currentDiff = differences[currentIdx];
125602
+ const disablePrev = currentIdx <= 1;
125603
+ const disableNext = currentIdx >= differences.length - 1;
125604
+ useEffect(() => {
125605
+ setCurrentIdx(0);
125606
+ }, [activeFilter]);
125607
+ useEffect(() => {
125608
+ onFilterChange == null ? void 0 : onFilterChange({ activeFilter });
125609
+ }, [activeFilter, onFilterChange]);
125500
125610
  useEffect(() => {
125501
125611
  if (currentCaretPosition !== -1) {
125502
- const mismatchIdx = mismatches.findIndex(
125503
- (m2) => m2.position === currentCaretPosition || m2.position === currentCaretPosition - 1
125612
+ const diffIdx = differences.findIndex(
125613
+ (d2, i) => i > 0 && currentCaretPosition >= d2.start && currentCaretPosition <= d2.end + 1
125504
125614
  );
125505
- if (mismatchIdx !== -1 && mismatchIdx !== currentIdx) {
125506
- handleButtonsState(currentCaretPosition);
125507
- setCurrentIdx(mismatchIdx);
125615
+ if (diffIdx !== -1 && diffIdx !== currentIdx) {
125616
+ setCurrentIdx(diffIdx);
125508
125617
  }
125509
125618
  }
125510
- }, [currentCaretPosition, mismatches, currentIdx, handleButtonsState]);
125511
- const updateView = /* @__PURE__ */ __name((mismatch) => {
125512
- const idx = mismatches.indexOf(mismatch);
125513
- const position2 = mismatch.position;
125514
- handleButtonsState(position2);
125619
+ }, [currentCaretPosition, differences, currentIdx]);
125620
+ const updateView = /* @__PURE__ */ __name((diff) => {
125621
+ const idx = differences.indexOf(diff);
125622
+ const { start: start2, end: end2 } = diff;
125515
125623
  setCurrentIdx(idx);
125516
- updateCaretPosition({ start: position2, end: position2 });
125624
+ updateCaretPosition({ start: start2, end: end2 });
125517
125625
  setTimeout(() => {
125518
125626
  scrollToAlignmentSelection();
125519
125627
  }, 0);
125520
125628
  }, "updateView");
125521
- const prevMismatch = /* @__PURE__ */ __name(() => {
125522
- if (currentIdx > 1) {
125523
- const newIdx = Math.max(0, currentIdx - 1);
125524
- let prev = mismatches[newIdx];
125525
- if (currentCaretPosition > 0) {
125526
- prev = [...mismatches].reverse().find((m2) => m2.position < currentCaretPosition);
125527
- }
125528
- if (prev) {
125529
- updateView(prev);
125530
- }
125531
- }
125532
- }, "prevMismatch");
125533
- const nextMismatch = /* @__PURE__ */ __name(() => {
125534
- if (currentIdx < mismatches.length - 1) {
125535
- const newIdx = Math.min(mismatches.length - 1, currentIdx + 1);
125536
- let next = mismatches[newIdx];
125537
- if (currentCaretPosition > 0) {
125538
- next = mismatches.find(
125539
- (m2) => m2.position > currentCaretPosition && m2.position > 1
125540
- );
125541
- }
125542
- if (next) {
125543
- updateView(next);
125629
+ const prevDifference = /* @__PURE__ */ __name(() => {
125630
+ var _a3, _b2;
125631
+ const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : 0;
125632
+ const prev = [...differences].reverse().find((d2) => d2.start >= 0 && d2.start < pivot);
125633
+ if (prev) updateView(prev);
125634
+ }, "prevDifference");
125635
+ const nextDifference = /* @__PURE__ */ __name(() => {
125636
+ var _a3, _b2;
125637
+ const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : -1;
125638
+ const next = differences.find((d2) => d2.start > pivot && d2.start >= 0);
125639
+ if (next) updateView(next);
125640
+ }, "nextDifference");
125641
+ const noDifferences = differences.length <= 1;
125642
+ const activeOption = FILTER_OPTIONS.find((o2) => o2.value === activeFilter);
125643
+ const activeLabel = (_a2 = activeOption == null ? void 0 : activeOption.label) != null ? _a2 : "Differences";
125644
+ const filterMenu = /* @__PURE__ */ React__default.createElement(Menu, null, FILTER_OPTIONS.map(({ value, label }) => {
125645
+ var _a3;
125646
+ const count2 = (_a3 = countsByType[value]) != null ? _a3 : 0;
125647
+ const isActive2 = activeFilter === value;
125648
+ return /* @__PURE__ */ React__default.createElement(
125649
+ MenuItem,
125650
+ {
125651
+ key: value,
125652
+ active: isActive2,
125653
+ onClick: /* @__PURE__ */ __name(() => setActiveFilter(value), "onClick"),
125654
+ text: /* @__PURE__ */ React__default.createElement("span", { className: "veDiffMenuItem-inner" }, label, /* @__PURE__ */ React__default.createElement(Tag, { round: true, minimal: true, style: { marginLeft: 6 } }, count2))
125544
125655
  }
125545
- }
125546
- }, "nextMismatch");
125547
- return /* @__PURE__ */ React__default.createElement(
125548
- "div",
125656
+ );
125657
+ }));
125658
+ return /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNavigator" }, /* @__PURE__ */ React__default.createElement(
125659
+ Popover,
125549
125660
  {
125550
- style: {
125551
- display: "flex",
125552
- flexDirection: "row",
125553
- justifyContent: "center",
125554
- alignItems: "center",
125555
- gap: 10
125556
- }
125557
- },
125558
- mismatches.length === 1 ? /* @__PURE__ */ React__default.createElement("span", { style: { fontStyle: "italic", color: "grey" } }, "no mismatches") : /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React__default.createElement(
125559
- "div",
125560
- {
125561
- style: {
125562
- display: "flex",
125563
- alignItems: "center"
125564
- }
125565
- },
125566
- /* @__PURE__ */ React__default.createElement("strong", null, "Mismatches"),
125567
- /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", gap: 2 } }, /* @__PURE__ */ React__default.createElement(
125568
- Button,
125569
- {
125570
- intent: "primary",
125571
- icon: "arrow-left",
125572
- "data-tip": "Previous Mismatch",
125573
- onClick: prevMismatch,
125574
- disabled: disablePrev,
125575
- small: true,
125576
- minimal: true
125577
- }
125578
- ), /* @__PURE__ */ React__default.createElement(
125661
+ minimal: true,
125662
+ position: Position.BOTTOM_LEFT,
125663
+ content: filterMenu,
125664
+ target: /* @__PURE__ */ React__default.createElement(
125579
125665
  Button,
125580
125666
  {
125581
- intent: "primary",
125582
- icon: "arrow-right",
125583
- "data-tip": "Next Mismatch",
125584
- onClick: nextMismatch,
125585
- disabled: disableNext,
125667
+ minimal: true,
125668
+ "data-tip": "Filter Difference Type",
125586
125669
  small: true,
125587
- minimal: true
125588
- }
125589
- ))
125590
- ), /* @__PURE__ */ React__default.createElement(
125591
- "span",
125592
- {
125593
- style: {
125594
- fontSize: "0.8em",
125595
- color: "grey",
125596
- lineHeight: "0.8em"
125597
- }
125598
- },
125599
- currentMismatch.position > 1 && /* @__PURE__ */ React__default.createElement("span", null, "Position: ", currentMismatch.position + 1, " | "),
125600
- "(",
125601
- currentIdx,
125602
- " of ",
125603
- mismatches.length - 1,
125604
- ")"
125605
- ))
125606
- );
125670
+ rightIcon: "caret-down",
125671
+ className: "veDiffFilter-trigger"
125672
+ },
125673
+ activeLabel
125674
+ )
125675
+ }
125676
+ ), noDifferences ? /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-empty" }, "no", " ", activeFilter === "all" ? "differences" : activeLabel.toLowerCase()) : /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNav" }, /* @__PURE__ */ React__default.createElement(
125677
+ Button,
125678
+ {
125679
+ minimal: true,
125680
+ small: true,
125681
+ "data-tip": "Previous Difference",
125682
+ icon: "arrow-left",
125683
+ intent: Intent.PRIMARY,
125684
+ onClick: prevDifference,
125685
+ disabled: disablePrev
125686
+ }
125687
+ ), /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNav-center" }, /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-fraction" }, currentIdx, /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-sep" }, "/"), differences.length - 1), (currentDiff == null ? void 0 : currentDiff.start) > -1 && /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-pos" }, ":", currentDiff.start + 1)), /* @__PURE__ */ React__default.createElement(
125688
+ Button,
125689
+ {
125690
+ minimal: true,
125691
+ small: true,
125692
+ "data-tip": "Next Difference",
125693
+ icon: "arrow-right",
125694
+ intent: Intent.PRIMARY,
125695
+ onClick: nextDifference,
125696
+ disabled: disableNext
125697
+ }
125698
+ )));
125607
125699
  }
125608
125700
  __name(FindMismatches, "FindMismatches");
125609
125701
  function getGapMap(sequence2) {
@@ -126292,17 +126384,18 @@ const AlignmentVisibilityTool = pure(/* @__PURE__ */ __name(function AlignmentVi
126292
126384
  minimal: true,
126293
126385
  position: "bottom",
126294
126386
  content: /* @__PURE__ */ React__default.createElement(VisibilityOptions$2, __spreadValues({}, props)),
126295
- target: /* @__PURE__ */ React__default.createElement(Tooltip, { content: "Visibility Options" }, /* @__PURE__ */ React__default.createElement(
126387
+ target: /* @__PURE__ */ React__default.createElement(
126296
126388
  Button,
126297
126389
  {
126298
126390
  className: "tg-alignment-visibility-toggle",
126299
126391
  small: true,
126392
+ "data-tip": "Visibility Options",
126300
126393
  rightIcon: "caret-down",
126301
126394
  intent: Intent.PRIMARY,
126302
126395
  minimal: true,
126303
126396
  icon: "eye-open"
126304
126397
  }
126305
- ))
126398
+ )
126306
126399
  }
126307
126400
  );
126308
126401
  }, "AlignmentVisibilityTool"));
@@ -140090,6 +140183,10 @@ const AlignmentView = /* @__PURE__ */ __name((props) => {
140090
140183
  const [tempTrimAfter, setTempTrimAfter] = useState({});
140091
140184
  const [tempTrimmingCaret, setTempTrimmingCaret] = useState({});
140092
140185
  const [searchMatchLayers, setSearchMatchLayers] = React__default.useState([]);
140186
+ const [activeFilterType, setActiveFilterType] = useState("all");
140187
+ const handleFilterChange = useCallback$1(({ activeFilter }) => {
140188
+ setActiveFilterType(activeFilter);
140189
+ }, []);
140093
140190
  const bindOutsideChangeHelper = useRef({});
140094
140191
  const alignmentHolder = useRef(null);
140095
140192
  const alignmentHolderTop = useRef(null);
@@ -140815,7 +140912,9 @@ ${seqDataToCopy}\r
140815
140912
  chromatogramData
140816
140913
  }) : linearViewOptions)), {
140817
140914
  additionalSelectionLayers: [
140818
- ...additionalSelectionLayers || [],
140915
+ ...i !== 0 ? (additionalSelectionLayers || []).filter(
140916
+ (layer) => activeFilterType === "all" ? layer.differenceType !== "gap" : layer.differenceType === activeFilterType
140917
+ ) : additionalSelectionLayers || [],
140819
140918
  ...searchMatchLayers || []
140820
140919
  ],
140821
140920
  dimensions: {
@@ -141474,7 +141573,14 @@ ${seqDataToCopy}\r
141474
141573
  setSearchMatchLayers
141475
141574
  }
141476
141575
  ),
141477
- /* @__PURE__ */ React__default.createElement(FindMismatches, { alignmentJson: alignmentTracks, id: id2 }),
141576
+ /* @__PURE__ */ React__default.createElement(
141577
+ FindMismatches,
141578
+ {
141579
+ alignmentJson: alignmentTracks,
141580
+ id: id2,
141581
+ onFilterChange: handleFilterChange
141582
+ }
141583
+ ),
141478
141584
  additionalTopEl,
141479
141585
  saveMessage && /* @__PURE__ */ React__default.createElement(
141480
141586
  "div",
@@ -141575,6 +141681,7 @@ ${seqDataToCopy}\r
141575
141681
  }
141576
141682
  )),
141577
141683
  alignmentTracks,
141684
+ activeFilterType,
141578
141685
  dimensions: {
141579
141686
  width: Math.max(width, 10) || 10
141580
141687
  },