@genspectrum/dashboard-components 0.13.7 → 0.14.1

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 (50) hide show
  1. package/custom-elements.json +13 -51
  2. package/dist/{LineageFilterChangedEvent-GedKNGFI.js → LineageFilterChangedEvent-C9dXOxt6.js} +11 -3
  3. package/dist/LineageFilterChangedEvent-C9dXOxt6.js.map +1 -0
  4. package/dist/components.d.ts +61 -67
  5. package/dist/components.js +95 -84
  6. package/dist/components.js.map +1 -1
  7. package/dist/util.d.ts +60 -50
  8. package/dist/util.js +1 -1
  9. package/package.json +1 -1
  10. package/src/preact/LapisUrlContext.ts +14 -1
  11. package/src/preact/aggregatedData/aggregate.stories.tsx +3 -3
  12. package/src/preact/aggregatedData/aggregate.tsx +3 -4
  13. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +34 -20
  14. package/src/preact/dateRangeSelector/computeInitialValues.ts +25 -21
  15. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +104 -40
  16. package/src/preact/dateRangeSelector/date-range-selector.tsx +29 -20
  17. package/src/preact/dateRangeSelector/dateRangeOption.ts +11 -1
  18. package/src/preact/lineageFilter/lineage-filter.stories.tsx +3 -3
  19. package/src/preact/lineageFilter/lineage-filter.tsx +3 -4
  20. package/src/preact/locationFilter/location-filter.stories.tsx +3 -3
  21. package/src/preact/locationFilter/location-filter.tsx +4 -4
  22. package/src/preact/map/sequences-by-location.stories.tsx +3 -3
  23. package/src/preact/map/sequences-by-location.tsx +3 -4
  24. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -3
  25. package/src/preact/mutationComparison/mutation-comparison.tsx +4 -4
  26. package/src/preact/mutationFilter/mutation-filter-info.tsx +3 -3
  27. package/src/preact/mutationFilter/mutation-filter.stories.tsx +5 -5
  28. package/src/preact/mutations/mutations.stories.tsx +3 -3
  29. package/src/preact/mutations/mutations.tsx +4 -4
  30. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +3 -3
  31. package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -4
  32. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -3
  33. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
  34. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +3 -3
  35. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -4
  36. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +3 -3
  37. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -4
  38. package/src/preact/statistic/statistics.stories.tsx +3 -3
  39. package/src/preact/statistic/statistics.tsx +2 -3
  40. package/src/preact/textInput/text-input.stories.tsx +3 -3
  41. package/src/preact/textInput/text-input.tsx +3 -4
  42. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +3 -3
  43. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -4
  44. package/src/web-components/PreactLitAdapter.tsx +3 -3
  45. package/src/web-components/gs-app.ts +3 -1
  46. package/src/web-components/input/gs-date-range-selector.stories.ts +5 -12
  47. package/src/web-components/input/gs-date-range-selector.tsx +15 -38
  48. package/standalone-bundle/dashboard-components.js +6078 -6072
  49. package/standalone-bundle/dashboard-components.js.map +1 -1
  50. package/dist/LineageFilterChangedEvent-GedKNGFI.js.map +0 -1
package/dist/util.d.ts CHANGED
@@ -136,10 +136,20 @@ declare const dateRangeOptionSchema: default_2.ZodObject<{
136
136
  dateTo?: string | undefined;
137
137
  }>;
138
138
 
139
- export declare type DateRangeSelectOption = string | {
140
- dateFrom: string;
141
- dateTo: string;
142
- };
139
+ export declare type DateRangeSelectOption = Required<DateRangeValue>;
140
+
141
+ declare type DateRangeValue = default_2.infer<typeof dateRangeValueSchema>;
142
+
143
+ declare const dateRangeValueSchema: default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
144
+ dateFrom: default_2.ZodOptional<default_2.ZodString>;
145
+ dateTo: default_2.ZodOptional<default_2.ZodString>;
146
+ }, "strip", default_2.ZodTypeAny, {
147
+ dateFrom?: string | undefined;
148
+ dateTo?: string | undefined;
149
+ }, {
150
+ dateFrom?: string | undefined;
151
+ dateTo?: string | undefined;
152
+ }>]>;
143
153
 
