@genspectrum/dashboard-components 0.19.4 → 0.19.6

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 (54) hide show
  1. package/custom-elements.json +99 -0
  2. package/dist/{LineageFilterChangedEvent-GgkxoF3X.js → LineageFilterChangedEvent-Cqa8Frcf.js} +2 -1
  3. package/dist/{LineageFilterChangedEvent-GgkxoF3X.js.map → LineageFilterChangedEvent-Cqa8Frcf.js.map} +1 -1
  4. package/dist/assets/mutationOverTimeWorker-DQGh08AS.js.map +1 -0
  5. package/dist/components.d.ts +64 -33
  6. package/dist/components.js +82 -22
  7. package/dist/components.js.map +1 -1
  8. package/dist/util.d.ts +47 -33
  9. package/dist/util.js +1 -1
  10. package/package.json +1 -1
  11. package/src/preact/aggregatedData/aggregate.stories.tsx +6 -0
  12. package/src/preact/aggregatedData/aggregate.tsx +10 -1
  13. package/src/preact/components/tabs.tsx +4 -4
  14. package/src/preact/genomeViewer/CDSPlot.tsx +4 -1
  15. package/src/preact/genomeViewer/genome-data-viewer.stories.tsx +6 -0
  16. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +6 -0
  17. package/src/preact/mutationComparison/mutation-comparison.tsx +4 -0
  18. package/src/preact/mutations/mutations.stories.tsx +6 -0
  19. package/src/preact/mutations/mutations.tsx +4 -1
  20. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +4 -2
  21. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +6 -0
  22. package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -1
  23. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -1
  24. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -0
  25. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +6 -0
  26. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -1
  27. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +6 -0
  28. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -1
  29. package/src/preact/sequencesByLocation/sequences-by-location.stories.tsx +6 -0
  30. package/src/preact/sequencesByLocation/sequences-by-location.tsx +4 -0
  31. package/src/preact/shared/stories/expectFinishedLoadingEvent.ts +12 -0
  32. package/src/preact/statistic/statistics.stories.tsx +6 -0
  33. package/src/preact/statistic/statistics.tsx +4 -1
  34. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +37 -1
  35. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +44 -4
  36. package/src/utilEntrypoint.ts +2 -0
  37. package/src/utils/gsEventNames.ts +1 -0
  38. package/src/utils/useDispatchFinishedLoadingEvent.ts +19 -0
  39. package/src/web-components/visualization/gs-aggregate.tsx +3 -0
  40. package/src/web-components/visualization/gs-genome-data-viewer.tsx +2 -0
  41. package/src/web-components/visualization/gs-mutation-comparison.tsx +3 -0
  42. package/src/web-components/visualization/gs-mutations-over-time.tsx +3 -0
  43. package/src/web-components/visualization/gs-mutations.tsx +2 -0
  44. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +3 -0
  45. package/src/web-components/visualization/gs-prevalence-over-time.tsx +3 -0
  46. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +3 -0
  47. package/src/web-components/visualization/gs-sequences-by-location.tsx +3 -0
  48. package/src/web-components/visualization/gs-statistics.tsx +3 -0
  49. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +3 -0
  50. package/standalone-bundle/assets/mutationOverTimeWorker-DAf2_NiP.js.map +1 -0
  51. package/standalone-bundle/dashboard-components.js +7012 -6961
  52. package/standalone-bundle/dashboard-components.js.map +1 -1
  53. package/dist/assets/mutationOverTimeWorker-ChQTFL68.js.map +0 -1
  54. package/standalone-bundle/assets/mutationOverTimeWorker-jChgWnwp.js.map +0 -1
