@genspectrum/dashboard-components 0.1.2 → 0.1.4

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 (81) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +453 -67
  3. package/dist/dashboard-components.js +778 -488
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +277 -50
  6. package/dist/style.css +132 -139
  7. package/package.json +9 -5
  8. package/src/lapisApi/lapisApi.ts +1 -1
  9. package/src/preact/aggregatedData/__mockData__/aggregated.json +585 -0
  10. package/src/preact/aggregatedData/aggregate-table.tsx +32 -0
  11. package/src/preact/aggregatedData/aggregate.stories.tsx +53 -0
  12. package/src/preact/aggregatedData/aggregate.tsx +102 -0
  13. package/src/preact/components/ReferenceGenomesAwaiter.tsx +25 -0
  14. package/src/preact/components/csv-download-button.tsx +8 -2
  15. package/src/preact/components/headline.tsx +16 -4
  16. package/src/preact/components/min-max-range-slider.tsx +4 -4
  17. package/src/preact/components/percent-intput.tsx +2 -3
  18. package/src/preact/components/resize-container.tsx +23 -0
  19. package/src/preact/components/table.tsx +1 -0
  20. package/src/preact/components/tabs.stories.tsx +2 -2
  21. package/src/preact/components/tabs.tsx +47 -24
  22. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +36 -4
  23. package/src/preact/dateRangeSelector/date-range-selector.tsx +57 -43
  24. package/src/preact/locationFilter/location-filter.tsx +2 -2
  25. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +5 -5
  26. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +45 -10
  27. package/src/preact/mutationComparison/mutation-comparison-table.tsx +20 -22
  28. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +6 -3
  29. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +8 -1
  30. package/src/preact/mutationComparison/mutation-comparison.tsx +13 -4
  31. package/src/preact/mutationFilter/mutation-filter.stories.tsx +70 -31
  32. package/src/preact/mutationFilter/mutation-filter.tsx +62 -14
  33. package/src/preact/mutations/getInsertionsTableData.spec.ts +6 -4
  34. package/src/preact/mutations/getInsertionsTableData.ts +1 -1
  35. package/src/preact/mutations/getMutationsTableData.spec.ts +9 -19
  36. package/src/preact/mutations/getMutationsTableData.ts +1 -1
  37. package/src/preact/mutations/mutations-insertions-table.tsx +3 -1
  38. package/src/preact/mutations/mutations-table.tsx +3 -1
  39. package/src/preact/mutations/mutations.stories.tsx +8 -1
  40. package/src/preact/mutations/mutations.tsx +16 -5
  41. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +1 -0
  42. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -0
  43. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +1 -0
  44. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -0
  45. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +17 -9
  46. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +8 -5
  47. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +12 -0
  48. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +13 -8
  49. package/src/preact/shared/sort/sortInsertions.spec.ts +11 -10
  50. package/src/preact/shared/sort/sortInsertions.ts +10 -17
  51. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +19 -10
  52. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +45 -12
  53. package/src/preact/textInput/text-input.stories.tsx +22 -1
  54. package/src/preact/textInput/text-input.tsx +3 -1
  55. package/src/query/queryAggregateData.spec.ts +32 -0
  56. package/src/query/queryAggregateData.ts +25 -0
  57. package/src/utils/typeAssertions.spec.ts +31 -0
  58. package/src/utils/typeAssertions.ts +16 -0
  59. package/src/web-components/PreactLitAdapter.tsx +0 -1
  60. package/src/web-components/app.stories.ts +129 -0
  61. package/src/web-components/app.ts +27 -6
  62. package/src/web-components/display/aggregate-component.stories.ts +73 -0
  63. package/src/web-components/display/aggregate-component.tsx +58 -0
  64. package/src/web-components/display/index.ts +1 -0
  65. package/src/web-components/display/mutation-comparison-component.stories.ts +29 -11
  66. package/src/web-components/display/mutation-comparison-component.tsx +72 -4
  67. package/src/web-components/display/mutations-component.stories.ts +14 -13
  68. package/src/web-components/display/mutations-component.tsx +14 -1
  69. package/src/web-components/display/prevalence-over-time-component.stories.ts +20 -18
  70. package/src/web-components/display/prevalence-over-time-component.tsx +12 -0
  71. package/src/web-components/display/relative-growth-advantage-component.stories.ts +11 -10
  72. package/src/web-components/display/relative-growth-advantage-component.tsx +12 -0
  73. package/src/web-components/input/date-range-selector-component.stories.ts +35 -8
  74. package/src/web-components/input/date-range-selector-component.tsx +18 -5
  75. package/src/web-components/input/location-filter-component.stories.ts +17 -8
  76. package/src/web-components/input/location-filter-component.tsx +2 -6
  77. package/src/web-components/input/mutation-filter-component.stories.ts +20 -9
  78. package/src/web-components/input/mutation-filter-component.tsx +10 -2
  79. package/src/web-components/input/text-input-component.stories.ts +13 -4
  80. package/src/web-components/input/text-input-component.tsx +11 -2
  81. package/src/web-components/input/location-filter.mdx +0 -25
