@genspectrum/dashboard-components 0.19.5 → 0.19.7

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 (57) hide show
  1. package/README.md +24 -8
  2. package/custom-elements.json +101 -2
  3. package/dist/{LineageFilterChangedEvent-GgkxoF3X.js → NumberRangeFilterChangedEvent-RZ8haPHq.js} +31 -5
  4. package/dist/NumberRangeFilterChangedEvent-RZ8haPHq.js.map +1 -0
  5. package/dist/assets/mutationOverTimeWorker-DQGh08AS.js.map +1 -0
  6. package/dist/components.d.ts +43 -12
  7. package/dist/components.js +78 -63
  8. package/dist/components.js.map +1 -1
  9. package/dist/util.d.ts +21 -10
  10. package/dist/util.js +3 -1
  11. package/package.json +1 -1
  12. package/src/preact/aggregatedData/aggregate.stories.tsx +6 -0
  13. package/src/preact/aggregatedData/aggregate.tsx +10 -1
  14. package/src/preact/components/tabs.tsx +4 -4
  15. package/src/preact/genomeViewer/CDSPlot.tsx +4 -1
  16. package/src/preact/genomeViewer/genome-data-viewer.stories.tsx +6 -0
  17. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +6 -0
  18. package/src/preact/mutationComparison/mutation-comparison.tsx +4 -0
  19. package/src/preact/mutations/mutations.stories.tsx +6 -0
  20. package/src/preact/mutations/mutations.tsx +4 -1
  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/numberRangeFilter/NumberRangeFilterChangedEvent.ts +1 -1
  24. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -1
  25. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -0
  26. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +6 -0
  27. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -1
  28. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +6 -0
  29. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -1
  30. package/src/preact/sequencesByLocation/sequences-by-location.stories.tsx +6 -0
  31. package/src/preact/sequencesByLocation/sequences-by-location.tsx +4 -0
  32. package/src/preact/shared/stories/expectFinishedLoadingEvent.ts +12 -0
  33. package/src/preact/statistic/statistics.stories.tsx +6 -0
  34. package/src/preact/statistic/statistics.tsx +4 -1
  35. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +2 -0
  36. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -1
  37. package/src/utilEntrypoint.ts +6 -1
  38. package/src/utils/gsEventNames.ts +1 -0
  39. package/src/utils/useDispatchFinishedLoadingEvent.ts +19 -0
  40. package/src/web-components/input/gs-number-range-filter.tsx +2 -2
  41. package/src/web-components/visualization/gs-aggregate.tsx +3 -0
  42. package/src/web-components/visualization/gs-genome-data-viewer.tsx +2 -0
  43. package/src/web-components/visualization/gs-mutation-comparison.tsx +3 -0
  44. package/src/web-components/visualization/gs-mutations-over-time.tsx +3 -0
  45. package/src/web-components/visualization/gs-mutations.tsx +2 -0
  46. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +3 -0
  47. package/src/web-components/visualization/gs-prevalence-over-time.tsx +3 -0
  48. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +3 -0
  49. package/src/web-components/visualization/gs-sequences-by-location.tsx +3 -0
  50. package/src/web-components/visualization/gs-statistics.tsx +3 -0
  51. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +3 -0
  52. package/standalone-bundle/assets/mutationOverTimeWorker-DAf2_NiP.js.map +1 -0
  53. package/standalone-bundle/dashboard-components.js +6980 -6945
  54. package/standalone-bundle/dashboard-components.js.map +1 -1
  55. package/dist/LineageFilterChangedEvent-GgkxoF3X.js.map +0 -1
  56. package/dist/assets/mutationOverTimeWorker-ChQTFL68.js.map +0 -1
  57. package/standalone-bundle/assets/mutationOverTimeWorker-jChgWnwp.js.map +0 -1