package/dist/util.d.ts CHANGED
@@ -151,6 +151,7 @@ declare const dateRangeValueSchema: default_2.ZodNullable<default_2.ZodUnion<[de
151
151
 
152
152
  export declare const gsEventNames: {
153
153
  readonly error: "gs-error";
154
+ readonly componentFinishedLoading: "gs-component-finished-loading";
154
155
  readonly dateRangeFilterChanged: "gs-date-range-filter-changed";
155
156
  readonly dateRangeOptionChanged: "gs-date-range-option-changed";
156
157
  readonly mutationFilterChanged: "gs-mutation-filter-changed";
@@ -486,6 +487,19 @@ declare const namedLapisFilterSchema: default_2.ZodObject<{
486
487
  displayName: string;
487
488
  }>;
488
489
 
490
+ export declare type NumberRange = default_2.infer<typeof numberRangeSchema>;
491
+
492
+ declare const numberRangeSchema: default_2.ZodObject<{
493
+ min: default_2.ZodOptional<default_2.ZodNumber>;
494
+ max: default_2.ZodOptional<default_2.ZodNumber>;
495
+ }, "strip", default_2.ZodTypeAny, {
496
+ min?: number | undefined;
497
+ max?: number | undefined;
498
+ }, {
499
+ min?: number | undefined;
500
+ max?: number | undefined;
501
+ }>;
502
+
489
503
  export declare type NumberSequencesOverTimeProps = default_2.infer<typeof numberSequencesOverTimePropsSchema>;
490
504
 
491
505
  declare const numberSequencesOverTimePropsSchema: default_2.ZodObject<{
@@ -930,7 +944,7 @@ declare global {
930
944
 
931
945
  declare global {
932
946
  interface HTMLElementTagNameMap {
933
- 'gs-mutation-comparison-component': MutationComparisonComponent;
947
+ 'gs-mutations-component': MutationsComponent;
934
948
  }
935
949
  }
936
950
 
@@ -938,7 +952,7 @@ declare global {
938
952
  declare global {
939
953
  namespace JSX {
940
954
  interface IntrinsicElements {
941
- 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
955
+ 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
942
956
  }
943
957
  }
944
958
  }
@@ -946,7 +960,7 @@ declare global {
946
960
 
947
961
  declare global {
948
962
  interface HTMLElementTagNameMap {
949
- 'gs-mutations-component': MutationsComponent;
963
+ 'gs-mutation-comparison-component': MutationComparisonComponent;
950
964
  }
951
965
  }
952
966
 
@@ -954,7 +968,7 @@ declare global {
954
968
  declare global {
955
969
  namespace JSX {
956
970
  interface IntrinsicElements {
957
- 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
971
+ 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
958
972
  }
959
973
  }
960
974
  }
@@ -994,7 +1008,7 @@ declare global {
994
1008
 
995
1009
  declare global {
996
1010
  interface HTMLElementTagNameMap {
997
- 'gs-aggregate': AggregateComponent;
1011
+ 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
998
1012
  }
999
1013
  }
1000
1014
 
@@ -1002,7 +1016,7 @@ declare global {
1002
1016
  declare global {
1003
1017
  namespace JSX {
1004
1018
  interface IntrinsicElements {
1005
- 'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1019
+ 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1006
1020
  }
1007
1021
  }
1008
1022
  }
@@ -1010,7 +1024,7 @@ declare global {
1010
1024
 
1011
1025
  declare global {
1012
1026
  interface HTMLElementTagNameMap {
1013
- 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1027
+ 'gs-aggregate': AggregateComponent;
1014
1028
  }
1015
1029
  }
1016
1030
 
@@ -1018,7 +1032,7 @@ declare global {
1018
1032
  declare global {
1019
1033
  namespace JSX {
1020
1034
  interface IntrinsicElements {
1021
- 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1035
+ 'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1022
1036
  }
1023
1037
  }
1024
1038
  }
@@ -1058,11 +1072,7 @@ declare global {
1058
1072
 
1059
1073
  declare global {
1060
1074
  interface HTMLElementTagNameMap {
1061
- 'gs-date-range-filter': DateRangeFilterComponent;
1062
- }
1063
- interface HTMLElementEventMap {
1064
- [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1065
- [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1075
+ 'gs-statistics': StatisticsComponent;
1066
1076
  }
1067
1077
  }
1068
1078
 
@@ -1070,7 +1080,7 @@ declare global {
1070
1080
  declare global {
1071
1081
  namespace JSX {
1072
1082
  interface IntrinsicElements {
1073
- 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1083
+ 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1074
1084
  }
1075
1085
  }
1076
1086
  }
@@ -1078,10 +1088,7 @@ declare global {
1078
1088
 
1079
1089
  declare global {
1080
1090
  interface HTMLElementTagNameMap {
1081
- 'gs-location-filter': LocationFilterComponent;
1082
- }
1083
- interface HTMLElementEventMap {
1084
- [gsEventNames.locationChanged]: LocationChangedEvent;
1091
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1085
1092
  }
1086
1093
  }
1087
1094
 
@@ -1089,7 +1096,7 @@ declare global {
1089
1096
  declare global {
1090
1097
  namespace JSX {
1091
1098
  interface IntrinsicElements {
1092
- 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1099
+ 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1093
1100
  }
1094
1101
  }
1095
1102
  }
@@ -1097,7 +1104,11 @@ declare global {
1097
1104
 
1098
1105
  declare global {
1099
1106
  interface HTMLElementTagNameMap {
1100
- 'gs-statistics': StatisticsComponent;
1107
+ 'gs-date-range-filter': DateRangeFilterComponent;
1108
+ }
1109
+ interface HTMLElementEventMap {
1110
+ [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1111
+ [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1101
1112
  }
1102
1113
  }
1103
1114
 
@@ -1105,7 +1116,7 @@ declare global {
1105
1116
  declare global {
1106
1117
  namespace JSX {
1107
1118
  interface IntrinsicElements {
1108
- 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1119
+ 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1109
1120
  }
1110
1121
  }
1111
1122
  }
@@ -1113,10 +1124,10 @@ declare global {
1113
1124
 
1114
1125
  declare global {
1115
1126
  interface HTMLElementTagNameMap {
1116
- 'gs-text-filter': TextFilterComponent;
1127
+ 'gs-location-filter': LocationFilterComponent;
1117
1128
  }
1118
1129
  interface HTMLElementEventMap {
1119
- [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1130
+ [gsEventNames.locationChanged]: LocationChangedEvent;
1120
1131
  }
1121
1132
  }
1122
1133
 
@@ -1124,7 +1135,7 @@ declare global {
1124
1135
  declare global {
1125
1136
  namespace JSX {
1126
1137
  interface IntrinsicElements {
1127
- 'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1138
+ 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1128
1139
  }
1129
1140
  }
1130
1141
  }
@@ -1132,10 +1143,10 @@ declare global {
1132
1143
 
1133
1144
  declare global {
1134
1145
  interface HTMLElementTagNameMap {
1135
- 'gs-lineage-filter': LineageFilterComponent;
1146
+ 'gs-text-filter': TextFilterComponent;
1136
1147
  }
1137
1148
  interface HTMLElementEventMap {
1138
- [gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
1149
+ [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1139
1150
  }
1140
1151
  }
1141
1152
 
@@ -1143,7 +1154,7 @@ declare global {
1143
1154
  declare global {
1144
1155
  namespace JSX {
1145
1156
  interface IntrinsicElements {
1146
- 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1157
+ 'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1147
1158
  }
1148
1159
  }
1149
1160
  }
@@ -1170,11 +1181,10 @@ declare global {
1170
1181
 
1171
1182
  declare global {
1172
1183
  interface HTMLElementTagNameMap {
1173
- 'gs-number-range-filter': NumberRangeFilterComponent;
1184
+ 'gs-lineage-filter': LineageFilterComponent;
1174
1185
  }
1175
1186
  interface HTMLElementEventMap {
1176
- [gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
1177
- [gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
1187
+ [gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
1178
1188
  }
1179
1189
  }
1180
1190
 
@@ -1182,7 +1192,7 @@ declare global {
1182
1192
  declare global {
1183
1193
  namespace JSX {
1184
1194
  interface IntrinsicElements {
1185
- 'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1195
+ 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1186
1196
  }
1187
1197
  }
1188
1198
  }
@@ -1190,7 +1200,11 @@ declare global {
1190
1200
 
1191
1201
  declare global {
1192
1202
  interface HTMLElementTagNameMap {
1193
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1203
+ 'gs-number-range-filter': NumberRangeFilterComponent;
1204
+ }
1205
+ interface HTMLElementEventMap {
1206
+ [gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
1207
+ [gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
1194
1208
  }
1195
1209
  }
1196
1210
 
@@ -1198,7 +1212,7 @@ declare global {
1198
1212
  declare global {
1199
1213
  namespace JSX {
1200
1214
  interface IntrinsicElements {
1201
- 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1215
+ 'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1202
1216
  }
1203
1217
  }
1204
1218
  }
package/dist/util.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, a, L, T, d, g, v } from "./LineageFilterChangedEvent-GgkxoF3X.js";
1
+ import { D, a, L, T, d, g, v } from "./LineageFilterChangedEvent-Cqa8Frcf.js";
2
2
  export {
3
3
  D as DateRangeOptionChangedEvent,
4
4
  a as LineageFilterChangedEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.19.4",
3
+ "version": "0.19.6",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -6,6 +6,7 @@ import { Aggregate, type AggregateProps } from './aggregate';
6
6
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
7
7
  import { LapisUrlContextProvider } from '../LapisUrlContext';
8
8
  import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
9
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
9
10
 
10
11
  const meta: Meta<AggregateProps> = {
11
12
  title: 'Visualization/Aggregate',
@@ -62,6 +63,11 @@ export const Default: StoryObj<AggregateProps> = {
62
63
  },
63
64
  };
64
65
 
66
+ export const FiresFinishedLoadingEvent: StoryObj<AggregateProps> = {
67
+ ...Default,
68
+ play: playThatExpectsFinishedLoadingEvent(),
69
+ };
70
+
65
71
  export const FailsLoadingData: StoryObj<AggregateProps> = {
66
72
  ...Default,
67
73
  parameters: {
@@ -5,6 +5,7 @@ import { useLapisUrl } from '../LapisUrlContext';
5
5
  import { AggregateTable } from './aggregate-table';
6
6
  import { type AggregateData, queryAggregateData } from '../../query/queryAggregateData';
7
7
  import { lapisFilterSchema, views } from '../../types';
8
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
8
9
  import { CsvDownloadButton } from '../components/csv-download-button';
9
10
  import { ErrorBoundary } from '../components/error-boundary';
10
11
  import { Fullscreen } from '../components/fullscreen';
@@ -75,6 +76,8 @@ type AggregatedDataTabsProps = {
75
76
  };
76
77
 
77
78
  const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data, originalComponentProps }) => {
79
+ const tabsRef = useDispatchFinishedLoadingEvent();
80
+
78
81
  const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
79
82
 
80
83
  const getTab = (view: AggregateView) => {
@@ -109,7 +112,13 @@ const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data,
109
112
 
110
113
  const tabs = originalComponentProps.views.map((view) => getTab(view));
111
114
 
112
- return <Tabs tabs={tabs} toolbar={<Toolbar data={data} originalComponentProps={originalComponentProps} />} />;
115
+ return (
116
+ <Tabs
117
+ ref={tabsRef}
118
+ tabs={tabs}
119
+ toolbar={<Toolbar data={data} originalComponentProps={originalComponentProps} />}
120
+ />
121
+ );
113
122
  };
114
123
 
115
124
  type ToolbarProps = {
@@ -1,4 +1,4 @@
1
- import { type FunctionComponent } from 'preact';
1
+ import { forwardRef } from 'preact/compat';
2
2
  import { useState } from 'preact/hooks';
3
3
  import { type JSXInternal } from 'preact/src/jsx';
4
4
 
@@ -12,7 +12,7 @@ interface ComponentTabsProps {
12
12
  toolbar?: JSXInternal.Element | ((activeTab: string) => JSXInternal.Element);
13
13
  }
14
14
 
15
- const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
15
+ const Tabs = forwardRef<HTMLDivElement, ComponentTabsProps>(({ tabs, toolbar }, ref) => {
16
16
  const [activeTab, setActiveTab] = useState(tabs[0]?.title);
17
17
 
18
18
  const tabElements = (
@@ -40,7 +40,7 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
40
40
  const toolbarElement = typeof toolbar === 'function' ? toolbar(activeTab) : toolbar;
41
41
 
42
42
  return (
43
- <div className='h-full w-full flex flex-col'>
43
+ <div ref={ref} className='h-full w-full flex flex-col'>
44
44
  <div className='flex flex-row justify-between flex-wrap'>
45
45
  {tabElements}
46
46
  {toolbar && <div className='py-2 flex flex-wrap gap-y-1'>{toolbarElement}</div>}
@@ -54,6 +54,6 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
54
54
  </div>
55
55
  </div>
56
56
  );
57
- };
57
+ });
58
58
 
59
59
  export default Tabs;
@@ -2,6 +2,7 @@ import { Fragment, type FunctionComponent } from 'preact';
2
2
  import { useMemo, useState } from 'preact/hooks';
3
3
 
4
4
  import { type CDSFeature } from './loadGff3';
5
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
5
6
  import { MinMaxRangeSlider } from '../components/min-max-range-slider';
6
7
  import Tooltip from '../components/tooltip';
7
8
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
@@ -183,6 +184,8 @@ interface CDSProps {
183
184
  }
184
185
 
185
186
  const CDSPlot: FunctionComponent<CDSProps> = (componentProps) => {
187
+ const ref = useDispatchFinishedLoadingEvent();
188
+
186
189
  const { gffData, genomeLength, width } = componentProps;
187
190
 
188
191
  const [zoomStart, setZoomStart] = useState(0);
@@ -197,7 +200,7 @@ const CDSPlot: FunctionComponent<CDSProps> = (componentProps) => {
197
200
  };
198
201
 
199
202
  return (
200
- <div class='p-4'>
203
+ <div ref={ref} class='p-4'>
201
204
  <CDSBars gffData={gffData} zoomStart={zoomStart} zoomEnd={zoomEnd} />
202
205
  <XAxis zoomStart={zoomStart} zoomEnd={zoomEnd} fullWidth={width} />
203
206
  <div class='relative w-full h-5'>
@@ -2,6 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
2
2
 
3
3
  import { GenomeDataViewer, type GenomeDataViewerProps } from './genome-data-viewer';
4
4
  import { playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
5
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
5
6
 
6
7
  const meta: Meta<GenomeDataViewerProps> = {
7
8
  title: 'Visualization/GenomeDataViewer',
@@ -75,6 +76,11 @@ export const Default: StoryObj<GenomeDataViewerProps> = {
75
76
  },
76
77
  };
77
78
 
79
+ export const FiresFinishedLoadingEvent: StoryObj<GenomeDataViewerProps> = {
80
+ ...Default,
81
+ play: playThatExpectsFinishedLoadingEvent(),
82
+ };
83
+
78
84
  export const InvalidProps: StoryObj<GenomeDataViewerProps> = {
79
85
  ...Default,
80
86
  args: {
@@ -10,6 +10,7 @@ import { type MutationAnnotations } from '../../web-components/mutation-annotati
10
10
  import { LapisUrlContextProvider } from '../LapisUrlContext';
11
11
  import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
12
12
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
13
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
13
14
  import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
14
15
 
15
16
  const dateToSomeDataset = '2022-01-01';
@@ -142,6 +143,11 @@ export const TwoVariants: StoryObj<MutationComparisonProps> = {
142
143
  },
143
144
  };
144
145
 
146
+ export const FiresFinishedLoadingEvent: StoryObj<MutationComparisonProps> = {
147
+ ...TwoVariants,
148
+ play: playThatExpectsFinishedLoadingEvent(),
149
+ };
150
+
145
151
  export const FilterForOnlyDeletions: StoryObj<MutationComparisonProps> = {
146
152
  ...TwoVariants,
147
153
  play: async ({ canvasElement }) => {
@@ -7,6 +7,7 @@ import { MutationComparisonTable } from './mutation-comparison-table';
7
7
  import { MutationComparisonVenn } from './mutation-comparison-venn';
8
8
  import { filterMutationData, type MutationData, queryMutationData } from './queryMutationData';
9
9
  import { namedLapisFilterSchema, sequenceTypeSchema, views } from '../../types';
10
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
10
11
  import { useLapisUrl } from '../LapisUrlContext';
11
12
  import { CsvDownloadButton } from '../components/csv-download-button';
12
13
  import { ErrorBoundary } from '../components/error-boundary';
@@ -80,6 +81,8 @@ type MutationComparisonTabsProps = {
80
81
  };
81
82
 
82
83
  const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = ({ data, originalComponentProps }) => {
84
+ const tabsRef = useDispatchFinishedLoadingEvent();
85
+
83
86
  const [proportionInterval, setProportionInterval] = useState({ min: 0.5, max: 1 });
84
87
  const [displayedMutationTypes, setDisplayedMutationTypes] = useState<DisplayedMutationType[]>([
85
88
  { label: 'Substitutions', checked: true, type: 'substitution' },
@@ -127,6 +130,7 @@ const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = (
127
130
 
128
131
  return (
129
132
  <Tabs
133
+ ref={tabsRef}
130
134
  tabs={tabs}
131
135
  toolbar={
132
136
  <Toolbar
@@ -17,6 +17,7 @@ import { type MutationAnnotations } from '../../web-components/mutation-annotati
17
17
  import { LapisUrlContextProvider } from '../LapisUrlContext';
18
18
  import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
19
19
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
20
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
20
21
  import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
21
22
 
22
23
  const meta: Meta<MutationsProps> = {
@@ -147,6 +148,11 @@ export const Default: StoryObj<MutationsProps> = {
147
148
  },
148
149
  };
149
150
 
151
+ export const FiresFinishedLoadingEvent: StoryObj<MutationsProps> = {
152
+ ...Default,
153
+ play: playThatExpectsFinishedLoadingEvent(),
154
+ };
155
+
150
156
  export const GridTab: StoryObj<MutationsProps> = {
151
157
  ...Default,
152
158
  play: async ({ canvasElement, step }) => {
@@ -15,6 +15,7 @@ import {
15
15
  type SubstitutionOrDeletionEntry,
16
16
  views,
17
17
  } from '../../types';
18
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
18
19
  import { useLapisUrl } from '../LapisUrlContext';
19
20
  import { CsvDownloadButton } from '../components/csv-download-button';
20
21
  import { ErrorBoundary } from '../components/error-boundary';
@@ -87,6 +88,8 @@ type MutationTabsProps = {
87
88
  };
88
89
 
89
90
  const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, originalComponentProps }) => {
91
+ const tabsRef = useDispatchFinishedLoadingEvent();
92
+
90
93
  const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 1 });
91
94
 
92
95
  const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
@@ -153,7 +156,7 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, or
153
156
  />
154
157
  );
155
158
 
156
- return <Tabs tabs={tabs} toolbar={toolbar} />;
159
+ return <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />;
157
160
  };
158
161
 
159
162
  type ToolbarProps = {
@@ -51,7 +51,9 @@ export function getFilteredMutationOverTimeData({
51
51
  return true;
52
52
  }
53
53
 
54
- if (applySearchFilter(entry.mutation, sequenceType, mutationFilterValue, annotationProvider)) {
54
+ if (
55
+ mutationOrAnnotationDoNotMatchFilter(entry.mutation, sequenceType, mutationFilterValue, annotationProvider)
56
+ ) {
55
57
  return true;
56
58
  }
57
59
 
@@ -67,7 +69,7 @@ export function getFilteredMutationOverTimeData({
67
69
  return filteredData;
68
70
  }
69
71
 
70
- export function applySearchFilter(
72
+ export function mutationOrAnnotationDoNotMatchFilter(
71
73
  mutation: Mutation,
72
74
  sequenceType: SequenceType,
73
75
  filterValue: string,
@@ -10,6 +10,7 @@ import { LapisUrlContextProvider } from '../LapisUrlContext';
10
10
  import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
11
11
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
12
12
  import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
13
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
13
14
  import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
14
15
 
15
16
  const meta: Meta<MutationsOverTimeProps> = {
@@ -83,6 +84,11 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
83
84
  },
84
85
  };
85
86
 
87
+ export const FiresFinishedLoadingEvent: StoryObj<MutationsOverTimeProps> = {
88
+ ...Default,
89
+ play: playThatExpectsFinishedLoadingEvent(),
90
+ };
91
+
86
92
  export const ShowsMutationAnnotations: StoryObj<MutationsOverTimeProps> = {
87
93
  ...Default,
88
94
  play: async ({ canvasElement }) => {
@@ -18,6 +18,7 @@ import {
18
18
  } from '../../types';
19
19
  import { type Deletion, type Substitution } from '../../utils/mutations';
20
20
  import { toTemporalClass } from '../../utils/temporalClass';
21
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
21
22
  import { useLapisUrl } from '../LapisUrlContext';
22
23
  import { useMutationAnnotationsProvider } from '../MutationAnnotationsContext';
23
24
  import { type ColorScale } from '../components/color-scale-selector';
@@ -126,6 +127,8 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
126
127
  originalComponentProps,
127
128
  overallMutationData,
128
129
  }) => {
130
+ const tabsRef = useDispatchFinishedLoadingEvent();
131
+
129
132
  const [mutationFilterValue, setMutationFilterValue] = useState('');
130
133
  const annotationProvider = useMutationAnnotationsProvider();
131
134
 
@@ -207,7 +210,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
207
210
 
208
211
  return (
209
212
  <PageSizeContextProvider pageSizes={originalComponentProps.pageSizes}>
210
- <Tabs tabs={tabs} toolbar={toolbar} />
213
+ <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />
211
214
  </PageSizeContextProvider>
212
215
  );
213
216
  };
@@ -7,6 +7,7 @@ import twoVariantsEG from '../../preact/numberSequencesOverTime/__mockData__/two
7
7
  import twoVariantsJN1 from '../../preact/numberSequencesOverTime/__mockData__/twoVariantsJN1.json';
8
8
  import { LapisUrlContextProvider } from '../LapisUrlContext';
9
9
  import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
10
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
10
11
 
11
12
  export default {
12
13
  title: 'Visualization/NumberSequencesOverTime',
@@ -71,8 +72,9 @@ const Template: StoryObj<NumberSequencesOverTimeProps> = {
71
72
  },
72
73
  };
73
74
 
74
- export const Table = {
75
+ export const FiresFinishedLoadingEvent: StoryObj<NumberSequencesOverTimeProps> = {
75
76
  ...Template,
77
+ play: playThatExpectsFinishedLoadingEvent(),
76
78
  };
77
79
 
78
80
  export const TwoVariants: StoryObj<NumberSequencesOverTimeProps> = {
@@ -11,6 +11,7 @@ import {
11
11
  queryNumberOfSequencesOverTime,
12
12
  } from '../../query/queryNumberOfSequencesOverTime';
13
13
  import { namedLapisFilterSchema, temporalGranularitySchema, views } from '../../types';
14
+ import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
14
15
  import { useLapisUrl } from '../LapisUrlContext';
15
16
  import { CsvDownloadButton } from '../components/csv-download-button';
16
17
  import { ErrorBoundary } from '../components/error-boundary';
@@ -88,6 +89,8 @@ interface NumberSequencesOverTimeTabsProps {
88
89
  }
89
90
 
90
91
  const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }: NumberSequencesOverTimeTabsProps) => {
92
+ const tabsRef = useDispatchFinishedLoadingEvent();
93
+
91
94
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
92
95
 
93
96
  const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
@@ -134,6 +137,7 @@ const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }: NumberSeq
134
137
 
135
138
  return (
136
139
  <Tabs
140
+ ref={tabsRef}
137
141
  tabs={originalComponentProps.views.map((view) => getTab(view))}
138
142
  toolbar={(activeTab) => (
139
143
  <Toolbar
@@ -11,6 +11,7 @@ import numeratorOneDataset from './__mockData__/numeratorFilterOneDataset.json';
11
11
  import { PrevalenceOverTime, type PrevalenceOverTimeProps } from './prevalence-over-time';
12
12
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
13
13
  import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
14
+ import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
14
15
 
15
16
  export default {
16
17
  title: 'Visualization/PrevalenceOverTime',
@@ -121,6 +122,11 @@ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
121
122
  },
122
123
  };
123
124
 
125
+ export const FiresFinishedLoadingEvent: StoryObj<PrevalenceOverTimeProps> = {
126
+ ...TwoVariants,
127
+ play: playThatExpectsFinishedLoadingEvent(),
128
+ };
129
+
124
130
  export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
125
131
  ...Template,
126
132
  args: {
@@ -9,6 +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 { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
12
13
  import { useLapisUrl } from '../LapisUrlContext';
13
14
  import { ConfidenceIntervalSelector } from '../components/confidence-interval-selector';
14
15
  import { CsvDownloadButton } from '../components/csv-download-button';
@@ -101,6 +102,8 @@ type PrevalenceOverTimeTabsProps = PrevalenceOverTimeProps & {
101
102
  };
102
103
 
103
104
  const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = ({ data, ...componentProps }) => {
105
+ const tabsRef = useDispatchFinishedLoadingEvent();
106
+
104
107
  const { views, granularity, confidenceIntervalMethods, pageSize, yAxisMaxLinear, yAxisMaxLogarithmic } =
105
108
  componentProps;
106
109
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
@@ -182,7 +185,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
182
185
  />
183
186
  );
184
187
 
185
- return <Tabs tabs={tabs} toolbar={toolbar} />;
188
+ return <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />;
186
189
  };
187
190
 
188
191
  type ToolbarProps = PrevalenceOverTimeProps & {