@@ -15,8 +15,21 @@ export class MutationsComponent extends PreactLitAdapterWithGridJsStyles {
15
15
  @property({ type: Array })
16
16
  views: View[] = ['table', 'grid'];
17
17
 
18
+ /**
19
+ * The size of the component.
20
+ *
21
+ * If not set, the component will take the full width of its container with height 700px.
22
+ *
23
+ * The width and height should be a string with a unit in css style, e.g. '100%', '500px' or '50vh'.
24
+ * If the unit is %, the size will be relative to the container of the component.
25
+ */
26
+ @property({ type: Object })
27
+ size: { width?: string; height?: string } | undefined = undefined;
28
+
18
29
  override render() {
19
- return <Mutations variant={this.variant} sequenceType={this.sequenceType} views={this.views} />;
30
+ return (
31
+ <Mutations variant={this.variant} sequenceType={this.sequenceType} views={this.views} size={this.size} />
32
+ );
20
33
  }
21
34
  }
22
35
 
@@ -32,6 +32,7 @@ const meta: Meta<PrevalenceOverTimeProps> = {
32
32
  options: ['wilson'],
33
33
  control: { type: 'check' },
34
34
  },
35
+ size: [{ control: 'object' }],
35
36
  },
36
37
  };
37
38
 
@@ -39,18 +40,17 @@ export default meta;
39
40
 
