@genspectrum/dashboard-components 0.1.4 → 0.1.5

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 (38) hide show
  1. package/custom-elements.json +213 -78
  2. package/dist/dashboard-components.js +303 -53
  3. package/dist/dashboard-components.js.map +1 -1
  4. package/dist/genspectrum-components.d.ts +288 -69
  5. package/dist/style.css +142 -15
  6. package/package.json +3 -3
  7. package/src/preact/aggregatedData/aggregate.stories.tsx +2 -0
  8. package/src/preact/aggregatedData/aggregate.tsx +9 -4
  9. package/src/preact/components/headline.stories.tsx +19 -1
  10. package/src/preact/components/headline.tsx +9 -1
  11. package/src/preact/components/info.stories.tsx +24 -3
  12. package/src/preact/components/info.tsx +49 -5
  13. package/src/preact/dateRangeSelector/date-range-selector.tsx +10 -10
  14. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -0
  15. package/src/preact/mutationComparison/mutation-comparison.tsx +3 -3
  16. package/src/preact/mutationFilter/mutation-filter.tsx +1 -1
  17. package/src/preact/mutations/mutations.stories.tsx +3 -0
  18. package/src/preact/mutations/mutations.tsx +9 -3
  19. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -0
  20. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +14 -4
  21. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +3 -0
  22. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +49 -4
  23. package/src/web-components/display/aggregate-component.stories.ts +3 -0
  24. package/src/web-components/display/aggregate-component.tsx +15 -1
  25. package/src/web-components/display/mutation-comparison-component.stories.ts +3 -0
  26. package/src/web-components/display/mutation-comparison-component.tsx +7 -0
  27. package/src/web-components/display/mutations-component.stories.ts +27 -7
  28. package/src/web-components/display/mutations-component.tsx +58 -4
  29. package/src/web-components/display/prevalence-over-time-component.stories.ts +24 -0
  30. package/src/web-components/display/prevalence-over-time-component.tsx +93 -5
  31. package/src/web-components/display/relative-growth-advantage-component.stories.ts +21 -0
  32. package/src/web-components/display/relative-growth-advantage-component.tsx +54 -3
  33. package/src/web-components/input/date-range-selector-component.stories.ts +17 -2
  34. package/src/web-components/input/date-range-selector-component.tsx +57 -5
  35. package/src/web-components/input/mutation-filter-component.stories.ts +13 -3
  36. package/src/web-components/input/mutation-filter-component.tsx +50 -2
  37. package/src/web-components/input/text-input-component.stories.ts +14 -3
  38. package/src/web-components/input/text-input-component.tsx +23 -1
@@ -23,6 +23,7 @@ const meta: Meta<MutationsProps> = {
23
23
  control: { type: 'check' },
24
24
  },
25
25
  size: [{ control: 'object' }],
26
+ headline: { control: 'text' },
26
27
  },
27
28
  };
28
29
 
