@genspectrum/dashboard-components 0.1.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 (186) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +109 -0
  3. package/custom-elements.json +1587 -0
  4. package/dist/dashboard-components.js +7322 -0
  5. package/dist/dashboard-components.js.map +1 -0
  6. package/dist/genspectrum-components.d.ts +298 -0
  7. package/dist/style.css +2930 -0
  8. package/package.json +109 -0
  9. package/src/constants.ts +6 -0
  10. package/src/index.ts +1 -0
  11. package/src/lapisApi/ReferenceGenome.ts +30 -0
  12. package/src/lapisApi/__mockData__/referenceGenome.json +58 -0
  13. package/src/lapisApi/lapisApi.ts +99 -0
  14. package/src/lapisApi/lapisTypes.ts +51 -0
  15. package/src/operator/Dataset.ts +3 -0
  16. package/src/operator/DivisionOperator.spec.ts +27 -0
  17. package/src/operator/DivisionOperator.ts +60 -0
  18. package/src/operator/FetchAggregatedOperator.ts +44 -0
  19. package/src/operator/FetchInsertionsOperator.ts +24 -0
  20. package/src/operator/FetchSubstitutionsOrDeletionsOperator.ts +49 -0
  21. package/src/operator/FillMissingOperator.spec.ts +26 -0
  22. package/src/operator/FillMissingOperator.ts +30 -0
  23. package/src/operator/GroupByAndSumOperator.spec.ts +26 -0
  24. package/src/operator/GroupByAndSumOperator.ts +26 -0
  25. package/src/operator/GroupByOperator.spec.ts +43 -0
  26. package/src/operator/GroupByOperator.ts +32 -0
  27. package/src/operator/MapOperator.spec.ts +13 -0
  28. package/src/operator/MapOperator.ts +16 -0
  29. package/src/operator/MockOperator.spec.ts +11 -0
  30. package/src/operator/MockOperator.ts +12 -0
  31. package/src/operator/Operator.ts +5 -0
  32. package/src/operator/SlidingOperator.spec.ts +52 -0
  33. package/src/operator/SlidingOperator.ts +23 -0
  34. package/src/operator/SortOperator.spec.ts +13 -0
  35. package/src/operator/SortOperator.ts +16 -0
  36. package/src/preact/LapisUrlContext.ts +3 -0
  37. package/src/preact/ReferenceGenomeContext.ts +5 -0
  38. package/src/preact/components/SegmentSelector.tsx +62 -0
  39. package/src/preact/components/chart.stories.tsx +42 -0
  40. package/src/preact/components/chart.tsx +32 -0
  41. package/src/preact/components/checkbox-selector.stories.tsx +56 -0
  42. package/src/preact/components/checkbox-selector.tsx +46 -0
  43. package/src/preact/components/confidence-interval-selector.tsx +45 -0
  44. package/src/preact/components/csv-download-button.stories.tsx +25 -0
  45. package/src/preact/components/csv-download-button.tsx +51 -0
  46. package/src/preact/components/error-display.stories.tsx +22 -0
  47. package/src/preact/components/error-display.tsx +5 -0
  48. package/src/preact/components/headline.stories.tsx +29 -0
  49. package/src/preact/components/headline.tsx +16 -0
  50. package/src/preact/components/info.stories.tsx +22 -0
  51. package/src/preact/components/info.tsx +16 -0
  52. package/src/preact/components/loading-display.stories.tsx +20 -0
  53. package/src/preact/components/loading-display.tsx +5 -0
  54. package/src/preact/components/min-max-percent-slider.css +40 -0
  55. package/src/preact/components/min-max-range-slider.tsx +95 -0
  56. package/src/preact/components/mutation-type-selector.tsx +30 -0
  57. package/src/preact/components/no-data-display.stories.tsx +20 -0
  58. package/src/preact/components/no-data-display.tsx +5 -0
  59. package/src/preact/components/percent-intput.tsx +49 -0
  60. package/src/preact/components/proportion-selector-dropdown.stories.tsx +66 -0
  61. package/src/preact/components/proportion-selector-dropdown.tsx +33 -0
  62. package/src/preact/components/proportion-selector.stories.tsx +81 -0
  63. package/src/preact/components/proportion-selector.tsx +43 -0
  64. package/src/preact/components/scaling-selector.stories.tsx +25 -0
  65. package/src/preact/components/scaling-selector.tsx +36 -0
  66. package/src/preact/components/select.stories.tsx +42 -0
  67. package/src/preact/components/select.tsx +21 -0
  68. package/src/preact/components/table.stories.tsx +24 -0
  69. package/src/preact/components/table.tsx +51 -0
  70. package/src/preact/components/tabs.stories.tsx +60 -0
  71. package/src/preact/components/tabs.tsx +49 -0
  72. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +32 -0
  73. package/src/preact/dateRangeSelector/date-range-selector.tsx +228 -0
  74. package/src/preact/dateRangeSelector/dateConversion.ts +8 -0
  75. package/src/preact/locationFilter/__mockData__/aggregated.json +775 -0
  76. package/src/preact/locationFilter/fetchAutocompletionList.spec.ts +36 -0
  77. package/src/preact/locationFilter/fetchAutocompletionList.ts +43 -0
  78. package/src/preact/locationFilter/location-filter.stories.tsx +50 -0
  79. package/src/preact/locationFilter/location-filter.tsx +112 -0
  80. package/src/preact/mutationComparison/__mockData__/nucleotideMutationsOtherVariant.json +295 -0
  81. package/src/preact/mutationComparison/__mockData__/nucleotideMutationsSomeVariant.json +304 -0
  82. package/src/preact/mutationComparison/fetchMutationData.spec.ts +118 -0
  83. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +125 -0
  84. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +40 -0
  85. package/src/preact/mutationComparison/mutation-comparison-table.tsx +43 -0
  86. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +122 -0
  87. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +152 -0
  88. package/src/preact/mutationComparison/mutation-comparison.tsx +179 -0
  89. package/src/preact/mutationComparison/queryMutationData.ts +53 -0
  90. package/src/preact/mutationFilter/mutation-filter.stories.tsx +164 -0
  91. package/src/preact/mutationFilter/mutation-filter.tsx +268 -0
  92. package/src/preact/mutationFilter/parseAndValidateMutation.ts +54 -0
  93. package/src/preact/mutationFilter/parseMutation.spec.ts +150 -0
  94. package/src/preact/mutationFilter/sequenceTypeFromSegment.spec.ts +66 -0
  95. package/src/preact/mutationFilter/sequenceTypeFromSegment.ts +20 -0
  96. package/src/preact/mutations/__mockData__/nucleotideInsertions.json +252 -0
  97. package/src/preact/mutations/__mockData__/nucleotideMutations.json +880 -0
  98. package/src/preact/mutations/getInsertionsTableData.spec.ts +36 -0
  99. package/src/preact/mutations/getInsertionsTableData.ts +10 -0
  100. package/src/preact/mutations/getMutationsGridData.spec.ts +135 -0
  101. package/src/preact/mutations/getMutationsGridData.ts +92 -0
  102. package/src/preact/mutations/getMutationsTableData.spec.ts +94 -0
  103. package/src/preact/mutations/getMutationsTableData.ts +17 -0
  104. package/src/preact/mutations/mutations-grid.tsx +84 -0
  105. package/src/preact/mutations/mutations-insertions-table.tsx +33 -0
  106. package/src/preact/mutations/mutations-table.tsx +47 -0
  107. package/src/preact/mutations/mutations.stories.tsx +95 -0
  108. package/src/preact/mutations/mutations.tsx +192 -0
  109. package/src/preact/mutations/queryMutations.ts +55 -0
  110. package/src/preact/prevalenceOverTime/__mockData__/denominator.json +1700 -0
  111. package/src/preact/prevalenceOverTime/__mockData__/denominatorOneVariant.json +608 -0
  112. package/src/preact/prevalenceOverTime/__mockData__/numeratorEG.json +1560 -0
  113. package/src/preact/prevalenceOverTime/__mockData__/numeratorJN1.json +592 -0
  114. package/src/preact/prevalenceOverTime/__mockData__/numeratorOneVariant.json +604 -0
  115. package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.spec.ts +67 -0
  116. package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.ts +18 -0
  117. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +105 -0
  118. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +86 -0
  119. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +141 -0
  120. package/src/preact/prevalenceOverTime/prevalence-over-time-table.tsx +46 -0
  121. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +165 -0
  122. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +202 -0
  123. package/src/preact/relativeGrowthAdvantage/__mockData__/denominator.json +376 -0
  124. package/src/preact/relativeGrowthAdvantage/__mockData__/numerator.json +332 -0
  125. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +138 -0
  126. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +71 -0
  127. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +136 -0
  128. package/src/preact/shared/charts/LogitScale.ts +48 -0
  129. package/src/preact/shared/charts/colors.ts +26 -0
  130. package/src/preact/shared/charts/confideceInterval.ts +29 -0
  131. package/src/preact/shared/charts/getYAxisScale.ts +16 -0
  132. package/src/preact/shared/charts/scales.ts +16 -0
  133. package/src/preact/shared/icons/DeleteIcon.tsx +17 -0
  134. package/src/preact/shared/sort/sortInsertions.spec.ts +47 -0
  135. package/src/preact/shared/sort/sortInsertions.ts +21 -0
  136. package/src/preact/shared/sort/sortMutationPositions.spec.ts +31 -0
  137. package/src/preact/shared/sort/sortMutationPositions.ts +14 -0
  138. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +47 -0
  139. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +17 -0
  140. package/src/preact/shared/table/formatProportion.ts +3 -0
  141. package/src/preact/textInput/__mockData__/aggregated_hosts.json +24 -0
  142. package/src/preact/textInput/fetchAutocompleteList.ts +9 -0
  143. package/src/preact/textInput/text-input.stories.tsx +49 -0
  144. package/src/preact/textInput/text-input.tsx +73 -0
  145. package/src/preact/useQuery.ts +27 -0
  146. package/src/query/queryInsertions.ts +14 -0
  147. package/src/query/queryPrevalenceOverTime.ts +126 -0
  148. package/src/query/queryRelativeGrowthAdvantage.ts +131 -0
  149. package/src/query/querySubstitutionsOrDeletions.ts +19 -0
  150. package/src/styles/tailwind.css +3 -0
  151. package/src/styles/tailwind.d.ts +3 -0
  152. package/src/types.ts +23 -0
  153. package/src/utils/mutations.spec.ts +64 -0
  154. package/src/utils/mutations.ts +165 -0
  155. package/src/utils/temporal.spec.ts +97 -0
  156. package/src/utils/temporal.ts +348 -0
  157. package/src/utils/test-utils.ts +5 -0
  158. package/src/utils/type-utils.ts +15 -0
  159. package/src/utils/utils.spec.ts +16 -0
  160. package/src/utils/utils.ts +38 -0
  161. package/src/web-components/PreactLitAdapter.tsx +62 -0
  162. package/src/web-components/PreactLitAdapterWithGridJsStyles.tsx +12 -0
  163. package/src/web-components/app.ts +51 -0
  164. package/src/web-components/display/index.ts +4 -0
  165. package/src/web-components/display/mutation-comparison-component.stories.ts +138 -0
  166. package/src/web-components/display/mutation-comparison-component.tsx +31 -0
  167. package/src/web-components/display/mutations-component.stories.ts +107 -0
  168. package/src/web-components/display/mutations-component.tsx +27 -0
  169. package/src/web-components/display/prevalence-over-time-component.stories.ts +205 -0
  170. package/src/web-components/display/prevalence-over-time-component.tsx +46 -0
  171. package/src/web-components/display/relative-growth-advantage-component.stories.ts +89 -0
  172. package/src/web-components/display/relative-growth-advantage-component.tsx +37 -0
  173. package/src/web-components/index.ts +3 -0
  174. package/src/web-components/input/date-range-selector-component.stories.ts +53 -0
  175. package/src/web-components/input/date-range-selector-component.tsx +33 -0
  176. package/src/web-components/input/index.ts +4 -0
  177. package/src/web-components/input/location-filter-component.stories.ts +184 -0
  178. package/src/web-components/input/location-filter-component.tsx +68 -0
  179. package/src/web-components/input/location-filter.mdx +25 -0
  180. package/src/web-components/input/mutation-filter-component.stories.ts +97 -0
  181. package/src/web-components/input/mutation-filter-component.tsx +27 -0
  182. package/src/web-components/input/text-input-component.stories.ts +92 -0
  183. package/src/web-components/input/text-input-component.tsx +30 -0
  184. package/src/web-components/lapis-context.ts +3 -0
  185. package/src/web-components/reference-genome-context.ts +5 -0
  186. package/src/web-components/withinShadowRoot.story.ts +34 -0