package/README.md CHANGED
@@ -54,9 +54,10 @@ We use [Lit](https://lit.dev/) to create web components.
54
54
 
55
55
  We have split the package into two parts:
56
56
 
57
- - The components, which are web components that can be used in the browser.
57
+ - The web components that can be used in the browser.
58
58
  - They can be imported with `import '@genspectrum/dashboard-components/components';`
59
- - utility functions, which can also be used in a node environment.
59
+ - Note that this imports all components at once. The `import` statement will make the web components available in the browser.
60
+ - Utility functions, types and constants which can also be used in a node environment.
60
61
  - They can be imported with `import '@genspectrum/dashboard-components/util';`
61
62
 
62
63
  We primarily provide two kinds of components:
@@ -65,7 +66,7 @@ We primarily provide two kinds of components:
65
66
  - Those components fetch data from the LAPIS instance and visualize it.
66
67
  - **Input components** that let you specify sequence filters for the LAPIS requests.
67
68
  - Input changes will fire events that can be listened to by the visualization components.
68
- It is the responsibility of the dashbaord maintainer to listen to those events
69
+ It is the responsibility of the dashboard maintainer to listen to those events
69
70
  and to wire the data correctly into the visualization components.
70
71
 
71
72
  ## Local Development
@@ -105,16 +106,26 @@ npm run storybook
105
106
  ```
106
107
 
107
108
  Then, open http://localhost:6006/ and http://localhost:6007/ in your browser.
108
- The Storybook on port 6007 uses the Preact build.
109
- The Storybook on port 6006 uses the Lit build and includes the Preact Storybook.
110
- Note that some Storybook integrations (such as interaction tests) do not work in the included Storybook.
111
- We only deploy the Lit part of the Storybook to GitHub pages.
112
109
 
110
+ The Storybook on port 6006 uses the Lit build.
111
+ Its purpose is public documentation and live demonstration of the publicly available web components.
112
+ It should focus on stories that are relevant for users of the components.
113
+ This storybook is deployed to GitHub pages.
114
+
115
+ Every web component should have a separate "Docs" page.
113
116
  Storybook offers an integration of the custom-elements.json that can generate doc pages for the web components.
114
117
  Refer to the
115
118
  [Custom Elements Manifest Docs](https://custom-elements-manifest.open-wc.org/analyzer/getting-started/#documenting-your-components)
116
119
  for how to document the components using JSDoc.
117
120
 
121
+ The Storybook on port 6007 uses the Preact build.
122
+ Its purpose is to test the components in a Preact environment.
123
+ It is not meant to be used outside the development environment
124
+ and contains many stories that are not relevant for the public (e.g. because they serve as a unit test for some edge case).
125
+ It should contain stories and corresponding unit tests for every Preact component that is relevant in a wider context
126
+ (either because it is a top level component that is also exposed as a web component
127
+ or because it is supposed to be reusable in other components).
128
+
118
129
  ### Testing
119
130
 
120
131
  We use vitest to run our unit tests:
@@ -147,7 +158,12 @@ We follow this testing concept:
147
158
 
148
159
  #### Mocking
149
160
 
150
- All our tests use mock data. In general, we use `storybook-addon-fetch-mock` for all outgoing requests. This strategy
161
+ All our tests use mock data.
162
+ Make sure that stories don't issue actual HTTP calls to LAPIS or other services.
163
+ This is to make sure that we have stable tests in CI that don't depend on the availability of other services.
164
+ We still use the real LAPIS URL so that a user can change the filters in a story and will still see data.
165
+
166
+ In general, we use `storybook-addon-fetch-mock` for all outgoing requests. This strategy
151
167
  cannot be used for components that use web workers, like gs-mutations-over-time. Therefore, we created custom mock
152
168
  workers that return mocked data. The mock workers are enabled in the package.json using
153
169
  Node.js [subpath imports](https://nodejs.org/api/packages.html#subpath-imports), following the guide
@@ -1323,14 +1323,14 @@
1323
1323
  "events": [
1324
1324
  {
1325
1325
  "type": {
1326
- "text": "CustomEvent<Record<string, string | undefined>>"
1326
+ "text": "CustomEvent<Record<string, number | undefined>>"
1327
1327
  },
1328
1328
  "description": "Fired when the slider is released, `onBlur` on the input fields after the user has typed a valid range in the input fields, or when one of the input fields is cleared. The `details` of this event contain an object with `${lapisField}From` and `${lapisField}To` as keys. The values are the numbers from the input fields or `undefined` if the input field is empty: ``` { [`${lapisField}From`]: number | undefined [`${lapisField}To`]: number | undefined } ``` Example: ``` { ageFrom: 18, ageTo: undefined } ```",
1329
1329
  "name": "gs-number-range-filter-changed"
1330
1330
  },
1331
1331
  {
1332
1332
  "type": {
1333
- "text": "CustomEvent<Record<string, string | undefined>>"
1333
+ "text": "CustomEvent<Record<string, number | undefined>>"
1334
1334
  },
1335
1335
  "description": "Similar to the `gs-number-range-filter-changed` event, but contains an `event.detail` that has a fixed format: ``` { min: number | undefined max: number | undefined } ``` This event should be used when you want to control this component externally. The `event.detail` can be used as the value of the component. Example: ``` { min: 18, max: undefined } ```",
1336
1336
  "name": "gs-number-range-value-changed"
@@ -1951,6 +1951,15 @@
1951
1951
  "attribute": "maxNumberOfBars"
1952
1952
  }
1953
1953
  ],
1954
+ "events": [
1955
+ {
1956
+ "type": {
1957
+ "text": "CustomEvent<undefined>"
1958
+ },
1959
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
1960
+ "name": "gs-component-finished-loading"
1961
+ }
1962
+ ],
1954
1963
  "attributes": [
1955
1964
  {
1956
1965
  "name": "fields",
@@ -2147,6 +2156,15 @@
2147
2156
  "attribute": "width"
2148
2157
  }
2149
2158
  ],
2159
+ "events": [
2160
+ {
2161
+ "type": {
2162
+ "text": "CustomEvent<undefined>"
2163
+ },
2164
+ "description": "Fired when the component has finished loading the required data.",
2165
+ "name": "gs-component-finished-loading"
2166
+ }
2167
+ ],
2150
2168
  "attributes": [
2151
2169
  {
2152
2170
  "name": "gff3Source",
@@ -2345,6 +2363,15 @@
2345
2363
  "attribute": "pageSize"
2346
2364
  }
2347
2365
  ],
2366
+ "events": [
2367
+ {
2368
+ "type": {
2369
+ "text": "CustomEvent<undefined>"
2370
+ },
2371
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
2372
+ "name": "gs-component-finished-loading"
2373
+ }
2374
+ ],
2348
2375
  "attributes": [
2349
2376
  {
2350
2377
  "name": "lapisFilters",
@@ -2664,6 +2691,15 @@
2664
2691
  "attribute": "pageSizes"
2665
2692
  }
2666
2693
  ],
2694
+ "events": [
2695
+ {
2696
+ "type": {
2697
+ "text": "CustomEvent<undefined>"
2698
+ },
2699
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
2700
+ "name": "gs-component-finished-loading"
2701
+ }
2702
+ ],
2667
2703
  "attributes": [
2668
2704
  {
2669
2705
  "name": "lapisFilter",
@@ -2967,6 +3003,15 @@
2967
3003
  "attribute": "pageSize"
2968
3004
  }
2969
3005
  ],
3006
+ "events": [
3007
+ {
3008
+ "type": {
3009
+ "text": "CustomEvent<undefined>"
3010
+ },
3011
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
3012
+ "name": "gs-component-finished-loading"
3013
+ }
3014
+ ],
2970
3015
  "attributes": [
2971
3016
  {
2972
3017
  "name": "lapisFilter",
@@ -3269,6 +3314,15 @@
3269
3314
  "attribute": "pageSize"
3270
3315
  }
3271
3316
  ],
3317
+ "events": [
3318
+ {
3319
+ "type": {
3320
+ "text": "CustomEvent<undefined>"
3321
+ },
3322
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
3323
+ "name": "gs-component-finished-loading"
3324
+ }
3325
+ ],
3272
3326
  "attributes": [
3273
3327
  {
3274
3328
  "name": "lapisFilters",
@@ -3620,6 +3674,15 @@
3620
3674
  "attribute": "yAxisMaxLogarithmic"
3621
3675
  }
3622
3676
  ],
3677
+ "events": [
3678
+ {
3679
+ "type": {
3680
+ "text": "CustomEvent<undefined>"
3681
+ },
3682
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
3683
+ "name": "gs-component-finished-loading"
3684
+ }
3685
+ ],
3623
3686
  "attributes": [
3624
3687
  {
3625
3688
  "name": "numeratorFilters",
@@ -3913,6 +3976,15 @@
3913
3976
  "attribute": "yAxisMaxLogarithmic"
3914
3977
  }
3915
3978
  ],
3979
+ "events": [
3980
+ {
3981
+ "type": {
3982
+ "text": "CustomEvent<undefined>"
3983
+ },
3984
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
3985
+ "name": "gs-component-finished-loading"
3986
+ }
3987
+ ],
3916
3988
  "attributes": [
3917
3989
  {
3918
3990
  "name": "numeratorFilter",
@@ -4247,6 +4319,15 @@
4247
4319
  "attribute": "pageSize"
4248
4320
  }
4249
4321
  ],
4322
+ "events": [
4323
+ {
4324
+ "type": {
4325
+ "text": "CustomEvent<undefined>"
4326
+ },
4327
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
4328
+ "name": "gs-component-finished-loading"
4329
+ }
4330
+ ],
4250
4331
  "attributes": [
4251
4332
  {
4252
4333
  "name": "lapisFilter",
@@ -4465,6 +4546,15 @@
4465
4546
  "attribute": "height"
4466
4547
  }
4467
4548
  ],
4549
+ "events": [
4550
+ {
4551
+ "type": {
4552
+ "text": "CustomEvent<undefined>"
4553
+ },
4554
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
4555
+ "name": "gs-component-finished-loading"
4556
+ }
4557
+ ],
4468
4558
  "attributes": [
4469
4559
  {
4470
4560
  "name": "numeratorFilter",
@@ -4745,6 +4835,15 @@
4745
4835
  "attribute": "pageSizes"
4746
4836
  }
4747
4837
  ],
4838
+ "events": [
4839
+ {
4840
+ "type": {
4841
+ "text": "CustomEvent<undefined>"
4842
+ },
4843
+ "description": "Fired when the component has finished loading the required data from LAPIS.",
4844
+ "name": "gs-component-finished-loading"
4845
+ }
4846
+ ],
4748
4847
  "attributes": [
4749
4848
  {
4750
4849
  "name": "lapisFilter",
@@ -1,6 +1,7 @@
1
1
  import z from "zod";
2
2
  const gsEventNames = {
3
3
  error: "gs-error",
4
+ componentFinishedLoading: "gs-component-finished-loading",
4
5
  dateRangeFilterChanged: "gs-date-range-filter-changed",
5
6
  dateRangeOptionChanged: "gs-date-range-option-changed",
6
7
  mutationFilterChanged: "gs-mutation-filter-changed",
@@ -142,17 +143,42 @@ class LineageFilterChangedEvent extends CustomEvent {
142
143
  });
143
144
  }
144
145
  }
146
+ const numberRangeSchema = z.object({
147
+ min: z.number().optional(),
148
+ max: z.number().optional()
149
+ });
150
+ class NumberRangeValueChangedEvent extends CustomEvent {
151
+ constructor(detail) {
152
+ super(gsEventNames.numberRangeValueChanged, {
153
+ detail,
154
+ bubbles: true,
155
+ composed: true
156
+ });
157
+ }
158
+ }
159
+ class NumberRangeFilterChangedEvent extends CustomEvent {
160
+ constructor(detail) {
161
+ super(gsEventNames.numberRangeFilterChanged, {
162
+ detail,
163
+ bubbles: true,
164
+ composed: true
165
+ });
166
+ }
167
+ }
145
168
  export {
146
169
  DateRangeOptionChangedEvent as D,
147
170
  LocationChangedEvent as L,
171
+ NumberRangeFilterChangedEvent as N,
148
172
  TextFilterChangedEvent as T,
149
173
  LineageFilterChangedEvent as a,
150
- dateRangeValueSchema as b,
151
- dateRangeOptionSchema as c,
174
+ NumberRangeValueChangedEvent as b,
175
+ dateRangeValueSchema as c,
152
176
  dateRangeOptionPresets as d,
153
- toYYYYMMDD as e,
154
- lapisLocationFilterSchema as f,
177
+ dateRangeOptionSchema as e,
178
+ toYYYYMMDD as f,
155
179
  gsEventNames as g,
180
+ lapisLocationFilterSchema as h,
181
+ numberRangeSchema as i,
156
182
  lapisFilterSchema as l,
157
183
  mutationsFilterSchema as m,
158
184
  namedLapisFilterSchema as n,
@@ -160,4 +186,4 @@ export {
160
186
  temporalGranularitySchema as t,
161
187
  views as v
162
188
  };
163
- //# sourceMappingURL=LineageFilterChangedEvent-GgkxoF3X.js.map
189
+ //# sourceMappingURL=NumberRangeFilterChangedEvent-RZ8haPHq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumberRangeFilterChangedEvent-RZ8haPHq.js","sources":["../src/utils/gsEventNames.ts","../src/types.ts","../src/preact/dateRangeFilter/dateConversion.ts","../src/preact/dateRangeFilter/dateRangeOption.ts","../src/preact/locationFilter/LocationChangedEvent.ts","../src/preact/textFilter/TextFilterChangedEvent.ts","../src/preact/lineageFilter/LineageFilterChangedEvent.ts","../src/preact/numberRangeFilter/NumberRangeFilterChangedEvent.ts"],"sourcesContent":["export const gsEventNames = {\n error: 'gs-error',\n componentFinishedLoading: 'gs-component-finished-loading',\n dateRangeFilterChanged: 'gs-date-range-filter-changed',\n dateRangeOptionChanged: 'gs-date-range-option-changed',\n mutationFilterChanged: 'gs-mutation-filter-changed',\n lineageFilterChanged: 'gs-lineage-filter-changed',\n locationChanged: 'gs-location-changed',\n textFilterChanged: 'gs-text-filter-changed',\n numberRangeFilterChanged: 'gs-number-range-filter-changed',\n numberRangeValueChanged: 'gs-number-range-value-changed',\n} as const;\n","import z from 'zod';\n\nimport {\n type Deletion,\n type DeletionClass,\n type Insertion,\n type InsertionClass,\n type Substitution,\n type SubstitutionClass,\n} from './utils/mutations';\n\nexport const mutationsFilterSchema = z.object({\n nucleotideMutations: z.array(z.string()),\n aminoAcidMutations: z.array(z.string()),\n nucleotideInsertions: z.array(z.string()),\n aminoAcidInsertions: z.array(z.string()),\n});\nexport type MutationsFilter = z.infer<typeof mutationsFilterSchema>;\n\nexport const lapisFilterSchema = z\n .record(z.union([z.string(), z.array(z.string()), z.number(), z.null(), z.boolean(), z.undefined()]))\n .and(mutationsFilterSchema.partial());\nexport type LapisFilter = z.infer<typeof lapisFilterSchema>;\n\nexport const namedLapisFilterSchema = z.object({\n lapisFilter: lapisFilterSchema,\n displayName: z.string(),\n});\nexport type NamedLapisFilter = z.infer<typeof namedLapisFilterSchema>;\n\nexport const lapisLocationFilterSchema = z.record(z.union([z.string(), z.undefined()]));\nexport type LapisLocationFilter = z.infer<typeof lapisLocationFilterSchema>;\n\nexport const temporalGranularitySchema = z.union([\n z.literal('day'),\n z.literal('week'),\n z.literal('month'),\n z.literal('year'),\n]);\nexport type TemporalGranularity = z.infer<typeof temporalGranularitySchema>;\n\nexport const sequenceTypeSchema = z.union([z.literal('nucleotide'), z.literal('amino acid')]);\nexport type SequenceType = z.infer<typeof sequenceTypeSchema>;\n\nexport type SubstitutionOrDeletion = 'substitution' | 'deletion';\n\nexport type MutationType = SubstitutionOrDeletion | 'insertion';\n\nexport type SubstitutionEntry<T extends Substitution = SubstitutionClass> = {\n type: 'substitution';\n mutation: T;\n count: number;\n proportion: number;\n};\n\nexport type DeletionEntry<T extends Deletion = DeletionClass> = {\n type: 'deletion';\n mutation: T;\n count: number;\n proportion: number;\n};\n\nexport type InsertionEntry<T extends Insertion = InsertionClass> = { type: 'insertion'; mutation: T; count: number };\n\nexport type SubstitutionOrDeletionEntry<\n S extends Substitution = SubstitutionClass,\n D extends Deletion = DeletionClass,\n> = SubstitutionEntry<S> | DeletionEntry<D>;\n\nexport type MutationEntry = SubstitutionEntry | DeletionEntry | InsertionEntry;\n\nexport const views = {\n table: 'table',\n venn: 'venn',\n grid: 'grid',\n insertions: 'insertions',\n bar: 'bar',\n line: 'line',\n bubble: 'bubble',\n map: 'map',\n} as const;\n","export const toYYYYMMDD = (date: Date) => {\n const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };\n return date.toLocaleDateString('en-CA', options);\n};\n","import z from 'zod';\n\nimport { toYYYYMMDD } from './dateConversion';\nimport { gsEventNames } from '../../utils/gsEventNames';\n\n/**\n * A date range option that can be used in the `gs-date-range-filter` component.\n */\nexport const dateRangeOptionSchema = z.object({\n /** The label of the date range option that will be shown to the user */\n label: z.string(),\n /**\n * The start date of the date range in the format `YYYY-MM-DD`.\n * If not set, the date range selector will default to the `earliestDate` property.\n */\n dateFrom: z.string().date().optional(),\n /**\n * The end date of the date range in the format `YYYY-MM-DD`.\n * If not set, the date range selector will default to the current date.\n */\n dateTo: z.string().date().optional(),\n});\n\nexport type DateRangeOption = z.infer<typeof dateRangeOptionSchema>;\n\nexport const dateRangeValueSchema = z\n .union([\n z.string(),\n z.object({\n dateFrom: z.string().date().optional(),\n dateTo: z.string().date().optional(),\n }),\n ])\n .nullable();\n\nexport type DateRangeValue = z.infer<typeof dateRangeValueSchema>;\n\nexport class DateRangeOptionChangedEvent extends CustomEvent<DateRangeValue> {\n constructor(detail: DateRangeValue) {\n super(gsEventNames.dateRangeOptionChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n\nconst today = new Date();\n\nconst twoWeeksAgo = new Date();\ntwoWeeksAgo.setDate(today.getDate() - 14);\n\nconst lastMonth = new Date(today);\nlastMonth.setMonth(today.getMonth() - 1);\n\nconst last2Months = new Date(today);\nlast2Months.setMonth(today.getMonth() - 2);\n\nconst last3Months = new Date(today);\nlast3Months.setMonth(today.getMonth() - 3);\n\nconst last6Months = new Date(today);\nlast6Months.setMonth(today.getMonth() - 6);\n\nconst lastYear = new Date(today);\nlastYear.setFullYear(today.getFullYear() - 1);\n\n/**\n * Presets for the `gs-date-range-filter` component that can be used as `dateRangeOptions`.\n */\nexport const dateRangeOptionPresets = {\n last2Weeks: {\n label: 'Last 2 weeks',\n dateFrom: toYYYYMMDD(twoWeeksAgo),\n },\n lastMonth: {\n label: 'Last month',\n dateFrom: toYYYYMMDD(lastMonth),\n },\n last2Months: {\n label: 'Last 2 months',\n dateFrom: toYYYYMMDD(last2Months),\n },\n last3Months: {\n label: 'Last 3 months',\n dateFrom: toYYYYMMDD(last3Months),\n },\n last6Months: {\n label: 'Last 6 months',\n dateFrom: toYYYYMMDD(last6Months),\n },\n lastYear: {\n label: 'Last year',\n dateFrom: toYYYYMMDD(lastYear),\n },\n allTimes: {\n label: 'All times',\n },\n} satisfies Record<string, DateRangeOption>;\n","import { type LapisLocationFilter } from '../../types';\nimport { gsEventNames } from '../../utils/gsEventNames';\n\nexport class LocationChangedEvent extends CustomEvent<LapisLocationFilter> {\n constructor(detail: LapisLocationFilter) {\n super(gsEventNames.locationChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n","import { gsEventNames } from '../../utils/gsEventNames';\n\ntype LapisTextFilter = Record<string, string | undefined>;\n\nexport class TextFilterChangedEvent extends CustomEvent<LapisTextFilter> {\n constructor(detail: LapisTextFilter) {\n super(gsEventNames.textFilterChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n","import { gsEventNames } from '../../utils/gsEventNames';\n\ntype LapisLineageFilter = Record<string, string | undefined>;\n\nexport class LineageFilterChangedEvent extends CustomEvent<LapisLineageFilter> {\n constructor(detail: LapisLineageFilter) {\n super(gsEventNames.lineageFilterChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n","import z from 'zod';\n\nimport { gsEventNames } from '../../utils/gsEventNames';\n\nexport type LapisNumberFilter = Record<string, number | undefined>;\n\nexport const numberRangeSchema = z.object({\n min: z.number().optional(),\n max: z.number().optional(),\n});\nexport type NumberRange = z.infer<typeof numberRangeSchema>;\n\nexport class NumberRangeValueChangedEvent extends CustomEvent<NumberRange> {\n constructor(detail: NumberRange) {\n super(gsEventNames.numberRangeValueChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n\nexport class NumberRangeFilterChangedEvent extends CustomEvent<LapisNumberFilter> {\n constructor(detail: LapisNumberFilter) {\n super(gsEventNames.numberRangeFilterChanged, {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n"],"names":[],"mappings":"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"}