144
154
  export declare type LapisFilter = default_2.infer<typeof lapisFilterSchema>;
145
155
 
@@ -838,7 +848,11 @@ declare global {
838
848
 
839
849
  declare global {
840
850
  interface HTMLElementTagNameMap {
841
- 'gs-mutation-comparison-component': MutationComparisonComponent;
851
+ 'gs-date-range-selector': DateRangeSelectorComponent;
852
+ }
853
+ interface HTMLElementEventMap {
854
+ 'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
855
+ 'gs-date-range-option-changed': DateRangeOptionChangedEvent;
842
856
  }
843
857
  }
844
858
 
@@ -846,7 +860,7 @@ declare global {
846
860
  declare global {
847
861
  namespace JSX {
848
862
  interface IntrinsicElements {
849
- 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
863
+ 'gs-date-range-selector': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
850
864
  }
851
865
  }
852
866
  }
@@ -854,7 +868,10 @@ declare global {
854
868
 
855
869
  declare global {
856
870
  interface HTMLElementTagNameMap {
857
- 'gs-mutations-component': MutationsComponent;
871
+ 'gs-text-input': TextInputComponent;
872
+ }
873
+ interface HTMLElementEventMap {
874
+ 'gs-text-input-changed': TextInputChangedEvent;
858
875
  }
859
876
  }
860
877
 
@@ -862,7 +879,7 @@ declare global {
862
879
  declare global {
863
880
  namespace JSX {
864
881
  interface IntrinsicElements {
865
- 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
882
+ 'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
866
883
  }
867
884
  }
868
885
  }
@@ -870,7 +887,10 @@ declare global {
870
887
 
871
888
  declare global {
872
889
  interface HTMLElementTagNameMap {
873
- 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
890
+ 'gs-location-filter': LocationFilterComponent;
891
+ }
892
+ interface HTMLElementEventMap {
893
+ 'gs-location-changed': LocationChangedEvent;
874
894
  }
875
895
  }
876
896
 
@@ -878,7 +898,7 @@ declare global {
878
898
  declare global {
879
899
  namespace JSX {
880
900
  interface IntrinsicElements {
881
- 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
901
+ 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
882
902
  }
883
903
  }
884
904
  }
@@ -886,7 +906,10 @@ declare global {
886
906
 
887
907
  declare global {
888
908
  interface HTMLElementTagNameMap {
889
- 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
909
+ 'gs-lineage-filter': LineageFilterComponent;
910
+ }
911
+ interface HTMLElementEventMap {
912
+ 'gs-lineage-filter-changed': LineageFilterChangedEvent;
890
913
  }
891
914
  }
892
915
 
@@ -894,7 +917,7 @@ declare global {
894
917
  declare global {
895
918
  namespace JSX {
896
919
  interface IntrinsicElements {
897
- 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
920
+ 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
898
921
  }
899
922
  }
900
923
  }
@@ -902,7 +925,10 @@ declare global {
902
925
 
903
926
  declare global {
904
927
  interface HTMLElementTagNameMap {
905
- 'gs-aggregate': AggregateComponent;
928
+ 'gs-mutation-filter': MutationFilterComponent;
929
+ }
930
+ interface HTMLElementEventMap {
931
+ 'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
906
932
  }
907
933
  }
908
934
 
@@ -910,7 +936,7 @@ declare global {
910
936
  declare global {
911
937
  namespace JSX {
912
938
  interface IntrinsicElements {
913
- 'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
939
+ 'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
914
940
  }
915
941
  }
916
942
  }
@@ -918,7 +944,7 @@ declare global {
918
944
 
919
945
  declare global {
920
946
  interface HTMLElementTagNameMap {
921
- 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
947
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
922
948
  }
923
949
  }
924
950
 
@@ -926,7 +952,7 @@ declare global {
926
952
  declare global {
927
953
  namespace JSX {
928
954
  interface IntrinsicElements {
929
- 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
955
+ 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
930
956
  }
931
957
  }
932
958
  }
@@ -934,7 +960,7 @@ declare global {
934
960
 
935
961
  declare global {
936
962
  interface HTMLElementTagNameMap {
937
- 'gs-mutations-over-time': MutationsOverTimeComponent;
963
+ 'gs-mutation-comparison-component': MutationComparisonComponent;
938
964
  }
939
965
  }
940
966
 
@@ -942,7 +968,7 @@ declare global {
942
968
  declare global {
943
969
  namespace JSX {
944
970
  interface IntrinsicElements {
945
- 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
971
+ 'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
946
972
  }
947
973
  }
948
974
  }
@@ -950,7 +976,7 @@ declare global {
950
976
 
951
977
  declare global {
952
978
  interface HTMLElementTagNameMap {
953
- 'gs-statistics': StatisticsComponent;
979
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
954
980
  }
955
981
  }
956
982
 
@@ -958,7 +984,7 @@ declare global {
958
984
  declare global {
959
985
  namespace JSX {
960
986
  interface IntrinsicElements {
961
- 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
987
+ 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
962
988
  }
963
989
  }
964
990
  }
@@ -966,7 +992,7 @@ declare global {
966
992
 
967
993
  declare global {
968
994
  interface HTMLElementTagNameMap {
969
- 'gs-sequences-by-location': SequencesByLocationComponent;
995
+ 'gs-mutations-component': MutationsComponent;
970
996
  }
971
997
  }
972
998
 
@@ -974,7 +1000,7 @@ declare global {
974
1000
  declare global {
975
1001
  namespace JSX {
976
1002
  interface IntrinsicElements {
977
- 'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1003
+ 'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
978
1004
  }
979
1005
  }
980
1006
  }
@@ -982,7 +1008,7 @@ declare global {
982
1008
 
983
1009
  declare global {
984
1010
  interface HTMLElementTagNameMap {
985
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1011
+ 'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
986
1012
  }
987
1013
  }
988
1014
 
@@ -990,7 +1016,7 @@ declare global {
990
1016
  declare global {
991
1017
  namespace JSX {
992
1018
  interface IntrinsicElements {
993
- 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1019
+ 'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
994
1020
  }
995
1021
  }
996
1022
  }
@@ -998,11 +1024,7 @@ declare global {
998
1024
 
999
1025
  declare global {
1000
1026
  interface HTMLElementTagNameMap {
1001
- 'gs-date-range-selector': DateRangeSelectorComponent;
1002
- }
1003
- interface HTMLElementEventMap {
1004
- 'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
1005
- 'gs-date-range-option-changed': DateRangeOptionChangedEvent;
1027
+ 'gs-aggregate': AggregateComponent;
1006
1028
  }
1007
1029
  }
1008
1030
 
@@ -1010,7 +1032,7 @@ declare global {
1010
1032
  declare global {
1011
1033
  namespace JSX {
1012
1034
  interface IntrinsicElements {
1013
- 'gs-date-range-selector': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1035
+ 'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1014
1036
  }
1015
1037
  }
1016
1038
  }
@@ -1018,10 +1040,7 @@ declare global {
1018
1040
 
1019
1041
  declare global {
1020
1042
  interface HTMLElementTagNameMap {
1021
- 'gs-location-filter': LocationFilterComponent;
1022
- }
1023
- interface HTMLElementEventMap {
1024
- 'gs-location-changed': LocationChangedEvent;
1043
+ 'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
1025
1044
  }
1026
1045
  }
1027
1046
 
@@ -1029,7 +1048,7 @@ declare global {
1029
1048
  declare global {
1030
1049
  namespace JSX {
1031
1050
  interface IntrinsicElements {
1032
- 'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1051
+ 'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1033
1052
  }
1034
1053
  }
1035
1054
  }
@@ -1037,10 +1056,7 @@ declare global {
1037
1056
 
1038
1057
  declare global {
1039
1058
  interface HTMLElementTagNameMap {
1040
- 'gs-mutation-filter': MutationFilterComponent;
1041
- }
1042
- interface HTMLElementEventMap {
1043
- 'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
1059
+ 'gs-mutations-over-time': MutationsOverTimeComponent;
1044
1060
  }
1045
1061
  }
1046
1062
 
@@ -1048,7 +1064,7 @@ declare global {
1048
1064
  declare global {
1049
1065
  namespace JSX {
1050
1066
  interface IntrinsicElements {
1051
- 'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1067
+ 'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1052
1068
  }
1053
1069
  }
1054
1070
  }
@@ -1056,10 +1072,7 @@ declare global {
1056
1072
 
1057
1073
  declare global {
1058
1074
  interface HTMLElementTagNameMap {
1059
- 'gs-text-input': TextInputComponent;
1060
- }
1061
- interface HTMLElementEventMap {
1062
- 'gs-text-input-changed': TextInputChangedEvent;
1075
+ 'gs-sequences-by-location': SequencesByLocationComponent;
1063
1076
  }
1064
1077
  }
1065
1078
 
@@ -1067,7 +1080,7 @@ declare global {
1067
1080
  declare global {
1068
1081
  namespace JSX {
1069
1082
  interface IntrinsicElements {
1070
- 'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1083
+ 'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1071
1084
  }
1072
1085
  }
1073
1086
  }
@@ -1075,10 +1088,7 @@ declare global {
1075
1088
 
1076
1089
  declare global {
1077
1090
  interface HTMLElementTagNameMap {
1078
- 'gs-lineage-filter': LineageFilterComponent;
1079
- }
1080
- interface HTMLElementEventMap {
1081
- 'gs-lineage-filter-changed': LineageFilterChangedEvent;
1091
+ 'gs-statistics': StatisticsComponent;
1082
1092
  }
1083
1093
  }
1084
1094
 
@@ -1086,7 +1096,7 @@ declare global {
1086
1096
  declare global {
1087
1097
  namespace JSX {
1088
1098
  interface IntrinsicElements {
1089
- 'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1099
+ 'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1090
1100
  }
1091
1101
  }
1092
1102
  }
package/dist/util.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, a, L, T, d, v } from "./LineageFilterChangedEvent-GedKNGFI.js";
1
+ import { D, a, L, T, d, v } from "./LineageFilterChangedEvent-C9dXOxt6.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.13.7",
3
+ "version": "0.14.1",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -1,3 +1,16 @@
1
1
  import { createContext } from 'preact';
2
+ import { useContext } from 'preact/hooks';
2
3
 
3
- export const LapisUrlContext = createContext('');
4
+ const LapisUrlContext = createContext('');
5
+
6
+ export const LapisUrlContextProvider = LapisUrlContext.Provider;
7
+
8
+ export const useLapisUrl = () => {
9
+ const lapisUrl = useContext(LapisUrlContext);
10
+
11
+ if (lapisUrl.endsWith('/')) {
12
+ return lapisUrl.slice(0, -1);
13
+ }
14
+
15
+ return lapisUrl;
16
+ };
@@ -4,7 +4,7 @@ import { expect, waitFor, within } from '@storybook/test';
4
4
  import aggregatedData from './__mockData__/aggregated.json';
5
5
  import { Aggregate, type AggregateProps } from './aggregate';
6
6
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
7
- import { LapisUrlContext } from '../LapisUrlContext';
7
+ import { LapisUrlContextProvider } from '../LapisUrlContext';
8
8
  import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
9
9
 
10
10
  const meta: Meta<AggregateProps> = {
@@ -44,9 +44,9 @@ export default meta;
44
44
 
45
45
  export const Default: StoryObj<AggregateProps> = {
46
46
  render: (args) => (
47
- <LapisUrlContext.Provider value={LAPIS_URL}>
47
+ <LapisUrlContextProvider value={LAPIS_URL}>
48
48
  <Aggregate {...args} />
49
- </LapisUrlContext.Provider>
49
+ </LapisUrlContextProvider>
50
50
  ),
51
51
  args: {
52
52
  fields: ['division', 'host'],
@@ -1,11 +1,10 @@
1
1
  import { type FunctionComponent } from 'preact';
2
- import { useContext } from 'preact/hooks';
3
2
  import z from 'zod';
4
3
 
4
+ 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 { LapisUrlContext } from '../LapisUrlContext';
9
8
  import { CsvDownloadButton } from '../components/csv-download-button';
10
9
  import { ErrorBoundary } from '../components/error-boundary';
11
10
  import { Fullscreen } from '../components/fullscreen';
@@ -48,7 +47,7 @@ export const Aggregate: FunctionComponent<AggregateProps> = (componentProps) =>
48
47
 
49
48
  export const AggregateInner: FunctionComponent<AggregateProps> = (componentProps) => {
50
49
  const { fields, lapisFilter, initialSortField, initialSortDirection } = componentProps;
51
- const lapis = useContext(LapisUrlContext);
50
+ const lapis = useLapisUrl();
52
51
 
53
52
  const { data, error, isLoading } = useQuery(async () => {
54
53
  return queryAggregateData(lapisFilter, fields, lapis);
@@ -129,7 +128,7 @@ type AggregateInfoProps = {
129
128
  };
130
129
 
131
130
  const AggregateInfo: FunctionComponent<AggregateInfoProps> = ({ originalComponentProps }) => {
132
- const lapis = useContext(LapisUrlContext);
131
+ const lapis = useLapisUrl();
133
132
  return (
134
133
  <Info>
135
134
  <InfoHeadline1>Aggregated data</InfoHeadline1>
@@ -18,8 +18,8 @@ const dateRangeOptions = [
18
18
  ];
19
19
 
20
20
  describe('computeInitialValues', () => {
21
- it('should compute for initial value if initial "from" and "to" are unset', () => {
22
- const result = computeInitialValues(fromToOption, undefined, undefined, earliestDate, dateRangeOptions);
21
+ it('should compute initial value if value is dateRangeOption label', () => {
22
+ const result = computeInitialValues(fromToOption, earliestDate, dateRangeOptions);
23
23
 
24
24
  expect(result.initialSelectedDateRange).toEqual(fromToOption);
25
25
  expectDateMatches(result.initialSelectedDateFrom, new Date(dateFromOptionValue));
@@ -27,7 +27,7 @@ describe('computeInitialValues', () => {
27
27
  });
28
28
 
29
29
  it('should use today as "dateTo" if it is unset in selected option', () => {
30
- const result = computeInitialValues(fromOption, undefined, undefined, earliestDate, dateRangeOptions);
30
+ const result = computeInitialValues(fromOption, earliestDate, dateRangeOptions);
31
31
 
32
32
  expect(result.initialSelectedDateRange).toEqual(fromOption);
33
33
  expectDateMatches(result.initialSelectedDateFrom, new Date(dateFromOptionValue));
@@ -35,7 +35,7 @@ describe('computeInitialValues', () => {
35
35
  });
36
36
 
37
37
  it('should use earliest date as "dateFrom" if it is unset in selected option', () => {
38
- const result = computeInitialValues(toOption, undefined, undefined, earliestDate, dateRangeOptions);
38
+ const result = computeInitialValues(toOption, earliestDate, dateRangeOptions);
39
39
 
40
40
  expect(result.initialSelectedDateRange).toEqual(toOption);
41
41
  expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
@@ -43,7 +43,7 @@ describe('computeInitialValues', () => {
43
43
  });
44
44
 
45
45
  it('should fall back to full range if initial value is not set', () => {
46
- const result = computeInitialValues(undefined, undefined, undefined, earliestDate, dateRangeOptions);
46
+ const result = computeInitialValues(undefined, earliestDate, dateRangeOptions);
47
47
 
48
48
  expect(result.initialSelectedDateRange).toBeUndefined();
49
49
  expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
@@ -51,39 +51,46 @@ describe('computeInitialValues', () => {
51
51
  });
52
52
 
53
53
  it('should throw when initial value is unknown', () => {
54
- expect(() =>
55
- computeInitialValues('not a known value', undefined, undefined, earliestDate, dateRangeOptions),
56
- ).toThrowError(/Invalid initialValue "not a known value", It must be one of/);
54
+ expect(() => computeInitialValues('not a known value', earliestDate, dateRangeOptions)).toThrowError(
55
+ /Invalid value "not a known value", It must be one of/,
56
+ );
57
57
  });
58
58
 
59
59
  it('should throw when initial value is set but no options are provided', () => {
60
- expect(() => computeInitialValues('not a known value', undefined, undefined, earliestDate, [])).toThrowError(
60
+ expect(() => computeInitialValues('not a known value', earliestDate, [])).toThrowError(
61
61
  /There are no selectable options/,
62
62
  );
63
63
  });
64
64
 
65
- it('should overwrite initial value if initial "from" is set', () => {
65
+ it('should select from date until today if only dateFrom is given', () => {
66
66
  const initialDateFrom = '2020-01-01';
67
- const result = computeInitialValues(fromOption, initialDateFrom, undefined, earliestDate, dateRangeOptions);
67
+ const result = computeInitialValues({ dateFrom: initialDateFrom }, earliestDate, dateRangeOptions);
68
68
 
69
69
  expect(result.initialSelectedDateRange).toBeUndefined();
70
70
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
71
71
  expectDateMatches(result.initialSelectedDateTo, today);
72
72
  });
73
73
 
74
- it('should overwrite initial value if initial "to" is set', () => {
74
+ it('should select from earliest date until date if only dateTo is given', () => {
75
75
  const initialDateTo = '2020-01-01';
76
- const result = computeInitialValues(fromOption, undefined, initialDateTo, earliestDate, dateRangeOptions);
76
+ const result = computeInitialValues({ dateTo: initialDateTo }, earliestDate, dateRangeOptions);
77
77
 
78
78
  expect(result.initialSelectedDateRange).toBeUndefined();
79
79
  expectDateMatches(result.initialSelectedDateFrom, new Date(earliestDate));
80
80
  expectDateMatches(result.initialSelectedDateTo, new Date(initialDateTo));
81
81
  });
82
82
 
83
- it('should overwrite initial value if initial "to" and "from" are set', () => {
83
+ it('should select date range is dateFrom and dateTo are given', () => {
84
84
  const initialDateFrom = '2020-01-01';
85
85
  const initialDateTo = '2022-01-01';
86
- const result = computeInitialValues(fromOption, initialDateFrom, initialDateTo, earliestDate, dateRangeOptions);
86
+ const result = computeInitialValues(
87
+ {
88
+ dateFrom: initialDateFrom,
89
+ dateTo: initialDateTo,
90
+ },
91
+ earliestDate,
92
+ dateRangeOptions,
93
+ );
87
94
 
88
95
  expect(result.initialSelectedDateRange).toBeUndefined();
89
96
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
@@ -93,7 +100,14 @@ describe('computeInitialValues', () => {
93
100
  it('should set initial "to" to "from" if "from" is after "to"', () => {
94
101
  const initialDateFrom = '2020-01-01';
95
102
  const initialDateTo = '1900-01-01';
96
- const result = computeInitialValues(undefined, initialDateFrom, initialDateTo, earliestDate, dateRangeOptions);
103
+ const result = computeInitialValues(
104
+ {
105
+ dateFrom: initialDateFrom,
106
+ dateTo: initialDateTo,
107
+ },
108
+ earliestDate,
109
+ dateRangeOptions,
110
+ );
97
111
 
98
112
  expect(result.initialSelectedDateRange).toBeUndefined();
99
113
  expectDateMatches(result.initialSelectedDateFrom, new Date(initialDateFrom));
@@ -101,14 +115,14 @@ describe('computeInitialValues', () => {
101
115
  });
102
116
 
103
117
  it('should throw if initial "from" is not a valid date', () => {
104
- expect(() => computeInitialValues(undefined, 'not a date', undefined, earliestDate, [])).toThrowError(
105
- 'Invalid initialDateFrom',
118
+ expect(() => computeInitialValues({ dateFrom: 'not a date' }, earliestDate, [])).toThrowError(
119
+ 'Invalid value.dateFrom',
106
120
  );
107
121
  });
108
122
 
109
123
  it('should throw if initial "to" is not a valid date', () => {
110
- expect(() => computeInitialValues(undefined, undefined, 'not a date', earliestDate, [])).toThrowError(
111
- 'Invalid initialDateTo',
124
+ expect(() => computeInitialValues({ dateTo: 'not a date' }, earliestDate, [])).toThrowError(
125
+ 'Invalid value.dateTo',
112
126
  );
113
127
  });
114
128
 
@@ -1,11 +1,9 @@
1
- import { type DateRangeOption } from './dateRangeOption';
1
+ import { type DateRangeOption, type DateRangeValue } from './dateRangeOption';
2
2
  import { getDatesForSelectorValue, getSelectableOptions } from './selectableOptions';
3
3
  import { UserFacingError } from '../components/error-display';
4
4
 
5
5
  export function computeInitialValues(
6
- initialValue: string | undefined,
7
- initialDateFrom: string | undefined,
8
- initialDateTo: string | undefined,
6
+ value: DateRangeValue | undefined,
9
7
  earliestDate: string,
10
8
  dateRangeOptions: DateRangeOption[],
11
9
  ): {
@@ -13,20 +11,26 @@ export function computeInitialValues(
13
11
  initialSelectedDateFrom: Date;
14
12
  initialSelectedDateTo: Date;
15
13
  } {
16
- if (isUndefinedOrEmpty(initialDateFrom) && isUndefinedOrEmpty(initialDateTo)) {
14
+ if (value === undefined) {
15
+ const { dateFrom, dateTo } = getDatesForSelectorValue(undefined, dateRangeOptions, earliestDate);
16
+ return {
17
+ initialSelectedDateRange: undefined,
18
+ initialSelectedDateFrom: dateFrom,
19
+ initialSelectedDateTo: dateTo,
20
+ };
21
+ }
22
+
23
+ if (typeof value === 'string') {
17
24
  const selectableOptions = getSelectableOptions(dateRangeOptions);
18
- const initialSelectedDateRange = selectableOptions.find((option) => option.value === initialValue)?.value;
25
+ const initialSelectedDateRange = selectableOptions.find((option) => option.value === value)?.value;
19
26
 
20
- if (initialValue !== undefined && initialSelectedDateRange === undefined) {
27
+ if (initialSelectedDateRange === undefined) {
21
28
  if (selectableOptions.length === 0) {
22
- throw new UserFacingError(
23
- 'Invalid initialValue',
24
- 'There are no selectable options, but initialValue is set.',
25
- );
29
+ throw new UserFacingError('Invalid value', 'There are no selectable options, but value is set.');
26
30
  }
27
31
  throw new UserFacingError(
28
- 'Invalid initialValue',
29
- `Invalid initialValue "${initialValue}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(', ')}`,
32
+ 'Invalid value',
33
+ `Invalid value "${value}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(', ')}`,
30
34
  );
31
35
  }
32
36
 
@@ -39,21 +43,21 @@ export function computeInitialValues(
39
43
  };
40
44
  }
41
45
 
42
- const initialSelectedDateFrom = isUndefinedOrEmpty(initialDateFrom)
43
- ? new Date(earliestDate)
44
- : new Date(initialDateFrom);
45
- let initialSelectedDateTo = isUndefinedOrEmpty(initialDateTo) ? new Date() : new Date(initialDateTo);
46
+ const { dateFrom, dateTo } = value;
47
+
48
+ const initialSelectedDateFrom = isUndefinedOrEmpty(dateFrom) ? new Date(earliestDate) : new Date(dateFrom);
49
+ let initialSelectedDateTo = isUndefinedOrEmpty(dateTo) ? new Date() : new Date(dateTo);
46
50
 
47
51
  if (isNaN(initialSelectedDateFrom.getTime())) {
48
52
  throw new UserFacingError(
49
- 'Invalid initialDateFrom',
50
- `Invalid initialDateFrom "${initialDateFrom}", It must be of the format YYYY-MM-DD`,
53
+ 'Invalid value.dateFrom',
54
+ `Invalid value.dateFrom "${dateFrom}", It must be of the format YYYY-MM-DD`,
51
55
  );
52
56
  }
53
57
  if (isNaN(initialSelectedDateTo.getTime())) {
54
58
  throw new UserFacingError(
55
- 'Invalid initialDateTo',
56
- `Invalid initialDateTo "${initialDateTo}", It must be of the format YYYY-MM-DD`,
59
+ 'Invalid value.dateTo',
60
+ `Invalid value.dateTo "${dateTo}", It must be of the format YYYY-MM-DD`,
57
61
  );
58
62
  }
59
63