@genspectrum/dashboard-components 0.6.19 → 0.7.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 (26) hide show
  1. package/custom-elements.json +18 -18
  2. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  3. package/dist/dashboard-components.js +96 -99
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +98 -48
  6. package/package.json +1 -3
  7. package/src/index.ts +1 -0
  8. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  9. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  10. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  11. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  12. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  13. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  14. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  15. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
  16. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
  17. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  18. package/src/preact/mutationsOverTime/mutations-over-time.tsx +7 -18
  19. package/src/query/queryMutationsOverTime.ts +3 -5
  20. package/src/utils/map2d.spec.ts +52 -13
  21. package/src/utils/map2d.ts +3 -4
  22. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  23. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  24. package/standalone-bundle/dashboard-components.js +11687 -12463
  25. package/standalone-bundle/dashboard-components.js.map +1 -1
  26. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +0 -1
@@ -99,6 +99,53 @@ export declare class App extends LitElement {
99
99
  createRenderRoot(): this;
100
100
  }
101
101
 
102
+ /**
103
+ * A date range option that can be used in the `gs-date-range-selector` component.
104
+ */
105
+ export declare type DateRangeOption = {
106
+ /** The label of the date range option that will be shown to the user */
107
+ label: string;
108
+ /**
109
+ * The start date of the date range in the format `YYYY-MM-DD`.
110
+ * If not set, the date range selector will default to the `earliestDate` property.
111
+ */
112
+ dateFrom?: string;
113
+ /**
114
+ * The end date of the date range in the format `YYYY-MM-DD`.
115
+ * If not set, the date range selector will default to the current date.
116
+ */
117
+ dateTo?: string;
118
+ };
119
+
120
+ /**
121
+ * Presets for the `gs-date-range-selector` component that can be used as `dateRangeOptions`.
122
+ */
123
+ export declare const dateRangeOptionPresets: {
124
+ last2Weeks: {
125
+ label: string;
126
+ dateFrom: string | undefined;
127
+ };
128
+ lastMonth: {
129
+ label: string;
130
+ dateFrom: string | undefined;
131
+ };
132
+ last2Months: {
133
+ label: string;
134
+ dateFrom: string | undefined;
135
+ };
136
+ last3Months: {
137
+ label: string;
138
+ dateFrom: string | undefined;
139
+ };
140
+ last6Months: {
141
+ label: string;
142
+ dateFrom: string | undefined;
143
+ };
144
+ allTimes: {
145
+ label: string;
146
+ };
147
+ };
148
+
102
149
  /**
103
150
  * ## Context
104
151
  * This component is a group of input fields designed to specify date range filters
@@ -130,15 +177,16 @@ export declare class App extends LitElement {
130
177
  */
