@genspectrum/dashboard-components 0.2.0 → 0.3.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 (59) hide show
  1. package/custom-elements.json +330 -179
  2. package/dist/dashboard-components.js +379 -187
  3. package/dist/dashboard-components.js.map +1 -1
  4. package/dist/genspectrum-components.d.ts +160 -114
  5. package/dist/style.css +171 -71
  6. package/package.json +1 -2
  7. package/src/constants.ts +1 -1
  8. package/src/lapisApi/lapisApi.ts +46 -2
  9. package/src/lapisApi/lapisTypes.ts +14 -0
  10. package/src/preact/aggregatedData/aggregate.stories.tsx +4 -2
  11. package/src/preact/aggregatedData/aggregate.tsx +8 -6
  12. package/src/preact/components/error-boundary.stories.tsx +6 -14
  13. package/src/preact/components/error-boundary.tsx +2 -11
  14. package/src/preact/components/error-display.stories.tsx +12 -5
  15. package/src/preact/components/error-display.tsx +37 -3
  16. package/src/preact/components/loading-display.stories.tsx +1 -1
  17. package/src/preact/components/resize-container.tsx +5 -14
  18. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +2 -0
  19. package/src/preact/dateRangeSelector/date-range-selector.tsx +11 -8
  20. package/src/preact/locationFilter/fetchAutocompletionList.ts +15 -1
  21. package/src/preact/locationFilter/location-filter.stories.tsx +1 -1
  22. package/src/preact/locationFilter/location-filter.tsx +16 -30
  23. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +6 -3
  24. package/src/preact/mutationComparison/mutation-comparison.tsx +10 -13
  25. package/src/preact/mutationComparison/queryMutationData.ts +2 -3
  26. package/src/preact/mutationFilter/mutation-filter.stories.tsx +8 -8
  27. package/src/preact/mutationFilter/mutation-filter.tsx +7 -6
  28. package/src/preact/mutations/mutations.stories.tsx +6 -3
  29. package/src/preact/mutations/mutations.tsx +8 -6
  30. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +14 -7
  31. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +10 -8
  32. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +6 -3
  33. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +9 -7
  34. package/src/preact/textInput/text-input.stories.tsx +26 -0
  35. package/src/preact/textInput/text-input.tsx +4 -5
  36. package/src/query/queryPrevalenceOverTime.ts +4 -10
  37. package/src/types.ts +4 -1
  38. package/src/web-components/ResizeContainer.mdx +13 -0
  39. package/src/web-components/app.ts +3 -1
  40. package/src/web-components/input/gs-date-range-selector.stories.ts +10 -2
  41. package/src/web-components/input/gs-date-range-selector.tsx +26 -16
  42. package/src/web-components/input/gs-location-filter.stories.ts +5 -7
  43. package/src/web-components/input/gs-location-filter.tsx +6 -7
  44. package/src/web-components/input/gs-mutation-filter.stories.ts +11 -8
  45. package/src/web-components/input/gs-mutation-filter.tsx +38 -26
  46. package/src/web-components/input/gs-text-input.stories.ts +3 -3
  47. package/src/web-components/input/gs-text-input.tsx +10 -10
  48. package/src/web-components/input/introduction.mdx +11 -0
  49. package/src/web-components/introduction.mdx +15 -0
  50. package/src/web-components/visualization/gs-aggregate.stories.ts +19 -6
  51. package/src/web-components/visualization/gs-aggregate.tsx +31 -15
  52. package/src/web-components/visualization/gs-mutation-comparison.stories.ts +13 -7
  53. package/src/web-components/visualization/gs-mutation-comparison.tsx +26 -17
  54. package/src/web-components/visualization/gs-mutations.stories.ts +14 -8
  55. package/src/web-components/visualization/gs-mutations.tsx +18 -8
  56. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +28 -18
  57. package/src/web-components/visualization/gs-prevalence-over-time.tsx +45 -22
  58. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +11 -5
  59. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +21 -9
@@ -400,6 +400,31 @@ function makeLapisResponse(data) {
400
400
  data
401
401
  });
402
402
  }
