@genspectrum/dashboard-components 0.13.7 → 0.14.2

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 (82) hide show
  1. package/custom-elements.json +24 -62
  2. package/dist/{LineageFilterChangedEvent-GedKNGFI.js → LineageFilterChangedEvent-C9dXOxt6.js} +11 -3
  3. package/dist/LineageFilterChangedEvent-C9dXOxt6.js.map +1 -0
  4. package/dist/assets/mutationOverTimeWorker-Dxnxrfe0.js.map +1 -1
  5. package/dist/components.d.ts +40 -50
  6. package/dist/components.js +112 -91
  7. package/dist/components.js.map +1 -1
  8. package/dist/util.d.ts +38 -28
  9. package/dist/util.js +1 -1
  10. package/package.json +2 -2
  11. package/src/lapisApi/lapisApi.ts +1 -1
  12. package/src/operator/FillMissingOperator.spec.ts +1 -1
  13. package/src/operator/GroupByAndSumOperator.spec.ts +1 -1
  14. package/src/operator/GroupByOperator.spec.ts +2 -2
  15. package/src/operator/MapOperator.spec.ts +1 -1
  16. package/src/operator/MockOperator.spec.ts +1 -1
  17. package/src/operator/MockOperator.ts +6 -4
  18. package/src/operator/SortOperator.spec.ts +1 -1
  19. package/src/preact/LapisUrlContext.ts +14 -1
  20. package/src/preact/aggregatedData/aggregate.stories.tsx +4 -4
  21. package/src/preact/aggregatedData/aggregate.tsx +3 -4
  22. package/src/preact/components/csv-download-button.stories.tsx +2 -2
  23. package/src/preact/components/csv-download-button.tsx +1 -1
  24. package/src/preact/components/error-boundary.stories.tsx +5 -5
  25. package/src/preact/components/error-boundary.tsx +14 -3
  26. package/src/preact/components/error-display.stories.tsx +9 -9
  27. package/src/preact/components/fullscreen.tsx +3 -3
  28. package/src/preact/components/info.tsx +1 -1
  29. package/src/preact/components/mutation-type-selector.stories.tsx +1 -1
  30. package/src/preact/components/table.stories.tsx +3 -3
  31. package/src/preact/components/table.tsx +1 -1
  32. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +34 -20
  33. package/src/preact/dateRangeSelector/computeInitialValues.ts +25 -21
  34. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +107 -46
  35. package/src/preact/dateRangeSelector/date-range-selector.tsx +31 -22
  36. package/src/preact/dateRangeSelector/dateRangeOption.ts +11 -1
  37. package/src/preact/lineageFilter/lineage-filter.stories.tsx +9 -9
  38. package/src/preact/lineageFilter/lineage-filter.tsx +3 -4
  39. package/src/preact/locationFilter/fetchAutocompletionList.ts +1 -1
  40. package/src/preact/locationFilter/location-filter.stories.tsx +9 -9
  41. package/src/preact/locationFilter/location-filter.tsx +4 -4
  42. package/src/preact/map/sequences-by-location.stories.tsx +4 -4
  43. package/src/preact/map/sequences-by-location.tsx +3 -4
  44. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -3
  45. package/src/preact/mutationComparison/mutation-comparison.tsx +4 -4
  46. package/src/preact/mutationFilter/mutation-filter-info.tsx +3 -3
  47. package/src/preact/mutationFilter/mutation-filter.stories.tsx +7 -7
  48. package/src/preact/mutations/getMutationsGridData.ts +1 -1
  49. package/src/preact/mutations/mutations.stories.tsx +3 -3
  50. package/src/preact/mutations/mutations.tsx +4 -4
  51. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  52. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +4 -4
  53. package/src/preact/mutationsOverTime/mutations-over-time.tsx +5 -4
  54. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +4 -4
  55. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
  56. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +4 -4
  57. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -4
  58. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -4
  59. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +4 -4
  60. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -4
  61. package/src/preact/shared/floating-ui/hooks.ts +1 -1
  62. package/src/preact/statistic/statistics.stories.tsx +3 -3
  63. package/src/preact/statistic/statistics.tsx +2 -3
  64. package/src/preact/textInput/text-input.stories.tsx +7 -7
  65. package/src/preact/textInput/text-input.tsx +3 -4
  66. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +3 -3
  67. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -4
  68. package/src/utils/map2d.ts +1 -0
  69. package/src/web-components/PreactLitAdapter.tsx +3 -3
  70. package/src/web-components/gs-app.stories.ts +7 -7
  71. package/src/web-components/gs-app.ts +3 -1
  72. package/src/web-components/input/gs-date-range-selector.stories.ts +10 -17
  73. package/src/web-components/input/gs-date-range-selector.tsx +15 -38
  74. package/src/web-components/input/gs-lineage-filter.stories.ts +1 -1
  75. package/src/web-components/input/gs-location-filter.stories.ts +1 -1
  76. package/src/web-components/input/gs-mutation-filter.stories.ts +7 -7
  77. package/src/web-components/input/gs-text-input.stories.ts +3 -3
  78. package/src/web-components/visualization/gs-aggregate.tsx +2 -2
  79. package/standalone-bundle/assets/mutationOverTimeWorker-CmSrq4SZ.js.map +1 -1
  80. package/standalone-bundle/dashboard-components.js +6068 -6055
  81. package/standalone-bundle/dashboard-components.js.map +1 -1
  82. package/dist/LineageFilterChangedEvent-GedKNGFI.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import type { StoryObj } from '@storybook/preact';