@@ -37,6 +38,7 @@ const Template = {
37
38
  sequenceType={args.sequenceType}
38
39
  views={args.views}
39
40
  size={args.size}
41
+ headline={args.headline}
40
42
  />
41
43
  </ReferenceGenomeContext.Provider>
42
44
  </LapisUrlContext.Provider>
@@ -50,6 +52,7 @@ export const Default: StoryObj<MutationsProps> = {
50
52
  sequenceType: 'nucleotide',
51
53
  views: ['grid', 'table', 'insertions'],
52
54
  size: { width: '100%', height: '700px' },
55
+ headline: 'Mutations',
53
56
  },
54
57
  parameters: {
55
58
  fetchMock: {
@@ -35,15 +35,21 @@ export interface MutationsProps {
35
35
  sequenceType: SequenceType;
36
36
  views: View[];
37
37
  size?: Size;
38
+ headline?: string;
38
39
  }
39
40
 
40
- export const Mutations: FunctionComponent<MutationsProps> = ({ variant, sequenceType, views, size }) => {
41
+ export const Mutations: FunctionComponent<MutationsProps> = ({
42
+ variant,
43
+ sequenceType,
44
+ views,
45
+ size,
46
+ headline = 'Mutations',
47
+ }) => {
41
48
  const lapis = useContext(LapisUrlContext);
42
49
  const { data, error, isLoading } = useQuery(async () => {
43
50
  return queryMutationsData(variant, sequenceType, lapis);
44
51
  }, [variant, sequenceType, lapis]);
45
52
 
46
- const headline = 'Mutations';
47
53
  if (isLoading) {
48
54
  return (
49
55
  <Headline heading={headline}>
@@ -197,7 +203,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
197
203
  filename='insertions.csv'
198
204
  />
199
205
  )}
200
- <Info className='mx-1' content='Info for mutations' />
206
+ <Info>Info for mutations</Info>
201
207
  </div>
202
208
  );
203
209
  };
@@ -30,6 +30,7 @@ export default {
30
30
  control: { type: 'check' },
31
31
  },
32
32
  size: [{ control: 'object' }],
33
+ headline: { control: 'text' },
33
34
  },
34
35
  };
35
36
 
@@ -44,6 +45,7 @@ const Template = {
44
45
  views={args.views}
45
46
  confidenceIntervalMethods={args.confidenceIntervalMethods}
46
47
  size={args.size}
48
+ headline={args.headline}
47
49
  />
48
50
  </LapisUrlContext.Provider>
49
51
  ),
@@ -62,6 +64,7 @@ export const TwoVariants = {
62
64
  views: ['bar', 'line', 'bubble', 'table'],
63
65
  confidenceIntervalMethods: ['wilson'],
64
66
  size: { width: '100%', height: '700px' },
67
+ headline: 'Prevalence over time',
65
68
  },
66
69
  parameters: {
67
70
  fetchMock: {
@@ -128,6 +131,7 @@ export const OneVariant = {
128
131
  views: ['bar', 'line', 'bubble', 'table'],
129
132
  confidenceIntervalMethods: ['wilson'],
130
133
  size: { width: '100%', height: '700px' },
134
+ headline: 'Prevalence over time',
131
135
  },
132
136
  parameters: {
133
137
  fetchMock: {
@@ -13,7 +13,7 @@ import { ConfidenceIntervalSelector } from '../components/confidence-interval-se
13
13
  import { CsvDownloadButton } from '../components/csv-download-button';
14
14
  import { ErrorDisplay } from '../components/error-display';
15
15
  import Headline from '../components/headline';
16
- import Info from '../components/info';
16
+ import Info, { InfoHeadline1, InfoParagraph } from '../components/info';
17
17
  import { LoadingDisplay } from '../components/loading-display';
18
18
  import { NoDataDisplay } from '../components/no-data-display';
19
19
  import { ResizeContainer, type Size } from '../components/resize-container';
@@ -33,6 +33,7 @@ export interface PrevalenceOverTimeProps {
33
33
  views: View[];
34
34
  confidenceIntervalMethods: ConfidenceIntervalMethod[];
35
35
  size?: Size;
36
+ headline?: string;
36
37
  }
37
38
 
38
39
  export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
@@ -43,6 +44,7 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
43
44
  views,
44
45
  confidenceIntervalMethods,
45
46
  size,
47
+ headline = 'Prevalence over time',
46
48
  }) => {
47
49
  const lapis = useContext(LapisUrlContext);
48
50
 
@@ -51,8 +53,6 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
51
53
  [lapis, numerator, denominator, granularity, smoothingWindow],
52
54
  );
53
55
 
54
- const headline = 'Prevalence over time';
55
-
56
56
  if (isLoading) {
57
57
  return (
58
58
  <Headline heading={headline}>
@@ -202,9 +202,19 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
202
202
  getData={() => getPrevalenceOverTimeTableData(data, granularity)}
203
203
  filename='prevalence-over-time.csv'
204
204
  />
205
- <Info className='ml-1' content='Info for prevalence over time' />
205
+
206
+ <PrevalenceOverTimeInfo />
206
207
  </div>
207
208
  );
208
209
  };
209
210
 
211
+ const PrevalenceOverTimeInfo: FunctionComponent = () => {
212
+ return (
213
+ <Info size={{ width: '600px', height: '30vh' }}>
214
+ <InfoHeadline1>Prevalence over time</InfoHeadline1>
215
+ <InfoParagraph>Prevalence over time info.</InfoParagraph>
216
+ </Info>
217
+ );
218
+ };
219
+
210
220
  export default PrevalenceOverTime;
@@ -19,6 +19,7 @@ export default {
19
19
  control: { type: 'check' },
20
20
  },
21
21
  size: [{ control: 'object' }],
22
+ headline: { control: 'text' },
22
23
  },
23
24
  };
24
25
 
@@ -31,6 +32,7 @@ export const Primary = {
31
32
  generationTime={args.generationTime}
32
33
  views={args.views}
33
34
  size={args.size}
35
+ headline={args.headline}
34
36
  />
35
37
  </LapisUrlContext.Provider>
36
38
  ),
@@ -40,6 +42,7 @@ export const Primary = {
40
42
  generationTime: 7,
41
43
  views: ['line'],
42
44
  size: { width: '100%', height: '700px' },
45
+ headline: 'Relative growth advantage',
43
46
  },
44
47
  parameters: {
45
48
  fetchMock: {
@@ -10,7 +10,7 @@ import { type LapisFilter } from '../../types';
10
10
  import { LapisUrlContext } from '../LapisUrlContext';
11
11
  import { ErrorDisplay } from '../components/error-display';
12
12
  import Headline from '../components/headline';
13
- import Info from '../components/info';
13
+ import Info, { InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
14
14
  import { LoadingDisplay } from '../components/loading-display';
15
15
  import { NoDataDisplay } from '../components/no-data-display';
16
16
  import { ResizeContainer, type Size } from '../components/resize-container';
@@ -27,6 +27,7 @@ export interface RelativeGrowthAdvantageProps {
27
27
  generationTime: number;
28
28
  views: View[];
29
29
  size?: Size;
30
+ headline?: string;
30
31
  }
31
32
 
32
33
  export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = ({
@@ -35,6 +36,7 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
35
36
  generationTime,
36
37
  views,
37
38
  size,
39
+ headline = 'Relative growth advantage',
38
40
  }) => {
39
41
  const lapis = useContext(LapisUrlContext);
40
42
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
@@ -44,7 +46,6 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
44
46
  [lapis, numerator, denominator, generationTime, views],
45
47
  );
46
48
 
47
- const headline = 'Relative growth advantage';
48
49
  if (isLoading) {
49
50
  return (
50
51
  <Headline heading={headline}>
@@ -77,6 +78,7 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
77
78
  yAxisScaleType={yAxisScaleType}
78
79
  setYAxisScaleType={setYAxisScaleType}
79
80
  views={views}
81
+ generationTime={generationTime}
80
82
  />
81
83
  </Headline>
82
84
  </ResizeContainer>
@@ -88,6 +90,7 @@ type RelativeGrowthAdvantageTabsProps = {
88
90
  yAxisScaleType: ScaleType;
89
91
  setYAxisScaleType: (scaleType: ScaleType) => void;
90
92
  views: View[];
93
+ generationTime: number;
91
94
  };
92
95
 
93
96
  const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabsProps> = ({
@@ -95,6 +98,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
95
98
  yAxisScaleType,
96
99
  setYAxisScaleType,
97
100
  views,
101
+ generationTime,
98
102
  }) => {
99
103
  const getTab = (view: View) => {
100
104
  switch (view) {
@@ -117,7 +121,11 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
117
121
 
118
122
  const tabs = views.map((view) => getTab(view));
119
123
  const toolbar = () => (
120
- <RelativeGrowthAdvantageToolbar yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
124
+ <RelativeGrowthAdvantageToolbar
125
+ generationTime={generationTime}
126
+ yAxisScaleType={yAxisScaleType}
127
+ setYAxisScaleType={setYAxisScaleType}
128
+ />
121
129
  );
122
130
 
123
131
  return <Tabs tabs={tabs} toolbar={toolbar} />;
@@ -126,16 +134,53 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
126
134
  type RelativeGrowthAdvantageToolbarProps = {
127
135
  yAxisScaleType: ScaleType;
128
136
  setYAxisScaleType: (scaleType: ScaleType) => void;
137
+ generationTime: number;
129
138
  };
130
139
 
131
140
  const RelativeGrowthAdvantageToolbar: FunctionComponent<RelativeGrowthAdvantageToolbarProps> = ({
132
141
  yAxisScaleType,
133
142
  setYAxisScaleType,
143
+ generationTime,
134
144
  }) => {
135
145
  return (
136
146
  <div class='flex'>
137
147
  <ScalingSelector yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
138
- <Info className='ml-1' content='Line chart' />
148
+ <RelativeGrowthAdvantageInfo generationTime={generationTime} />
139
149
  </div>
140
150
  );
141
151
  };
152
+
153
+ const RelativeGrowthAdvantageInfo: FunctionComponent<{ generationTime: number }> = ({ generationTime }) => {
154
+ return (
155
+ <Info size={{ width: '600px', height: '30vh' }}>
156
+ <InfoHeadline1>Relative growth advantage</InfoHeadline1>
157
+ <InfoParagraph>
158
+ If variants spread pre-dominantly by local transmission across demographic groups, this estimate
159
+ reflects the relative viral intrinsic growth advantage of the focal variant in the selected country and
160
+ time frame. We report the relative growth advantage per {generationTime} days (in percentage; 0% means
161
+ equal growth). Importantly, the relative growth advantage estimate reflects the advantage compared to
162
+ the co-circulating variants. Thus, as new variants spread, the advantage of the focal variant may
163
+ decrease. Different mechanisms can alter the intrinsic growth rate, including an intrinsic transmission
164
+ advantage, immune evasion, and a prolonged infectious period. When absolute numbers of a variant are
165
+ low, the growth advantage may merely reflect the current importance of introductions from abroad or the
166
+ variant spreading in a particular demographic group. In this case, the estimate does not provide
167
+ information on any intrinsic fitness advantages.
168
+ </InfoParagraph>
169
+ <InfoParagraph>
170
+ Example: Assume that 10 infections from the focal variant and 100 infections from the co-circulating
171
+ variants occur today and that the focal variant has a relative growth advantage of 50%. Then, if the
172
+ number of new infections from the co-circulating variants remains at 100 in {generationTime} days from
173
+ today, we expect the number of new infections from the focal variant to be 15.
174
+ </InfoParagraph>
175
+
176
+ <InfoHeadline2>Reference</InfoHeadline2>
177
+ <InfoParagraph>
178
+ Chen, Chaoran, et al. "Quantification of the spread of SARS-CoV-2 variant B.1.1.7 in Switzerland."
179
+ Epidemics (2021); doi:{' '}
180
+ <InfoLink href='https://www.sciencedirect.com/science/article/pii/S1755436521000335?via=ihub'>
181
+ 10.1016/j.epidem.2021.100480
182
+ </InfoLink>
183
+ </InfoParagraph>
184
+ </Info>
185
+ );
186
+ };
@@ -19,6 +19,7 @@ const meta: Meta<AggregateProps> = {
19
19
  control: { type: 'check' },
20
20
  },
21
21
  size: [{ control: 'object' }],
22
+ headline: { control: 'text' },
22
23
  },
23
24
  parameters: withComponentDocs({
24
25
  fetchMock: {
@@ -59,6 +60,7 @@ export const Table: StoryObj<AggregateProps> = {
59
60
  .filter=${args.filter}
60
61
  .views=${args.views}
61
62
  .size=${args.size}
63
+ .headline=${args.headline}
62
64
  ></gs-aggregate-component>
63
65
  </gs-app>
64
66
  `,
@@ -69,5 +71,6 @@ export const Table: StoryObj<AggregateProps> = {
69
71
  country: 'USA',
70
72
  },
71
73
  size: { width: '100%', height: '700px' },
74
+ headline: 'Aggregate',
72
75
  },
73
76
  };
@@ -46,8 +46,22 @@ export class AggregateComponent extends PreactLitAdapterWithGridJsStyles {
46
46
  @property({ type: Object })
47
47
  size: { width?: string; height?: string } | undefined = undefined;
48
48
 
49
+ /**
50
+ * The headline of the component. Set to an empty string to hide the headline.
51
+ */
52
+ @property({ type: String })
53
+ headline: string | undefined = 'Aggregate';
54
+
49
55
  override render() {
50
- return <Aggregate fields={this.fields} views={this.views} filter={this.filter} size={this.size} />;
56
+ return (
57
+ <Aggregate
58
+ fields={this.fields}
59
+ views={this.views}
60
+ filter={this.filter}
61
+ size={this.size}
62
+ headline={this.headline}
63
+ />
64
+ );
51
65
  }
52
66
  }
53
67
 
@@ -32,6 +32,7 @@ const meta: Meta<MutationComparisonProps> = {
32
32
  control: { type: 'check' },
33
33
  },
34
34
  size: { control: 'object' },
35
+ headline: { control: 'text' },
35
36
  },
36
37
  parameters: withComponentDocs({
37
38
  componentDocs: {
@@ -54,6 +55,7 @@ const Template: StoryObj<MutationComparisonProps> = {
54
55
  .sequenceType=${args.sequenceType}
55
56
  .views=${args.views}
56
57
  .size=${args.size}
58
+ .headline=${args.headline}
57
59
  ></gs-mutation-comparison-component>
58
60
  </gs-app>
59
61
  `,
@@ -83,6 +85,7 @@ export const Default: StoryObj<MutationComparisonProps> = {
83
85
  sequenceType: 'nucleotide',
84
86
  views: ['table', 'venn'],
85
87
  size: { width: '100%', height: '700px' },
88
+ headline: 'Mutation comparison',
86
89
  },
87
90
  parameters: {
88
91
  fetchMock: {
@@ -72,6 +72,12 @@ export class MutationComparisonComponent extends PreactLitAdapterWithGridJsStyle
72
72
  @property({ type: Object })
73
73
  size: { width?: string; height?: string } | undefined = undefined;
74
74
 
75
+ /**
76
+ * The headline of the component. Set to an empty string to hide the headline.
77
+ */
78
+ @property({ type: String })
79
+ headline: string | undefined = 'Mutation comparison';
80
+
75
81
  override render() {
76
82
  return (
77
83
  <MutationComparison
@@ -79,6 +85,7 @@ export class MutationComparisonComponent extends PreactLitAdapterWithGridJsStyle
79
85
  sequenceType={this.sequenceType}
80
86
  views={this.views}
81
87
  size={this.size}
88
+ headline={this.headline}
82
89
  />
83
90
  );
84
91
  }
@@ -4,15 +4,23 @@ import { html } from 'lit';
4
4
 
5
5
  import './mutations-component';
6
6
  import '../app';
7
+ import { withComponentDocs } from '../../../.storybook/ComponentDocsBlock';
7
8
  import { LAPIS_URL, NUCLEOTIDE_INSERTIONS_ENDPOINT, NUCLEOTIDE_MUTATIONS_ENDPOINT } from '../../constants';
8
9
  import nucleotideInsertions from '../../preact/mutations/__mockData__/nucleotideInsertions.json';
9
10
  import nucleotideMutations from '../../preact/mutations/__mockData__/nucleotideMutations.json';
10
11
  import { type MutationsProps } from '../../preact/mutations/mutations';
11
12
  import { withinShadowRoot } from '../withinShadowRoot.story';
12
13
 
14
+ const codeExample = String.raw`
15
+ <gs-mutations
16
+ variant='{ "country": "Switzerland", "pangoLineage": "B.1.1.7", "dateTo": "2022-01-01" }'
17
+ sequenceType="nucleotide"
18
+ views='["grid", "table", "insertions"]'
19
+ ></gs-mutations>`;
20
+
13
21
  const meta: Meta<MutationsProps> = {
14
22
  title: 'Visualization/Mutations',
15
- component: 'gs-mutations',
23
+ component: 'gs-mutations-component',
16
24
  argTypes: {
17
25
  variant: { control: 'object' },
18
26
  sequenceType: {
@@ -24,7 +32,24 @@ const meta: Meta<MutationsProps> = {
24
32
  control: { type: 'check' },
25
33
  },
26
34
  size: { control: 'object' },
35
+ headline: { control: 'text' },
36
+ },
37
+ args: {
38
+ variant: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
39
+ sequenceType: 'nucleotide',
40
+ views: ['grid', 'table', 'insertions'],
41
+ size: { width: '100%', height: '700px' },
42
+ headline: 'Mutations',
27
43
  },
44
+ parameters: withComponentDocs({
45
+ componentDocs: {
46
+ tag: 'gs-mutations-component',
47
+ opensShadowDom: true,
48
+ expectsChildren: false,
49
+ codeExample,
50
+ },
51
+ }),
52
+ tags: ['autodocs'],
28
53
  };
29
54
 
30
55
  export default meta;
@@ -37,6 +62,7 @@ const Template: StoryObj<MutationsProps> = {
37
62
  .sequenceType=${args.sequenceType}
38
63
  .views=${args.views}
39
64
  .size=${args.size}
65
+ .headline=${args.headline}
40
66
  ></gs-mutations-component>
41
67
  </gs-app>
42
68
  `,
@@ -44,12 +70,6 @@ const Template: StoryObj<MutationsProps> = {
44
70
 
45
71
  export const Default: StoryObj<MutationsProps> = {
46
72
  ...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
- size: { width: '100%', height: '700px' },
52
- },
53
73
  parameters: {
54
74
  fetchMock: {
55
75
  mocks: [
@@ -2,18 +2,54 @@ import { customElement, property } from 'lit/decorators.js';
2
2
 
3
3
  import { Mutations, type View } from '../../preact/mutations/mutations';
4
4
  import { type LapisFilter, type SequenceType } from '../../types';
5
+ import type { Equals, Expect } from '../../utils/typeAssertions';
5
6
  import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsStyles';
6
7
 
8
+ /**
9
+ * This component displays mutations (substitutions, deletions and insertions) for a given variant.
10
+ *
11
+ * ## Views
12
+ *
13
+ * ### Table View
14
+ *
15
+ * The table view shows all substitutions and deletions for the given variant.
16
+ * It shows the type (substitution or deletion), the total count of the mutation
17
+ * and the proportion of the mutation in the variant.
18
+ * The proportion is relative to the total number of sequences matching
19
+ * the specified sequence filters with non-ambiguous reads at that position.
20
+ *
21
+ * The proportion interval filter can be used to filter the displayed mutations on client side.
22
+ *
23
+ * ### Grid View
24
+ *
25
+ * The grid view shows the proportion of each sequence symbol (nucleotide or amino acid) for each position that has a mutation.
26
+ * Only positions with at least one mutation in the selected proportion interval are shown.
27
+ *
28
+ * ### Insertions View
29
+ *
30
+ * The insertions view shows the count of all insertions for the given variant.
31
+ *
32
+ */
7
33
  @customElement('gs-mutations-component')
8
34
  export class MutationsComponent extends PreactLitAdapterWithGridJsStyles {
35
+ /**
36
+ * The `variant` will be sent as is to LAPIS to filter the mutation data.
37
+ * It must be a valid LAPIS filter object.
38
+ */
9
39
  @property({ type: Object })
10
- variant: LapisFilter = { displayName: '' };
40
+ variant: Record<string, string | number | null | boolean> = { displayName: '' };
11
41
 
42
+ /**
43
+ * The type of the sequence for which the mutations should be shown.
44
+ */
12
45
  @property({ type: String })
13
- sequenceType: SequenceType = 'nucleotide';
46
+ sequenceType: 'nucleotide' | 'amino acid' = 'nucleotide';
14
47
 
48
+ /**
49
+ * A list of tabs with views that this component should provide.
50
+ */
15
51
  @property({ type: Array })
16
- views: View[] = ['table', 'grid'];
52
+ views: ('table' | 'grid' | 'insertions')[] = ['table', 'grid'];
17
53
 
18
54
  /**
19
55
  * The size of the component.
@@ -26,9 +62,21 @@ export class MutationsComponent extends PreactLitAdapterWithGridJsStyles {
26
62
  @property({ type: Object })
27
63
  size: { width?: string; height?: string } | undefined = undefined;
28
64
 
65
+ /**
66
+ * The headline of the component. Set to an empty string to hide the headline.
67
+ */
68
+ @property({ type: String })
69
+ headline: string | undefined = 'Mutations';
70
+
29
71
  override render() {
30
72
  return (
31
- <Mutations variant={this.variant} sequenceType={this.sequenceType} views={this.views} size={this.size} />
73
+ <Mutations
74
+ variant={this.variant}
75
+ sequenceType={this.sequenceType}
76
+ views={this.views}
77
+ size={this.size}
78
+ headline={this.headline}
79
+ />
32
80
  );
33
81
  }
34
82
  }
@@ -38,3 +86,9 @@ declare global {
38
86
  'gs-mutations-component': MutationsComponent;
39
87
  }
40
88
  }
89
+
90
+ /* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */
91
+ type VariantsMatches = Expect<Equals<typeof MutationsComponent.prototype.variant, LapisFilter>>;
92
+ type SequenceTypeMatches = Expect<Equals<typeof MutationsComponent.prototype.sequenceType, SequenceType>>;
93
+ type ViewsMatches = Expect<Equals<typeof MutationsComponent.prototype.views, View[]>>;
94
+ /* eslint-enable @typescript-eslint/no-unused-vars, no-unused-vars */
@@ -4,6 +4,7 @@ import { html } from 'lit';
4
4
 
5
5
  import '../app';
6
6
  import './prevalence-over-time-component';
7
+ import { withComponentDocs } from '../../../.storybook/ComponentDocsBlock';
7
8
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
9
  import denominator from '../../preact/prevalenceOverTime/__mockData__/denominator.json';
9
10
  import denominatorOneVariant from '../../preact/prevalenceOverTime/__mockData__/denominatorOneVariant.json';
@@ -13,6 +14,16 @@ import numeratorOneVariant from '../../preact/prevalenceOverTime/__mockData__/nu
13
14
  import { type PrevalenceOverTimeProps } from '../../preact/prevalenceOverTime/prevalence-over-time';
14
15
  import { withinShadowRoot } from '../withinShadowRoot.story';
15
16
 
17
+ const codeExample = String.raw`
18
+ <gs-prevalence-over-time
19
+ numerator='[{ "displayName": "EG", "country": "USA", "pangoLineage": "EG*" }, { "displayName": "JN.1", "country": "USA", "pangoLineage": "JN.1*" }]'
20
+ denominator='{ "country": "USA", "displayName": "All" }'
21
+ granularity="month"
22
+ smoothingWindow="0"
23
+ views='["bar", "line", "bubble", "table"]'
24
+ confidenceIntervalMethods='["wilson"]'
25
+ ></gs-prevalence-over-time>`;
26
+
16
27
  const meta: Meta<PrevalenceOverTimeProps> = {
17
28
  title: 'Visualization/Prevalence over time',
18
29
  component: 'gs-prevalence-over-time',
@@ -33,7 +44,17 @@ const meta: Meta<PrevalenceOverTimeProps> = {
33
44
  control: { type: 'check' },
34
45
  },
35
46
  size: [{ control: 'object' }],
47
+ headline: { control: 'text' },
36
48
  },
49
+ parameters: withComponentDocs({
50
+ componentDocs: {
51
+ tag: 'gs-prevalence-over-time',
52
+ opensShadowDom: true,
53
+ expectsChildren: false,
54
+ codeExample,
55
+ },
56
+ }),
57
+ tags: ['autodocs'],
37
58
  };
38
59
 
39
60
  export default meta;
@@ -49,6 +70,7 @@ const Template: StoryObj<PrevalenceOverTimeProps> = {
49
70
  .views=${args.views}
50
71
  .confidenceIntervalMethods=${args.confidenceIntervalMethods}
51
72
  .size=${args.size}
73
+ .headline=${args.headline}
52
74
  ></gs-prevalence-over-time>
53
75
  </gs-app>
54
76
  `,
@@ -67,6 +89,7 @@ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
67
89
  views: ['bar', 'line', 'bubble', 'table'],
68
90
  confidenceIntervalMethods: ['wilson'],
69
91
  size: { width: '100%', height: '700px' },
92
+ headline: 'Prevalence over time',
70
93
  },
71
94
  parameters: {
72
95
  fetchMock: {
@@ -133,6 +156,7 @@ export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
133
156
  views: ['bar', 'line', 'bubble', 'table'],
134
157
  confidenceIntervalMethods: ['wilson'],
135
158
  size: { width: '100%', height: '700px' },
159
+ headline: 'Prevalence over time',
136
160
  },
137
161
  parameters: {
138
162
  fetchMock: {