403
+ const problemDetail = z$1.object({
404
+ title: z$1.string().optional(),
405
+ status: z$1.number(),
406
+ detail: z$1.string().optional(),
407
+ type: z$1.string(),
408
+ instance: z$1.string().optional()
409
+ });
410
+ const lapisError = z$1.object({
411
+ error: problemDetail
412
+ });
413
+ class UnknownLapisError extends Error {
414
+ constructor(message, status) {
415
+ super(message);
416
+ this.status = status;
417
+ this.name = "UnknownLapisError";
418
+ }
419
+ }
420
+ class LapisError extends Error {
421
+ constructor(message, status, problemDetail2) {
422
+ super(message);
423
+ this.status = status;
424
+ this.problemDetail = problemDetail2;
425
+ this.name = "LapisError";
426
+ }
427
+ }
403
428
  async function fetchAggregated(lapisUrl, body, signal) {
404
429
  const response = await fetch(aggregatedEndpoint(lapisUrl), {
405
430
  method: "POST",
@@ -450,9 +475,26 @@ async function fetchReferenceGenome(lapisUrl, signal) {
450
475
  const handleErrors = async (response) => {
451
476
  if (!response.ok) {
452
477
  if (response.status >= 400 && response.status < 500) {
453
- throw new Error(`${response.statusText}: ${JSON.stringify(await response.json())}`);
478
+ const json = await response.json();
479
+ const lapisErrorResult = lapisError.safeParse(json);
480
+ if (lapisErrorResult.success) {
481
+ throw new LapisError(
482
+ response.statusText + lapisErrorResult.data.error.detail,
483
+ response.status,
484
+ lapisErrorResult.data.error
485
+ );
486
+ }
487
+ const problemDetailResult = problemDetail.safeParse(json);
488
+ if (problemDetailResult.success) {
489
+ throw new LapisError(
490
+ response.statusText + problemDetailResult.data.detail,
491
+ response.status,
492
+ problemDetailResult.data
493
+ );
494
+ }
495
+ throw new UnknownLapisError(`${response.statusText}: ${JSON.stringify(json)}`, response.status);
454
496
  }
455
- throw new Error(`${response.statusText}: ${response.status}`);
497
+ throw new UnknownLapisError(`${response.statusText}: ${response.status}`, response.status);
456
498
  }
457
499
  };
458
500
  const aggregatedEndpoint = (lapisUrl) => `${lapisUrl}/sample/aggregated`;
@@ -491,7 +533,8 @@ let App = class extends LitElement {
491
533
  }
492
534
  render() {
493
535
  return this.updateReferenceGenome.render({
494
- complete: () => html` <slot></slot>`,
536
+ complete: () => html``,
537
+ // Children will be rendered in the light DOM anyway. We can't use slots without a shadow DOM.
495
538
  error: () => html` <div class="m-2 w-full alert alert-error">
496
539
  Error: Cannot fetch reference genome. Is LAPIS available?
497
540
  </div>`
@@ -1227,26 +1270,46 @@ const CsvDownloadButton = ({
1227
1270
  return /* @__PURE__ */ u$1("button", { className, onClick: download, children: label });
1228
1271
  };
1229
1272
  class UserFacingError extends Error {
1230
- constructor(message) {
1273
+ constructor(headline, message) {
1231
1274
  super(message);
1275
+ this.headline = headline;
1232
1276
  this.name = "UserFacingError";
1233
1277
  }
1234
1278
  }
1235
1279
  const ErrorDisplay = ({ error }) => {
1280
+ console.error(error);
1281
+ const ref = F(null);
1236
1282
  return /* @__PURE__ */ u$1("div", { className: "h-full w-full rounded-md border-2 border-gray-100 p-2 flex items-center justify-center flex-col", children: [
1237
1283
  /* @__PURE__ */ u$1("div", { className: "text-red-700 font-bold", children: "Error" }),
1238
- /* @__PURE__ */ u$1("div", { children: "Oops! Something went wrong." }),
1239
- error instanceof UserFacingError && /* @__PURE__ */ u$1("div", { className: "text-sm text-gray-600", children: error.message })
1284
+ /* @__PURE__ */ u$1("div", { children: [
1285
+ "Oops! Something went wrong.",
1286
+ error instanceof UserFacingError && /* @__PURE__ */ u$1(Fragment, { children: [
1287
+ " ",
1288
+ /* @__PURE__ */ u$1(
1289
+ "button",
1290
+ {
1291
+ className: "text-sm text-gray-600 hover:text-gray-300",
1292
+ onClick: () => {
1293
+ var _a;
1294
+ return (_a = ref.current) == null ? void 0 : _a.showModal();
1295
+ },
1296
+ children: "Show details."
1297
+ }
1298
+ ),
1299
+ /* @__PURE__ */ u$1("dialog", { ref, class: "modal", children: [
1300
+ /* @__PURE__ */ u$1("div", { class: "modal-box", children: [
1301
+ /* @__PURE__ */ u$1("form", { method: "dialog", children: /* @__PURE__ */ u$1("button", { className: "btn btn-sm btn-circle btn-ghost absolute right-2 top-2", children: "✕" }) }),
1302
+ /* @__PURE__ */ u$1("h1", { class: "text-lg", children: error.headline }),
1303
+ /* @__PURE__ */ u$1("p", { class: "py-4", children: error.message })
1304
+ ] }),
1305
+ /* @__PURE__ */ u$1("form", { method: "dialog", class: "modal-backdrop", children: /* @__PURE__ */ u$1("button", { children: "close" }) })
1306
+ ] })
1307
+ ] })
1308
+ ] })
1240
1309
  ] });
1241
1310
  };
1242
- const ResizeContainer = ({ children, size, defaultSize }) => {
1243
- return /* @__PURE__ */ u$1("div", { style: extendByDefault(size, defaultSize), children });
1244
- };
1245
- const extendByDefault = (size, defaultSize) => {
1246
- if (size === void 0) {
1247
- return defaultSize;
1248
- }
1249
- return { ...defaultSize, ...size };
1311
+ const ResizeContainer = ({ children, size }) => {
1312
+ return /* @__PURE__ */ u$1("div", { style: size, children });
1250
1313
  };
1251
1314
  const Headline = ({ heading, children }) => {
1252
1315
  if (!heading) {
@@ -1268,18 +1331,10 @@ const ResizingHeadline = ({ heading, children }) => {
1268
1331
  /* @__PURE__ */ u$1("div", { style: { height: `calc(100% - ${h1Height})` }, children })
1269
1332
  ] });
1270
1333
  };
1271
- const ErrorBoundary = ({
1272
- size,
1273
- defaultSize,
1274
- headline,
1275
- children
1276
- }) => {
1334
+ const ErrorBoundary = ({ size, headline, children }) => {
1277
1335
  const [internalError] = b2();
1278
1336
  if (internalError) {
1279
- console.error(internalError);
1280
- }
1281
- if (internalError) {
1282
- return /* @__PURE__ */ u$1(ResizeContainer, { defaultSize, size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(ErrorDisplay, { error: internalError }) }) });
1337
+ return /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(ErrorDisplay, { error: internalError }) }) });
1283
1338
  }
1284
1339
  return /* @__PURE__ */ u$1(Fragment, { children });
1285
1340
  };
@@ -1568,11 +1623,12 @@ const MutationComparison = ({
1568
1623
  variants,
1569
1624
  sequenceType,
1570
1625
  views,
1571
- size,
1626
+ width,
1627
+ height,
1572
1628
  headline = "Mutation comparison"
1573
1629
  }) => {
1574
- const defaultSize = { height: "600px", width: "100%" };
1575
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationComparisonInner, { variants, sequenceType, views }) }) }) });
1630
+ const size = { height, width };
1631
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationComparisonInner, { variants, sequenceType, views }) }) }) });
1576
1632
  };