@@ -0,0 +1,31 @@
1
+ import { customElement, property } from 'lit/decorators.js';
2
+
3
+ import {
4
+ MutationComparison,
5
+ type MutationComparisonVariant,
6
+ type View,
7
+ } from '../../preact/mutationComparison/mutation-comparison';
8
+ import { type SequenceType } from '../../types';
9
+ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsStyles';
10
+
11
+ @customElement('gs-mutation-comparison-component')
12
+ export class MutationComparisonComponent extends PreactLitAdapterWithGridJsStyles {
13
+ @property({ type: Array })
14
+ variants: MutationComparisonVariant[] = [];
15
+
16
+ @property({ type: String })
17
+ sequenceType: SequenceType = 'nucleotide';
18
+
19
+ @property({ type: Array })
20
+ views: View[] = ['table'];
21
+
22
+ override render() {
23
+ return <MutationComparison variants={this.variants} sequenceType={this.sequenceType} views={this.views} />;
24
+ }
25
+ }
26
+
27
+ declare global {
28
+ interface HTMLElementTagNameMap {
29
+ 'gs-mutation-comparison-component': MutationComparisonComponent;
30
+ }
31
+ }
@@ -0,0 +1,107 @@
1
+ import { expect, fireEvent, waitFor } from '@storybook/test';
2
+ import type { Meta, StoryObj } from '@storybook/web-components';
3
+ import { html } from 'lit';
4
+
5
+ import './mutations-component';
6
+ import '../app';
7
+ import { LAPIS_URL, NUCLEOTIDE_INSERTIONS_ENDPOINT, NUCLEOTIDE_MUTATIONS_ENDPOINT } from '../../constants';
8
+ import nucleotideInsertions from '../../preact/mutations/__mockData__/nucleotideInsertions.json';
9
+ import nucleotideMutations from '../../preact/mutations/__mockData__/nucleotideMutations.json';
10
+ import { type MutationsProps } from '../../preact/mutations/mutations';
11
+ import { withinShadowRoot } from '../withinShadowRoot.story';
12
+
13
+ const meta: Meta<MutationsProps> = {
14
+ title: 'Visualization/Mutations',
15
+ component: 'gs-mutations',
16
+ argTypes: {
17
+ variant: { control: 'object' },
18
+ sequenceType: {
19
+ options: ['nucleotide', 'amino acid'],
20
+ control: { type: 'radio' },
21
+ },
22
+ views: {
23
+ options: ['table', 'grid', 'insertions'],
24
+ control: { type: 'check' },
25
+ },
26
+ },
27
+ };
28
+
29
+ export default meta;
30
+
31
+ const Template: StoryObj<MutationsProps> = {
32
+ render: (args) => html`
33
+ <div class="w-11/12 h-11/12">
34
+ <gs-app lapis="${LAPIS_URL}">
35
+ <gs-mutations-component
36
+ .variant=${args.variant}
37
+ .sequenceType=${args.sequenceType}
38
+ .views=${args.views}
39
+ ></gs-mutations-component>
40
+ </gs-app>
41
+ </div>
42
+ `,
43
+ };
44
+
45
+ export const Default: StoryObj<MutationsProps> = {
46
+ ...Template,
47
+ args: {
48
+ variant: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
49
+ sequenceType: 'nucleotide',
50
+ views: ['grid', 'table', 'insertions'],
51
+ },
52
+ parameters: {
53
+ fetchMock: {
54
+ mocks: [
55
+ {
56
+ matcher: {
57
+ name: 'nucleotideMutations',
58
+ url: NUCLEOTIDE_MUTATIONS_ENDPOINT,
59
+ body: {
60
+ country: 'Switzerland',
61
+ pangoLineage: 'B.1.1.7',
62
+ dateTo: '2022-01-01',
63
+ minProportion: 0,
64
+ },
65
+ },
66
+ response: {
67
+ status: 200,
68
+ body: nucleotideMutations,
69
+ },
70
+ },
71
+ {
72
+ matcher: {
73
+ name: 'nucleotideInsertions',
74
+ url: NUCLEOTIDE_INSERTIONS_ENDPOINT,
75
+ body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
76
+ },
77
+ response: {
78
+ status: 200,
79
+ body: nucleotideInsertions,
80
+ },
81
+ },
82
+ ],
83
+ },
84
+ },
85
+ };
86
+
87
+ export const OnTableTab: StoryObj<MutationsProps> = {
88
+ ...Default,
89
+ play: async ({ canvasElement }) => {
90
+ const canvas = await withinShadowRoot(canvasElement, 'gs-mutations-component');
91
+
92
+ await waitFor(() => expect(canvas.getByLabelText('Table', { selector: 'input' })).toBeInTheDocument());
93
+
94
+ await fireEvent.click(canvas.getByLabelText('Table', { selector: 'input' }));
95
+ },
96
+ };
97
+
98
+ export const OnInsertionsTab: StoryObj<MutationsProps> = {
99
+ ...Default,
100
+ play: async ({ canvasElement }) => {
101
+ const canvas = await withinShadowRoot(canvasElement, 'gs-mutations-component');
102
+
103
+ await waitFor(() => expect(canvas.getByLabelText('Insertions', { selector: 'input' })).toBeInTheDocument());
104
+
105
+ await fireEvent.click(canvas.getByLabelText('Insertions', { selector: 'input' }));
106
+ },
107
+ };
@@ -0,0 +1,27 @@
1
+ import { customElement, property } from 'lit/decorators.js';
2
+
3
+ import { Mutations, type View } from '../../preact/mutations/mutations';
4
+ import { type LapisFilter, type SequenceType } from '../../types';
5
+ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsStyles';
6
+
7
+ @customElement('gs-mutations-component')
8
+ export class MutationsComponent extends PreactLitAdapterWithGridJsStyles {
9
+ @property({ type: Object })
10
+ variant: LapisFilter = { displayName: '' };
11
+
12
+ @property({ type: String })
13
+ sequenceType: SequenceType = 'nucleotide';
14
+
15
+ @property({ type: Array })
16
+ views: View[] = ['table', 'grid'];
17
+
18
+ override render() {
19
+ return <Mutations variant={this.variant} sequenceType={this.sequenceType} views={this.views} />;
20
+ }
21
+ }
22
+
23
+ declare global {
24
+ interface HTMLElementTagNameMap {
25
+ 'gs-mutations-component': MutationsComponent;
26
+ }
27
+ }
@@ -0,0 +1,205 @@
1
+ import { expect, fireEvent, waitFor } from '@storybook/test';
2
+ import type { Meta, StoryObj } from '@storybook/web-components';
3
+ import { html } from 'lit';
4
+
5
+ import '../app';
6
+ import './prevalence-over-time-component';
7
+ import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
+ import denominator from '../../preact/prevalenceOverTime/__mockData__/denominator.json';
9
+ import denominatorOneVariant from '../../preact/prevalenceOverTime/__mockData__/denominatorOneVariant.json';
10
+ import numeratorEG from '../../preact/prevalenceOverTime/__mockData__/numeratorEG.json';
11
+ import numeratorJN1 from '../../preact/prevalenceOverTime/__mockData__/numeratorJN1.json';
12
+ import numeratorOneVariant from '../../preact/prevalenceOverTime/__mockData__/numeratorOneVariant.json';
13
+ import { type PrevalenceOverTimeProps } from '../../preact/prevalenceOverTime/prevalence-over-time';
14
+ import { withinShadowRoot } from '../withinShadowRoot.story';
15
+
16
+ const meta: Meta<PrevalenceOverTimeProps> = {
17
+ title: 'Visualization/Prevalence over time',
18
+ component: 'gs-prevalence-over-time',
19
+ argTypes: {
20
+ numerator: { control: 'object' },
21
+ denominator: { control: 'object' },
22
+ granularity: {
23
+ options: ['day', 'week', 'month', 'year'],
24
+ control: { type: 'radio' },
25
+ },
26
+ smoothingWindow: { control: 'number' },
27
+ views: {
28
+ options: ['bar', 'line', 'bubble', 'table'],
29
+ control: { type: 'check' },
30
+ },
31
+ confidenceIntervalMethods: {
32
+ options: ['wilson'],
33
+ control: { type: 'check' },
34
+ },
35
+ },
36
+ };
37
+
38
+ export default meta;
39
+
40
+ const Template: StoryObj<PrevalenceOverTimeProps> = {
41
+ render: (args) => html`
42
+ <div class="w-11/12 h-11/12">
43
+ <gs-app lapis="${LAPIS_URL}">
44
+ <gs-prevalence-over-time
45
+ .numerator=${args.numerator}
46
+ .denominator=${args.denominator}
47
+ .granularity=${args.granularity}
48
+ .smoothingWindow=${args.smoothingWindow}
49
+ .views=${args.views}
50
+ .confidenceIntervalMethods=${args.confidenceIntervalMethods}
51
+ ></gs-prevalence-over-time>
52
+ </gs-app>
53
+ </div>
54
+ `,
55
+ };
56
+
57
+ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
58
+ ...Template,
59
+ args: {
60
+ numerator: [
61
+ { displayName: 'EG', country: 'USA', pangoLineage: 'EG*', dateFrom: '2023-01-01' },
62
+ { displayName: 'JN.1', country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' },
63
+ ],
64
+ denominator: { country: 'USA', dateFrom: '2023-01-01', displayName: 'All' },
65
+ granularity: 'month',
66
+ smoothingWindow: 0,
67
+ views: ['bar', 'line', 'bubble', 'table'],
68
+ confidenceIntervalMethods: ['wilson'],
69
+ },
70
+ parameters: {
71
+ fetchMock: {
72
+ mocks: [
73
+ {
74
+ matcher: {
75
+ name: 'numeratorEG',
76
+ url: AGGREGATED_ENDPOINT,
77
+ body: {
78
+ country: 'USA',
79
+ pangoLineage: 'EG*',
80
+ dateFrom: '2023-01-01',
81
+ fields: ['date'],
82
+ },
83
+ },
84
+ response: {
85
+ status: 200,
86
+ body: numeratorEG,
87
+ },
88
+ },
89
+ {
90
+ matcher: {
91
+ name: 'numeratorJN1',
92
+ url: AGGREGATED_ENDPOINT,
93
+ body: {
94
+ country: 'USA',
95
+ pangoLineage: 'JN.1*',
96
+ dateFrom: '2023-01-01',
97
+ fields: ['date'],
98
+ },
99
+ },
100
+ response: {
101
+ status: 200,
102
+ body: numeratorJN1,
103
+ },
104
+ },
105
+ {
106
+ matcher: {
107
+ name: 'denominator',
108
+ url: AGGREGATED_ENDPOINT,
109
+ body: {
110
+ country: 'USA',
111
+ dateFrom: '2023-01-01',
112
+ fields: ['date'],
113
+ },
114
+ },
115
+ response: {
116
+ status: 200,
117
+ body: denominator,
118
+ },
119
+ },
120
+ ],
121
+ },
122
+ },
123
+ };
124
+
125
+ export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
126
+ ...Template,
127
+ args: {
128
+ numerator: { displayName: 'EG', country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
129
+ denominator: { country: 'USA', dateFrom: '2023-10-01', displayName: 'All' },
130
+ granularity: 'day',
131
+ smoothingWindow: 7,
132
+ views: ['bar', 'line', 'bubble', 'table'],
133
+ confidenceIntervalMethods: ['wilson'],
134
+ },
135
+ parameters: {
136
+ fetchMock: {
137
+ mocks: [
138
+ {
139
+ matcher: {
140
+ name: 'numeratorOneVariant',
141
+ url: AGGREGATED_ENDPOINT,
142
+ body: {
143
+ country: 'USA',
144
+ pangoLineage: 'BA.2.86*',
145
+ dateFrom: '2023-10-01',
146
+ fields: ['date'],
147
+ },
148
+ },
149
+ response: {
150
+ status: 200,
151
+ body: numeratorOneVariant,
152
+ },
153
+ },
154
+ {
155
+ matcher: {
156
+ name: 'denominatorOneVariant',
157
+ url: AGGREGATED_ENDPOINT,
158
+ body: {
159
+ country: 'USA',
160
+ dateFrom: '2023-10-01',
161
+ fields: ['date'],
162
+ },
163
+ },
164
+ response: {
165
+ status: 200,
166
+ body: denominatorOneVariant,
167
+ },
168
+ },
169
+ ],
170
+ },
171
+ },
172
+ };
173
+
174
+ export const OneVariantOnLineTab: StoryObj<PrevalenceOverTimeProps> = {
175
+ ...OneVariant,
176
+ play: async ({ canvasElement }) => {
177
+ const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
178
+
179
+ await waitFor(() => expect(canvas.getByLabelText('Line', { selector: 'input' })).toBeInTheDocument());
180
+
181
+ await fireEvent.click(canvas.getByLabelText('Line', { selector: 'input' }));
182
+ },
183
+ };
184
+
185
+ export const OneVariantOnBubbleTab: StoryObj<PrevalenceOverTimeProps> = {
186
+ ...OneVariant,
187
+ play: async ({ canvasElement }) => {
188
+ const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
189
+
190
+ await waitFor(() => expect(canvas.getByLabelText('Bubble', { selector: 'input' })).toBeInTheDocument());
191
+
192
+ await fireEvent.click(canvas.getByLabelText('Bubble', { selector: 'input' }));
193
+ },
194
+ };
195
+
196
+ export const OneVariantOnTableTab: StoryObj<PrevalenceOverTimeProps> = {
197
+ ...OneVariant,
198
+ play: async ({ canvasElement }) => {
199
+ const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
200
+
201
+ await waitFor(() => expect(canvas.getByLabelText('Table', { selector: 'input' })).toBeInTheDocument());
202
+
203
+ await fireEvent.click(canvas.getByLabelText('Table', { selector: 'input' }));
204
+ },
205
+ };
@@ -0,0 +1,46 @@
1
+ import { customElement, property } from 'lit/decorators.js';
2
+
3
+ import PrevalenceOverTime, { type View } from '../../preact/prevalenceOverTime/prevalence-over-time';
4
+ import { type ConfidenceIntervalMethod } from '../../preact/shared/charts/confideceInterval';
5
+ import { type NamedLapisFilter, type TemporalGranularity } from '../../types';
6
+ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsStyles';
7
+
8
+ @customElement('gs-prevalence-over-time')
9
+ export class PrevalenceOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
10
+ @property({ type: Object })
11
+ numerator: NamedLapisFilter | NamedLapisFilter[] = { displayName: '' };
12
+
13
+ @property({ type: Object })
14
+ denominator: NamedLapisFilter = { displayName: '' };
15
+
16
+ @property({ type: String })
17
+ granularity: TemporalGranularity = 'day';
18
+
19
+ @property({ type: Number })
20
+ smoothingWindow: number = 0;
21
+
22
+ @property({ type: Array })
23
+ views: View[] = ['bar', 'line', 'bubble', 'table'];
24
+
25
+ @property({ type: Array })
26
+ confidenceIntervalMethods: ConfidenceIntervalMethod[] = ['wilson'];
27
+
28
+ override render() {
29
+ return (
30
+ <PrevalenceOverTime
31
+ numerator={this.numerator}
32
+ denominator={this.denominator}
33
+ granularity={this.granularity}
34
+ smoothingWindow={this.smoothingWindow}
35
+ views={this.views}
36
+ confidenceIntervalMethods={this.confidenceIntervalMethods}
37
+ />
38
+ );
39
+ }
40
+ }
41
+
42
+ declare global {
43
+ interface HTMLElementTagNameMap {
44
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
45
+ }
46
+ }
@@ -0,0 +1,89 @@
1
+ import type { Meta, StoryObj } from '@storybook/web-components';
2
+ import { html } from 'lit';
3
+
4
+ import './relative-growth-advantage-component';
5
+ import '../app';
6
+ import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
7
+ import denominator from '../../preact/relativeGrowthAdvantage/__mockData__/denominator.json';
8
+ import numerator from '../../preact/relativeGrowthAdvantage/__mockData__/numerator.json';
9
+ import { type RelativeGrowthAdvantageProps } from '../../preact/relativeGrowthAdvantage/relative-growth-advantage';
10
+
11
+ const meta: Meta<RelativeGrowthAdvantageProps> = {
12
+ title: 'Visualization/Relative growth advantage',
13
+ component: 'gs-relative-growth-advantage',
14
+ argTypes: {
15
+ numerator: { control: 'object' },
16
+ denominator: { control: 'object' },
17
+ generationTime: { control: 'number' },
18
+ views: {
19
+ options: ['line'],
20
+ control: { type: 'check' },
21
+ },
22
+ },
23
+ };
24
+
25
+ export default meta;
26
+
27
+ const Template: StoryObj<RelativeGrowthAdvantageProps> = {
28
+ render: (args) => html`
29
+ <div class="w-11/12 h-11/12">
30
+ <gs-app lapis="${LAPIS_URL}">
31
+ <gs-relative-growth-advantage
32
+ .numerator=${args.numerator}
33
+ .denominator=${args.denominator}
34
+ .generationTime=${args.generationTime}
35
+ .views=${args.views}
36
+ ></gs-relative-growth-advantage>
37
+ </gs-app>
38
+ </div>
39
+ `,
40
+ };
41
+
42
+ export const Default: StoryObj<RelativeGrowthAdvantageProps> = {
43
+ ...Template,
44
+ args: {
45
+ numerator: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateFrom: '2020-12-01', dateTo: '2021-03-01' },
46
+ denominator: { country: 'Switzerland', dateFrom: '2020-12-01', dateTo: '2021-03-01' },
47
+ generationTime: 7,
48
+ views: ['line'],
49
+ },
50
+ parameters: {
51
+ fetchMock: {
52
+ mocks: [
53
+ {
54
+ matcher: {
55
+ name: 'numerator',
56
+ url: AGGREGATED_ENDPOINT,
57
+ body: {
58
+ country: 'Switzerland',
59
+ pangoLineage: 'B.1.1.7',
60
+ dateFrom: '2020-12-01',
61
+ dateTo: '2021-03-01',
62
+ fields: ['date'],
63
+ },
64
+ },
65
+ response: {
66
+ status: 200,
67
+ body: numerator,
68
+ },
69
+ },
70
+ {
71
+ matcher: {
72
+ name: 'denominator',
73
+ url: AGGREGATED_ENDPOINT,
74
+ body: {
75
+ country: 'Switzerland',
76
+ dateFrom: '2020-12-01',
77
+ dateTo: '2021-03-01',
78
+ fields: ['date'],
79
+ },
80
+ },
81
+ response: {
82
+ status: 200,
83
+ body: denominator,
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ },
89
+ };
@@ -0,0 +1,37 @@
1
+ import { customElement, property } from 'lit/decorators.js';
2
+
3
+ import { RelativeGrowthAdvantage, type View } from '../../preact/relativeGrowthAdvantage/relative-growth-advantage';
4
+ import type { LapisFilter } from '../../types';
5
+ import { PreactLitAdapter } from '../PreactLitAdapter';
6
+
7
+ @customElement('gs-relative-growth-advantage')
8
+ export class RelativeGrowthAdvantageComponent extends PreactLitAdapter {
9
+ @property({ type: Object })
10
+ numerator: LapisFilter = {};
11
+
12
+ @property({ type: Object })
13
+ denominator: LapisFilter = {};
14
+
15
+ @property({ type: Number })
16
+ generationTime: number = 7;
17
+
18
+ @property({ type: Array })
19
+ views: View[] = ['line'];
20
+
21
+ override render() {
22
+ return (
23
+ <RelativeGrowthAdvantage
24
+ numerator={this.numerator}
25
+ denominator={this.denominator}
26
+ generationTime={this.generationTime}
27
+ views={this.views}
28
+ />
29
+ );
30
+ }
31
+ }
32
+
33
+ declare global {
34
+ interface HTMLElementTagNameMap {
35
+ 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ export { App } from './app.js';
2
+ export * from './display';
3
+ export * from './input';
@@ -0,0 +1,53 @@
1
+ import { withActions } from '@storybook/addon-actions/decorator';
2
+ import { expect, waitFor } from '@storybook/test';
3
+ import type { Meta, StoryObj } from '@storybook/web-components';
4
+ import { html } from 'lit';
5
+
6
+ import { LAPIS_URL } from '../../constants';
7
+ import { type DateRangeSelectorProps } from '../../preact/dateRangeSelector/date-range-selector';
8
+ import './date-range-selector-component';
9
+ import '../app';
10
+ import { toYYYYMMDD } from '../../preact/dateRangeSelector/dateConversion';
11
+ import { withinShadowRoot } from '../withinShadowRoot.story';
12
+
13
+ const meta: Meta<DateRangeSelectorProps> = {
14
+ title: 'Input/DateRangeSelector',
15
+ component: 'gs-date-range-selector',
16
+ parameters: {
17
+ actions: {
18
+ handles: ['gs-date-range-changed'],
19
+ },
20
+ fetchMock: {},
21
+ },
22
+ decorators: [withActions],
23
+ };
24
+
25
+ export default meta;
26
+
27
+ export const DateRangeSelectorStory: StoryObj<DateRangeSelectorProps> = {
28
+ render: (args) =>
29
+ html` <gs-app lapis="${LAPIS_URL}">
30
+ <div class="max-w-screen-lg">
31
+ <gs-date-range-selector
32
+ .customSelectOptions=${args.customSelectOptions}
33
+ .earliestDate=${args.earliestDate}
34
+ ></gs-date-range-selector>
35
+ </div>
36
+ </gs-app>`,
37
+
38
+ play: async ({ canvasElement, step }) => {
39
+ const canvas = await withinShadowRoot(canvasElement, 'gs-date-range-selector');
40
+ const dateTo = () => canvas.getByPlaceholderText('Date to');
41
+
42
+ await step('Expect last 6 months to be selected', async () => {
43
+ await expect(canvas.getByRole('combobox')).toHaveValue('last6Months');
44
+ await waitFor(() => {
45
+ expect(dateTo()).toHaveValue(toYYYYMMDD(new Date()));
46
+ });
47
+ });
48
+ },
49
+ args: {
50
+ customSelectOptions: [{ label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' }],
51
+ earliestDate: '1970-01-01',
52
+ },
53
+ };
@@ -0,0 +1,33 @@
1
+ import { customElement, property } from 'lit/decorators.js';
2
+
3
+ import { type CustomSelectOption, DateRangeSelector } from '../../preact/dateRangeSelector/date-range-selector';
4
+ import { PreactLitAdapter } from '../PreactLitAdapter';
5
+
6
+ /**
7
+ * @fires {CustomEvent<{ dateFrom: string; dateTo: string; }>} gs-date-range-changed - When the date range has changed
8
+ */
9
+ @customElement('gs-date-range-selector')
10
+ export class DateRangeSelectorComponent extends PreactLitAdapter {
11
+ @property({ type: Array })
12
+ customSelectOptions: CustomSelectOption[] = [];
13
+
14
+ @property({ type: String })
15
+ earliestDate: string | undefined = '1900-01-01';
16
+
17
+ override render() {
18
+ return <DateRangeSelector customSelectOptions={this.customSelectOptions} earliestDate={this.earliestDate} />;
19
+ }
20
+ }
21
+
22
+ declare global {
23
+ interface HTMLElementTagNameMap {
24
+ 'gs-date-range-selector': DateRangeSelectorComponent;
25
+ }
26
+
27
+ interface HTMLElementEventMap {
28
+ 'gs-date-range-changed': CustomEvent<{
29
+ dateFrom: string;
30
+ dateTo: string;
31
+ }>;
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ export { DateRangeSelectorComponent } from './date-range-selector-component';
2
+ export { LocationFilterComponent } from './location-filter-component';
3
+ export { TextInputComponent } from './text-input-component';
4
+ export { MutationFilterComponent } from './mutation-filter-component';