@genspectrum/dashboard-components 0.1.2 → 0.1.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 (81) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +453 -67
  3. package/dist/dashboard-components.js +778 -488
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +277 -50
  6. package/dist/style.css +132 -139
  7. package/package.json +9 -5
  8. package/src/lapisApi/lapisApi.ts +1 -1
  9. package/src/preact/aggregatedData/__mockData__/aggregated.json +585 -0
  10. package/src/preact/aggregatedData/aggregate-table.tsx +32 -0
  11. package/src/preact/aggregatedData/aggregate.stories.tsx +53 -0
  12. package/src/preact/aggregatedData/aggregate.tsx +102 -0
  13. package/src/preact/components/ReferenceGenomesAwaiter.tsx +25 -0
  14. package/src/preact/components/csv-download-button.tsx +8 -2
  15. package/src/preact/components/headline.tsx +16 -4
  16. package/src/preact/components/min-max-range-slider.tsx +4 -4
  17. package/src/preact/components/percent-intput.tsx +2 -3
  18. package/src/preact/components/resize-container.tsx +23 -0
  19. package/src/preact/components/table.tsx +1 -0
  20. package/src/preact/components/tabs.stories.tsx +2 -2
  21. package/src/preact/components/tabs.tsx +47 -24
  22. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +36 -4
  23. package/src/preact/dateRangeSelector/date-range-selector.tsx +57 -43
  24. package/src/preact/locationFilter/location-filter.tsx +2 -2
  25. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +5 -5
  26. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +45 -10
  27. package/src/preact/mutationComparison/mutation-comparison-table.tsx +20 -22
  28. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +6 -3
  29. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +8 -1
  30. package/src/preact/mutationComparison/mutation-comparison.tsx +13 -4
  31. package/src/preact/mutationFilter/mutation-filter.stories.tsx +70 -31
  32. package/src/preact/mutationFilter/mutation-filter.tsx +62 -14
  33. package/src/preact/mutations/getInsertionsTableData.spec.ts +6 -4
  34. package/src/preact/mutations/getInsertionsTableData.ts +1 -1
  35. package/src/preact/mutations/getMutationsTableData.spec.ts +9 -19
  36. package/src/preact/mutations/getMutationsTableData.ts +1 -1
  37. package/src/preact/mutations/mutations-insertions-table.tsx +3 -1
  38. package/src/preact/mutations/mutations-table.tsx +3 -1
  39. package/src/preact/mutations/mutations.stories.tsx +8 -1
  40. package/src/preact/mutations/mutations.tsx +16 -5
  41. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +1 -0
  42. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -0
  43. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +1 -0
  44. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -0
  45. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +17 -9
  46. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +8 -5
  47. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +12 -0
  48. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +13 -8
  49. package/src/preact/shared/sort/sortInsertions.spec.ts +11 -10
  50. package/src/preact/shared/sort/sortInsertions.ts +10 -17
  51. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +19 -10
  52. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +45 -12
  53. package/src/preact/textInput/text-input.stories.tsx +22 -1
  54. package/src/preact/textInput/text-input.tsx +3 -1
  55. package/src/query/queryAggregateData.spec.ts +32 -0
  56. package/src/query/queryAggregateData.ts +25 -0
  57. package/src/utils/typeAssertions.spec.ts +31 -0
  58. package/src/utils/typeAssertions.ts +16 -0
  59. package/src/web-components/PreactLitAdapter.tsx +0 -1
  60. package/src/web-components/app.stories.ts +129 -0
  61. package/src/web-components/app.ts +27 -6
  62. package/src/web-components/display/aggregate-component.stories.ts +73 -0
  63. package/src/web-components/display/aggregate-component.tsx +58 -0
  64. package/src/web-components/display/index.ts +1 -0
  65. package/src/web-components/display/mutation-comparison-component.stories.ts +29 -11
  66. package/src/web-components/display/mutation-comparison-component.tsx +72 -4
  67. package/src/web-components/display/mutations-component.stories.ts +14 -13
  68. package/src/web-components/display/mutations-component.tsx +14 -1
  69. package/src/web-components/display/prevalence-over-time-component.stories.ts +20 -18
  70. package/src/web-components/display/prevalence-over-time-component.tsx +12 -0
  71. package/src/web-components/display/relative-growth-advantage-component.stories.ts +11 -10
  72. package/src/web-components/display/relative-growth-advantage-component.tsx +12 -0
  73. package/src/web-components/input/date-range-selector-component.stories.ts +35 -8
  74. package/src/web-components/input/date-range-selector-component.tsx +18 -5
  75. package/src/web-components/input/location-filter-component.stories.ts +17 -8
  76. package/src/web-components/input/location-filter-component.tsx +2 -6
  77. package/src/web-components/input/mutation-filter-component.stories.ts +20 -9
  78. package/src/web-components/input/mutation-filter-component.tsx +10 -2
  79. package/src/web-components/input/text-input-component.stories.ts +13 -4
  80. package/src/web-components/input/text-input-component.tsx +11 -2
  81. package/src/web-components/input/location-filter.mdx +0 -25
@@ -2,10 +2,11 @@ import { createContext, provide, consume } from "@lit/context";
2
2
  import { Task } from "@lit/task";
3
3
  import { LitElement, html, unsafeCSS } from "lit";
4
4
  import z$1 from "zod";
5
- import { options, Fragment, createContext as createContext$1, render } from "preact";
5
+ import { options, createContext as createContext$1, Fragment, render } from "preact";
6
6
  import { Grid } from "gridjs";
7
7
  import { Chart, registerables, Scale } from "chart.js";
8
8
  import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn";
9
+ import { ReactiveElement } from "@lit/reactive-element";
9
10
  import { BarWithErrorBarsController, BarWithErrorBar } from "chartjs-chart-error-bars";
10
11
  import flatpickr from "flatpickr";
11
12
  /**
@@ -448,7 +449,7 @@ async function fetchReferenceGenome(lapisUrl, signal) {
448
449
  }
449
450
  const handleErrors = async (response) => {
450
451
  if (!response.ok) {
451
- if (response.status % 500 === 0) {
452
+ if (response.status >= 400 && response.status < 500) {
452
453
  throw new Error(`${response.statusText}: ${JSON.stringify(await response.json())}`);
453
454
  }
454
455
  throw new Error(`${response.statusText}: ${response.status}`);
@@ -462,15 +463,15 @@ const substitutionsOrDeletionsEndpoint = (lapisUrl, sequenceType) => {
462
463
  return sequenceType === "amino acid" ? `${lapisUrl}/sample/aminoAcidMutations` : `${lapisUrl}/sample/nucleotideMutations`;
463
464
  };
464
465
  const referenceGenomeEndpoint = (lapisUrl) => `${lapisUrl}/sample/referenceGenome`;
465
- var __defProp$9 = Object.defineProperty;
466
- var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
467
- var __decorateClass$9 = (decorators, target, key, kind) => {
468
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
466
+ var __defProp$a = Object.defineProperty;
467
+ var __getOwnPropDesc$a = Object.getOwnPropertyDescriptor;
468
+ var __decorateClass$a = (decorators, target, key, kind) => {
469
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$a(target, key) : target;
469
470
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
470
471
  if (decorator = decorators[i2])
471
472
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
472
473
  if (kind && result)
473
- __defProp$9(target, key, result);
474
+ __defProp$a(target, key, result);
474
475
  return result;
475
476
  };
476
477
  let App = class extends LitElement {
@@ -490,35 +491,33 @@ let App = class extends LitElement {
490
491
  }
491
492
  render() {
492
493
  return this.updateReferenceGenome.render({
493
- complete: () => {
494
- return html` <slot></slot>`;
495
- },
494
+ complete: () => html` <slot></slot>`,
496
495
  error: () => html`<p>Error</p>`,
497
496
  // TODO(#143): Add more advanced error handling
498
- pending: () => {
499
- return html`<p>Loading...</p>`;
500
- }
497
+ pending: () => html` <p>Loading reference genomes...</p> `
501
498
  });
502
499
  }
503
500
  createRenderRoot() {
504
501
  return this;
505
502
  }
506
503
  };
507
- __decorateClass$9([
504
+ __decorateClass$a([
508
505
  provide({ context: lapisContext }),
509
506
  n2()
510
507
  ], App.prototype, "lapis", 2);
511
- __decorateClass$9([
508
+ __decorateClass$a([
512
509
  provide({ context: referenceGenomeContext })
513
510
  ], App.prototype, "referenceGenome", 2);
514
- App = __decorateClass$9([
511
+ App = __decorateClass$a([
515
512
  t$2("gs-app")
516
513
  ], App);
517
514
  var f$1 = 0;
518
515
  function u$1(e2, t2, n3, o2, i2, u2) {
519
- var a2, c2, p2 = {};
520
- for (c2 in t2)
521
- "ref" == c2 ? a2 = t2[c2] : p2[c2] = t2[c2];
516
+ t2 || (t2 = {});
517
+ var a2, c2, p2 = t2;
518
+ if ("ref" in p2)
519
+ for (c2 in p2 = {}, t2)
520
+ "ref" == c2 ? a2 = t2[c2] : p2[c2] = t2[c2];
522
521
  var l2 = { type: e2, props: p2, key: n3, ref: a2, __k: null, __: null, __b: 0, __e: null, __d: void 0, __c: null, constructor: void 0, __v: --f$1, __i: -1, __u: 0, __source: i2, __self: u2 };
523
522
  if ("function" == typeof e2 && (a2 = e2.defaultProps))
524
523
  for (c2 in a2)
@@ -662,18 +661,29 @@ function getMutationComparisonTableData(data, proportionInterval) {
662
661
  const mutationsToProportions = /* @__PURE__ */ new Map();
663
662
  for (const mutationData of data.content) {
664
663
  for (const mutationEntry of mutationData.data) {
665
- const mutation = mutationEntry.mutation.toString();
666
- const proportions = mutationsToProportions.get(mutation) || {};
667
- proportions[mutationData.displayName] = mutationEntry.proportion;
668
- mutationsToProportions.set(mutation, proportions);
664
+ const mutationKey = mutationEntry.mutation.toString();
665
+ const existingRow = mutationsToProportions.get(mutationKey);
666
+ if (!existingRow) {
667
+ mutationsToProportions.set(
668
+ mutationKey,
669
+ initializeMutationRow(mutationEntry.mutation, mutationData.displayName, mutationEntry.proportion)
670
+ );
671
+ } else {
672
+ existingRow.proportions = updateProportions(
673
+ existingRow.proportions,
674
+ mutationData.displayName,
675
+ mutationEntry.proportion
676
+ );
677
+ mutationsToProportions.set(mutationKey, existingRow);
678
+ }
669
679
  }
670
680
  }