1577
1633
  const MutationComparisonInner = ({
1578
1634
  variants,
@@ -2290,39 +2346,6 @@ html {
2290
2346
  --tw-contain-paint: ;
2291
2347
  --tw-contain-style: ;
2292
2348
  }
2293
- .container {
2294
- width: 100%;
2295
- }
2296
- @media (min-width: 640px) {
2297
-
2298
- .container {
2299
- max-width: 640px;
2300
- }
2301
- }
2302
- @media (min-width: 768px) {
2303
-
2304
- .container {
2305
- max-width: 768px;
2306
- }
2307
- }
2308
- @media (min-width: 1024px) {
2309
-
2310
- .container {
2311
- max-width: 1024px;
2312
- }
2313
- }
2314
- @media (min-width: 1280px) {
2315
-
2316
- .container {
2317
- max-width: 1280px;
2318
- }
2319
- }
2320
- @media (min-width: 1536px) {
2321
-
2322
- .container {
2323
- max-width: 1536px;
2324
- }
2325
- }
2326
2349
  .alert {
2327
2350
  display: grid;
2328
2351
  width: 100%;
@@ -2425,6 +2448,12 @@ html {
2425
2448
  .btn:disabled {
2426
2449
  pointer-events: none;
2427
2450
  }
2451
+ .btn-circle {
2452
+ height: 3rem;
2453
+ width: 3rem;
2454
+ border-radius: 9999px;
2455
+ padding: 0px;
2456
+ }
2428
2457
  :where(.btn:is(input[type="checkbox"])),
2429
2458
  :where(.btn:is(input[type="radio"])) {
2430
2459
  width: auto;
@@ -2577,16 +2606,14 @@ html {
2577
2606
  --glass-border-opacity: 15%;
2578
2607
  }
2579
2608
 
2580
- .btn-outline.btn-primary:hover {
2581
- --tw-text-opacity: 1;
2582
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
2609
+ .btn-ghost:hover {
2610
+ border-color: transparent;
2583
2611
  }
2584
2612
 
2585
- @supports (color: color-mix(in oklab, black, black)) {
2613
+ @supports (color: oklch(0% 0 0)) {
2586
2614
 
2587
- .btn-outline.btn-primary:hover {
2588
- background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
2589
- border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
2615
+ .btn-ghost:hover {
2616
+ background-color: var(--fallback-bc,oklch(var(--bc)/0.2));
2590
2617
  }
2591
2618
  }
2592
2619
 
@@ -2799,6 +2826,69 @@ html {
2799
2826
  :where(.menu li) .badge {
2800
2827
  justify-self: end;
2801
2828
  }
2829
+ .modal {
2830
+ pointer-events: none;
2831
+ position: fixed;
2832
+ inset: 0px;
2833
+ margin: 0px;
2834
+ display: grid;
2835
+ height: 100%;
2836
+ max-height: none;
2837
+ width: 100%;
2838
+ max-width: none;
2839
+ justify-items: center;
2840
+ padding: 0px;
2841
+ opacity: 0;
2842
+ overscroll-behavior: contain;
2843
+ z-index: 999;
2844
+ background-color: transparent;
2845
+ color: inherit;
2846
+ transition-duration: 200ms;
2847
+ transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
2848
+ transition-property: transform, opacity, visibility;
2849
+ overflow-y: hidden;
2850
+ }
2851
+ :where(.modal) {
2852
+ align-items: center;
2853
+ }
2854
+ .modal-box {
2855
+ max-height: calc(100vh - 5em);
2856
+ grid-column-start: 1;
2857
+ grid-row-start: 1;
2858
+ width: 91.666667%;
2859
+ max-width: 32rem;
2860
+ --tw-scale-x: .9;
2861
+ --tw-scale-y: .9;
2862
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2863
+ border-bottom-right-radius: var(--rounded-box, 1rem);
2864
+ border-bottom-left-radius: var(--rounded-box, 1rem);
2865
+ border-top-left-radius: var(--rounded-box, 1rem);
2866
+ border-top-right-radius: var(--rounded-box, 1rem);
2867
+ --tw-bg-opacity: 1;
2868
+ background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
2869
+ padding: 1.5rem;
2870
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
2871
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
2872
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
2873
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
2874
+ transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
2875
+ transition-duration: 200ms;
2876
+ box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
2877
+ overflow-y: auto;
2878
+ overscroll-behavior: contain;
2879
+ }
2880
+ .modal-open,
2881
+ .modal:target,
2882
+ .modal-toggle:checked + .modal,
2883
+ .modal[open] {
2884
+ pointer-events: auto;
2885
+ visibility: visible;
2886
+ opacity: 1;
2887
+ }
2888
+ :root:has(:is(.modal-open, .modal:target, .modal-toggle:checked + .modal, .modal[open])) {
2889
+ overflow: hidden;
2890
+ scrollbar-gutter: stable;
2891
+ }
2802
2892
  .radio {
2803
2893
  flex-shrink: 0;
2804
2894
  --chkbg: var(--bc);
@@ -2996,34 +3086,12 @@ input.tab:checked + .tab-content,
2996
3086
  background-color: var(--btn-color, var(--fallback-b2));
2997
3087
  border-color: var(--btn-color, var(--fallback-b2));
2998
3088
  }
2999
-
3000
- .btn-primary {
3001
- --btn-color: var(--fallback-p);
3002
- }
3003
- }
3004
- @supports (color: color-mix(in oklab, black, black)) {
3005
-
3006
- .btn-outline.btn-primary.btn-active {
3007
- background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
3008
- border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
3009
- }
3010
3089
  }
3011
3090
  .btn:focus-visible {
3012
3091
  outline-style: solid;
3013
3092
  outline-width: 2px;
3014
3093
  outline-offset: 2px;
3015
3094
  }
3016
- .btn-primary {
3017
- --tw-text-opacity: 1;
3018
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
3019
- outline-color: var(--fallback-p,oklch(var(--p)/1));
3020
- }
3021
- @supports (color: oklch(0% 0 0)) {
3022
-
3023
- .btn-primary {
3024
- --btn-color: var(--p);
3025
- }
3026
- }
3027
3095
  .btn.glass {
3028
3096
  --tw-shadow: 0 0 #0000;
3029
3097
  --tw-shadow-colored: 0 0 #0000;
@@ -3034,13 +3102,19 @@ input.tab:checked + .tab-content,
3034
3102
  --glass-opacity: 25%;
3035
3103
  --glass-border-opacity: 15%;
3036
3104
  }
3037
- .btn-outline.btn-primary {
3038
- --tw-text-opacity: 1;
3039
- color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
3105
+ .btn-ghost {
3106
+ border-width: 1px;
3107
+ border-color: transparent;
3108
+ background-color: transparent;
3109
+ color: currentColor;
3110
+ --tw-shadow: 0 0 #0000;
3111
+ --tw-shadow-colored: 0 0 #0000;
3112
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
3113
+ outline-color: currentColor;
3040
3114
  }
3041
- .btn-outline.btn-primary.btn-active {
3042
- --tw-text-opacity: 1;
3043
- color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
3115
+ .btn-ghost.btn-active {
3116
+ border-color: transparent;
3117
+ background-color: var(--fallback-bc,oklch(var(--bc)/0.2));
3044
3118
  }
3045
3119
  .btn.btn-disabled,
3046
3120
  .btn[disabled],
@@ -3355,6 +3429,29 @@ input.tab:checked + .tab-content,
3355
3429
  border-color: currentColor;
3356
3430
  opacity: 0.6;
3357
3431
  }
3432
+ .modal:not(dialog:not(.modal-open)),
3433
+ .modal::backdrop {
3434
+ background-color: #0006;
3435
+ animation: modal-pop 0.2s ease-out;
3436
+ }
3437
+ .modal-backdrop {
3438
+ z-index: -1;
3439
+ grid-column-start: 1;
3440
+ grid-row-start: 1;
3441
+ display: grid;
3442
+ align-self: stretch;
3443
+ justify-self: stretch;
3444
+ color: transparent;
3445
+ }
3446
+ .modal-open .modal-box,
3447
+ .modal-toggle:checked + .modal .modal-box,
3448
+ .modal:target .modal-box,
3449
+ .modal[open] .modal-box {
3450
+ --tw-translate-y: 0px;
3451
+ --tw-scale-x: 1;
3452
+ --tw-scale-y: 1;
3453
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
3454
+ }
3358
3455
  @keyframes modal-pop {
3359
3456
 
3360
3457
  0% {
@@ -3840,6 +3937,18 @@ input.tab:checked + .tab-content,
3840
3937
  border-radius: 9999px;
3841
3938
  padding: 0px;
3842
3939
  }
3940
+ .btn-circle:where(.btn-md) {
3941
+ height: 3rem;
3942
+ width: 3rem;
3943
+ border-radius: 9999px;
3944
+ padding: 0px;
3945
+ }
3946
+ .btn-circle:where(.btn-lg) {
3947
+ height: 4rem;
3948
+ width: 4rem;
3949
+ border-radius: 9999px;
3950
+ padding: 0px;
3951
+ }
3843
3952
  .join.join-vertical {
3844
3953
  flex-direction: column;
3845
3954
  }
@@ -3954,6 +4063,42 @@ input.tab:checked + .tab-content,
3954
4063
  margin-bottom: 0px;
3955
4064
  margin-inline-start: -1px;
3956
4065
  }
4066
+ .modal-top :where(.modal-box) {
4067
+ width: 100%;
4068
+ max-width: none;
4069
+ --tw-translate-y: -2.5rem;
4070
+ --tw-scale-x: 1;
4071
+ --tw-scale-y: 1;
4072
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
4073
+ border-bottom-right-radius: var(--rounded-box, 1rem);
4074
+ border-bottom-left-radius: var(--rounded-box, 1rem);
4075
+ border-top-left-radius: 0px;
4076
+ border-top-right-radius: 0px;
4077
+ }
4078
+ .modal-middle :where(.modal-box) {
4079
+ width: 91.666667%;
4080
+ max-width: 32rem;
4081
+ --tw-translate-y: 0px;
4082
+ --tw-scale-x: .9;
4083
+ --tw-scale-y: .9;
4084
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
4085
+ border-top-left-radius: var(--rounded-box, 1rem);
4086
+ border-top-right-radius: var(--rounded-box, 1rem);
4087
+ border-bottom-right-radius: var(--rounded-box, 1rem);
4088
+ border-bottom-left-radius: var(--rounded-box, 1rem);
4089
+ }
4090
+ .modal-bottom :where(.modal-box) {
4091
+ width: 100%;
4092
+ max-width: none;
4093
+ --tw-translate-y: 2.5rem;
4094
+ --tw-scale-x: 1;
4095
+ --tw-scale-y: 1;
4096
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
4097
+ border-top-left-radius: var(--rounded-box, 1rem);
4098
+ border-top-right-radius: var(--rounded-box, 1rem);
4099
+ border-bottom-right-radius: 0px;
4100
+ border-bottom-left-radius: 0px;
4101
+ }
3957
4102
  .steps-horizontal .step {
3958
4103
  grid-template-rows: 40px 1fr;
3959
4104
  grid-template-columns: auto;
@@ -4079,9 +4224,15 @@ input.tab:checked + .tab-content,
4079
4224
  .relative {
4080
4225
  position: relative;
4081
4226
  }
4227
+ .right-2 {
4228
+ right: 0.5rem;
4229
+ }
4082
4230
  .right-6 {
4083
4231
  right: 1.5rem;
4084
4232
  }
4233
+ .top-2 {
4234
+ top: 0.5rem;
4235
+ }
4085
4236
  .top-8 {
4086
4237
  top: 2rem;
4087
4238
  }
@@ -4115,9 +4266,6 @@ input.tab:checked + .tab-content,
4115
4266
  .me-1 {
4116
4267
  margin-inline-end: 0.25rem;
4117
4268
  }
4118
- .ml-1 {
4119
- margin-left: 0.25rem;
4120
- }
4121
4269
  .ml-2 {
4122
4270
  margin-left: 0.5rem;
4123
4271
  }
@@ -4318,6 +4466,10 @@ input.tab:checked + .tab-content,
4318
4466
  padding-top: 0.5rem;
4319
4467
  padding-bottom: 0.5rem;
4320
4468
  }
4469
+ .py-4 {
4470
+ padding-top: 1rem;
4471
+ padding-bottom: 1rem;
4472
+ }
4321
4473
  .text-justify {
4322
4474
  text-align: justify;
4323
4475
  }
@@ -4398,6 +4550,10 @@ input.tab:checked + .tab-content,
4398
4550
  --tw-text-opacity: 1;
4399
4551
  color: rgb(30 64 175 / var(--tw-text-opacity));
4400
4552
  }
4553
+ .hover\\:text-gray-300:hover {
4554
+ --tw-text-opacity: 1;
4555
+ color: rgb(209 213 219 / var(--tw-text-opacity));
4556
+ }
4401
4557
  .hover\\:text-gray-700:hover {
4402
4558
  --tw-text-opacity: 1;
4403
4559
  color: rgb(55 65 81 / var(--tw-text-opacity));
@@ -4460,7 +4616,8 @@ let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles
4460
4616
  this.variants = [];
4461
4617
  this.sequenceType = "nucleotide";
4462
4618
  this.views = ["table"];
4463
- this.size = void 0;
4619
+ this.width = "100%";
4620
+ this.height = "700px";
4464
4621
  this.headline = "Mutation comparison";
4465
4622
  }
4466
4623
  render() {
@@ -4470,7 +4627,8 @@ let MutationComparisonComponent = class extends PreactLitAdapterWithGridJsStyles
4470
4627
  variants: this.variants,
4471
4628
  sequenceType: this.sequenceType,
4472
4629
  views: this.views,
4473
- size: this.size,
4630
+ width: this.width,
4631
+ height: this.height,
4474
4632
  headline: this.headline
4475
4633
  }
4476
4634
  );
@@ -4486,8 +4644,11 @@ __decorateClass$8([
4486
4644
  n2({ type: Array })
4487
4645
  ], MutationComparisonComponent.prototype, "views", 2);
4488
4646
  __decorateClass$8([
4489
- n2({ type: Object })
4490
- ], MutationComparisonComponent.prototype, "size", 2);
4647
+ n2({ type: String })
4648
+ ], MutationComparisonComponent.prototype, "width", 2);
4649
+ __decorateClass$8([
4650
+ n2({ type: String })
4651
+ ], MutationComparisonComponent.prototype, "height", 2);
4491
4652
  __decorateClass$8([
4492
4653
  n2({ type: String })
4493
4654
  ], MutationComparisonComponent.prototype, "headline", 2);
@@ -4756,11 +4917,12 @@ const Mutations = ({
4756
4917
  variant,
4757
4918
  sequenceType,
4758
4919
  views,
4759
- size,
4920
+ width,
4921
+ height,
4760
4922
  headline = "Mutations"
4761
4923
  }) => {
4762
- const defaultSize = { height: "600px", width: "100%" };
4763
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationsInner, { variant, sequenceType, views }) }) }) });
4924
+ const size = { height, width };
4925
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(MutationsInner, { variant, sequenceType, views }) }) }) });
4764
4926
  };
