@genspectrum/dashboard-components 0.12.1 → 0.13.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.
- package/custom-elements.json +292 -25
- package/dist/{LocationChangedEvent-CORvQvXv.js → LineageFilterChangedEvent-GedKNGFI.js} +25 -3
- package/dist/LineageFilterChangedEvent-GedKNGFI.js.map +1 -0
- package/dist/assets/mutationOverTimeWorker-B1-WrM4b.js.map +1 -0
- package/dist/components.d.ts +124 -25
- package/dist/components.js +765 -572
- package/dist/components.js.map +1 -1
- package/dist/style.css +3 -0
- package/dist/util.d.ts +48 -18
- package/dist/util.js +3 -1
- package/package.json +2 -2
- package/src/constants.ts +6 -0
- package/src/lapisApi/__mockData__/wiseReferenceGenome.json +9 -0
- package/src/lapisApi/lapisApi.ts +17 -0
- package/src/lapisApi/lapisTypes.ts +7 -1
- package/src/operator/FetchDetailsOperator.ts +28 -0
- package/src/preact/components/downshift-combobox.tsx +145 -0
- package/src/preact/components/tabs.tsx +1 -1
- package/src/preact/lineageFilter/LineageFilterChangedEvent.ts +11 -0
- package/src/preact/lineageFilter/fetchLineageAutocompleteList.spec.ts +16 -2
- package/src/preact/lineageFilter/fetchLineageAutocompleteList.ts +13 -2
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +110 -9
- package/src/preact/lineageFilter/lineage-filter.tsx +40 -50
- package/src/preact/locationFilter/LocationChangedEvent.ts +1 -1
- package/src/preact/locationFilter/fetchAutocompletionList.spec.ts +6 -2
- package/src/preact/locationFilter/fetchAutocompletionList.ts +16 -6
- package/src/preact/locationFilter/location-filter.stories.tsx +33 -30
- package/src/preact/locationFilter/location-filter.tsx +47 -144
- package/src/preact/mutationsOverTime/MutationOverTimeData.ts +9 -5
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +5 -3
- package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +4 -7
- package/src/preact/textInput/TextInputChangedEvent.ts +1 -1
- package/src/preact/textInput/fetchStringAutocompleteList.ts +20 -0
- package/src/preact/textInput/text-input.stories.tsx +14 -11
- package/src/preact/textInput/text-input.tsx +39 -140
- package/src/preact/wastewater/mutationsOverTime/__mockData__/details.json +88 -0
- package/src/preact/wastewater/mutationsOverTime/computeWastewaterMutationsOverTimeDataPerLocation.spec.ts +159 -0
- package/src/preact/wastewater/mutationsOverTime/computeWastewaterMutationsOverTimeDataPerLocation.ts +51 -0
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +71 -0
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +151 -0
- package/src/query/queryMutationsOverTime.ts +6 -14
- package/src/query/queryWastewaterMutationsOverTime.spec.ts +94 -0
- package/src/query/queryWastewaterMutationsOverTime.ts +55 -0
- package/src/types.ts +3 -0
- package/src/utilEntrypoint.ts +2 -0
- package/src/utils/map2d.ts +39 -0
- package/src/web-components/index.ts +1 -0
- package/src/web-components/input/gs-lineage-filter.stories.ts +120 -31
- package/src/web-components/input/gs-lineage-filter.tsx +24 -8
- package/src/web-components/input/gs-location-filter.stories.ts +9 -0
- package/src/web-components/input/gs-location-filter.tsx +21 -3
- package/src/web-components/input/gs-text-input.stories.ts +14 -5
- package/src/web-components/input/gs-text-input.tsx +23 -7
- package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts +82 -0
- package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +112 -0
- package/src/web-components/wastewaterVisualization/index.ts +1 -0
- package/standalone-bundle/assets/{mutationOverTimeWorker-DEybsZ5r.js.map → mutationOverTimeWorker-Cls1J0cl.js.map} +1 -1
- package/standalone-bundle/dashboard-components.js +6972 -6796
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
- package/dist/LocationChangedEvent-CORvQvXv.js.map +0 -1
- package/dist/assets/mutationOverTimeWorker-DTv93Ere.js.map +0 -1
- package/src/preact/textInput/fetchAutocompleteList.ts +0 -9
package/custom-elements.json
CHANGED
|
@@ -270,6 +270,14 @@
|
|
|
270
270
|
"package": "./visualization"
|
|
271
271
|
}
|
|
272
272
|
},
|
|
273
|
+
{
|
|
274
|
+
"kind": "js",
|
|
275
|
+
"name": "*",
|
|
276
|
+
"declaration": {
|
|
277
|
+
"name": "*",
|
|
278
|
+
"package": "./wastewaterVisualization"
|
|
279
|
+
}
|
|
280
|
+
},
|
|
273
281
|
{
|
|
274
282
|
"kind": "js",
|
|
275
283
|
"name": "*",
|
|
@@ -534,15 +542,31 @@
|
|
|
534
542
|
"type": {
|
|
535
543
|
"text": "Meta<Required<LineageFilterProps>>"
|
|
536
544
|
},
|
|
537
|
-
"default": "{ title: 'Input/Lineage filter', component: 'gs-lineage-filter', parameters: withComponentDocs({ actions: { handles: ['gs-lineage-filter-changed', ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'pangoLineage', url: AGGREGATED_ENDPOINT, body: { fields: ['pangoLineage'], }, }, response: { status: 200, body: aggregatedData, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], }"
|
|
545
|
+
"default": "{ title: 'Input/Lineage filter', component: 'gs-lineage-filter', parameters: withComponentDocs({ actions: { handles: ['gs-lineage-filter-changed', ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'pangoLineage', url: AGGREGATED_ENDPOINT, body: { fields: ['pangoLineage'], country: 'Germany', }, }, response: { status: 200, body: aggregatedData, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], argTypes: { lapisField: { control: { type: 'select', }, options: ['host'], }, placeholderText: { control: { type: 'text', }, }, value: { control: { type: 'text', }, }, width: { control: { type: 'text', }, }, lapisFilter: { control: { type: 'object', }, }, }, }"
|
|
538
546
|
},
|
|
539
547
|
{
|
|
540
548
|
"kind": "variable",
|
|
541
|
-
"name": "
|
|
549
|
+
"name": "LineageFilter",
|
|
550
|
+
"type": {
|
|
551
|
+
"text": "StoryObj<Required<LineageFilterProps>>"
|
|
552
|
+
},
|
|
553
|
+
"default": "{ ...Template, play: async ({ canvasElement }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-lineage-filter'); await waitFor(() => { return expect(canvas.getByPlaceholderText('Enter a lineage')).toBeVisible(); }); }, }"
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
"kind": "variable",
|
|
557
|
+
"name": "DelayToShowLoadingState",
|
|
558
|
+
"type": {
|
|
559
|
+
"text": "StoryObj<Required<LineageFilterProps>>"
|
|
560
|
+
},
|
|
561
|
+
"default": "{ ...Template, parameters: { fetchMock: { mocks: [ { matcher: aggregatedEndpointMatcher, response: { status: 200, body: aggregatedData, }, options: { delay: 5000, }, }, ], }, }, }"
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
"kind": "variable",
|
|
565
|
+
"name": "FetchingLocationsFails",
|
|
542
566
|
"type": {
|
|
543
567
|
"text": "StoryObj<Required<LineageFilterProps>>"
|
|
544
568
|
},
|
|
545
|
-
"default": "{
|
|
569
|
+
"default": "{ ...Template, parameters: { fetchMock: { mocks: [ { matcher: aggregatedEndpointMatcher, response: { status: 400, body: { error: { status: 400, detail: 'Dummy error message from mock LAPIS', type: 'about:blank' }, }, }, }, ], }, }, play: async ({ canvasElement }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-lineage-filter'); await waitFor(() => expect(canvas.getByText('Oops! Something went wrong.', { exact: false })).toBeInTheDocument(), ); }, }"
|
|
546
570
|
},
|
|
547
571
|
{
|
|
548
572
|
"kind": "variable",
|
|
@@ -550,7 +574,7 @@
|
|
|
550
574
|
"type": {
|
|
551
575
|
"text": "StoryObj<Required<LineageFilterProps>>"
|
|
552
576
|
},
|
|
553
|
-
"default": "{ ...
|
|
577
|
+
"default": "{ ...LineageFilter, play: async ({ canvasElement, step }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-lineage-filter'); const inputField = () => canvas.getByPlaceholderText('Enter a lineage'); const listenerMock = fn(); await step('Setup event listener mock', async () => { canvasElement.addEventListener('gs-lineage-filter-changed', listenerMock); }); await step('wait until data is loaded', async () => { await waitFor(() => { return expect(inputField()).toBeEnabled(); }); }); await step('Enters an invalid lineage value', async () => { await userEvent.type(inputField(), 'notInList'); await expect(listenerMock).not.toHaveBeenCalled(); }); await step('Empty input', async () => { await userEvent.type(inputField(), '{backspace>9/}'); await userEvent.click(canvas.getByLabelText('toggle menu')); await waitFor(() => { return expect(listenerMock.mock.calls.at(-1)![0].detail).toStrictEqual({ pangoLineage: undefined, }); }); }); await step('Enter a valid lineage value', async () => { await userEvent.type(inputField(), 'B.1.1.7*'); await userEvent.click(canvas.getByRole('option', { name: 'B.1.1.7*' })); await waitFor(() => { return expect(listenerMock.mock.calls.at(-1)![0].detail).toStrictEqual({ pangoLineage: 'B.1.1.7*', }); }); }); }, args: { ...LineageFilter.args, value: '', }, }"
|
|
554
578
|
}
|
|
555
579
|
],
|
|
556
580
|
"exports": [
|
|
@@ -564,9 +588,25 @@
|
|
|
564
588
|
},
|
|
565
589
|
{
|
|
566
590
|
"kind": "js",
|
|
567
|
-
"name": "
|
|
591
|
+
"name": "LineageFilter",
|
|
568
592
|
"declaration": {
|
|
569
|
-
"name": "
|
|
593
|
+
"name": "LineageFilter",
|
|
594
|
+
"module": "src/web-components/input/gs-lineage-filter.stories.ts"
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
"kind": "js",
|
|
599
|
+
"name": "DelayToShowLoadingState",
|
|
600
|
+
"declaration": {
|
|
601
|
+
"name": "DelayToShowLoadingState",
|
|
602
|
+
"module": "src/web-components/input/gs-lineage-filter.stories.ts"
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
"kind": "js",
|
|
607
|
+
"name": "FetchingLocationsFails",
|
|
608
|
+
"declaration": {
|
|
609
|
+
"name": "FetchingLocationsFails",
|
|
570
610
|
"module": "src/web-components/input/gs-lineage-filter.stories.ts"
|
|
571
611
|
}
|
|
572
612
|
},
|
|
@@ -586,18 +626,18 @@
|
|
|
586
626
|
"declarations": [
|
|
587
627
|
{
|
|
588
628
|
"kind": "class",
|
|
589
|
-
"description": "\n## Context\n\nThis component provides a text input field to filter by lineages.\nCurrently, it is designed to work well with Pango Lineages,\nbut it may also be used for other lineage types, if suitable.\n\nIt fetches all available values of the `lapisField` from the LAPIS instance
|
|
629
|
+
"description": "\n## Context\n\nThis component provides a text input field to filter by lineages.\nCurrently, it is designed to work well with Pango Lineages,\nbut it may also be used for other lineage types, if suitable.\n\nIt fetches all available values of the `lapisField` from the LAPIS instance within the given `lapisFilter`\nand provides an autocomplete list with the available values of the lineage and sublineage queries\n(a `*` appended to the lineage value).",
|
|
590
630
|
"name": "LineageFilterComponent",
|
|
591
631
|
"members": [
|
|
592
632
|
{
|
|
593
633
|
"kind": "field",
|
|
594
|
-
"name": "
|
|
634
|
+
"name": "value",
|
|
595
635
|
"type": {
|
|
596
636
|
"text": "string"
|
|
597
637
|
},
|
|
598
638
|
"default": "''",
|
|
599
639
|
"description": "The initial value to use for this lineage filter.",
|
|
600
|
-
"attribute": "
|
|
640
|
+
"attribute": "value"
|
|
601
641
|
},
|
|
602
642
|
{
|
|
603
643
|
"kind": "field",
|
|
@@ -609,6 +649,16 @@
|
|
|
609
649
|
"description": "Required.\n\nThe LAPIS field name to use for this lineage filter.\nThe field must exist on this LAPIS instance.",
|
|
610
650
|
"attribute": "lapisField"
|
|
611
651
|
},
|
|
652
|
+
{
|
|
653
|
+
"kind": "field",
|
|
654
|
+
"name": "lapisFilter",
|
|
655
|
+
"type": {
|
|
656
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
657
|
+
},
|
|
658
|
+
"default": "{}",
|
|
659
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
660
|
+
"attribute": "lapisFilter"
|
|
661
|
+
},
|
|
612
662
|
{
|
|
613
663
|
"kind": "field",
|
|
614
664
|
"name": "placeholderText",
|
|
@@ -633,7 +683,7 @@
|
|
|
633
683
|
"events": [
|
|
634
684
|
{
|
|
635
685
|
"type": {
|
|
636
|
-
"text": "CustomEvent<Record<string, string>>"
|
|
686
|
+
"text": "CustomEvent<Record<string, string | undefined>>"
|
|
637
687
|
},
|
|
638
688
|
"description": "Fired when the input field is changed. The `details` of this event contain an object with the `lapisField` as key and the input value as value. Example: ``` { \"pangoLineage\": \"B.1.1.7\" } ```",
|
|
639
689
|
"name": "gs-lineage-filter-changed"
|
|
@@ -641,13 +691,13 @@
|
|
|
641
691
|
],
|
|
642
692
|
"attributes": [
|
|
643
693
|
{
|
|
644
|
-
"name": "
|
|
694
|
+
"name": "value",
|
|
645
695
|
"type": {
|
|
646
696
|
"text": "string"
|
|
647
697
|
},
|
|
648
698
|
"default": "''",
|
|
649
699
|
"description": "The initial value to use for this lineage filter.",
|
|
650
|
-
"fieldName": "
|
|
700
|
+
"fieldName": "value"
|
|
651
701
|
},
|
|
652
702
|
{
|
|
653
703
|
"name": "lapisField",
|
|
@@ -658,6 +708,15 @@
|
|
|
658
708
|
"description": "Required.\n\nThe LAPIS field name to use for this lineage filter.\nThe field must exist on this LAPIS instance.",
|
|
659
709
|
"fieldName": "lapisField"
|
|
660
710
|
},
|
|
711
|
+
{
|
|
712
|
+
"name": "lapisFilter",
|
|
713
|
+
"type": {
|
|
714
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
715
|
+
},
|
|
716
|
+
"default": "{}",
|
|
717
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
718
|
+
"fieldName": "lapisFilter"
|
|
719
|
+
},
|
|
661
720
|
{
|
|
662
721
|
"name": "placeholderText",
|
|
663
722
|
"type": {
|
|
@@ -714,7 +773,7 @@
|
|
|
714
773
|
"type": {
|
|
715
774
|
"text": "Meta"
|
|
716
775
|
},
|
|
717
|
-
"default": "{ title: 'Input/Location filter', component: 'gs-location-filter', parameters: withComponentDocs({ actions: { handles: ['gs-location-changed', ...previewHandles], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), argTypes: { fields: { control: { type: 'object', }, }, value: { control: { type: 'object', }, }, width: { control: { type: 'text', }, }, placeholderText: { control: { type: 'text', }, }, }, tags: ['autodocs'], }"
|
|
776
|
+
"default": "{ title: 'Input/Location filter', component: 'gs-location-filter', parameters: withComponentDocs({ actions: { handles: ['gs-location-changed', ...previewHandles], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), argTypes: { fields: { control: { type: 'object', }, }, value: { control: { type: 'object', }, }, width: { control: { type: 'text', }, }, placeholderText: { control: { type: 'text', }, }, lapisFilter: { age: 18, }, }, tags: ['autodocs'], }"
|
|
718
777
|
},
|
|
719
778
|
{
|
|
720
779
|
"kind": "variable",
|
|
@@ -798,14 +857,14 @@
|
|
|
798
857
|
"declarations": [
|
|
799
858
|
{
|
|
800
859
|
"kind": "class",
|
|
801
|
-
"description": "## Context\n\nThis component provides an input field to specify filters for locations.\n\nIt expects a list of fields that form a strict hierarchical order, such as continent, country, and city.\nThe component retrieves a list of all possible values for these fields from the Lapis instance
|
|
860
|
+
"description": "## Context\n\nThis component provides an input field to specify filters for locations.\n\nIt expects a list of fields that form a strict hierarchical order, such as continent, country, and city.\nThe component retrieves a list of all possible values for these fields from the Lapis instance,\nwithin the `lapisFilter`.\nThis list is then utilized to display autocomplete suggestions and to validate the input.",
|
|
802
861
|
"name": "LocationFilterComponent",
|
|
803
862
|
"members": [
|
|
804
863
|
{
|
|
805
864
|
"kind": "field",
|
|
806
865
|
"name": "value",
|
|
807
866
|
"type": {
|
|
808
|
-
"text": "Record<string, string |
|
|
867
|
+
"text": "Record<string, string | undefined> | undefined"
|
|
809
868
|
},
|
|
810
869
|
"default": "undefined",
|
|
811
870
|
"description": "The initial value to use for this location filter.",
|
|
@@ -821,6 +880,16 @@
|
|
|
821
880
|
"description": "Required.\n\nThe fields to display in the location filter, in hierarchical order.\nThe top-level field should be the first entry in the array.\nThis component assumes that the values for each field form a strict hierarchy\n(e.g., `fields = ['continent', 'country', 'city']`).",
|
|
822
881
|
"attribute": "fields"
|
|
823
882
|
},
|
|
883
|
+
{
|
|
884
|
+
"kind": "field",
|
|
885
|
+
"name": "lapisFilter",
|
|
886
|
+
"type": {
|
|
887
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
888
|
+
},
|
|
889
|
+
"default": "{}",
|
|
890
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
891
|
+
"attribute": "lapisFilter"
|
|
892
|
+
},
|
|
824
893
|
{
|
|
825
894
|
"kind": "field",
|
|
826
895
|
"name": "width",
|
|
@@ -845,7 +914,7 @@
|
|
|
845
914
|
"events": [
|
|
846
915
|
{
|
|
847
916
|
"type": {
|
|
848
|
-
"text": "CustomEvent<Record<string, string>>"
|
|
917
|
+
"text": "CustomEvent<Record<string, string | undefined>>"
|
|
849
918
|
},
|
|
850
919
|
"description": "Fired when a value from the datalist is selected or when a valid value is typed into the field. The `details` of this event contain an object with all `fields` as keys and the corresponding values as values, even if they are `undefined`. Example: ``` { continent: \"Asia\", country: \"China\", city: \"Beijing\", district: undefined, } ```",
|
|
851
920
|
"name": "gs-location-changed"
|
|
@@ -855,7 +924,7 @@
|
|
|
855
924
|
{
|
|
856
925
|
"name": "value",
|
|
857
926
|
"type": {
|
|
858
|
-
"text": "Record<string, string |
|
|
927
|
+
"text": "Record<string, string | undefined> | undefined"
|
|
859
928
|
},
|
|
860
929
|
"default": "undefined",
|
|
861
930
|
"description": "The initial value to use for this location filter.",
|
|
@@ -870,6 +939,15 @@
|
|
|
870
939
|
"description": "Required.\n\nThe fields to display in the location filter, in hierarchical order.\nThe top-level field should be the first entry in the array.\nThis component assumes that the values for each field form a strict hierarchy\n(e.g., `fields = ['continent', 'country', 'city']`).",
|
|
871
940
|
"fieldName": "fields"
|
|
872
941
|
},
|
|
942
|
+
{
|
|
943
|
+
"name": "lapisFilter",
|
|
944
|
+
"type": {
|
|
945
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
946
|
+
},
|
|
947
|
+
"default": "{}",
|
|
948
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
949
|
+
"fieldName": "lapisFilter"
|
|
950
|
+
},
|
|
873
951
|
{
|
|
874
952
|
"name": "width",
|
|
875
953
|
"type": {
|
|
@@ -1084,7 +1162,7 @@
|
|
|
1084
1162
|
"type": {
|
|
1085
1163
|
"text": "Meta<Required<TextInputProps>>"
|
|
1086
1164
|
},
|
|
1087
|
-
"default": "{ title: 'Input/Text input', component: 'gs-text-input', parameters: withComponentDocs({ actions: { handles: ['gs-text-input-changed', ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'hosts', url: AGGREGATED_ENDPOINT, body: { fields: ['host'], }, }, response: { status: 200, body: data, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), argTypes: { lapisField: { control: { type: 'text', }, }, placeholderText: { control: { type: 'text', }, },
|
|
1165
|
+
"default": "{ title: 'Input/Text input', component: 'gs-text-input', parameters: withComponentDocs({ actions: { handles: ['gs-text-input-changed', ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'hosts', url: AGGREGATED_ENDPOINT, body: { fields: ['host'], country: 'Germany', }, }, response: { status: 200, body: data, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), argTypes: { lapisField: { control: { type: 'text', }, }, placeholderText: { control: { type: 'text', }, }, value: { control: { type: 'text', }, }, width: { control: { type: 'text', }, }, lapisFilter: { control: { type: 'object', }, }, }, tags: ['autodocs'], }"
|
|
1088
1166
|
},
|
|
1089
1167
|
{
|
|
1090
1168
|
"kind": "variable",
|
|
@@ -1092,7 +1170,7 @@
|
|
|
1092
1170
|
"type": {
|
|
1093
1171
|
"text": "StoryObj<Required<TextInputProps>>"
|
|
1094
1172
|
},
|
|
1095
|
-
"default": "{ render: (args) => { return html` <gs-app lapis=\"${LAPIS_URL}\"> <div class=\"max-w-screen-lg\"> <gs-text-input .lapisField=${args.lapisField} .placeholderText=${args.placeholderText} .
|
|
1173
|
+
"default": "{ render: (args) => { return html` <gs-app lapis=\"${LAPIS_URL}\"> <div class=\"max-w-screen-lg\"> <gs-text-input .lapisField=${args.lapisField} .lapisFilter=${args.lapisFilter} .placeholderText=${args.placeholderText} .value=${args.value} .width=${args.width} ></gs-text-input> </div> </gs-app>`; }, args: { lapisField: 'host', lapisFilter: { country: 'Germany' }, placeholderText: 'Enter host name', value: 'Homo sapiens', width: '100%', }, }"
|
|
1096
1174
|
},
|
|
1097
1175
|
{
|
|
1098
1176
|
"kind": "variable",
|
|
@@ -1100,7 +1178,7 @@
|
|
|
1100
1178
|
"type": {
|
|
1101
1179
|
"text": "StoryObj<Required<TextInputProps>>"
|
|
1102
1180
|
},
|
|
1103
|
-
"default": "{ ...Default, play: async ({ canvasElement, step }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-text-input'); const inputField = () => canvas.getByPlaceholderText('Enter host name'); const listenerMock = fn(); await step('Setup event listener mock', async () => { canvasElement.addEventListener('gs-text-input-changed', listenerMock); }); await step('wait until data is loaded', async () => { await waitFor(() => { return expect(inputField()).toBeEnabled(); }); }); await step('Enters an invalid host name', async () => { await userEvent.type(inputField(), 'notInList'); await expect(listenerMock).not.toHaveBeenCalled(); }); await step('Empty input', async () => { await userEvent.type(inputField(), '{backspace>9/}'); }); await step('Enter a valid host name', async () => { await userEvent.type(inputField(), 'Homo s'); const dropdownOption = await canvas.findByText('Homo sapiens'); await userEvent.click(dropdownOption); }); await step('Verify event is fired with correct detail', async () => { await waitFor(() => { expect(listenerMock).toHaveBeenCalledWith( expect.objectContaining({ detail: { host: 'Homo sapiens', }, }), ); }); }); await step('Remove initial value', async () => { await fireEvent.click(canvas.getByRole('button', { name: 'clear selection' })); await expect(listenerMock).toHaveBeenCalledWith( expect.objectContaining({ detail: { host: undefined, }, }), ); }); await step('Empty input', async () => { inputField().blur(); await expect(listenerMock.mock.calls.at(-1)![0].detail).toStrictEqual({ host: undefined, }); }); }, args: { ...Default.args,
|
|
1181
|
+
"default": "{ ...Default, play: async ({ canvasElement, step }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-text-input'); const inputField = () => canvas.getByPlaceholderText('Enter host name'); const listenerMock = fn(); await step('Setup event listener mock', async () => { canvasElement.addEventListener('gs-text-input-changed', listenerMock); }); await step('wait until data is loaded', async () => { await waitFor(() => { return expect(inputField()).toBeEnabled(); }); }); await step('Enters an invalid host name', async () => { await userEvent.type(inputField(), 'notInList'); await expect(listenerMock).not.toHaveBeenCalled(); }); await step('Empty input', async () => { await userEvent.type(inputField(), '{backspace>9/}'); }); await step('Enter a valid host name', async () => { await userEvent.type(inputField(), 'Homo s'); const dropdownOption = await canvas.findByText('Homo sapiens'); await userEvent.click(dropdownOption); }); await step('Verify event is fired with correct detail', async () => { await waitFor(() => { expect(listenerMock).toHaveBeenCalledWith( expect.objectContaining({ detail: { host: 'Homo sapiens', }, }), ); }); }); await step('Remove initial value', async () => { await fireEvent.click(canvas.getByRole('button', { name: 'clear selection' })); await expect(listenerMock).toHaveBeenCalledWith( expect.objectContaining({ detail: { host: undefined, }, }), ); }); await step('Empty input', async () => { inputField().blur(); await expect(listenerMock.mock.calls.at(-1)![0].detail).toStrictEqual({ host: undefined, }); }); }, args: { ...Default.args, value: '', }, }"
|
|
1104
1182
|
}
|
|
1105
1183
|
],
|
|
1106
1184
|
"exports": [
|
|
@@ -1141,13 +1219,13 @@
|
|
|
1141
1219
|
"members": [
|
|
1142
1220
|
{
|
|
1143
1221
|
"kind": "field",
|
|
1144
|
-
"name": "
|
|
1222
|
+
"name": "value",
|
|
1145
1223
|
"type": {
|
|
1146
1224
|
"text": "string | undefined"
|
|
1147
1225
|
},
|
|
1148
1226
|
"default": "undefined",
|
|
1149
1227
|
"description": "The initial value to use for this text input.",
|
|
1150
|
-
"attribute": "
|
|
1228
|
+
"attribute": "value"
|
|
1151
1229
|
},
|
|
1152
1230
|
{
|
|
1153
1231
|
"kind": "field",
|
|
@@ -1159,6 +1237,16 @@
|
|
|
1159
1237
|
"description": "Required.\n\nThe LAPIS field name to use for this text input.\nThe field must exist on this LAPIS instance.",
|
|
1160
1238
|
"attribute": "lapisField"
|
|
1161
1239
|
},
|
|
1240
|
+
{
|
|
1241
|
+
"kind": "field",
|
|
1242
|
+
"name": "lapisFilter",
|
|
1243
|
+
"type": {
|
|
1244
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
1245
|
+
},
|
|
1246
|
+
"default": "{}",
|
|
1247
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
1248
|
+
"attribute": "lapisFilter"
|
|
1249
|
+
},
|
|
1162
1250
|
{
|
|
1163
1251
|
"kind": "field",
|
|
1164
1252
|
"name": "placeholderText",
|
|
@@ -1183,7 +1271,7 @@
|
|
|
1183
1271
|
"events": [
|
|
1184
1272
|
{
|
|
1185
1273
|
"type": {
|
|
1186
|
-
"text": "CustomEvent<Record<string, string>>"
|
|
1274
|
+
"text": "CustomEvent<Record<string, string | undefined>>"
|
|
1187
1275
|
},
|
|
1188
1276
|
"description": "Fired when the input field is changed. The `details` of this event contain an object with the `lapisField` as key and the input value as value. Example: ``` { \"host\": \"Homo sapiens\" } ```",
|
|
1189
1277
|
"name": "gs-text-input-changed"
|
|
@@ -1191,13 +1279,13 @@
|
|
|
1191
1279
|
],
|
|
1192
1280
|
"attributes": [
|
|
1193
1281
|
{
|
|
1194
|
-
"name": "
|
|
1282
|
+
"name": "value",
|
|
1195
1283
|
"type": {
|
|
1196
1284
|
"text": "string | undefined"
|
|
1197
1285
|
},
|
|
1198
1286
|
"default": "undefined",
|
|
1199
1287
|
"description": "The initial value to use for this text input.",
|
|
1200
|
-
"fieldName": "
|
|
1288
|
+
"fieldName": "value"
|
|
1201
1289
|
},
|
|
1202
1290
|
{
|
|
1203
1291
|
"name": "lapisField",
|
|
@@ -1208,6 +1296,15 @@
|
|
|
1208
1296
|
"description": "Required.\n\nThe LAPIS field name to use for this text input.\nThe field must exist on this LAPIS instance.",
|
|
1209
1297
|
"fieldName": "lapisField"
|
|
1210
1298
|
},
|
|
1299
|
+
{
|
|
1300
|
+
"name": "lapisFilter",
|
|
1301
|
+
"type": {
|
|
1302
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
1303
|
+
},
|
|
1304
|
+
"default": "{}",
|
|
1305
|
+
"description": "The filter that is used to fetch the available the autocomplete options.\nIf not set it fetches all available options.\nIt must be a valid LAPIS filter object.",
|
|
1306
|
+
"fieldName": "lapisFilter"
|
|
1307
|
+
},
|
|
1211
1308
|
{
|
|
1212
1309
|
"name": "placeholderText",
|
|
1213
1310
|
"type": {
|
|
@@ -3856,6 +3953,176 @@
|
|
|
3856
3953
|
}
|
|
3857
3954
|
]
|
|
3858
3955
|
},
|
|
3956
|
+
{
|
|
3957
|
+
"kind": "javascript-module",
|
|
3958
|
+
"path": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts",
|
|
3959
|
+
"declarations": [
|
|
3960
|
+
{
|
|
3961
|
+
"kind": "variable",
|
|
3962
|
+
"name": "meta",
|
|
3963
|
+
"type": {
|
|
3964
|
+
"text": "Meta<Required<WastewaterMutationsOverTimeProps>>"
|
|
3965
|
+
},
|
|
3966
|
+
"default": "{ title: 'Wastewater visualization/Wastewater mutations over time', component: 'gs-wastewater-mutations-over-time', argTypes: { lapisFilter: { control: 'object' }, sequenceType: { options: ['nucleotide', 'amino acid'], control: { type: 'radio' }, }, width: { control: 'text' }, height: { control: 'text' }, }, args: { lapisFilter: { versionStatus: 'LATEST_VERSION', isRevocation: false }, sequenceType: 'nucleotide', width: '100%', height: '700px', }, parameters: withComponentDocs({ componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, fetchMock: {}, }), tags: ['autodocs'], }"
|
|
3967
|
+
},
|
|
3968
|
+
{
|
|
3969
|
+
"kind": "variable",
|
|
3970
|
+
"name": "WastewaterMutationsOverTime",
|
|
3971
|
+
"type": {
|
|
3972
|
+
"text": "StoryObj<Required<WastewaterMutationsOverTimeProps>>"
|
|
3973
|
+
},
|
|
3974
|
+
"default": "{ render: (args) => html` <gs-app lapis=\"${WISE_LAPIS_URL}\"> <gs-wastewater-mutations-over-time .lapisFilter=${args.lapisFilter} .sequenceType=${args.sequenceType} .width=${args.width} .height=${args.height} ></gs-wastewater-mutations-over-time> </gs-app> `, parameters: { fetchMock: { mocks: [ { matcher: { name: 'details', url: WISE_DETAILS_ENDPOINT, body: { fields: ['date', 'location', 'nucleotideMutationFrequency', 'aminoAcidMutationFrequency'], versionStatus: 'LATEST_VERSION', isRevocation: false, }, }, response: { status: 200, body: details, }, }, ], }, }, }"
|
|
3975
|
+
}
|
|
3976
|
+
],
|
|
3977
|
+
"exports": [
|
|
3978
|
+
{
|
|
3979
|
+
"kind": "js",
|
|
3980
|
+
"name": "default",
|
|
3981
|
+
"declaration": {
|
|
3982
|
+
"name": "meta",
|
|
3983
|
+
"module": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts"
|
|
3984
|
+
}
|
|
3985
|
+
},
|
|
3986
|
+
{
|
|
3987
|
+
"kind": "js",
|
|
3988
|
+
"name": "WastewaterMutationsOverTime",
|
|
3989
|
+
"declaration": {
|
|
3990
|
+
"name": "WastewaterMutationsOverTime",
|
|
3991
|
+
"module": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts"
|
|
3992
|
+
}
|
|
3993
|
+
}
|
|
3994
|
+
]
|
|
3995
|
+
},
|
|
3996
|
+
{
|
|
3997
|
+
"kind": "javascript-module",
|
|
3998
|
+
"path": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx",
|
|
3999
|
+
"declarations": [
|
|
4000
|
+
{
|
|
4001
|
+
"kind": "class",
|
|
4002
|
+
"description": "## Context\n\nThis component displays mutations for Swiss wastewater data generated within the WISE consortium. It is designed\nonly for this purpose and is not designed to be reused outside the WISE project.\n\nIt relies on a LAPIS instance that has the fields `nucleotideMutationFrequency` and `aminoAcidMutationFrequency`.\nThose fields are expected to be JSON strings of the format `{ [mutation]: frequency | null }`\n(e.g. `{ \"A123T\": 0.5, \"C456G\": 0.7, \"T789G\": null }`).\n\nThe component will stratify by `location`.\nEvery location will be rendered in a separate tab.\nThe content of the tab is a \"mutations over time\" grid, similar to the one used in the `gs-mutations-over-time` component.\n\nThis component also assumes that the LAPIS instance has the field `date` which can be used for the time axis.",
|
|
4003
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4004
|
+
"members": [
|
|
4005
|
+
{
|
|
4006
|
+
"kind": "field",
|
|
4007
|
+
"name": "lapisFilter",
|
|
4008
|
+
"type": {
|
|
4009
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
4010
|
+
},
|
|
4011
|
+
"default": "{}",
|
|
4012
|
+
"description": "Required.\n\nLAPIS filter to select the displayed data.",
|
|
4013
|
+
"attribute": "lapisFilter"
|
|
4014
|
+
},
|
|
4015
|
+
{
|
|
4016
|
+
"kind": "field",
|
|
4017
|
+
"name": "sequenceType",
|
|
4018
|
+
"type": {
|
|
4019
|
+
"text": "'nucleotide' | 'amino acid'"
|
|
4020
|
+
},
|
|
4021
|
+
"default": "'nucleotide'",
|
|
4022
|
+
"description": "Required.\n\nWhether to display nucleotide or amino acid mutations.",
|
|
4023
|
+
"attribute": "sequenceType"
|
|
4024
|
+
},
|
|
4025
|
+
{
|
|
4026
|
+
"kind": "field",
|
|
4027
|
+
"name": "width",
|
|
4028
|
+
"type": {
|
|
4029
|
+
"text": "string"
|
|
4030
|
+
},
|
|
4031
|
+
"default": "'100%'",
|
|
4032
|
+
"description": "The width of the component.\n\nVisit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.",
|
|
4033
|
+
"attribute": "width"
|
|
4034
|
+
},
|
|
4035
|
+
{
|
|
4036
|
+
"kind": "field",
|
|
4037
|
+
"name": "height",
|
|
4038
|
+
"type": {
|
|
4039
|
+
"text": "string"
|
|
4040
|
+
},
|
|
4041
|
+
"default": "'700px'",
|
|
4042
|
+
"description": "The height of the component.\n\nVisit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.",
|
|
4043
|
+
"attribute": "height"
|
|
4044
|
+
}
|
|
4045
|
+
],
|
|
4046
|
+
"attributes": [
|
|
4047
|
+
{
|
|
4048
|
+
"name": "lapisFilter",
|
|
4049
|
+
"type": {
|
|
4050
|
+
"text": "Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n }"
|
|
4051
|
+
},
|
|
4052
|
+
"default": "{}",
|
|
4053
|
+
"description": "Required.\n\nLAPIS filter to select the displayed data.",
|
|
4054
|
+
"fieldName": "lapisFilter"
|
|
4055
|
+
},
|
|
4056
|
+
{
|
|
4057
|
+
"name": "sequenceType",
|
|
4058
|
+
"type": {
|
|
4059
|
+
"text": "'nucleotide' | 'amino acid'"
|
|
4060
|
+
},
|
|
4061
|
+
"default": "'nucleotide'",
|
|
4062
|
+
"description": "Required.\n\nWhether to display nucleotide or amino acid mutations.",
|
|
4063
|
+
"fieldName": "sequenceType"
|
|
4064
|
+
},
|
|
4065
|
+
{
|
|
4066
|
+
"name": "width",
|
|
4067
|
+
"type": {
|
|
4068
|
+
"text": "string"
|
|
4069
|
+
},
|
|
4070
|
+
"default": "'100%'",
|
|
4071
|
+
"description": "The width of the component.\n\nVisit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.",
|
|
4072
|
+
"fieldName": "width"
|
|
4073
|
+
},
|
|
4074
|
+
{
|
|
4075
|
+
"name": "height",
|
|
4076
|
+
"type": {
|
|
4077
|
+
"text": "string"
|
|
4078
|
+
},
|
|
4079
|
+
"default": "'700px'",
|
|
4080
|
+
"description": "The height of the component.\n\nVisit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.",
|
|
4081
|
+
"fieldName": "height"
|
|
4082
|
+
}
|
|
4083
|
+
],
|
|
4084
|
+
"superclass": {
|
|
4085
|
+
"name": "PreactLitAdapterWithGridJsStyles",
|
|
4086
|
+
"module": "/src/web-components/PreactLitAdapterWithGridJsStyles"
|
|
4087
|
+
},
|
|
4088
|
+
"tagName": "gs-wastewater-mutations-over-time",
|
|
4089
|
+
"customElement": true
|
|
4090
|
+
}
|
|
4091
|
+
],
|
|
4092
|
+
"exports": [
|
|
4093
|
+
{
|
|
4094
|
+
"kind": "js",
|
|
4095
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4096
|
+
"declaration": {
|
|
4097
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4098
|
+
"module": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx"
|
|
4099
|
+
}
|
|
4100
|
+
},
|
|
4101
|
+
{
|
|
4102
|
+
"kind": "custom-element-definition",
|
|
4103
|
+
"name": "gs-wastewater-mutations-over-time",
|
|
4104
|
+
"declaration": {
|
|
4105
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4106
|
+
"module": "src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx"
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
]
|
|
4110
|
+
},
|
|
4111
|
+
{
|
|
4112
|
+
"kind": "javascript-module",
|
|
4113
|
+
"path": "src/web-components/wastewaterVisualization/index.ts",
|
|
4114
|
+
"declarations": [],
|
|
4115
|
+
"exports": [
|
|
4116
|
+
{
|
|
4117
|
+
"kind": "js",
|
|
4118
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4119
|
+
"declaration": {
|
|
4120
|
+
"name": "WastewaterMutationsOverTimeComponent",
|
|
4121
|
+
"module": "./gs-wastewater-mutations-over-time"
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
]
|
|
4125
|
+
},
|
|
3859
4126
|
{
|
|
3860
4127
|
"kind": "javascript-module",
|
|
3861
4128
|
"path": "src/web-components/withinShadowRoot.story.ts",
|
|
@@ -10,6 +10,7 @@ const namedLapisFilterSchema = z.object({
|
|
|
10
10
|
lapisFilter: lapisFilterSchema,
|
|
11
11
|
displayName: z.string()
|
|
12
12
|
});
|
|
13
|
+
const lapisLocationFilterSchema = z.record(z.union([z.string(), z.undefined()]));
|
|
13
14
|
const temporalGranularitySchema = z.union([
|
|
14
15
|
z.literal("day"),
|
|
15
16
|
z.literal("week"),
|
|
@@ -105,12 +106,33 @@ class LocationChangedEvent extends CustomEvent {
|
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
}
|
|
109
|
+
class TextInputChangedEvent extends CustomEvent {
|
|
110
|
+
constructor(detail) {
|
|
111
|
+
super("gs-text-input-changed", {
|
|
112
|
+
detail,
|
|
113
|
+
bubbles: true,
|
|
114
|
+
composed: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
class LineageFilterChangedEvent extends CustomEvent {
|
|
119
|
+
constructor(detail) {
|
|
120
|
+
super("gs-lineage-filter-changed", {
|
|
121
|
+
detail,
|
|
122
|
+
bubbles: true,
|
|
123
|
+
composed: true
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
108
127
|
export {
|
|
109
128
|
DateRangeOptionChangedEvent as D,
|
|
110
129
|
LocationChangedEvent as L,
|
|
111
|
-
|
|
112
|
-
|
|
130
|
+
TextInputChangedEvent as T,
|
|
131
|
+
LineageFilterChangedEvent as a,
|
|
132
|
+
dateRangeOptionSchema as b,
|
|
133
|
+
toYYYYMMDD as c,
|
|
113
134
|
dateRangeOptionPresets as d,
|
|
135
|
+
lapisLocationFilterSchema as e,
|
|
114
136
|
lapisFilterSchema as l,
|
|
115
137
|
mutationsFilterSchema as m,
|
|
116
138
|
namedLapisFilterSchema as n,
|
|
@@ -118,4 +140,4 @@ export {
|
|
|
118
140
|
temporalGranularitySchema as t,
|
|
119
141
|
views as v
|
|
120
142
|
};
|
|
121
|
-
//# sourceMappingURL=
|
|
143
|
+
//# sourceMappingURL=LineageFilterChangedEvent-GedKNGFI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LineageFilterChangedEvent-GedKNGFI.js","sources":["../src/types.ts","../src/preact/dateRangeSelector/dateConversion.ts","../src/preact/dateRangeSelector/dateRangeOption.ts","../src/preact/locationFilter/LocationChangedEvent.ts","../src/preact/textInput/TextInputChangedEvent.ts","../src/preact/lineageFilter/LineageFilterChangedEvent.ts"],"sourcesContent":["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';\n\n/**\n * A date range option that can be used in the `gs-date-range-selector` 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 type DateRangeSelectOption = string | { dateFrom: string; dateTo: string };\n\nexport class DateRangeOptionChangedEvent extends CustomEvent<DateRangeSelectOption> {\n constructor(detail: DateRangeSelectOption) {\n super('gs-date-range-option-changed', {\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-selector` 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';\n\nexport class LocationChangedEvent extends CustomEvent<LapisLocationFilter> {\n constructor(detail: LapisLocationFilter) {\n super('gs-location-changed', {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n","type LapisTextFilter = Record<string, string | undefined>;\n\nexport class TextInputChangedEvent extends CustomEvent<LapisTextFilter> {\n constructor(detail: LapisTextFilter) {\n super('gs-text-input-changed', {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n","type LapisLineageFilter = Record<string, string | undefined>;\n\nexport class LineageFilterChangedEvent extends CustomEvent<LapisLineageFilter> {\n constructor(detail: LapisLineageFilter) {\n super('gs-lineage-filter-changed', {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n"],"names":[],"mappings":"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"}
|