@genspectrum/dashboard-components 0.15.0 → 0.16.1

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 (86) hide show
  1. package/custom-elements.json +255 -57
  2. package/dist/components.d.ts +49 -32
  3. package/dist/components.js +361 -212
  4. package/dist/components.js.map +1 -1
  5. package/dist/style.css +9 -0
  6. package/dist/util.d.ts +43 -43
  7. package/package.json +1 -1
  8. package/src/preact/ReferenceGenomeContext.ts +16 -1
  9. package/src/preact/aggregatedData/aggregate-bar-chart.tsx +26 -5
  10. package/src/preact/aggregatedData/aggregate.stories.tsx +0 -1
  11. package/src/preact/aggregatedData/aggregate.tsx +5 -1
  12. package/src/preact/components/ReferenceGenomesAwaiter.tsx +1 -6
  13. package/src/preact/components/info.tsx +1 -0
  14. package/src/preact/components/resize-container.tsx +1 -1
  15. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +4 -2
  16. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +0 -1
  17. package/src/preact/mutationComparison/mutation-comparison.tsx +5 -1
  18. package/src/preact/mutationFilter/mutation-filter.stories.tsx +17 -1
  19. package/src/preact/mutationFilter/mutation-filter.tsx +8 -0
  20. package/src/preact/mutations/mutations.stories.tsx +0 -1
  21. package/src/preact/mutations/mutations.tsx +1 -1
  22. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +70 -14
  23. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +30 -7
  24. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +56 -55
  25. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +26 -39
  26. package/src/preact/mutationsOverTime/mutations-over-time.tsx +22 -7
  27. package/src/preact/numberSequencesOverTime/number-sequences-over-time-bar-chart.tsx +8 -3
  28. package/src/preact/numberSequencesOverTime/number-sequences-over-time-line-chart.tsx +8 -3
  29. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -1
  30. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +18 -3
  31. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +48 -35
  32. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +83 -70
  33. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +48 -37
  34. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +0 -3
  35. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +6 -1
  36. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +31 -23
  37. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +0 -1
  38. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +5 -1
  39. package/src/preact/sequencesByLocation/__mockData__/worldAtlas.json +1 -0
  40. package/src/preact/{map → sequencesByLocation}/sequences-by-location-map.tsx +6 -3
  41. package/src/preact/{map → sequencesByLocation}/sequences-by-location-table.tsx +1 -1
  42. package/src/preact/{map → sequencesByLocation}/sequences-by-location.stories.tsx +58 -1
  43. package/src/preact/{map → sequencesByLocation}/sequences-by-location.tsx +10 -1
  44. package/src/preact/shared/aspectRatio/AspectRatio.tsx +13 -0
  45. package/src/preact/shared/charts/getMaintainAspectRatio.ts +3 -0
  46. package/src/preact/statistic/statistics.stories.tsx +0 -1
  47. package/src/preact/statistic/statistics.tsx +4 -4
  48. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +0 -1
  49. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +1 -1
  50. package/src/query/computeMapLocationData.spec.ts +1 -1
  51. package/src/query/computeMapLocationData.ts +1 -1
  52. package/src/query/querySequencesByLocationData.ts +1 -1
  53. package/src/utilEntrypoint.ts +1 -1
  54. package/src/web-components/PreactLitAdapter.tsx +2 -5
  55. package/src/web-components/ResizeContainer.mdx +4 -1
  56. package/src/web-components/gs-app.ts +2 -4
  57. package/src/web-components/visualization/gs-aggregate.stories.ts +13 -6
  58. package/src/web-components/visualization/gs-aggregate.tsx +1 -1
  59. package/src/web-components/visualization/gs-mutation-comparison.stories.ts +8 -1
  60. package/src/web-components/visualization/gs-mutation-comparison.tsx +1 -1
  61. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +24 -1
  62. package/src/web-components/visualization/gs-mutations-over-time.tsx +30 -1
  63. package/src/web-components/visualization/gs-mutations.stories.ts +8 -1
  64. package/src/web-components/visualization/gs-mutations.tsx +1 -1
  65. package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +11 -1
  66. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +1 -1
  67. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +8 -2
  68. package/src/web-components/visualization/gs-prevalence-over-time.tsx +1 -1
  69. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +8 -1
  70. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +1 -1
  71. package/src/web-components/visualization/gs-sequences-by-location.stories.ts +13 -7
  72. package/src/web-components/visualization/gs-sequences-by-location.tsx +6 -3
  73. package/src/web-components/visualization/gs-statistics.stories.ts +0 -1
  74. package/src/web-components/visualization/gs-statistics.tsx +1 -1
  75. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts +9 -1
  76. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +1 -1
  77. package/standalone-bundle/dashboard-components.js +5817 -5706
  78. package/standalone-bundle/dashboard-components.js.map +1 -1
  79. package/standalone-bundle/style.css +1 -1
  80. package/src/preact/map/__mockData__/worldAtlas.json +0 -497127
  81. /package/src/preact/{map → sequencesByLocation}/__mockData__/aggregatedGermany.json +0 -0
  82. /package/src/preact/{map → sequencesByLocation}/__mockData__/aggregatedWorld.json +0 -0
  83. /package/src/preact/{map → sequencesByLocation}/__mockData__/germanyMap.json +0 -0
  84. /package/src/preact/{map → sequencesByLocation}/__mockData__/howToGenerateWorldMap.md +0 -0
  85. /package/src/preact/{map → sequencesByLocation}/leafletStyleModifications.css +0 -0
  86. /package/src/preact/{map → sequencesByLocation}/loadMapSource.tsx +0 -0
@@ -2,7 +2,7 @@ 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$2 from "zod";
5
- import { options, createContext as createContext$1, Fragment, render, Component, createRef, createElement, toChildArray, cloneElement, hydrate } from "preact";
5
+ import { createContext as createContext$1, options, Fragment, render, Component, createRef, createElement, toChildArray, cloneElement, hydrate } from "preact";
6
6
  import { Grid } from "gridjs";
7
7
  import { Chart, registerables, Scale, BarController } from "chart.js";
8
8
  import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn";
@@ -539,6 +539,15 @@ const substitutionsOrDeletionsEndpoint = (lapisUrl, sequenceType) => {
539
539
  return sequenceType === "amino acid" ? `${lapisUrl}/sample/aminoAcidMutations` : `${lapisUrl}/sample/nucleotideMutations`;
540
540
  };
541
541
  const referenceGenomeEndpoint = (lapisUrl) => `${lapisUrl}/sample/referenceGenome`;
542
+ const UNINITIALIZED_SEQUENCE = "__uninitialized__";
543
+ const INITIAL_REFERENCE_GENOMES = {
544
+ nucleotideSequences: [{ name: UNINITIALIZED_SEQUENCE, sequence: "" }],
545
+ genes: []
546
+ };
547
+ const ReferenceGenomeContext = createContext$1(INITIAL_REFERENCE_GENOMES);
548
+ function isNotInitialized(referenceGenome) {
549
+ return referenceGenome.genes.length === 0 && referenceGenome.nucleotideSequences.length === 1 && referenceGenome.nucleotideSequences[0].name === UNINITIALIZED_SEQUENCE;
550
+ }
542
551
  var __defProp$g = Object.defineProperty;
543
552
  var __getOwnPropDesc$f = Object.getOwnPropertyDescriptor;