4765
4927
  const MutationsInner = ({ variant, sequenceType, views }) => {
4766
4928
  const lapis = P(LapisUrlContext);
@@ -4899,7 +5061,8 @@ let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
4899
5061
  this.variant = {};
4900
5062
  this.sequenceType = "nucleotide";
4901
5063
  this.views = ["table", "grid"];
4902
- this.size = void 0;
5064
+ this.width = "100%";
5065
+ this.height = "700px";
4903
5066
  this.headline = "Mutations";
4904
5067
  }
4905
5068
  render() {
@@ -4909,7 +5072,8 @@ let MutationsComponent = class extends PreactLitAdapterWithGridJsStyles {
4909
5072
  variant: this.variant,
4910
5073
  sequenceType: this.sequenceType,
4911
5074
  views: this.views,
4912
- size: this.size,
5075
+ width: this.width,
5076
+ height: this.height,
4913
5077
  headline: this.headline
4914
5078
  }
4915
5079
  );
@@ -4925,8 +5089,11 @@ __decorateClass$7([
4925
5089
  n2({ type: Array })
4926
5090
  ], MutationsComponent.prototype, "views", 2);
4927
5091
  __decorateClass$7([
4928
- n2({ type: Object })
4929
- ], MutationsComponent.prototype, "size", 2);
5092
+ n2({ type: String })
5093
+ ], MutationsComponent.prototype, "width", 2);
5094
+ __decorateClass$7([
5095
+ n2({ type: String })
5096
+ ], MutationsComponent.prototype, "height", 2);
4930
5097
  __decorateClass$7([
4931
5098
  n2({ type: String })
4932
5099
  ], MutationsComponent.prototype, "headline", 2);
