@genspectrum/dashboard-components 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/custom-elements.json +220 -0
  2. package/dist/dashboard-components.js +675 -178
  3. package/dist/dashboard-components.js.map +1 -1
  4. package/dist/genspectrum-components.d.ts +70 -2
  5. package/dist/style.css +10 -4
  6. package/package.json +3 -1
  7. package/src/constants.ts +1 -1
  8. package/src/lapisApi/lapisTypes.ts +1 -0
  9. package/src/operator/FillMissingOperator.spec.ts +3 -1
  10. package/src/operator/FillMissingOperator.ts +4 -2
  11. package/src/preact/components/tooltip.stories.tsx +54 -0
  12. package/src/preact/components/tooltip.tsx +31 -0
  13. package/src/preact/mutationComparison/queryMutationData.ts +12 -4
  14. package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +642 -0
  15. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +1747 -0
  16. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +1774 -0
  17. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +1819 -0
  18. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +1864 -0
  19. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +1927 -0
  20. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +1864 -0
  21. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +9 -0
  22. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +98 -0
  23. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +66 -0
  24. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +127 -0
  25. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +206 -0
  26. package/src/preact/mutationsOverTime/mutations-over-time.tsx +170 -0
  27. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +1 -1
  28. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +1 -0
  29. package/src/preact/shared/table/formatProportion.ts +2 -2
  30. package/src/query/queryAggregatedDataOverTime.ts +8 -33
  31. package/src/query/queryMutationsOverTime.spec.ts +378 -0
  32. package/src/query/queryMutationsOverTime.ts +179 -0
  33. package/src/query/queryNumberOfSequencesOverTime.ts +0 -1
  34. package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
  35. package/src/utils/Map2d.ts +75 -0
  36. package/src/utils/map2d.spec.ts +94 -0
  37. package/src/utils/mutations.ts +5 -1
  38. package/src/utils/temporal.spec.ts +5 -0
  39. package/src/utils/temporal.ts +88 -5
  40. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +225 -0
  41. package/src/web-components/visualization/gs-mutations-over-time.tsx +112 -0
  42. package/src/web-components/visualization/index.ts +1 -0
@@ -9,6 +9,7 @@ import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn
9
9
  import { autoUpdate, computePosition, offset, shift, flip, size } from "@floating-ui/dom";
10
10
  import { ReactiveElement } from "@lit/reactive-element";
11
11
  import { BarWithErrorBarsController, BarWithErrorBar } from "chartjs-chart-error-bars";
12
+ import hash from "object-hash";
12
13
  import flatpickr from "flatpickr";