131
178
  export declare class DateRangeSelectorComponent extends PreactLitAdapter {
132
179
  /**
133
- * An array of custom options that the select field should provide,
134
- * in addition to the predefined options.
180
+ * An array of date range options that the select field should provide.
135
181
  * The `label` will be shown to the user, and it will be available as `initialValue`.
136
182
  * The dates must be in the format `YYYY-MM-DD`.
183
+ *
184
+ * If dateFrom or dateTo is not set, the component will default to the `earliestDate` or the current date.
137
185
  */
138
- customSelectOptions: {
186
+ dateRangeOptions: {
139
187
  label: string;
140
- dateFrom: string;
141
- dateTo: string;
188
+ dateFrom?: string;
189
+ dateTo?: string;
142
190
  }[];
143
191
  /**
144
192
  * The `dateFrom` value to use in the `allTimes` preset in the format `YYYY-MM-DD`.
@@ -146,13 +194,15 @@ export declare class DateRangeSelectorComponent extends PreactLitAdapter {
146
194
  earliestDate: string;
147
195
  /**
148
196
  * The initial value to use for this date range selector.
149
- * Must be a valid label from the preset labels or a `label` given in the `customSelectOptions`.
197
+ * Must be a valid label from the `dateRangeOptions`.
150
198
  *
151
- * If the value is invalid, the component will default to `'last6Months'`.
199
+ * If the value is not set, the component will default to the range `earliestDate` until today.
152
200
  *
153
201
  * It will be overwritten if `initialDateFrom` or `initialDateTo` is set.
202
+ *
203
+ * We provide some options in `dateRangeOptionPresets` for convenience.
154
204
  */
155
- initialValue: 'custom' | 'allTimes' | 'last2Weeks' | 'lastMonth' | 'last2Months' | 'last3Months' | 'last6Months' | string;
205
+ initialValue: string | undefined;
156
206
  /**
157
207
  * A date string in the format `YYYY-MM-DD`.
158
208
  * If set, the date range selector will be initialized with the given date (overwriting `initialValue` to `custom`).
@@ -989,7 +1039,10 @@ declare global {
989
1039
 
990
1040
  declare global {
991
1041
  interface HTMLElementTagNameMap {
992
- 'gs-mutation-comparison-component': MutationComparisonComponent;
1042
+ 'gs-date-range-selector': DateRangeSelectorComponent;
1043
+ }
1044
+ interface HTMLElementEventMap {
1045
+ 'gs-date-range-changed': CustomEvent<Record<string, string>>;
993
1046
  }
994
1047
  }
995
1048
 
@@ -997,7 +1050,7 @@ declare global {
997
1050
  declare global {
998
1051
  namespace JSX {
999
1052
  interface IntrinsicElements {
1000
- 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1053
+ 'gs-date-range-selector': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1001
1054
  }
1002
1055
  }
1003
1056
  }
@@ -1005,7 +1058,10 @@ declare global {
1005
1058
 
1006
1059
  declare global {
1007
1060
  interface HTMLElementTagNameMap {
1008
- 'gs-mutations-component': MutationsComponent;
1061
+ 'gs-location-filter': LocationFilterComponent;
1062
+ }
1063
+ interface HTMLElementEventMap {
1064
+ 'gs-location-changed': CustomEvent<Record<string, string>>;
1009
1065
  }
1010
1066
  }
1011
1067
 
@@ -1013,7 +1069,7 @@ declare global {
1013
1069
  declare global {
1014
1070
  namespace JSX {
1015
1071
  interface IntrinsicElements {
1016
- 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1072
+ 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1017
1073
  }
1018
1074
  }
1019
1075
  }
@@ -1021,7 +1077,10 @@ declare global {
1021
1077
 
1022
1078
  declare global {
1023
1079
  interface HTMLElementTagNameMap {
1024
- 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
1080
+ 'gs-text-input': TextInputComponent;
1081
+ }
1082
+ interface HTMLElementEventMap {
1083
+ 'gs-text-input-changed': CustomEvent<Record<string, string>>;
1025
1084
  }
1026
1085
  }
1027
1086
 
@@ -1029,7 +1088,7 @@ declare global {
1029
1088
  declare global {
1030
1089
  namespace JSX {
1031
1090
  interface IntrinsicElements {
1032
- 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1091
+ 'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1033
1092
  }
1034
1093
  }
1035
1094
  }
@@ -1037,7 +1096,11 @@ declare global {
1037
1096
 
1038
1097
  declare global {
1039
1098
  interface HTMLElementTagNameMap {
1040
- 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
1099
+ 'gs-mutation-filter': MutationFilterComponent;
1100
+ }
1101
+ interface HTMLElementEventMap {
1102
+ 'gs-mutation-filter-changed': CustomEvent<SelectedMutationFilterStrings>;
1103
+ 'gs-mutation-filter-on-blur': CustomEvent<SelectedMutationFilterStrings>;
1041
1104
  }
1042
1105
  }
1043
1106
 
@@ -1045,7 +1108,7 @@ declare global {
1045
1108
  declare global {
1046
1109
  namespace JSX {
1047
1110
  interface IntrinsicElements {
1048
- 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1111
+ 'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1049
1112
  }
1050
1113
  }
1051
1114
  }
@@ -1053,7 +1116,10 @@ declare global {
1053
1116
 
1054
1117
  declare global {
1055
1118
  interface HTMLElementTagNameMap {
1056
- 'gs-aggregate-component': AggregateComponent;
1119
+ 'gs-lineage-filter': LineageFilterComponent;
1120
+ }
1121
+ interface HTMLElementEventMap {
1122
+ 'gs-lineage-filter-changed': CustomEvent<Record<string, string>>;
1057
1123
  }
1058
1124
  }
1059
1125
 
@@ -1061,7 +1127,7 @@ declare global {
1061
1127
  declare global {
1062
1128
  namespace JSX {
1063
1129
  interface IntrinsicElements {
1064
- 'gs-aggregate-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1130
+ 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1065
1131
  }
1066
1132
  }
1067
1133
  }
@@ -1069,7 +1135,7 @@ declare global {
1069
1135
 
1070
1136
  declare global {
1071
1137
  interface HTMLElementTagNameMap {
1072
- 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1138
+ 'gs-mutation-comparison-component': MutationComparisonComponent;
1073
1139
  }
1074
1140
  }
1075
1141
 
@@ -1077,7 +1143,7 @@ declare global {
1077
1143
  declare global {
1078
1144
  namespace JSX {
1079
1145
  interface IntrinsicElements {
1080
- 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1146
+ 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1081
1147
  }
1082
1148
  }
1083
1149
  }
@@ -1085,7 +1151,7 @@ declare global {
1085
1151
 
1086
1152
  declare global {
1087
1153
  interface HTMLElementTagNameMap {
1088
- 'gs-mutations-over-time': MutationsOverTimeComponent;
1154
+ 'gs-mutations-component': MutationsComponent;
1089
1155
  }
1090
1156
  }
1091
1157
 
@@ -1093,7 +1159,7 @@ declare global {
1093
1159
  declare global {
1094
1160
  namespace JSX {
1095
1161
  interface IntrinsicElements {
1096
- 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1162
+ 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1097
1163
  }
1098
1164
  }
1099
1165
  }
@@ -1101,10 +1167,7 @@ declare global {
1101
1167
 
1102
1168
  declare global {
1103
1169
  interface HTMLElementTagNameMap {
1104
- 'gs-date-range-selector': DateRangeSelectorComponent;
1105
- }
1106
- interface HTMLElementEventMap {
1107
- 'gs-date-range-changed': CustomEvent<Record<string, string>>;
1170
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
1108
1171
  }
1109
1172
  }
1110
1173
 
@@ -1112,7 +1175,7 @@ declare global {
1112
1175
  declare global {
1113
1176
  namespace JSX {
1114
1177
  interface IntrinsicElements {
1115
- 'gs-date-range-selector': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1178
+ 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1116
1179
  }
1117
1180
  }
1118
1181
  }
@@ -1120,10 +1183,7 @@ declare global {
1120
1183
 
1121
1184
  declare global {
1122
1185
  interface HTMLElementTagNameMap {
1123
- 'gs-location-filter': LocationFilterComponent;
1124
- }
1125
- interface HTMLElementEventMap {
1126
- 'gs-location-changed': CustomEvent<Record<string, string>>;
1186
+ 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
1127
1187
  }
1128
1188
  }
1129
1189
 
@@ -1131,7 +1191,7 @@ declare global {
1131
1191
  declare global {
1132
1192
  namespace JSX {
1133
1193
  interface IntrinsicElements {
1134
- 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1194
+ 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1135
1195
  }
1136
1196
  }
1137
1197
  }
@@ -1139,10 +1199,7 @@ declare global {
1139
1199
 
1140
1200
  declare global {
1141
1201
  interface HTMLElementTagNameMap {
1142
- 'gs-text-input': TextInputComponent;
1143
- }
1144
- interface HTMLElementEventMap {
1145
- 'gs-text-input-changed': CustomEvent<Record<string, string>>;
1202
+ 'gs-aggregate-component': AggregateComponent;
1146
1203
  }
1147
1204
  }
1148
1205
 
@@ -1150,7 +1207,7 @@ declare global {
1150
1207
  declare global {
1151
1208
  namespace JSX {
1152
1209
  interface IntrinsicElements {
1153
- 'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1210
+ 'gs-aggregate-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1154
1211
  }
1155
1212
  }
1156
1213
  }
@@ -1158,10 +1215,7 @@ declare global {
1158
1215
 
1159
1216
  declare global {
1160
1217
  interface HTMLElementTagNameMap {
1161
- 'gs-lineage-filter': LineageFilterComponent;
1162
- }
1163
- interface HTMLElementEventMap {
1164
- 'gs-lineage-filter-changed': CustomEvent<Record<string, string>>;
1218
+ 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1165
1219
  }
1166
1220
  }
1167
1221
 
@@ -1169,7 +1223,7 @@ declare global {
1169
1223
  declare global {
1170
1224
  namespace JSX {
1171
1225
  interface IntrinsicElements {
1172
- 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1226
+ 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1173
1227
  }
1174
1228
  }
1175
1229
  }
@@ -1177,11 +1231,7 @@ declare global {
1177
1231
 
1178
1232
  declare global {
1179
1233
  interface HTMLElementTagNameMap {
1180
- 'gs-mutation-filter': MutationFilterComponent;
1181
- }
1182
- interface HTMLElementEventMap {
1183
- 'gs-mutation-filter-changed': CustomEvent<SelectedMutationFilterStrings>;
1184
- 'gs-mutation-filter-on-blur': CustomEvent<SelectedMutationFilterStrings>;
1234
+ 'gs-mutations-over-time': MutationsOverTimeComponent;
1185
1235
  }
1186
1236
  }
1187
1237
 
@@ -1189,7 +1239,7 @@ declare global {
1189
1239
  declare global {
1190
1240
  namespace JSX {
1191
1241
  interface IntrinsicElements {
1192
- 'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1242
+ 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1193
1243
  }
1194
1244
  }
1195
1245
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.6.19",
3
+ "version": "0.7.0",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -80,7 +80,6 @@
80
80
  "flatpickr": "^4.6.13",
81
81
  "gridjs": "^6.2.0",
82
82
  "lit": "^3.1.3",
83
- "object-hash": "^3.0.0",
84
83
  "preact": "^10.20.1",
85
84
  "zod": "^3.23.0"
86
85
  },
@@ -103,7 +102,6 @@
103
102
  "@storybook/web-components": "^8.0.9",
104
103
  "@storybook/web-components-vite": "^8.0.9",
105
104
  "@types/node": "^22.0.0",
106
- "@types/object-hash": "^3.0.6",
107
105
  "@typescript-eslint/eslint-plugin": "^8.2.0",
108
106
  "@typescript-eslint/parser": "^8.2.0",
109
107
  "autoprefixer": "^10.4.19",
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './web-components';
2
2
 
3
3
  export { type ErrorEvent, UserFacingError } from './preact/components/error-display';
4
+ export { type DateRangeOption, dateRangeOptionPresets } from './preact/dateRangeSelector/dateRangeOption';
4
5
 
5
6
  declare global {
6
7
  interface HTMLElementEventMap {
@@ -1,48 +1,75 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
3
  import { computeInitialValues } from './computeInitialValues';
4
- import { PRESET_VALUE_CUSTOM, PRESET_VALUE_LAST_3_MONTHS, PRESET_VALUE_LAST_6_MONTHS } from './selectableOptions';
5
4
 
6
5
  const today = new Date();
7
6
  const earliestDate = '1900-01-01';
8
7
 
8
+ const fromOption = 'fromOption';
9
+ const toOption = 'toOption';
10
+ const fromToOption = 'fromToOption';
11
+ const dateFromOptionValue = '2010-06-30';
12
+ const dateToOptionValue = '2020-01-01';
13
+
14
+ const dateRangeOptions = [
15
+ { label: fromOption, dateFrom: dateFromOptionValue },
16
+ { label: toOption, dateTo: dateToOptionValue },
17
+ { label: fromToOption, dateFrom: dateFromOptionValue, dateTo: dateToOptionValue },
18
+ ];
19
+
9
20
  describe('computeInitialValues', () => {
10
21
  it('should compute for initial value if initial "from" and "to" are unset', () => {
11
- const result = computeInitialValues(PRESET_VALUE_LAST_3_MONTHS, undefined, undefined, earliestDate, []);
22
+ const result = computeInitialValues(fromToOption, undefined, undefined, earliestDate, dateRangeOptions);
12
23
 
13
- const expectedFrom = new Date();
14
- expectedFrom.setMonth(today.getMonth() - 3);
24
+ expect(result.initialSelectedDateRange).toEqual(fromToOption);
25
+ expectDateMatches(result.initialSelectedDateFrom, new Date(dateFromOptionValue));
26
+ expectDateMatches(result.initialSelectedDateTo, new Date(dateToOptionValue));
27
+ });
15
28
 
16
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_LAST_3_MONTHS);
17
- expectDateMatches(result.initialSelectedDateFrom, expectedFrom);
29
+ it('should use today as "dateTo" if it is unset in selected option', () => {
30
+ const result = computeInitialValues(fromOption, undefined, undefined, earliestDate, dateRangeOptions);
31
+
32
+ expect(result.initialSelectedDateRange).toEqual(fromOption);
33
+ expectDateMatches(result.initialSelectedDateFrom, new Date(dateFromOptionValue));
18
34
  expectDateMatches(result.initialSelectedDateTo, today);
19
35
  });
20
36
 
21
- it('should fall back to default when initial value is unknown', () => {
22
- const result = computeInitialValues('not a known value', undefined, undefined, earliestDate, []);
37
+ it('should use earliest date as "dateFrom" if it is unset in selected option', () => {
38
+ const result = computeInitialValues(toOption, undefined, undefined, earliestDate, dateRangeOptions);
23
39
 
24
- const expectedFrom = new Date();
25
- expectedFrom.setMonth(today.getMonth() - 6);
40
+ expect(result.initialSelectedDateRange).toEqual(toOption);
41
+ expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
42
+ expectDateMatches(result.initialSelectedDateTo, new Date(dateToOptionValue));
43
+ });
26
44
 
27
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_LAST_6_MONTHS);
28
- expectDateMatches(result.initialSelectedDateFrom, expectedFrom);
45
+ it('should fall back to full range if initial value is not set', () => {
46
+ const result = computeInitialValues(undefined, undefined, undefined, earliestDate, dateRangeOptions);
47
+
48
+ expect(result.initialSelectedDateRange).toBeUndefined();
49
+ expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
29
50
  expectDateMatches(result.initialSelectedDateTo, today);
30
51
  });
31
52
 
53
+ it('should fall back to default when initial value is unknown', () => {
54
+ expect(() => computeInitialValues('not a known value', undefined, undefined, earliestDate, [])).toThrowError(
55
+ /Invalid initialValue "not a known value", It must be one of/,
56
+ );
57
+ });
58
+
32
59
  it('should overwrite initial value if initial "from" is set', () => {
33
60
  const initialDateFrom = '2020-01-01';
34
- const result = computeInitialValues(PRESET_VALUE_LAST_3_MONTHS, initialDateFrom, undefined, earliestDate, []);
61
+ const result = computeInitialValues(fromOption, initialDateFrom, undefined, earliestDate, dateRangeOptions);
35
62
 
36
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_CUSTOM);
63
+ expect(result.initialSelectedDateRange).toBeUndefined();
37
64
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
38
65
  expectDateMatches(result.initialSelectedDateTo, today);
39
66
  });
40
67
 
41
68
  it('should overwrite initial value if initial "to" is set', () => {
42
69
  const initialDateTo = '2020-01-01';
43
- const result = computeInitialValues(PRESET_VALUE_LAST_3_MONTHS, undefined, initialDateTo, earliestDate, []);
70
+ const result = computeInitialValues(fromOption, undefined, initialDateTo, earliestDate, dateRangeOptions);
44
71
 
45
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_CUSTOM);
72
+ expect(result.initialSelectedDateRange).toBeUndefined();
46
73
  expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
47
74
  expectDateMatches(result.initialSelectedDateTo, new Date(initialDateTo));
48
75
  });
@@ -50,15 +77,9 @@ describe('computeInitialValues', () => {
50
77
  it('should overwrite initial value if initial "to" and "from" are set', () => {
51
78
  const initialDateFrom = '2020-01-01';
52
79
  const initialDateTo = '2022-01-01';
53
- const result = computeInitialValues(
54
- PRESET_VALUE_LAST_3_MONTHS,
55
- initialDateFrom,
56
- initialDateTo,
57
- earliestDate,
58
- [],
59
- );
80
+ const result = computeInitialValues(fromOption, initialDateFrom, initialDateTo, earliestDate, dateRangeOptions);
60
81
 
61
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_CUSTOM);
82
+ expect(result.initialSelectedDateRange).toBeUndefined();
62
83
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
63
84
  expectDateMatches(result.initialSelectedDateTo, new Date(initialDateTo));
64
85
  });
@@ -66,29 +87,23 @@ describe('computeInitialValues', () => {
66
87
  it('should set initial "to" to "from" if "from" is after "to"', () => {
67
88
  const initialDateFrom = '2020-01-01';
68
89
  const initialDateTo = '1900-01-01';
69
- const result = computeInitialValues(
70
- PRESET_VALUE_LAST_3_MONTHS,
71
- initialDateFrom,
72
- initialDateTo,
73
- earliestDate,
74
- [],
75
- );
90
+ const result = computeInitialValues(undefined, initialDateFrom, initialDateTo, earliestDate, dateRangeOptions);
76
91
 
77
- expect(result.initialSelectedDateRange).toEqual(PRESET_VALUE_CUSTOM);
92
+ expect(result.initialSelectedDateRange).toBeUndefined();
78
93
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
79
94
  expectDateMatches(result.initialSelectedDateTo, new Date(initialDateFrom));
80
95
  });
81
96
 
82
97
  it('should throw if initial "from" is not a valid date', () => {
83
- expect(() =>
84
- computeInitialValues(PRESET_VALUE_LAST_3_MONTHS, 'not a date', undefined, earliestDate, []),
85
- ).toThrowError('Invalid initialDateFrom');
98
+ expect(() => computeInitialValues(undefined, 'not a date', undefined, earliestDate, [])).toThrowError(
99
+ 'Invalid initialDateFrom',
100
+ );
86
101
  });
87
102
 
88
103
  it('should throw if initial "to" is not a valid date', () => {
89
- expect(() =>
90
- computeInitialValues(PRESET_VALUE_LAST_3_MONTHS, undefined, 'not a date', earliestDate, []),
91
- ).toThrowError('Invalid initialDateTo');
104
+ expect(() => computeInitialValues(undefined, undefined, 'not a date', earliestDate, [])).toThrowError(
105
+ 'Invalid initialDateTo',
106
+ );
92
107
  });
93
108
 
94
109
  function expectDateMatches(actual: Date, expected: Date) {
@@ -1,36 +1,30 @@
1
- import {
2
- type CustomSelectOption,
3
- getDatesForSelectorValue,
4
- getSelectableOptions,
5
- PRESET_VALUE_CUSTOM,
6
- PRESET_VALUE_LAST_6_MONTHS,
7
- type PresetOptionValues,
8
- } from './selectableOptions';
1
+ import { type DateRangeOption } from './dateRangeOption';
2
+ import { getDatesForSelectorValue, getSelectableOptions } from './selectableOptions';
9
3
  import { UserFacingError } from '../components/error-display';
10
4
 
11
- export function computeInitialValues<CustomLabel extends string>(
12
- initialValue: PresetOptionValues | CustomLabel | undefined,
5
+ export function computeInitialValues(
6
+ initialValue: string | undefined,
13
7
  initialDateFrom: string | undefined,
14
8
  initialDateTo: string | undefined,
15
9
  earliestDate: string,
16
- customSelectOptions: CustomSelectOption<CustomLabel>[],
10
+ dateRangeOptions: DateRangeOption[],
17
11
  ): {
18
- initialSelectedDateRange: CustomLabel | PresetOptionValues;
12
+ initialSelectedDateRange: string | undefined;
19
13
  initialSelectedDateFrom: Date;
20
14
  initialSelectedDateTo: Date;
21
15
  } {
22
16
  if (isUndefinedOrEmpty(initialDateFrom) && isUndefinedOrEmpty(initialDateTo)) {
23
- const selectableOptions = getSelectableOptions(customSelectOptions);
24
- const initialSelectedDateRange =
25
- initialValue !== undefined && selectableOptions.some((option) => option.value === initialValue)
26
- ? initialValue
27
- : PRESET_VALUE_LAST_6_MONTHS;
17
+ const selectableOptions = getSelectableOptions(dateRangeOptions);
18
+ const initialSelectedDateRange = selectableOptions.find((option) => option.value === initialValue)?.value;
28
19
 
29
- const { dateFrom, dateTo } = getDatesForSelectorValue(
30
- initialSelectedDateRange,
31
- customSelectOptions,
32
- earliestDate,
33
- );
20
+ if (initialValue !== undefined && initialSelectedDateRange === undefined) {
21
+ throw new UserFacingError(
22
+ 'Invalid initialValue',
23
+ `Invalid initialValue "${initialValue}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(', ')}`,
24
+ );
25
+ }
26
+
27
+ const { dateFrom, dateTo } = getDatesForSelectorValue(initialSelectedDateRange, dateRangeOptions, earliestDate);
34
28
 
35
29
  return {
36
30
  initialSelectedDateRange,
@@ -62,7 +56,7 @@ export function computeInitialValues<CustomLabel extends string>(
62
56
  }
63
57
 
64
58
  return {
65
- initialSelectedDateRange: PRESET_VALUE_CUSTOM,
59
+ initialSelectedDateRange: undefined,
66
60
  initialSelectedDateFrom,
67
61
  initialSelectedDateTo,
68
62
  };