@@ -6321,10 +6488,10 @@ class SlidingOperator {
6321
6488
  }
6322
6489
  function queryPrevalenceOverTime(numeratorFilter, denominatorFilter, granularity, smoothingWindow, lapis, signal) {
6323
6490
  const numeratorFilters = makeArray(numeratorFilter);
6324
- const denominatorData = fetchAndPrepare(getFilter(denominatorFilter), granularity, smoothingWindow);
6491
+ const denominatorData = fetchAndPrepare(denominatorFilter, granularity, smoothingWindow);
6325
6492
  const subQueries = numeratorFilters.map(async (namedLapisFilter) => {
6326
- const { displayName, ...filter } = namedLapisFilter;
6327
- const numeratorData = fetchAndPrepare(filter, granularity, smoothingWindow);
6493
+ const { displayName, lapisFilter } = namedLapisFilter;
6494
+ const numeratorData = fetchAndPrepare(lapisFilter, granularity, smoothingWindow);
6328
6495
  const divide = new DivisionOperator(
6329
6496
  numeratorData,
6330
6497
  denominatorData,
@@ -6342,10 +6509,6 @@ function queryPrevalenceOverTime(numeratorFilter, denominatorFilter, granularity
6342
6509
  });
6343
6510
  return Promise.all(subQueries);
6344
6511
  }
6345
- function getFilter(filter) {
6346
- const { displayName, ...filterWithoutDisplayName } = filter;
6347
- return filterWithoutDisplayName;
6348
- }
6349
6512
  function makeArray(arrayOrSingleItem) {
6350
6513
  if (Array.isArray(arrayOrSingleItem)) {
6351
6514
  return arrayOrSingleItem;
@@ -6472,11 +6635,12 @@ const PrevalenceOverTime = ({
6472
6635
  smoothingWindow,
6473
6636
  views,
6474
6637
  confidenceIntervalMethods,
6475
- size,
6638
+ width,
6639
+ height,
6476
6640
  headline = "Prevalence over time"
6477
6641
  }) => {
6478
- const defaultSize = { height: "600px", width: "100%" };
6479
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6642
+ const size = { height, width };
6643
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6480
6644
  PrevalenceOverTimeInner,
6481
6645
  {
6482
6646
  numerator,
@@ -6635,14 +6799,15 @@ var __decorateClass$6 = (decorators, target, key, kind) => {
6635
6799
  let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles {
6636
6800
  constructor() {
6637
6801
  super(...arguments);
6638
- this.numerator = { displayName: "" };
6639
- this.denominator = { displayName: "" };
6802
+ this.numerator = { displayName: "", lapisFilter: {} };
6803
+ this.denominator = {};
6640
6804
  this.granularity = "day";
6641
6805
  this.smoothingWindow = 0;
6642
6806
  this.views = ["bar", "line", "bubble", "table"];
6643
6807
  this.confidenceIntervalMethods = ["wilson"];
6644
6808
  this.headline = "Prevalence over time";
6645
- this.size = void 0;
6809
+ this.width = "100%";
6810
+ this.height = "700px";
6646
6811
  }
6647
6812
  render() {
6648
6813
  return /* @__PURE__ */ u$1(
@@ -6654,7 +6819,8 @@ let PrevalenceOverTimeComponent = class extends PreactLitAdapterWithGridJsStyles
6654
6819
  smoothingWindow: this.smoothingWindow,
6655
6820
  views: this.views,
6656
6821
  confidenceIntervalMethods: this.confidenceIntervalMethods,
6657
- size: this.size,
6822
+ width: this.width,
6823
+ height: this.height,
6658
6824
  headline: this.headline
6659
6825
  }
6660
6826
  );
@@ -6682,8 +6848,11 @@ __decorateClass$6([
6682
6848
  n2({ type: String })
6683
6849
  ], PrevalenceOverTimeComponent.prototype, "headline", 2);
6684
6850
  __decorateClass$6([
6685
- n2({ type: Object })
6686
- ], PrevalenceOverTimeComponent.prototype, "size", 2);
6851
+ n2({ type: String })
6852
+ ], PrevalenceOverTimeComponent.prototype, "width", 2);
6853
+ __decorateClass$6([
6854
+ n2({ type: String })
6855
+ ], PrevalenceOverTimeComponent.prototype, "height", 2);
6687
6856
  PrevalenceOverTimeComponent = __decorateClass$6([
6688
6857
  t$2("gs-prevalence-over-time")
6689
6858
  ], PrevalenceOverTimeComponent);
@@ -6874,14 +7043,15 @@ function toYearMonthDay(d2) {
6874
7043
  }
6875
7044
  const RelativeGrowthAdvantage = ({
6876
7045
  views,
6877
- size,
7046
+ width,
7047
+ height,
6878
7048
  numerator,
6879
7049
  denominator,
6880
7050
  generationTime,
6881
7051
  headline = "Relative growth advantage"
6882
7052
  }) => {
6883
- const defaultSize = { height: "600px", width: "100%" };
6884
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
7053
+ const size = { height, width };
7054
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(
6885
7055
  RelativeGrowthAdvantageInner,
6886
7056
  {
6887
7057
  views,
@@ -7010,7 +7180,8 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
7010
7180
  this.generationTime = 7;
7011
7181
  this.views = ["line"];
7012
7182
  this.headline = "Relative growth advantage";
7013
- this.size = void 0;
7183
+ this.width = "100%";
7184
+ this.height = "700px";
7014
7185
  }
7015
7186
  render() {
7016
7187
  return /* @__PURE__ */ u$1(
@@ -7020,7 +7191,8 @@ let RelativeGrowthAdvantageComponent = class extends PreactLitAdapter {
7020
7191
  denominator: this.denominator,
7021
7192
  generationTime: this.generationTime,
7022
7193
  views: this.views,
7023
- size: this.size,
7194
+ width: this.width,
7195
+ height: this.height,
7024
7196
  headline: this.headline
7025
7197
  }
7026
7198
  );
@@ -7042,8 +7214,11 @@ __decorateClass$5([
7042
7214
  n2({ type: String })
7043
7215
  ], RelativeGrowthAdvantageComponent.prototype, "headline", 2);
7044
7216
  __decorateClass$5([
7045
- n2({ type: Object })
7046
- ], RelativeGrowthAdvantageComponent.prototype, "size", 2);
7217
+ n2({ type: String })
7218
+ ], RelativeGrowthAdvantageComponent.prototype, "width", 2);
7219
+ __decorateClass$5([
7220
+ n2({ type: String })
7221
+ ], RelativeGrowthAdvantageComponent.prototype, "height", 2);
7047
7222
  RelativeGrowthAdvantageComponent = __decorateClass$5([
7048
7223
  t$2("gs-relative-growth-advantage")
7049
7224
  ], RelativeGrowthAdvantageComponent);
@@ -7080,13 +7255,14 @@ async function queryAggregateData(variant, fields, lapis, signal) {
7080
7255
  }
7081
7256
  const Aggregate = ({
7082
7257
  views,
7083
- size,
7258
+ width,
7259
+ height,
7084
7260
  headline = "Mutations",
7085
7261
  filter,
7086
7262
  fields
7087
7263
  }) => {
7088
- const defaultSize = { height: "600px", width: "100%" };
7089
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(AggregateInner, { fields, filter, views }) }) }) });
7264
+ const size = { height, width };
7265
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, headline, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(Headline, { heading: headline, children: /* @__PURE__ */ u$1(AggregateInner, { fields, filter, views }) }) }) });
7090
7266
  };
