@genspectrum/dashboard-components 1.1.0 → 1.2.0

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 (97) hide show
  1. package/custom-elements.json +2 -2
  2. package/dist/{NumberRangeFilterChangedEvent-B64OQZjX.js → NumberRangeFilterChangedEvent-CQ32Qy8D.js} +2 -2
  3. package/dist/NumberRangeFilterChangedEvent-CQ32Qy8D.js.map +1 -0
  4. package/dist/assets/mutationOverTimeWorker-DpW4YOGl.js.map +1 -0
  5. package/dist/components.d.ts +31 -31
  6. package/dist/components.js +74 -120
  7. package/dist/components.js.map +1 -1
  8. package/dist/util.d.ts +31 -31
  9. package/dist/util.js +1 -1
  10. package/package.json +7 -3
  11. package/src/lapisApi/lapisApi.ts +2 -2
  12. package/src/operator/DivisionOperator.ts +4 -2
  13. package/src/operator/FetchDetailsOperator.ts +1 -1
  14. package/src/operator/RenameFieldOperator.ts +3 -3
  15. package/src/preact/aggregatedData/aggregate.tsx +0 -5
  16. package/src/preact/components/annotated-mutation.tsx +0 -1
  17. package/src/preact/components/clearable-select.stories.tsx +1 -1
  18. package/src/preact/components/confidence-interval-selector.tsx +1 -1
  19. package/src/preact/components/error-boundary.tsx +1 -5
  20. package/src/preact/components/error-display.tsx +1 -1
  21. package/src/preact/components/fullscreen.tsx +2 -5
  22. package/src/preact/components/info.stories.tsx +1 -1
  23. package/src/preact/components/min-max-range-slider.tsx +1 -1
  24. package/src/preact/components/proportion-selector.tsx +4 -4
  25. package/src/preact/components/select.tsx +1 -1
  26. package/src/preact/components/table.tsx +1 -1
  27. package/src/preact/components/tabs.tsx +1 -1
  28. package/src/preact/components/tooltip.stories.tsx +1 -1
  29. package/src/preact/components/tooltip.tsx +1 -1
  30. package/src/preact/genomeViewer/CDSPlot.tsx +3 -3
  31. package/src/preact/genomeViewer/loadGff3.ts +5 -8
  32. package/src/preact/lineageFilter/lineage-filter.tsx +1 -1
  33. package/src/preact/locationFilter/location-filter.tsx +4 -4
  34. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +1 -3
  35. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +1 -1
  36. package/src/preact/mutationComparison/mutation-comparison.tsx +0 -5
  37. package/src/preact/mutationFilter/mutation-filter-info.tsx +2 -2
  38. package/src/preact/mutationFilter/mutation-filter.tsx +1 -1
  39. package/src/preact/mutations/getMutationsGridData.ts +2 -6
  40. package/src/preact/mutations/getMutationsTableData.ts +1 -1
  41. package/src/preact/mutations/mutations-grid.tsx +1 -1
  42. package/src/preact/mutations/mutations.tsx +0 -5
  43. package/src/preact/mutationsOverTime/mutations-over-time.tsx +3 -9
  44. package/src/preact/numberRangeFilter/number-range-filter.tsx +4 -4
  45. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +1 -4
  46. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +0 -5
  47. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +1 -1
  48. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -1
  49. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +1 -1
  50. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +1 -1
  51. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +5 -5
  52. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +1 -4
  53. package/src/preact/sequencesByLocation/loadMapSource.tsx +5 -2
  54. package/src/preact/shared/aspectRatio/AspectRatio.tsx +1 -1
  55. package/src/preact/shared/floating-ui/hooks.ts +2 -2
  56. package/src/preact/shared/sort/sortMutationPositions.ts +2 -2
  57. package/src/preact/shared/tanstackTable/pagination.tsx +2 -2
  58. package/src/preact/shared/tanstackTable/tanstackTable.tsx +1 -1
  59. package/src/preact/statistic/statistics.tsx +0 -5
  60. package/src/preact/textFilter/fetchStringAutocompleteList.ts +1 -10
  61. package/src/preact/textFilter/text-filter.tsx +1 -6
  62. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +1 -1
  63. package/src/preact/webWorkers/useWebWorker.ts +2 -1
  64. package/src/preact/webWorkers/workerFunction.ts +2 -2
  65. package/src/query/computeMapLocationData.ts +1 -1
  66. package/src/query/queryAggregatedDataOverTime.ts +3 -3
  67. package/src/query/queryMutationsOverTime.spec.ts +9 -9
  68. package/src/query/queryMutationsOverTime.ts +22 -16
  69. package/src/query/queryRelativeGrowthAdvantage.ts +5 -9
  70. package/src/query/queryWastewaterMutationsOverTime.ts +1 -1
  71. package/src/types.ts +1 -1
  72. package/src/utils/mutations.ts +10 -10
  73. package/src/utils/type-utils.ts +1 -1
  74. package/src/utils/typeAssertions.spec.ts +1 -1
  75. package/src/web-components/gs-app.spec-d.ts +1 -1
  76. package/src/web-components/gs-app.stories.ts +1 -1
  77. package/src/web-components/input/gs-date-range-filter.tsx +2 -2
  78. package/src/web-components/input/gs-lineage-filter.tsx +2 -2
  79. package/src/web-components/input/gs-location-filter.tsx +3 -3
  80. package/src/web-components/input/gs-mutation-filter.tsx +2 -2
  81. package/src/web-components/input/gs-number-range-filter.spec.ts +1 -1
  82. package/src/web-components/input/gs-text-filter.tsx +2 -2
  83. package/src/web-components/visualization/gs-aggregate.tsx +2 -2
  84. package/src/web-components/visualization/gs-genome-data-viewer.spec-d.ts +1 -1
  85. package/src/web-components/visualization/gs-mutation-comparison.tsx +2 -2
  86. package/src/web-components/visualization/gs-mutations.tsx +2 -2
  87. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +2 -2
  88. package/src/web-components/visualization/gs-prevalence-over-time.tsx +2 -2
  89. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +2 -2
  90. package/src/web-components/visualization/gs-sequences-by-location.tsx +2 -2
  91. package/src/web-components/visualization/gs-statistics.tsx +2 -2
  92. package/standalone-bundle/assets/mutationOverTimeWorker-CZVvQBze.js.map +1 -0
  93. package/standalone-bundle/dashboard-components.js +1444 -1456
  94. package/standalone-bundle/dashboard-components.js.map +1 -1
  95. package/dist/NumberRangeFilterChangedEvent-B64OQZjX.js.map +0 -1
  96. package/dist/assets/mutationOverTimeWorker-DjH04AQB.js.map +0 -1
  97. package/standalone-bundle/assets/mutationOverTimeWorker-B6bf3R3j.js.map +0 -1