13
14
  /**
14
15
  * @license
@@ -490,14 +491,14 @@ const substitutionsOrDeletionsEndpoint = (lapisUrl, sequenceType) => {
490
491
  return sequenceType === "amino acid" ? `${lapisUrl}/sample/aminoAcidMutations` : `${lapisUrl}/sample/nucleotideMutations`;
491
492
  };
492
493
  const referenceGenomeEndpoint = (lapisUrl) => `${lapisUrl}/sample/referenceGenome`;
493
- var __defProp$c = Object.defineProperty;
494
+ var __defProp$d = Object.defineProperty;
494
495
  var __getOwnPropDesc$c = Object.getOwnPropertyDescriptor;
495
- var __decorateClass$c = (decorators, target, key, kind) => {
496
+ var __decorateClass$d = (decorators, target, key, kind) => {
496
497
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$c(target, key) : target;
497
498
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
498
499
  if (decorator = decorators[i2])
499
500
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
500
- if (kind && result) __defProp$c(target, key, result);
501
+ if (kind && result) __defProp$d(target, key, result);
501
502
  return result;
502
503
  };
503
504
  let App = class extends LitElement {
@@ -528,14 +529,14 @@ let App = class extends LitElement {
528
529
  return this;
529
530
  }
530
531
  };
531
- __decorateClass$c([
532
+ __decorateClass$d([
532
533
  provide({ context: lapisContext }),
533
534
  n2()
534
535
  ], App.prototype, "lapis", 2);
535
- __decorateClass$c([
536
+ __decorateClass$d([
536
537
  provide({ context: referenceGenomeContext })
537
538
  ], App.prototype, "referenceGenome", 2);
538
- App = __decorateClass$c([
539
+ App = __decorateClass$d([
539
540
  t$2("gs-app")
540
541
  ], App);
541
542
  var f$1 = 0;
@@ -558,7 +559,7 @@ function h(n3) {
558
559
  }
559
560
  function p(n3, u2, i2) {
560
561
  var o2 = d(t++, 2);
561
- if (o2.t = n3, !o2.__c && (o2.__ = [i2 ? i2(u2) : D$1(void 0, u2), function(n4) {
562
+ if (o2.t = n3, !o2.__c && (o2.__ = [D$1(void 0, u2), function(n4) {
562
563
  var t2 = o2.__N ? o2.__N[0] : o2.__[0], r2 = o2.t(t2, n4);
563
564
  t2 !== r2 && (o2.__N = [r2, o2.__[1]], o2.__c.setState({}));
564
565
  }], o2.__c = r, !r.u)) {
@@ -773,6 +774,7 @@ class Substitution {
773
774
  this.valueAtReference = valueAtReference;
774
775
  this.substitutionValue = substitutionValue;
775
776
  this.position = position;
777
+ this.type = "substitution";
776
778
  const segmentString = this.segment ? `${this.segment}:` : "";
777
779
  const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
778
780
  const substitutionValueString = this.substitutionValue ? `${this.substitutionValue}` : "";
@@ -806,6 +808,7 @@ class Deletion {
806
808
  this.segment = segment;
807
809
  this.valueAtReference = valueAtReference;
808
810
  this.position = position;
811
+ this.type = "deletion";
809
812
  const segmentString = this.segment ? `${this.segment}:` : "";
810
813
  const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
811
814
  this.code = `${segmentString}${valueAtReferenceString}${this.position}-`;
@@ -833,6 +836,7 @@ class Insertion {
833
836
  this.segment = segment;
834
837
  this.position = position;
835
838
  this.insertedSymbols = insertedSymbols;
839
+ this.type = "insertion";
836
840
  this.code = `ins_${this.segment ? `${this.segment}:` : ""}${this.position}:${this.insertedSymbols}`;
837
841
  }
838
842
  equals(other) {
@@ -918,8 +922,8 @@ const compareSubstitutionValues = (a2, b3) => {
918
922
  }
919
923
  return a2.localeCompare(b3);
920
924
  };
921
- const formatProportion = (proportion) => {
922
- return `${(proportion * 100).toFixed(2)}%`;
925
+ const formatProportion = (proportion, digits = 2) => {
926
+ return `${(proportion * 100).toFixed(digits)}%`;
923
927
  };
924
928
  const MutationComparisonTable = ({
925
929
  data,
@@ -1133,6 +1137,12 @@ async function queryMutationData(lapisFilters, sequenceType, lapis) {
1133
1137
  return { mutationData };
1134
1138
  }
1135
1139
  function filterMutationData(data, displayedSegments, displayedMutationTypes) {
1140
+ return data.map((mutationEntry) => ({
1141
+ displayName: mutationEntry.displayName,
1142
+ data: filterBySegmentAndMutationType(mutationEntry.data, displayedSegments, displayedMutationTypes)
1143
+ }));
1144
+ }
1145
+ function filterBySegmentAndMutationType(data, displayedSegments, displayedMutationTypes) {
1136
1146
  const byDisplayedSegments = (mutationEntry) => {
1137
1147
  if (mutationEntry.mutation.segment === void 0) {
1138
1148
  return true;
@@ -1146,10 +1156,7 @@ function filterMutationData(data, displayedSegments, displayedMutationTypes) {
1146
1156
  (displayedMutationType) => displayedMutationType.checked && displayedMutationType.type === mutationEntry.type
1147
1157
  );
1148
1158
  };
1149
- return data.map((mutationEntry) => ({
1150
- displayName: mutationEntry.displayName,
1151
- data: mutationEntry.data.filter(byDisplayedSegments).filter(byDisplayedMutationTypes)
1152
- }));
1159
+ return data.filter(byDisplayedSegments).filter(byDisplayedMutationTypes);
1153
1160
  }
1154
1161
  const LapisUrlContext = createContext$1("");
1155
1162
  function useFloatingUi(referenceRef, floatingRef, middleware, placement) {
@@ -1750,7 +1757,7 @@ const MutationComparisonTabs = ({
1750
1757
  {
1751
1758
  tabs,
1752
1759
  toolbar: /* @__PURE__ */ u$1(
1753
- Toolbar$4,
1760
+ Toolbar$5,
1754
1761
  {
1755
1762
  displayedSegments,
1756
1763
  setDisplayedSegments,
@@ -1764,7 +1771,7 @@ const MutationComparisonTabs = ({
1764
1771
  }
1765
1772
  );
1766
1773
  };
1767
- const Toolbar$4 = ({
1774
+ const Toolbar$5 = ({
1768
1775
  displayedSegments,
1769
1776
  setDisplayedSegments,
1770
1777
  displayedMutationTypes,
@@ -1804,7 +1811,7 @@ const Toolbar$4 = ({
1804
1811
  const gridJsStyle = '.gridjs-head button, .gridjs-footer button {\n cursor: pointer;\n background-color: transparent;\n background-image: none;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n}\n\n.gridjs-temp {\n position: relative;\n}\n\n.gridjs-head {\n width: 100%;\n margin-bottom: 5px;\n padding: 5px 1px;\n}\n.gridjs-head::after {\n content: "";\n display: block;\n clear: both;\n}\n.gridjs-head:empty {\n padding: 0;\n border: none;\n}\n\n.gridjs-container {\n overflow: hidden;\n display: inline-block;\n padding: 2px;\n color: #000;\n position: relative;\n z-index: 0;\n}\n\n.gridjs-footer {\n display: block;\n position: relative;\n width: 100%;\n z-index: 5;\n padding: 12px 24px;\n border-top: 1px solid #e5e7eb;\n background-color: #fff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.26);\n border-radius: 0 0 8px 8px;\n border-bottom-width: 1px;\n border-color: #e5e7eb;\n}\n.gridjs-footer:empty {\n padding: 0;\n border: none;\n}\n\ninput.gridjs-input {\n outline: none;\n background-color: #fff;\n border: 1px solid #d2d6dc;\n border-radius: 5px;\n padding: 10px 13px;\n font-size: 14px;\n line-height: 1.45;\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\ninput.gridjs-input:focus {\n box-shadow: 0 0 0 3px rgba(149, 189, 243, 0.5);\n border-color: #9bc2f7;\n}\n\n.gridjs-pagination {\n color: #3d4044;\n}\n.gridjs-pagination::after {\n content: "";\n display: block;\n clear: both;\n}\n.gridjs-pagination .gridjs-summary {\n float: left;\n margin-top: 5px;\n}\n.gridjs-pagination .gridjs-pages {\n float: right;\n}\n.gridjs-pagination .gridjs-pages button {\n padding: 5px 14px;\n border: 1px solid #d2d6dc;\n background-color: #fff;\n border-right: none;\n outline: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n.gridjs-pagination .gridjs-pages button:focus {\n box-shadow: 0 0 0 2px rgba(149, 189, 243, 0.5);\n position: relative;\n margin-right: -1px;\n border-right: 1px solid #d2d6dc;\n}\n.gridjs-pagination .gridjs-pages button:hover {\n background-color: #f7f7f7;\n color: rgb(60, 66, 87);\n outline: none;\n}\n.gridjs-pagination .gridjs-pages button:disabled,\n.gridjs-pagination .gridjs-pages button[disabled],\n.gridjs-pagination .gridjs-pages button:hover:disabled {\n cursor: default;\n background-color: #fff;\n color: #6b7280;\n}\n.gridjs-pagination .gridjs-pages button.gridjs-spread {\n cursor: default;\n box-shadow: none;\n background-color: #fff;\n}\n.gridjs-pagination .gridjs-pages button.gridjs-currentPage {\n background-color: #f7f7f7;\n font-weight: bold;\n}\n.gridjs-pagination .gridjs-pages button:last-child {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n border-right: 1px solid #d2d6dc;\n}\n.gridjs-pagination .gridjs-pages button:first-child {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.gridjs-pagination .gridjs-pages button:last-child:focus {\n margin-right: 0;\n}\n\nbutton.gridjs-sort {\n float: right;\n height: 24px;\n width: 13px;\n background-color: transparent;\n background-repeat: no-repeat;\n background-position-x: center;\n cursor: pointer;\n padding: 0;\n margin: 0;\n border: none;\n outline: none;\n background-size: contain;\n}\nbutton.gridjs-sort-neutral {\n opacity: 0.3;\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSI0MDEuOTk4cHgiIGhlaWdodD0iNDAxLjk5OHB4IiB2aWV3Qm94PSIwIDAgNDAxLjk5OCA0MDEuOTk4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0MDEuOTk4IDQwMS45OTg7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik03My4wOTIsMTY0LjQ1MmgyNTUuODEzYzQuOTQ5LDAsOS4yMzMtMS44MDcsMTIuODQ4LTUuNDI0YzMuNjEzLTMuNjE2LDUuNDI3LTcuODk4LDUuNDI3LTEyLjg0NwoJCQljMC00Ljk0OS0xLjgxMy05LjIyOS01LjQyNy0xMi44NUwyMTMuODQ2LDUuNDI0QzIxMC4yMzIsMS44MTIsMjA1Ljk1MSwwLDIwMC45OTksMHMtOS4yMzMsMS44MTItMTIuODUsNS40MjRMNjAuMjQyLDEzMy4zMzEKCQkJYy0zLjYxNywzLjYxNy01LjQyNCw3LjkwMS01LjQyNCwxMi44NWMwLDQuOTQ4LDEuODA3LDkuMjMxLDUuNDI0LDEyLjg0N0M2My44NjMsMTYyLjY0NSw2OC4xNDQsMTY0LjQ1Miw3My4wOTIsMTY0LjQ1MnoiLz4KCQk8cGF0aCBkPSJNMzI4LjkwNSwyMzcuNTQ5SDczLjA5MmMtNC45NTIsMC05LjIzMywxLjgwOC0xMi44NSw1LjQyMWMtMy42MTcsMy42MTctNS40MjQsNy44OTgtNS40MjQsMTIuODQ3CgkJCWMwLDQuOTQ5LDEuODA3LDkuMjMzLDUuNDI0LDEyLjg0OEwxODguMTQ5LDM5Ni41N2MzLjYyMSwzLjYxNyw3LjkwMiw1LjQyOCwxMi44NSw1LjQyOHM5LjIzMy0xLjgxMSwxMi44NDctNS40MjhsMTI3LjkwNy0xMjcuOTA2CgkJCWMzLjYxMy0zLjYxNCw1LjQyNy03Ljg5OCw1LjQyNy0xMi44NDhjMC00Ljk0OC0xLjgxMy05LjIyOS01LjQyNy0xMi44NDdDMzM4LjEzOSwyMzkuMzUzLDMzMy44NTQsMjM3LjU0OSwzMjguOTA1LDIzNy41NDl6Ii8+Cgk8L2c+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: center;\n}\nbutton.gridjs-sort-asc {\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIyOTIuMzYycHgiIGhlaWdodD0iMjkyLjM2MXB4IiB2aWV3Qm94PSIwIDAgMjkyLjM2MiAyOTIuMzYxIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyOTIuMzYyIDI5Mi4zNjE7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0yODYuOTM1LDE5Ny4yODdMMTU5LjAyOCw2OS4zODFjLTMuNjEzLTMuNjE3LTcuODk1LTUuNDI0LTEyLjg0Ny01LjQyNHMtOS4yMzMsMS44MDctMTIuODUsNS40MjRMNS40MjQsMTk3LjI4NwoJCUMxLjgwNywyMDAuOTA0LDAsMjA1LjE4NiwwLDIxMC4xMzRzMS44MDcsOS4yMzMsNS40MjQsMTIuODQ3YzMuNjIxLDMuNjE3LDcuOTAyLDUuNDI1LDEyLjg1LDUuNDI1aDI1NS44MTMKCQljNC45NDksMCw5LjIzMy0xLjgwOCwxMi44NDgtNS40MjVjMy42MTMtMy42MTMsNS40MjctNy44OTgsNS40MjctMTIuODQ3UzI5MC41NDgsMjAwLjkwNCwyODYuOTM1LDE5Ny4yODd6Ii8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: 35%;\n background-size: 10px;\n}\nbutton.gridjs-sort-desc {\n background-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHdpZHRoPSIyOTIuMzYycHgiIGhlaWdodD0iMjkyLjM2MnB4IiB2aWV3Qm94PSIwIDAgMjkyLjM2MiAyOTIuMzYyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyOTIuMzYyIDI5Mi4zNjI7IgoJIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxwYXRoIGQ9Ik0yODYuOTM1LDY5LjM3N2MtMy42MTQtMy42MTctNy44OTgtNS40MjQtMTIuODQ4LTUuNDI0SDE4LjI3NGMtNC45NTIsMC05LjIzMywxLjgwNy0xMi44NSw1LjQyNAoJCUMxLjgwNyw3Mi45OTgsMCw3Ny4yNzksMCw4Mi4yMjhjMCw0Ljk0OCwxLjgwNyw5LjIyOSw1LjQyNCwxMi44NDdsMTI3LjkwNywxMjcuOTA3YzMuNjIxLDMuNjE3LDcuOTAyLDUuNDI4LDEyLjg1LDUuNDI4CgkJczkuMjMzLTEuODExLDEyLjg0Ny01LjQyOEwyODYuOTM1LDk1LjA3NGMzLjYxMy0zLjYxNyw1LjQyNy03Ljg5OCw1LjQyNy0xMi44NDdDMjkyLjM2Miw3Ny4yNzksMjkwLjU0OCw3Mi45OTgsMjg2LjkzNSw2OS4zNzd6Ii8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+");\n background-position-y: 65%;\n background-size: 10px;\n}\nbutton.gridjs-sort:focus {\n outline: none;\n}\n\ntable.gridjs-table {\n width: 100%;\n max-width: 100%;\n border-collapse: collapse;\n text-align: left;\n display: table;\n margin: 0;\n padding: 0;\n overflow: auto;\n table-layout: fixed;\n}\n\n.gridjs-tbody {\n background-color: #fff;\n}\n\ntd.gridjs-td {\n border: 1px solid #e5e7eb;\n padding: 12px 24px;\n background-color: #fff;\n box-sizing: content-box;\n}\ntd.gridjs-td:first-child {\n border-left: none;\n}\ntd.gridjs-td:last-child {\n border-right: none;\n}\ntd.gridjs-message {\n text-align: center;\n}\n\nth.gridjs-th {\n position: relative;\n color: #6b7280;\n background-color: #f9fafb;\n border: 1px solid #e5e7eb;\n border-top: none;\n padding: 14px 24px;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n box-sizing: border-box;\n white-space: nowrap;\n outline: none;\n vertical-align: middle;\n}\nth.gridjs-th .gridjs-th-content {\n text-overflow: ellipsis;\n overflow: hidden;\n width: 100%;\n float: left;\n}\nth.gridjs-th-sort {\n cursor: pointer;\n}\nth.gridjs-th-sort .gridjs-th-content {\n width: calc(100% - 15px);\n}\nth.gridjs-th-sort:hover {\n background-color: #e5e7eb;\n}\nth.gridjs-th-sort:focus {\n background-color: #e5e7eb;\n}\nth.gridjs-th-fixed {\n position: sticky;\n box-shadow: 0 1px 0 0 #e5e7eb;\n}\n@supports (-moz-appearance: none) {\n th.gridjs-th-fixed {\n box-shadow: 0 0 0 1px #e5e7eb;\n }\n}\nth.gridjs-th:first-child {\n border-left: none;\n}\nth.gridjs-th:last-child {\n border-right: none;\n}\n\n.gridjs-tr {\n border: none;\n}\n.gridjs-tr-selected td {\n background-color: #ebf5ff;\n}\n.gridjs-tr:last-child td {\n border-bottom: 0;\n}\n\n.gridjs *,\n.gridjs :after,\n.gridjs :before {\n box-sizing: border-box;\n}\n\n.gridjs-wrapper {\n position: relative;\n z-index: 1;\n overflow: auto;\n width: 100%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.26);\n border-radius: 8px 8px 0 0;\n display: block;\n border-top-width: 1px;\n border-color: #e5e7eb;\n}\n.gridjs-wrapper:nth-last-of-type(2) {\n border-radius: 8px;\n border-bottom-width: 1px;\n}\n\n.gridjs-search {\n float: left;\n}\n.gridjs-search-input {\n width: 250px;\n}\n\n.gridjs-loading-bar {\n z-index: 10;\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n background-color: #fff;\n opacity: 0.5;\n}\n.gridjs-loading-bar::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateX(-100%);\n background-image: linear-gradient(90deg, rgba(204, 204, 204, 0) 0, rgba(204, 204, 204, 0.2) 20%, rgba(204, 204, 204, 0.5) 60%, rgba(204, 204, 204, 0));\n animation: shimmer 2s infinite;\n content: "";\n}\n@keyframes shimmer {\n 100% {\n transform: translateX(100%);\n }\n}\n\n.gridjs-td .gridjs-checkbox {\n display: block;\n margin: auto;\n cursor: pointer;\n}\n\n.gridjs-resizable {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n width: 5px;\n}\n.gridjs-resizable:hover {\n cursor: ew-resize;\n background-color: #9bc2f7;\n}\n/*# sourceMappingURL=mermaid.css?inline.map */';
1805
1812
  const minMaxPercentSliderCss = 'input[type=range]::-webkit-slider-thumb {\n -webkit-appearance: none;\n pointer-events: all;\n width: 24px;\n height: 24px;\n background-color: #fff;\n border-radius: 50%;\n box-shadow: 0 0 0 1px #C6C6C6;\n cursor: pointer;\n}\n\ninput[type=range]::-moz-range-thumb {\n -webkit-appearance: none;\n pointer-events: all;\n width: 24px;\n height: 24px;\n background-color: #fff;\n border-radius: 50%;\n box-shadow: 0 0 0 1px #C6C6C6;\n cursor: pointer;\n}\n\ninput[type=range]::-webkit-slider-thumb:hover {\n background: #f7f7f7;\n}\n\ninput[type=range]::-webkit-slider-thumb:active {\n box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;\n -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe;\n}\n\ninput[type="range"] {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n height: 2px;\n width: 100%;\n position: absolute;\n background-color: #C6C6C6;\n pointer-events: none;\n}';
1806
1813
  const tailwindStyle = `/*
1807
- ! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com
1814
+ ! tailwindcss v3.4.6 | MIT License | https://tailwindcss.com
1808
1815
  *//*
1809
1816
  1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
1810
1817
  2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
@@ -4253,9 +4260,6 @@ input.tab:checked + .tab-content,
4253
4260
  .mb-2 {
4254
4261
  margin-bottom: 0.5rem;
4255
4262
  }
4256
- .ml-2 {
4257
- margin-left: 0.5rem;
4258
- }
4259
4263
  .ml-2\\.5 {
4260
4264
  margin-left: 0.625rem;
4261
4265
  }
@@ -4460,6 +4464,9 @@ input.tab:checked + .tab-content,
4460
4464
  padding-top: 1rem;
4461
4465
  padding-bottom: 1rem;
4462
4466
  }
4467
+ .text-center {
4468
+ text-align: center;
4469
+ }
4463
4470
  .text-justify {
4464
4471
  text-align: justify;
4465
4472
  }
@@ -4551,6 +4558,9 @@ input.tab:checked + .tab-content,
4551
4558
  --tw-bg-opacity: 1;
4552
4559
  background-color: rgb(243 244 246 / var(--tw-bg-opacity));
4553
4560
  }
4561
+ .hover\\:font-bold:hover {
4562
+ font-weight: 700;
4563
+ }
4554
4564
  .hover\\:text-blue-700:hover {
4555
4565
  --tw-text-opacity: 1;
4556
4566
  color: rgb(29 78 216 / var(--tw-text-opacity));
@@ -4575,15 +4585,17 @@ input.tab:checked + .tab-content,
4575
4585
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
4576
4586
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
4577
4587
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
4588
+ }
4589
+ .peer:hover ~ .peer-hover\\:block {
4590
+ display: block;
4578
4591
  }`;
4579
- var __defProp$b = Object.defineProperty;
4580
- var __getOwnPropDesc$b = Object.getOwnPropertyDescriptor;
4581
- var __decorateClass$b = (decorators, target, key, kind) => {
4582
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$b(target, key) : target;
4592
+ var __defProp$c = Object.defineProperty;
4593
+ var __decorateClass$c = (decorators, target, key, kind) => {
4594
+ var result = void 0;
4583
4595
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
4584
4596
  if (decorator = decorators[i2])
4585
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4586
- if (kind && result) __defProp$b(target, key, result);
4597
+ result = decorator(target, key, result) || result;
4598
+ if (result) __defProp$c(target, key, result);
4587
4599
  return result;
4588
4600
  };
4589
4601
  const tailwindElementCss = unsafeCSS(tailwindStyle);
@@ -4605,25 +4617,25 @@ const _PreactLitAdapter = class _PreactLitAdapter extends ReactiveElement {
4605
4617
  };
4606
4618
  _PreactLitAdapter.styles = [tailwindElementCss, minMaxPercentSliderElementCss];
4607
4619
  let PreactLitAdapter = _PreactLitAdapter;
4608
- __decorateClass$b([
4620
+ __decorateClass$c([
4609
4621
  consume({ context: lapisContext })
4610
- ], PreactLitAdapter.prototype, "lapis", 2);
4611
- __decorateClass$b([
4622
+ ], PreactLitAdapter.prototype, "lapis");
4623
+ __decorateClass$c([
4612
4624
  consume({ context: referenceGenomeContext, subscribe: true })
4613
- ], PreactLitAdapter.prototype, "referenceGenome", 2);
4625
+ ], PreactLitAdapter.prototype, "referenceGenome");
4614
4626
  const gridJsElementCss = unsafeCSS(gridJsStyle);
4615
4627
  const _PreactLitAdapterWithGridJsStyles = class _PreactLitAdapterWithGridJsStyles extends PreactLitAdapter {
4616
4628
  };
4617
4629
  _PreactLitAdapterWithGridJsStyles.styles = [...PreactLitAdapter.styles, gridJsElementCss];
4618
4630
  let PreactLitAdapterWithGridJsStyles = _PreactLitAdapterWithGridJsStyles;
4619
- var __defProp$a = Object.defineProperty;
4620
- var __getOwnPropDesc$a = Object.getOwnPropertyDescriptor;
4621
- var __decorateClass$a = (decorators, target, key, kind) => {
4622
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$a(target, key) : target;
4631
+ var __defProp$b = Object.defineProperty;
4632
+ var __getOwnPropDesc$b = Object.getOwnPropertyDescriptor;
4633
+ var __decorateClass$b = (decorators, target, key, kind) => {
4634
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$b(target, key) : target;
4623
4635
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
4624
4636
  if (decorator = decorators[i2])
4625
4637
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4626
- if (kind && result) __defProp$a(target, key, result);
4638
+ if (kind && result) __defProp$b(target, key, result);
4627
4639
  return result;
4628
4640
  };
4629
4641
  let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -4650,25 +4662,25 @@ let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles
4650
4662
  );
4651
4663
  }
4652
4664
  };
4653
- __decorateClass$a([
4665
+ __decorateClass$b([
4654
4666
  n2({ type: Array })
4655
4667
  ], MutationComparisonComponent.prototype, "lapisFilters", 2);
4656
- __decorateClass$a([
4668
+ __decorateClass$b([
4657
4669
  n2({ type: String })
4658
4670
  ], MutationComparisonComponent.prototype, "sequenceType", 2);
4659
- __decorateClass$a([
4671
+ __decorateClass$b([
4660
4672
  n2({ type: Array })
4661
4673
  ], MutationComparisonComponent.prototype, "views", 2);
4662
- __decorateClass$a([
4674
+ __decorateClass$b([
4663
4675
  n2({ type: String })
4664
4676
  ], MutationComparisonComponent.prototype, "width", 2);
4665
- __decorateClass$a([
4677
+ __decorateClass$b([
4666
4678
  n2({ type: String })
4667
4679
  ], MutationComparisonComponent.prototype, "height", 2);
4668
- __decorateClass$a([
4680
+ __decorateClass$b([
4669
4681
  n2({ type: Object })
4670
4682
  ], MutationComparisonComponent.prototype, "pageSize", 2);
4671
- MutationComparisonComponent = __decorateClass$a([
4683
+ MutationComparisonComponent = __decorateClass$b([
4672
4684
  t$2("gs-mutation-comparison")
4673
4685
  ], MutationComparisonComponent);
4674
4686
  function getInsertionsTableData(data) {
@@ -5003,7 +5015,7 @@ const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5003
5015
  };
5004
5016
  const tabs = views.map((view) => getTab(view));
5005
5017
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
5006
- Toolbar$3,
5018
+ Toolbar$4,
5007
5019
  {
5008
5020
  activeTab,
5009
5021
  displayedSegments,
@@ -5017,7 +5029,7 @@ const MutationsTabs = ({ mutationsData, sequenceType, views, pageSize }) => {
5017
5029
  );
5018
5030
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
5019
5031
  };
5020
- const Toolbar$3 = ({
5032
+ const Toolbar$4 = ({
5021
5033
  activeTab,
5022
5034
  displayedSegments,
5023
5035
  setDisplayedSegments,
@@ -5070,14 +5082,14 @@ const Toolbar$3 = ({
5070
5082
  /* @__PURE__ */ u$1(Info, { height: "100px", children: "Info for mutations" })
5071
5083
  ] });
5072
5084
  };
5073
- var __defProp$9 = Object.defineProperty;
5074
- var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
5075
- var __decorateClass$9 = (decorators, target, key, kind) => {
5076
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
5085
+ var __defProp$a = Object.defineProperty;
5086
+ var __getOwnPropDesc$a = Object.getOwnPropertyDescriptor;
5087
+ var __decorateClass$a = (decorators, target, key, kind) => {
5088
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$a(target, key) : target;
5077
5089
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
5078
5090
  if (decorator = decorators[i2])
5079
5091
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
5080
- if (kind && result) __defProp$9(target, key, result);
5092
+ if (kind && result) __defProp$a(target, key, result);
5081
5093
  return result;
5082
5094
  };
5083
5095
  let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -5104,25 +5116,25 @@ let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
5104
5116
  );
5105
5117
  }
5106
5118
  };
5107
- __decorateClass$9([
5119
+ __decorateClass$a([
5108
5120
  n2({ type: Object })
5109
5121
  ], MutationsComponent.prototype, "lapisFilter", 2);
5110
- __decorateClass$9([
5122
+ __decorateClass$a([
5111
5123
  n2({ type: String })
5112
5124
  ], MutationsComponent.prototype, "sequenceType", 2);
5113
- __decorateClass$9([
5125
+ __decorateClass$a([
5114
5126
  n2({ type: Array })
5115
5127
  ], MutationsComponent.prototype, "views", 2);
5116
- __decorateClass$9([
5128
+ __decorateClass$a([
5117
5129
  n2({ type: String })
5118
5130
  ], MutationsComponent.prototype, "width", 2);
5119
- __decorateClass$9([
5131
+ __decorateClass$a([
5120
5132
  n2({ type: String })
5121
5133
  ], MutationsComponent.prototype, "height", 2);
5122
- __decorateClass$9([
5134
+ __decorateClass$a([
5123
5135
  n2({ type: Object })
5124
5136
  ], MutationsComponent.prototype, "pageSize", 2);
5125
- MutationsComponent = __decorateClass$9([
5137
+ MutationsComponent = __decorateClass$a([
5126
5138
  t$2("gs-mutations")
5127
5139
  ], MutationsComponent);
5128
5140
  function getPrevalenceOverTimeTableData(data, granularity) {
@@ -5929,6 +5941,15 @@ class YearMonthDay {
5929
5941
  toString() {
5930
5942
  return this.text;
5931
5943
  }
5944
+ englishName() {
5945
+ return this.dayjs.format("dddd, MMMM D, YYYY");
5946
+ }
5947
+ get firstDay() {
5948
+ return this;
5949
+ }
5950
+ get lastDay() {
5951
+ return this;
5952
+ }
5932
5953
  get year() {
5933
5954
  return this.cache.getYear(`${this.yearNumber}`);
5934
5955
  }
@@ -5963,10 +5984,18 @@ class YearWeek {
5963
5984
  toString() {
5964
5985
  return this.text;
5965
5986
  }
5987
+ englishName() {
5988
+ return `Week ${this.isoWeekNumber}, ${this.isoYearNumber}`;
5989
+ }
5966
5990
  get firstDay() {
5967
5991
  const firstDay = dayjs().year(this.isoYearNumber).month(1).date(4).isoWeek(this.isoWeekNumber).startOf("isoWeek");
5968
5992
  return this.cache.getYearMonthDay(firstDay.format("YYYY-MM-DD"));
5969
5993
  }
5994
+ get lastDay() {
5995
+ const firstDay = dayjs().year(this.isoYearNumber).startOf("year").add((this.isoWeekNumber - 1) * 7, "day").startOf("week").add(1, "day");
5996
+ const lastDay = firstDay.add(6, "day");
5997
+ return this.cache.getYearMonthDay(lastDay.format("YYYY-MM-DD"));
5998
+ }
5970
5999
  get year() {
5971
6000
  return this.cache.getYear(`${this.isoYearNumber}`);
5972
6001
  }
@@ -5995,9 +6024,17 @@ class YearMonth {
5995
6024
  toString() {
5996
6025
  return this.text;
5997
6026
  }
6027
+ englishName() {
6028
+ return `${monthName(this.monthNumber)} ${this.yearNumber}`;
6029
+ }
5998
6030
  get firstDay() {
5999
6031
  return this.cache.getYearMonthDay(dayjs(`${this.yearNumber}-${this.monthNumber}-01`).format("YYYY-MM-DD"));
6000
6032
  }
6033
+ get lastDay() {
6034
+ return this.cache.getYearMonthDay(
6035
+ dayjs(`${this.yearNumber}-${this.monthNumber}-01`).endOf("month").format("YYYY-MM-DD")
6036
+ );
6037
+ }
6001
6038
  get year() {
6002
6039
  return this.cache.getYear(`${this.yearNumber}`);
6003
6040
  }
@@ -6025,12 +6062,21 @@ class Year {
6025
6062
  toString() {
6026
6063
  return this.text;
6027
6064
  }
6065
+ englishName() {
6066
+ return this.year.toString();
6067
+ }
6028
6068
  get firstMonth() {
6029
6069
  return this.cache.getYearMonth(`${this.year}-01`);
6030
6070
  }
6071
+ get lastMonth() {
6072
+ return this.cache.getYearMonth(`${this.year}-12`);
6073
+ }
6031
6074
  get firstDay() {
6032
6075
  return this.firstMonth.firstDay;
6033
6076
  }
6077
+ get lastDay() {
6078
+ return this.lastMonth.lastDay;
6079
+ }
6034
6080
  addYears(years) {
6035
6081
  const date = this.firstDay.dayjs.add(years, "year");
6036
6082
  const s2 = date.format("YYYY");
@@ -6044,6 +6090,9 @@ class Year {
6044
6090
  return new Year(year, cache);
6045
6091
  }
6046
6092
  }
6093
+ function monthName(month) {
6094
+ return dayjs().month(month - 1).format("MMMM");
6095
+ }
6047
6096
  function generateAllDaysInRange(start, end) {
6048
6097
  const days = [];
6049
6098
  const daysInBetween = end.minus(start);
@@ -6140,9 +6189,9 @@ function getMinMaxTemporal(values) {
6140
6189
  }
6141
6190
  }
6142
6191
  if (min === null || max === null) {
6143
- return null;
6192
+ return { min: null, max: null };
6144
6193
  }
6145
- return [min, max];
6194
+ return { min, max };
6146
6195
  }
6147
6196
  function addUnit(temporal, amount) {
6148
6197
  if (temporal instanceof YearMonthDay) {
@@ -6159,6 +6208,29 @@ function addUnit(temporal, amount) {
6159
6208
  }
6160
6209
  throw new Error(`Invalid argument: ${temporal}`);
6161
6210
  }
6211
+ function parseDateStringToTemporal(date, granularity) {
6212
+ const cache = TemporalCache.getInstance();
6213
+ const day = cache.getYearMonthDay(date);
6214
+ switch (granularity) {
6215
+ case "day":
6216
+ return day;
6217
+ case "week":
6218
+ return day.week;
6219
+ case "month":
6220
+ return day.month;
6221
+ case "year":
6222
+ return day.year;
6223
+ }
6224
+ }
6225
+ function dateRangeCompare(a2, b3) {
6226
+ if (a2.dateRange === null) {
6227
+ return 1;
6228
+ }
6229
+ if (b3.dateRange === null) {
6230
+ return -1;
6231
+ }
6232
+ return compareTemporal(a2.dateRange, b3.dateRange);
6233
+ }
6162
6234
  function getMinMaxNumber(values) {
6163
6235
  let min = null;
6164
6236
  let max = null;
@@ -6450,7 +6522,7 @@ class FillMissingOperator {
6450
6522
  if (minMax === null) {
6451
6523
  return childEvaluated;
6452
6524
  }
6453
- const [min, max] = minMax;
6525
+ const { min, max } = minMax;
6454
6526
  const requiredKeys = this.getAllRequiredKeysFn(min, max);
6455
6527
  const content = childEvaluated.content;
6456
6528
  for (const key of requiredKeys) {
@@ -6557,39 +6629,12 @@ function queryAggregatedDataOverTime(filter, granularity, smoothingWindow, lapis
6557
6629
  const sortData = new SortOperator(fillData, dateRangeCompare);
6558
6630
  return smoothingWindow >= 1 ? new SlidingOperator(sortData, smoothingWindow, averageSmoothing) : sortData;
6559
6631
  }
6560
- function mapDateToGranularityRange(d2, granularity) {
6561
- let dateRange = null;
6562
- if (d2.date !== null) {
6563
- const date = TemporalCache.getInstance().getYearMonthDay(d2.date);
6564
- switch (granularity) {
6565
- case "day":
6566
- dateRange = date;
6567
- break;
6568
- case "week":
6569
- dateRange = date.week;
6570
- break;
6571
- case "month":
6572
- dateRange = date.month;
6573
- break;
6574
- case "year":
6575
- dateRange = date.year;
6576
- break;
6577
- }
6578
- }
6632
+ function mapDateToGranularityRange(data, granularity) {
6579
6633
  return {
6580
- dateRange,
6581
- count: d2.count
6634
+ dateRange: data.date === null ? null : parseDateStringToTemporal(data.date, granularity),
6635
+ count: data.count
6582
6636
  };
6583
6637
  }
6584
- function dateRangeCompare(a2, b3) {
6585
- if (a2.dateRange === null) {
6586
- return 1;
6587
- }
6588
- if (b3.dateRange === null) {
6589
- return -1;
6590
- }
6591
- return compareTemporal(a2.dateRange, b3.dateRange);
6592
- }
6593
6638
  function averageSmoothing(slidingWindow) {
6594
6639
  const average = slidingWindow.reduce((acc, curr) => acc + curr.count, 0) / slidingWindow.length;
6595
6640
  const centerIndex = Math.floor(slidingWindow.length / 2);
@@ -6826,7 +6871,7 @@ const PrevalenceOverTimeTabs = ({
6826
6871
  };
6827
6872
  const tabs = views.map((view) => getTab(view));
6828
6873
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
6829
- Toolbar$2,
6874
+ Toolbar$3,
6830
6875
  {
6831
6876
  activeTab,
6832
6877
  yAxisScaleType,
@@ -6840,7 +6885,7 @@ const PrevalenceOverTimeTabs = ({
6840
6885
  );
6841
6886
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
6842
6887
  };
6843
- const Toolbar$2 = ({
6888
+ const Toolbar$3 = ({
6844
6889
  activeTab,
6845
6890
  yAxisScaleType,
6846
6891
  setYAxisScaleType,
@@ -6878,14 +6923,14 @@ const PrevalenceOverTimeInfo = () => {
6878
6923
  ] });
6879
6924
  };
6880
6925
  const maxInData = (data) => Math.max(...data.flatMap((variant) => variant.content.map((dataPoint) => dataPoint.prevalence)));
6881
- var __defProp$8 = Object.defineProperty;
6882
- var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
6883
- var __decorateClass$8 = (decorators, target, key, kind) => {
6884
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
6926
+ var __defProp$9 = Object.defineProperty;
6927
+ var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
6928
+ var __decorateClass$9 = (decorators, target, key, kind) => {
6929
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
6885
6930
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
6886
6931
  if (decorator = decorators[i2])
6887
6932
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
6888
- if (kind && result) __defProp$8(target, key, result);
6933
+ if (kind && result) __defProp$9(target, key, result);
6889
6934
  return result;
6890
6935
  };
6891
6936
  let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -6926,43 +6971,43 @@ let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
6926
6971
  );
6927
6972
  }
6928
6973
  };
6929
- __decorateClass$8([
6974
+ __decorateClass$9([
6930
6975
  n2({ type: Object })
6931
6976
  ], PrevalenceOverTimeComponent.prototype, "numeratorFilter", 2);
6932
- __decorateClass$8([
6977
+ __decorateClass$9([
6933
6978
  n2({ type: Object })
6934
6979
  ], PrevalenceOverTimeComponent.prototype, "denominatorFilter", 2);
6935
- __decorateClass$8([
6980
+ __decorateClass$9([
6936
6981
  n2({ type: String })
6937
6982
  ], PrevalenceOverTimeComponent.prototype, "granularity", 2);
6938
- __decorateClass$8([
6983
+ __decorateClass$9([
6939
6984
  n2({ type: Number })
6940
6985
  ], PrevalenceOverTimeComponent.prototype, "smoothingWindow", 2);
6941
- __decorateClass$8([
6986
+ __decorateClass$9([
6942
6987
  n2({ type: Array })
6943
6988
  ], PrevalenceOverTimeComponent.prototype, "views", 2);
6944
- __decorateClass$8([
6989
+ __decorateClass$9([
6945
6990
  n2({ type: Array })
6946
6991
  ], PrevalenceOverTimeComponent.prototype, "confidenceIntervalMethods", 2);
6947
- __decorateClass$8([
6992
+ __decorateClass$9([
6948
6993
  n2({ type: String })
6949
6994
  ], PrevalenceOverTimeComponent.prototype, "width", 2);
6950
- __decorateClass$8([
6995
+ __decorateClass$9([
6951
6996
  n2({ type: String })
6952
6997
  ], PrevalenceOverTimeComponent.prototype, "height", 2);
6953
- __decorateClass$8([
6998
+ __decorateClass$9([
6954
6999
  n2({ type: String })
6955
7000
  ], PrevalenceOverTimeComponent.prototype, "lapisDateField", 2);
6956
- __decorateClass$8([
7001
+ __decorateClass$9([
6957
7002
  n2({ type: Object })
6958
7003
  ], PrevalenceOverTimeComponent.prototype, "pageSize", 2);
6959
- __decorateClass$8([
7004
+ __decorateClass$9([
6960
7005
  n2({ type: String })
6961
7006
  ], PrevalenceOverTimeComponent.prototype, "yAxisMaxLinear", 2);
6962
- __decorateClass$8([
7007
+ __decorateClass$9([
6963
7008
  n2({ type: String })
6964
7009
  ], PrevalenceOverTimeComponent.prototype, "yAxisMaxLogarithmic", 2);
6965
- PrevalenceOverTimeComponent = __decorateClass$8([
7010
+ PrevalenceOverTimeComponent = __decorateClass$9([
6966
7011
  t$2("gs-prevalence-over-time")
6967
7012
  ], PrevalenceOverTimeComponent);
6968
7013
  Chart.register(...registerables, LogitScale);
@@ -7105,11 +7150,10 @@ async function queryRelativeGrowthAdvantage(numerator, denominator, generationTi
7105
7150
  mapNumerator.evaluate(lapis, signal),
7106
7151
  mapDenominator.evaluate(lapis, signal)
7107
7152
  ]);
7108
- const minMaxDate = getMinMaxTemporal(denominatorData.content.map((d2) => d2.date));
7109
- if (!minMaxDate) {
7153
+ const { min: minDate, max: maxDate } = getMinMaxTemporal(denominatorData.content.map((d2) => d2.date));
7154
+ if (!minDate && !maxDate) {
7110
7155
  return null;
7111
7156
  }
7112
- const [minDate, maxDate] = minMaxDate;
7113
7157
  const numeratorCounts = /* @__PURE__ */ new Map();
7114
7158
  numeratorData.content.forEach((d2) => {
7115
7159
  if (d2.date) {
@@ -7287,14 +7331,14 @@ const RelativeGrowthAdvantageInfo = ({ generationTime }) => {
7287
7331
  ] })
7288
7332
  ] });
7289
7333
  };
7290
- var __defProp$7 = Object.defineProperty;
7291
- var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
7292
- var __decorateClass$7 = (decorators, target, key, kind) => {
7293
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
7334
+ var __defProp$8 = Object.defineProperty;
7335
+ var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
7336
+ var __decorateClass$8 = (decorators, target, key, kind) => {
7337
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
7294
7338
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
7295
7339
  if (decorator = decorators[i2])
7296
7340
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
7297
- if (kind && result) __defProp$7(target, key, result);
7341
+ if (kind && result) __defProp$8(target, key, result);
7298
7342
  return result;
7299
7343
  };
7300
7344
  let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
@@ -7329,34 +7373,34 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
7329
7373
  );
7330
7374
  }
7331
7375
  };
7332
- __decorateClass$7([
7376
+ __decorateClass$8([
7333
7377
  n2({ type: Object })
7334
7378
  ], RelativeGrowthAdvantageComponent.prototype, "numeratorFilter", 2);
7335
- __decorateClass$7([
7379
+ __decorateClass$8([
7336
7380
  n2({ type: Object })
7337
7381
  ], RelativeGrowthAdvantageComponent.prototype, "denominatorFilter", 2);
7338
- __decorateClass$7([
7382
+ __decorateClass$8([
7339
7383
  n2({ type: Number })
7340
7384
  ], RelativeGrowthAdvantageComponent.prototype, "generationTime", 2);
7341
- __decorateClass$7([
7385
+ __decorateClass$8([
7342
7386
  n2({ type: Array })
7343
7387
  ], RelativeGrowthAdvantageComponent.prototype, "views", 2);
7344
- __decorateClass$7([
7388
+ __decorateClass$8([
7345
7389
  n2({ type: String })
7346
7390
  ], RelativeGrowthAdvantageComponent.prototype, "width", 2);
7347
- __decorateClass$7([
7391
+ __decorateClass$8([
7348
7392
  n2({ type: String })
7349
7393
  ], RelativeGrowthAdvantageComponent.prototype, "height", 2);
7350
- __decorateClass$7([
7394
+ __decorateClass$8([
7351
7395
  n2({ type: String })
7352
7396
  ], RelativeGrowthAdvantageComponent.prototype, "lapisDateField", 2);
7353
- __decorateClass$7([
7397
+ __decorateClass$8([
7354
7398
  n2({ type: String })
7355
7399
  ], RelativeGrowthAdvantageComponent.prototype, "yAxisMaxLinear", 2);
7356
- __decorateClass$7([
7400
+ __decorateClass$8([
7357
7401
  n2({ type: String })
7358
7402
  ], RelativeGrowthAdvantageComponent.prototype, "yAxisMaxLogarithmic", 2);
7359
- RelativeGrowthAdvantageComponent = __decorateClass$7([
7403
+ RelativeGrowthAdvantageComponent = __decorateClass$8([
7360
7404
  t$2("gs-relative-growth-advantage")
7361
7405
  ], RelativeGrowthAdvantageComponent);
7362
7406
  const compareAscending = (a2, b3) => {
@@ -7445,22 +7489,22 @@ const AggregatedDataTabs = ({ data, views, fields, pageSize }) => {
7445
7489
  }
7446
7490
  };
7447
7491
  const tabs = views.map((view) => getTab(view));
7448
- return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar: /* @__PURE__ */ u$1(Toolbar$1, { data }) });
7492
+ return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar: /* @__PURE__ */ u$1(Toolbar$2, { data }) });
7449
7493
  };
7450
- const Toolbar$1 = ({ data }) => {
7494
+ const Toolbar$2 = ({ data }) => {
7451
7495
  return /* @__PURE__ */ u$1("div", { class: "flex flex-row", children: [
7452
7496
  /* @__PURE__ */ u$1(CsvDownloadButton, { className: "mx-1 btn btn-xs", getData: () => data, filename: "aggregate.csv" }),
7453
7497
  /* @__PURE__ */ u$1(Info, { height: "100px", children: "Info for aggregate" })
7454
7498
  ] });
7455
7499
  };
7456
- var __defProp$6 = Object.defineProperty;
7457
- var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
7458
- var __decorateClass$6 = (decorators, target, key, kind) => {
7459
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
7500
+ var __defProp$7 = Object.defineProperty;
7501
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
7502
+ var __decorateClass$7 = (decorators, target, key, kind) => {
7503
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
7460
7504
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
7461
7505
  if (decorator = decorators[i2])
7462
7506
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
7463
- if (kind && result) __defProp$6(target, key, result);
7507
+ if (kind && result) __defProp$7(target, key, result);
7464
7508
  return result;
7465
7509
  };
7466
7510
  let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -7491,31 +7535,31 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
7491
7535
  );
7492
7536
  }
7493
7537
  };
7494
- __decorateClass$6([
7538
+ __decorateClass$7([
7495
7539
  n2({ type: Array })
7496
7540
  ], AggregateComponent.prototype, "fields", 2);
7497
- __decorateClass$6([
7541
+ __decorateClass$7([
7498
7542
  n2({ type: Array })
7499
7543
  ], AggregateComponent.prototype, "views", 2);
7500
- __decorateClass$6([
7544
+ __decorateClass$7([
7501
7545
  n2({ type: Object })
7502
7546
  ], AggregateComponent.prototype, "filter", 2);
7503
- __decorateClass$6([
7547
+ __decorateClass$7([
7504
7548
  n2({ type: String })
7505
7549
  ], AggregateComponent.prototype, "width", 2);
7506
- __decorateClass$6([
7550
+ __decorateClass$7([
7507
7551
  n2({ type: String })
7508
7552
  ], AggregateComponent.prototype, "height", 2);
7509
- __decorateClass$6([
7553
+ __decorateClass$7([
7510
7554
  n2({ type: String })
7511
7555
  ], AggregateComponent.prototype, "initialSortField", 2);
7512
- __decorateClass$6([
7556
+ __decorateClass$7([
7513
7557
  n2({ type: String })
7514
7558
  ], AggregateComponent.prototype, "initialSortDirection", 2);
7515
- __decorateClass$6([
7559
+ __decorateClass$7([
7516
7560
  n2({ type: Object })
7517
7561
  ], AggregateComponent.prototype, "pageSize", 2);
7518
- AggregateComponent = __decorateClass$6([
7562
+ AggregateComponent = __decorateClass$7([
7519
7563
  t$2("gs-aggregate")
7520
7564
  ], AggregateComponent);
7521
7565
  const getNumberOfSequencesOverTimeTableData = (data, dateRangeKey) => {
@@ -7531,7 +7575,7 @@ const getNumberOfSequencesOverTimeTableData = (data, dateRangeKey) => {
7531
7575
  if (minMax === null) {
7532
7576
  return [];
7533
7577
  }
7534
- const allDateRanges = generateAllInRange(...minMax);
7578
+ const allDateRanges = generateAllInRange(minMax.min, minMax.max);
7535
7579
  if (allDateRangesThatOccurInData.has(null)) {
7536
7580
  allDateRanges.unshift(null);
7537
7581
  }
@@ -7729,7 +7773,7 @@ const NumberSequencesOverTimeTabs = ({ views, data, granularity, pageSize }) =>
7729
7773
  {
7730
7774
  tabs: views.map((view) => getTab(view)),
7731
7775
  toolbar: (activeTab) => /* @__PURE__ */ u$1(
7732
- Toolbar,
7776
+ Toolbar$1,
7733
7777
  {
7734
7778
  activeTab,
7735
7779
  data,
@@ -7741,7 +7785,7 @@ const NumberSequencesOverTimeTabs = ({ views, data, granularity, pageSize }) =>
7741
7785
  }
7742
7786
  );
7743
7787
  };
7744
- const Toolbar = ({ activeTab, data, granularity, yAxisScaleType, setYAxisScaleType }) => {
7788
+ const Toolbar$1 = ({ activeTab, data, granularity, yAxisScaleType, setYAxisScaleType }) => {
7745
7789
  return /* @__PURE__ */ u$1(Fragment, { children: [
7746
7790
  activeTab !== "Table" && /* @__PURE__ */ u$1(
7747
7791
  ScalingSelector,
@@ -7766,14 +7810,14 @@ const NumberSequencesOverTimeInfo = () => /* @__PURE__ */ u$1(Info, { height: "1
7766
7810
  /* @__PURE__ */ u$1(InfoHeadline1, { children: "Number of sequences over time" }),
7767
7811
  /* @__PURE__ */ u$1(InfoParagraph, { children: /* @__PURE__ */ u$1("a", { href: "https://github.com/GenSpectrum/dashboard-components/issues/315", children: "TODO" }) })
7768
7812
  ] });
7769
- var __defProp$5 = Object.defineProperty;
7770
- var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
7771
- var __decorateClass$5 = (decorators, target, key, kind) => {
7772
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
7813
+ var __defProp$6 = Object.defineProperty;
7814
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
7815
+ var __decorateClass$6 = (decorators, target, key, kind) => {
7816
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
7773
7817
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
7774
7818
  if (decorator = decorators[i2])
7775
7819
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
7776
- if (kind && result) __defProp$5(target, key, result);
7820
+ if (kind && result) __defProp$6(target, key, result);
7777
7821
  return result;
7778
7822
  };
7779
7823
  let NumberSequencesOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -7804,33 +7848,485 @@ let NumberSequencesOverTimeComponent = class extends PreactLitAdapterWithGridJsS
7804
7848
  );
7805
7849
  }
7806
7850
  };
7807
- __decorateClass$5([
7851
+ __decorateClass$6([
7808
7852
  n2({ type: Object })
7809
7853
  ], NumberSequencesOverTimeComponent.prototype, "lapisFilter", 2);
7810
- __decorateClass$5([
7854
+ __decorateClass$6([
7811
7855
  n2({ type: String })
7812
7856
  ], NumberSequencesOverTimeComponent.prototype, "lapisDateField", 2);
7813
- __decorateClass$5([
7857
+ __decorateClass$6([
7814
7858
  n2({ type: Array })
7815
7859
  ], NumberSequencesOverTimeComponent.prototype, "views", 2);
7816
- __decorateClass$5([
7860
+ __decorateClass$6([
7817
7861
  n2({ type: String })
7818
7862
  ], NumberSequencesOverTimeComponent.prototype, "width", 2);
7819
- __decorateClass$5([
7863
+ __decorateClass$6([
7820
7864
  n2({ type: String })
7821
7865
  ], NumberSequencesOverTimeComponent.prototype, "height", 2);
7822
- __decorateClass$5([
7866
+ __decorateClass$6([
7823
7867
  n2({ type: String })
7824
7868
  ], NumberSequencesOverTimeComponent.prototype, "granularity", 2);
7825
- __decorateClass$5([
7869
+ __decorateClass$6([
7826
7870
  n2({ type: Number })
7827
7871
  ], NumberSequencesOverTimeComponent.prototype, "smoothingWindow", 2);
7828
- __decorateClass$5([
7872
+ __decorateClass$6([
7829
7873
  n2({ type: Object })
7830
7874
  ], NumberSequencesOverTimeComponent.prototype, "pageSize", 2);
7831
- NumberSequencesOverTimeComponent = __decorateClass$5([
7875
+ NumberSequencesOverTimeComponent = __decorateClass$6([
7832
7876
  t$2("gs-number-sequences-over-time")
7833
7877
  ], NumberSequencesOverTimeComponent);
7878
+ function getFilteredMutationOverTimeData(data, displayedSegments, displayedMutationTypes, proportionInterval) {
7879
+ const filteredData = data.copy();
7880
+ filterDisplayedSegments(displayedSegments, filteredData);
7881
+ filterMutationTypes(displayedMutationTypes, filteredData);
7882
+ filterProportion(filteredData, proportionInterval);
7883
+ return filteredData;
7884
+ }
7885
+ function filterDisplayedSegments(displayedSegments, data) {
7886
+ displayedSegments.forEach((segment) => {
7887
+ if (!segment.checked) {
7888
+ data.getFirstAxisKeys().forEach((mutation) => {
7889
+ if (mutation.segment === segment.segment) {
7890
+ data.deleteRow(mutation);
7891
+ }
7892
+ });
7893
+ }
7894
+ });
7895
+ }
7896
+ function filterMutationTypes(displayedMutationTypes, data) {
7897
+ displayedMutationTypes.forEach((mutationType) => {
7898
+ if (!mutationType.checked) {
7899
+ data.getFirstAxisKeys().forEach((mutation) => {
7900
+ if (mutationType.type === mutation.type) {
7901
+ data.deleteRow(mutation);
7902
+ }
7903
+ });
7904
+ }
7905
+ });
7906
+ }
7907
+ function filterProportion(data, proportionInterval) {
7908
+ data.getFirstAxisKeys().forEach((mutation) => {
7909
+ const row = data.getRow(mutation, { count: 0, proportion: 0 });
7910
+ if (!row.some(
7911
+ (value) => value.proportion >= proportionInterval.min && value.proportion <= proportionInterval.max
7912
+ )) {
7913
+ data.deleteRow(mutation);
7914
+ }
7915
+ });
7916
+ }
7917
+ const Tooltip = ({ children, content }) => {
7918
+ const referenceRef = A(null);
7919
+ const floatingRef = A(null);
7920
+ useFloatingUi(referenceRef, floatingRef, [offset(5), shift(), flip()]);
7921
+ return /* @__PURE__ */ u$1("div", { className: "relative", children: [
7922
+ /* @__PURE__ */ u$1("div", { className: "peer", ref: referenceRef, children }),
7923
+ /* @__PURE__ */ u$1("div", { ref: floatingRef, className: `${dropdownClass} hidden peer-hover:block`, children: content })
7924
+ ] });
7925
+ };
7926
+ const MAX_NUMBER_OF_GRID_ROWS = 100;
7927
+ const MutationsOverTimeGrid = ({ data }) => {
7928
+ const mutations = data.getFirstAxisKeys();
7929
+ if (mutations.length > MAX_NUMBER_OF_GRID_ROWS) {
7930
+ throw new UserFacingError(
7931
+ "Too many mutations",
7932
+ `The dataset contains ${mutations.length} mutations. Please adapt the filters to reduce the number to below ${MAX_NUMBER_OF_GRID_ROWS}.`
7933
+ );
7934
+ }
7935
+ const dates = data.getSecondAxisKeys().sort((a2, b3) => compareTemporal(a2, b3));
7936
+ return /* @__PURE__ */ u$1(
7937
+ "div",
7938
+ {
7939
+ style: {
7940
+ display: "grid",
7941
+ gridTemplateRows: `repeat(${mutations.length}, 24px)`,
7942
+ gridTemplateColumns: `8rem repeat(${dates.length}, minmax(1.5rem, 1fr))`
7943
+ },
7944
+ children: mutations.map((mutation, i2) => {
7945
+ return /* @__PURE__ */ u$1(Fragment, { children: [
7946
+ /* @__PURE__ */ u$1(
7947
+ "div",
7948
+ {
7949
+ style: { gridRowStart: i2 + 1, gridColumnStart: 1 },
7950
+ children: /* @__PURE__ */ u$1(MutationCell, { mutation })
7951
+ },
7952
+ `mutation-${mutation.toString()}`
7953
+ ),
7954
+ dates.map((date, j2) => {
7955
+ const value = data.get(mutation, date) ?? { proportion: 0, count: 0 };
7956
+ return /* @__PURE__ */ u$1(
7957
+ "div",
7958
+ {
7959
+ style: { gridRowStart: i2 + 1, gridColumnStart: j2 + 2 },
7960
+ children: /* @__PURE__ */ u$1(ProportionCell, { value, date, mutation })
7961
+ },
7962
+ `${mutation.toString()}-${date.toString()}`
7963
+ );
7964
+ })
7965
+ ] }, `fragment-${mutation.toString()}`);
7966
+ })
7967
+ }
7968
+ );
7969
+ };
7970
+ const ProportionCell = ({ value, mutation, date }) => {
7971
+ const tooltipContent = /* @__PURE__ */ u$1("div", { children: [
7972
+ /* @__PURE__ */ u$1("p", { children: [
7973
+ /* @__PURE__ */ u$1("span", { className: "font-bold", children: date.englishName() }),
7974
+ " (",
7975
+ timeIntervalDisplay(date),
7976
+ ")"
7977
+ ] }),
7978
+ /* @__PURE__ */ u$1("p", { children: mutation.code }),
7979
+ /* @__PURE__ */ u$1("p", { children: [
7980
+ "Proportion: ",
7981
+ formatProportion(value.proportion)
7982
+ ] }),
7983
+ /* @__PURE__ */ u$1("p", { children: [
7984
+ "Count: ",
7985
+ value.count
7986
+ ] })
7987
+ ] });
7988
+ return /* @__PURE__ */ u$1(Fragment, { children: /* @__PURE__ */ u$1("div", { className: "py-1", children: /* @__PURE__ */ u$1(Tooltip, { content: tooltipContent, children: /* @__PURE__ */ u$1(
7989
+ "div",
7990
+ {
7991
+ style: {
7992
+ backgroundColor: backgroundColor(value.proportion),
7993
+ color: textColor(value.proportion)
7994
+ },
7995
+ className: "text-center hover:font-bold text-xs",
7996
+ children: formatProportion(value.proportion, 0)
7997
+ }
7998
+ ) }) }) });
7999
+ };
8000
+ const timeIntervalDisplay = (date) => {
8001
+ if (date instanceof YearMonthDay) {
8002
+ return date.toString();
8003
+ }
8004
+ return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
8005
+ };
8006
+ const backgroundColor = (proportion) => {
8007
+ const minAlpha = 0;
8008
+ const maxAlpha = 1;
8009
+ const alpha = minAlpha + (maxAlpha - minAlpha) * proportion;
8010
+ return singleGraphColorRGBByName("indigo", alpha);
8011
+ };
8012
+ const textColor = (proportion) => {
8013
+ return proportion > 0.5 ? "white" : "black";
8014
+ };
8015
+ const MutationCell = ({ mutation }) => {
8016
+ return /* @__PURE__ */ u$1("div", { className: "text-center", children: mutation.toString() });
8017
+ };
8018
+ class Map2d {
8019
+ constructor(serializeFirstAxis = (key) => typeof key === "string" ? key : hash(key), serializeSecondAxis = (key) => typeof key === "string" ? key : hash(key)) {
8020
+ this.serializeFirstAxis = serializeFirstAxis;
8021
+ this.serializeSecondAxis = serializeSecondAxis;
8022
+ this.data = /* @__PURE__ */ new Map();
8023
+ this.keysFirstAxis = /* @__PURE__ */ new Map();
8024
+ this.keysSecondAxis = /* @__PURE__ */ new Map();
8025
+ }
8026
+ get(keyFirstAxis, keySecondAxis) {
8027
+ var _a;
8028
+ const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
8029
+ const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
8030
+ return (_a = this.data.get(serializedKeyFirstAxis)) == null ? void 0 : _a.get(serializedKeySecondAxis);
8031
+ }
8032
+ getRow(key, fillEmptyWith) {
8033
+ const serializedKeyFirstAxis = this.serializeFirstAxis(key);
8034
+ const row = this.data.get(serializedKeyFirstAxis);
8035
+ if (row === void 0) {
8036
+ return [];
8037
+ }
8038
+ return Array.from(this.keysSecondAxis.keys()).map((key2) => row.get(key2) ?? fillEmptyWith);
8039
+ }
8040
+ set(keyFirstAxis, keySecondAxis, value) {
8041
+ const serializedKeyFirstAxis = this.serializeFirstAxis(keyFirstAxis);
8042
+ const serializedKeySecondAxis = this.serializeSecondAxis(keySecondAxis);
8043
+ if (!this.data.has(serializedKeyFirstAxis)) {
8044
+ this.data.set(serializedKeyFirstAxis, /* @__PURE__ */ new Map());
8045
+ }
8046
+ this.data.get(serializedKeyFirstAxis).set(serializedKeySecondAxis, value);
8047
+ this.keysFirstAxis.set(serializedKeyFirstAxis, keyFirstAxis);
8048
+ this.keysSecondAxis.set(serializedKeySecondAxis, keySecondAxis);
8049
+ }
8050
+ deleteRow(key) {
8051
+ const serializedKeyFirstAxis = this.serializeFirstAxis(key);
8052
+ this.data.delete(serializedKeyFirstAxis);
8053
+ this.keysFirstAxis.delete(serializedKeyFirstAxis);
8054
+ }
8055
+ getFirstAxisKeys() {
8056
+ return Array.from(this.keysFirstAxis.values());
8057
+ }
8058
+ getSecondAxisKeys() {
8059
+ return Array.from(this.keysSecondAxis.values());
8060
+ }
8061
+ getAsArray(fillEmptyWith) {
8062
+ return this.getFirstAxisKeys().map((firstAxisKey) => {
8063
+ return this.getSecondAxisKeys().map((secondAxisKey) => {
8064
+ return this.get(firstAxisKey, secondAxisKey) ?? fillEmptyWith;
8065
+ });
8066
+ });
8067
+ }
8068
+ copy() {
8069
+ const copy = new Map2d(this.serializeFirstAxis, this.serializeSecondAxis);
8070
+ this.data.forEach((value, key) => {
8071
+ const keyFirstAxis = this.keysFirstAxis.get(key);
8072
+ value.forEach((value2, key2) => {
8073
+ const keySecondAxis = this.keysSecondAxis.get(key2);
8074
+ copy.set(keyFirstAxis, keySecondAxis, value2);
8075
+ });
8076
+ });
8077
+ return copy;
8078
+ }
8079
+ }
8080
+ const MAX_NUMBER_OF_GRID_COLUMNS = 200;
8081
+ async function queryMutationsOverTimeData(lapisFilter, sequenceType, lapis, lapisDateField, granularity, signal) {
8082
+ const allDates = await getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal);
8083
+ if (allDates.length > MAX_NUMBER_OF_GRID_COLUMNS) {
8084
+ throw new UserFacingError(
8085
+ "Too many dates",
8086
+ `The dataset would contain ${allDates.length} date intervals. Please reduce the number to below ${MAX_NUMBER_OF_GRID_COLUMNS} to display the data. You can achieve this by either narrowing the date range in the provided LAPIS filter or by selecting a larger granularity.`
8087
+ );
8088
+ }
8089
+ const subQueries = allDates.map(async (date) => {
8090
+ const dateFrom = date.firstDay.toString();
8091
+ const dateTo = date.lastDay.toString();
8092
+ const filter = {
8093
+ ...lapisFilter,
8094
+ [`${lapisDateField}From`]: dateFrom,
8095
+ [`${lapisDateField}To`]: dateTo
8096
+ };
8097
+ const data2 = await fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType).evaluate(lapis, signal);
8098
+ return {
8099
+ date,
8100
+ mutations: data2.content
8101
+ };
8102
+ });
8103
+ const data = await Promise.all(subQueries);
8104
+ return groupByMutation(data);
8105
+ }
8106
+ async function getDatesInDataset(lapisFilter, lapis, granularity, lapisDateField, signal) {
8107
+ const { content: availableDates } = await queryAvailableDates(
8108
+ lapisFilter,
8109
+ lapis,
8110
+ granularity,
8111
+ lapisDateField,
8112
+ signal
8113
+ );
8114
+ const { dateFrom, dateTo } = getDateRangeFromFilter(lapisFilter, lapisDateField, granularity);
8115
+ const { min, max } = getMinMaxTemporal(availableDates);
8116
+ return generateAllInRange(dateFrom ?? min, dateTo ?? max);
8117
+ }
8118
+ function getDateRangeFromFilter(lapisFilter, lapisDateField, granularity) {
8119
+ const valueFromFilter = lapisFilter[lapisDateField];
8120
+ if (valueFromFilter) {
8121
+ return {
8122
+ dateFrom: parseDateStringToTemporal(valueFromFilter, granularity),
8123
+ dateTo: parseDateStringToTemporal(valueFromFilter, granularity)
8124
+ };
8125
+ }
8126
+ const minFromFilter = lapisFilter[`${lapisDateField}From`];
8127
+ const maxFromFilter = lapisFilter[`${lapisDateField}To`];
8128
+ return {
8129
+ dateFrom: minFromFilter ? parseDateStringToTemporal(minFromFilter, granularity) : null,
8130
+ dateTo: maxFromFilter ? parseDateStringToTemporal(maxFromFilter, granularity) : null
8131
+ };
8132
+ }
8133
+ function queryAvailableDates(lapisFilter, lapis, granularity, lapisDateField, signal) {
8134
+ return fetchAndPrepareDates(lapisFilter, granularity, lapisDateField).evaluate(lapis, signal);
8135
+ }
8136
+ function fetchAndPrepareDates(filter, granularity, lapisDateField) {
8137
+ const fetchData = new FetchAggregatedOperator(filter, [lapisDateField]);
8138
+ const dataWithFixedDateKey = new RenameFieldOperator(fetchData, lapisDateField, "date");
8139
+ const mapData = new MapOperator(dataWithFixedDateKey, (data) => mapDateToGranularityRange(data, granularity));
8140
+ const groupByData = new GroupByAndSumOperator(mapData, "dateRange", "count");
8141
+ const sortData = new SortOperator(groupByData, dateRangeCompare);
8142
+ return new MapOperator(sortData, (data) => data.dateRange);
8143
+ }
8144
+ function fetchAndPrepareSubstitutionsOrDeletions(filter, sequenceType) {
8145
+ return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType, 1e-3);
8146
+ }
8147
+ function groupByMutation(data) {
8148
+ const dataArray = new Map2d(
8149
+ (mutation) => mutation.code,
8150
+ (date) => date.toString()
8151
+ );
8152
+ data.forEach((mutationData) => {
8153
+ mutationData.mutations.forEach((mutationEntry) => {
8154
+ dataArray.set(mutationEntry.mutation, mutationData.date, {
8155
+ count: mutationEntry.count,
8156
+ proportion: mutationEntry.proportion
8157
+ });
8158
+ });
8159
+ });
8160
+ addZeroValuesForDatesWithNoMutationData(dataArray, data);
8161
+ return dataArray;
8162
+ }
8163
+ function addZeroValuesForDatesWithNoMutationData(dataArray, data) {
8164
+ if (dataArray.getFirstAxisKeys().length !== 0) {
8165
+ const someMutation = dataArray.getFirstAxisKeys()[0];
8166
+ data.forEach((mutationData) => {
8167
+ if (mutationData.mutations.length === 0) {
8168
+ dataArray.set(someMutation, mutationData.date, { count: 0, proportion: 0 });
8169
+ }
8170
+ });
8171
+ }
8172
+ }
8173
+ const MutationsOverTime = ({ width, height, ...innerProps }) => {
8174
+ const size2 = { height, width };
8175
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size: size2, children: /* @__PURE__ */ u$1(ResizeContainer, { size: size2, children: /* @__PURE__ */ u$1(MutationsOverTimeInner, { ...innerProps }) }) });
8176
+ };
8177
+ const MutationsOverTimeInner = ({
8178
+ lapisFilter,
8179
+ sequenceType,
8180
+ views,
8181
+ granularity,
8182
+ lapisDateField
8183
+ }) => {
8184
+ const lapis = x(LapisUrlContext);
8185
+ const { data, error, isLoading } = useQuery(async () => {
8186
+ return queryMutationsOverTimeData(lapisFilter, sequenceType, lapis, lapisDateField, granularity);
8187
+ }, [lapisFilter, sequenceType, lapis, granularity, lapisDateField]);
8188
+ if (isLoading) {
8189
+ return /* @__PURE__ */ u$1(LoadingDisplay, {});
8190
+ }
8191
+ if (error !== null) {
8192
+ return /* @__PURE__ */ u$1(ErrorDisplay, { error });
8193
+ }
8194
+ if (data === null) {
8195
+ return /* @__PURE__ */ u$1(NoDataDisplay, {});
8196
+ }
8197
+ return /* @__PURE__ */ u$1(MutationsOverTimeTabs, { mutationOverTimeData: data, sequenceType, views });
8198
+ };
8199
+ const MutationsOverTimeTabs = ({
8200
+ mutationOverTimeData,
8201
+ sequenceType,
8202
+ views
8203
+ }) => {
8204
+ const [proportionInterval, setProportionInterval] = h({ min: 0.05, max: 0.9 });
8205
+ const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
8206
+ const [displayedMutationTypes, setDisplayedMutationTypes] = h([
8207
+ { label: "Substitutions", checked: true, type: "substitution" },
8208
+ { label: "Deletions", checked: true, type: "deletion" }
8209
+ ]);
8210
+ const filteredData = T(
8211
+ () => getFilteredMutationOverTimeData(
8212
+ mutationOverTimeData,
8213
+ displayedSegments,
8214
+ displayedMutationTypes,
8215
+ proportionInterval
8216
+ ),
8217
+ [mutationOverTimeData, displayedSegments, displayedMutationTypes, proportionInterval]
8218
+ );
8219
+ const getTab = (view) => {
8220
+ switch (view) {
8221
+ case "grid":
8222
+ return {
8223
+ title: "Grid",
8224
+ content: /* @__PURE__ */ u$1(MutationsOverTimeGrid, { data: filteredData })
8225
+ };
8226
+ }
8227
+ };
8228
+ const tabs = views.map((view) => getTab(view));
8229
+ const toolbar = () => /* @__PURE__ */ u$1(
8230
+ Toolbar,
8231
+ {
8232
+ displayedSegments,
8233
+ setDisplayedSegments,
8234
+ displayedMutationTypes,
8235
+ setDisplayedMutationTypes,
8236
+ proportionInterval,
8237
+ setProportionInterval
8238
+ }
8239
+ );
8240
+ return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
8241
+ };
8242
+ const Toolbar = ({
8243
+ displayedSegments,
8244
+ setDisplayedSegments,
8245
+ displayedMutationTypes,
8246
+ setDisplayedMutationTypes,
8247
+ proportionInterval,
8248
+ setProportionInterval
8249
+ }) => {
8250
+ return /* @__PURE__ */ u$1(Fragment, { children: [
8251
+ /* @__PURE__ */ u$1(SegmentSelector, { displayedSegments, setDisplayedSegments }),
8252
+ /* @__PURE__ */ u$1(
8253
+ MutationTypeSelector,
8254
+ {
8255
+ setDisplayedMutationTypes,
8256
+ displayedMutationTypes
8257
+ }
8258
+ ),
8259
+ /* @__PURE__ */ u$1(Fragment, { children: /* @__PURE__ */ u$1(
8260
+ ProportionSelectorDropdown,
8261
+ {
8262
+ proportionInterval,
8263
+ setMinProportion: (min) => setProportionInterval((prev) => ({ ...prev, min })),
8264
+ setMaxProportion: (max) => setProportionInterval((prev) => ({ ...prev, max }))
8265
+ }
8266
+ ) }),
8267
+ /* @__PURE__ */ u$1(Info, { height: "100px", children: "Info for mutations over time" })
8268
+ ] });
8269
+ };
8270
+ var __defProp$5 = Object.defineProperty;
8271
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
8272
+ var __decorateClass$5 = (decorators, target, key, kind) => {
8273
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
8274
+ for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
8275
+ if (decorator = decorators[i2])
8276
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8277
+ if (kind && result) __defProp$5(target, key, result);
8278
+ return result;
8279
+ };
8280
+ let MutationsOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles {
8281
+ constructor() {
8282
+ super(...arguments);
8283
+ this.lapisFilter = {};
8284
+ this.sequenceType = "nucleotide";
8285
+ this.views = ["grid"];
8286
+ this.width = "100%";
8287
+ this.height = "700px";
8288
+ this.granularity = "week";
8289
+ this.lapisDateField = "date";
8290
+ }
8291
+ render() {
8292
+ return /* @__PURE__ */ u$1(
8293
+ MutationsOverTime,
8294
+ {
8295
+ lapisFilter: this.lapisFilter,
8296
+ sequenceType: this.sequenceType,
8297
+ views: this.views,
8298
+ width: this.width,
8299
+ height: this.height,
8300
+ granularity: this.granularity,
8301
+ lapisDateField: this.lapisDateField
8302
+ }
8303
+ );
8304
+ }
8305
+ };
8306
+ __decorateClass$5([
8307
+ n2({ type: Object })
8308
+ ], MutationsOverTimeComponent.prototype, "lapisFilter", 2);
8309
+ __decorateClass$5([
8310
+ n2({ type: String })
8311
+ ], MutationsOverTimeComponent.prototype, "sequenceType", 2);
8312
+ __decorateClass$5([
8313
+ n2({ type: Array })
8314
+ ], MutationsOverTimeComponent.prototype, "views", 2);
8315
+ __decorateClass$5([
8316
+ n2({ type: String })
8317
+ ], MutationsOverTimeComponent.prototype, "width", 2);
8318
+ __decorateClass$5([
8319
+ n2({ type: String })
8320
+ ], MutationsOverTimeComponent.prototype, "height", 2);
8321
+ __decorateClass$5([
8322
+ n2({ type: String })
8323
+ ], MutationsOverTimeComponent.prototype, "granularity", 2);
8324
+ __decorateClass$5([
8325
+ n2({ type: String })
8326
+ ], MutationsOverTimeComponent.prototype, "lapisDateField", 2);
8327
+ MutationsOverTimeComponent = __decorateClass$5([
8328
+ t$2("gs-mutations-over-time")
8329
+ ], MutationsOverTimeComponent);
7834
8330
  const PRESET_VALUE_CUSTOM = "custom";
7835
8331
  const PRESET_VALUE_ALL_TIMES = "allTimes";
7836
8332
  const PRESET_VALUE_LAST_2_WEEKS = "last2Weeks";
@@ -8867,68 +9363,68 @@ const SelectedMutationDisplay = ({ selectedFilters, setSelectedFilters, fireChan
8867
9363
  ] });
8868
9364
  };
8869
9365
  const SelectedAminoAcidInsertion = ({ insertion, onDelete }) => {
8870
- const backgroundColor = singleGraphColorRGBByName("teal", 0.3);
8871
- const textColor = singleGraphColorRGBByName("teal", 1);
9366
+ const backgroundColor2 = singleGraphColorRGBByName("teal", 0.3);
9367
+ const textColor2 = singleGraphColorRGBByName("teal", 1);
8872
9368
  return /* @__PURE__ */ u$1(
8873
9369
  SelectedFilter,
8874
9370
  {
8875
9371
  mutation: insertion,
8876
9372
  onDelete,
8877
- backgroundColor,
8878
- textColor
9373
+ backgroundColor: backgroundColor2,
9374
+ textColor: textColor2
8879
9375
  }
8880
9376
  );
8881
9377
  };
8882
9378
  const SelectedAminoAcidMutation = ({ mutation, onDelete }) => {
8883
- const backgroundColor = singleGraphColorRGBByName("rose", 0.3);
8884
- const textColor = singleGraphColorRGBByName("rose", 1);
9379
+ const backgroundColor2 = singleGraphColorRGBByName("rose", 0.3);
9380
+ const textColor2 = singleGraphColorRGBByName("rose", 1);
8885
9381
  return /* @__PURE__ */ u$1(
8886
9382
  SelectedFilter,
8887
9383
  {
8888
9384
  mutation,
8889
9385
  onDelete,
8890
- backgroundColor,
8891
- textColor
9386
+ backgroundColor: backgroundColor2,
9387
+ textColor: textColor2
8892
9388
  }
8893
9389
  );
8894
9390
  };
8895
9391
  const SelectedNucleotideMutation = ({ mutation, onDelete }) => {
8896
- const backgroundColor = singleGraphColorRGBByName("indigo", 0.3);
8897
- const textColor = singleGraphColorRGBByName("indigo", 1);
9392
+ const backgroundColor2 = singleGraphColorRGBByName("indigo", 0.3);
9393
+ const textColor2 = singleGraphColorRGBByName("indigo", 1);
8898
9394
  return /* @__PURE__ */ u$1(
8899
9395
  SelectedFilter,
8900
9396
  {
8901
9397
  mutation,
8902
9398
  onDelete,
8903
- backgroundColor,
8904
- textColor
9399
+ backgroundColor: backgroundColor2,
9400
+ textColor: textColor2
8905
9401
  }
8906
9402
  );
8907
9403
  };
8908
9404
  const SelectedNucleotideInsertion = ({ insertion, onDelete }) => {
8909
- const backgroundColor = singleGraphColorRGBByName("green", 0.3);
8910
- const textColor = singleGraphColorRGBByName("green", 1);
9405
+ const backgroundColor2 = singleGraphColorRGBByName("green", 0.3);
9406
+ const textColor2 = singleGraphColorRGBByName("green", 1);
8911
9407
  return /* @__PURE__ */ u$1(
8912
9408
  SelectedFilter,
8913
9409
  {
8914
9410
  mutation: insertion,
8915
9411
  onDelete,
8916
- backgroundColor,
8917
- textColor
9412
+ backgroundColor: backgroundColor2,
9413
+ textColor: textColor2
8918
9414
  }
8919
9415
  );
8920
9416
  };
8921
9417
  const SelectedFilter = ({
8922
9418
  mutation,
8923
9419
  onDelete,
8924
- backgroundColor,
8925
- textColor
9420
+ backgroundColor: backgroundColor2,
9421
+ textColor: textColor2
8926
9422
  }) => {
8927
9423
  return /* @__PURE__ */ u$1(
8928
9424
  "span",
8929
9425
  {
8930
9426
  class: "inline-block mx-1 px-2 py-1 font-medium text-xs rounded-full",
8931
- style: { backgroundColor, color: textColor },
9427
+ style: { backgroundColor: backgroundColor2, color: textColor2 },
8932
9428
  children: [
8933
9429
  mutation.toString(),
8934
9430
  /* @__PURE__ */ u$1("button", { type: "button", onClick: () => onDelete(mutation), children: /* @__PURE__ */ u$1(DeleteIcon, {}) })
@@ -9091,6 +9587,7 @@ export {
9091
9587
  MutationComparisonComponent,
9092
9588
  MutationFilterComponent,
9093
9589
  MutationsComponent,
9590
+ MutationsOverTimeComponent,
9094
9591
  NumberSequencesOverTimeComponent,
9095
9592
  PrevalenceOverTimeComponent,
9096
9593
  RelativeGrowthAdvantageComponent,