7091
7267
  const AggregateInner = ({ fields, views, filter }) => {
7092
7268
  const lapis = P(LapisUrlContext);
@@ -7140,7 +7316,8 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
7140
7316
  this.fields = [];
7141
7317
  this.views = ["table"];
7142
7318
  this.filter = {};
7143
- this.size = void 0;
7319
+ this.width = "100%";
7320
+ this.height = "700px";
7144
7321
  this.headline = "Aggregate";
7145
7322
  }
7146
7323
  render() {
@@ -7150,7 +7327,8 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
7150
7327
  fields: this.fields,
7151
7328
  views: this.views,
7152
7329
  filter: this.filter,
7153
- size: this.size,
7330
+ width: this.width,
7331
+ height: this.height,
7154
7332
  headline: this.headline
7155
7333
  }
7156
7334
  );
@@ -7166,8 +7344,11 @@ __decorateClass$4([
7166
7344
  n2({ type: Object })
7167
7345
  ], AggregateComponent.prototype, "filter", 2);
7168
7346
  __decorateClass$4([
7169
- n2({ type: Object })
7170
- ], AggregateComponent.prototype, "size", 2);
7347
+ n2({ type: String })
7348
+ ], AggregateComponent.prototype, "width", 2);
7349
+ __decorateClass$4([
7350
+ n2({ type: String })
7351
+ ], AggregateComponent.prototype, "height", 2);
7171
7352
  __decorateClass$4([
7172
7353
  n2({ type: String })
7173
7354
  ], AggregateComponent.prototype, "headline", 2);