40
41
  const Template: StoryObj<PrevalenceOverTimeProps> = {
41
42
  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>
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
+ .size=${args.size}
52
+ ></gs-prevalence-over-time>
53
+ </gs-app>
54
54
  `,
55
55
  };
56
56
 
@@ -66,6 +66,7 @@ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
66
66
  smoothingWindow: 0,
67
67
  views: ['bar', 'line', 'bubble', 'table'],
68
68
  confidenceIntervalMethods: ['wilson'],
69
+ size: { width: '100%', height: '700px' },
69
70
  },
70
71
  parameters: {
71
72
  fetchMock: {
@@ -131,6 +132,7 @@ export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
131
132
  smoothingWindow: 7,
132
133
  views: ['bar', 'line', 'bubble', 'table'],
133
134
  confidenceIntervalMethods: ['wilson'],
135
+ size: { width: '100%', height: '700px' },
134
136
  },
135
137
  parameters: {
136
138
  fetchMock: {
@@ -176,9 +178,9 @@ export const OneVariantOnLineTab: StoryObj<PrevalenceOverTimeProps> = {
176
178
  play: async ({ canvasElement }) => {
177
179
  const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
178
180
 
179
- await waitFor(() => expect(canvas.getByLabelText('Line', { selector: 'input' })).toBeInTheDocument());
181
+ await waitFor(() => expect(canvas.getByRole('button', { name: 'Line' })).toBeInTheDocument());
180
182
 
181
- await fireEvent.click(canvas.getByLabelText('Line', { selector: 'input' }));
183
+ await fireEvent.click(canvas.getByRole('button', { name: 'Line' }));
182
184
  },
183
185
  };
184
186
 
@@ -187,9 +189,9 @@ export const OneVariantOnBubbleTab: StoryObj<PrevalenceOverTimeProps> = {
187
189
  play: async ({ canvasElement }) => {
188
190
  const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
189
191
 
190
- await waitFor(() => expect(canvas.getByLabelText('Bubble', { selector: 'input' })).toBeInTheDocument());
192
+ await waitFor(() => expect(canvas.getByRole('button', { name: 'Bubble' })).toBeInTheDocument());
191
193
 
192
- await fireEvent.click(canvas.getByLabelText('Bubble', { selector: 'input' }));
194
+ await fireEvent.click(canvas.getByRole('button', { name: 'Bubble' }));
193
195
  },
194
196
  };
195
197
 
@@ -198,8 +200,8 @@ export const OneVariantOnTableTab: StoryObj<PrevalenceOverTimeProps> = {
198
200
  play: async ({ canvasElement }) => {
199
201
  const canvas = await withinShadowRoot(canvasElement, 'gs-prevalence-over-time');
200
202
 
201
- await waitFor(() => expect(canvas.getByLabelText('Table', { selector: 'input' })).toBeInTheDocument());
203
+ await waitFor(() => expect(canvas.getByRole('button', { name: 'Table' })).toBeInTheDocument());
202
204
 
203
- await fireEvent.click(canvas.getByLabelText('Table', { selector: 'input' }));
205
+ await fireEvent.click(canvas.getByRole('button', { name: 'Table' }));
204
206
  },
205
207
  };
@@ -25,6 +25,17 @@ export class PrevalenceOverTimeComponent extends PreactLitAdapterWithGridJsStyle
25
25
  @property({ type: Array })
26
26
  confidenceIntervalMethods: ConfidenceIntervalMethod[] = ['wilson'];
27
27
 
28
+ /**
29
+ * The size of the component.
30
+ *
31
+ * If not set, the component will take the full width of its container with height 700px.
32
+ *
33
+ * The width and height should be a string with a unit in css style, e.g. '100%', '500px' or '50vh'.
34
+ * If the unit is %, the size will be relative to the container of the component.
35
+ */
36
+ @property({ type: Object })
37
+ size: { width?: string; height?: string } | undefined = undefined;
38
+
28
39
  override render() {
29
40
  return (
30
41
  <PrevalenceOverTime
@@ -34,6 +45,7 @@ export class PrevalenceOverTimeComponent extends PreactLitAdapterWithGridJsStyle
34
45
  smoothingWindow={this.smoothingWindow}
35
46
  views={this.views}
36
47
  confidenceIntervalMethods={this.confidenceIntervalMethods}
48
+ size={this.size}
37
49
  />
38
50
  );
39
51
  }
@@ -19,6 +19,7 @@ const meta: Meta<RelativeGrowthAdvantageProps> = {
19
19
  options: ['line'],
20
20
  control: { type: 'check' },
21
21
  },
22
+ size: [{ control: 'object' }],
22
23
  },
23
24
  };
24
25
 
@@ -26,16 +27,15 @@ export default meta;
26
27
 
27
28
  const Template: StoryObj<RelativeGrowthAdvantageProps> = {
28
29
  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>
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
+ .size=${args.size}
37
+ ></gs-relative-growth-advantage>
38
+ </gs-app>
39
39
  `,
40
40
  };
41
41
 
@@ -46,6 +46,7 @@ export const Default: StoryObj<RelativeGrowthAdvantageProps> = {
46
46
  denominator: { country: 'Switzerland', dateFrom: '2020-12-01', dateTo: '2021-03-01' },
47
47
  generationTime: 7,
48
48
  views: ['line'],
49
+ size: { width: '100%', height: '700px' },
49
50
  },