package/dist/util.d.ts CHANGED
@@ -164,7 +164,7 @@ declare type LapisLineageFilter = Record<string, string | undefined>;
164
164
 
165
165
  declare type LapisLocationFilter = default_2.infer<typeof lapisLocationFilterSchema>;
166
166
 
167
- declare const lapisLocationFilterSchema: default_2.ZodRecord<default_2.ZodString, default_2.ZodUnion<[default_2.ZodString, default_2.ZodUndefined]>>;
167
+ declare const lapisLocationFilterSchema: default_2.ZodRecord<default_2.ZodString, default_2.ZodUnion<[default_2.ZodString, default_2.ZodUndefined, default_2.ZodNull]>>;
168
168
 
169
169
  export declare type LapisNumberFilter = Record<string, number | undefined>;
170
170
 
@@ -917,7 +917,7 @@ declare global {
917
917
 
918
918
  declare global {
919
919
  interface HTMLElementTagNameMap {
920
- 'gs-genome-data-viewer': GenomeDataViewerComponent;
920
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
921
921
  }
922
922
  }
923
923
 
@@ -925,7 +925,7 @@ declare global {
925
925
  declare global {
926
926
  namespace JSX {
927
927
  interface IntrinsicElements {
928
- 'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
928
+ 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
929
929
  }
930
930
  }
931
931
  }
@@ -933,7 +933,7 @@ declare global {
933
933
 
934
934
  declare global {
935
935
  interface HTMLElementTagNameMap {
936
- 'gs-mutation-comparison-component': MutationComparisonComponent;
936
+ 'gs-genome-data-viewer': GenomeDataViewerComponent;
937
937
  }
938
938
  }
939
939
 
@@ -941,7 +941,7 @@ declare global {
941
941
  declare global {
942
942
  namespace JSX {
943
943
  interface IntrinsicElements {
944
- 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
944
+ 'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
945
945
  }
946
946
  }
947
947
  }
@@ -949,7 +949,7 @@ declare global {
949
949
 
950
950
  declare global {
951
951
  interface HTMLElementTagNameMap {
952
- 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
952
+ 'gs-mutations': MutationsComponent;
953
953
  }
954
954
  }
955
955
 
@@ -957,7 +957,7 @@ declare global {
957
957
  declare global {
958
958
  namespace JSX {
959
959
  interface IntrinsicElements {
960
- 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
960
+ 'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
961
961
  }
962
962
  }
963
963
  }
@@ -965,7 +965,7 @@ declare global {
965
965
 
966
966
  declare global {
967
967
  interface HTMLElementTagNameMap {
968
- 'gs-mutations': MutationsComponent;
968
+ 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
969
969
  }
970
970
  }
971
971
 
@@ -973,7 +973,7 @@ declare global {
973
973
  declare global {
974
974
  namespace JSX {
975
975
  interface IntrinsicElements {
976
- 'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
976
+ 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
977
977
  }
978
978
  }
979
979
  }
@@ -981,7 +981,7 @@ declare global {
981
981
 
982
982
  declare global {
983
983
  interface HTMLElementTagNameMap {
984
- 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
984
+ 'gs-mutation-comparison-component': MutationComparisonComponent;
985
985
  }
986
986
  }
987
987
 
@@ -989,7 +989,7 @@ declare global {
989
989
  declare global {
990
990
  namespace JSX {
991
991
  interface IntrinsicElements {
992
- 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
992
+ 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
993
993
  }
994
994
  }
995
995
  }
@@ -1013,7 +1013,7 @@ declare global {
1013
1013
 
1014
1014
  declare global {
1015
1015
  interface HTMLElementTagNameMap {
1016
- 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1016
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
1017
1017
  }
1018
1018
  }
1019
1019
 
@@ -1021,7 +1021,7 @@ declare global {
1021
1021
  declare global {
1022
1022
  namespace JSX {
1023
1023
  interface IntrinsicElements {
1024
- 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1024
+ 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1025
1025
  }
1026
1026
  }
1027
1027
  }
@@ -1029,7 +1029,7 @@ declare global {
1029
1029
 
1030
1030
  declare global {
1031
1031
  interface HTMLElementTagNameMap {
1032
- 'gs-mutations-over-time': MutationsOverTimeComponent;
1032
+ 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1033
1033
  }
1034
1034
  }
1035
1035
 
@@ -1037,7 +1037,7 @@ declare global {
1037
1037
  declare global {
1038
1038
  namespace JSX {
1039
1039
  interface IntrinsicElements {
1040
- 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1040
+ 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1041
1041
  }
1042
1042
  }
1043
1043
  }
@@ -1045,7 +1045,7 @@ declare global {
1045
1045
 
1046
1046
  declare global {
1047
1047
  interface HTMLElementTagNameMap {
1048
- 'gs-sequences-by-location': SequencesByLocationComponent;
1048
+ 'gs-mutations-over-time': MutationsOverTimeComponent;
1049
1049
  }
1050
1050
  }
1051
1051
 
@@ -1053,7 +1053,7 @@ declare global {
1053
1053
  declare global {
1054
1054
  namespace JSX {
1055
1055
  interface IntrinsicElements {
1056
- 'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1056
+ 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1057
1057
  }
1058
1058
  }
1059
1059
  }
@@ -1061,7 +1061,7 @@ declare global {
1061
1061
 
1062
1062
  declare global {
1063
1063
  interface HTMLElementTagNameMap {
1064
- 'gs-statistics': StatisticsComponent;
1064
+ 'gs-sequences-by-location': SequencesByLocationComponent;
1065
1065
  }
1066
1066
  }
1067
1067
 
@@ -1069,7 +1069,7 @@ declare global {
1069
1069
  declare global {
1070
1070
  namespace JSX {
1071
1071
  interface IntrinsicElements {
1072
- 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1072
+ 'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1073
1073
  }
1074
1074
  }
1075
1075
  }
@@ -1077,7 +1077,7 @@ declare global {
1077
1077
 
1078
1078
  declare global {
1079
1079
  interface HTMLElementTagNameMap {
1080
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1080
+ 'gs-statistics': StatisticsComponent;
1081
1081
  }
1082
1082
  }
1083
1083
 
@@ -1085,7 +1085,7 @@ declare global {
1085
1085
  declare global {
1086
1086
  namespace JSX {
1087
1087
  interface IntrinsicElements {
1088
- 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1088
+ 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1089
1089
  }
1090
1090
  }
1091
1091
  }
@@ -1093,10 +1093,11 @@ declare global {
1093
1093
 
1094
1094
  declare global {
1095
1095
  interface HTMLElementTagNameMap {
1096
- 'gs-location-filter': LocationFilterComponent;
1096
+ 'gs-date-range-filter': DateRangeFilterComponent;
1097
1097
  }
1098
1098
  interface HTMLElementEventMap {
1099
- [gsEventNames.locationChanged]: LocationChangedEvent;
1099
+ [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1100
+ [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1100
1101
  }
1101
1102
  }
1102
1103
 
@@ -1104,7 +1105,7 @@ declare global {
1104
1105
  declare global {
1105
1106
  namespace JSX {
1106
1107
  interface IntrinsicElements {
1107
- 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1108
+ 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1108
1109
  }
1109
1110
  }
1110
1111
  }
@@ -1112,10 +1113,10 @@ declare global {
1112
1113
 
1113
1114
  declare global {
1114
1115
  interface HTMLElementTagNameMap {
1115
- 'gs-text-filter': TextFilterComponent;
1116
+ 'gs-location-filter': LocationFilterComponent;
1116
1117
  }
1117
1118
  interface HTMLElementEventMap {
1118
- [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1119
+ [gsEventNames.locationChanged]: LocationChangedEvent;
1119
1120
  }
1120
1121
  }
1121
1122
 
@@ -1123,7 +1124,7 @@ declare global {
1123
1124
  declare global {
1124
1125
  namespace JSX {
1125
1126
  interface IntrinsicElements {
1126
- 'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1127
+ 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1127
1128
  }
1128
1129
  }
1129
1130
  }
@@ -1131,11 +1132,10 @@ declare global {
1131
1132
 
1132
1133
  declare global {
1133
1134
  interface HTMLElementTagNameMap {
1134
- 'gs-date-range-filter': DateRangeFilterComponent;
1135
+ 'gs-text-filter': TextFilterComponent;
1135
1136
  }
1136
1137
  interface HTMLElementEventMap {
1137
- [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1138
- [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1138
+ [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1139
1139
  }
1140
1140
  }
1141
1141
 
@@ -1143,7 +1143,7 @@ declare global {
1143
1143
  declare global {
1144
1144
  namespace JSX {
1145
1145
  interface IntrinsicElements {
1146
- 'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1146
+ 'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1147
1147
  }
1148
1148
  }
1149
1149
  }
package/dist/util.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, a, L, N, b, T, d, g, v } from "./NumberRangeFilterChangedEvent-B64OQZjX.js";
1
+ import { D, a, L, N, b, T, d, g, v } from "./NumberRangeFilterChangedEvent-CQ32Qy8D.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": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -99,6 +99,7 @@
99
99
  },
100
100
  "devDependencies": {
101
101
  "@custom-elements-manifest/analyzer": "^0.10.2",
102
+ "@eslint/js": "^9.31.0",
102
103
  "@iconify-json/mdi": "^1.1.67",
103
104
  "@iconify-json/mdi-light": "^1.1.10",
104
105
  "@iconify/tailwind4": "^1.0.6",
@@ -127,11 +128,13 @@
127
128
  "autoprefixer": "^10.4.19",
128
129
  "daisyui": "^5.0.0",
129
130
  "depcheck": "^1.4.7",
130
- "eslint": "^8.57.0",
131
- "eslint-config-preact": "^1.3.0",
131
+ "eslint": "^9.31.0",
132
132
  "eslint-plugin-import": "^2.29.1",
133
133
  "eslint-plugin-jest": "^28.2.0",
134
+ "eslint-plugin-react": "^7.37.5",
135
+ "eslint-plugin-react-hooks": "^5.2.0",
134
136
  "eslint-plugin-storybook": "^0.12.0",
137
+ "globals": "^16.3.0",
135
138
  "happy-dom": "^17.1.1",
136
139
  "http-server": "^14.1.1",
137
140
  "lit-analyzer": "^2.0.3",
@@ -143,6 +146,7 @@
143
146
  "storybook-addon-fetch-mock": "^2.0.0",
144
147
  "tailwindcss": "^4.0.9",
145
148
  "typescript": "^5.8.2",
149
+ "typescript-eslint": "^8.36.0",
146
150
  "vite": "^6.0.3",
147
151
  "vite-plugin-dts": "4.5.0",
148
152
  "vitest": "^3.0.2"
@@ -176,7 +176,7 @@ const handleErrors = async (response: Response, requestedData: string) => {
176
176
  const lapisErrorResult = lapisError.safeParse(json);
177
177
  if (lapisErrorResult.success) {
178
178
  throw new LapisError(
179
- response.statusText + lapisErrorResult.data.error.detail,
179
+ response.statusText + (lapisErrorResult.data.error.detail ?? ''),
180
180
  response.status,
181
181
  lapisErrorResult.data.error,
182
182
  requestedData,
@@ -186,7 +186,7 @@ const handleErrors = async (response: Response, requestedData: string) => {
186
186
  const problemDetailResult = problemDetail.safeParse(json);
187
187
  if (problemDetailResult.success) {
188
188
  throw new LapisError(
189
- response.statusText + problemDetailResult.data.detail,
189
+ response.statusText + (problemDetailResult.data.detail ?? ''),
190
190
  response.status,
191
191
  problemDetailResult.data,
192
192
  requestedData,
@@ -8,7 +8,8 @@ export type DivisionOperatorResult<
8
8
  ResultField extends string,
9
9
  NumeratorField extends string,
10
10
  DenominatorField extends string,
11
- > = { [P in KeyField]: ValueObject[KeyField] } & MappedNumber<ResultField> &
11
+ > = Record<KeyField, ValueObject[KeyField]> &
12
+ MappedNumber<ResultField> &
12
13
  MappedNumber<NumeratorField> &
13
14
  MappedNumber<DenominatorField>;
14
15
 
@@ -50,7 +51,8 @@ export class DivisionOperator<
50
51
  [this.numeratorField]: numeratorValue as number,
51
52
  [this.denominatorField]: row[this.valueField] as number,
52
53
  [this.resultField]: (numeratorValue as number) / (row[this.valueField] as number),
53
- } as { [P in KeyField]: ValueObject[KeyField] } & MappedNumber<ResultField> &
54
+ } as Record<KeyField, ValueObject[KeyField]> &
55
+ MappedNumber<ResultField> &
54
56
  MappedNumber<NumeratorField> &
55
57
  MappedNumber<DenominatorField>;
56
58
  });
@@ -3,7 +3,7 @@ import { type Operator } from './Operator';
3
3
  import { fetchDetails } from '../lapisApi/lapisApi';
4
4
  import { type LapisFilter } from '../types';
5
5
 
6
- type Details<Fields extends string> = { [field in Fields]: string | number | boolean | null };
6
+ type Details<Fields extends string> = Record<Fields, string | number | boolean | null>;
7
7
 
8
8
  export class FetchDetailsOperator<Fields extends string> implements Operator<Details<Fields>> {
9
9
  constructor(
@@ -4,8 +4,8 @@ import type { Operator } from './Operator';
4
4
  export class RenameFieldOperator<
5
5
  OldFieldName extends string,
6
6
  NewFieldName extends string,
7
- Data extends { [key in OldFieldName]: unknown },
8
- > extends MapOperator<Data, Data & { [key in NewFieldName]: Data[OldFieldName] }> {
7
+ Data extends Record<OldFieldName, unknown>,
8
+ > extends MapOperator<Data, Data & Record<NewFieldName, Data[OldFieldName]>> {
9
9
  constructor(child: Operator<Data>, oldFieldName: OldFieldName, newFieldName: NewFieldName) {
10
10
  super(
11
11
  child,
@@ -13,7 +13,7 @@ export class RenameFieldOperator<
13
13
  ({
14
14
  ...value,
15
15
  [newFieldName]: value[oldFieldName],
16
- }) as Data & { [key in NewFieldName]: Data[OldFieldName] },
16
+ }) as Data & Record<NewFieldName, Data[OldFieldName]>,
17
17
  );
18
18
  }
19
19
  }
@@ -11,7 +11,6 @@ import { ErrorBoundary } from '../components/error-boundary';
11
11
  import { Fullscreen } from '../components/fullscreen';
12
12
  import Info, { InfoComponentCode, InfoHeadline1, InfoParagraph } from '../components/info';
13
13
  import { LoadingDisplay } from '../components/loading-display';
14
- import { NoDataDisplay } from '../components/no-data-display';
15
14
  import { ResizeContainer } from '../components/resize-container';
16
15
  import Tabs from '../components/tabs';
17
16
  import { useQuery } from '../useQuery';
@@ -63,10 +62,6 @@ export const AggregateInner: FunctionComponent<AggregateProps> = (componentProps
63
62
  throw error;
64
63
  }
65
64
 
66
- if (data === null) {
67
- return <NoDataDisplay />;
68
- }
69
-
70
65
  return <AggregatedDataTabs data={data} originalComponentProps={componentProps} />;
71
66
  };
72
67
 
@@ -58,7 +58,6 @@ const AnnotatedMutationWithoutContext: FunctionComponent<AnnotatedMutationWithou
58
58
  <Fragment key={annotation.name}>
59
59
  <InfoHeadline2>{annotation.name}</InfoHeadline2>
60
60
  <InfoParagraph>
61
- {/* eslint-disable-next-line react/no-danger */}
62
61
  <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(annotation.description) }} />
63
62
  </InfoParagraph>
64
63
  </Fragment>
@@ -14,7 +14,7 @@ export default meta;
14
14
 
15
15
  export const Default: StoryObj<ClearableSelectProps> = {
16
16
  render: (args) => (
17
- <div class='flex justify-center px-4 py-16'>
17
+ <div className='flex justify-center px-4 py-16'>
18
18
  <ClearableSelect {...args} />
19
19
  </div>
20
20
  ),
@@ -33,7 +33,7 @@ export const ConfidenceIntervalSelector: FunctionComponent<ConfidenceIntervalSel
33
33
  return (
34
34
  <Select
35
35
  items={items}
36
- selected={confidenceIntervalMethod === undefined ? 'none' : confidenceIntervalMethod}
36
+ selected={confidenceIntervalMethod}
37
37
  onChange={(event: Event) => {
38
38
  const select = event.target as HTMLSelectElement;
39
39
  const value = select.value as ConfidenceIntervalMethod;
@@ -19,7 +19,7 @@ export const ErrorBoundary = <T extends Record<string, unknown>>({
19
19
  schema,
20
20
  children,
21
21
  }: RenderableProps<ErrorBoundaryProps<T>>) => {
22
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- useErrorBoundary unfortunately return `[any, ...]`
22
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- useErrorBoundary unfortunately returns `[any, ...]`
23
23
  const [internalError, resetError] = useErrorBoundary();
24
24
  const componentPropsParseError = useCheckComponentProps(schema, componentProps);
25
25
 
@@ -54,10 +54,6 @@ export const ErrorBoundary = <T extends Record<string, unknown>>({
54
54
 
55
55
  function useCheckComponentProps<T extends Record<string, unknown>>(schema: ZodSchema<T>, componentProps: T) {
56
56
  return useMemo(() => {
57
- if (schema === undefined || componentProps === undefined) {
58
- return undefined;
59
- }
60
-
61
57
  const parseResult = schema.safeParse(componentProps);
62
58
  if (parseResult.success) {
63
59
  return undefined;
@@ -151,7 +151,7 @@ function ZodErrorDetails({ error }: { error: InvalidPropsError }) {
151
151
  </p>
152
152
  )}
153
153
  <p>This is a summary of the unexpected attribute values:</p>
154
- <ul class='m-4 list-outside list-disc '>
154
+ <ul className='m-4 list-outside list-disc '>
155
155
  {error.zodError.issues.map((issue, index) => {
156
156
  const actual =
157
157
  issue.path[0] in error.componentProps
@@ -33,14 +33,11 @@ function findComponentRoot(element: HTMLElement) {
33
33
  }
34
34
 
35
35
  function findShadowRoot(element: HTMLElement) {
36
- let current: Node = element;
37
- while (current) {
36
+ let current: Node | null = element;
37
+ while (current !== null) {
38
38
  if (current instanceof ShadowRoot) {
39
39
  return current;
40
40
  }
41
- if (current.parentNode === null) {
42
- return null;
43
- }
44
41
  current = current.parentNode;
45
42
  }
46
43
  return null;
@@ -15,7 +15,7 @@ const tooltipText = 'This is a tooltip which shows some information.';
15
15
 
16
16
  export const InfoStory: StoryObj = {
17
17
  render: (args) => (
18
- <div class='flex justify-center px-4 py-16'>
18
+ <div className='flex justify-center px-4 py-16'>
19
19
  <Info {...args}>{tooltipText}</Info>
20
20
  </div>
21
21
  ),
@@ -71,7 +71,7 @@ export const MinMaxRangeSlider: FunctionComponent<MinMaxPercentSliderProps> = ({
71
71
  `;
72
72
 
73
73
  return (
74
- <div class='my-4 relative w-full h-full'>
74
+ <div className='my-4 relative w-full h-full'>
75
75
  <input
76
76
  id='fromSlider'
77
77
  type='range'
@@ -60,21 +60,21 @@ export const ProportionSelector: FunctionComponent<ProportionSelectorProps> = ({
60
60
  const indicateError = internalMinProportion > internalMaxProportion;
61
61
 
62
62
  return (
63
- <div class='flex flex-col w-64 mb-2'>
64
- <div class='flex items-center '>
63
+ <div className='flex flex-col w-64 mb-2'>
64
+ <div className='flex items-center '>
65
65
  <PercentInput
66
66
  percentage={internalMinProportion * 100}
67
67
  setPercentage={updateMinPercentage}
68
68
  indicateError={indicateError}
69
69
  />
70
- <div class='m-2'>-</div>
70
+ <div className='m-2'>-</div>
71
71
  <PercentInput
72
72
  percentage={internalMaxProportion * 100}
73
73
  setPercentage={updateMaxPercentage}
74
74
  indicateError={indicateError}
75
75
  />
76
76
  </div>
77
- <div class='my-1'>
77
+ <div className='my-1'>
78
78
  <MinMaxRangeSlider
79
79
  min={internalMinProportion * 100}
80
80
  max={internalMaxProportion * 100}
@@ -10,7 +10,7 @@ export interface SelectProps {
10
10
 
11
11
  export const Select: FunctionComponent<SelectProps> = ({ items, selected, onChange, selectStyle }) => {
12
12
  return (
13
- <select class={`select ${selectStyle} w-fit`} value={selected} onChange={onChange}>
13
+ <select className={`select ${selectStyle} w-fit`} value={selected} onChange={onChange}>
14
14
  {items.map((item) => (
15
15
  <option key={item.value} value={item.value} disabled={item.disabled}>
16
16
  {item.label}
@@ -29,7 +29,7 @@ export interface TableProps {
29
29
  export const Table = ({ data, columns, pageSize }: TableProps) => {
30
30
  const pagination = typeof pageSize === 'number' ? { limit: pageSize } : pageSize;
31
31
 
32
- const wrapper = useRef(null);
32
+ const wrapper = useRef<HTMLDivElement>(null);
33
33
 
34
34
  useEffect(() => {
35
35
  if (wrapper.current === null) {
@@ -40,7 +40,7 @@ const Tabs = forwardRef<HTMLDivElement, ComponentTabsProps>(({ tabs, toolbar },
40
40
  const toolbarElement = typeof toolbar === 'function' ? toolbar(activeTab) : toolbar;
41
41
 
42
42
  return (
43
- <div ref={ref} className='h-full w-full flex flex-col'>
43
+ <div ref={ref} className='h-full w-full flex flex-col bg-white'>
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>}
@@ -24,7 +24,7 @@ const tooltipContent = 'This is some content.';
24
24
 
25
25
  export const TooltipStory: StoryObj<TooltipProps> = {
26
26
  render: (args) => (
27
- <div class='flex justify-center px-4 py-16'>
27
+ <div className='flex justify-center px-4 py-16'>
28
28
  <Tooltip {...args}>
29
29
  <div className='bg-red-200'>Hover me</div>
30
30
  </Tooltip>
@@ -47,7 +47,7 @@ const Tooltip: FunctionComponent<TooltipProps> = ({ children, content, position
47
47
  <div>{children}</div>
48
48
  <div
49
49
  className={`absolute z-10 w-max bg-white p-4 border border-gray-200 rounded-md invisible group-hover:visible ${getPositionCss(position)}`}
50
- style={{ ...tooltipStyle }}
50
+ style={tooltipStyle}
51
51
  >
52
52
  {content}
53
53
  </div>
@@ -72,7 +72,7 @@ const XAxis: FunctionComponent<XAxisProps> = (componentProps) => {
72
72
  return (
73
73
  <div
74
74
  key={idx}
75
- class='absolute text-xs text-black px-1 hover:opacity-80 border-l border-r border-gray-400 border-t'
75
+ className='absolute text-xs text-black px-1 hover:opacity-80 border-l border-r border-gray-400 border-t'
76
76
  style={{
77
77
  left: `calc(${leftPercent}% - 1px)`,
78
78
  width: `calc(${widthPercent}% - 1px)`,
@@ -200,10 +200,10 @@ const CDSPlot: FunctionComponent<CDSProps> = (componentProps) => {
200
200
  };
201
201
 
202
202
  return (
203
- <div ref={ref} class='p-4'>
203
+ <div ref={ref} className='p-4'>
204
204
  <CDSBars gffData={gffData} zoomStart={zoomStart} zoomEnd={zoomEnd} />
205
205
  <XAxis zoomStart={zoomStart} zoomEnd={zoomEnd} fullWidth={width} />
206
- <div class='relative w-full h-5'>
206
+ <div className='relative w-full h-5'>
207
207
  <MinMaxRangeSlider
208
208
  min={zoomStart}
209
209
  max={zoomEnd}
@@ -12,9 +12,7 @@ type Position = {
12
12
  end: number;
13
13
  };
14
14
 
15
- type CDSMap = {
16
- [id: string]: { positions: Position[]; label: string };
17
- };
15
+ type CDSMap = Record<string, { positions: Position[]; label: string }>;
18
16
 
19
17
  export async function loadGff3(gff3Source: string, genomeLength: number | undefined) {
20
18
  try {
@@ -25,9 +23,7 @@ export async function loadGff3(gff3Source: string, genomeLength: number | undefi
25
23
 
26
24
  const response = await fetch(gff3Source);
27
25
  const content = await response.text();
28
- if (!genomeLength) {
29
- genomeLength = loadGenomeLength(content);
30
- }
26
+ genomeLength ??= loadGenomeLength(content);
31
27
  return { features: parseGFF3(content), length: genomeLength };
32
28
  }
33
29
 
@@ -89,7 +85,7 @@ function getCDSMap(lines: string[], genome_type: string, geneMap: CDSMap): CDSMa
89
85
  }
90
86
 
91
87
  const attrPairs = getAttributes(attributes);
92
- const labelAttribute = attrPairs.get('Name') || attrPairs.get('gene') || attrPairs.get('gene_name');
88
+ const labelAttribute = attrPairs.get('Name') ?? attrPairs.get('gene') ?? attrPairs.get('gene_name');
93
89
  if (!labelAttribute) {
94
90
  throw new UserFacingError(
95
91
  'Invalid gff3 source',
@@ -97,11 +93,12 @@ function getCDSMap(lines: string[], genome_type: string, geneMap: CDSMap): CDSMa
97
93
  );
98
94
  }
99
95
  const label = removeQuotes(labelAttribute);
100
- const id = removeQuotes(attrPairs.get('ID') || labelAttribute);
96
+ const id = removeQuotes(attrPairs.get('ID') ?? labelAttribute);
101
97
  const parentAttribute = attrPairs.get('Parent');
102
98
  if (parentAttribute) {
103
99
  const parent = removeQuotes(parentAttribute);
104
100
  if (parent && parent in geneMap) {
101
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
105
102
  delete geneMap[parent];
106
103
  }
107
104
  }
@@ -99,5 +99,5 @@ function filterByInputValue(item: LineageItem, inputValue: string | null) {
99
99
  if (inputValue === null || inputValue === '') {
100
100
  return true;
101
101
  }
102
- return item.lineage?.toLowerCase().includes(inputValue?.toLowerCase() || '');
102
+ return item.lineage.toLowerCase().includes(inputValue.toLowerCase() || '');
103
103
  }