@@ -7201,23 +7382,25 @@ const DateRangeSelector = ({
7201
7382
  customSelectOptions,
7202
7383
  earliestDate = "1900-01-01",
7203
7384
  initialValue,
7204
- width
7385
+ width,
7386
+ dateColumn
7205
7387
  }) => {
7206
- const defaultSize = { width: "100%", height: "3rem" };
7207
- const size = width === void 0 ? void 0 : { width, height: defaultSize.height };
7208
- return /* @__PURE__ */ u$1(ErrorBoundary, { defaultSize, size, children: /* @__PURE__ */ u$1(ResizeContainer, { defaultSize, size, children: /* @__PURE__ */ u$1(
7388
+ const size = { width, height: "3rem" };
7389
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(
7209
7390
  DateRangeSelectorInner,
7210
7391
  {
7211
7392
  customSelectOptions,
7212
7393
  earliestDate,
7213
- initialValue
7394
+ initialValue,
7395
+ dateColumn
7214
7396
  }
7215
7397
  ) }) });
7216
7398
  };
7217
7399
  const DateRangeSelectorInner = ({
7218
7400
  customSelectOptions,
7219
7401
  earliestDate = "1900-01-01",
7220
- initialValue
7402
+ initialValue,
7403
+ dateColumn
7221
7404
  }) => {
7222
7405
  const fromDatePickerRef = F(null);
7223
7406
  const toDatePickerRef = F(null);
@@ -7294,8 +7477,8 @@ const DateRangeSelectorInner = ({
7294
7477
  const dateFrom = toYYYYMMDD(dateFromPicker == null ? void 0 : dateFromPicker.selectedDates[0]);
7295
7478
  const dateTo = toYYYYMMDD(dateToPicker == null ? void 0 : dateToPicker.selectedDates[0]);
7296
7479
  const detail = {
7297
- ...dateFrom !== void 0 && { dateFrom },
7298
- ...dateTo !== void 0 && { dateTo }
7480
+ ...dateFrom !== void 0 && { [`${dateColumn}From`]: dateFrom },
7481
+ ...dateTo !== void 0 && { [`${dateColumn}To`]: dateTo }
7299
7482
  };
7300
7483
  (_a = divRef.current) == null ? void 0 : _a.dispatchEvent(
7301
7484
  new CustomEvent("gs-date-range-changed", {
@@ -7409,7 +7592,8 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
7409
7592
  this.customSelectOptions = [];
7410
7593
  this.earliestDate = "1900-01-01";
7411
7594
  this.initialValue = "last6Months";
7412
- this.width = void 0;
7595
+ this.width = "100%";
7596
+ this.dateColumn = "date";
7413
7597
  }
7414
7598
  render() {
7415
7599
  return /* @__PURE__ */ u$1(
@@ -7418,6 +7602,7 @@ let DateRangeSelectorComponent = class extends PreactLitAdapter {
7418
7602
  customSelectOptions: this.customSelectOptions,
7419
7603
  earliestDate: this.earliestDate,
7420
7604
  initialValue: this.initialValue,
7605
+ dateColumn: this.dateColumn,
7421
7606
  width: this.width
7422
7607
  }
7423
7608
  );
@@ -7433,15 +7618,29 @@ __decorateClass$3([
7433
7618
  n2()
7434
7619
  ], DateRangeSelectorComponent.prototype, "initialValue", 2);
7435
7620
  __decorateClass$3([
7436
- n2({ type: Object })
7621
+ n2({ type: String })
7437
7622
  ], DateRangeSelectorComponent.prototype, "width", 2);
7623
+ __decorateClass$3([
7624
+ n2({ type: String })
7625
+ ], DateRangeSelectorComponent.prototype, "dateColumn", 2);
7438
7626
  DateRangeSelectorComponent = __decorateClass$3([
7439
7627
  t$2("gs-date-range-selector")
7440
7628
  ], DateRangeSelectorComponent);
7441
7629
  async function fetchAutocompletionList(fields, lapis, signal) {
7442
7630
  const toAncestorInHierarchyOverwriteValues = Array(fields.length - 1).fill(0).map((_2, i2) => i2 + 1).map((i2) => fields.slice(i2).reduce((acc, field) => ({ ...acc, [field]: null }), {}));
7443
7631
  const fetchAggregatedOperator = new FetchAggregatedOperator({}, fields);
7444
- const data = (await fetchAggregatedOperator.evaluate(lapis, signal)).content;
7632
+ let data;
7633
+ try {
7634
+ data = (await fetchAggregatedOperator.evaluate(lapis, signal)).content;
7635
+ } catch (error) {
7636
+ if (error instanceof LapisError) {
7637
+ throw new UserFacingError(
7638
+ `Failed to fetch autocomplete list from LAPIS: ${error.problemDetail.status} ${error.problemDetail.title ?? ""}`,
7639
+ error.problemDetail.detail ?? error.message
7640
+ );
7641
+ }
7642
+ throw error;
7643
+ }
7445
7644
  const locationValues = data.map((entry) => fields.reduce((acc, field) => ({ ...acc, [field]: entry[field] }), {})).reduce((setOfAllHierarchies, entry) => {
7446
7645
  setOfAllHierarchies.add(JSON.stringify(entry));
7447
7646
  toAncestorInHierarchyOverwriteValues.forEach((overwriteValues) => {
@@ -7471,15 +7670,14 @@ function compareLocationEntries(fields) {
7471
7670
  };
7472
7671
  }
7473
7672
  const LocationFilter = ({ width, initialValue, fields }) => {
7474
- const defaultSize = { width: "100%", height: "3rem" };
7475
- const size = width === void 0 ? void 0 : { width, height: defaultSize.height };
7476
- return /* @__PURE__ */ u$1(ErrorBoundary, { defaultSize, size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(LocationFilterInner, { initialValue, fields }) }) });
7673
+ const size = { width, height: "3rem" };
7674
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(LocationFilterInner, { initialValue, fields }) }) });
7477
7675
  };
7478
7676
  const LocationFilterInner = ({ initialValue, fields }) => {
7479
7677
  const lapis = P(LapisUrlContext);
7480
7678
  const [value, setValue] = p(initialValue ?? "");
7481
7679
  const [unknownLocation, setUnknownLocation] = p(false);
7482
- const formRef = F(null);
7680
+ const divRef = F(null);
7483
7681
  const { data, error, isLoading } = useQuery(() => fetchAutocompletionList(fields, lapis), [fields, lapis]);
7484
7682
  if (isLoading) {
7485
7683
  return /* @__PURE__ */ u$1(LoadingDisplay, {});
@@ -7488,35 +7686,27 @@ const LocationFilterInner = ({ initialValue, fields }) => {
7488
7686
  return /* @__PURE__ */ u$1(ErrorDisplay, { error });
7489
7687
  }
7490
7688
  const onInput = (event) => {
7491
- if (event.target instanceof HTMLInputElement) {
7492
- const inputValue = event.target.value;
7493
- setValue(inputValue);
7494
- if (unknownLocation) {
7495
- const eventDetail = parseLocation(inputValue, fields);
7496
- if (hasMatchingEntry(data, eventDetail)) {
7497
- setUnknownLocation(false);
7498
- }
7499
- }
7500
- }
7501
- };
7502
- const submit = (event) => {
7503
7689
  var _a;
7504
- event.preventDefault();
7505
- const eventDetail = parseLocation(value, fields);
7690
+ const inputValue = event.currentTarget.value;
7691
+ setValue(inputValue);
7692
+ if (inputValue.trim() === value.trim()) {
7693
+ return;
7694
+ }
7695
+ const eventDetail = parseLocation(inputValue, fields);
7506
7696
  if (hasMatchingEntry(data, eventDetail)) {
7507
- setUnknownLocation(false);
7508
- (_a = formRef.current) == null ? void 0 : _a.dispatchEvent(
7697
+ (_a = divRef.current) == null ? void 0 : _a.dispatchEvent(
7509
7698
  new CustomEvent("gs-location-changed", {
7510
7699
  detail: eventDetail,
7511
7700
  bubbles: true,
7512
7701
  composed: true
7513
7702
  })
7514
7703
  );
7704
+ setUnknownLocation(false);
7515
7705
  } else {
7516
7706
  setUnknownLocation(true);
7517
7707
  }
7518
7708
  };
7519
- return /* @__PURE__ */ u$1("form", { class: "flex w-full", onSubmit: submit, ref: formRef, children: [
7709
+ return /* @__PURE__ */ u$1("div", { class: "flex w-full", ref: divRef, children: [
7520
7710
  /* @__PURE__ */ u$1(
7521
7711
  "input",
7522
7712
  {
@@ -7530,8 +7720,7 @@ const LocationFilterInner = ({ initialValue, fields }) => {
7530
7720
  /* @__PURE__ */ u$1("datalist", { id: "countries", children: data == null ? void 0 : data.map((v2) => {
7531
7721
  const value2 = fields.map((field) => v2[field]).filter((value3) => value3 !== null).join(" / ");
7532
7722
  return /* @__PURE__ */ u$1("option", { value: value2 }, value2);
7533
- }) }),
7534
- /* @__PURE__ */ u$1("button", { class: "btn btn-primary ml-1", type: "submit", children: "Submit" })
7723
+ }) })
7535
7724
  ] });
7536
7725
  };
7537
7726
  const parseLocation = (location, fields) => {
@@ -7561,7 +7750,7 @@ let LocationFilterComponent = class extends PreactLitAdapter {
7561
7750
  super(...arguments);
7562
7751
  this.initialValue = "";
7563
7752
  this.fields = [];
7564
- this.width = void 0;
7753
+ this.width = "100%";
7565
7754
  }
7566
7755
  render() {
7567
7756
  return /* @__PURE__ */ u$1(LocationFilter, { initialValue: this.initialValue, fields: this.fields, width: this.width });
@@ -7574,7 +7763,7 @@ __decorateClass$2([
7574
7763
  n2({ type: Array })
7575
7764
  ], LocationFilterComponent.prototype, "fields", 2);
7576
7765
  __decorateClass$2([
7577
- n2({ type: Object })
7766
+ n2({ type: String })
7578
7767
  ], LocationFilterComponent.prototype, "width", 2);
7579
7768
  LocationFilterComponent = __decorateClass$2([
7580
7769
  t$2("gs-location-filter")
@@ -7585,9 +7774,8 @@ async function fetchAutocompleteList(lapis, field, signal) {
7585
7774
  return data.map((item) => item[field]);
7586
7775
  }
7587
7776
  const TextInput = ({ width, lapisField, placeholderText, initialValue }) => {
7588
- const defaultSize = { width: "100%", height: "3rem" };
7589
- const size = width === void 0 ? void 0 : { width, height: defaultSize.height };
7590
- return /* @__PURE__ */ u$1(ErrorBoundary, { defaultSize, size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(TextInputInner, { lapisField, placeholderText, initialValue }) }) });
7777
+ const size = { width, height: "3rem" };
7778
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(TextInputInner, { lapisField, placeholderText, initialValue }) }) });
7591
7779
  };
7592
7780
  const TextInputInner = ({
7593
7781
  lapisField,
@@ -7658,7 +7846,7 @@ let TextInputComponent = class extends PreactLitAdapter {
7658
7846
  this.initialValue = "";
7659
7847
  this.lapisField = "";
7660
7848
  this.placeholderText = "";
7661
- this.width = void 0;
7849
+ this.width = "100%";
7662
7850
  }
7663
7851
  render() {
7664
7852
  return /* @__PURE__ */ u$1(
@@ -7682,7 +7870,7 @@ __decorateClass$1([
7682
7870
  n2()
7683
7871
  ], TextInputComponent.prototype, "placeholderText", 2);
7684
7872
  __decorateClass$1([
7685
- n2({ type: Object })
7873
+ n2({ type: String })
7686
7874
  ], TextInputComponent.prototype, "width", 2);
7687
7875
  TextInputComponent = __decorateClass$1([
7688
7876
  t$2("gs-text-input")
@@ -7763,9 +7951,9 @@ const DeleteIcon = () => {
7763
7951
  }
7764
7952
  );
7765
7953
  };
7766
- const MutationFilter = ({ initialValue, size }) => {
7767
- const defaultSize = { width: "100%", height: "6.5rem" };
7768
- return /* @__PURE__ */ u$1(ErrorBoundary, { size, defaultSize, children: /* @__PURE__ */ u$1(ResizeContainer, { size, defaultSize, children: /* @__PURE__ */ u$1(MutationFilterInner, { initialValue }) }) });
7954
+ const MutationFilter = ({ initialValue, width, height }) => {
7955
+ const size = { height, width };
7956
+ return /* @__PURE__ */ u$1(ErrorBoundary, { size, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(MutationFilterInner, { initialValue }) }) });
7769
7957
  };
7770
7958
  const MutationFilterInner = ({ initialValue }) => {
7771
7959
  const referenceGenome = P(ReferenceGenomeContext);
@@ -8011,18 +8199,22 @@ let MutationFilterComponent = class extends PreactLitAdapter {
8011
8199
  constructor() {
8012
8200
  super(...arguments);
8013
8201
  this.initialValue = void 0;
8014
- this.size = void 0;
8202
+ this.width = "100%";
8203
+ this.height = "6.5rem";
8015
8204
  }
8016
8205
  render() {
8017
- return /* @__PURE__ */ u$1(ReferenceGenomesAwaiter, { children: /* @__PURE__ */ u$1(MutationFilter, { initialValue: this.initialValue, size: this.size }) });
8206
+ return /* @__PURE__ */ u$1(ReferenceGenomesAwaiter, { children: /* @__PURE__ */ u$1(MutationFilter, { initialValue: this.initialValue, width: this.width, height: this.height }) });
8018
8207
  }
8019
8208
  };
8020
8209
  __decorateClass([
8021
8210
  n2()
8022
8211
  ], MutationFilterComponent.prototype, "initialValue", 2);
8023
8212
  __decorateClass([
8024
- n2({ type: Object })
8025
- ], MutationFilterComponent.prototype, "size", 2);
8213
+ n2({ type: String })
8214
+ ], MutationFilterComponent.prototype, "width", 2);
8215
+ __decorateClass([
8216
+ n2({ type: String })
8217
+ ], MutationFilterComponent.prototype, "height", 2);
8026
8218
  MutationFilterComponent = __decorateClass([
8027
8219
  t$2("gs-mutation-filter")
8028
8220
  ], MutationFilterComponent);