2
2
  import { expect, waitFor } from '@storybook/test';
3
3
 
4
- import { LapisUrlContext } from '../LapisUrlContext';
4
+ import { LapisUrlContextProvider } from '../LapisUrlContext';
5
5
  import denominatorFilter from './__mockData__/denominatorFilter.json';
6
6
  import denominatorOneDataset from './__mockData__/denominatorFilterOneDataset.json';
7
7
  import numeratorFilterEG from './__mockData__/numeratorFilterEG.json';
@@ -42,9 +42,9 @@ export default {
42
42
 
43
43
  const Template = {
44
44
  render: (args: PrevalenceOverTimeProps) => (
45
- <LapisUrlContext.Provider value={LAPIS_URL}>
45
+ <LapisUrlContextProvider value={LAPIS_URL}>
46
46
  <PrevalenceOverTime {...args} />
47
- </LapisUrlContext.Provider>
47
+ </LapisUrlContextProvider>
48
48
  ),
49
49
  };
50
50
 
@@ -254,7 +254,7 @@ export const WithNoLapisDateField: StoryObj<PrevalenceOverTimeProps> = {
254
254
  lapisDateField: '',
255
255
  },
256
256
  play: async ({ canvasElement, step }) => {
257
- step('expect error message', async () => {
257
+ await step('expect error message', async () => {
258
258
  await expectInvalidAttributesErrorMessage(canvasElement, 'String must contain at least 1 character(s)');
259
259
  });
260
260
  },
@@ -1,5 +1,5 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { useContext, useEffect, useState } from 'preact/hooks';
2
+ import { useEffect, useState } from 'preact/hooks';
3
3
  import z from 'zod';
4
4
 
5
5
  import { getPrevalenceOverTimeTableData } from './getPrevalenceOverTimeTableData';
@@ -9,7 +9,7 @@ import PrevalenceOverTimeLineChart from './prevalence-over-time-line-chart';
9
9
  import PrevalenceOverTimeTable from './prevalence-over-time-table';
10
10
  import { type PrevalenceOverTimeData, queryPrevalenceOverTime } from '../../query/queryPrevalenceOverTime';
11
11
  import { lapisFilterSchema, namedLapisFilterSchema, temporalGranularitySchema, views } from '../../types';
12
- import { LapisUrlContext } from '../LapisUrlContext';
12
+ import { useLapisUrl } from '../LapisUrlContext';
13
13
  import { ConfidenceIntervalSelector } from '../components/confidence-interval-selector';
14
14
  import { CsvDownloadButton } from '../components/csv-download-button';
15
15
  import { ErrorBoundary } from '../components/error-boundary';
@@ -65,7 +65,7 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = (c
65
65
 
66
66
  export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeProps> = (componentProps) => {
67
67
  const { numeratorFilters, denominatorFilter, granularity, smoothingWindow, lapisDateField } = componentProps;
68
- const lapis = useContext(LapisUrlContext);
68
+ const lapis = useLapisUrl();
69
69
 
70
70
  const { data, error, isLoading } = useQuery(
71
71
  () =>
@@ -226,7 +226,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
226
226
 
227
227
  const PrevalenceOverTimeInfo: FunctionComponent<PrevalenceOverTimeProps> = (componentProps) => {
228
228
  const { granularity, smoothingWindow, views } = componentProps;
229
- const lapis = useContext(LapisUrlContext);
229
+ const lapis = useLapisUrl();
230
230
  return (
231
231
  <Info>
232
232
  <InfoHeadline1>Prevalence over time</InfoHeadline1>
@@ -5,7 +5,7 @@ import denominator from './__mockData__/denominatorFilter.json';
5
5
  import numerator from './__mockData__/numeratorFilter.json';
6
6
  import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './relative-growth-advantage';
7
7
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
- import { LapisUrlContext } from '../LapisUrlContext';
8
+ import { LapisUrlContextProvider } from '../LapisUrlContext';
9
9
  import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
10
10
 
11
11
  export default {
@@ -30,9 +30,9 @@ export default {
30
30
 
31
31
  export const Primary: StoryObj<RelativeGrowthAdvantageProps> = {
32
32
  render: (args: RelativeGrowthAdvantageProps) => (
33
- <LapisUrlContext.Provider value={LAPIS_URL}>
33
+ <LapisUrlContextProvider value={LAPIS_URL}>
34
34
  <RelativeGrowthAdvantage {...args} />
35
- </LapisUrlContext.Provider>
35
+ </LapisUrlContextProvider>
36
36
  ),
37
37
  args: {
38
38
  numeratorFilter: {
@@ -188,7 +188,7 @@ export const WithNoLapisDateField: StoryObj<RelativeGrowthAdvantageProps> = {
188
188
  lapisDateField: '',
189
189
  },
190
190
  play: async ({ canvasElement, step }) => {
191
- step('expect error message', async () => {
191
+ await step('expect error message', async () => {
192
192
  await expectInvalidAttributesErrorMessage(canvasElement, 'String must contain at least 1 character(s)');
193
193
  });
194
194
  },
@@ -1,5 +1,5 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { useContext, useState } from 'preact/hooks';
2
+ import { useState } from 'preact/hooks';
3
3
  import z from 'zod';
4
4
 
5
5
  import RelativeGrowthAdvantageChart from './relative-growth-advantage-chart';
@@ -9,7 +9,7 @@ import {
9
9
  type RelativeGrowthAdvantageData,
10
10
  } from '../../query/queryRelativeGrowthAdvantage';
11
11
  import { lapisFilterSchema, views } from '../../types';
12
- import { LapisUrlContext } from '../LapisUrlContext';
12
+ import { useLapisUrl } from '../LapisUrlContext';
13
13
  import { ErrorBoundary } from '../components/error-boundary';
14
14
  import { Fullscreen } from '../components/fullscreen';
15
15
  import Info, { InfoComponentCode, InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
@@ -52,7 +52,7 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
52
52
  };
53
53
 
54
54
  export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantageProps> = (componentProps) => {
55
- const lapis = useContext(LapisUrlContext);
55
+ const lapis = useLapisUrl();
56
56
  const { numeratorFilter, denominatorFilter, generationTime, lapisDateField } = componentProps;
57
57
 
58
58
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
@@ -160,7 +160,7 @@ const RelativeGrowthAdvantageToolbar: FunctionComponent<RelativeGrowthAdvantageT
160
160
  const RelativeGrowthAdvantageInfo: FunctionComponent<{ originalComponentProps: RelativeGrowthAdvantageProps }> = ({
161
161
  originalComponentProps,
162
162
  }) => {
163
- const lapis = useContext(LapisUrlContext);
163
+ const lapis = useLapisUrl();
164
164
  const generationTime = originalComponentProps.generationTime;
165
165
 
166
166
  return (
@@ -20,7 +20,7 @@ export function useFloatingUi(
20
20
  const { current: floating } = floatingRef;
21
21
 
22
22
  const update = () => {
23
- computePosition(reference, floating, {
23
+ void computePosition(reference, floating, {
24
24
  placement,
25
25
  middleware,
26
26
  }).then(({ x, y }) => {
@@ -2,7 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
2
2
  import { expect, waitFor, within } from '@storybook/test';
3
3
 
4
4
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
5
- import { LapisUrlContext } from '../LapisUrlContext';
5
+ import { LapisUrlContextProvider } from '../LapisUrlContext';
6
6
  import denominatorData from './__mockData__/denominator.json';
7
7
  import numeratorData from './__mockData__/numerator.json';
8
8
  import { Statistics, type StatisticsProps } from './statistics';
@@ -55,9 +55,9 @@ export default meta;
55
55
 
56
56
  export const Default: StoryObj<StatisticsProps> = {
57
57
  render: (args) => (
58
- <LapisUrlContext.Provider value={LAPIS_URL}>
58
+ <LapisUrlContextProvider value={LAPIS_URL}>
59
59
  <Statistics {...args} />
60
- </LapisUrlContext.Provider>
60
+ </LapisUrlContextProvider>
61
61
  ),
62
62
  args: {
63
63
  numeratorFilter: {
@@ -1,10 +1,9 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { useContext } from 'preact/hooks';
3
2
  import z from 'zod';
4
3
 
5
4
  import { queryGeneralStatistics } from '../../query/queryGeneralStatistics';
6
5
  import { lapisFilterSchema } from '../../types';
7
- import { LapisUrlContext } from '../LapisUrlContext';
6
+ import { useLapisUrl } from '../LapisUrlContext';
8
7
  import { ErrorBoundary } from '../components/error-boundary';
9
8
  import { LoadingDisplay } from '../components/loading-display';
10
9
  import { NoDataDisplay } from '../components/no-data-display';
@@ -35,7 +34,7 @@ export const Statistics: FunctionComponent<StatisticsProps> = (componentProps) =
35
34
 
36
35
  export const StatisticsInner: FunctionComponent<StatisticsProps> = (componentProps) => {
37
36
  const { numeratorFilter, denominatorFilter } = componentProps;
38
- const lapis = useContext(LapisUrlContext);
37
+ const lapis = useLapisUrl();
39
38
 
40
39
  const { data, error, isLoading } = useQuery(async () => {
41
40
  return queryGeneralStatistics(numeratorFilter, denominatorFilter, lapis);
@@ -5,7 +5,7 @@ import data from './__mockData__/aggregated_hosts.json';
5
5
  import { TextInput, type TextInputProps } from './text-input';
6
6
  import { previewHandles } from '../../../.storybook/preview';
7
7
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
- import { LapisUrlContext } from '../LapisUrlContext';
8
+ import { LapisUrlContextProvider } from '../LapisUrlContext';
9
9
  import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
10
10
 
11
11
  const meta: Meta<TextInputProps> = {
@@ -67,9 +67,9 @@ export default meta;
67
67
 
68
68
  export const Default: StoryObj<TextInputProps> = {
69
69
  render: (args) => (
70
- <LapisUrlContext.Provider value={LAPIS_URL}>
70
+ <LapisUrlContextProvider value={LAPIS_URL}>
71
71
  <TextInput {...args} />
72
- </LapisUrlContext.Provider>
72
+ </LapisUrlContextProvider>
73
73
  ),
74
74
  args: {
75
75
  lapisField: 'host',
@@ -92,13 +92,13 @@ export const RemoveInitialValue: StoryObj<TextInputProps> = {
92
92
  const canvas = within(canvasElement);
93
93
 
94
94
  const changedListenerMock = fn();
95
- await step('Setup event listener mock', async () => {
95
+ await step('Setup event listener mock', () => {
96
96
  canvasElement.addEventListener('gs-text-input-changed', changedListenerMock);
97
97
  });
98
98
 
99
- await waitFor(() => {
99
+ await waitFor(async () => {
100
100
  const input = canvas.getByPlaceholderText('Enter a host name', { exact: false });
101
- expect(input).toHaveValue('Homo sapiens');
101
+ await expect(input).toHaveValue('Homo sapiens');
102
102
  });
103
103
 
104
104
  await step('Remove initial value', async () => {
@@ -122,7 +122,7 @@ export const WithNoLapisField: StoryObj<TextInputProps> = {
122
122
  lapisField: '',
123
123
  },
124
124
  play: async ({ canvasElement, step }) => {
125
- step('expect error message', async () => {
125
+ await step('expect error message', async () => {
126
126
  await expectInvalidAttributesErrorMessage(canvasElement, 'String must contain at least 1 character(s)');
127
127
  });
128
128
  },
@@ -1,10 +1,9 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { useContext } from 'preact/hooks';
3
2
  import z from 'zod';
4
3
 
5
- import { fetchStringAutocompleteList } from './fetchStringAutocompleteList';
6
- import { LapisUrlContext } from '../LapisUrlContext';
4
+ import { useLapisUrl } from '../LapisUrlContext';
7
5
  import { TextInputChangedEvent } from './TextInputChangedEvent';
6
+ import { fetchStringAutocompleteList } from './fetchStringAutocompleteList';
8
7
  import { lapisFilterSchema } from '../../types';
9
8
  import { DownshiftCombobox } from '../components/downshift-combobox';
10
9
  import { ErrorBoundary } from '../components/error-boundary';
@@ -46,7 +45,7 @@ const TextInputInner: FunctionComponent<TextInputInnerProps> = ({
46
45
  placeholderText,
47
46
  lapisFilter,
48
47
  }) => {
49
- const lapis = useContext(LapisUrlContext);
48
+ const lapis = useLapisUrl();
50
49
 
51
50
  const { data, error, isLoading } = useQuery(
52
51
  () => fetchStringAutocompleteList({ lapis, field: lapisField, lapisFilter }),
@@ -3,7 +3,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
3
3
  import { WastewaterMutationsOverTime, type WastewaterMutationsOverTimeProps } from './wastewater-mutations-over-time';
4
4
  import { WISE_DETAILS_ENDPOINT, WISE_LAPIS_URL } from '../../../constants';
5
5
  import referenceGenome from '../../../lapisApi/__mockData__/referenceGenome.json';
6
- import { LapisUrlContext } from '../../LapisUrlContext';
6
+ import { LapisUrlContextProvider } from '../../LapisUrlContext';
7
7
  import { ReferenceGenomeContext } from '../../ReferenceGenomeContext';
8
8
  import details from './__mockData__/details.json';
9
9
 
@@ -28,11 +28,11 @@ export default meta;
28
28
 
29
29
  const Template = {
30
30
  render: (args: WastewaterMutationsOverTimeProps) => (
31
- <LapisUrlContext.Provider value={WISE_LAPIS_URL}>
31
+ <LapisUrlContextProvider value={WISE_LAPIS_URL}>
32
32
  <ReferenceGenomeContext.Provider value={referenceGenome}>
33
33
  <WastewaterMutationsOverTime {...args} />
34
34
  </ReferenceGenomeContext.Provider>
35
- </LapisUrlContext.Provider>
35
+ </LapisUrlContextProvider>
36
36
  ),
37
37
  };
38
38
 
@@ -1,10 +1,10 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { type Dispatch, type StateUpdater, useContext, useState } from 'preact/hooks';
2
+ import { type Dispatch, type StateUpdater, useState } from 'preact/hooks';
3
3
  import z from 'zod';
4
4
 
5
5
  import { computeWastewaterMutationsOverTimeDataPerLocation } from './computeWastewaterMutationsOverTimeDataPerLocation';
6
6
  import { lapisFilterSchema, sequenceTypeSchema } from '../../../types';
7
- import { LapisUrlContext } from '../../LapisUrlContext';
7
+ import { useLapisUrl } from '../../LapisUrlContext';
8
8
  import { type ColorScale } from '../../components/color-scale-selector';
9
9
  import { ColorScaleSelectorDropdown } from '../../components/color-scale-selector-dropdown';
10
10
  import { ErrorBoundary } from '../../components/error-boundary';
@@ -44,7 +44,7 @@ export const WastewaterMutationsOverTime: FunctionComponent<WastewaterMutationsO
44
44
  export const WastewaterMutationsOverTimeInner: FunctionComponent<WastewaterMutationsOverTimeProps> = (
45
45
  componentProps,
46
46
  ) => {
47
- const lapis = useContext(LapisUrlContext);
47
+ const lapis = useLapisUrl();
48
48
 
49
49
  const {
50
50
  data: mutationOverTimeDataPerLocation,
@@ -142,7 +142,7 @@ type WastewaterMutationsOverTimeInfoProps = {
142
142
  const WastewaterMutationsOverTimeInfo: FunctionComponent<WastewaterMutationsOverTimeInfoProps> = ({
143
143
  originalComponentProps,
144
144
  }) => {
145
- const lapis = useContext(LapisUrlContext);
145
+ const lapis = useLapisUrl();
146
146
  return (
147
147
  <Info>
148
148
  <InfoHeadline1>Info for mutations over time</InfoHeadline1>
@@ -150,6 +150,7 @@ export class Map2dView<Key1 extends object | string, Key2 extends object | strin
150
150
  this.keysSecondAxis = new Map(map.keysSecondAxis);
151
151
 
152
152
  if (map instanceof Map2dView) {
153
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- the generics match, we know that.
153
154
  this.baseMap = map.baseMap;
154
155
  }
155
156
  this.baseMap = map;
@@ -7,7 +7,7 @@ import { type JSXInternal } from 'preact/src/jsx';
7
7
  import { lapisContext } from './lapis-context';
8
8
  import { referenceGenomeContext } from './reference-genome-context';
9
9
  import { type ReferenceGenome } from '../lapisApi/ReferenceGenome';
10
- import { LapisUrlContext } from '../preact/LapisUrlContext';
10
+ import { LapisUrlContextProvider } from '../preact/LapisUrlContext';
11
11
  import { ReferenceGenomeContext } from '../preact/ReferenceGenomeContext';
12
12
  import minMaxPercentSliderCss from '../preact/components/min-max-percent-slider.css?inline';
13
13
  import tailwindStyle from '../styles/tailwind.css?inline';
@@ -47,11 +47,11 @@ export abstract class PreactLitAdapter extends ReactiveElement {
47
47
 
48
48
  override update(changedProperties: PropertyValues) {
49
49
  const vdom = (
50
- <LapisUrlContext.Provider value={this.lapis}>
50
+ <LapisUrlContextProvider value={this.lapis}>
51
51
  <ReferenceGenomeContext.Provider value={this.referenceGenome}>
52
52
  {this.render()}
53
53
  </ReferenceGenomeContext.Provider>
54
- </LapisUrlContext.Provider>
54
+ </LapisUrlContextProvider>
55
55
  );
56
56
  super.update(changedProperties);
57
57
  render(vdom, this.renderRoot);
@@ -50,9 +50,9 @@ export const Default: StoryObj<{ lapis: string }> = {
50
50
  play: async ({ canvasElement }) => {
51
51
  const canvas = within(canvasElement);
52
52
 
53
- await waitFor(() => {
54
- expect(canvas.getByText(LAPIS_URL)).toBeVisible();
55
- expect(canvas.getByText('"name": "ORF1a",', { exact: false })).toBeVisible();
53
+ await waitFor(async () => {
54
+ await expect(canvas.getByText(LAPIS_URL)).toBeVisible();
55
+ await expect(canvas.getByText('"name": "ORF1a",', { exact: false })).toBeVisible();
56
56
  });
57
57
  },
58
58
  };
@@ -66,8 +66,8 @@ export const WithNoLapisUrl: StoryObj<{ lapis: string }> = {
66
66
  play: async ({ canvasElement }) => {
67
67
  const canvas = within(canvasElement);
68
68
 
69
- await waitFor(() => {
70
- expect(canvas.getByText("Error: Invalid LAPIS URL: 'notAValidUrl'", { exact: false })).toBeVisible();
69
+ await waitFor(async () => {
70
+ await expect(canvas.getByText("Error: Invalid LAPIS URL: 'notAValidUrl'", { exact: false })).toBeVisible();
71
71
  });
72
72
  },
73
73
  };
@@ -103,8 +103,8 @@ export const FailsToFetchReferenceGenome: StoryObj<{ lapis: string }> = {
103
103
  play: async ({ canvasElement }) => {
104
104
  const canvas = within(canvasElement);
105
105
 
106
- await waitFor(() => {
107
- expect(canvas.getByText('Error: Cannot fetch reference genome.', { exact: false })).toBeVisible();
106
+ await waitFor(async () => {
107
+ await expect(canvas.getByText('Error: Cannot fetch reference genome.', { exact: false })).toBeVisible();
108
108
  });
109
109
  },
110
110
  };
@@ -55,7 +55,9 @@ export class AppComponent extends LitElement {
55
55
  task: async () => {
56
56
  const lapisUrl = lapisUrlSchema.parse(this.lapis);
57
57
 
58
- this.referenceGenome = await fetchReferenceGenome(lapisUrl);
58
+ this.referenceGenome = await fetchReferenceGenome(
59
+ lapisUrl.endsWith('/') ? lapisUrl.slice(0, -1) : lapisUrl,
60
+ );
59
61
  },
60
62
  args: () => [this.lapis],
61
63
  });
@@ -16,9 +16,7 @@ const codeExample = String.raw`
16
16
  <gs-date-range-selector
17
17
  dateRangeOptions='[{ "label": "Year 2021", "dateFrom": "2021-01-01", "dateTo": "2021-12-31" }]'
18
18
  earliestDate="1970-01-01"
19
- initialValue="Year 2021"
20
- initialDateFrom="2020-01-01"
21
- initialDateTo="2021-01-01"
19
+ value="Year 2021"
22
20
  width="100%"
23
21
  lapisDateField="myDateColumn"
24
22
  ></gs-date-range-selector>`;
@@ -40,11 +38,10 @@ const meta: Meta<Required<DateRangeSelectorProps>> = {
40
38
  },
41
39
  }),
42
40
  argTypes: {
43
- initialValue: {
41
+ value: {
44
42
  control: {
45
- type: 'select',
43
+ type: 'object',
46
44
  },
47
- options: [dateRangeOptionPresets.lastMonth.label, dateRangeOptionPresets.allTimes.label, 'CustomDateRange'],
48
45
  },
49
46
  lapisDateField: { control: { type: 'text' } },
50
47
  dateRangeOptions: {
@@ -71,11 +68,9 @@ const meta: Meta<Required<DateRangeSelectorProps>> = {
71
68
  customDateRange,
72
69
  ],
73
70
  earliestDate: '1970-01-01',
74
- initialValue: dateRangeOptionPresets.lastMonth.label,
71
+ value: dateRangeOptionPresets.lastMonth.label,
75
72
  lapisDateField: 'aDateColumn',
76
73
  width: '100%',
77
- initialDateFrom: undefined,
78
- initialDateTo: undefined,
79
74
  },
80
75
  tags: ['autodocs'],
81
76
  };
@@ -89,9 +84,7 @@ export const Default: StoryObj<Required<DateRangeSelectorProps>> = {
89
84
  <gs-date-range-selector
90
85
  .dateRangeOptions=${args.dateRangeOptions}
91
86
  .earliestDate=${args.earliestDate}
92
- .initialValue=${args.initialValue}
93
- .initialDateFrom=${args.initialDateFrom}
94
- .initialDateTo=${args.initialDateTo}
87
+ .value=${args.value}
95
88
  .width=${args.width}
96
89
  .lapisDateField=${args.lapisDateField}
97
90
  ></gs-date-range-selector>
@@ -106,15 +99,15 @@ export const FiresEvents: StoryObj<Required<DateRangeSelectorProps>> = {
106
99
 
107
100
  const filterChangedListenerMock = fn();
108
101
  const optionChangedListenerMock = fn();
109
- await step('Setup event listener mock', async () => {
102
+ await step('Setup event listener mock', () => {
110
103
  canvasElement.addEventListener('gs-date-range-filter-changed', filterChangedListenerMock);
111
104
  canvasElement.addEventListener('gs-date-range-option-changed', optionChangedListenerMock);
112
105
  });
113
106
 
114
107
  await step('Expect last 6 months to be selected', async () => {
115
108
  await expect(selectField(canvas)).toHaveValue('Last month');
116
- await waitFor(() => {
117
- expect(dateToPicker(canvas)).toHaveValue(toYYYYMMDD(new Date()));
109
+ await waitFor(async () => {
110
+ await expect(dateToPicker(canvas)).toHaveValue(toYYYYMMDD(new Date()));
118
111
  });
119
112
  });
120
113
 
@@ -140,5 +133,5 @@ export const FiresEvents: StoryObj<Required<DateRangeSelectorProps>> = {
140
133
  },
141
134
  };
142
135
 
143
- const dateToPicker = (canvas: ReturnType<typeof within>) => canvas.getByPlaceholderText('Date to');
144
- const selectField = (canvas: ReturnType<typeof within>) => canvas.getByRole('combobox');
136
+ const dateToPicker = (canvas: ReturnType<typeof within>): HTMLElement => canvas.getByPlaceholderText('Date to');
137
+ const selectField = (canvas: ReturnType<typeof within>): HTMLElement => canvas.getByRole('combobox');
@@ -46,15 +46,18 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
46
46
  * Contains the selected dateRangeOption or when users select custom values it contains the selected dates.
47
47
  *
48
48
  * Use this event, when you want to control this component in your JS application.
49
+ * You can supply the `detail` of this event to the `value` attribute of this component.
49
50
  */
50
51
  @customElement('gs-date-range-selector')
51
52
  export class DateRangeSelectorComponent extends PreactLitAdapter {
52
53
  /**
53
54
  * An array of date range options that the select field should provide.
54
- * The `label` will be shown to the user, and it will be available as `initialValue`.
55
+ * The `label` will be shown to the user, and it will be available as `value`.
55
56
  * The dates must be in the format `YYYY-MM-DD`.
56
57
  *
57
58
  * If dateFrom or dateTo is not set, the component will default to the `earliestDate` or the current date.
59
+ *
60
+ * We provide some options in `dateRangeOptionPresets` for convenience.
58
61
  */
59
62
  @property({ type: Array })
60
63
  dateRangeOptions: { label: string; dateFrom?: string; dateTo?: string }[] = [];
@@ -66,33 +69,17 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
66
69
  earliestDate: string = '1900-01-01';
67
70
 
68
71
  /**
69
- * The initial value to use for this date range selector.
70
- * Must be a valid label from the `dateRangeOptions`.
71
- *
72
- * If the value is not set, the component will default to the range `earliestDate` until today.
73
- *
74
- * It will be overwritten if `initialDateFrom` or `initialDateTo` is set.
72
+ * The value to use for this date range selector.
73
+ * - If it is a string, then it must be a valid label from the `dateRangeOptions`.
74
+ * - If it is an object, then it accepts dates in the format `YYYY-MM-DD` for the keys `dateFrom` and `dateTo`.
75
+ * Keys that are not set will default to the `earliestDate` or the current date respectively.
76
+ * - If the attribute is not set, the component will default to the range `earliestDate` until today.
75
77
  *
76
- * We provide some options in `dateRangeOptionPresets` for convenience.
77
- */
78
- @property()
79
- initialValue: string | undefined = undefined;
80
-
81
- /**
82
- * A date string in the format `YYYY-MM-DD`.
83
- * If set, the date range selector will be initialized with the given date (overwriting `initialValue` to `custom`).
84
- * If `initialDateTo` is set, but this is unset, it will default to `earliestDate`.
85
- */
86
- @property()
87
- initialDateFrom: string | undefined = undefined;
88
-
89
- /**
90
- * A date string in the format `YYYY-MM-DD`.
91
- * If set, the date range selector will be initialized with the given date (overwriting `initialValue` to `custom`).
92
- * If `initialDateFrom` is set, but this is unset, it will default to the current date.
78
+ * The `detail` of the `gs-date-range-option-changed` event can be used for this attribute,
79
+ * if you want to control this component in your JS application.
93
80
  */
94
- @property()
95
- initialDateTo: string | undefined = undefined;
81
+ @property({ type: Object })
82
+ value: string | { dateFrom?: string; dateTo?: string } | undefined = undefined;
96
83
 
97
84
  /**
98
85
  * The width of the component.
@@ -113,9 +100,7 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
113
100
  <DateRangeSelector
114
101
  dateRangeOptions={this.dateRangeOptions}
115
102
  earliestDate={this.earliestDate}
116
- initialValue={this.initialValue}
117
- initialDateFrom={this.initialDateFrom}
118
- initialDateTo={this.initialDateTo}
103
+ value={this.value}
119
104
  lapisDateField={this.lapisDateField}
120
105
  width={this.width}
121
106
  />
@@ -150,15 +135,7 @@ type CustomSelectOptionsMatches = Expect<
150
135
  type EarliestDateMatches = Expect<
151
136
  Equals<typeof DateRangeSelectorComponent.prototype.earliestDate, DateRangeSelectorProps['earliestDate']>
152
137
  >;
153
- type InitialValueMatches = Expect<
154
- Equals<typeof DateRangeSelectorComponent.prototype.initialValue, DateRangeSelectorProps['initialValue']>
155
- >;
156
- type InitialDateFromMatches = Expect<
157
- Equals<typeof DateRangeSelectorComponent.prototype.initialDateFrom, DateRangeSelectorProps['initialDateFrom']>
158
- >;
159
- type InitialDateToMatches = Expect<
160
- Equals<typeof DateRangeSelectorComponent.prototype.initialDateTo, DateRangeSelectorProps['initialDateTo']>
161
- >;
138
+ type ValueMatches = Expect<Equals<typeof DateRangeSelectorComponent.prototype.value, DateRangeSelectorProps['value']>>;
162
139
  type WidthMatches = Expect<Equals<typeof DateRangeSelectorComponent.prototype.width, DateRangeSelectorProps['width']>>;
163
140
  type DateColumnMatches = Expect<
164
141
  Equals<typeof DateRangeSelectorComponent.prototype.lapisDateField, DateRangeSelectorProps['lapisDateField']>
@@ -181,7 +181,7 @@ export const FiresEvent: StoryObj<Required<LineageFilterProps>> = {
181
181
 
182
182
  const inputField = () => canvas.getByPlaceholderText('Enter a lineage');
183
183
  const listenerMock = fn();
184
- await step('Setup event listener mock', async () => {
184
+ await step('Setup event listener mock', () => {
185
185
  canvasElement.addEventListener('gs-lineage-filter-changed', listenerMock);
186
186
  });
187
187
 
@@ -188,7 +188,7 @@ export const FiresEvent: StoryObj<LocationFilterProps> = {
188
188
  const inputField = () => canvas.getByRole('combobox');
189
189
 
190
190
  const listenerMock = fn();
191
- await step('Setup event listener mock', async () => {
191
+ await step('Setup event listener mock', () => {
192
192
  canvasElement.addEventListener('gs-location-changed', listenerMock);
193
193
  });
194
194
 
@@ -72,7 +72,7 @@ export const FiresFilterChangedEvent: StoryObj<MutationFilterProps> = {
72
72
 
73
73
  const inputField = () => canvas.getByPlaceholderText('Enter a mutation', { exact: false });
74
74
  const listenerMock = fn();
75
- await step('Setup event listener mock', async () => {
75
+ await step('Setup event listener mock', () => {
76
76
  canvasElement.addEventListener('gs-mutation-filter-changed', listenerMock);
77
77
  });
78
78
 
@@ -154,18 +154,18 @@ export const MultiSegmentedReferenceGenomes: StoryObj<MutationFilterProps> = {
154
154
 
155
155
  const inputField = () => canvas.getByPlaceholderText('Enter a mutation', { exact: false });
156
156
 
157
- await waitFor(() => {
157
+ await waitFor(async () => {
158
158
  const placeholderText = inputField().getAttribute('placeholder');
159
159
 
160
- expect(placeholderText).toEqual(
160
+ await expect(placeholderText).toEqual(
161
161
  'Enter a mutation (e.g. seg1:23T, ins_seg1:10462:A, gene1:57Q, ins_gene1:31:N)',
162
162
  );
163
163
  });
164
164
 
165
- await waitFor(() => {
166
- expect(canvas.getByText('seg1:123T')).toBeVisible();
167
- expect(canvas.getByText('gene2:56')).toBeVisible();
168
- return expect(canvas.getByText('ins_seg2:78:AAA')).toBeVisible();
165
+ await waitFor(async () => {
166
+ await expect(canvas.getByText('seg1:123T')).toBeVisible();
167
+ await expect(canvas.getByText('gene2:56')).toBeVisible();
168
+ await expect(canvas.getByText('ins_seg2:78:AAA')).toBeVisible();
169
169
  });
170
170
  },
171
171
  };
@@ -113,7 +113,7 @@ export const FiresEvents: StoryObj<Required<TextInputProps>> = {
113
113
 
114
114
  const inputField = () => canvas.getByPlaceholderText('Enter host name');
115
115
  const listenerMock = fn();
116
- await step('Setup event listener mock', async () => {
116
+ await step('Setup event listener mock', () => {
117
117
  canvasElement.addEventListener('gs-text-input-changed', listenerMock);
118
118
  });
119
119
 
@@ -140,8 +140,8 @@ export const FiresEvents: StoryObj<Required<TextInputProps>> = {
140
140
  });
141
141
 
142
142
  await step('Verify event is fired with correct detail', async () => {
143
- await waitFor(() => {
144
- expect(listenerMock).toHaveBeenCalledWith(
143
+ await waitFor(async () => {
144
+ await expect(listenerMock).toHaveBeenCalledWith(
145
145
  expect.objectContaining({
146
146
  detail: {
147
147
  host: 'Homo sapiens',