544
553
  var __decorateClass$g = (decorators, target, key, kind) => {
@@ -554,10 +563,7 @@ let AppComponent = class extends LitElement {
554
563
  constructor() {
555
564
  super(...arguments);
556
565
  this.lapis = "";
557
- this.referenceGenome = {
558
- nucleotideSequences: [],
559
- genes: []
560
- };
566
+ this.referenceGenome = INITIAL_REFERENCE_GENOMES;
561
567
  this.updateReferenceGenome = new Task(this, {
562
568
  task: async () => {
563
569
  const lapisUrl = lapisUrlSchema.parse(this.lapis);
@@ -954,7 +960,8 @@ const GsChart = ({ configuration }) => {
954
960
  Chart.register(...registerables, VennDiagramController, ArcSlice);
955
961
  const MutationComparisonVenn = ({
956
962
  data,
957
- proportionInterval
963
+ proportionInterval,
964
+ maintainAspectRatio
958
965
  }) => {
959
966
  const [selectedDatasetIndex, setSelectedDatasetIndex] = h(null);
960
967
  const sets = T$1(
@@ -978,7 +985,7 @@ const MutationComparisonVenn = ({
978
985
  type: "venn",
979
986
  data: sets,
980
987
  options: {
981
- maintainAspectRatio: false,
988
+ maintainAspectRatio,
982
989
  scales: {
983
990
  x: {
984
991
  ticks: {
@@ -1021,7 +1028,7 @@ const MutationComparisonVenn = ({
1021
1028
  }
1022
1029
  }
1023
1030
  }),
1024
- [sets]
1031
+ [maintainAspectRatio, sets]
1025
1032
  );
1026
1033
  if (data.content.length > 5) {
1027
1034
  return /* @__PURE__ */ u$1("div", { children: "Too many datasets to display. Maximum are five. " });
@@ -1374,7 +1381,7 @@ function componentParametersToCode(componentName, params, lapisUrl) {
1374
1381
  return typeof value === "object" ? JSON.stringify(value) : value;
1375
1382
  };
1376
1383
  const attributes = indentLines(
1377
- Object.entries(params).map(([key, value]) => `${key}='${stringifyIfNeeded(value)}'`).join("\n"),
1384
+ Object.entries(params).filter(([_2, value]) => value !== void 0).map(([key, value]) => `${key}='${stringifyIfNeeded(value)}'`).join("\n"),
1378
1385
  4
1379
1386
  );
1380
1387
  return `<gs-app lapis="${lapisUrl}">
@@ -2018,7 +2025,6 @@ const ProportionSelectorDropdown = ({
2018
2025
  }
2019
2026
  ) }) });
2020
2027
  };
2021
- const ReferenceGenomeContext = createContext$1({ nucleotideSequences: [], genes: [] });
2022
2028
  const SegmentSelector = ({
2023
2029
  displayedSegments,
2024
2030
  setDisplayedSegments
@@ -2084,6 +2090,9 @@ const Tabs = ({ tabs, toolbar }) => {
2084
2090
  /* @__PURE__ */ u$1("div", { className: `p-2 flex-grow overflow-scroll border-2 border-gray-100 rounded-b-md rounded-tr-md`, children: tabs.map((tab) => /* @__PURE__ */ u$1("div", { className: "h-full", hidden: activeTab !== tab.title, children: tab.content }, tab.title)) })
2085
2091
  ] });
2086
2092
  };
2093
+ function getMaintainAspectRatio(height) {
2094
+ return height === void 0 || height === "";
2095
+ }
2087
2096
  function useQuery(fetchDataCallback, dependencies) {
2088
2097
  const [data, setData] = h(null);
2089
2098
  const [error, setError] = h(null);
@@ -2114,7 +2123,7 @@ function useQuery(fetchDataCallback, dependencies) {
2114
2123
  const mutationComparisonViewSchema = z$2.union([z$2.literal(views.table), z$2.literal(views.venn)]);
2115
2124
  const mutationComparisonPropsSchema = z$2.object({
2116
2125
  width: z$2.string(),
2117
- height: z$2.string(),
2126
+ height: z$2.string().optional(),
2118
2127
  lapisFilters: z$2.array(namedLapisFilterSchema).min(1),
2119
2128
  sequenceType: sequenceTypeSchema,
2120
2129
  views: z$2.array(mutationComparisonViewSchema),
@@ -2153,6 +2162,7 @@ const MutationComparisonTabs = ({ data, originalComponentProps }) => {
2153
2162
  () => filterMutationData(data, displayedSegments, displayedMutationTypes),
2154
2163
  [data, displayedSegments, displayedMutationTypes]
2155
2164
  );
2165
+ const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
2156
2166
  const getTab = (view) => {
2157
2167
  switch (view) {
2158
2168
  case "table":
@@ -2174,7 +2184,8 @@ const MutationComparisonTabs = ({ data, originalComponentProps }) => {
2174
2184
  MutationComparisonVenn,
2175
2185
  {
2176
2186
  data: { content: filteredData },
2177
- proportionInterval
2187
+ proportionInterval,
2188
+ maintainAspectRatio
2178
2189
  }
2179
2190
  )
2180
2191
  };
@@ -4955,6 +4966,9 @@ input.tab:checked + .tab-content,
4955
4966
  .relative {
4956
4967
  position: relative;
4957
4968
  }
4969
+ .inset-0 {
4970
+ inset: 0px;
4971
+ }
4958
4972
  .-right-3 {
4959
4973
  right: -0.75rem;
4960
4974
  }
@@ -5138,6 +5152,9 @@ input.tab:checked + .tab-content,
5138
5152
  .min-w-32 {
5139
5153
  min-width: 8rem;
5140
5154
  }
5155
+ .min-w-\\[180px\\] {
5156
+ min-width: 180px;
5157
+ }
5141
5158
  .min-w-\\[7\\.5rem\\] {
5142
5159
  min-width: 7.5rem;
5143
5160
  }
@@ -5221,6 +5238,9 @@ input.tab:checked + .tab-content,
5221
5238
  .whitespace-nowrap {
5222
5239
  white-space: nowrap;
5223
5240
  }
5241
+ .text-wrap {
5242
+ text-wrap: wrap;
5243
+ }
5224
5244
  .text-nowrap {
5225
5245
  text-wrap: nowrap;
5226
5246
  }
@@ -5559,10 +5579,7 @@ const _PreactLitAdapter = class _PreactLitAdapter extends ReactiveElement {
5559
5579
  constructor() {
5560
5580
  super(...arguments);
5561
5581
  this.lapis = "";
5562
- this.referenceGenome = {
5563
- nucleotideSequences: [],
5564
- genes: []
5565
- };
5582
+ this.referenceGenome = INITIAL_REFERENCE_GENOMES;
5566
5583
  }
5567
5584
  update(changedProperties) {
5568
5585
  const vdom = /* @__PURE__ */ u$1(LapisUrlContextProvider, { value: this.lapis, children: /* @__PURE__ */ u$1(ReferenceGenomeContext.Provider, { value: this.referenceGenome, children: this.render() }) });
@@ -5600,7 +5617,7 @@ let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles
5600
5617
  this.sequenceType = "nucleotide";
5601
5618
  this.views = ["table"];
5602
5619
  this.width = "100%";
5603
- this.height = "700px";
5620
+ this.height = void 0;
5604
5621
  this.pageSize = false;
5605
5622
  }
5606
5623
  render() {
@@ -5983,7 +6000,7 @@ const mutationsPropsSchema = z$2.object({
5983
6000
  views: mutationsViewSchema.array(),
5984
6001
  pageSize: z$2.union([z$2.boolean(), z$2.number()]),
5985
6002
  width: z$2.string(),
5986
- height: z$2.string()
6003
+ height: z$2.string().optional()
5987
6004
  });
5988
6005
  const Mutations = (componentProps) => {
5989
6006
  const { width, height } = componentProps;
@@ -6168,7 +6185,7 @@ let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
6168
6185
  this.sequenceType = "nucleotide";
6169
6186
  this.views = ["table", "grid"];
6170
6187
  this.width = "100%";
6171
- this.height = "700px";
6188
+ this.height = void 0;
6172
6189
  this.pageSize = false;
6173
6190
  }
6174
6191
  render() {
@@ -6326,42 +6343,51 @@ function getYAxisScale(scaleType) {
6326
6343
  }
6327
6344
  }
6328
6345
  Chart.register(...registerables, LogitScale, BarWithErrorBarsController, BarWithErrorBar);
6346
+ const NO_DATA$2 = "noData";
6329
6347
  const PrevalenceOverTimeBarChart = ({
6330
6348
  data,
6331
6349
  yAxisScaleType,
6332
6350
  confidenceIntervalMethod,
6333
- yAxisMaxConfig
6351
+ yAxisMaxConfig,
6352
+ maintainAspectRatio
6334
6353
  }) => {
6335
- const nullFirstData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
6354
+ const config = T$1(() => {
6355
+ const nullFirstData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
6356
+ return {
6357
+ content: variantData.content.sort(sortNullToBeginningThenByDate),
6358
+ displayName: variantData.displayName
6359
+ };
6360
+ });
6361
+ if (nullFirstData.length === 0) {
6362
+ return NO_DATA$2;
6363
+ }
6364
+ const datasets2 = nullFirstData.map(
6365
+ (graphData, index) => getDataset$1(graphData, index, confidenceIntervalMethod)
6366
+ );
6367
+ const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nullFirstData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
6336
6368
  return {
6337
- content: variantData.content.sort(sortNullToBeginningThenByDate),
6338
- displayName: variantData.displayName
6339
- };
6340
- });
6341
- if (nullFirstData.length === 0) {
6342
- return /* @__PURE__ */ u$1(NoDataDisplay, {});
6343
- }
6344
- const datasets2 = nullFirstData.map((graphData, index) => getDataset$1(graphData, index, confidenceIntervalMethod));
6345
- const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nullFirstData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
6346
- const config = {
6347
- type: BarWithErrorBarsController.id,
6348
- data: {
6349
- datasets: datasets2
6350
- },
6351
- options: {
6352
- maintainAspectRatio: false,
6353
- animation: false,
6354
- scales: {
6355
- y: { ...getYAxisScale(yAxisScaleType), max: maxY }
6369
+ type: BarWithErrorBarsController.id,
6370
+ data: {
6371
+ datasets: datasets2
6356
6372
  },
6357
- plugins: {
6358
- legend: {
6359
- display: false
6373
+ options: {
6374
+ maintainAspectRatio,
6375
+ animation: false,
6376
+ scales: {
6377
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY }
6360
6378
  },
6361
- tooltip: tooltip$2(confidenceIntervalMethod)
6379
+ plugins: {
6380
+ legend: {
6381
+ display: false
6382
+ },
6383
+ tooltip: tooltip$2(confidenceIntervalMethod)
6384
+ }
6362
6385
  }
6363
- }
6364
- };
6386
+ };
6387
+ }, [data, yAxisScaleType, confidenceIntervalMethod, yAxisMaxConfig, maintainAspectRatio]);
6388
+ if (config === NO_DATA$2) {
6389
+ return /* @__PURE__ */ u$1(NoDataDisplay, {});
6390
+ }
6365
6391
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
6366
6392
  };
6367
6393
  const getDataset$1 = (prevalenceOverTimeVariant, index, confidenceIntervalMethod) => {
@@ -7356,120 +7382,134 @@ function getMinMaxNumber(values) {
7356
7382
  return [min, max];
7357
7383
  }
7358
7384
  Chart.register(...registerables, LogitScale);
7385
+ const NO_DATA$1 = "noData";
7359
7386
  const PrevalenceOverTimeBubbleChart = ({
7360
7387
  data,
7361
7388
  yAxisScaleType,
7362
- yAxisMaxConfig
7389
+ yAxisMaxConfig,
7390
+ maintainAspectRatio
7363
7391
  }) => {
7364
- const nonNullDateRangeData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
7365
- return {
7366
- content: variantData.content.filter((dataPoint) => dataPoint.dateRange !== null),
7367
- displayName: variantData.displayName
7392
+ const config = T$1(() => {
7393
+ const nonNullDateRangeData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
7394
+ return {
7395
+ content: variantData.content.filter((dataPoint) => dataPoint.dateRange !== null),
7396
+ displayName: variantData.displayName
7397
+ };
7398
+ });
7399
+ if (nonNullDateRangeData.length === 0) {
7400
+ return NO_DATA$1;
7401
+ }
7402
+ const firstDate = nonNullDateRangeData[0].content[0].dateRange;
7403
+ const total = nonNullDateRangeData.map((graphData) => graphData.content.map((dataPoint) => dataPoint.total)).flat();
7404
+ const [minTotal, maxTotal] = getMinMaxNumber(total);
7405
+ const scaleBubble = (value) => {
7406
+ return (value - minTotal) / (maxTotal - minTotal) * 4.5 + 0.5;
7368
7407
  };
7369
- });
7370
- if (nonNullDateRangeData.length === 0) {
7371
- return /* @__PURE__ */ u$1(NoDataDisplay, {});
7372
- }
7373
- const firstDate = nonNullDateRangeData[0].content[0].dateRange;
7374
- const total = nonNullDateRangeData.map((graphData) => graphData.content.map((dataPoint) => dataPoint.total)).flat();
7375
- const [minTotal, maxTotal] = getMinMaxNumber(total);
7376
- const scaleBubble = (value) => {
7377
- return (value - minTotal) / (maxTotal - minTotal) * 4.5 + 0.5;
7378
- };
7379
- const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nonNullDateRangeData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
7380
- const config = {
7381
- type: "bubble",
7382
- data: {
7383
- datasets: nonNullDateRangeData.map((graphData, index) => ({
7384
- label: graphData.displayName,
7385
- data: graphData.content.filter((dataPoint) => dataPoint.dateRange !== null).map((dataPoint) => ({
7386
- x: minusTemporal(dataPoint.dateRange, firstDate),
7387
- y: dataPoint.prevalence,
7388
- r: scaleBubble(dataPoint.total)
7389
- })),
7390
- borderWidth: 1,
7391
- pointRadius: 0,
7392
- backgroundColor: singleGraphColorRGBAById(index, 0.3),
7393
- borderColor: singleGraphColorRGBAById(index)
7394
- }))
7395
- },
7396
- options: {
7397
- animation: false,
7398
- maintainAspectRatio: false,
7399
- scales: {
7400
- x: {
7401
- ticks: {
7402
- callback: (value) => addUnit(firstDate, value).toString()
7403
- }
7404
- },
7405
- y: { ...getYAxisScale(yAxisScaleType), max: maxY }
7408
+ const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nonNullDateRangeData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
7409
+ return {
7410
+ type: "bubble",
7411
+ data: {
7412
+ datasets: nonNullDateRangeData.map((graphData, index) => ({
7413
+ label: graphData.displayName,
7414
+ data: graphData.content.filter((dataPoint) => dataPoint.dateRange !== null).map((dataPoint) => ({
7415
+ x: minusTemporal(dataPoint.dateRange, firstDate),
7416
+ y: dataPoint.prevalence,
7417
+ r: scaleBubble(dataPoint.total)
7418
+ })),
7419
+ borderWidth: 1,
7420
+ pointRadius: 0,
7421
+ backgroundColor: singleGraphColorRGBAById(index, 0.3),
7422
+ borderColor: singleGraphColorRGBAById(index)
7423
+ }))
7406
7424
  },
7407
- plugins: {
7408
- legend: {
7409
- display: false
7425
+ options: {
7426
+ animation: false,
7427
+ maintainAspectRatio,
7428
+ scales: {
7429
+ x: {
7430
+ ticks: {
7431
+ callback: (value) => addUnit(firstDate, value).toString()
7432
+ }
7433
+ },
7434
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY }
7410
7435
  },
7411
- tooltip: {
7412
- mode: "index",
7413
- intersect: false,
7414
- callbacks: {
7415
- title: (context) => {
7416
- var _a;
7417
- const dataset = nonNullDateRangeData[context[0].datasetIndex];
7418
- const dataPoint = dataset.content[context[0].dataIndex];
7419
- return (_a = dataPoint.dateRange) == null ? void 0 : _a.toString();
7420
- },
7421
- label: (context) => {
7422
- const dataset = nonNullDateRangeData[context.datasetIndex];
7423
- const dataPoint = dataset.content[context.dataIndex];
7424
- const percentage = (dataPoint.prevalence * 100).toFixed(2);
7425
- const count = dataPoint.count.toFixed(0);
7426
- const total2 = dataPoint.total.toFixed(0);
7427
- return `${dataset.displayName}: ${percentage}%, ${count}/${total2} samples`;
7436
+ plugins: {
7437
+ legend: {
7438
+ display: false
7439
+ },
7440
+ tooltip: {
7441
+ mode: "index",
7442
+ intersect: false,
7443
+ callbacks: {
7444
+ title: (context) => {
7445
+ var _a;
7446
+ const dataset = nonNullDateRangeData[context[0].datasetIndex];
7447
+ const dataPoint = dataset.content[context[0].dataIndex];
7448
+ return (_a = dataPoint.dateRange) == null ? void 0 : _a.toString();
7449
+ },
7450
+ label: (context) => {
7451
+ const dataset = nonNullDateRangeData[context.datasetIndex];
7452
+ const dataPoint = dataset.content[context.dataIndex];
7453
+ const percentage = (dataPoint.prevalence * 100).toFixed(2);
7454
+ const count = dataPoint.count.toFixed(0);
7455
+ const total2 = dataPoint.total.toFixed(0);
7456
+ return `${dataset.displayName}: ${percentage}%, ${count}/${total2} samples`;
7457
+ }
7428
7458
  }
7429
7459
  }
7430
7460
  }
7431
7461
  }
7432
- }
7433
- };
7462
+ };
7463
+ }, [data, maintainAspectRatio, yAxisMaxConfig, yAxisScaleType]);
7464
+ if (config === NO_DATA$1) {
7465
+ return /* @__PURE__ */ u$1(NoDataDisplay, {});
7466
+ }
7434
7467
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
7435
7468
  };
7436
7469
  Chart.register(...registerables, LogitScale);
7470
+ const NO_DATA = "noData";
7437
7471
  const PrevalenceOverTimeLineChart = ({
7438
7472
  data,
7439
7473
  yAxisScaleType,
7440
7474
  confidenceIntervalMethod,
7441
- yAxisMaxConfig
7475
+ yAxisMaxConfig,
7476
+ maintainAspectRatio
7442
7477
  }) => {
7443
- const nonNullDateRangeData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
7478
+ const config = T$1(() => {
7479
+ const nonNullDateRangeData = data.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0).map((variantData) => {
7480
+ return {
7481
+ content: variantData.content.filter((dataPoint) => dataPoint.dateRange !== null),
7482
+ displayName: variantData.displayName
7483
+ };
7484
+ });
7485
+ if (nonNullDateRangeData.length === 0) {
7486
+ return NO_DATA;
7487
+ }
7488
+ const datasets2 = nonNullDateRangeData.map((graphData, index) => getDataset(graphData, index, confidenceIntervalMethod)).flat();
7489
+ const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nonNullDateRangeData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
7444
7490
  return {
7445
- content: variantData.content.filter((dataPoint) => dataPoint.dateRange !== null),
7446
- displayName: variantData.displayName
7447
- };
7448
- });
7449
- if (nonNullDateRangeData.length === 0) {
7450
- return /* @__PURE__ */ u$1(NoDataDisplay, {});
7451
- }
7452
- const datasets2 = nonNullDateRangeData.map((graphData, index) => getDataset(graphData, index, confidenceIntervalMethod)).flat();
7453
- const maxY = yAxisScaleType !== "logit" ? getYAxisMax(maxInData(nonNullDateRangeData), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
7454
- const config = {
7455
- type: "line",
7456
- data: {
7457
- datasets: datasets2
7458
- },
7459
- options: {
7460
- animation: false,
7461
- maintainAspectRatio: false,
7462
- scales: {
7463
- y: { ...getYAxisScale(yAxisScaleType), max: maxY }
7491
+ type: "line",
7492
+ data: {
7493
+ datasets: datasets2
7464
7494
  },
7465
- plugins: {
7466
- legend: {
7467
- display: false
7495
+ options: {
7496
+ animation: false,
7497
+ maintainAspectRatio,
7498
+ scales: {
7499
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY }
7468
7500
  },
7469
- tooltip: tooltip$1(confidenceIntervalMethod)
7501
+ plugins: {
7502
+ legend: {
7503
+ display: false
7504
+ },
7505
+ tooltip: tooltip$1(confidenceIntervalMethod)
7506
+ }
7470
7507
  }
7471
- }
7472
- };
7508
+ };
7509
+ }, [data, yAxisScaleType, confidenceIntervalMethod, yAxisMaxConfig, maintainAspectRatio]);
7510
+ if (config === NO_DATA) {
7511
+ return /* @__PURE__ */ u$1(NoDataDisplay, {});
7512
+ }
7473
7513
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
7474
7514
  };
7475
7515
  const getDataset = (prevalenceOverTimeVariant, dataIndex, confidenceIntervalMethod) => {
@@ -7855,7 +7895,7 @@ const prevalenceOverTimeViewSchema = z$2.union([
7855
7895
  ]);
7856
7896
  const prevalenceOverTimePropsSchema = z$2.object({
7857
7897
  width: z$2.string(),
7858
- height: z$2.string(),
7898
+ height: z$2.string().optional(),
7859
7899
  numeratorFilters: z$2.array(namedLapisFilterSchema).min(1),
7860
7900
  denominatorFilter: lapisFilterSchema,
7861
7901
  granularity: temporalGranularitySchema,
@@ -7912,6 +7952,7 @@ const PrevalenceOverTimeTabs = ({ data, ...componentProps }) => {
7912
7952
  });
7913
7953
  }, [confidenceIntervalMethods]);
7914
7954
  const yAxisMaxConfig = { linear: yAxisMaxLinear, logarithmic: yAxisMaxLogarithmic };
7955
+ const maintainAspectRatio = getMaintainAspectRatio(componentProps.height);
7915
7956
  const getTab = (view) => {
7916
7957
  switch (view) {
7917
7958
  case "bar":
@@ -7923,7 +7964,8 @@ const PrevalenceOverTimeTabs = ({ data, ...componentProps }) => {
7923
7964
  data,
7924
7965
  yAxisScaleType,
7925
7966
  confidenceIntervalMethod,
7926
- yAxisMaxConfig
7967
+ yAxisMaxConfig,
7968
+ maintainAspectRatio
7927
7969
  }
7928
7970
  )
7929
7971
  };
@@ -7936,7 +7978,8 @@ const PrevalenceOverTimeTabs = ({ data, ...componentProps }) => {
7936
7978
  data,
7937
7979
  yAxisScaleType,
7938
7980
  confidenceIntervalMethod,
7939
- yAxisMaxConfig
7981
+ yAxisMaxConfig,
7982
+ maintainAspectRatio
7940
7983
  }
7941
7984
  )
7942
7985
  };
@@ -7948,7 +7991,8 @@ const PrevalenceOverTimeTabs = ({ data, ...componentProps }) => {
7948
7991
  {
7949
7992
  data,
7950
7993
  yAxisScaleType,
7951
- yAxisMaxConfig
7994
+ yAxisMaxConfig,
7995
+ maintainAspectRatio
7952
7996
  }
7953
7997
  )
7954
7998
  };
@@ -8053,7 +8097,7 @@ let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
8053
8097
  this.views = ["bar", "line", "bubble", "table"];
8054
8098
  this.confidenceIntervalMethods = ["none", "wilson"];
8055
8099
  this.width = "100%";
8056
- this.height = "700px";
8100
+ this.height = void 0;
8057
8101
  this.lapisDateField = "";
8058
8102
  this.pageSize = false;
8059
8103
  this.yAxisMaxLinear = 1;
@@ -8119,28 +8163,35 @@ PrevalenceOverTimeComponent = __decorateClass$c([
8119
8163
  t$3("gs-prevalence-over-time")
8120
8164
  ], PrevalenceOverTimeComponent);
8121
8165
  Chart.register(...registerables, LogitScale);
8122
- const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType, yAxisMaxConfig }) => {
8123
- const maxY = yAxisScaleType !== "logit" ? getYAxisMax(Math.max(...data.proportion), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
8124
- const config = {
8125
- type: "line",
8126
- data: {
8127
- labels: data.t,
8128
- datasets: datasets(data)
8129
- },
8130
- options: {
8131
- maintainAspectRatio: false,
8132
- animation: false,
8133
- scales: {
8134
- y: { ...getYAxisScale(yAxisScaleType), max: maxY }
8166
+ const RelativeGrowthAdvantageChart = ({
8167
+ data,
8168
+ yAxisScaleType,
8169
+ yAxisMaxConfig,
8170
+ maintainAspectRatio
8171
+ }) => {
8172
+ const config = T$1(() => {
8173
+ const maxY = yAxisScaleType !== "logit" ? getYAxisMax(Math.max(...data.proportion), yAxisMaxConfig == null ? void 0 : yAxisMaxConfig[yAxisScaleType]) : void 0;
8174
+ return {
8175
+ type: "line",
8176
+ data: {
8177
+ labels: data.t,
8178
+ datasets: datasets(data)
8135
8179
  },
8136
- plugins: {
8137
- legend: {
8138
- display: false
8180
+ options: {
8181
+ maintainAspectRatio,
8182
+ animation: false,
8183
+ scales: {
8184
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY }
8139
8185
  },
8140
- tooltip: tooltip()
8186
+ plugins: {
8187
+ legend: {
8188
+ display: false
8189
+ },
8190
+ tooltip: tooltip()
8191
+ }
8141
8192
  }
8142
- }
8143
- };
8193
+ };
8194
+ }, [data, yAxisScaleType, yAxisMaxConfig, maintainAspectRatio]);
8144
8195
  return /* @__PURE__ */ u$1("div", { className: "flex h-full flex-col", children: [
8145
8196
  /* @__PURE__ */ u$1(
8146
8197
  RelativeGrowthAdvantageDisplay,
@@ -8348,7 +8399,7 @@ function toYearMonthDay(d2) {
8348
8399
  const relativeGrowthAdvantageViewSchema = z$2.literal(views.line);
8349
8400
  const relativeGrowthAdvantagePropsSchema = z$2.object({
8350
8401
  width: z$2.string(),
8351
- height: z$2.string(),
8402
+ height: z$2.string().optional(),
8352
8403
  numeratorFilter: lapisFilterSchema,
8353
8404
  denominatorFilter: lapisFilterSchema,
8354
8405
  generationTime: z$2.number(),
@@ -8398,6 +8449,7 @@ const RelativeGrowthAdvantageTabs = ({
8398
8449
  setYAxisScaleType,
8399
8450
  originalComponentProps
8400
8451
  }) => {
8452
+ const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
8401
8453
  const getTab = (view) => {
8402
8454
  switch (view) {
8403
8455
  case "line":
@@ -8415,7 +8467,8 @@ const RelativeGrowthAdvantageTabs = ({
8415
8467
  yAxisMaxConfig: {
8416
8468
  linear: originalComponentProps.yAxisMaxLinear,
8417
8469
  logarithmic: originalComponentProps.yAxisMaxLogarithmic
8418
- }
8470
+ },
8471
+ maintainAspectRatio
8419
8472
  }
8420
8473
  )
8421
8474
  };
@@ -8494,7 +8547,7 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
8494
8547
  this.generationTime = 7;
8495
8548
  this.views = ["line"];
8496
8549
  this.width = "100%";
8497
- this.height = "700px";
8550
+ this.height = void 0;
8498
8551
  this.lapisDateField = "";
8499
8552
  this.yAxisMaxLinear = 1;
8500
8553
  this.yAxisMaxLogarithmic = 1;
@@ -8604,7 +8657,12 @@ const AggregateTable = ({
8604
8657
  return /* @__PURE__ */ u$1(Table, { data: sortedData, columns: headers, pageSize });
8605
8658
  };
8606
8659
  Chart.register(...registerables, BarController);
8607
- const AggregateBarChart = ({ data, fields, maxNumberOfBars }) => {
8660
+ const AggregateBarChart = ({
8661
+ data,
8662
+ fields,
8663
+ maxNumberOfBars,
8664
+ maintainAspectRatio
8665
+ }) => {
8608
8666
  if (data.length === 0) {
8609
8667
  return /* @__PURE__ */ u$1(NoDataDisplay, {});
8610
8668
  }
@@ -8620,9 +8678,22 @@ const AggregateBarChart = ({ data, fields, maxNumberOfBars }) => {
8620
8678
  `Cannot display a bar chart when the "fields" attribute of this component contains more than two values. Got the fields: ${fields.join(", ")}. This must be fixed by the administrator of this page.`
8621
8679
  );
8622
8680
  }
8623
- return /* @__PURE__ */ u$1(AggregateBarChartInner, { data, fields, maxNumberOfBars });
8681
+ return /* @__PURE__ */ u$1(
8682
+ AggregateBarChartInner,
8683
+ {
8684
+ data,
8685
+ fields,
8686
+ maxNumberOfBars,
8687
+ maintainAspectRatio
8688
+ }
8689
+ );
8624
8690
  };
8625
- const AggregateBarChartInner = ({ data, fields, maxNumberOfBars }) => {
8691
+ const AggregateBarChartInner = ({
8692
+ data,
8693
+ fields,
8694
+ maxNumberOfBars,
8695
+ maintainAspectRatio
8696
+ }) => {
8626
8697
  const config = T$1(() => {
8627
8698
  const { datasets: datasets2, countsOfEachBar } = getDatasets$2(fields, maxNumberOfBars, data);
8628
8699
  return {
@@ -8631,7 +8702,7 @@ const AggregateBarChartInner = ({ data, fields, maxNumberOfBars }) => {
8631
8702
  datasets: datasets2
8632
8703
  },
8633
8704
  options: {
8634
- maintainAspectRatio: false,
8705
+ maintainAspectRatio,
8635
8706
  animation: false,
8636
8707
  indexAxis: "y",
8637
8708
  scales: {
@@ -8639,7 +8710,10 @@ const AggregateBarChartInner = ({ data, fields, maxNumberOfBars }) => {
8639
8710
  stacked: true
8640
8711
  },
8641
8712
  y: {
8642
- stacked: true
8713
+ stacked: true,
8714
+ ticks: {
8715
+ autoSkip: false
8716
+ }
8643
8717
  }
8644
8718
  },
8645
8719
  plugins: {
@@ -8661,7 +8735,7 @@ const AggregateBarChartInner = ({ data, fields, maxNumberOfBars }) => {
8661
8735
  }
8662
8736
  }
8663
8737
  };
8664
- }, [data, fields, maxNumberOfBars]);
8738
+ }, [data, fields, maintainAspectRatio, maxNumberOfBars]);
8665
8739
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
8666
8740
  };
8667
8741
  function getDatasets$2(fields, maxNumberOfBars, data) {
@@ -8731,7 +8805,7 @@ const aggregatePropsSchema = z$2.object({
8731
8805
  initialSortDirection: z$2.union([z$2.literal("ascending"), z$2.literal("descending")]),
8732
8806
  pageSize: z$2.union([z$2.boolean(), z$2.number()]),
8733
8807
  width: z$2.string(),
8734
- height: z$2.string(),
8808
+ height: z$2.string().optional(),
8735
8809
  maxNumberOfBars: z$2.number()
8736
8810
  });
8737
8811
  const Aggregate = (componentProps) => {
@@ -8757,6 +8831,7 @@ const AggregateInner = (componentProps) => {
8757
8831
  return /* @__PURE__ */ u$1(AggregatedDataTabs, { data, originalComponentProps: componentProps });
8758
8832
  };
8759
8833
  const AggregatedDataTabs = ({ data, originalComponentProps }) => {
8834
+ const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
8760
8835
  const getTab = (view) => {
8761
8836
  switch (view) {
8762
8837
  case views.table:
@@ -8781,7 +8856,8 @@ const AggregatedDataTabs = ({ data, originalComponentProps }) => {
8781
8856
  {
8782
8857
  data,
8783
8858
  fields: originalComponentProps.fields,
8784
- maxNumberOfBars: originalComponentProps.maxNumberOfBars
8859
+ maxNumberOfBars: originalComponentProps.maxNumberOfBars,
8860
+ maintainAspectRatio
8785
8861
  }
8786
8862
  )
8787
8863
  };
@@ -8827,7 +8903,7 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
8827
8903
  this.views = ["table"];
8828
8904
  this.lapisFilter = {};
8829
8905
  this.width = "100%";
8830
- this.height = "700px";
8906
+ this.height = void 0;
8831
8907
  this.initialSortField = "count";
8832
8908
  this.initialSortDirection = "descending";
8833
8909
  this.pageSize = false;
@@ -8911,7 +8987,11 @@ const getNumberOfSequencesOverTimeTableData = (data, dateRangeKey) => {
8911
8987
  });
8912
8988
  };
8913
8989
  Chart.register(...registerables);
8914
- const NumberSequencesOverTimeBarChart = ({ data, yAxisScaleType }) => {
8990
+ const NumberSequencesOverTimeBarChart = ({
8991
+ data,
8992
+ yAxisScaleType,
8993
+ maintainAspectRatio
8994
+ }) => {
8915
8995
  const config = T$1(
8916
8996
  () => ({
8917
8997
  type: "bar",
@@ -8919,7 +8999,7 @@ const NumberSequencesOverTimeBarChart = ({ data, yAxisScaleType }) => {
8919
8999
  datasets: getDatasets$1(data)
8920
9000
  },
8921
9001
  options: {
8922
- maintainAspectRatio: false,
9002
+ maintainAspectRatio,
8923
9003
  animation: false,
8924
9004
  scales: {
8925
9005
  y: {
@@ -8937,7 +9017,7 @@ const NumberSequencesOverTimeBarChart = ({ data, yAxisScaleType }) => {
8937
9017
  }
8938
9018
  }
8939
9019
  }),
8940
- [data, yAxisScaleType]
9020
+ [data, maintainAspectRatio, yAxisScaleType]
8941
9021
  );
8942
9022
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
8943
9023
  };
@@ -8957,7 +9037,11 @@ const getDatasets$1 = (data) => {
8957
9037
  );
8958
9038
  };
8959
9039
  Chart.register(...registerables);
8960
- const NumberSequencesOverTimeLineChart = ({ data, yAxisScaleType }) => {
9040
+ const NumberSequencesOverTimeLineChart = ({
9041
+ data,
9042
+ yAxisScaleType,
9043
+ maintainAspectRatio
9044
+ }) => {
8961
9045
  const config = T$1(
8962
9046
  () => ({
8963
9047
  type: "line",
@@ -8965,7 +9049,7 @@ const NumberSequencesOverTimeLineChart = ({ data, yAxisScaleType }) => {
8965
9049
  datasets: getDatasets(data)
8966
9050
  },
8967
9051
  options: {
8968
- maintainAspectRatio: false,
9052
+ maintainAspectRatio,
8969
9053
  animation: false,
8970
9054
  scales: {
8971
9055
  y: {
@@ -8983,7 +9067,7 @@ const NumberSequencesOverTimeLineChart = ({ data, yAxisScaleType }) => {
8983
9067
  }
8984
9068
  }
8985
9069
  }),
8986
- [data, yAxisScaleType]
9070
+ [data, maintainAspectRatio, yAxisScaleType]
8987
9071
  );
8988
9072
  return /* @__PURE__ */ u$1(GsChart, { configuration: config });
8989
9073
  };
@@ -9042,7 +9126,7 @@ const numberSequencesOverTimeViewSchema = z$2.union([
9042
9126
  ]);
9043
9127
  const numberSequencesOverTimePropsSchema = z$2.object({
9044
9128
  width: z$2.string(),
9045
- height: z$2.string(),
9129
+ height: z$2.string().optional(),
9046
9130
  lapisFilters: z$2.array(namedLapisFilterSchema).min(1),
9047
9131
  lapisDateField: z$2.string().min(1),
9048
9132
  views: z$2.array(numberSequencesOverTimeViewSchema),
@@ -9075,17 +9159,32 @@ const NumberSequencesOverTimeInner = (componentProps) => {
9075
9159
  };
9076
9160
  const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }) => {
9077
9161
  const [yAxisScaleType, setYAxisScaleType] = h("linear");
9162
+ const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
9078
9163
  const getTab = (view) => {
9079
9164
  switch (view) {
9080
9165
  case "bar":
9081
9166
  return {
9082
9167
  title: "Bar",
9083
- content: /* @__PURE__ */ u$1(NumberSequencesOverTimeBarChart, { data, yAxisScaleType })
9168
+ content: /* @__PURE__ */ u$1(
9169
+ NumberSequencesOverTimeBarChart,
9170
+ {
9171
+ data,
9172
+ yAxisScaleType,
9173
+ maintainAspectRatio
9174
+ }
9175
+ )
9084
9176
  };
9085
9177
  case "line":
9086
9178
  return {
9087
9179
  title: "Line",
9088
- content: /* @__PURE__ */ u$1(NumberSequencesOverTimeLineChart, { data, yAxisScaleType })
9180
+ content: /* @__PURE__ */ u$1(
9181
+ NumberSequencesOverTimeLineChart,
9182
+ {
9183
+ data,
9184
+ yAxisScaleType,
9185
+ maintainAspectRatio
9186
+ }
9187
+ )
9089
9188
  };
9090
9189
  case "table":
9091
9190
  return {
@@ -9182,7 +9281,7 @@ let NumberSequencesOverTimeComponent = class extends PreactLitAdapterWithGridJsS
9182
9281
  this.lapisDateField = "";
9183
9282
  this.views = ["bar", "line", "table"];
9184
9283
  this.width = "100%";
9185
- this.height = "700px";
9284
+ this.height = void 0;
9186
9285
  this.granularity = "day";
9187
9286
  this.smoothingWindow = 0;
9188
9287
  this.pageSize = false;
@@ -9406,8 +9505,17 @@ class BaseMutationOverTimeDataMap extends Map2dBase {
9406
9505
  super(serializeSubstitutionOrDeletion, serializeTemporal, initialContent);
9407
9506
  }
9408
9507
  }
9409
- function getFilteredMutationOverTimeData(data, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval) {
9508
+ const displayMutationsSchema = z$2.array(z$2.string()).min(1);
9509
+ function getFilteredMutationOverTimeData({
9510
+ data,
9511
+ overallMutationData,
9512
+ displayedSegments,
9513
+ displayedMutationTypes,
9514
+ proportionInterval,
9515
+ displayMutations
9516
+ }) {
9410
9517
  const filteredData = new Map2dView(data);
9518
+ const displayMutationsSet = displayMutations === void 0 ? null : new Set(displayMutations.map((it) => it.toUpperCase()));
9411
9519
  const mutationsToFilterOut = overallMutationData.filter((entry) => {
9412
9520
  if (entry.proportion < proportionInterval.min || entry.proportion > proportionInterval.max) {
9413
9521
  return true;
@@ -9415,6 +9523,9 @@ function getFilteredMutationOverTimeData(data, overallMutationData, displayedSeg
9415
9523
  if (displayedSegments.some((segment) => segment.segment === entry.mutation.segment && !segment.checked)) {
9416
9524
  return true;
9417
9525
  }
9526
+ if (displayMutationsSet !== null && !displayMutationsSet.has(entry.mutation.code)) {
9527
+ return true;
9528
+ }
9418
9529
  return displayedMutationTypes.some(
9419
9530
  (mutationType) => mutationType.type === entry.mutation.type && !mutationType.checked
9420
9531
  );
@@ -9537,8 +9648,7 @@ const MutationsOverTimeGrid = ({
9537
9648
  allMutations.length,
9538
9649
  " mutations. You can narrow the filter to reduce the number of mutations."
9539
9650
  ] }),
9540
- allMutations.length === 0 && /* @__PURE__ */ u$1("div", { className: "flex justify-center", children: "No data available for your filters." }),
9541
- /* @__PURE__ */ u$1(
9651
+ allMutations.length === 0 ? /* @__PURE__ */ u$1("div", { className: "flex justify-center", children: "No data available for your filters." }) : /* @__PURE__ */ u$1(
9542
9652
  "div",
9543
9653
  {
9544
9654
  ref: gridRef,
@@ -9712,8 +9822,13 @@ const mutationOverTimeSchema = z$2.object({
9712
9822
  views: z$2.array(mutationsOverTimeViewSchema),
9713
9823
  granularity: temporalGranularitySchema,
9714
9824
  lapisDateField: z$2.string().min(1),
9825
+ displayMutations: displayMutationsSchema.optional(),
9826
+ initialMeanProportionInterval: z$2.object({
9827
+ min: z$2.number().min(0).max(1),
9828
+ max: z$2.number().min(0).max(1)
9829
+ }),
9715
9830
  width: z$2.string(),
9716
- height: z$2.string()
9831
+ height: z$2.string().optional()
9717
9832
  });
9718
9833
  const MutationsOverTime = (componentProps) => {
9719
9834
  const { width, height } = componentProps;
@@ -9762,22 +9877,31 @@ const MutationsOverTimeTabs$1 = ({
9762
9877
  originalComponentProps,
9763
9878
  overallMutationData
9764
9879
  }) => {
9765
- const [proportionInterval, setProportionInterval] = h({ min: 0.05, max: 0.9 });
9880
+ const [proportionInterval, setProportionInterval] = h(originalComponentProps.initialMeanProportionInterval);
9766
9881
  const [colorScale, setColorScale] = h({ min: 0, max: 1, color: "indigo" });
9767
9882
  const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
9768
9883
  const [displayedMutationTypes, setDisplayedMutationTypes] = h([
9769
9884
  { label: "Substitutions", checked: true, type: "substitution" },
9770
9885
  { label: "Deletions", checked: true, type: "deletion" }
9771
9886
  ]);
9887
+ const displayMutations = originalComponentProps.displayMutations;
9772
9888
  const filteredData = T$1(() => {
9773
- return getFilteredMutationOverTimeData(
9774
- mutationOverTimeData,
9889
+ return getFilteredMutationOverTimeData({
9890
+ data: mutationOverTimeData,
9775
9891
  overallMutationData,
9776
9892
  displayedSegments,
9777
9893
  displayedMutationTypes,
9778
- proportionInterval
9779
- );
9780
- }, [mutationOverTimeData, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval]);
9894
+ proportionInterval,
9895
+ displayMutations
9896
+ });
9897
+ }, [
9898
+ mutationOverTimeData,
9899
+ overallMutationData,
9900
+ displayedSegments,
9901
+ displayedMutationTypes,
9902
+ proportionInterval,
9903
+ displayMutations
9904
+ ]);
9781
9905
  const getTab = (view) => {
9782
9906
  if (filteredData === void 0) {
9783
9907
  return {
@@ -9904,9 +10028,11 @@ let MutationsOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
9904
10028
  this.sequenceType = "nucleotide";
9905
10029
  this.views = ["grid"];
9906
10030
  this.width = "100%";
9907
- this.height = "700px";
10031
+ this.height = void 0;
9908
10032
  this.granularity = "week";
9909
10033
  this.lapisDateField = "date";
10034
+ this.displayMutations = void 0;
10035
+ this.initialMeanProportionInterval = { min: 0.05, max: 0.9 };
9910
10036
  }
9911
10037
  render() {
9912
10038
  return /* @__PURE__ */ u$1(
@@ -9918,7 +10044,9 @@ let MutationsOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
9918
10044
  width: this.width,
9919
10045
  height: this.height,
9920
10046
  granularity: this.granularity,
9921
- lapisDateField: this.lapisDateField
10047
+ lapisDateField: this.lapisDateField,
10048
+ displayMutations: this.displayMutations,
10049
+ initialMeanProportionInterval: this.initialMeanProportionInterval
9922
10050
  }
9923
10051
  );
9924
10052
  }
@@ -9944,6 +10072,12 @@ __decorateClass$8([
9944
10072
  __decorateClass$8([
9945
10073
  n$1({ type: String })
9946
10074
  ], MutationsOverTimeComponent.prototype, "lapisDateField", 2);
10075
+ __decorateClass$8([
10076
+ n$1({ type: Array })
10077
+ ], MutationsOverTimeComponent.prototype, "displayMutations", 2);
10078
+ __decorateClass$8([
10079
+ n$1({ type: Object })
10080
+ ], MutationsOverTimeComponent.prototype, "initialMeanProportionInterval", 2);
9947
10081
  MutationsOverTimeComponent = __decorateClass$8([
9948
10082
  t$3("gs-mutations-over-time")
9949
10083
  ], MutationsOverTimeComponent);
@@ -10591,6 +10725,12 @@ svg.leaflet-image-layer.leaflet-interactive path {\r
10591
10725
  }\r
10592
10726
  `;
10593
10727
  const leafletStyleModifications = ".leaflet-container {\n background: transparent;\n}\n";
10728
+ function AspectRatio({ children, aspectRatio }) {
10729
+ if (aspectRatio === void 0) {
10730
+ return children;
10731
+ }
10732
+ return /* @__PURE__ */ u$1("div", { class: `w-full relative`, style: { paddingTop: `${aspectRatio}%` }, children: /* @__PURE__ */ u$1("div", { className: "absolute inset-0", children }) });
10733
+ }
10594
10734
  const SequencesByLocationMap = ({
10595
10735
  locations,
10596
10736
  totalCount,
@@ -10602,7 +10742,8 @@ const SequencesByLocationMap = ({
10602
10742
  zoom,
10603
10743
  offsetX,
10604
10744
  offsetY,
10605
- hasTableView
10745
+ hasTableView,
10746
+ maintainAspectRatio
10606
10747
  }) => {
10607
10748
  const ref = A$1(null);
10608
10749
  y(() => {
@@ -10633,8 +10774,8 @@ const SequencesByLocationMap = ({
10633
10774
  leafletMap.remove();
10634
10775
  };
10635
10776
  }, [ref, locations, enableMapNavigation, lapisLocationField, zoom, offsetX, offsetY]);
10636
- return /* @__PURE__ */ u$1("div", { className: "h-full", children: [
10637
- /* @__PURE__ */ u$1("div", { ref, className: "h-full" }),
10777
+ return /* @__PURE__ */ u$1(AspectRatio, { aspectRatio: maintainAspectRatio ? 50 : void 0, children: [
10778
+ /* @__PURE__ */ u$1("div", { className: "h-full", ref }),
10638
10779
  /* @__PURE__ */ u$1("div", { className: "relative", children: /* @__PURE__ */ u$1(
10639
10780
  DataMatchInformation,
10640
10781
  {
@@ -10771,7 +10912,7 @@ const SequencesByLocationTable = ({
10771
10912
  sort: true,
10772
10913
  formatter: (cell) => formatProportion(cell)
10773
10914
  },
10774
- ..."isShownOnMap" in tableData[0] ? [{ id: "isShownOnMap", name: "shown on map", sort: true, width: "20%" }] : []
10915
+ ...tableData.length > 0 && "isShownOnMap" in tableData[0] ? [{ id: "isShownOnMap", name: "shown on map", sort: true, width: "20%" }] : []
10775
10916
  ];
10776
10917
  return /* @__PURE__ */ u$1(Table, { data: tableData, columns: headers, pageSize });
10777
10918
  };
@@ -10902,7 +11043,7 @@ const sequencesByLocationPropsSchema = z$2.object({
10902
11043
  mapSource: mapSourceSchema.optional(),
10903
11044
  enableMapNavigation: z$2.boolean(),
10904
11045
  width: z$2.string(),
10905
- height: z$2.string(),
11046
+ height: z$2.string().optional(),
10906
11047
  views: z$2.array(sequencesByLocationViewSchema),
10907
11048
  zoom: z$2.number(),
10908
11049
  offsetX: z$2.number(),
@@ -10931,12 +11072,16 @@ const SequencesByLocationMapInner = (props) => {
10931
11072
  if (error) {
10932
11073
  throw error;
10933
11074
  }
11075
+ if (data.tableData.length === 0) {
11076
+ return /* @__PURE__ */ u$1(NoDataDisplay, {});
11077
+ }
10934
11078
  return /* @__PURE__ */ u$1(SequencesByLocationMapTabs, { data, originalComponentProps: props });
10935
11079
  };
10936
11080
  const SequencesByLocationMapTabs = ({
10937
11081
  originalComponentProps,
10938
11082
  data
10939
11083
  }) => {
11084
+ const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
10940
11085
  const getTab = (view) => {
10941
11086
  switch (view) {
10942
11087
  case views.map: {
@@ -10955,7 +11100,8 @@ const SequencesByLocationMapTabs = ({
10955
11100
  zoom: originalComponentProps.zoom,
10956
11101
  offsetX: originalComponentProps.offsetX,
10957
11102
  offsetY: originalComponentProps.offsetY,
10958
- hasTableView: originalComponentProps.views.includes(views.table)
11103
+ hasTableView: originalComponentProps.views.includes(views.table),
11104
+ maintainAspectRatio
10959
11105
  }
10960
11106
  )
10961
11107
  };
@@ -11025,7 +11171,7 @@ let SequencesByLocationComponent = class extends PreactLitAdapterWithGridJsStyle
11025
11171
  this.mapSource = void 0;
11026
11172
  this.enableMapNavigation = false;
11027
11173
  this.width = "100%";
11028
- this.height = "700px";
11174
+ this.height = void 0;
11029
11175
  this.views = ["map", "table"];
11030
11176
  this.zoom = 1;
11031
11177
  this.offsetX = 0;
@@ -11098,7 +11244,7 @@ async function queryGeneralStatistics(numeratorFilter, denominatorFilter, lapis,
11098
11244
  }
11099
11245
  const statisticsPropsSchema = z$2.object({
11100
11246
  width: z$2.string(),
11101
- height: z$2.string(),
11247
+ height: z$2.string().optional(),
11102
11248
  numeratorFilter: lapisFilterSchema,
11103
11249
  denominatorFilter: lapisFilterSchema
11104
11250
  });
@@ -11126,16 +11272,16 @@ const StatisticsInner = (componentProps) => {
11126
11272
  };
11127
11273
  const MetricDataTabs = ({ data }) => {
11128
11274
  const { count, proportion } = data;
11129
- return /* @__PURE__ */ u$1("div", { className: "flex flex-col sm:flex-row rounded-md border-2 border-gray-100", children: [
11275
+ return /* @__PURE__ */ u$1("div", { className: "flex flex-col sm:flex-row rounded-md border-2 border-gray-100 min-w-[180px]", children: [
11130
11276
  /* @__PURE__ */ u$1("div", { className: "stat", children: [
11131
11277
  /* @__PURE__ */ u$1("div", { className: "stat-title", children: "Sequences" }),
11132
11278
  /* @__PURE__ */ u$1("div", { className: "stat-value text-2xl sm:text-4xl", children: count.toLocaleString("en-us") }),
11133
- /* @__PURE__ */ u$1("div", { className: "stat-desc", children: "The total number of sequenced samples" })
11279
+ /* @__PURE__ */ u$1("div", { className: "stat-desc text-wrap", children: "The total number of sequenced samples" })
11134
11280
  ] }),
11135
11281
  /* @__PURE__ */ u$1("div", { className: "stat", children: [
11136
11282
  /* @__PURE__ */ u$1("div", { className: "stat-title", children: "Overall proportion" }),
11137
11283
  /* @__PURE__ */ u$1("div", { className: "stat-value text-2xl sm:text-4xl", children: formatProportion(proportion) }),
11138
- /* @__PURE__ */ u$1("div", { className: "stat-desc", children: "The proportion among all sequenced samples" })
11284
+ /* @__PURE__ */ u$1("div", { className: "stat-desc text-wrap", children: "The proportion among all sequenced samples" })
11139
11285
  ] })
11140
11286
  ] });
11141
11287
  };
@@ -11155,7 +11301,7 @@ let StatisticsComponent = class extends PreactLitAdapterWithGridJsStyles {
11155
11301
  this.numeratorFilter = {};
11156
11302
  this.denominatorFilter = {};
11157
11303
  this.width = "100%";
11158
- this.height = "100%";
11304
+ this.height = void 0;
11159
11305
  }
11160
11306
  render() {
11161
11307
  return /* @__PURE__ */ u$1(
@@ -11274,7 +11420,7 @@ const wastewaterMutationOverTimeSchema = z$2.object({
11274
11420
  lapisFilter: lapisFilterSchema,
11275
11421
  sequenceType: sequenceTypeSchema,
11276
11422
  width: z$2.string(),
11277
- height: z$2.string(),
11423
+ height: z$2.string().optional(),
11278
11424
  maxNumberOfGridRows: z$2.number()
11279
11425
  });
11280
11426
  const WastewaterMutationsOverTime = (componentProps) => {
@@ -11375,7 +11521,7 @@ let WastewaterMutationsOverTimeComponent = class extends PreactLitAdapterWithGri
11375
11521
  this.lapisFilter = {};
11376
11522
  this.sequenceType = "nucleotide";
11377
11523
  this.width = "100%";
11378
- this.height = "700px";
11524
+ this.height = void 0;
11379
11525
  this.maxNumberOfGridRows = 100;
11380
11526
  }
11381
11527
  render() {
@@ -15131,9 +15277,6 @@ const ReferenceGenomesAwaiter = ({ children }) => {
15131
15277
  }
15132
15278
  return /* @__PURE__ */ u$1(Fragment, { children });
15133
15279
  };
15134
- function isNotInitialized(referenceGenome) {
15135
- return referenceGenome.nucleotideSequences.length === 0 && referenceGenome.genes.length === 0;
15136
- }
15137
15280
  const ExampleMutation = ({ sequenceType, mutationType }) => {
15138
15281
  const referenceGenome = x$1(ReferenceGenomeContext);
15139
15282
  return /* @__PURE__ */ u$1("b", { children: getExampleMutation(referenceGenome, sequenceType, mutationType) });
@@ -15567,6 +15710,12 @@ const MutationFilterInner = ({ initialValue }) => {
15567
15710
  getInitialState(initialValue, referenceGenome)
15568
15711
  );
15569
15712
  const filterRef = A$1(null);
15713
+ if (referenceGenome.nucleotideSequences.length === 0 && referenceGenome.genes.length === 0) {
15714
+ throw new UserFacingError(
15715
+ "No reference sequences available",
15716
+ "This organism has neither nucleotide nor amino acid sequences configured in its reference genome. You cannot filter by mutations."
15717
+ );
15718
+ }
15570
15719
  const handleRemoveValue = (option) => {
15571
15720
  const newSelectedFilters = {
15572
15721
  ...selectedFilters,