@genspectrum/dashboard-components 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -596,6 +596,12 @@
596
596
  }
597
597
  ]
598
598
  },
599
+ {
600
+ "kind": "javascript-module",
601
+ "path": "src/web-components/input/gs-lineage-filter.spec.ts",
602
+ "declarations": [],
603
+ "exports": []
604
+ },
599
605
  {
600
606
  "kind": "javascript-module",
601
607
  "path": "src/web-components/input/gs-lineage-filter.stories.ts",
@@ -606,7 +612,7 @@
606
612
  "type": {
607
613
  "text": "Meta<Required<LineageFilterProps>>"
608
614
  },
609
- "default": "{ title: 'Input/Lineage filter', component: 'gs-lineage-filter', parameters: withComponentDocs({ actions: { handles: [gsEventNames.lineageFilterChanged, ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'pangoLineage', url: AGGREGATED_ENDPOINT, body: { fields: ['pangoLineage'], country: 'Germany', }, }, response: { status: 200, body: aggregatedData, }, }, { matcher: { name: 'lineageDefinition', url: lineageDefinitionEndpoint(LAPIS_URL, 'pangoLineage'), }, response: { status: 200, body: lineageDefinition, }, }, ], }, 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', }, }, hideCounts: { control: { type: 'boolean', }, }, }, }"
615
+ "default": "{ title: 'Input/Lineage filter', component: 'gs-lineage-filter', parameters: withComponentDocs({ actions: { handles: [gsEventNames.lineageFilterChanged, gsEventNames.lineageFilterMultiChanged, ...previewHandles], }, fetchMock: { mocks: [ { matcher: { name: 'pangoLineage', url: AGGREGATED_ENDPOINT, body: { fields: ['pangoLineage'], country: 'Germany', }, }, response: { status: 200, body: aggregatedData, }, }, { matcher: { name: 'lineageDefinition', url: lineageDefinitionEndpoint(LAPIS_URL, 'pangoLineage'), }, response: { status: 200, body: lineageDefinition, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], argTypes: { lapisField: { control: { type: 'select', }, options: ['host'], }, placeholderText: { control: { type: 'text', }, }, value: { control: { type: 'object', }, }, width: { control: { type: 'text', }, }, lapisFilter: { control: { type: 'object', }, }, hideCounts: { control: { type: 'boolean', }, }, multiSelect: { control: { type: 'boolean', }, }, }, }"
610
616
  },
611
617
  {
612
618
  "kind": "variable",
@@ -639,6 +645,14 @@
639
645
  "text": "StoryObj<Required<LineageFilterProps>>"
640
646
  },
641
647
  "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', () => { canvasElement.addEventListener(gsEventNames.lineageFilterChanged, 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*(677,146)' })); await waitFor(() => { return expect(listenerMock.mock.calls.at(-1)![0].detail).toStrictEqual({ pangoLineage: 'B.1.1.7*', }); }); }); }, args: { ...LineageFilter.args, value: '', }, }"
648
+ },
649
+ {
650
+ "kind": "variable",
651
+ "name": "MultiSelectMode",
652
+ "type": {
653
+ "text": "StoryObj<Required<LineageFilterProps>>"
654
+ },
655
+ "default": "{ ...Template, args: { ...Template.args, multiSelect: true, value: ['B.1.1.7', 'BA.5'], placeholderText: 'Select lineages', }, play: async ({ canvasElement }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-lineage-filter'); await waitFor(() => { return expect(canvas.getByPlaceholderText('Select lineages')).toBeVisible(); }); }, }"
642
656
  }
643
657
  ],
644
658
  "exports": [
@@ -681,6 +695,14 @@
681
695
  "name": "FiresEvent",
682
696
  "module": "src/web-components/input/gs-lineage-filter.stories.ts"
683
697
  }
698
+ },
699
+ {
700
+ "kind": "js",
701
+ "name": "MultiSelectMode",
702
+ "declaration": {
703
+ "name": "MultiSelectMode",
704
+ "module": "src/web-components/input/gs-lineage-filter.stories.ts"
705
+ }
684
706
  }
685
707
  ]
686
708
  },