671
- return [...mutationsToProportions.entries()].map(([mutation, proportions]) => {
681
+ return [...mutationsToProportions.values()].map((row) => {
672
682
  return {
673
- mutation,
683
+ mutation: row.mutation,
674
684
  ...data.content.map((mutationData) => {
675
685
  return {
676
- [`${mutationData.displayName} prevalence`]: proportions[mutationData.displayName] || 0
686
+ [`${mutationData.displayName} prevalence`]: row.proportions[mutationData.displayName] || 0
677
687
  };
678
688
  }).reduce((acc, val) => ({ ...acc, ...val }), {})
679
689
  };
@@ -683,6 +693,17 @@ function getMutationComparisonTableData(data, proportionInterval) {
683
693
  )
684
694
  );
685
695
  }
696
+ function initializeMutationRow(mutation, displayName, proportion) {
697
+ return {
698
+ mutation,
699
+ proportions: {
700
+ [displayName]: proportion
701
+ }
702
+ };
703
+ }
704
+ function updateProportions(proportions, displayName, proportion) {
705
+ return { ...proportions, [displayName]: proportion };
706
+ }
686
707
  const tableStyle = {
687
708
  table: {
688
709
  fontSize: "12px"
@@ -717,49 +738,183 @@ const Table = ({ data, columns, pagination }) => {
717
738
  });
718
739
  return /* @__PURE__ */ u$1("div", { ref: wrapper3 });
719
740
  };
720
- const substitutionAndDeletionRegex = /(?:([A-Za-z0-9]+):)?([A-Za-z])(\d+)([A-Za-z]|-|\*)/;
721
- const sortSubstitutionsAndDeletions = (a2, b2) => {
722
- const aMatch = a2.match(substitutionAndDeletionRegex);
723
- const bMatch = b2.match(substitutionAndDeletionRegex);
724
- if (aMatch && bMatch) {
725
- if (aMatch[1] !== bMatch[1]) {
726
- return aMatch[1].localeCompare(bMatch[1]);
741
+ const substitutionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(?<substitutionValue>[A-Za-z.])?$/;
742
+ class Substitution {
743
+ constructor(segment, valueAtReference, substitutionValue, position) {
744
+ this.segment = segment;
745
+ this.valueAtReference = valueAtReference;
746
+ this.substitutionValue = substitutionValue;
747
+ this.position = position;
748
+ const segmentString = this.segment ? `${this.segment}:` : "";
749
+ const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
750
+ const substitutionValueString = this.substitutionValue ? `${this.substitutionValue}` : "";
751
+ this.code = `${segmentString}${valueAtReferenceString}${this.position}${substitutionValueString}`;
752
+ }
753
+ equals(other) {
754
+ if (!(other instanceof Substitution)) {
755
+ return false;
756
+ }
757
+ return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.substitutionValue === other.substitutionValue && this.position === other.position;
758
+ }
759
+ toString() {
760
+ return this.code;
761
+ }
762
+ static parse(mutationStr) {
763
+ const match = mutationStr.match(substitutionRegex);
764
+ if (match === null || match.groups === void 0) {
765
+ return null;
766
+ }
767
+ return new Substitution(
768
+ match.groups.segment,
769
+ match.groups.valueAtReference,
770
+ match.groups.substitutionValue,
771
+ parseInt(match.groups.position, 10)
772
+ );
773
+ }
774
+ }
775
+ const deletionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(-)$/;
776
+ class Deletion {
777
+ constructor(segment, valueAtReference, position) {
778
+ this.segment = segment;
779
+ this.valueAtReference = valueAtReference;
780
+ this.position = position;
781
+ const segmentString = this.segment ? `${this.segment}:` : "";
782
+ const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
783
+ this.code = `${segmentString}${valueAtReferenceString}${this.position}-`;
784
+ }
785
+ equals(other) {
786
+ if (!(other instanceof Deletion)) {
787
+ return false;
788
+ }
789
+ return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.position === other.position;
790
+ }
791
+ toString() {
792
+ return this.code;
793
+ }
794
+ static parse(mutationStr) {
795
+ const match = mutationStr.match(deletionRegex);
796
+ if (match === null || match.groups === void 0) {
797
+ return null;
727
798
  }
728
- if (aMatch[3] !== bMatch[3]) {
729
- return parseInt(aMatch[3], 10) - parseInt(bMatch[3], 10);
799
+ return new Deletion(match.groups.segment, match.groups.valueAtReference, parseInt(match.groups.position, 10));
800
+ }
801
+ }
802
+ const insertionRegexp = /^ins_((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<position>\d+):(?<insertedSymbols>(([A-Za-z?]|(\.\*))+))$/i;
803
+ class Insertion {
804
+ constructor(segment, position, insertedSymbols) {
805
+ this.segment = segment;
806
+ this.position = position;
807
+ this.insertedSymbols = insertedSymbols;
808
+ this.code = `ins_${this.segment ? `${this.segment}:` : ""}${this.position}:${this.insertedSymbols}`;
809
+ }
810
+ equals(other) {
811
+ if (!(other instanceof Insertion)) {
812
+ return false;
813
+ }
814
+ return this.segment === other.segment && this.insertedSymbols === other.insertedSymbols && this.position === other.position;
815
+ }
816
+ toString() {
817
+ return this.code;
818
+ }
819
+ static parse(mutationStr) {
820
+ const match = mutationStr.match(insertionRegexp);
821
+ if (match === null || match.groups === void 0) {
822
+ return null;
823
+ }
824
+ return new Insertion(match.groups.segment, parseInt(match.groups.position, 10), match.groups.insertedSymbols);
825
+ }
826
+ }
827
+ const bases = {
828
+ nucleotide: ["A", "C", "G", "T", "-"],
829
+ "amino acid": [
830
+ "I",
831
+ "L",
832
+ "V",
833
+ "F",
834
+ "M",
835
+ "C",
836
+ "A",
837
+ "G",
838
+ "P",
839
+ "T",
840
+ "S",
841
+ "Y",
842
+ "W",
843
+ "Q",
844
+ "N",
845
+ "H",
846
+ "E",
847
+ "D",
848
+ "K",
849
+ "R",
850
+ "-"
851
+ ]
852
+ };
853
+ const sortSubstitutionsAndDeletions = (a2, b2) => {
854
+ if (a2.segment !== b2.segment) {
855
+ compareSegments(a2.segment, b2.segment);
856
+ }
857
+ if (a2.position !== b2.position) {
858
+ return comparePositions(a2.position, b2.position);
859
+ }
860
+ const aIsDeletion = a2 instanceof Deletion;
861
+ const bIsDeletion = b2 instanceof Deletion;
862
+ if (aIsDeletion !== bIsDeletion) {
863
+ return aIsDeletion ? 1 : -1;
864
+ }
865
+ if (!aIsDeletion && !bIsDeletion) {
866
+ if (a2.substitutionValue !== b2.substitutionValue) {
867
+ return compareSubstitutionValues(a2.substitutionValue, b2.substitutionValue);
730
868
  }
731
- return aMatch[4].localeCompare(bMatch[4]);
732
869
  }
733
- throw new Error(`Invalid substitution or deletion: ${a2} or ${b2}`);
870
+ return 0;
871
+ };
872
+ const compareSegments = (a2, b2) => {
873
+ if (a2 === void 0) {
874
+ return -1;
875
+ }
876
+ if (b2 === void 0) {
877
+ return 1;
878
+ }
879
+ return a2.localeCompare(b2);
880
+ };
881
+ const comparePositions = (a2, b2) => {
882
+ return a2 - b2;
883
+ };
884
+ const compareSubstitutionValues = (a2, b2) => {
885
+ if (a2 === void 0) {
886
+ return -1;
887
+ }
888
+ if (b2 === void 0) {
889
+ return 1;
890
+ }
891
+ return a2.localeCompare(b2);
734
892
  };
735
893
  const formatProportion = (proportion) => {
736
894
  return `${(proportion * 100).toFixed(2)}%`;
737
895
  };
738
896
  const MutationComparisonTable = ({ data, proportionInterval }) => {
739
- const getHeaders = () => {
740
- return [
741
- {
742
- name: "Mutation",
743
- sort: {
744
- compare: (a2, b2) => {
745
- return sortSubstitutionsAndDeletions(a2, b2);
746
- }
747
- }
897
+ const headers = [
898
+ {
899
+ name: "Mutation",
900
+ sort: {
901
+ compare: sortSubstitutionsAndDeletions
748
902
  },
749
- {
750
- name: "Prevalence",
751
- columns: data.content.map((mutationData) => {
752
- return {
753
- name: mutationData.displayName,
754
- sort: true,
755
- formatter: (cell) => formatProportion(cell)
756
- };
757
- })
758
- }
759
- ];
760
- };
903
+ formatter: (cell) => cell.toString()
904
+ },
905
+ {
906
+ name: "Prevalence",
907
+ columns: data.content.map((mutationData) => {
908
+ return {
909
+ name: mutationData.displayName,
910
+ sort: true,
911
+ formatter: (cell) => formatProportion(cell)
912
+ };
913
+ })
914
+ }
915
+ ];
761
916
  const tableData = getMutationComparisonTableData(data, proportionInterval).map((row) => Object.values(row));
762
- return /* @__PURE__ */ u$1(Table, { data: tableData, columns: getHeaders(), pagination: true });
917
+ return /* @__PURE__ */ u$1(Table, { data: tableData, columns: headers, pagination: true });
763
918
  };
764
919
  const GsChart = ({ configuration }) => {
765
920
  const canvasRef = F(null);
@@ -821,6 +976,7 @@ const MutationComparisonVenn = ({
821
976
  type: "venn",
822
977
  data: sets,
823
978
  options: {
979
+ maintainAspectRatio: false,
824
980
  scales: {
825
981
  x: {
826
982
  ticks: {
@@ -868,123 +1024,11 @@ const MutationComparisonVenn = ({
868
1024
  if (data.content.length > 5) {
869
1025
  return /* @__PURE__ */ u$1("div", { children: "Too many variants to display. Maximum are five. " });
870
1026
  }
871
- return /* @__PURE__ */ u$1(Fragment, { children: [
872
- /* @__PURE__ */ u$1(GsChart, { configuration: config }),
1027
+ return /* @__PURE__ */ u$1("div", { className: "h-full flex flex-col", children: [
1028
+ /* @__PURE__ */ u$1("div", { className: "flex-1", children: /* @__PURE__ */ u$1(GsChart, { configuration: config }) }),
873
1029
  /* @__PURE__ */ u$1("div", { class: "flex flex-wrap break-words m-2", ref: divRef })
874
1030
  ] });
875
1031
  };
876
- const substitutionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(?<substitutionValue>[A-Za-z.])?$/;
877
- class Substitution {
878
- constructor(segment, valueAtReference, substitutionValue, position) {
879
- this.segment = segment;
880
- this.valueAtReference = valueAtReference;
881
- this.substitutionValue = substitutionValue;
882
- this.position = position;
883
- const segmentString = this.segment ? `${this.segment}:` : "";
884
- const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
885
- const substitutionValueString = this.substitutionValue ? `${this.substitutionValue}` : "";
886
- this.code = `${segmentString}${valueAtReferenceString}${this.position}${substitutionValueString}`;
887
- }
888
- equals(other) {
889
- if (!(other instanceof Substitution)) {
890
- return false;
891
- }
892
- return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.substitutionValue === other.substitutionValue && this.position === other.position;
893
- }
894
- toString() {
895
- return this.code;
896
- }
897
- static parse(mutationStr) {
898
- const match = mutationStr.match(substitutionRegex);
899
- if (match === null || match.groups === void 0) {
900
- return null;
901
- }
902
- return new Substitution(
903
- match.groups.segment,
904
- match.groups.valueAtReference,
905
- match.groups.substitutionValue,
906
- parseInt(match.groups.position, 10)
907
- );
908
- }
909
- }
910
- const deletionRegex = /^((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<valueAtReference>[A-Za-z])?(?<position>\d+)(-)$/;
911
- class Deletion {
912
- constructor(segment, valueAtReference, position) {
913
- this.segment = segment;
914
- this.valueAtReference = valueAtReference;
915
- this.position = position;
916
- const segmentString = this.segment ? `${this.segment}:` : "";
917
- const valueAtReferenceString = this.valueAtReference ? `${this.valueAtReference}` : "";
918
- this.code = `${segmentString}${valueAtReferenceString}${this.position}-`;
919
- }
920
- equals(other) {
921
- if (!(other instanceof Deletion)) {
922
- return false;
923
- }
924
- return this.segment === other.segment && this.valueAtReference === other.valueAtReference && this.position === other.position;
925
- }
926
- toString() {
927
- return this.code;
928
- }
929
- static parse(mutationStr) {
930
- const match = mutationStr.match(deletionRegex);
931
- if (match === null || match.groups === void 0) {
932
- return null;
933
- }
934
- return new Deletion(match.groups.segment, match.groups.valueAtReference, parseInt(match.groups.position, 10));
935
- }
936
- }
937
- const insertionRegexp = /^ins_((?<segment>[A-Za-z0-9_-]+)(?=:):)?(?<position>\d+):(?<insertedSymbols>(([A-Za-z?]|(\.\*))+))$/i;
938
- class Insertion {
939
- constructor(segment, position, insertedSymbols) {
940
- this.segment = segment;
941
- this.position = position;
942
- this.insertedSymbols = insertedSymbols;
943
- this.code = `ins_${this.segment ? `${this.segment}:` : ""}${this.position}:${this.insertedSymbols}`;
944
- }
945
- equals(other) {
946
- if (!(other instanceof Insertion)) {
947
- return false;
948
- }
949
- return this.segment === other.segment && this.insertedSymbols === other.insertedSymbols && this.position === other.position;
950
- }
951
- toString() {
952
- return this.code;
953
- }
954
- static parse(mutationStr) {
955
- const match = mutationStr.match(insertionRegexp);
956
- if (match === null || match.groups === void 0) {
957
- return null;
958
- }
959
- return new Insertion(match.groups.segment, parseInt(match.groups.position, 10), match.groups.insertedSymbols);
960
- }
961
- }
962
- const bases = {
963
- nucleotide: ["A", "C", "G", "T", "-"],
964
- "amino acid": [
965
- "I",
966
- "L",
967
- "V",
968
- "F",
969
- "M",
970
- "C",
971
- "A",
972
- "G",
973
- "P",
974
- "T",
975
- "S",
976
- "Y",
977
- "W",
978
- "Q",
979
- "N",
980
- "H",
981
- "E",
982
- "D",
983
- "K",
984
- "R",
985
- "-"
986
- ]
987
- };
988
1032
  class FetchSubstitutionsOrDeletionsOperator {
989
1033
  constructor(filter, sequenceType, minProportion) {
990
1034
  this.filter = filter;
@@ -1181,9 +1225,17 @@ const ErrorDisplay = ({ error }) => {
1181
1225
  ] });
1182
1226
  };
1183
1227
  const Headline = ({ heading, children }) => {
1184
- return /* @__PURE__ */ u$1(Fragment, { children: [
1185
- /* @__PURE__ */ u$1("h1", { children: heading }),
1186
- children
1228
+ const ref = F(null);
1229
+ const [h1Height, setH1Height] = p("2rem");
1230
+ _(() => {
1231
+ if (ref.current) {
1232
+ const h1Height2 = ref.current.getBoundingClientRect().height;
1233
+ setH1Height(`${h1Height2}px`);
1234
+ }
1235
+ }, []);
1236
+ return /* @__PURE__ */ u$1("div", { className: "h-full w-full", children: [
1237
+ /* @__PURE__ */ u$1("h1", { ref, children: heading }),
1238
+ /* @__PURE__ */ u$1("div", { style: { height: `calc(100% - ${h1Height})` }, children })
1187
1239
  ] });
1188
1240
  };
1189
1241
  const Info = ({ content, className }) => {
@@ -1379,30 +1431,51 @@ const ProportionSelectorDropdown = ({
1379
1431
  ) }) })
1380
1432
  ] });
1381
1433
  };
1434
+ const ResizeContainer = ({ children, size, defaultSize }) => {
1435
+ return /* @__PURE__ */ u$1("div", { style: extendByDefault(size, defaultSize), children });
1436
+ };
1437
+ const extendByDefault = (size, defaultSize) => {
1438
+ if (size === void 0) {
1439
+ return defaultSize;
1440
+ }
1441
+ return { ...defaultSize, ...size };
1442
+ };
1382
1443
  const Tabs = ({ tabs, toolbar }) => {
1383
1444
  const [activeTab, setActiveTab] = p(tabs[0].title);
1384
- const tabNames = tabs.map((tab) => tab.title).join(", ");
1385
- const tabElements = tabs.map((tab) => {
1386
- return /* @__PURE__ */ u$1(Fragment, { children: [
1387
- /* @__PURE__ */ u$1(
1388
- "input",
1389
- {
1390
- type: "radio",
1391
- name: tabNames,
1392
- role: "tab",
1393
- className: "tab",
1394
- "aria-label": tab.title,
1395
- checked: activeTab === tab.title,
1396
- onChange: () => setActiveTab(tab.title)
1397
- }
1398
- ),
1399
- /* @__PURE__ */ u$1("div", { role: "tabpanel", className: "tab-content bg-base-100 border-base-300 rounded-box p-1", children: tab.content })
1400
- ] }, tab.title);
1401
- });
1445
+ const [heightOfTabs, setHeightOfTabs] = p("3rem");
1446
+ const tabRef = F(null);
1447
+ _(() => {
1448
+ if (tabRef.current) {
1449
+ const heightOfTabs2 = tabRef.current.getBoundingClientRect().height;
1450
+ setHeightOfTabs(`${heightOfTabs2}px`);
1451
+ }
1452
+ }, []);
1453
+ const tabElements = /* @__PURE__ */ u$1("div", { className: "flex flex-row", children: tabs.map((tab) => {
1454
+ return /* @__PURE__ */ u$1(Fragment, { children: /* @__PURE__ */ u$1(
1455
+ "button",
1456
+ {
1457
+ className: `px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 ${activeTab === tab.title ? "border-b-2 border-gray-400" : "text-gray-600 hover:bg-gray-100 hover:text-gray-700"}`,
1458
+ onClick: () => {
1459
+ setActiveTab(tab.title);
1460
+ },
1461
+ children: tab.title
1462
+ }
1463
+ ) }, tab.title);
1464
+ }) });
1402
1465
  const toolbarElement = typeof toolbar === "function" ? toolbar(activeTab) : toolbar;
1403
- return /* @__PURE__ */ u$1("div", { role: "tablist", className: "tabs tabs-lifted", children: [
1404
- tabElements,
1405
- toolbar && /* @__PURE__ */ u$1("div", { className: "m-1 col-[9999]", children: toolbarElement })
1466
+ return /* @__PURE__ */ u$1("div", { className: "h-full w-full", children: [
1467
+ /* @__PURE__ */ u$1("div", { ref: tabRef, className: "flex flex-row justify-between", children: [
1468
+ tabElements,
1469
+ toolbar && /* @__PURE__ */ u$1("div", { className: "py-2", children: toolbarElement })
1470
+ ] }),
1471
+ /* @__PURE__ */ u$1(
1472
+ "div",
1473
+ {
1474
+ className: `p-2 border-2 border-gray-100 rounded-b-md rounded-tr-md ${activeTab === tabs[0].title ? "" : "rounded-tl-md"}`,
1475
+ style: { height: `calc(100% - ${heightOfTabs})` },
1476
+ children: tabs.map((tab) => /* @__PURE__ */ u$1("div", { className: "h-full overflow-auto", hidden: activeTab !== tab.title, children: tab.content }, tab.title))
1477
+ }
1478
+ )
1406
1479
  ] });
1407
1480
  };
1408
1481
  function useQuery(fetchDataCallback, dependencies = []) {
@@ -1426,7 +1499,12 @@ function useQuery(fetchDataCallback, dependencies = []) {
1426
1499
  }, [JSON.stringify(dependencies)]);
1427
1500
  return { data, error, isLoading };
1428
1501
  }
1429
- const MutationComparison = ({ variants, sequenceType, views }) => {
1502
+ const MutationComparison = ({
1503
+ variants,
1504
+ sequenceType,
1505
+ views,
1506
+ size
1507
+ }) => {
1430
1508
  const lapis = P(LapisUrlContext);
1431
1509
  const { data, error, isLoading } = useQuery(async () => {
1432
1510
  return queryMutationData(variants, sequenceType, lapis);
@@ -1441,7 +1519,7 @@ const MutationComparison = ({ variants, sequenceType, views }) => {
1441
1519
  if (data === null) {
1442
1520
  return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(NoDataDisplay, {}) });
1443
1521
  }
1444
- return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationComparisonTabs, { data: data.mutationData, sequenceType, views }) });
1522
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize: { height: "700px", width: "100%" }, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationComparisonTabs, { data: data.mutationData, sequenceType, views }) }) });
1445
1523
  };
1446
1524
  const MutationComparisonTabs = ({ data, views, sequenceType }) => {
1447
1525
  const [proportionInterval, setProportionInterval] = p({ min: 0.5, max: 1 });
@@ -1486,7 +1564,7 @@ const MutationComparisonTabs = ({ data, views, sequenceType }) => {
1486
1564
  {
1487
1565
  tabs,
1488
1566
  toolbar: /* @__PURE__ */ u$1(
1489
- Toolbar$2,
1567
+ Toolbar$3,
1490
1568
  {
1491
1569
  displayedSegments,
1492
1570
  setDisplayedSegments,
@@ -1500,7 +1578,7 @@ const MutationComparisonTabs = ({ data, views, sequenceType }) => {
1500
1578
  }
1501
1579
  );
1502
1580
  };
1503
- const Toolbar$2 = ({
1581
+ const Toolbar$3 = ({
1504
1582
  displayedSegments,
1505
1583
  setDisplayedSegments,
1506
1584
  displayedMutationTypes,
@@ -2032,108 +2110,6 @@ html {
2032
2110
  --bc: 27.8078% 0.029596 256.847952;
2033
2111
  }
2034
2112
 
2035
- @media (prefers-color-scheme: dark) {
2036
-
2037
- :root {
2038
- color-scheme: dark;
2039
- --in: 72.06% 0.191 231.6;
2040
- --su: 64.8% 0.150 160;
2041
- --wa: 84.71% 0.199 83.87;
2042
- --er: 71.76% 0.221 22.18;
2043
- --pc: 13.138% 0.0392 275.75;
2044
- --sc: 14.96% 0.052 342.55;
2045
- --ac: 14.902% 0.0334 183.61;
2046
- --inc: 0% 0 0;
2047
- --suc: 0% 0 0;
2048
- --wac: 0% 0 0;
2049
- --erc: 0% 0 0;
2050
- --rounded-box: 1rem;
2051
- --rounded-btn: 0.5rem;
2052
- --rounded-badge: 1.9rem;
2053
- --animation-btn: 0.25s;
2054
- --animation-input: .2s;
2055
- --btn-focus-scale: 0.95;
2056
- --border-btn: 1px;
2057
- --tab-border: 1px;
2058
- --tab-radius: 0.5rem;
2059
- --p: 65.69% 0.196 275.75;
2060
- --s: 74.8% 0.26 342.55;
2061
- --a: 74.51% 0.167 183.61;
2062
- --n: 31.3815% 0.021108 254.139175;
2063
- --nc: 74.6477% 0.0216 264.435964;
2064
- --b1: 25.3267% 0.015896 252.417568;
2065
- --b2: 23.2607% 0.013807 253.100675;
2066
- --b3: 21.1484% 0.01165 254.087939;
2067
- --bc: 74.6477% 0.0216 264.435964;
2068
- }
2069
- }
2070
-
2071
- [data-theme=light] {
2072
- color-scheme: light;
2073
- --in: 72.06% 0.191 231.6;
2074
- --su: 64.8% 0.150 160;
2075
- --wa: 84.71% 0.199 83.87;
2076
- --er: 71.76% 0.221 22.18;
2077
- --pc: 89.824% 0.06192 275.75;
2078
- --ac: 15.352% 0.0368 183.61;
2079
- --inc: 0% 0 0;
2080
- --suc: 0% 0 0;
2081
- --wac: 0% 0 0;
2082
- --erc: 0% 0 0;
2083
- --rounded-box: 1rem;
2084
- --rounded-btn: 0.5rem;
2085
- --rounded-badge: 1.9rem;
2086
- --animation-btn: 0.25s;
2087
- --animation-input: .2s;
2088
- --btn-focus-scale: 0.95;
2089
- --border-btn: 1px;
2090
- --tab-border: 1px;
2091
- --tab-radius: 0.5rem;
2092
- --p: 49.12% 0.3096 275.75;
2093
- --s: 69.71% 0.329 342.55;
2094
- --sc: 98.71% 0.0106 342.55;
2095
- --a: 76.76% 0.184 183.61;
2096
- --n: 32.1785% 0.02476 255.701624;
2097
- --nc: 89.4994% 0.011585 252.096176;
2098
- --b1: 100% 0 0;
2099
- --b2: 96.1151% 0 0;
2100
- --b3: 92.4169% 0.00108 197.137559;
2101
- --bc: 27.8078% 0.029596 256.847952;
2102
- }
2103
-
2104
- [data-theme=dark] {
2105
- color-scheme: dark;
2106
- --in: 72.06% 0.191 231.6;
2107
- --su: 64.8% 0.150 160;
2108
- --wa: 84.71% 0.199 83.87;
2109
- --er: 71.76% 0.221 22.18;
2110
- --pc: 13.138% 0.0392 275.75;
2111
- --sc: 14.96% 0.052 342.55;
2112
- --ac: 14.902% 0.0334 183.61;
2113
- --inc: 0% 0 0;
2114
- --suc: 0% 0 0;
2115
- --wac: 0% 0 0;
2116
- --erc: 0% 0 0;
2117
- --rounded-box: 1rem;
2118
- --rounded-btn: 0.5rem;
2119
- --rounded-badge: 1.9rem;
2120
- --animation-btn: 0.25s;
2121
- --animation-input: .2s;
2122
- --btn-focus-scale: 0.95;
2123
- --border-btn: 1px;
2124
- --tab-border: 1px;
2125
- --tab-radius: 0.5rem;
2126
- --p: 65.69% 0.196 275.75;
2127
- --s: 74.8% 0.26 342.55;
2128
- --a: 74.51% 0.167 183.61;
2129
- --n: 31.3815% 0.021108 254.139175;
2130
- --nc: 74.6477% 0.0216 264.435964;
2131
- --b1: 25.3267% 0.015896 252.417568;
2132
- --b2: 23.2607% 0.013807 253.100675;
2133
- --b3: 21.1484% 0.01165 254.087939;
2134
- --bc: 74.6477% 0.0216 264.435964;
2135
- }
2136
-
2137
2113
  *, ::before, ::after {
2138
2114
  --tw-border-spacing-x: 0;
2139
2115
  --tw-border-spacing-y: 0;
@@ -2241,6 +2217,39 @@ html {
2241
2217
  --tw-contain-paint: ;
2242
2218
  --tw-contain-style: ;
2243
2219
  }
2220
+ .container {
2221
+ width: 100%;
2222
+ }
2223
+ @media (min-width: 640px) {
2224
+
2225
+ .container {
2226
+ max-width: 640px;
2227
+ }
2228
+ }
2229
+ @media (min-width: 768px) {
2230
+
2231
+ .container {
2232
+ max-width: 768px;
2233
+ }
2234
+ }
2235
+ @media (min-width: 1024px) {
2236
+
2237
+ .container {
2238
+ max-width: 1024px;
2239
+ }
2240
+ }
2241
+ @media (min-width: 1280px) {
2242
+
2243
+ .container {
2244
+ max-width: 1280px;
2245
+ }
2246
+ }
2247
+ @media (min-width: 1536px) {
2248
+
2249
+ .container {
2250
+ max-width: 1536px;
2251
+ }
2252
+ }
2244
2253
  .avatar.placeholder > div {
2245
2254
  display: flex;
2246
2255
  align-items: center;
@@ -2832,19 +2841,6 @@ html {
2832
2841
  cursor: default;
2833
2842
  grid-column-start: span 9999;
2834
2843
  }
2835
- .tab-content {
2836
- grid-column-start: 1;
2837
- grid-column-end: span 9999;
2838
- grid-row-start: 2;
2839
- margin-top: calc(var(--tab-border) * -1);
2840
- display: none;
2841
- border-color: transparent;
2842
- border-width: var(--tab-border, 0);
2843
- }
2844
- :checked + .tab-content:nth-child(2),
2845
- .tab-active + .tab-content:nth-child(2) {
2846
- border-start-start-radius: 0px;
2847
- }
2848
2844
  input.tab:checked + .tab-content,
2849
2845
  .tab-active + .tab-content {
2850
2846
  display: block;
@@ -2992,6 +2988,14 @@ input.tab:checked + .tab-content,
2992
2988
  outline-offset: 2px;
2993
2989
  outline-color: var(--fallback-bc,oklch(var(--bc)/1));
2994
2990
  }
2991
+ .checkbox:disabled {
2992
+ border-width: 0px;
2993
+ cursor: not-allowed;
2994
+ border-color: transparent;
2995
+ --tw-bg-opacity: 1;
2996
+ background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
2997
+ opacity: 0.2;
2998
+ }
2995
2999
  .checkbox:checked,
2996
3000
  .checkbox[aria-checked="true"] {
2997
3001
  background-repeat: no-repeat;
@@ -3018,13 +3022,6 @@ input.tab:checked + .tab-content,
3018
3022
  linear-gradient(-90deg, transparent 80%, var(--chkbg) 80%),
3019
3023
  linear-gradient(0deg, var(--chkbg) 43%, var(--chkfg) 43%, var(--chkfg) 57%, var(--chkbg) 57%);
3020
3024
  }
3021
- .checkbox:disabled {
3022
- cursor: not-allowed;
3023
- border-color: transparent;
3024
- --tw-bg-opacity: 1;
3025
- background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
3026
- opacity: 0.2;
3027
- }
3028
3025
  @keyframes checkmark {
3029
3026
 
3030
3027
  0% {
@@ -3080,7 +3077,8 @@ input.tab:checked + .tab-content,
3080
3077
  border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)));
3081
3078
  outline-color: var(--fallback-er,oklch(var(--er)/1));
3082
3079
  }
3083
- .input-disabled,
3080
+ .input:has(> input[disabled]),
3081
+ .input-disabled,
3084
3082
  .input:disabled,
3085
3083
  .input[disabled] {
3086
3084
  cursor: not-allowed;
@@ -3090,16 +3088,20 @@ input.tab:checked + .tab-content,
3090
3088
  background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
3091
3089
  color: var(--fallback-bc,oklch(var(--bc)/0.4));
3092
3090
  }
3093
- .input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder {
3091
+ .input:has(> input[disabled])::-moz-placeholder, .input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder {
3094
3092
  color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
3095
3093
  --tw-placeholder-opacity: 0.2;
3096
3094
  }
3097
- .input-disabled::placeholder,
3095
+ .input:has(> input[disabled])::placeholder,
3096
+ .input-disabled::placeholder,
3098
3097
  .input:disabled::placeholder,
3099
3098
  .input[disabled]::placeholder {
3100
3099
  color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
3101
3100
  --tw-placeholder-opacity: 0.2;
3102
3101
  }
3102
+ .input:has(> input[disabled]) > input[disabled] {
3103
+ cursor: not-allowed;
3104
+ }
3103
3105
  .input::-webkit-date-and-time-value {
3104
3106
  text-align: inherit;
3105
3107
  }
@@ -3126,6 +3128,13 @@ input.tab:checked + .tab-content,
3126
3128
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E");
3127
3129
  mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E");
3128
3130
  }
3131
+ .loading-spinner {
3132
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E");
3133
+ mask-image: url("data:image/svg+xml,%3Csvg width='24' height='24' stroke='%23000' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E.spinner_V8m1%7Btransform-origin:center;animation:spinner_zKoa 2s linear infinite%7D.spinner_V8m1 circle%7Bstroke-linecap:round;animation:spinner_YpZS 1.5s ease-out infinite%7D%40keyframes spinner_zKoa%7B100%25%7Btransform:rotate(360deg)%7D%7D%40keyframes spinner_YpZS%7B0%25%7Bstroke-dasharray:0 150;stroke-dashoffset:0%7D47.5%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-16%7D95%25%2C100%25%7Bstroke-dasharray:42 150;stroke-dashoffset:-59%7D%7D%3C%2Fstyle%3E%3Cg class='spinner_V8m1'%3E%3Ccircle cx='12' cy='12' r='9.5' fill='none' stroke-width='3'%3E%3C%2Fcircle%3E%3C%2Fg%3E%3C%2Fsvg%3E");
3134
+ }
3135
+ .loading-md {
3136
+ width: 1.5rem;
3137
+ }
3129
3138
  :where(.menu li:empty) {
3130
3139
  --tw-bg-opacity: 1;
3131
3140
  background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
@@ -3882,12 +3891,6 @@ input.tab:checked + .tab-content,
3882
3891
  .z-\\[1\\] {
3883
3892
  z-index: 1;
3884
3893
  }
3885
- .col-\\[9999\\] {
3886
- grid-column: 9999;
3887
- }
3888
- .m-1 {
3889
- margin: 0.25rem;
3890
- }
3891
3894
  .m-2 {
3892
3895
  margin: 0.5rem;
3893
3896
  }
@@ -3933,8 +3936,11 @@ input.tab:checked + .tab-content,
3933
3936
  .grid {
3934
3937
  display: grid;
3935
3938
  }
3936
- .w-11\\/12 {
3937
- width: 91.666667%;
3939
+ .hidden {
3940
+ display: none;
3941
+ }
3942
+ .h-full {
3943
+ height: 100%;
3938
3944
  }
3939
3945
  .w-16 {
3940
3946
  width: 4rem;
@@ -3957,6 +3963,9 @@ input.tab:checked + .tab-content,
3957
3963
  .max-w-screen-lg {
3958
3964
  max-width: 1024px;
3959
3965
  }
3966
+ .flex-1 {
3967
+ flex: 1 1 0%;
3968
+ }
3960
3969
  .grow {
3961
3970
  flex-grow: 1;
3962
3971
  }
@@ -3978,12 +3987,18 @@ input.tab:checked + .tab-content,
3978
3987
  .justify-center {
3979
3988
  justify-content: center;
3980
3989
  }
3990
+ .justify-between {
3991
+ justify-content: space-between;
3992
+ }
3981
3993
  .gap-1 {
3982
3994
  gap: 0.25rem;
3983
3995
  }
3984
3996
  .gap-2 {
3985
3997
  gap: 0.5rem;
3986
3998
  }
3999
+ .overflow-auto {
4000
+ overflow: auto;
4001
+ }
3987
4002
  .whitespace-nowrap {
3988
4003
  white-space: nowrap;
3989
4004
  }
@@ -4005,24 +4020,41 @@ input.tab:checked + .tab-content,
4005
4020
  .rounded-none {
4006
4021
  border-radius: 0px;
4007
4022
  }
4023
+ .rounded-b-md {
4024
+ border-bottom-right-radius: 0.375rem;
4025
+ border-bottom-left-radius: 0.375rem;
4026
+ }
4027
+ .rounded-tl-md {
4028
+ border-top-left-radius: 0.375rem;
4029
+ }
4030
+ .rounded-tr-md {
4031
+ border-top-right-radius: 0.375rem;
4032
+ }
4008
4033
  .border {
4009
4034
  border-width: 1px;
4010
4035
  }
4011
4036
  .border-2 {
4012
4037
  border-width: 2px;
4013
4038
  }
4014
- .border-base-300 {
4015
- --tw-border-opacity: 1;
4016
- border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));
4039
+ .border-b-2 {
4040
+ border-bottom-width: 2px;
4017
4041
  }
4018
4042
  .border-error {
4019
4043
  --tw-border-opacity: 1;
4020
4044
  border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity)));
4021
4045
  }
4046
+ .border-gray-100 {
4047
+ --tw-border-opacity: 1;
4048
+ border-color: rgb(243 244 246 / var(--tw-border-opacity));
4049
+ }
4022
4050
  .border-gray-300 {
4023
4051
  --tw-border-opacity: 1;
4024
4052
  border-color: rgb(209 213 219 / var(--tw-border-opacity));
4025
4053
  }
4054
+ .border-gray-400 {
4055
+ --tw-border-opacity: 1;
4056
+ border-color: rgb(156 163 175 / var(--tw-border-opacity));
4057
+ }
4026
4058
  .bg-base-100 {
4027
4059
  --tw-bg-opacity: 1;
4028
4060
  background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
@@ -4035,9 +4067,6 @@ input.tab:checked + .tab-content,
4035
4067
  --tw-bg-opacity: 1;
4036
4068
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
4037
4069
  }
4038
- .p-1 {
4039
- padding: 0.25rem;
4040
- }
4041
4070
  .p-2 {
4042
4071
  padding: 0.5rem;
4043
4072
  }
@@ -4061,17 +4090,43 @@ input.tab:checked + .tab-content,
4061
4090
  padding-top: 0.125rem;
4062
4091
  padding-bottom: 0.125rem;
4063
4092
  }
4064
- .py-16 {
4065
- padding-top: 4rem;
4066
- padding-bottom: 4rem;
4093
+ .py-16 {
4094
+ padding-top: 4rem;
4095
+ padding-bottom: 4rem;
4096
+ }
4097
+ .py-2 {
4098
+ padding-top: 0.5rem;
4099
+ padding-bottom: 0.5rem;
4100
+ }
4101
+ .text-lg {
4102
+ font-size: 1.125rem;
4103
+ line-height: 1.75rem;
4104
+ }
4105
+ .text-sm {
4106
+ font-size: 0.875rem;
4107
+ line-height: 1.25rem;
4108
+ }
4109
+ .text-xl {
4110
+ font-size: 1.25rem;
4111
+ line-height: 1.75rem;
4067
4112
  }
4068
4113
  .text-xs {
4069
4114
  font-size: 0.75rem;
4070
4115
  line-height: 1rem;
4071
4116
  }
4117
+ .font-bold {
4118
+ font-weight: 700;
4119
+ }
4072
4120
  .font-medium {
4073
4121
  font-weight: 500;
4074
4122
  }
4123
+ .leading-5 {
4124
+ line-height: 1.25rem;
4125
+ }
4126
+ .text-gray-600 {
4127
+ --tw-text-opacity: 1;
4128
+ color: rgb(75 85 99 / var(--tw-text-opacity));
4129
+ }
4075
4130
  .shadow {
4076
4131
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
4077
4132
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -4079,21 +4134,37 @@ input.tab:checked + .tab-content,
4079
4134
  }
4080
4135
  .filter {
4081
4136
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
4137
+ }
4138
+ .transition-colors {
4139
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
4140
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
4141
+ transition-duration: 150ms;
4142
+ }
4143
+ .duration-150 {
4144
+ transition-duration: 150ms;
4145
+ }
4146
+ .hover\\:bg-gray-100:hover {
4147
+ --tw-bg-opacity: 1;
4148
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity));
4149
+ }
4150
+ .hover\\:text-gray-700:hover {
4151
+ --tw-text-opacity: 1;
4152
+ color: rgb(55 65 81 / var(--tw-text-opacity));
4082
4153
  }`;
4083
- var __defProp$8 = Object.defineProperty;
4084
- var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
4085
- var __decorateClass$8 = (decorators, target, key, kind) => {
4086
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
4154
+ var __defProp$9 = Object.defineProperty;
4155
+ var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
4156
+ var __decorateClass$9 = (decorators, target, key, kind) => {
4157
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
4087
4158
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
4088
4159
  if (decorator = decorators[i2])
4089
4160
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4090
4161
  if (kind && result)
4091
- __defProp$8(target, key, result);
4162
+ __defProp$9(target, key, result);
4092
4163
  return result;
4093
4164
  };
4094
4165
  const tailwindElementCss = unsafeCSS(tailwindStyle);
4095
4166
  const minMaxPercentSliderElementCss = unsafeCSS(minMaxPercentSliderCss);
4096
- const _PreactLitAdapter = class _PreactLitAdapter extends b {
4167
+ const _PreactLitAdapter = class _PreactLitAdapter extends ReactiveElement {
4097
4168
  constructor() {
4098
4169
  super(...arguments);
4099
4170
  this.lapis = "";
@@ -4103,7 +4174,6 @@ const _PreactLitAdapter = class _PreactLitAdapter extends b {
4103
4174
  };
4104
4175
  }
4105
4176
  update(changedProperties) {
4106
- console.log("this.lapis", this.lapis);
4107
4177
  const vdom = /* @__PURE__ */ u$1(LapisUrlContext.Provider, { value: this.lapis, children: /* @__PURE__ */ u$1(ReferenceGenomeContext.Provider, { value: this.referenceGenome, children: this.render() }) });
4108
4178
  super.update(changedProperties);
4109
4179
  render(vdom, this.renderRoot);
@@ -4111,10 +4181,10 @@ const _PreactLitAdapter = class _PreactLitAdapter extends b {
4111
4181
  };
4112
4182
  _PreactLitAdapter.styles = [tailwindElementCss, minMaxPercentSliderElementCss];
4113
4183
  let PreactLitAdapter = _PreactLitAdapter;
4114
- __decorateClass$8([
4184
+ __decorateClass$9([
4115
4185
  consume({ context: lapisContext })
4116
4186
  ], PreactLitAdapter.prototype, "lapis", 2);
4117
- __decorateClass$8([
4187
+ __decorateClass$9([
4118
4188
  consume({ context: referenceGenomeContext, subscribe: true })
4119
4189
  ], PreactLitAdapter.prototype, "referenceGenome", 2);
4120
4190
  const gridJsElementCss = unsafeCSS(gridJsStyle);
@@ -4122,15 +4192,15 @@ const _PreactLitAdapterWithGridJsStyles = class _PreactLitAdapterWithGridJsStyle
4122
4192
  };
4123
4193
  _PreactLitAdapterWithGridJsStyles.styles = [...PreactLitAdapter.styles, gridJsElementCss];
4124
4194
  let PreactLitAdapterWithGridJsStyles = _PreactLitAdapterWithGridJsStyles;
4125
- var __defProp$7 = Object.defineProperty;
4126
- var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
4127
- var __decorateClass$7 = (decorators, target, key, kind) => {
4128
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
4195
+ var __defProp$8 = Object.defineProperty;
4196
+ var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
4197
+ var __decorateClass$8 = (decorators, target, key, kind) => {
4198
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
4129
4199
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
4130
4200
  if (decorator = decorators[i2])
4131
4201
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4132
4202
  if (kind && result)
4133
- __defProp$7(target, key, result);
4203
+ __defProp$8(target, key, result);
4134
4204
  return result;
4135
4205
  };
4136
4206
  let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -4139,27 +4209,39 @@ let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles
4139
4209
  this.variants = [];
4140
4210
  this.sequenceType = "nucleotide";
4141
4211
  this.views = ["table"];
4212
+ this.size = void 0;
4142
4213
  }
4143
4214
  render() {
4144
- return /* @__PURE__ */ u$1(MutationComparison, { variants: this.variants, sequenceType: this.sequenceType, views: this.views });
4215
+ return /* @__PURE__ */ u$1(
4216
+ MutationComparison,
4217
+ {
4218
+ variants: this.variants,
4219
+ sequenceType: this.sequenceType,
4220
+ views: this.views,
4221
+ size: this.size
4222
+ }
4223
+ );
4145
4224
  }
4146
4225
  };
4147
- __decorateClass$7([
4226
+ __decorateClass$8([
4148
4227
  n2({ type: Array })
4149
4228
  ], MutationComparisonComponent.prototype, "variants", 2);
4150
- __decorateClass$7([
4229
+ __decorateClass$8([
4151
4230
  n2({ type: String })
4152
4231
  ], MutationComparisonComponent.prototype, "sequenceType", 2);
4153
- __decorateClass$7([
4232
+ __decorateClass$8([
4154
4233
  n2({ type: Array })
4155
4234
  ], MutationComparisonComponent.prototype, "views", 2);
4156
- MutationComparisonComponent = __decorateClass$7([
4235
+ __decorateClass$8([
4236
+ n2({ type: Object })
4237
+ ], MutationComparisonComponent.prototype, "size", 2);
4238
+ MutationComparisonComponent = __decorateClass$8([
4157
4239
  t$2("gs-mutation-comparison-component")
4158
4240
  ], MutationComparisonComponent);
4159
4241
  function getInsertionsTableData(data) {
4160
4242
  return data.map((mutationEntry) => {
4161
4243
  return {
4162
- insertion: mutationEntry.mutation.toString(),
4244
+ insertion: mutationEntry.mutation,
4163
4245
  count: mutationEntry.count
4164
4246
  };
4165
4247
  });
@@ -4170,7 +4252,7 @@ function getMutationsTableData(data, proportionInterval) {
4170
4252
  };
4171
4253
  return data.filter(byProportion2).map((mutationEntry) => {
4172
4254
  return {
4173
- mutation: mutationEntry.mutation.toString(),
4255
+ mutation: mutationEntry.mutation,
4174
4256
  type: mutationEntry.type,
4175
4257
  count: mutationEntry.count,
4176
4258
  proportion: mutationEntry.proportion
@@ -4301,22 +4383,13 @@ const MutationsGrid = ({ data, sequenceType, proportionInterval }) => {
4301
4383
  return /* @__PURE__ */ u$1(Table, { data: tableData, columns: getHeaders(), pagination: true });
4302
4384
  };
4303
4385
  const sortInsertions = (a2, b2) => {
4304
- const insertionA = Insertion.parse(a2);
4305
- const insertionB = Insertion.parse(b2);
4306
- if (insertionA && insertionB) {
4307
- const segmentA = insertionA.segment;
4308
- const segmentB = insertionB.segment;
4309
- if (segmentA !== void 0 && segmentB !== void 0 && segmentA !== segmentB) {
4310
- return segmentA.localeCompare(segmentB);
4311
- }
4312
- const positionA = insertionA.position;
4313
- const positionB = insertionB.position;
4314
- if (positionA !== positionB) {
4315
- return positionA - positionB;
4316
- }
4317
- return insertionA.insertedSymbols.localeCompare(insertionB.insertedSymbols);
4386
+ if (a2.segment !== b2.segment) {
4387
+ return compareSegments(a2.segment, b2.segment);
4388
+ }
4389
+ if (a2.position !== b2.position) {
4390
+ return comparePositions(a2.position, b2.position);
4318
4391
  }
4319
- throw new Error(`Invalid insertion: ${a2} or ${b2}`);
4392
+ return a2.insertedSymbols.localeCompare(b2.insertedSymbols);
4320
4393
  };
4321
4394
  const InsertionsTable = ({ data }) => {
4322
4395
  const getHeaders = () => {
@@ -4327,7 +4400,8 @@ const InsertionsTable = ({ data }) => {
4327
4400
  compare: (a2, b2) => {
4328
4401
  return sortInsertions(a2, b2);
4329
4402
  }
4330
- }
4403
+ },
4404
+ formatter: (cell) => cell.toString()
4331
4405
  },
4332
4406
  {
4333
4407
  name: "Count",
@@ -4347,7 +4421,8 @@ const MutationsTable = ({ data, proportionInterval }) => {
4347
4421
  compare: (a2, b2) => {
4348
4422
  return sortSubstitutionsAndDeletions(a2, b2);
4349
4423
  }
4350
- }
4424
+ },
4425
+ formatter: (cell) => cell.toString()
4351
4426
  },
4352
4427
  {
4353
4428
  name: "Type",
@@ -4421,7 +4496,7 @@ function filterMutationsData(data, displayedSegments, displayedMutationTypes) {
4421
4496
  gridData: filteredSubstitutionsOrDeletions
4422
4497
  };
4423
4498
  }
4424
- const Mutations = ({ variant, sequenceType, views }) => {
4499
+ const Mutations = ({ variant, sequenceType, views, size }) => {
4425
4500
  const lapis = P(LapisUrlContext);
4426
4501
  const { data, error, isLoading } = useQuery(async () => {
4427
4502
  return queryMutationsData(variant, sequenceType, lapis);
@@ -4436,7 +4511,7 @@ const Mutations = ({ variant, sequenceType, views }) => {
4436
4511
  if (data === null) {
4437
4512
  return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(NoDataDisplay, {}) });
4438
4513
  }
4439
- return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationsTabs, { mutationsData: data, sequenceType, views }) });
4514
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize: { height: "700px", width: "100%" }, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationsTabs, { mutationsData: data, sequenceType, views }) }) });
4440
4515
  };
4441
4516
  const MutationsTabs = ({ mutationsData, sequenceType, views }) => {
4442
4517
  const [proportionInterval, setProportionInterval] = p({ min: 0.05, max: 1 });
@@ -4474,7 +4549,7 @@ const MutationsTabs = ({ mutationsData, sequenceType, views }) => {
4474
4549
  };
4475
4550
  const tabs = views.map((view) => getTab(view));
4476
4551
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
4477
- Toolbar$1,
4552
+ Toolbar$2,
4478
4553
  {
4479
4554
  activeTab,
4480
4555
  displayedSegments,
@@ -4488,7 +4563,7 @@ const MutationsTabs = ({ mutationsData, sequenceType, views }) => {
4488
4563
  );
4489
4564
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
4490
4565
  };
4491
- const Toolbar$1 = ({
4566
+ const Toolbar$2 = ({
4492
4567
  activeTab,
4493
4568
  displayedSegments,
4494
4569
  setDisplayedSegments,
@@ -4530,22 +4605,27 @@ const Toolbar$1 = ({
4530
4605
  CsvDownloadButton,
4531
4606
  {
4532
4607
  className: "mx-1 btn btn-xs",
4533
- getData: () => getInsertionsTableData(filteredData.insertions),
4608
+ getData: () => getInsertionsTableData(filteredData.insertions).map((row) => {
4609
+ return {
4610
+ insertion: row.insertion.toString(),
4611
+ count: row.count
4612
+ };
4613
+ }),
4534
4614
  filename: "insertions.csv"
4535
4615
  }
4536
4616
  ),
4537
4617
  /* @__PURE__ */ u$1(Info, { className: "mx-1", content: "Info for mutations" })
4538
4618
  ] });
4539
4619
  };
4540
- var __defProp$6 = Object.defineProperty;
4541
- var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
4542
- var __decorateClass$6 = (decorators, target, key, kind) => {
4543
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
4620
+ var __defProp$7 = Object.defineProperty;
4621
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
4622
+ var __decorateClass$7 = (decorators, target, key, kind) => {
4623
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
4544
4624
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
4545
4625
  if (decorator = decorators[i2])
4546
4626
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4547
4627
  if (kind && result)
4548
- __defProp$6(target, key, result);
4628
+ __defProp$7(target, key, result);
4549
4629
  return result;
4550
4630
  };
4551
4631
  let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -4554,21 +4634,25 @@ let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
4554
4634
  this.variant = { displayName: "" };
4555
4635
  this.sequenceType = "nucleotide";
4556
4636
  this.views = ["table", "grid"];
4637
+ this.size = void 0;
4557
4638
  }
4558
4639
  render() {
4559
- return /* @__PURE__ */ u$1(Mutations, { variant: this.variant, sequenceType: this.sequenceType, views: this.views });
4640
+ return /* @__PURE__ */ u$1(Mutations, { variant: this.variant, sequenceType: this.sequenceType, views: this.views, size: this.size });
4560
4641
  }
4561
4642
  };
4562
- __decorateClass$6([
4643
+ __decorateClass$7([
4563
4644
  n2({ type: Object })
4564
4645
  ], MutationsComponent.prototype, "variant", 2);
4565
- __decorateClass$6([
4646
+ __decorateClass$7([
4566
4647
  n2({ type: String })
4567
4648
  ], MutationsComponent.prototype, "sequenceType", 2);
4568
- __decorateClass$6([
4649
+ __decorateClass$7([
4569
4650
  n2({ type: Array })
4570
4651
  ], MutationsComponent.prototype, "views", 2);
4571
- MutationsComponent = __decorateClass$6([
4652
+ __decorateClass$7([
4653
+ n2({ type: Object })
4654
+ ], MutationsComponent.prototype, "size", 2);
4655
+ MutationsComponent = __decorateClass$7([
4572
4656
  t$2("gs-mutations-component")
4573
4657
  ], MutationsComponent);
4574
4658
  function getPrevalenceOverTimeTableData(data, granularity) {
@@ -4680,6 +4764,7 @@ const PrevalenceOverTimeBarChart = ({
4680
4764
  datasets: data.map((graphData, index) => datasets$1(graphData, index, confidenceIntervalMethod))
4681
4765
  },
4682
4766
  options: {
4767
+ maintainAspectRatio: false,
4683
4768
  animation: false,
4684
4769
  scales: {
4685
4770
  y: getYAxisScale(yAxisScaleType)
@@ -5633,6 +5718,7 @@ const PrevalenceOverTimeBubbleChart = ({ data, yAxisScaleType }) => {
5633
5718
  },
5634
5719
  options: {
5635
5720
  animation: false,
5721
+ maintainAspectRatio: false,
5636
5722
  scales: {
5637
5723
  x: {
5638
5724
  ticks: {
@@ -5690,6 +5776,7 @@ const PrevalenceOverTimeLineChart = ({
5690
5776
  },
5691
5777
  options: {
5692
5778
  animation: false,
5779
+ maintainAspectRatio: false,
5693
5780
  scales: {
5694
5781
  y: getYAxisScale(yAxisScaleType)
5695
5782
  },
@@ -6106,7 +6193,8 @@ const PrevalenceOverTime = ({
6106
6193
  granularity,
6107
6194
  smoothingWindow,
6108
6195
  views,
6109
- confidenceIntervalMethods
6196
+ confidenceIntervalMethods,
6197
+ size
6110
6198
  }) => {
6111
6199
  const lapis = P(LapisUrlContext);
6112
6200
  const { data, error, isLoading } = useQuery(
@@ -6123,7 +6211,7 @@ const PrevalenceOverTime = ({
6123
6211
  if (data === null) {
6124
6212
  return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(NoDataDisplay, {}) });
6125
6213
  }
6126
- return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6214
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize: { height: "600px", width: "100%" }, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6127
6215
  PrevalenceOverTimeTabs,
6128
6216
  {
6129
6217
  views,
@@ -6131,7 +6219,7 @@ const PrevalenceOverTime = ({
6131
6219
  granularity,
6132
6220
  confidenceIntervalMethods
6133
6221
  }
6134
- ) });
6222
+ ) }) });
6135
6223
  };
6136
6224
  const PrevalenceOverTimeTabs = ({
6137
6225
  views,
@@ -6175,12 +6263,15 @@ const PrevalenceOverTimeTabs = ({
6175
6263
  content: /* @__PURE__ */ u$1(PrevalenceOverTimeBubbleChart, { data, yAxisScaleType })
6176
6264
  };
6177
6265
  case "table":
6178
- return { title: "Table", content: /* @__PURE__ */ u$1(PrevalenceOverTimeTable, { data, granularity }) };
6266
+ return {
6267
+ title: "Table",
6268
+ content: /* @__PURE__ */ u$1(PrevalenceOverTimeTable, { data, granularity })
6269
+ };
6179
6270
  }
6180
6271
  };
6181
6272
  const tabs = views.map((view) => getTab(view));
6182
6273
  const toolbar = (activeTab) => /* @__PURE__ */ u$1(
6183
- Toolbar,
6274
+ Toolbar$1,
6184
6275
  {
6185
6276
  activeTab,
6186
6277
  yAxisScaleType,
@@ -6194,7 +6285,7 @@ const PrevalenceOverTimeTabs = ({
6194
6285
  );
6195
6286
  return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar });
6196
6287
  };
6197
- const Toolbar = ({
6288
+ const Toolbar$1 = ({
6198
6289
  activeTab,
6199
6290
  yAxisScaleType,
6200
6291
  setYAxisScaleType,
@@ -6225,15 +6316,15 @@ const Toolbar = ({
6225
6316
  /* @__PURE__ */ u$1(Info, { className: "ml-1", content: "Info for prevalence over time" })
6226
6317
  ] });
6227
6318
  };
6228
- var __defProp$5 = Object.defineProperty;
6229
- var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
6230
- var __decorateClass$5 = (decorators, target, key, kind) => {
6231
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
6319
+ var __defProp$6 = Object.defineProperty;
6320
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
6321
+ var __decorateClass$6 = (decorators, target, key, kind) => {
6322
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
6232
6323
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
6233
6324
  if (decorator = decorators[i2])
6234
6325
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
6235
6326
  if (kind && result)
6236
- __defProp$5(target, key, result);
6327
+ __defProp$6(target, key, result);
6237
6328
  return result;
6238
6329
  };
6239
6330
  let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles {
@@ -6245,6 +6336,7 @@ let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
6245
6336
  this.smoothingWindow = 0;
6246
6337
  this.views = ["bar", "line", "bubble", "table"];
6247
6338
  this.confidenceIntervalMethods = ["wilson"];
6339
+ this.size = void 0;
6248
6340
  }
6249
6341
  render() {
6250
6342
  return /* @__PURE__ */ u$1(
@@ -6255,30 +6347,34 @@ let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
6255
6347
  granularity: this.granularity,
6256
6348
  smoothingWindow: this.smoothingWindow,
6257
6349
  views: this.views,
6258
- confidenceIntervalMethods: this.confidenceIntervalMethods
6350
+ confidenceIntervalMethods: this.confidenceIntervalMethods,
6351
+ size: this.size
6259
6352
  }
6260
6353
  );
6261
6354
  }
6262
6355
  };
6263
- __decorateClass$5([
6356
+ __decorateClass$6([
6264
6357
  n2({ type: Object })
6265
6358
  ], PrevalenceOverTimeComponent.prototype, "numerator", 2);
6266
- __decorateClass$5([
6359
+ __decorateClass$6([
6267
6360
  n2({ type: Object })
6268
6361
  ], PrevalenceOverTimeComponent.prototype, "denominator", 2);
6269
- __decorateClass$5([
6362
+ __decorateClass$6([
6270
6363
  n2({ type: String })
6271
6364
  ], PrevalenceOverTimeComponent.prototype, "granularity", 2);
6272
- __decorateClass$5([
6365
+ __decorateClass$6([
6273
6366
  n2({ type: Number })
6274
6367
  ], PrevalenceOverTimeComponent.prototype, "smoothingWindow", 2);
6275
- __decorateClass$5([
6368
+ __decorateClass$6([
6276
6369
  n2({ type: Array })
6277
6370
  ], PrevalenceOverTimeComponent.prototype, "views", 2);
6278
- __decorateClass$5([
6371
+ __decorateClass$6([
6279
6372
  n2({ type: Array })
6280
6373
  ], PrevalenceOverTimeComponent.prototype, "confidenceIntervalMethods", 2);
6281
- PrevalenceOverTimeComponent = __decorateClass$5([
6374
+ __decorateClass$6([
6375
+ n2({ type: Object })
6376
+ ], PrevalenceOverTimeComponent.prototype, "size", 2);
6377
+ PrevalenceOverTimeComponent = __decorateClass$6([
6282
6378
  t$2("gs-prevalence-over-time")
6283
6379
  ], PrevalenceOverTimeComponent);
6284
6380
  Chart.register(...registerables, LogitScale);
@@ -6290,6 +6386,7 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }) => {
6290
6386
  datasets: datasets(data)
6291
6387
  },
6292
6388
  options: {
6389
+ maintainAspectRatio: false,
6293
6390
  animation: false,
6294
6391
  scales: {
6295
6392
  y: getYAxisScale(yAxisScaleType)
@@ -6302,9 +6399,9 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }) => {
6302
6399
  }
6303
6400
  }
6304
6401
  };
6305
- return /* @__PURE__ */ u$1(Fragment, { children: [
6306
- /* @__PURE__ */ u$1(GsChart, { configuration: config }),
6307
- /* @__PURE__ */ u$1("div", { children: [
6402
+ return /* @__PURE__ */ u$1("div", { className: "flex flex-col h-full", children: [
6403
+ /* @__PURE__ */ u$1("div", { className: "flex-1", children: /* @__PURE__ */ u$1(GsChart, { configuration: config }) }),
6404
+ /* @__PURE__ */ u$1("p", { children: [
6308
6405
  "Advantage: ",
6309
6406
  (data.params.fd.value * 100).toFixed(2),
6310
6407
  "% (",
@@ -6469,7 +6566,8 @@ const RelativeGrowthAdvantage = ({
6469
6566
  numerator,
6470
6567
  denominator,
6471
6568
  generationTime,
6472
- views
6569
+ views,
6570
+ size
6473
6571
  }) => {
6474
6572
  const lapis = P(LapisUrlContext);
6475
6573
  const [yAxisScaleType, setYAxisScaleType] = p("linear");
@@ -6487,7 +6585,7 @@ const RelativeGrowthAdvantage = ({
6487
6585
  if (data === null) {
6488
6586
  return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(NoDataDisplay, {}) });
6489
6587
  }
6490
- return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6588
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize: { height: "700px", width: "100%" }, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6491
6589
  RelativeGrowthAdvantageTabs,
6492
6590
  {
6493
6591
  data,
@@ -6495,7 +6593,7 @@ const RelativeGrowthAdvantage = ({
6495
6593
  setYAxisScaleType,
6496
6594
  views
6497
6595
  }
6498
- ) });
6596
+ ) }) });
6499
6597
  };
6500
6598
  const RelativeGrowthAdvantageTabs = ({
6501
6599
  data,
@@ -6535,15 +6633,15 @@ const RelativeGrowthAdvantageToolbar = ({
6535
6633
  /* @__PURE__ */ u$1(Info, { className: "ml-1", content: "Line chart" })
6536
6634
  ] });
6537
6635
  };
6538
- var __defProp$4 = Object.defineProperty;
6539
- var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
6540
- var __decorateClass$4 = (decorators, target, key, kind) => {
6541
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
6636
+ var __defProp$5 = Object.defineProperty;
6637
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
6638
+ var __decorateClass$5 = (decorators, target, key, kind) => {
6639
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
6542
6640
  for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
6543
6641
  if (decorator = decorators[i2])
6544
6642
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
6545
6643
  if (kind && result)
6546
- __defProp$4(target, key, result);
6644
+ __defProp$5(target, key, result);
6547
6645
  return result;
6548
6646
  };
6549
6647
  let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
@@ -6553,6 +6651,7 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
6553
6651
  this.denominator = {};
6554
6652
  this.generationTime = 7;
6555
6653
  this.views = ["line"];
6654
+ this.size = void 0;
6556
6655
  }
6557
6656
  render() {
6558
6657
  return /* @__PURE__ */ u$1(
@@ -6561,26 +6660,135 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
6561
6660
  numerator: this.numerator,
6562
6661
  denominator: this.denominator,
6563
6662
  generationTime: this.generationTime,
6564
- views: this.views
6663
+ views: this.views,
6664
+ size: this.size
6565
6665
  }
6566
6666
  );
6567
6667
  }
6568
6668
  };
6569
- __decorateClass$4([
6669
+ __decorateClass$5([
6570
6670
  n2({ type: Object })
6571
6671
  ], RelativeGrowthAdvantageComponent.prototype, "numerator", 2);
6572
- __decorateClass$4([
6672
+ __decorateClass$5([
6573
6673
  n2({ type: Object })
6574
6674
  ], RelativeGrowthAdvantageComponent.prototype, "denominator", 2);
6575
- __decorateClass$4([
6675
+ __decorateClass$5([
6576
6676
  n2({ type: Number })
6577
6677
  ], RelativeGrowthAdvantageComponent.prototype, "generationTime", 2);
6578
- __decorateClass$4([
6678
+ __decorateClass$5([
6579
6679
  n2({ type: Array })
6580
6680
  ], RelativeGrowthAdvantageComponent.prototype, "views", 2);
6581
- RelativeGrowthAdvantageComponent = __decorateClass$4([
6681
+ __decorateClass$5([
6682
+ n2({ type: Object })
6683
+ ], RelativeGrowthAdvantageComponent.prototype, "size", 2);
6684
+ RelativeGrowthAdvantageComponent = __decorateClass$5([
6582
6685
  t$2("gs-relative-growth-advantage")
6583
6686
  ], RelativeGrowthAdvantageComponent);
6687
+ const AggregateTable = ({ data, fields }) => {
6688
+ const headers = [
6689
+ ...fields.map((field) => {
6690
+ return {
6691
+ name: field,
6692
+ sort: true
6693
+ };
6694
+ }),
6695
+ {
6696
+ name: "count",
6697
+ sort: true
6698
+ },
6699
+ {
6700
+ name: "proportion",
6701
+ sort: true,
6702
+ formatter: (cell) => formatProportion(cell)
6703
+ }
6704
+ ];
6705
+ return /* @__PURE__ */ u$1(Table, { data, columns: headers, pagination: true });
6706
+ };
6707
+ async function queryAggregateData(variant, fields, lapis, signal) {
6708
+ const fetchData = new FetchAggregatedOperator(variant, fields);
6709
+ const data = (await fetchData.evaluate(lapis, signal)).content;
6710
+ const total = data.reduce((acc, row) => acc + row.count, 0);
6711
+ return data.map(
6712
+ (row) => ({
6713
+ ...row,
6714
+ proportion: row.count / total
6715
+ })
6716
+ );
6717
+ }
6718
+ const Aggregate = ({ fields, views, filter, size }) => {
6719
+ const lapis = P(LapisUrlContext);
6720
+ const { data, error, isLoading } = useQuery(async () => {
6721
+ return queryAggregateData(filter, fields, lapis);
6722
+ }, [filter, fields, lapis]);
6723
+ const headline = "Aggregate";
6724
+ if (isLoading) {
6725
+ return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(LoadingDisplay, {}) });
6726
+ }
6727
+ if (error !== null) {
6728
+ return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(ErrorDisplay, { error }) });
6729
+ }
6730
+ if (data === null) {
6731
+ return /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(NoDataDisplay, {}) });
6732
+ }
6733
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize: { height: "700px", width: "100%" }, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(AggregatedDataTabs, { data, views, fields }) }) });
6734
+ };
6735
+ const AggregatedDataTabs = ({ data, views, fields }) => {
6736
+ const getTab = (view) => {
6737
+ switch (view) {
6738
+ case "table":
6739
+ return {
6740
+ title: "Table",
6741
+ content: /* @__PURE__ */ u$1(AggregateTable, { data, fields })
6742
+ };
6743
+ }
6744
+ };
6745
+ const tabs = views.map((view) => getTab(view));
6746
+ return /* @__PURE__ */ u$1(Tabs, { tabs, toolbar: /* @__PURE__ */ u$1(Toolbar, { data }) });
6747
+ };
6748
+ const Toolbar = ({ data }) => {
6749
+ return /* @__PURE__ */ u$1("div", { class: "flex flex-row", children: [
6750
+ /* @__PURE__ */ u$1(CsvDownloadButton, { className: "mx-1 btn btn-xs", getData: () => data, filename: "aggregate.csv" }),
6751
+ /* @__PURE__ */ u$1(Info, { className: "mx-1", content: "Info for aggregate" })
6752
+ ] });
6753
+ };
6754
+ var __defProp$4 = Object.defineProperty;
6755
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
6756
+ var __decorateClass$4 = (decorators, target, key, kind) => {
6757
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
6758
+ for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
6759
+ if (decorator = decorators[i2])
6760
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
6761
+ if (kind && result)
6762
+ __defProp$4(target, key, result);
6763
+ return result;
6764
+ };
6765
+ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
6766
+ constructor() {
6767
+ super(...arguments);
6768
+ this.fields = [];
6769
+ this.views = ["table"];
6770
+ this.filter = {};
6771
+ this.size = void 0;
6772
+ }
6773
+ render() {
6774
+ return /* @__PURE__ */ u$1(Aggregate, { fields: this.fields, views: this.views, filter: this.filter, size: this.size });
6775
+ }
6776
+ };
6777
+ __decorateClass$4([
6778
+ n2({ type: Array })
6779
+ ], AggregateComponent.prototype, "fields", 2);
6780
+ __decorateClass$4([
6781
+ n2({ type: Array })
6782
+ ], AggregateComponent.prototype, "views", 2);
6783
+ __decorateClass$4([
6784
+ n2({ type: Object })
6785
+ ], AggregateComponent.prototype, "filter", 2);
6786
+ __decorateClass$4([
6787
+ n2({ type: Object })
6788
+ ], AggregateComponent.prototype, "size", 2);
6789
+ AggregateComponent = __decorateClass$4([
6790
+ t$2("gs-aggregate-component")
6791
+ ], AggregateComponent);
6584
6792
  const toYYYYMMDD = (date) => {
6585
6793
  if (!date) {
6586
6794
  return void 0;
@@ -6588,16 +6796,36 @@ const toYYYYMMDD = (date) => {
6588
6796
  const options2 = { year: "numeric", month: "2-digit", day: "2-digit" };
6589
6797
  return date.toLocaleDateString("en-CA", options2);
6590
6798
  };
6799
+ const PRESET_VALUE_CUSTOM = "custom";
6800
+ const PRESET_VALUE_ALL_TIMES = "allTimes";
6801
+ const PRESET_VALUE_LAST_2_WEEKS = "last2Weeks";
6802
+ const PRESET_VALUE_LAST_MONTH = "lastMonth";
6803
+ const PRESET_VALUE_LAST_2_MONTHS = "last2Months";
6804
+ const PRESET_VALUE_LAST_3_MONTHS = "last3Months";
6805
+ const PRESET_VALUE_LAST_6_MONTHS = "last6Months";
6806
+ const presets = {
6807
+ [PRESET_VALUE_CUSTOM]: { label: "Custom" },
6808
+ [PRESET_VALUE_ALL_TIMES]: { label: "All times" },
6809
+ [PRESET_VALUE_LAST_2_WEEKS]: { label: "Last 2 weeks" },
6810
+ [PRESET_VALUE_LAST_MONTH]: { label: "Last month" },
6811
+ [PRESET_VALUE_LAST_2_MONTHS]: { label: "Last 2 months" },
6812
+ [PRESET_VALUE_LAST_3_MONTHS]: { label: "Last 3 months" },
6813
+ [PRESET_VALUE_LAST_6_MONTHS]: { label: "Last 6 months" }
6814
+ };
6591
6815
  const DateRangeSelector = ({
6592
6816
  customSelectOptions,
6593
- earliestDate = "1900-01-01"
6817
+ earliestDate = "1900-01-01",
6818
+ initialValue
6594
6819
  }) => {
6595
6820
  const datePickerRef = F(null);
6596
6821
  const endDatePickerRef = F(null);
6597
6822
  const divRef = F(null);
6598
6823
  const [dateFromPicker, setDateFromPicker] = p(null);
6599
6824
  const [dateToPicker, setDateToPicker] = p(null);
6600
- const [selectedDateRange, setSelectedDateRange] = p("last6Months");
6825
+ const selectableOptions = getSelectableOptions(customSelectOptions);
6826
+ const [selectedDateRange, setSelectedDateRange] = p(
6827
+ initialValue !== void 0 && selectableOptions.some((option) => option.value === initialValue) ? initialValue : PRESET_VALUE_LAST_6_MONTHS
6828
+ );
6601
6829
  const [selectedDates, setSelectedDates] = p({
6602
6830
  dateFrom: getDatesForSelectorValue("last6Months", customSelectOptions, earliestDate).dateFrom,
6603
6831
  dateTo: getDatesForSelectorValue("last6Months", customSelectOptions, earliestDate).dateTo
@@ -6628,23 +6856,6 @@ const DateRangeSelector = ({
6628
6856
  dateToPicker == null ? void 0 : dateToPicker.destroy();
6629
6857
  };
6630
6858
  }, [datePickerRef, endDatePickerRef]);
6631
- const selectableOptions = () => {
6632
- const presetOptions = [
6633
- { label: "Custom", value: "custom" },
6634
- { label: "All times", value: "allTimes" },
6635
- { label: "Last 2 weeks", value: "last2Weeks" },
6636
- { label: "Last month", value: "lastMonth" },
6637
- { label: "Last 2 weeks", value: "last2Weeks" },
6638
- { label: "Last month", value: "lastMonth" },
6639
- { label: "Last 2 months", value: "last2Months" },
6640
- { label: "Last 3 months", value: "last3Months" },
6641
- { label: "Last 6 months", value: "last6Months" }
6642
- ];
6643
- const customOptions = customSelectOptions.map((customSelectOption) => {
6644
- return { label: customSelectOption.label, value: customLabelToOptionValue(customSelectOption.label) };
6645
- });
6646
- return [...presetOptions, ...customOptions];
6647
- };
6648
6859
  const onSelectChange = (value) => {
6649
6860
  setSelectedDateRange(value);
6650
6861
  const dateRange = getDatesForSelectorValue(value, customSelectOptions, earliestDate);
@@ -6696,7 +6907,7 @@ const DateRangeSelector = ({
6696
6907
  /* @__PURE__ */ u$1(
6697
6908
  Select,
6698
6909
  {
6699
- items: selectableOptions(),
6910
+ items: selectableOptions,
6700
6911
  selected: selectedDateRange,
6701
6912
  selectStyle: "select-bordered rounded-none join-item",
6702
6913
  onChange: (event) => {
@@ -6731,44 +6942,48 @@ const DateRangeSelector = ({
6731
6942
  )
6732
6943
  ] });
6733
6944
  };
6734
- const customLabelToOptionValue = (customLabel) => {
6735
- return `${customLabel}customLabel`;
6945
+ const getSelectableOptions = (customSelectOptions) => {
6946
+ const presetOptions = Object.entries(presets).map(([key, value]) => {
6947
+ return { label: value.label, value: key };
6948
+ });
6949
+ const customOptions = customSelectOptions.map((customSelectOption) => {
6950
+ return { label: customSelectOption.label, value: customSelectOption.label };
6951
+ });
6952
+ return [...presetOptions, ...customOptions];
6736
6953
  };
6737
6954
  const getDatesForSelectorValue = (selectorValue, customSelectOptions, earliestDate) => {
6738
6955
  const today = /* @__PURE__ */ new Date();
6739
- const customSelectOption = customSelectOptions.find(
6740
- (option) => customLabelToOptionValue(option.label) === selectorValue
6741
- );
6956
+ const customSelectOption = customSelectOptions.find((option) => option.label === selectorValue);
6742
6957
  if (customSelectOption) {
6743
6958
  return { dateFrom: new Date(customSelectOption.dateFrom), dateTo: new Date(customSelectOption.dateTo) };
6744
6959
  }
6745
6960
  switch (selectorValue) {
6746
- case "last2Weeks": {
6961
+ case PRESET_VALUE_LAST_2_WEEKS: {
6747
6962
  const twoWeeksAgo = new Date(today);
6748
6963
  twoWeeksAgo.setDate(today.getDate() - 14);
6749
6964
  return { dateFrom: twoWeeksAgo, dateTo: today };
6750
6965
  }
6751
- case "lastMonth": {
6966
+ case PRESET_VALUE_LAST_MONTH: {
6752
6967
  const lastMonth = new Date(today);
6753
6968
  lastMonth.setMonth(today.getMonth() - 1);
6754
6969
  return { dateFrom: lastMonth, dateTo: today };
6755
6970
  }
6756
- case "last2Months": {
6971
+ case PRESET_VALUE_LAST_2_MONTHS: {
6757
6972
  const twoMonthsAgo = new Date(today);
6758
6973
  twoMonthsAgo.setMonth(today.getMonth() - 2);
6759
6974
  return { dateFrom: twoMonthsAgo, dateTo: today };
6760
6975
  }
6761
- case "last3Months": {
6976
+ case PRESET_VALUE_LAST_3_MONTHS: {
6762
6977
  const threeMonthsAgo = new Date(today);
6763
6978
  threeMonthsAgo.setMonth(today.getMonth() - 3);
6764
6979
  return { dateFrom: threeMonthsAgo, dateTo: today };
6765
6980
  }
6766
- case "last6Months": {
6981
+ case PRESET_VALUE_LAST_6_MONTHS: {
6767
6982
  const sixMonthsAgo = new Date(today);
6768
6983
  sixMonthsAgo.setMonth(today.getMonth() - 6);
6769
6984
  return { dateFrom: sixMonthsAgo, dateTo: today };
6770
6985
  }
6771
- case "allTimes": {
6986
+ case PRESET_VALUE_ALL_TIMES: {
6772
6987
  return { dateFrom: new Date(earliestDate), dateTo: today };
6773
6988
  }
6774
6989
  default:
@@ -6791,9 +7006,17 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
6791
7006
  super(...arguments);
6792
7007
  this.customSelectOptions = [];
6793
7008
  this.earliestDate = "1900-01-01";
7009
+ this.initialValue = "";
6794
7010
  }
6795
7011
  render() {
6796
- return /* @__PURE__ */ u$1(DateRangeSelector, { customSelectOptions: this.customSelectOptions, earliestDate: this.earliestDate });
7012
+ return /* @__PURE__ */ u$1(
7013
+ DateRangeSelector,
7014
+ {
7015
+ customSelectOptions: this.customSelectOptions,
7016
+ earliestDate: this.earliestDate,
7017
+ initialValue: this.initialValue
7018
+ }
7019
+ );
6797
7020
  }
6798
7021
  };
6799
7022
  __decorateClass$3([
@@ -6802,6 +7025,9 @@ __decorateClass$3([
6802
7025
  __decorateClass$3([
6803
7026
  n2({ type: String })
6804
7027
  ], DateRangeSelectorComponent.prototype, "earliestDate", 2);
7028
+ __decorateClass$3([
7029
+ n2()
7030
+ ], DateRangeSelectorComponent.prototype, "initialValue", 2);
6805
7031
  DateRangeSelectorComponent = __decorateClass$3([
6806
7032
  t$2("gs-date-range-selector")
6807
7033
  ], DateRangeSelectorComponent);
@@ -6837,7 +7063,7 @@ function compareLocationEntries(fields) {
6837
7063
  return 0;
6838
7064
  };
6839
7065
  }
6840
- const LocationFilter = ({ value: initialValue, fields }) => {
7066
+ const LocationFilter = ({ initialValue, fields }) => {
6841
7067
  const lapis = P(LapisUrlContext);
6842
7068
  const [value, setValue] = p(initialValue ?? "");
6843
7069
  const [unknownLocation, setUnknownLocation] = p(false);
@@ -6930,16 +7156,16 @@ var __decorateClass$2 = (decorators, target, key, kind) => {
6930
7156
  let LocationFilterComponent = class extends PreactLitAdapter {
6931
7157
  constructor() {
6932
7158
  super(...arguments);
6933
- this.value = "";
7159
+ this.initialValue = "";
6934
7160
  this.fields = [];
6935
7161
  }
6936
7162
  render() {
6937
- return /* @__PURE__ */ u$1(LocationFilter, { value: this.value, fields: this.fields });
7163
+ return /* @__PURE__ */ u$1(LocationFilter, { initialValue: this.initialValue, fields: this.fields });
6938
7164
  }
6939
7165
  };
6940
7166
  __decorateClass$2([
6941
7167
  n2()
6942
- ], LocationFilterComponent.prototype, "value", 2);
7168
+ ], LocationFilterComponent.prototype, "initialValue", 2);
6943
7169
  __decorateClass$2([
6944
7170
  n2({ type: Array })
6945
7171
  ], LocationFilterComponent.prototype, "fields", 2);
@@ -6951,7 +7177,7 @@ async function fetchAutocompleteList(lapis, field, signal) {
6951
7177
  const data = (await fetchAggregatedOperator.evaluate(lapis, signal)).content;
6952
7178
  return data.map((item) => item[field]);
6953
7179
  }
6954
- const TextInput = ({ lapisField, placeholderText }) => {
7180
+ const TextInput = ({ lapisField, placeholderText, initialValue }) => {
6955
7181
  const lapis = P(LapisUrlContext);
6956
7182
  const inputRef = F(null);
6957
7183
  const { data, error, isLoading } = useQuery(() => fetchAutocompleteList(lapis, lapisField), [lapisField, lapis]);
@@ -6992,7 +7218,8 @@ const TextInput = ({ lapisField, placeholderText }) => {
6992
7218
  placeholder: placeholderText !== void 0 ? placeholderText : lapisField,
6993
7219
  onInput,
6994
7220
  ref: inputRef,
6995
- list: lapisField
7221
+ list: lapisField,
7222
+ value: initialValue
6996
7223
  }
6997
7224
  ),
6998
7225
  /* @__PURE__ */ u$1("datalist", { id: lapisField, children: data.map((item) => /* @__PURE__ */ u$1("option", { value: item }, item)) })
@@ -7012,13 +7239,24 @@ var __decorateClass$1 = (decorators, target, key, kind) => {
7012
7239
  let TextInputComponent = class extends PreactLitAdapter {
7013
7240
  constructor() {
7014
7241
  super(...arguments);
7242
+ this.initialValue = "";
7015
7243
  this.lapisField = "";
7016
7244
  this.placeholderText = "";
7017
7245
  }
7018
7246
  render() {
7019
- return /* @__PURE__ */ u$1(TextInput, { lapisField: this.lapisField, placeholderText: this.placeholderText });
7247
+ return /* @__PURE__ */ u$1(
7248
+ TextInput,
7249
+ {
7250
+ lapisField: this.lapisField,
7251
+ placeholderText: this.placeholderText,
7252
+ initialValue: this.initialValue
7253
+ }
7254
+ );
7020
7255
  }
7021
7256
  };
7257
+ __decorateClass$1([
7258
+ n2()
7259
+ ], TextInputComponent.prototype, "initialValue", 2);
7022
7260
  __decorateClass$1([
7023
7261
  n2()
7024
7262
  ], TextInputComponent.prototype, "lapisField", 2);
@@ -7028,6 +7266,16 @@ __decorateClass$1([
7028
7266
  TextInputComponent = __decorateClass$1([
7029
7267
  t$2("gs-text-input")
7030
7268
  ], TextInputComponent);
7269
+ const ReferenceGenomesAwaiter = ({ children }) => {
7270
+ const referenceGenome = P(ReferenceGenomeContext);
7271
+ if (isNotInitialized(referenceGenome)) {
7272
+ return /* @__PURE__ */ u$1("div", { className: "laoding loading-spinner loading-md", children: "Loading..." });
7273
+ }
7274
+ return /* @__PURE__ */ u$1(Fragment, { children });
7275
+ };
7276
+ function isNotInitialized(referenceGenome) {
7277
+ return referenceGenome.nucleotideSequences.length === 0 && referenceGenome.genes.length === 0;
7278
+ }
7031
7279
  const sequenceTypeFromSegment = (possibleSegment, referenceGenome) => {
7032
7280
  if (possibleSegment === void 0) {
7033
7281
  return referenceGenome.nucleotideSequences.length === 1 ? "nucleotide" : void 0;
@@ -7094,14 +7342,11 @@ const DeleteIcon = () => {
7094
7342
  }
7095
7343
  );
7096
7344
  };
7097
- const MutationFilter = () => {
7345
+ const MutationFilter = ({ initialValue }) => {
7098
7346
  const referenceGenome = P(ReferenceGenomeContext);
7099
- const [selectedFilters, setSelectedFilters] = p({
7100
- nucleotideMutations: [],
7101
- aminoAcidMutations: [],
7102
- nucleotideInsertions: [],
7103
- aminoAcidInsertions: []
7104
- });
7347
+ const [selectedFilters, setSelectedFilters] = p(
7348
+ getInitialState(initialValue, referenceGenome)
7349
+ );
7105
7350
  const [inputValue, setInputValue] = p("");
7106
7351
  const [isError, setIsError] = p(false);
7107
7352
  const formRef = F(null);
@@ -7147,14 +7392,17 @@ const MutationFilter = () => {
7147
7392
  setIsError(false);
7148
7393
  };
7149
7394
  return /* @__PURE__ */ u$1("div", { class: `rounded-lg border border-gray-300 bg-white p-2`, children: [
7150
- /* @__PURE__ */ u$1(
7151
- SelectedMutationDisplay,
7152
- {
7153
- selectedFilters,
7154
- setSelectedFilters,
7155
- fireChangeEvent
7156
- }
7157
- ),
7395
+ /* @__PURE__ */ u$1("div", { class: "flex justify-between", children: [
7396
+ /* @__PURE__ */ u$1(
7397
+ SelectedMutationDisplay,
7398
+ {
7399
+ selectedFilters,
7400
+ setSelectedFilters,
7401
+ fireChangeEvent
7402
+ }
7403
+ ),
7404
+ /* @__PURE__ */ u$1(Info, { className: "mx-1", content: "Info for mutation filter" })
7405
+ ] }),
7158
7406
  /* @__PURE__ */ u$1("form", { className: "mt-2 w-full", onSubmit: handleSubmit, ref: formRef, children: /* @__PURE__ */ u$1("label", { className: `input flex items-center gap-2 ${isError ? "input-error" : "input-bordered"}`, children: [
7159
7407
  /* @__PURE__ */ u$1(
7160
7408
  "input",
@@ -7163,7 +7411,7 @@ const MutationFilter = () => {
7163
7411
  type: "text",
7164
7412
  value: inputValue,
7165
7413
  onInput: handleInputChange,
7166
- placeholder: "Enter a mutation",
7414
+ placeholder: getPlaceholder(referenceGenome),
7167
7415
  onBlur: handleOnBlur
7168
7416
  }
7169
7417
  ),
@@ -7171,6 +7419,40 @@ const MutationFilter = () => {
7171
7419
  ] }) })
7172
7420
  ] });
7173
7421
  };
7422
+ function getInitialState(initialValue, referenceGenome) {
7423
+ if (initialValue === void 0) {
7424
+ return {
7425
+ nucleotideMutations: [],
7426
+ aminoAcidMutations: [],
7427
+ nucleotideInsertions: [],
7428
+ aminoAcidInsertions: []
7429
+ };
7430
+ }
7431
+ const values = Array.isArray(initialValue) ? initialValue : Object.values(initialValue).flatMap((it) => it);
7432
+ return values.reduce(
7433
+ (selectedFilters, value) => {
7434
+ const parsedMutation = parseAndValidateMutation(value, referenceGenome);
7435
+ if (parsedMutation === null) {
7436
+ return selectedFilters;
7437
+ }
7438
+ return {
7439
+ ...selectedFilters,
7440
+ [parsedMutation.type]: [...selectedFilters[parsedMutation.type], parsedMutation.value]
7441
+ };
7442
+ },
7443
+ {
7444
+ nucleotideMutations: [],
7445
+ aminoAcidMutations: [],
7446
+ nucleotideInsertions: [],
7447
+ aminoAcidInsertions: []
7448
+ }
7449
+ );
7450
+ }
7451
+ function getPlaceholder(referenceGenome) {
7452
+ const segmentPrefix = referenceGenome.nucleotideSequences.length > 1 ? `${referenceGenome.nucleotideSequences[0].name}:` : "";
7453
+ const firstGene = referenceGenome.genes[0].name;
7454
+ return `Enter a mutation (e.g. ${segmentPrefix}A123T, ins_${segmentPrefix}123:AT, ${firstGene}:M123E, ins_${firstGene}:123:ME)`;
7455
+ }
7174
7456
  const SelectedMutationDisplay = ({ selectedFilters, setSelectedFilters, fireChangeEvent }) => {
7175
7457
  const onSelectedRemoved = (mutation, key) => {
7176
7458
  const newSelectedValues = {
@@ -7301,14 +7583,22 @@ var __decorateClass = (decorators, target, key, kind) => {
7301
7583
  return result;
7302
7584
  };
7303
7585
  let MutationFilterComponent = class extends PreactLitAdapter {
7586
+ constructor() {
7587
+ super(...arguments);
7588
+ this.initialValue = void 0;
7589
+ }
7304
7590
  render() {
7305
- return /* @__PURE__ */ u$1(MutationFilter, {});
7591
+ return /* @__PURE__ */ u$1(ReferenceGenomesAwaiter, { children: /* @__PURE__ */ u$1(MutationFilter, { initialValue: this.initialValue }) });
7306
7592
  }
7307
7593
  };
7594
+ __decorateClass([
7595
+ n2()
7596
+ ], MutationFilterComponent.prototype, "initialValue", 2);
7308
7597
  MutationFilterComponent = __decorateClass([
7309
7598
  t$2("gs-mutation-filter")
7310
7599
  ], MutationFilterComponent);
7311
7600
  export {
7601
+ AggregateComponent,
7312
7602
  App,
7313
7603
  DateRangeSelectorComponent,
7314
7604
  LocationFilterComponent,