50
51
  parameters: {
51
52
  fetchMock: {
@@ -18,6 +18,17 @@ export class RelativeGrowthAdvantageComponent extends PreactLitAdapter {
18
18
  @property({ type: Array })
19
19
  views: View[] = ['line'];
20
20
 
21
+ /**
22
+ * The size of the component.
23
+ *
24
+ * If not set, the component will take the full width of its container with height 700px.
25
+ *
26
+ * The width and height should be a string with a unit in css style, e.g. '100%', '500px' or '50vh'.
27
+ * If the unit is %, the size will be relative to the container of the component.
28
+ */
29
+ @property({ type: Object })
30
+ size: { width?: string; height?: string } | undefined = undefined;
31
+
21
32
  override render() {
22
33
  return (
23
34
  <RelativeGrowthAdvantage
@@ -25,6 +36,7 @@ export class RelativeGrowthAdvantageComponent extends PreactLitAdapter {
25
36
  denominator={this.denominator}
26
37
  generationTime={this.generationTime}
27
38
  views={this.views}
39
+ size={this.size}
28
40
  />
29
41
  );
30
42
  }
@@ -4,13 +4,22 @@ import type { Meta, StoryObj } from '@storybook/web-components';
4
4
  import { html } from 'lit';
5
5
 
6
6
  import { LAPIS_URL } from '../../constants';
7
- import { type DateRangeSelectorProps } from '../../preact/dateRangeSelector/date-range-selector';
7
+ import {
8
+ type DateRangeSelectorProps,
9
+ PRESET_VALUE_ALL_TIMES,
10
+ PRESET_VALUE_CUSTOM,
11
+ PRESET_VALUE_LAST_2_MONTHS,
12
+ PRESET_VALUE_LAST_2_WEEKS,
13
+ PRESET_VALUE_LAST_3_MONTHS,
14
+ PRESET_VALUE_LAST_6_MONTHS,
15
+ PRESET_VALUE_LAST_MONTH,
16
+ } from '../../preact/dateRangeSelector/date-range-selector';
8
17
  import './date-range-selector-component';
9
18
  import '../app';
10
19
  import { toYYYYMMDD } from '../../preact/dateRangeSelector/dateConversion';
11
20
  import { withinShadowRoot } from '../withinShadowRoot.story';
12
21
 
13
- const meta: Meta<DateRangeSelectorProps> = {
22
+ const meta: Meta<DateRangeSelectorProps<'CustomDateRange'>> = {
14
23
  title: 'Input/DateRangeSelector',
15
24
  component: 'gs-date-range-selector',
16
25
  parameters: {
@@ -19,22 +28,44 @@ const meta: Meta<DateRangeSelectorProps> = {
19
28
  },
20
29
  fetchMock: {},
21
30
  },
31
+ argTypes: {
32
+ initialValue: {
33
+ control: {
34
+ type: 'select',
35
+ },
36
+ options: [
37
+ PRESET_VALUE_CUSTOM,
38
+ PRESET_VALUE_ALL_TIMES,
39
+ PRESET_VALUE_LAST_2_WEEKS,
40
+ PRESET_VALUE_LAST_MONTH,
41
+ PRESET_VALUE_LAST_2_MONTHS,
42
+ PRESET_VALUE_LAST_3_MONTHS,
43
+ PRESET_VALUE_LAST_6_MONTHS,
44
+ 'CustomDateRange',
45
+ ],
46
+ },
47
+ },
48
+ args: {
49
+ customSelectOptions: [{ label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' }],
50
+ earliestDate: '1970-01-01',
51
+ initialValue: PRESET_VALUE_LAST_6_MONTHS,
52
+ },
22
53
  decorators: [withActions],
23
54
  };
24
55
 
25
56
  export default meta;
26
57
 
27
- export const DateRangeSelectorStory: StoryObj<DateRangeSelectorProps> = {
58
+ export const DateRangeSelectorStory: StoryObj<DateRangeSelectorProps<'CustomDateRange'>> = {
28
59
  render: (args) =>
29
60
  html` <gs-app lapis="${LAPIS_URL}">
30
61
  <div class="max-w-screen-lg">
31
62
  <gs-date-range-selector
32
63
  .customSelectOptions=${args.customSelectOptions}
33
64
  .earliestDate=${args.earliestDate}
65
+ .initialValue=${args.initialValue}
34
66
  ></gs-date-range-selector>
35
67
  </div>
36
68
  </gs-app>`,
37
-
38
69
  play: async ({ canvasElement, step }) => {
39
70
  const canvas = await withinShadowRoot(canvasElement, 'gs-date-range-selector');
40
71
  const dateTo = () => canvas.getByPlaceholderText('Date to');
@@ -46,8 +77,4 @@ export const DateRangeSelectorStory: StoryObj<DateRangeSelectorProps> = {
46
77
  });
47
78
  });
48
79
  },
49
- args: {
50
- customSelectOptions: [{ label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' }],
51
- earliestDate: '1970-01-01',
52
- },
53
80
  };
@@ -1,27 +1,40 @@
1
1
  import { customElement, property } from 'lit/decorators.js';
2
2
 
3
- import { type CustomSelectOption, DateRangeSelector } from '../../preact/dateRangeSelector/date-range-selector';
3
+ import {
4
+ type CustomSelectOption,
5
+ DateRangeSelector,
6
+ type PresetOptionValues,
7
+ } from '../../preact/dateRangeSelector/date-range-selector';
4
8
  import { PreactLitAdapter } from '../PreactLitAdapter';
5
9
 
6
10
  /**
7
11
  * @fires {CustomEvent<{ dateFrom: string; dateTo: string; }>} gs-date-range-changed - When the date range has changed
8
12
  */
9
13
  @customElement('gs-date-range-selector')
10
- export class DateRangeSelectorComponent extends PreactLitAdapter {
14
+ export class DateRangeSelectorComponent<CustomLabel extends string> extends PreactLitAdapter {
11
15
  @property({ type: Array })
12
- customSelectOptions: CustomSelectOption[] = [];
16
+ customSelectOptions: CustomSelectOption<CustomLabel>[] = [];
13
17
 
14
18
  @property({ type: String })
15
19
  earliestDate: string | undefined = '1900-01-01';
16
20
 
21
+ @property()
22
+ initialValue: PresetOptionValues | CustomLabel | string | undefined = '';
23
+
17
24
  override render() {
18
- return <DateRangeSelector customSelectOptions={this.customSelectOptions} earliestDate={this.earliestDate} />;
25
+ return (
26
+ <DateRangeSelector
27
+ customSelectOptions={this.customSelectOptions}
28
+ earliestDate={this.earliestDate}
29
+ initialValue={this.initialValue}
30
+ />
31
+ );
19
32
  }
20
33
  }
21
34
 
22
35
  declare global {
23
36
  interface HTMLElementTagNameMap {
24
- 'gs-date-range-selector': DateRangeSelectorComponent;
37
+ 'gs-date-range-selector': DateRangeSelectorComponent<string>;
25
38
  }
26
39
 
27
40
  interface HTMLElementEventMap {
@@ -4,6 +4,7 @@ import type { Meta, StoryObj } from '@storybook/web-components';
4
4
  import { html } from 'lit';
5
5
  import { ifDefined } from 'lit/directives/if-defined.js';
6
6
 
7
+ import { withComponentDocs } from '../../../.storybook/ComponentDocsBlock';
7
8
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
9
  import '../app';
9
10
  import './location-filter-component';
@@ -14,12 +15,19 @@ import { withinShadowRoot } from '../withinShadowRoot.story';
14
15
  const meta: Meta = {
15
16
  title: 'Input/Location filter',
16
17
  component: 'gs-location-filter',
17
- parameters: {
18
+ parameters: withComponentDocs({
18
19
  actions: {
19
20
  handles: ['gs-location-changed'],
20
21
  },
21
- },
22
+ componentDocs: {
23
+ tag: 'gs-location-filter',
24
+ opensShadowDom: true,
25
+ expectsChildren: false,
26
+ codeExample: `<gs-location-filter fields="['continent', 'country']" value='Europe / Switzerland'></gs-location-filter>`,
27
+ },
28
+ }),
22
29
  decorators: [withActions],
30
+ tags: ['autodocs'],
23
31
  };
24
32
 
25
33
  export default meta;
@@ -28,13 +36,16 @@ const Template: StoryObj<LocationFilterProps> = {
28
36
  render: (args) => {
29
37
  return html` <gs-app lapis="${LAPIS_URL}">
30
38
  <div class="max-w-screen-lg">
31
- <gs-location-filter .fields=${args.fields} value=${ifDefined(args.value)}></gs-location-filter>
39
+ <gs-location-filter
40
+ .fields=${args.fields}
41
+ initialValue=${ifDefined(args.initialValue)}
42
+ ></gs-location-filter>
32
43
  </div>
33
44
  </gs-app>`;
34
45
  },
35
46
  args: {
36
47
  fields: ['region', 'country', 'division', 'location'],
37
- value: '',
48
+ initialValue: '',
38
49
  },
39
50
  };
40
51
 
@@ -97,7 +108,7 @@ export const FetchingLocationsFails: StoryObj<LocationFilterProps> = {
97
108
  {
98
109
  matcher: aggregatedEndpointMatcher,
99
110
  response: {
100
- status: 500,
111
+ status: 400,
101
112
  body: { error: 'no data' },
102
113
  },
103
114
  },
@@ -108,9 +119,7 @@ export const FetchingLocationsFails: StoryObj<LocationFilterProps> = {
108
119
  const canvas = await withinShadowRoot(canvasElement, 'gs-location-filter');
109
120
 
110
121
  await waitFor(() =>
111
- expect(
112
- canvas.getByText('Internal Server Error: {"error":"no data"} ', { exact: false }),
113
- ).toBeInTheDocument(),
122
+ expect(canvas.getByText('Bad Request: {"error":"no data"} ', { exact: false })).toBeInTheDocument(),
114
123
  );
115
124
  },
116
125
  };
@@ -4,10 +4,6 @@ import { LocationFilter } from '../../preact/locationFilter/location-filter';
4
4
  import { PreactLitAdapter } from '../PreactLitAdapter';
5
5
 
6
6
  /**
7
- * ## Tag
8
- *
9
- * `gs-location-filter`
10
- *
11
7
  * ## Context
12
8
  *
13
9
  * This component provides an input field to specify filters for locations.
@@ -41,7 +37,7 @@ export class LocationFilterComponent extends PreactLitAdapter {
41
37
  * Must be of the form `valueForField1 / valueForField2 / ... / valueForFieldN`.
42
38
  */
43
39
  @property()
44
- value = '';
40
+ initialValue = '';
45
41
 
46
42
  /**
47
43
  * The fields to display in the location filter, in hierarchical order.
@@ -53,7 +49,7 @@ export class LocationFilterComponent extends PreactLitAdapter {
53
49
  fields: string[] = [];
54
50
 
55
51
  override render() {
56
- return <LocationFilter value={this.value} fields={this.fields} />;
52
+ return <LocationFilter initialValue={this.initialValue} fields={this.fields} />;
57
53
  }
58
54
  }
59
55
 
@@ -5,6 +5,7 @@ import { html } from 'lit';
5
5
 
6
6
  import { LAPIS_URL } from '../../constants';
7
7
  import '../app';
8
+ import { type MutationFilterProps } from '../../preact/mutationFilter/mutation-filter';
8
9
  import { withinShadowRoot } from '../withinShadowRoot.story';
9
10
  import './mutation-filter-component';
10
11
 
@@ -22,22 +23,32 @@ const meta: Meta = {
22
23
 
23
24
  export default meta;
24
25
 
25
- export const Default: StoryObj<{ lapisField: string; placeholderText: string }> = {
26
- render: () => {
26
+ const Template: StoryObj<MutationFilterProps> = {
27
+ render: (args) => {
27
28
  return html` <gs-app lapis="${LAPIS_URL}">
28
29
  <div class="max-w-screen-lg">
29
- <gs-mutation-filter></gs-mutation-filter>
30
+ <gs-mutation-filter .initialValue=${args.initialValue}></gs-mutation-filter>
30
31
  </div>
31
32
  </gs-app>`;
32
33
  },
34
+ args: {
35
+ initialValue: [],
36
+ },
37
+ };
38
+
39
+ export const Default: StoryObj<MutationFilterProps> = {
40
+ ...Template,
41
+ args: {
42
+ initialValue: ['A123T'],
43
+ },
33
44
  };
34
45
 
35
- export const FiresFilterChangedEvent: StoryObj<{ lapisField: string; placeholderText: string }> = {
36
- ...Default,
46
+ export const FiresFilterChangedEvent: StoryObj<MutationFilterProps> = {
47
+ ...Template,
37
48
  play: async ({ canvasElement, step }) => {
38
49
  const canvas = await withinShadowRoot(canvasElement, 'gs-mutation-filter');
39
50
 
40
- const inputField = () => canvas.getByPlaceholderText('Enter a mutation');
51
+ const inputField = () => canvas.getByPlaceholderText('Enter a mutation', { exact: false });
41
52
  const submitButton = () => canvas.getByRole('button', { name: '+' });
42
53
  const listenerMock = fn();
43
54
  await step('Setup event listener mock', async () => {
@@ -70,12 +81,12 @@ export const FiresFilterChangedEvent: StoryObj<{ lapisField: string; placeholder
70
81
  },
71
82
  };
72
83
 
73
- export const FiresFilterOnBlurEvent: StoryObj<{ lapisField: string; placeholderText: string }> = {
74
- ...Default,
84
+ export const FiresFilterOnBlurEvent: StoryObj<MutationFilterProps> = {
85
+ ...Template,
75
86
  play: async ({ canvasElement, step }) => {
76
87
  const canvas = await withinShadowRoot(canvasElement, 'gs-mutation-filter');
77
88
 
78
- const inputField = () => canvas.getByPlaceholderText('Enter a mutation');
89
+ const inputField = () => canvas.getByPlaceholderText('Enter a mutation', { exact: false });
79
90
  const listenerMock = fn();
80
91
  await step('Setup event listener mock', async () => {
81
92
  canvasElement.addEventListener('gs-mutation-filter-on-blur', listenerMock);
@@ -1,6 +1,7 @@
1
- import { customElement } from 'lit/decorators.js';
1
+ import { customElement, property } from 'lit/decorators.js';
2
2
 
3
3
  import { type TextInputComponent } from './text-input-component';
4
+ import { ReferenceGenomesAwaiter } from '../../preact/components/ReferenceGenomesAwaiter';
4
5
  import { MutationFilter, type SelectedMutationFilterStrings } from '../../preact/mutationFilter/mutation-filter';
5
6
  import { PreactLitAdapter } from '../PreactLitAdapter';
6
7
 
@@ -10,8 +11,15 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
10
11
  */
11
12
  @customElement('gs-mutation-filter')
12
13
  export class MutationFilterComponent extends PreactLitAdapter {
14
+ @property()
15
+ initialValue: SelectedMutationFilterStrings | string[] | undefined = undefined;
16
+
13
17
  override render() {
14
- return <MutationFilter />;
18
+ return (
19
+ <ReferenceGenomesAwaiter>
20
+ <MutationFilter initialValue={this.initialValue} />
21
+ </ReferenceGenomesAwaiter>
22
+ );
15
23
  }
16
24
  }
17
25
 
@@ -7,6 +7,7 @@ import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
7
7
  import '../app';
8
8
  import './text-input-component';
9
9
  import data from '../../preact/textInput/__mockData__/aggregated_hosts.json';
10
+ import type { TextInputProps } from '../../preact/textInput/text-input';
10
11
  import { withinShadowRoot } from '../withinShadowRoot.story';
11
12
 
12
13
  const meta: Meta = {
@@ -35,26 +36,30 @@ const meta: Meta = {
35
36
  },
36
37
  },
37
38
  decorators: [withActions],
38
- tags: ['autodocs'],
39
39
  };
40
40
 
41
41
  export default meta;
42
42
 
43
- export const Default: StoryObj<{ lapisField: string; placeholderText: string }> = {
43
+ export const Default: StoryObj<TextInputProps> = {
44
44
  render: (args) => {
45
45
  return html` <gs-app lapis="${LAPIS_URL}">
46
46
  <div class="max-w-screen-lg">
47
- <gs-text-input .lapisField=${args.lapisField} .placeholderText=${args.placeholderText}></gs-text-input>
47
+ <gs-text-input
48
+ .lapisField=${args.lapisField}
49
+ .placeholderText=${args.placeholderText}
50
+ .initialValue=${args.initialValue}
51
+ ></gs-text-input>
48
52
  </div>
49
53
  </gs-app>`;
50
54
  },
51
55
  args: {
52
56
  lapisField: 'host',
53
57
  placeholderText: 'Enter host name',
58
+ initialValue: 'Homo sapiens',
54
59
  },
55
60
  };
56
61
 
57
- export const FiresEvent: StoryObj<{ lapisField: string; placeholderText: string }> = {
62
+ export const FiresEvent: StoryObj<TextInputProps> = {
58
63
  ...Default,
59
64
  play: async ({ canvasElement, step }) => {
60
65
  const canvas = await withinShadowRoot(canvasElement, 'gs-text-input');
@@ -89,4 +94,8 @@ export const FiresEvent: StoryObj<{ lapisField: string; placeholderText: string
89
94
  );
90
95
  });
91
96
  },
97
+ args: {
98
+ ...Default.args,
99
+ initialValue: '',
100
+ },
92
101
  };
@@ -8,14 +8,23 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
8
8
  */
9
9
  @customElement('gs-text-input')
10
10
  export class TextInputComponent extends PreactLitAdapter {
11
+ @property()
12
+ initialValue: string | undefined = '';
13
+
11
14
  @property()
12
15
  lapisField = '';
13
16
 
14
17
  @property()
15
- placeholderText = '';
18
+ placeholderText: string | undefined = '';
16
19
 
17
20
  override render() {
18
- return <TextInput lapisField={this.lapisField} placeholderText={this.placeholderText} />;
21
+ return (
22
+ <TextInput
23
+ lapisField={this.lapisField}
24
+ placeholderText={this.placeholderText}
25
+ initialValue={this.initialValue}
26
+ />
27
+ );
19
28
  }
20
29
  }
21
30
 
@@ -1,25 +0,0 @@
1
- import { ArgTypes, Description, Meta, Story, Title, Source } from '@storybook/blocks';
2
-
3
- import * as LocationFilterStories from './location-filter-component.stories.ts';
4
-
5
- <Meta of={LocationFilterStories} name='Docs' />
6
-
7
- <Title of={LocationFilterStories} />
8
-
9
- <Description of={LocationFilterStories} />
10
-
11
- ## Specification
12
-
13
- <ArgTypes of={LocationFilterStories} />
14
-
15
- ## Example
16
-
17
- <Source
18
- code={`<gs-location-filter fields="['continent', 'country']" value='Europe / Switzerland'></gs-location-filter>`}
19
- />
20
-
21
- ### Live Example
22
-
23
- [See here](?path=/story/input-location-filter--location-filter)
24
-
25
- <Story of={LocationFilterStories.LocationFilter} />