@@ -690,17 +712,17 @@
690
712
  "declarations": [
691
713
  {
692
714
  "kind": "class",
693
- "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).",
715
+ "description": "## 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).\n\nWhen `multiSelect` is true, it allows selecting multiple lineages and displays them as removable chips.",
694
716
  "name": "LineageFilterComponent",
695
717
  "members": [
696
718
  {
697
719
  "kind": "field",
698
720
  "name": "value",
699
721
  "type": {
700
- "text": "string"
722
+ "text": "string | string[]"
701
723
  },
702
724
  "default": "''",
703
- "description": "The initial value to use for this lineage filter.",
725
+ "description": "The initial value to use for this lineage filter.\nCan be a string for single select mode or an array of strings (or comma-separated string) for multi-select mode.\nExamples: \"B.1.1.7\" or [\"B.1.1.7\", \"BA.5\"] or \"B.1.1.7,BA.5\"",
704
726
  "attribute": "value"
705
727
  },
706
728
  {
@@ -713,6 +735,16 @@
713
735
  "description": "Required.\n\nThe LAPIS field name to use for this lineage filter.\nThe field must exist on this LAPIS instance.",
714
736
  "attribute": "lapisField"
715
737
  },
738
+ {
739
+ "kind": "field",
740
+ "name": "multiSelect",
741
+ "type": {
742
+ "text": "boolean | undefined"
743
+ },
744
+ "default": "false",
745
+ "description": "Whether to enable multi-select mode.\nWhen true, allows selecting multiple lineages displayed as removable chips.\nDefaults to false.",
746
+ "attribute": "multiSelect"
747
+ },
716
748
  {
717
749
  "kind": "field",
718
750
  "name": "lapisFilter",
@@ -759,18 +791,25 @@
759
791
  "type": {
760
792
  "text": "CustomEvent<Record<string, string | undefined>>"
761
793
  },
762
- "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\" } ```",
794
+ "description": "Fired when the selection changes in single-select mode. The `details` of this event contain an object with the `lapisField` as key and the selected value as value. Example: ``` { \"pangoLineage\": \"B.1.1.7\" } ```",
763
795
  "name": "gs-lineage-filter-changed"
796
+ },
797
+ {
798
+ "type": {
799
+ "text": "CustomEvent<Record<string, string[] | undefined>>"
800
+ },
801
+ "description": "Fired when the selection changes in multi-select mode. The `details` of this event contain an object with the `lapisField` as key and an array of selected values. Example: ``` { \"pangoLineage\": [\"B.1.1.7\", \"BA.5\"] } ```",
802
+ "name": "gs-lineage-filter-multi-changed"
764
803
  }
765
804
  ],
766
805
  "attributes": [
767
806
  {
768
807
  "name": "value",
769
808
  "type": {
770
- "text": "string"
809
+ "text": "string | string[]"
771
810
  },
772
811
  "default": "''",
773
- "description": "The initial value to use for this lineage filter.",
812
+ "description": "The initial value to use for this lineage filter.\nCan be a string for single select mode or an array of strings (or comma-separated string) for multi-select mode.\nExamples: \"B.1.1.7\" or [\"B.1.1.7\", \"BA.5\"] or \"B.1.1.7,BA.5\"",
774
813
  "fieldName": "value"
775
814
  },
776
815
  {
@@ -782,6 +821,15 @@
782
821
  "description": "Required.\n\nThe LAPIS field name to use for this lineage filter.\nThe field must exist on this LAPIS instance.",
783
822
  "fieldName": "lapisField"
784
823
  },
824
+ {
825
+ "name": "multiSelect",
826
+ "type": {
827
+ "text": "boolean | undefined"
828
+ },
829
+ "default": "false",
830
+ "description": "Whether to enable multi-select mode.\nWhen true, allows selecting multiple lineages displayed as removable chips.\nDefaults to false.",
831
+ "fieldName": "multiSelect"
832
+ },
785
833
  {
786
834
  "name": "lapisFilter",
787
835
  "type": {
@@ -6,6 +6,7 @@ const gsEventNames = {
6
6
  dateRangeOptionChanged: "gs-date-range-option-changed",
7
7
  mutationFilterChanged: "gs-mutation-filter-changed",
8
8
  lineageFilterChanged: "gs-lineage-filter-changed",
9
+ lineageFilterMultiChanged: "gs-lineage-filter-multi-changed",
9
10
  locationChanged: "gs-location-changed",
10
11
  textFilterChanged: "gs-text-filter-changed",
11
12
  numberRangeFilterChanged: "gs-number-range-filter-changed",
@@ -159,6 +160,15 @@ class LineageFilterChangedEvent extends CustomEvent {
159
160
  });
160
161
  }
161
162
  }
163
+ class LineageMultiFilterChangedEvent extends CustomEvent {
164
+ constructor(detail) {
165
+ super(gsEventNames.lineageFilterMultiChanged, {
166
+ detail,
167
+ bubbles: true,
168
+ composed: true
169
+ });
170
+ }
171
+ }
162
172
  const numberRangeSchema = z.object({
163
173
  min: z.number().optional(),
164
174
  max: z.number().optional()
@@ -196,12 +206,13 @@ export {
196
206
  lapisLocationFilterSchema as h,
197
207
  mutationTypeSchema as i,
198
208
  mutationsFilterSchema as j,
199
- numberRangeSchema as k,
209
+ LineageMultiFilterChangedEvent as k,
200
210
  lapisFilterSchema as l,
201
211
  mutationType as m,
202
212
  namedLapisFilterSchema as n,
213
+ numberRangeSchema as o,
203
214
  sequenceTypeSchema as s,
204
215
  temporalGranularitySchema as t,
205
216
  views as v
206
217
  };
207
- //# sourceMappingURL=NumberRangeFilterChangedEvent-BnPI-Asz.js.map
218
+ //# sourceMappingURL=NumberRangeFilterChangedEvent-Cdtcp9YL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumberRangeFilterChangedEvent-Cdtcp9YL.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 lineageFilterMultiChanged: 'gs-lineage-filter-multi-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(), z.null()]));\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 SubstitutionOrDeletionOrInsertion = 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\nexport const mutationType = {\n nucleotideMutations: 'nucleotideMutations',\n nucleotideInsertions: 'nucleotideInsertions',\n aminoAcidMutations: 'aminoAcidMutations',\n aminoAcidInsertions: 'aminoAcidInsertions',\n} as const;\n\nexport const mutationTypeSchema = z.enum([\n mutationType.nucleotideMutations,\n mutationType.nucleotideInsertions,\n mutationType.aminoAcidMutations,\n mutationType.aminoAcidInsertions,\n]);\n\nexport type MutationType = z.infer<typeof mutationTypeSchema>;\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 */\n dateFrom: z.string().date().optional(),\n /**\n * The end date of the date range in the format `YYYY-MM-DD`.\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\ntype DateRangeOptionPresets = {\n last2Weeks: DateRangeOption;\n lastMonth: DateRangeOption;\n last2Months: DateRangeOption;\n last3Months: DateRangeOption;\n last6Months: DateRangeOption;\n lastYear: DateRangeOption;\n};\n\nlet dateRangeOptionsPresetsCacheDate: string | null = null;\nlet dateRangeOptionPresetsCache: DateRangeOptionPresets | null = null;\n\n/**\n * Presets for the `gs-date-range-filter` component that can be used as `dateRangeOptions`.\n */\nexport const dateRangeOptionPresets = (): DateRangeOptionPresets => {\n const today = new Date();\n const todayString = new Date().toISOString().slice(0, 10);\n\n if (\n dateRangeOptionPresetsCache === null ||\n dateRangeOptionsPresetsCacheDate === null ||\n dateRangeOptionsPresetsCacheDate !== todayString\n ) {\n dateRangeOptionsPresetsCacheDate = todayString;\n\n const twoWeeksAgo = new Date();\n twoWeeksAgo.setDate(today.getDate() - 14);\n\n const lastMonth = new Date(today);\n lastMonth.setMonth(today.getMonth() - 1);\n\n const last2Months = new Date(today);\n last2Months.setMonth(today.getMonth() - 2);\n\n const last3Months = new Date(today);\n last3Months.setMonth(today.getMonth() - 3);\n\n const last6Months = new Date(today);\n last6Months.setMonth(today.getMonth() - 6);\n\n const lastYear = new Date(today);\n lastYear.setFullYear(today.getFullYear() - 1);\n\n dateRangeOptionPresetsCache = {\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 };\n }\n\n return dateRangeOptionPresetsCache;\n};\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>;\ntype LapisLineageMultiFilter = 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\nexport class LineageMultiFilterChangedEvent extends CustomEvent<LapisLineageMultiFilter> {\n constructor(detail: LapisLineageMultiFilter) {\n super(gsEventNames.lineageFilterMultiChanged, {\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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"}
@@ -275,7 +275,6 @@ export declare class GenomeDataViewerComponent extends PreactLitAdapter {
275
275
  }
276
276
 
277
277
  /**
278
- *
279
278
  * ## Context
280
279
  *
281
280
  * This component provides a text input field to filter by lineages.
@@ -286,21 +285,35 @@ export declare class GenomeDataViewerComponent extends PreactLitAdapter {
286
285
  * and provides an autocomplete list with the available values of the lineage and sublineage queries
287
286
  * (a `*` appended to the lineage value).
288
287
  *
288
+ * When `multiSelect` is true, it allows selecting multiple lineages and displays them as removable chips.
289
+ *
289
290
  * @fires {CustomEvent<Record<string, string | undefined>>} gs-lineage-filter-changed
290
- * Fired when the input field is changed.
291
- * The `details` of this event contain an object with the `lapisField` as key and the input value as value.
291
+ * Fired when the selection changes in single-select mode.
292
+ * The `details` of this event contain an object with the `lapisField` as key and the selected value as value.
292
293
  * Example:
293
294
  * ```
294
295
  * {
295
296
  * "pangoLineage": "B.1.1.7"
296
297
  * }
297
- * ```
298
+ * ```
299
+ *
300
+ * @fires {CustomEvent<Record<string, string[] | undefined>>} gs-lineage-filter-multi-changed
301
+ * Fired when the selection changes in multi-select mode.
302
+ * The `details` of this event contain an object with the `lapisField` as key and an array of selected values.
303
+ * Example:
304
+ * ```
305
+ * {
306
+ * "pangoLineage": ["B.1.1.7", "BA.5"]
307
+ * }
308
+ * ```
298
309
  */
299
310
  export declare class LineageFilterComponent extends PreactLitAdapter {
300
311
  /**
301
312
  * The initial value to use for this lineage filter.
313
+ * Can be a string for single select mode or an array of strings (or comma-separated string) for multi-select mode.
314
+ * Examples: "B.1.1.7" or ["B.1.1.7", "BA.5"] or "B.1.1.7,BA.5"
302
315
  */
303
- value: string;
316
+ value: string | string[];
304
317
  /**
305
318
  * Required.
306
319
  *
@@ -308,6 +321,12 @@ export declare class LineageFilterComponent extends PreactLitAdapter {
308
321
  * The field must exist on this LAPIS instance.
309
322
  */
310
323
  lapisField: string;
324
+ /**
325
+ * Whether to enable multi-select mode.
326
+ * When true, allows selecting multiple lineages displayed as removable chips.
327
+ * Defaults to false.
328
+ */
329
+ multiSelect: boolean | undefined;
311
330
  /**
312
331
  * The filter that is used to fetch the available the autocomplete options.
313
332
  * If not set it fetches all available options.
@@ -1685,7 +1704,7 @@ declare global {
1685
1704
 
1686
1705
  declare global {
1687
1706
  interface HTMLElementTagNameMap {
1688
- 'gs-mutations': MutationsComponent;
1707
+ 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
1689
1708
  }
1690
1709
  }
1691
1710
 
@@ -1693,7 +1712,7 @@ declare global {
1693
1712
  declare global {
1694
1713
  namespace JSX {
1695
1714
  interface IntrinsicElements {
1696
- 'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1715
+ 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1697
1716
  }
1698
1717
  }
1699
1718
  }
@@ -1701,7 +1720,7 @@ declare global {
1701
1720
 
1702
1721
  declare global {
1703
1722
  interface HTMLElementTagNameMap {
1704
- 'gs-prevalence-over-time': PrevalenceOverTimeComponent;
1723
+ 'gs-mutations': MutationsComponent;
1705
1724
  }
1706
1725
  }
1707
1726
 
@@ -1709,7 +1728,7 @@ declare global {
1709
1728
  declare global {
1710
1729
  namespace JSX {
1711
1730
  interface IntrinsicElements {
1712
- 'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1731
+ 'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1713
1732
  }
1714
1733
  }
1715
1734
  }
@@ -1811,22 +1830,6 @@ declare global {
1811
1830
  }
1812
1831
 
1813
1832
 
1814
- declare global {
1815
- interface HTMLElementTagNameMap {
1816
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1817
- }
1818
- }
1819
-
1820
-
1821
- declare global {
1822
- namespace JSX {
1823
- interface IntrinsicElements {
1824
- 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1825
- }
1826
- }
1827
- }
1828
-
1829
-
1830
1833
  declare global {
1831
1834
  interface HTMLElementTagNameMap {
1832
1835
  'gs-date-range-filter': DateRangeFilterComponent;
@@ -1910,6 +1913,7 @@ declare global {
1910
1913
  }
1911
1914
  interface HTMLElementEventMap {
1912
1915
  [gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
1916
+ [gsEventNames.lineageFilterMultiChanged]: LineageMultiFilterChangedEvent;
1913
1917
  }
1914
1918
  }
1915
1919
 
@@ -1943,6 +1947,22 @@ declare global {
1943
1947
  }
1944
1948
 
1945
1949
 
1950
+ declare global {
1951
+ interface HTMLElementTagNameMap {
1952
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1953
+ }
1954
+ }
1955
+
1956
+
1957
+ declare global {
1958
+ namespace JSX {
1959
+ interface IntrinsicElements {
1960
+ 'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
1961
+ }
1962
+ }
1963
+ }
1964
+
1965
+
1946
1966
  declare module 'chart.js' {
1947
1967
  interface CartesianScaleTypeRegistry {
1948
1968
  logit: {