From 129ec05eb1faaaead16bd7bcb4b76e68b22b114e Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Thu, 11 Dec 2025 08:09:39 +0000 Subject: [PATCH 01/26] test(website): add a test that validates the wastewater config (#957) --- website/src/types/wastewaterConfig.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 website/src/types/wastewaterConfig.spec.ts diff --git a/website/src/types/wastewaterConfig.spec.ts b/website/src/types/wastewaterConfig.spec.ts new file mode 100644 index 000000000..e1b58e06b --- /dev/null +++ b/website/src/types/wastewaterConfig.spec.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from 'vitest'; + +import { wastewaterOrganismConfigs } from './wastewaterConfig'; + +describe.each(Object.entries(wastewaterOrganismConfigs))('wastewaterConfig %s', (_configName, config) => { + test('default resistance set name is valid', () => { + if (config.resistanceAnalysisModeEnabled) { + const resistanceSetNames = config.resistanceMutationSets.map((s) => s.name); + const defaultSetName = config.filterDefaults.resistance.resistanceSet; + expect(resistanceSetNames).include(defaultSetName); + } + }); +}); From 3e7252fdd2f215c3f40cd6db72fcd51815858a72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:19:04 +0100 Subject: [PATCH 02/26] chore(github-actions): bump actions/upload-artifact from 4 to 5 (#890) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 308b8bcad..1da9ea447 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -60,7 +60,7 @@ jobs: - name: Run Playwright tests run: npm run e2e - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 if: ${{ !cancelled() }} with: name: playwright-report From 0b751a0856fc11042c0a046e35a931810321381c Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Mon, 15 Dec 2025 10:44:59 +0100 Subject: [PATCH 03/26] chore(ci): consistently use latest version of node (#964) --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index dd947f1aa..69b3dbcdc 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: - node-version: 22 + node-version: lts/* - uses: actions/cache@v4 with: path: ~/.npm From ab3a7c1898fef63f5571951f60ea647d0a16718a Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Mon, 15 Dec 2025 10:28:13 +0000 Subject: [PATCH 04/26] feat(website): add time frame selector to W-ASAP variant explorer (#961) * feat(website): add time frame selector to W-ASAP variant explorer * feat(website): update text * refactor(website): use const object instead of string literals --- .../pageStateSelectors/wasap/InfoBlocks.tsx | 7 ++ .../VariantExplorerFilter.browser.spec.tsx | 1 + .../wasap/filters/VariantExplorerFilter.tsx | 17 ++++- .../views/wasap/useWasapPageData.ts | 26 ++++++- .../components/views/wasap/wasapPageConfig.ts | 10 +++ website/src/lapis/getMutations.spec.ts | 71 +++++++++++++++++++ website/src/lapis/getMutations.ts | 7 +- website/src/types/wastewaterConfig.ts | 6 +- .../WasapPageStateHandler.ts | 9 +++ 9 files changed, 147 insertions(+), 7 deletions(-) diff --git a/website/src/components/pageStateSelectors/wasap/InfoBlocks.tsx b/website/src/components/pageStateSelectors/wasap/InfoBlocks.tsx index e5bf4cdf4..e8505938d 100644 --- a/website/src/components/pageStateSelectors/wasap/InfoBlocks.tsx +++ b/website/src/components/pageStateSelectors/wasap/InfoBlocks.tsx @@ -97,6 +97,13 @@ export function DefineClinicalSignatureInfo() { indicate that either not all sequences of the variant have the mutation or not all sequences with the mutation belong to the variant (or both).

+ +

Time Frame

+

+ Time frame for sequence selection. Shorter windows reduce dominance of well-sequenced historical + variants, yielding higher Jaccard values for emerging variants with fewer clinical sequences. Use this + filter to exclude variants no longer in circulation when assessing significance of current mutations. +

); } diff --git a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.browser.spec.tsx b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.browser.spec.tsx index e2e23b58e..dca132918 100644 --- a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.browser.spec.tsx +++ b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.browser.spec.tsx @@ -17,6 +17,7 @@ describe('VariantExplorerFilter', () => { minProportion: 0.05, minCount: 10, minJaccard: 0.5, + timeFrame: 'all', }; it('calls setPageState when changing sequence type', async ({ routeMockers: { lapis } }) => { diff --git a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx index 86624a8c3..1186e83d8 100644 --- a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx +++ b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx @@ -1,6 +1,10 @@ import { Inset } from '../../../../styles/Inset'; import { GsLineageFilter } from '../../../genspectrum/GsLineageFilter'; -import type { WasapVariantFilter } from '../../../views/wasap/wasapPageConfig'; +import { + VARIANT_TIME_FRAME, + type VariantTimeFrame, + type WasapVariantFilter, +} from '../../../views/wasap/wasapPageConfig'; import { SelectorHeadline } from '../../SelectorHeadline'; import { DefineClinicalSignatureInfo } from '../InfoBlocks'; import { LabeledField } from '../utils/LabeledField'; @@ -70,6 +74,17 @@ export function VariantExplorerFilter({ step={0.01} onChange={(v) => setPageState({ ...pageState, minJaccard: v })} /> + + + ); diff --git a/website/src/components/views/wasap/useWasapPageData.ts b/website/src/components/views/wasap/useWasapPageData.ts index ef7f9297a..01082e8a7 100644 --- a/website/src/components/views/wasap/useWasapPageData.ts +++ b/website/src/components/views/wasap/useWasapPageData.ts @@ -1,7 +1,8 @@ -import type { CustomColumn } from '@genspectrum/dashboard-components/util'; +import type { CustomColumn, LapisFilter } from '@genspectrum/dashboard-components/util'; import { useQuery } from '@tanstack/react-query'; +import dayjs from 'dayjs'; -import type { WasapAnalysisFilter, WasapPageConfig } from './wasapPageConfig'; +import type { VariantTimeFrame, WasapAnalysisFilter, WasapPageConfig } from './wasapPageConfig'; import { getCladeLineages } from '../../../lapis/getCladeLineages'; import { getMutations, getMutationsForVariant } from '../../../lapis/getMutations'; @@ -47,6 +48,7 @@ async function fetchMutationSelection( analysis.minProportion, analysis.minCount, analysis.minJaccard, + getLapisFilterForTimeFrame(analysis.timeFrame, config.clinicalLapis.dateField), ).then((r) => ({ type: 'jaccard', mutationsWithScore: r })); case 'resistance': if (!config.resistanceAnalysisModeEnabled) { @@ -97,6 +99,26 @@ async function fetchMutationSelection( } } +function getLapisFilterForTimeFrame(timeFrame: VariantTimeFrame, dateFieldName: string): LapisFilter { + let fromDate = undefined; + switch (timeFrame) { + case 'all': + break; + case '6months': + fromDate = dayjs().subtract(6, 'month').format('YYYY-MM-DD'); + break; + case '3months': + fromDate = dayjs().subtract(3, 'month').format('YYYY-MM-DD'); + break; + } + if (fromDate === undefined) { + return {}; + } + return { + [`${dateFieldName}From`]: fromDate, + }; +} + /** * The W-ASAP page data consists of the mutations to display in the mutations-over-time component, * and the additional custom columns that might optionally be displayed. diff --git a/website/src/components/views/wasap/wasapPageConfig.ts b/website/src/components/views/wasap/wasapPageConfig.ts index bf5c0af01..9f93e6f21 100644 --- a/website/src/components/views/wasap/wasapPageConfig.ts +++ b/website/src/components/views/wasap/wasapPageConfig.ts @@ -71,6 +71,7 @@ type VariantAnalysisModeConfig = variantAnalysisModeEnabled: true; clinicalLapis: { lapisBaseUrl: string; + dateField: string; lineageField: string; }; filterDefaults: { @@ -157,6 +158,14 @@ export type WasapManualFilter = { mutations?: string[]; }; +export const VARIANT_TIME_FRAME = { + all: 'all', + sixMonths: '6months', + threeMonths: '3months', +} as const; + +export type VariantTimeFrame = (typeof VARIANT_TIME_FRAME)[keyof typeof VARIANT_TIME_FRAME]; + export type WasapVariantFilter = { mode: 'variant'; sequenceType: SequenceType; @@ -164,6 +173,7 @@ export type WasapVariantFilter = { minProportion: number; minCount: number; minJaccard: number; + timeFrame: VariantTimeFrame; }; export type WasapResistanceFilter = { diff --git a/website/src/lapis/getMutations.spec.ts b/website/src/lapis/getMutations.spec.ts index eeed16228..394b30edd 100644 --- a/website/src/lapis/getMutations.spec.ts +++ b/website/src/lapis/getMutations.spec.ts @@ -41,6 +41,28 @@ describe('getMutations', () => { expect(result).toEqual(['A123C', 'G234T']); }); + test('should return filtered mutations with multiple filters', async () => { + lapisRouteMocker.mockPostNucleotideMutations( + { minProportion: 0.1, pangoLineage: 'B.1.1.7', dateFrom: '2023-05-01' }, + { + data: [ + { mutation: 'A123C', count: 5 }, + { mutation: 'G234T', count: 2 }, + ], + }, + ); + + const result = await getMutations( + DUMMY_LAPIS_URL, + 'nucleotide', + { pangoLineage: 'B.1.1.7', dateFrom: '2023-05-01' }, + 0.1, + 3, + ); + + expect(result).toEqual(['A123C']); + }); + test('should throw on failed request', async () => { lapisRouteMocker.mockPostNucleotideMutations( { minProportion: 0.1 }, @@ -105,6 +127,50 @@ describe('getMutationsForVariant', () => { 0.1, 5, 0.9, + {}, + ); + + expect(result).toEqual([{ mutation: 'A2C', jaccardIndex: 1 }]); + }); + + test('should set date filter correctly', async () => { + // Setup: + // - Variant FOO has 20 sequences + // - A1C: in 20 FOO sequences, 40 total -> Jaccard = 20/(20+40-20) = 20/40 = 0.5 (excluded, < 0.9) + // - A2C: in 20 FOO sequences, 20 total -> Jaccard = 20/(20+20-20) = 20/20 = 1.0 (included, >= 0.9) + // - A3C: in 2 FOO sequences (excluded by minCount < 5) + lapisRouteMocker.mockPostAggregated({ pangoLineage: 'FOO', dateFrom: '2025-01-01' }, { data: [{ count: 20 }] }); + lapisRouteMocker.mockPostNucleotideMutationsMulti([ + { + body: { minProportion: 0.1, pangoLineage: 'FOO', dateFrom: '2025-01-01' }, + response: { + data: [ + { mutation: 'A1C', count: 20 }, + { mutation: 'A2C', count: 20 }, + { mutation: 'A3C', count: 2 }, + ], + }, + }, + { + body: { minProportion: 0, dateFrom: '2025-01-01' }, + response: { + data: [ + { mutation: 'A1C', count: 40 }, + { mutation: 'A2C', count: 20 }, + { mutation: 'A3C', count: 2 }, + ], + }, + }, + ]); + + const result = await getMutationsForVariant( + DUMMY_LAPIS_URL, + 'nucleotide', + { pangoLineage: 'FOO' }, + 0.1, + 5, + 0.9, + { dateFrom: '2025-01-01' }, ); expect(result).toEqual([{ mutation: 'A2C', jaccardIndex: 1 }]); @@ -137,6 +203,7 @@ describe('getMutationsForVariant', () => { 0.05, 5, 0.6, + {}, ); expect(result).toEqual([{ mutation: 'T100C', jaccardIndex: 10 / 15 }]); @@ -169,6 +236,7 @@ describe('getMutationsForVariant', () => { 0.01, 5, 0.01, + {}, ); expect(result).toEqual([]); @@ -211,6 +279,7 @@ describe('getMutationsForVariant', () => { 0.05, 5, 0.75, + {}, ); expect(result).toEqual([ @@ -247,6 +316,7 @@ describe('getMutationsForVariant', () => { 0.05, 5, 0.9, + {}, ); expect(result).toEqual([{ mutation: 'S:L452R', jaccardIndex: 1 }]); @@ -279,6 +349,7 @@ describe('getMutationsForVariant', () => { 0.05, 5, 0.9, + {}, ); expect(result).toEqual([{ mutation: 'S:L452R', jaccardIndex: 1 }]); diff --git a/website/src/lapis/getMutations.ts b/website/src/lapis/getMutations.ts index b82b22cb4..27b7ffe2a 100644 --- a/website/src/lapis/getMutations.ts +++ b/website/src/lapis/getMutations.ts @@ -54,18 +54,19 @@ export async function getMutationsForVariant( minProportion: number, minCount: number, minJaccardIndex: number, + dateFilter: LapisFilter | undefined, ) { return Promise.all([ // sequence counts WITH mutation and WITH lineage - getMutationsInternal(lapisUrl, mutationType, lineageFilter, minProportion).then((r) => + getMutationsInternal(lapisUrl, mutationType, { ...lineageFilter, ...dateFilter }, minProportion).then((r) => r.filter((item) => item.count >= minCount), ), // sequence counts WITH mutation (only) - getMutationsInternal(lapisUrl, mutationType, undefined, 0).then((r) => + getMutationsInternal(lapisUrl, mutationType, dateFilter, 0).then((r) => Object.fromEntries(r.map((item) => [item.mutation, item.count])), ), // sequence count WITH lineage (only) - getTotalCount(lapisUrl, lineageFilter), + getTotalCount(lapisUrl, { ...lineageFilter, ...dateFilter }), ]).then(([intersectionCounts, totalCounts, variantCount]) => intersectionCounts .map(({ mutation, count }) => ({ diff --git a/website/src/types/wastewaterConfig.ts b/website/src/types/wastewaterConfig.ts index 5fb496f42..3b9ac3c0b 100644 --- a/website/src/types/wastewaterConfig.ts +++ b/website/src/types/wastewaterConfig.ts @@ -1,7 +1,7 @@ import type { MutationAnnotation } from '@genspectrum/dashboard-components/util'; import { covidResistanceMutations } from '../components/views/wasap/resistanceMutations'; -import type { WasapPageConfig } from '../components/views/wasap/wasapPageConfig'; +import { VARIANT_TIME_FRAME, type WasapPageConfig } from '../components/views/wasap/wasapPageConfig'; export const wastewaterOrganisms = { covid: 'covid', @@ -33,6 +33,7 @@ export const wastewaterOrganismConfigs: Record { minProportion: Number(texts.minProportion ?? this.config.filterDefaults.variant.minProportion), minCount: Number(texts.minCount ?? this.config.filterDefaults.variant.minCount), minJaccard: Number(texts.minJaccard ?? this.config.filterDefaults.variant.minJaccard), + timeFrame: + (texts.timeFrame as VariantTimeFrame | undefined) ?? + this.config.filterDefaults.variant.timeFrame, }; break; case 'resistance': @@ -126,6 +130,7 @@ export class WasapPageStateHandler implements PageStateHandler { setSearchFromString(search, 'minProportion', String(analysis.minProportion)); setSearchFromString(search, 'minCount', String(analysis.minCount)); setSearchFromString(search, 'minJaccard', String(analysis.minJaccard)); + setSearchFromString(search, 'timeFrame', analysis.timeFrame); break; case 'resistance': setSearchFromString(search, 'resistanceSet', analysis.resistanceSet); @@ -195,6 +200,10 @@ function generateWasapFilterConfig(pageConfig: WasapPageConfig): BaselineFilterC type: 'text', lapisField: 'minJaccard', }, + { + type: 'text', + lapisField: 'timeFrame', + }, { type: 'text', lapisField: 'resistanceSet', From 5770669633729978ac5df6250cda3c289165c2be Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:08:52 +0100 Subject: [PATCH 05/26] chore(build): use node 24 in website Docker image (#967) --- Dockerfile_website | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile_website b/Dockerfile_website index 02b5f0977..823df38e9 100644 --- a/Dockerfile_website +++ b/Dockerfile_website @@ -1,6 +1,6 @@ # Dockerfile for the website # This is here so that the build context can access the backend config files -FROM node:22-alpine AS base +FROM node:24-alpine AS base WORKDIR /app COPY website/package.json website/package-lock.json website/patches ./ From a6ea5b9cbc63d4635889fe014d8df0e6fa4e3668 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:29:52 +0100 Subject: [PATCH 06/26] refactor(website): migrate compare variants data display to React (#963) * refactor(website): migrate compare variants data display to React resolves #960 * chore(website): update memo * chore(website): delete now unused component * chore(website): bump components --- website/package-lock.json | 163 +++++------------- website/package.json | 2 +- .../genspectrum/GsMutationComparison.astro | 25 --- .../genspectrum/GsMutationComparison.tsx | 35 ++++ .../GenericCompareVariantsDataDisplay.tsx | 72 ++++++++ .../GenericCompareVariantsPage.astro | 55 ++---- .../compareVariants/SelectVariants.astro | 14 -- .../views/compareVariants/SelectVariants.tsx | 18 ++ 8 files changed, 179 insertions(+), 205 deletions(-) delete mode 100644 website/src/components/genspectrum/GsMutationComparison.astro create mode 100644 website/src/components/genspectrum/GsMutationComparison.tsx create mode 100644 website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx delete mode 100644 website/src/components/views/compareVariants/SelectVariants.astro create mode 100644 website/src/components/views/compareVariants/SelectVariants.tsx diff --git a/website/package-lock.json b/website/package-lock.json index c4becf25d..14af7a826 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@astrojs/node": "^9.4.4", "@auth/core": "^0.37.4", - "@genspectrum/dashboard-components": "^1.11.1", + "@genspectrum/dashboard-components": "^1.12.0", "@tanstack/react-query": "^5.90.1", "astro": "^5.13.10", "auth-astro": "^4.2.0", @@ -110,7 +110,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@csstools/css-calc": "^2.1.2", "@csstools/css-color-parser": "^3.0.8", @@ -125,8 +124,7 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC", - "optional": true, - "peer": true + "optional": true }, "node_modules/@astrojs/check": { "version": "0.9.4", @@ -151,7 +149,8 @@ "version": "2.12.2", "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.12.2.tgz", "integrity": "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@astrojs/internal-helpers": { "version": "0.7.3", @@ -310,6 +309,7 @@ "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.37.4.tgz", "integrity": "sha512-HOXJwXWXQRhbBDHlMU0K/6FT1v+wjtzdKhsNg0ZN7/gne6XPsIrjZ4daMcFnbq0Z/vsAbYBinQhhua0d77v7qw==", "license": "ISC", + "peer": true, "dependencies": { "@panva/hkdf": "^1.2.1", "jose": "^5.9.6", @@ -365,6 +365,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -711,7 +712,6 @@ ], "license": "MIT-0", "optional": true, - "peer": true, "engines": { "node": ">=18" } @@ -733,7 +733,6 @@ ], "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=18" }, @@ -759,7 +758,6 @@ ], "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@csstools/color-helpers": "^5.0.2", "@csstools/css-calc": "^2.1.2" @@ -772,53 +770,6 @@ "@csstools/css-tokenizer": "^3.0.3" } }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -1513,9 +1464,9 @@ "license": "MIT" }, "node_modules/@genspectrum/dashboard-components": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@genspectrum/dashboard-components/-/dashboard-components-1.11.1.tgz", - "integrity": "sha512-nsyGuETthi5kAwb4shb21vPtobSq96bPfSvxLPTAFbNDH9wNsjC0X7otnKvQqKWxYNE3H4j561LZJinwqlRiiA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@genspectrum/dashboard-components/-/dashboard-components-1.12.0.tgz", + "integrity": "sha512-RW7j1Q1TqtP7dKR//BaIrvCfaQmVZ/Z5ZTWDUDs5o+uhliSQKlnCk44qALmxa3MsgFVcBK8st5s+S3kKqS+ZaQ==", "license": "AGPL-3.0-only", "dependencies": { "@floating-ui/dom": "^1.6.5", @@ -3209,6 +3160,7 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3468,6 +3420,7 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3479,6 +3432,7 @@ "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -3574,6 +3528,7 @@ "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/types": "8.44.1", @@ -3816,6 +3771,7 @@ "integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@testing-library/dom": "^10.4.0", "@testing-library/user-event": "^14.6.1", @@ -4070,6 +4026,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4094,7 +4051,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 14" } @@ -4436,6 +4392,7 @@ "resolved": "https://registry.npmjs.org/astro/-/astro-5.13.10.tgz", "integrity": "sha512-PgIrIYvrR7fCoSPPt1sGlpoYK/FNil1BwKazND1DyaZC7SbWLi9hdIHM3ApdrL2SWK7oiADRPw7cTn80UyDWqA==", "license": "MIT", + "peer": true, "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.7.3", @@ -4922,6 +4879,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -5113,6 +5071,7 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", "license": "MIT", + "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -5522,7 +5481,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@asamuzakjp/css-color": "^3.1.1", "rrweb-cssom": "^0.8.0" @@ -5581,16 +5539,6 @@ "node": ">=12" } }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -5638,7 +5586,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -5654,7 +5601,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=18" } @@ -5742,8 +5688,7 @@ "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/decode-named-character-reference": { "version": "1.2.0", @@ -6324,6 +6269,7 @@ "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7440,22 +7386,6 @@ "uncrypto": "^0.1.3" } }, - "node_modules/happy-dom": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.4.4.tgz", - "integrity": "sha512-/Pb0ctk3HTZ5xEL3BZ0hK1AqDSAUuRQitOmROPHhfUYEWpmTImwfD8vFDGADmMAX0JYgbcgxWoLFKtsWhcpuVA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "webidl-conversions": "^7.0.0", - "whatwg-mimetype": "^3.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -7746,7 +7676,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -7799,7 +7728,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -7815,7 +7743,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "agent-base": "^7.1.2", "debug": "4" @@ -7831,7 +7758,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -8255,8 +8181,7 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/is-regex": { "version": "1.2.1", @@ -8504,7 +8429,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", @@ -8546,7 +8470,6 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, - "peer": true, "dependencies": { "tldts": "^6.1.32" }, @@ -8561,7 +8484,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=18" } @@ -10174,6 +10096,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", @@ -10353,8 +10276,7 @@ "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/oauth4webapi": { "version": "3.3.0", @@ -11043,6 +10965,7 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -11072,6 +10995,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11088,6 +11012,7 @@ "integrity": "sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@astrojs/compiler": "^2.9.1", "prettier": "^3.0.0", @@ -11255,6 +11180,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -11351,6 +11277,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -11363,6 +11290,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -11831,6 +11759,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", "integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.6" }, @@ -11870,8 +11799,7 @@ "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/run-parallel": { "version": "1.2.0", @@ -11994,8 +11922,7 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/sass-formatter": { "version": "0.7.9", @@ -12014,7 +11941,6 @@ "dev": true, "license": "ISC", "optional": true, - "peer": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -12713,8 +12639,7 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/synckit": { "version": "0.9.2", @@ -12738,7 +12663,8 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.2.3", @@ -12860,7 +12786,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tldts-core": "^6.1.86" }, @@ -12874,8 +12799,7 @@ "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/tmp": { "version": "0.0.33", @@ -12974,7 +12898,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "punycode": "^2.3.1" }, @@ -13191,6 +13114,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13575,6 +13499,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -13706,6 +13631,7 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -14064,7 +13990,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -14089,7 +14014,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "engines": { "node": ">=12" } @@ -14101,7 +14025,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -14116,7 +14039,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=12" } @@ -14128,7 +14050,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" @@ -14287,6 +14208,7 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", "license": "MIT", + "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -14410,7 +14332,6 @@ "dev": true, "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=18" } @@ -14421,8 +14342,7 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/xxhash-wasm": { "version": "1.1.0", @@ -14703,6 +14623,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/website/package.json b/website/package.json index e67541fa6..c5a791dc5 100644 --- a/website/package.json +++ b/website/package.json @@ -25,7 +25,7 @@ "dependencies": { "@astrojs/node": "^9.4.4", "@auth/core": "^0.37.4", - "@genspectrum/dashboard-components": "^1.11.1", + "@genspectrum/dashboard-components": "^1.12.0", "@tanstack/react-query": "^5.90.1", "astro": "^5.13.10", "auth-astro": "^4.2.0", diff --git a/website/src/components/genspectrum/GsMutationComparison.astro b/website/src/components/genspectrum/GsMutationComparison.astro deleted file mode 100644 index edb4f07df..000000000 --- a/website/src/components/genspectrum/GsMutationComparison.astro +++ /dev/null @@ -1,25 +0,0 @@ ---- -import type { NamedLapisFilter, SequenceType } from '@genspectrum/dashboard-components/util'; - -import { defaultTablePageSize } from '../../views/View'; -import ComponentWrapper from '../ComponentWrapper.astro'; - -interface Props { - lapisFilters: NamedLapisFilter[]; - sequenceType: SequenceType; - height?: string; - pageSize?: number; -} - -const { lapisFilters, sequenceType, height, pageSize } = Astro.props; ---- - - - - diff --git a/website/src/components/genspectrum/GsMutationComparison.tsx b/website/src/components/genspectrum/GsMutationComparison.tsx new file mode 100644 index 000000000..eac5b1a70 --- /dev/null +++ b/website/src/components/genspectrum/GsMutationComparison.tsx @@ -0,0 +1,35 @@ +import type { NamedLapisFilter, SequenceType } from '@genspectrum/dashboard-components/util'; +import type { FC } from 'react'; + +import { defaultTablePageSize } from '../../views/View'; +import { ComponentWrapper } from '../ComponentWrapper.tsx'; + +export type GsMutationComparisonProps = { + lapisFilters: NamedLapisFilter[]; + sequenceType: SequenceType; + height?: string; + pageSize?: number; +}; + +export const GsMutationComparison: FC = ({ + lapisFilters, + sequenceType, + height, + pageSize, +}) => { + return ( + + + + ); +}; diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx b/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx new file mode 100644 index 000000000..2b57434cd --- /dev/null +++ b/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx @@ -0,0 +1,72 @@ +import { type FC, useMemo } from 'react'; + +import { SelectVariants } from './SelectVariants.tsx'; +import type { OrganismsConfig } from '../../../config.ts'; +import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; +import type { CompareVariantsData } from '../../../views/View.ts'; +import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; +import { compareVariantsViewKey } from '../../../views/viewKeys.ts'; +import { ComponentsGrid } from '../../ComponentsGrid.tsx'; +import { GsMutationComparison } from '../../genspectrum/GsMutationComparison.tsx'; +import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; + +export type GenericCompareVariantsDataDisplayProps = { + organismViewKey: `${OrganismWithViewKey}.${typeof compareVariantsViewKey}`; + organismsConfig: OrganismsConfig; + pageState: CompareVariantsData; +}; + +const componentHeight = '540px'; // prevalence over time table with 10 rows + +export const GenericCompareVariantsDataDisplay: FC = ({ + organismViewKey, + organismsConfig, + pageState, +}) => { + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const datasetLapisFilter = view.pageStateHandler.datasetFilterToLapisFilter(pageState.datasetFilter); + const timeGranularity = chooseGranularityBasedOnDateRange({ + earliestDate: new Date(view.organismConstants.earliestDate), + dateRange: pageState.datasetFilter.dateFilters[view.organismConstants.mainDateField], + }); + + const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); + + const notEnoughVariantsSelected = pageState.variants.size < 2; + + return ( +
+ {notEnoughVariantsSelected ? ( + + ) : ( + + + + + + )} +
+ ); +}; diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro b/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro index 8d077ac5d..76727768d 100644 --- a/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro +++ b/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro @@ -1,14 +1,10 @@ --- -import SelectVariants from './SelectVariants.astro'; +import { GenericCompareVariantsDataDisplay } from './GenericCompareVariantsDataDisplay'; import { isStaging, getDashboardsConfig } from '../../../config'; import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange'; import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareVariantsViewKey } from '../../../views/viewKeys'; -import ComponentsGrid from '../../ComponentsGrid.astro'; -import GsMutationComparison from '../../genspectrum/GsMutationComparison.astro'; -import GsPrevalenceOverTime from '../../genspectrum/GsPrevalenceOverTime.astro'; import { CompareVariantsPageStateSelector } from '../../pageStateSelectors/CompareVariantsPageStateSelector'; import { CompareVariantsSelectorFallback } from '../../pageStateSelectors/FallbackElement'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; @@ -24,16 +20,8 @@ const view = ServerSide.routing.getOrganismView(organismViewKey); const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); -const datasetLapisFilter = view.pageStateHandler.datasetFilterToLapisFilter(pageState.datasetFilter); -const timeGranularity = chooseGranularityBasedOnDateRange({ - earliestDate: new Date(view.organismConstants.earliestDate), - dateRange: pageState.datasetFilter.dateFilters[view.organismConstants.mainDateField], -}); - const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); - const notEnoughVariantsSelected = pageState.variants.size < 2; - const downloadLinks = notEnoughVariantsSelected ? [] : numeratorLapisFilters.map(({ lapisFilter, displayName }) => ({ @@ -42,47 +30,26 @@ const downloadLinks = notEnoughVariantsSelected downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, })); -const componentHeight = '540px'; // prevalence over time table with 10 rows +const organismConfig = getDashboardsConfig().dashboards.organisms; --- - { - notEnoughVariantsSelected ? ( - - ) : ( - - - - - - ) - } +
+ +
diff --git a/website/src/components/views/compareVariants/SelectVariants.astro b/website/src/components/views/compareVariants/SelectVariants.astro deleted file mode 100644 index cc249d57a..000000000 --- a/website/src/components/views/compareVariants/SelectVariants.astro +++ /dev/null @@ -1,14 +0,0 @@ ---- -import { PageHeadline } from '../../../styles/containers/PageHeadline'; ---- - -
- Compare Variants -
-

To proceed, please select two or more variants in the variant filter.

-

- Note that the dataset filter is applied to all variants. Adjust the dataset filter as needed to refine your - selection. -

-
-
diff --git a/website/src/components/views/compareVariants/SelectVariants.tsx b/website/src/components/views/compareVariants/SelectVariants.tsx new file mode 100644 index 000000000..b0aabb861 --- /dev/null +++ b/website/src/components/views/compareVariants/SelectVariants.tsx @@ -0,0 +1,18 @@ +import type { FC } from 'react'; + +import { PageHeadline } from '../../../styles/containers/PageHeadline.tsx'; + +export const SelectVariants: FC = () => { + return ( +
+ Compare Variants +
+

To proceed, please select two or more variants in the variant filter.

+

+ Note that the dataset filter is applied to all variants. Adjust the dataset filter as needed to + refine your selection. +

+
+
+ ); +}; From 4392c0cfda5e6906d31b8f87882cc2ff8d2c95f5 Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Mon, 15 Dec 2025 12:42:40 +0000 Subject: [PATCH 07/26] test(website): add WasapPageStateHandler unit test (#962) * test(website): add WasapPageStateHandler unit test * test(website): add timeframe to test after rebase --- .../components/views/wasap/wasapPageConfig.ts | 4 +- .../WasapPageStateHandler.spec.ts | 322 ++++++++++++++++++ .../WasapPageStateHandler.ts | 6 +- 3 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 website/src/views/pageStateHandlers/WasapPageStateHandler.spec.ts diff --git a/website/src/components/views/wasap/wasapPageConfig.ts b/website/src/components/views/wasap/wasapPageConfig.ts index 9f93e6f21..52c98df41 100644 --- a/website/src/components/views/wasap/wasapPageConfig.ts +++ b/website/src/components/views/wasap/wasapPageConfig.ts @@ -1,4 +1,4 @@ -import type { DateRangeOption, SequenceType } from '@genspectrum/dashboard-components/util'; +import type { DateRangeOption, SequenceType, TemporalGranularity } from '@genspectrum/dashboard-components/util'; import type { ResistanceMutationSet } from './resistanceMutations'; @@ -144,7 +144,7 @@ export type WasapAnalysisMode = 'manual' | 'variant' | 'resistance' | 'untracked export type WasapBaseFilter = { locationName?: string; samplingDate?: DateRangeOption; - granularity: string; + granularity: TemporalGranularity; excludeEmpty: boolean; }; diff --git a/website/src/views/pageStateHandlers/WasapPageStateHandler.spec.ts b/website/src/views/pageStateHandlers/WasapPageStateHandler.spec.ts new file mode 100644 index 000000000..fd6a5da5c --- /dev/null +++ b/website/src/views/pageStateHandlers/WasapPageStateHandler.spec.ts @@ -0,0 +1,322 @@ +import { describe, expect, it } from 'vitest'; + +import { WasapPageStateHandler } from './WasapPageStateHandler'; +import { covidResistanceMutations } from '../../components/views/wasap/resistanceMutations'; +import { + VARIANT_TIME_FRAME, + type WasapManualFilter, + type WasapPageConfig, + type WasapResistanceFilter, + type WasapUntrackedFilter, + type WasapVariantFilter, +} from '../../components/views/wasap/wasapPageConfig'; + +const config: WasapPageConfig = { + name: 'SARS-CoV-2', + path: `/wastewater/covid`, + description: 'Analyze SARS-CoV-2 data that was collected by the WISE project.', + linkTemplate: { + nucleotideMutation: + 'https://open.cov-spectrum.org/explore/World/AllSamples/AllTimes/variants?nucMutations={{mutation}}', + aminoAcidMutation: + 'https://open.cov-spectrum.org/explore/World/AllSamples/AllTimes/variants?aaMutations={{mutation}}', + }, + manualAnalysisModeEnabled: true, + variantAnalysisModeEnabled: true, + resistanceAnalysisModeEnabled: true, + untrackedAnalysisModeEnabled: true, + resistanceMutationSets: covidResistanceMutations, + lapisBaseUrl: 'https://lapis.wasap.genspectrum.org', + samplingDateField: 'samplingDate', + locationNameField: 'locationName', + clinicalLapis: { + lapisBaseUrl: 'https://lapis.cov-spectrum.org/open/v2', + cladeField: 'nextstrainClade', + lineageField: 'nextcladePangoLineage', + dateField: 'date', + }, + browseDataUrl: 'https://db.wasap.genspectrum.org/covid/search', + browseDataDescription: 'Browse the data in the W-ASAP Loculus instance.', + defaultLocationName: 'Zürich (ZH)', + filterDefaults: { + manual: { + mode: 'manual', + sequenceType: 'nucleotide', + mutations: undefined, + }, + variant: { + mode: 'variant', + sequenceType: 'nucleotide', + variant: 'XFG*', + minProportion: 0.8, + minCount: 15, + minJaccard: 0.75, + timeFrame: VARIANT_TIME_FRAME.all, + }, + resistance: { + mode: 'resistance', + sequenceType: 'amino acid', + resistanceSet: '3CLpro', + }, + untracked: { + mode: 'untracked', + sequenceType: 'nucleotide', + excludeSet: 'predefined', + }, + }, +}; + +describe('WasapPageStateHandler', () => { + const handler = new WasapPageStateHandler(config); + + describe('default URL', () => { + it('should return the default page URL', () => { + const url = handler.getDefaultPageUrl(); + expect(url).toBe('/wastewater/covid'); + }); + }); + + describe('base filter', () => { + it('parses base filter with all fields', () => { + const url = + '/wastewater/covid?' + + 'locationName=Berlin&' + + 'samplingDate=2024-01-01--2024-12-31&' + + 'granularity=week&' + + 'excludeEmpty=false&' + + 'analysisMode=manual&' + + 'sequenceType=nucleotide&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.base.locationName).toBe('Berlin'); + expect(filter.base.samplingDate).toEqual({ + label: 'Custom', + dateFrom: '2024-01-01', + dateTo: '2024-12-31', + }); + expect(filter.base.granularity).toBe('week'); + expect(filter.base.excludeEmpty).toBe(false); + }); + + it('defaults base filter fields when missing from URL', () => { + const url = '/wastewater/covid?analysisMode=manual&sequenceType=nucleotide&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.base.locationName).toBe('Zürich (ZH)'); + expect(filter.base.samplingDate).toBeUndefined(); + expect(filter.base.granularity).toBe('day'); + expect(filter.base.excludeEmpty).toBe(true); + }); + + it('encodes excludeEmpty=false in URL but omits when true', () => { + const filterTrue = handler.parsePageStateFromUrl( + new URL('http://example.com/wastewater/covid?analysisMode=manual&sequenceType=nucleotide&'), + ); + const filterFalse = handler.parsePageStateFromUrl( + new URL( + 'http://example.com/wastewater/covid?analysisMode=manual&sequenceType=nucleotide&excludeEmpty=false&', + ), + ); + + const urlTrue = handler.toUrl(filterTrue); + const urlFalse = handler.toUrl(filterFalse); + + expect(urlTrue).not.toContain('excludeEmpty'); + expect(urlFalse).toContain('excludeEmpty=false'); + }); + + it('parses excludeEmpty string "false" as boolean false', () => { + const url = '/wastewater/covid?analysisMode=manual&sequenceType=nucleotide&excludeEmpty=false&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(typeof filter.base.excludeEmpty).toBe('boolean'); + expect(filter.base.excludeEmpty).toBe(false); + }); + }); + + describe('manual mode', () => { + it('parses and encodes manual filter', () => { + const url = + '/wastewater/covid?' + + 'locationName=Z%C3%BCrich+%28ZH%29&' + + 'granularity=day&' + + 'analysisMode=manual&' + + 'sequenceType=nucleotide&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + expect(filter.base.locationName).toBe('Zürich (ZH)'); + expect(filter.base.granularity).toBe('day'); + expect(filter.analysis.mode).toBe('manual'); + expect(filter.analysis.sequenceType).toBe('nucleotide'); + + const newUrl = handler.toUrl(filter); + expect(newUrl).toBe(url); + }); + + it('parses manual mode with multiple mutations', () => { + const url = + '/wastewater/covid?' + + 'analysisMode=manual&' + + 'sequenceType=nucleotide&' + + 'mutations=A23T%7CS:E44H%7CORFla:T123A&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('manual'); + const analysis = filter.analysis as WasapManualFilter; + expect(analysis.mutations).toEqual(['A23T', 'S:E44H', 'ORFla:T123A']); + }); + + it('manual mode with no mutations specified', () => { + const url = '/wastewater/covid?analysisMode=manual&sequenceType=amino+acid&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('manual'); + const analysis = filter.analysis as WasapManualFilter; + expect(analysis.sequenceType).toBe('amino acid'); + expect(analysis.mutations).toBeUndefined(); + }); + }); + + describe('variant mode', () => { + it('parses and encodes variant filter with all parameters', () => { + const url = + '/wastewater/covid?' + + 'locationName=Berlin&' + + 'granularity=week&' + + 'analysisMode=variant&' + + 'sequenceType=nucleotide&' + + 'variant=BA.2*&' + + 'minProportion=0.5&' + + 'minCount=10&' + + 'minJaccard=0.6&' + + 'timeFrame=3months&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('variant'); + const analysis = filter.analysis as WasapVariantFilter; + expect(analysis.variant).toBe('BA.2*'); + expect(typeof analysis.minProportion).toBe('number'); + expect(analysis.minProportion).toBe(0.5); + expect(typeof analysis.minCount).toBe('number'); + expect(analysis.minCount).toBe(10); + expect(typeof analysis.minJaccard).toBe('number'); + expect(analysis.minJaccard).toBe(0.6); + expect(analysis.timeFrame).toBe(VARIANT_TIME_FRAME.threeMonths); + + const newUrl = handler.toUrl(filter); + expect(newUrl).toBe(url); + }); + + it('converts numeric string parameters to numbers', () => { + const url = + '/wastewater/covid?' + + 'analysisMode=variant&' + + 'minProportion=0.5&' + + 'minCount=10&' + + 'minJaccard=0.6&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + const analysis = filter.analysis as WasapVariantFilter; + expect(typeof analysis.minProportion).toBe('number'); + expect(typeof analysis.minCount).toBe('number'); + expect(typeof analysis.minJaccard).toBe('number'); + }); + + it('variant mode round-trip preserves numeric precision', () => { + const url = + '/wastewater/covid?' + 'analysisMode=variant&' + 'minProportion=0.123456&' + 'minJaccard=0.789012&'; + const filter1 = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + const url2 = handler.toUrl(filter1); + const filter2 = handler.parsePageStateFromUrl(new URL(`http://example.com${url2}`)); + + const analysis1 = filter1.analysis as WasapVariantFilter; + const analysis2 = filter2.analysis as WasapVariantFilter; + expect(analysis2.minProportion).toBe(analysis1.minProportion); + expect(analysis2.minJaccard).toBe(analysis1.minJaccard); + }); + }); + + describe('resistance mode', () => { + it('parses and encodes resistance filter', () => { + const url = + '/wastewater/covid?' + + 'locationName=Z%C3%BCrich+%28ZH%29&' + + 'granularity=day&' + + 'analysisMode=resistance&' + + 'resistanceSet=3CLpro&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('resistance'); + const analysis = filter.analysis as WasapResistanceFilter; + expect(analysis.resistanceSet).toBe('3CLpro'); + + const newUrl = handler.toUrl(filter); + expect(newUrl).toBe(url); + }); + + it('resistance mode always uses amino acid sequence type', () => { + const url = '/wastewater/covid?analysisMode=resistance&resistanceSet=3CLpro&sequenceType=nucleotide&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('resistance'); + const analysis = filter.analysis as WasapResistanceFilter; + expect(analysis.sequenceType).toBe('amino acid'); + }); + }); + + describe('untracked mode', () => { + it('parses and encodes untracked filter with predefined excludeSet', () => { + const url = + '/wastewater/covid?' + + 'locationName=Z%C3%BCrich+%28ZH%29&' + + 'granularity=day&' + + 'analysisMode=untracked&' + + 'sequenceType=nucleotide&' + + 'excludeSet=predefined&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('untracked'); + const analysis = filter.analysis as WasapUntrackedFilter; + expect(analysis.excludeSet).toBe('predefined'); + expect(analysis.excludeVariants).toBeUndefined(); + + const newUrl = handler.toUrl(filter); + expect(newUrl).toBe(url); + }); + + it('parses and encodes untracked filter with custom excludeSet and variants', () => { + const url = + '/wastewater/covid?' + + 'locationName=Z%C3%BCrich+%28ZH%29&' + + 'granularity=day&' + + 'analysisMode=untracked&' + + 'sequenceType=nucleotide&' + + 'excludeSet=custom&' + + 'excludeVariants=XBB.1.5*%7CBA.2*%7CJN.1&'; + const filter = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + + expect(filter.analysis.mode).toBe('untracked'); + const analysis = filter.analysis as WasapUntrackedFilter; + expect(analysis.excludeSet).toBe('custom'); + expect(analysis.excludeVariants).toEqual(['XBB.1.5*', 'BA.2*', 'JN.1']); + + const newUrl = handler.toUrl(filter); + expect(newUrl).toBe(url); + }); + + it('untracked mode round-trip with pipe-separated variants', () => { + const url = + '/wastewater/covid?' + + 'analysisMode=untracked&' + + 'sequenceType=nucleotide&' + + 'excludeSet=custom&' + + 'excludeVariants=XBB*%7CBA.2*%7CJN.1%7CXFG*&'; + const filter1 = handler.parsePageStateFromUrl(new URL(`http://example.com${url}`)); + const url2 = handler.toUrl(filter1); + const filter2 = handler.parsePageStateFromUrl(new URL(`http://example.com${url2}`)); + + const analysis1 = filter1.analysis as WasapUntrackedFilter; + const analysis2 = filter2.analysis as WasapUntrackedFilter; + expect(analysis2.excludeVariants).toEqual(analysis1.excludeVariants); + }); + }); +}); diff --git a/website/src/views/pageStateHandlers/WasapPageStateHandler.ts b/website/src/views/pageStateHandlers/WasapPageStateHandler.ts index 0d9a85e61..d16b8e31f 100644 --- a/website/src/views/pageStateHandlers/WasapPageStateHandler.ts +++ b/website/src/views/pageStateHandlers/WasapPageStateHandler.ts @@ -1,9 +1,9 @@ -import { type SequenceType } from '@genspectrum/dashboard-components/util'; +import { type SequenceType, type TemporalGranularity } from '@genspectrum/dashboard-components/util'; import { type PageStateHandler } from './PageStateHandler'; import { parseDateRangesFromUrl, setSearchFromDateRange } from './dateFilterFromToUrl'; import { parseTextFiltersFromUrl } from './textFilterFromToUrl'; -import { type BaselineFilterConfig } from '../../components/pageStateSelectors/BaselineSelector'; +import type { BaselineFilterConfig } from '../../components/pageStateSelectors/BaselineSelector'; import { enabledAnalysisModes, type ExcludeSetName, @@ -96,7 +96,7 @@ export class WasapPageStateHandler implements PageStateHandler { const base: WasapBaseFilter = { locationName: texts.locationName ?? this.config.defaultLocationName, samplingDate: dateRanges.samplingDate, - granularity: texts.granularity ?? 'day', + granularity: (texts.granularity as TemporalGranularity | undefined) ?? 'day', excludeEmpty: texts.excludeEmpty !== 'false', }; From ad5eec6c41bbdd521e7391c890618f61a0fe9df1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:21:16 +0100 Subject: [PATCH 08/26] chore(github-actions): bump actions/upload-artifact from 5 to 6 (#970) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 1da9ea447..898ff2fc4 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -60,7 +60,7 @@ jobs: - name: Run Playwright tests run: npm run e2e - - uses: actions/upload-artifact@v5 + - uses: actions/upload-artifact@v6 if: ${{ !cancelled() }} with: name: playwright-report From 94b8aeb85bc3cf48a613aa58c5f82fe815e0c25b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:21:43 +0100 Subject: [PATCH 09/26] chore(github-actions): bump actions/cache from 4 to 5 (#971) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/commitlint.yml | 2 +- .github/workflows/e2e.yml | 2 +- .github/workflows/website.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 15d84dfbb..54d7437f9 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -21,7 +21,7 @@ jobs: with: node-version: lts/* - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 898ff2fc4..fc416fcdd 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -13,7 +13,7 @@ jobs: with: node-version: lts/* - name: Cache .npm - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('lapis-e2e/**/package-lock.json') }} diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 69b3dbcdc..6ba0d4a9b 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-node@v6 with: node-version: lts/* - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} @@ -38,7 +38,7 @@ jobs: - uses: actions/setup-node@v6 with: node-version: lts/* - - uses: actions/cache@v4 + - uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} From 169819a676b5fa010ccf84cf6e5b5d65d8a9d08a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 19:17:56 +0000 Subject: [PATCH 10/26] chore(website): bump the minorandpatch group across 1 directory with 31 updates Bumps the minorandpatch group with 28 updates in the /website directory: | Package | From | To | | --- | --- | --- | | [@astrojs/node](https://github.com/withastro/astro/tree/HEAD/packages/integrations/node) | `9.4.4` | `9.5.1` | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.90.1` | `5.90.12` | | [axios](https://github.com/axios/axios) | `1.12.2` | `1.13.2` | | [cookie](https://github.com/jshttp/cookie) | `1.0.2` | `1.1.1` | | [dayjs](https://github.com/iamkun/dayjs) | `1.11.18` | `1.11.19` | | [katex](https://github.com/KaTeX/KaTeX) | `0.16.25` | `0.16.27` | | [patch-package](https://github.com/ds300/patch-package) | `8.0.0` | `8.0.1` | | [winston](https://github.com/winstonjs/winston) | `3.17.0` | `3.19.0` | | [yaml](https://github.com/eemeli/yaml) | `2.8.1` | `2.8.2` | | [@astrojs/check](https://github.com/withastro/astro/tree/HEAD/packages/language-tools/astro-check) | `0.9.4` | `0.9.6` | | [@astrojs/react](https://github.com/withastro/astro/tree/HEAD/packages/integrations/react) | `4.3.1` | `4.4.2` | | [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.36.0` | `9.39.2` | | [@iconify/tailwind4](https://github.com/iconify/iconify-tailwind/tree/HEAD/packages/plugin) | `1.0.6` | `1.2.0` | | [@playwright/test](https://github.com/microsoft/playwright) | `1.55.0` | `1.57.0` | | [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.1.13` | `4.1.18` | | [@tanstack/eslint-plugin-query](https://github.com/TanStack/query/tree/HEAD/packages/eslint-plugin-query) | `5.90.1` | `5.91.2` | | [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) | `6.8.0` | `6.9.1` | | [@testing-library/react](https://github.com/testing-library/react-testing-library) | `16.3.0` | `16.3.1` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.44.1` | `8.50.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.44.1` | `8.50.0` | | [daisyui](https://github.com/saadeghi/daisyui/tree/HEAD/packages/daisyui) | `5.1.14` | `5.5.14` | | [eslint](https://github.com/eslint/eslint) | `9.36.0` | `9.39.2` | | [eslint-plugin-astro](https://github.com/ota-meshi/eslint-plugin-astro) | `1.3.1` | `1.5.0` | | [msw](https://github.com/mswjs/msw) | `2.11.3` | `2.12.4` | | [prettier](https://github.com/prettier/prettier) | `3.6.2` | `3.7.4` | | [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) | `0.6.14` | `0.7.2` | | [typescript](https://github.com/microsoft/TypeScript) | `5.9.2` | `5.9.3` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.44.1` | `8.50.0` | Updates `@astrojs/node` from 9.4.4 to 9.5.1 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/integrations/node/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/@astrojs/node@9.5.1/packages/integrations/node) Updates `@tanstack/react-query` from 5.90.1 to 5.90.12 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.90.12/packages/react-query) Updates `astro` from 5.13.10 to 5.16.5 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/astro@5.16.5/packages/astro) Updates `axios` from 1.12.2 to 1.13.2 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.12.2...v1.13.2) Updates `cookie` from 1.0.2 to 1.1.1 - [Release notes](https://github.com/jshttp/cookie/releases) - [Commits](https://github.com/jshttp/cookie/compare/v1.0.2...v1.1.1) Updates `dayjs` from 1.11.18 to 1.11.19 - [Release notes](https://github.com/iamkun/dayjs/releases) - [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md) - [Commits](https://github.com/iamkun/dayjs/compare/v1.11.18...v1.11.19) Updates `katex` from 0.16.25 to 0.16.27 - [Release notes](https://github.com/KaTeX/KaTeX/releases) - [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md) - [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.25...v0.16.27) Updates `patch-package` from 8.0.0 to 8.0.1 - [Release notes](https://github.com/ds300/patch-package/releases) - [Changelog](https://github.com/ds300/patch-package/blob/master/CHANGELOG.md) - [Commits](https://github.com/ds300/patch-package/commits) Updates `winston` from 3.17.0 to 3.19.0 - [Release notes](https://github.com/winstonjs/winston/releases) - [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md) - [Commits](https://github.com/winstonjs/winston/compare/v3.17.0...v3.19.0) Updates `yaml` from 2.8.1 to 2.8.2 - [Release notes](https://github.com/eemeli/yaml/releases) - [Commits](https://github.com/eemeli/yaml/compare/v2.8.1...v2.8.2) Updates `@astrojs/check` from 0.9.4 to 0.9.6 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/language-tools/astro-check/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/@astrojs/check@0.9.6/packages/language-tools/astro-check) Updates `@astrojs/react` from 4.3.1 to 4.4.2 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/integrations/react/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/@astrojs/react@4.4.2/packages/integrations/react) Updates `@eslint/js` from 9.36.0 to 9.39.2 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/commits/v9.39.2/packages/js) Updates `@iconify/tailwind4` from 1.0.6 to 1.2.0 - [Commits](https://github.com/iconify/iconify-tailwind/commits/HEAD/packages/plugin) Updates `@playwright/test` from 1.55.0 to 1.57.0 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.55.0...v1.57.0) Updates `@tailwindcss/vite` from 4.1.13 to 4.1.18 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.1.18/packages/@tailwindcss-vite) Updates `@tanstack/eslint-plugin-query` from 5.90.1 to 5.91.2 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/eslint-plugin-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/eslint-plugin-query@5.91.2/packages/eslint-plugin-query) Updates `@testing-library/jest-dom` from 6.8.0 to 6.9.1 - [Release notes](https://github.com/testing-library/jest-dom/releases) - [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/jest-dom/compare/v6.8.0...v6.9.1) Updates `@testing-library/react` from 16.3.0 to 16.3.1 - [Release notes](https://github.com/testing-library/react-testing-library/releases) - [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/react-testing-library/compare/v16.3.0...v16.3.1) Updates `@typescript-eslint/eslint-plugin` from 8.44.1 to 8.50.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.44.1 to 8.50.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.0/packages/parser) Updates `daisyui` from 5.1.14 to 5.5.14 - [Release notes](https://github.com/saadeghi/daisyui/releases) - [Changelog](https://github.com/saadeghi/daisyui/blob/master/CHANGELOG.md) - [Commits](https://github.com/saadeghi/daisyui/commits/v5.5.14/packages/daisyui) Updates `eslint` from 9.36.0 to 9.39.2 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v9.36.0...v9.39.2) Updates `eslint-plugin-astro` from 1.3.1 to 1.5.0 - [Release notes](https://github.com/ota-meshi/eslint-plugin-astro/releases) - [Changelog](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/CHANGELOG.md) - [Commits](https://github.com/ota-meshi/eslint-plugin-astro/compare/v1.3.1...v1.5.0) Updates `msw` from 2.11.3 to 2.12.4 - [Release notes](https://github.com/mswjs/msw/releases) - [Changelog](https://github.com/mswjs/msw/blob/main/CHANGELOG.md) - [Commits](https://github.com/mswjs/msw/compare/v2.11.3...v2.12.4) Updates `playwright` from 1.55.0 to 1.57.0 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.55.0...v1.57.0) Updates `prettier` from 3.6.2 to 3.7.4 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.6.2...3.7.4) Updates `prettier-plugin-tailwindcss` from 0.6.14 to 0.7.2 - [Release notes](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/compare/v0.6.14...v0.7.2) Updates `tailwindcss` from 4.1.13 to 4.1.18 - [Release notes](https://github.com/tailwindlabs/tailwindcss/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.1.18/packages/tailwindcss) Updates `typescript` from 5.9.2 to 5.9.3 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.2...v5.9.3) Updates `typescript-eslint` from 8.44.1 to 8.50.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@astrojs/node" dependency-version: 9.5.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@tanstack/react-query" dependency-version: 5.90.12 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: astro dependency-version: 5.16.5 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: axios dependency-version: 1.13.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: cookie dependency-version: 1.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: dayjs dependency-version: 1.11.19 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: katex dependency-version: 0.16.27 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: patch-package dependency-version: 8.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: winston dependency-version: 3.19.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: yaml dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@astrojs/check" dependency-version: 0.9.6 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@astrojs/react" dependency-version: 4.4.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@eslint/js" dependency-version: 9.39.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@iconify/tailwind4" dependency-version: 1.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@playwright/test" dependency-version: 1.57.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@tailwindcss/vite" dependency-version: 4.1.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@tanstack/eslint-plugin-query" dependency-version: 5.91.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@testing-library/jest-dom" dependency-version: 6.9.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@testing-library/react" dependency-version: 16.3.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.50.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@typescript-eslint/parser" dependency-version: 8.50.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: daisyui dependency-version: 5.5.14 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: eslint dependency-version: 9.39.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: eslint-plugin-astro dependency-version: 1.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: msw dependency-version: 2.12.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: playwright dependency-version: 1.57.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: prettier dependency-version: 3.7.4 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: prettier-plugin-tailwindcss dependency-version: 0.7.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: tailwindcss dependency-version: 4.1.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: typescript dependency-version: 5.9.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: typescript-eslint dependency-version: 8.50.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch ... Signed-off-by: dependabot[bot] --- website/package-lock.json | 2294 +++++++++++++++++-------------------- website/package.json | 56 +- 2 files changed, 1108 insertions(+), 1242 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index 14af7a826..54a935833 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -9,64 +9,64 @@ "version": "0.0.1", "hasInstallScript": true, "dependencies": { - "@astrojs/node": "^9.4.4", + "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.1", + "@tanstack/react-query": "^5.90.12", "astro": "^5.13.10", "auth-astro": "^4.2.0", - "axios": "^1.12.2", - "cookie": "^1.0.2", - "dayjs": "^1.11.18", - "katex": "^0.16.25", - "patch-package": "^8.0.0", + "axios": "^1.13.2", + "cookie": "^1.1.1", + "dayjs": "^1.11.19", + "katex": "^0.16.27", + "patch-package": "^8.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-katex": "^3.1.0", "react-toastify": "^11.0.5", "uuid": "^11.1.0", - "winston": "^3.17.0", + "winston": "^3.19.0", "winston-daily-rotate-file": "^5.0.0", - "yaml": "^2.8.1" + "yaml": "^2.8.2" }, "devDependencies": { - "@astrojs/check": "^0.9.4", - "@astrojs/react": "^4.3.1", - "@eslint/js": "^9.36.0", + "@astrojs/check": "^0.9.6", + "@astrojs/react": "^4.4.2", + "@eslint/js": "^9.39.2", "@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi-light": "^1.2.2", - "@iconify/tailwind4": "^1.0.6", - "@playwright/test": "^1.55.0", - "@tailwindcss/vite": "^4.1.13", - "@tanstack/eslint-plugin-query": "^5.90.1", + "@iconify/tailwind4": "^1.2.0", + "@playwright/test": "^1.57.0", + "@tailwindcss/vite": "^4.1.18", + "@tanstack/eslint-plugin-query": "^5.91.2", "@testing-library/dom": "^10.4.1", - "@testing-library/jest-dom": "^6.8.0", - "@testing-library/react": "^16.3.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.1", "@testing-library/user-event": "^14.6.1", "@types/node": "^24.5.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.44.1", - "@typescript-eslint/parser": "^8.44.1", + "@typescript-eslint/eslint-plugin": "^8.50.0", + "@typescript-eslint/parser": "^8.50.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", - "daisyui": "^5.1.14", + "daisyui": "^5.5.14", "dotenv": "^16.5.0", - "eslint": "^9.36.0", - "eslint-plugin-astro": "^1.3.1", + "eslint": "^9.39.2", + "eslint-plugin-astro": "^1.5.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", - "msw": "^2.11.3", + "msw": "^2.12.4", "playwright": "^1.55.0", - "prettier": "^3.6.2", + "prettier": "^3.7.4", "prettier-plugin-astro": "^0.14.1", - "prettier-plugin-tailwindcss": "^0.6.14", + "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", - "typescript": "^5.9.2", - "typescript-eslint": "^8.44.1", + "typescript": "^5.9.3", + "typescript-eslint": "^8.50.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" @@ -80,27 +80,27 @@ "license": "MIT" }, "node_modules/@antfu/install-pkg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.0.0.tgz", - "integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", "dev": true, "license": "MIT", "dependencies": { - "package-manager-detector": "^0.2.8", - "tinyexec": "^0.3.2" + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@antfu/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", + "node_modules/@antfu/install-pkg/node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": ">=18" } }, "node_modules/@asamuzakjp/css-color": { @@ -127,62 +127,62 @@ "optional": true }, "node_modules/@astrojs/check": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.4.tgz", - "integrity": "sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.6.tgz", + "integrity": "sha512-jlaEu5SxvSgmfGIFfNgcn5/f+29H61NJzEMfAZ82Xopr4XBchXB1GVlcJsE+elUlsYSbXlptZLX+JMG3b/wZEA==", "dev": true, "license": "MIT", "dependencies": { - "@astrojs/language-server": "^2.15.0", + "@astrojs/language-server": "^2.16.1", "chokidar": "^4.0.1", "kleur": "^4.1.5", "yargs": "^17.7.2" }, "bin": { - "astro-check": "dist/bin.js" + "astro-check": "bin/astro-check.js" }, "peerDependencies": { "typescript": "^5.0.0" } }, "node_modules/@astrojs/compiler": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.12.2.tgz", - "integrity": "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", + "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==", "license": "MIT", "peer": true }, "node_modules/@astrojs/internal-helpers": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.3.tgz", - "integrity": "sha512-6Pl0bQEIChuW5wqN7jdKrzWfCscW2rG/Cz+fzt4PhSQX2ivBpnhXgFUCs0M3DCYvjYHnPVG2W36X5rmFjZ62sw==", + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz", + "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==", "license": "MIT" }, "node_modules/@astrojs/language-server": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.15.4.tgz", - "integrity": "sha512-JivzASqTPR2bao9BWsSc/woPHH7OGSGc9aMxXL4U6egVTqBycB3ZHdBJPuOCVtcGLrzdWTosAqVPz1BVoxE0+A==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.2.tgz", + "integrity": "sha512-J3hVx/mFi3FwEzKf8ExYXQNERogD6RXswtbU+TyrxoXRBiQoBO5ooo7/lRWJ+rlUKUd7+rziMPI9jYB7TRlh0w==", "dev": true, "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.10.3", "@astrojs/yaml2ts": "^0.2.2", "@jridgewell/sourcemap-codec": "^1.4.15", - "@volar/kit": "~2.4.7", - "@volar/language-core": "~2.4.7", - "@volar/language-server": "~2.4.7", - "@volar/language-service": "~2.4.7", + "@volar/kit": "~2.4.23", + "@volar/language-core": "~2.4.23", + "@volar/language-server": "~2.4.23", + "@volar/language-service": "~2.4.23", "fast-glob": "^3.2.12", "muggle-string": "^0.4.1", - "volar-service-css": "0.0.62", - "volar-service-emmet": "0.0.62", - "volar-service-html": "0.0.62", - "volar-service-prettier": "0.0.62", - "volar-service-typescript": "0.0.62", - "volar-service-typescript-twoslash-queries": "0.0.62", - "volar-service-yaml": "0.0.62", - "vscode-html-languageservice": "^5.2.0", - "vscode-uri": "^3.0.8" + "volar-service-css": "0.0.67", + "volar-service-emmet": "0.0.67", + "volar-service-html": "0.0.67", + "volar-service-prettier": "0.0.67", + "volar-service-typescript": "0.0.67", + "volar-service-typescript-twoslash-queries": "0.0.67", + "volar-service-yaml": "0.0.67", + "vscode-html-languageservice": "^5.5.2", + "vscode-uri": "^3.1.0" }, "bin": { "astro-ls": "bin/nodeServer.js" @@ -201,18 +201,18 @@ } }, "node_modules/@astrojs/markdown-remark": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.7.tgz", - "integrity": "sha512-KXGdq6/BC18doBCYXp08alHlWChH0hdD2B1qv9wIyOHbvwI5K6I7FhSta8dq1hBQNdun8YkKPR013D/Hm8xd0g==", + "version": "6.3.10", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.10.tgz", + "integrity": "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.7.3", + "@astrojs/internal-helpers": "0.7.5", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", @@ -220,27 +220,27 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", - "shiki": "^3.12.2", - "smol-toml": "^1.4.2", + "shiki": "^3.19.0", + "smol-toml": "^1.5.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.1", + "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "node_modules/@astrojs/node": { - "version": "9.4.4", - "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.4.4.tgz", - "integrity": "sha512-zQelZmeejnpw3Y5cj2gCyAZ6HT7tjgsWLZH8k40s3bTaT6lqJXlPtKJeIsuEcod21vZLODqBEQeu0CWrWm01EQ==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.5.1.tgz", + "integrity": "sha512-7k+SU877OUQylPr0mFcWrGvNuC78Lp9w+GInY8Rwc+LkHyDP9xls+nZAioK0WDWd+fyeQnlHbpDGURO3ZHuDVg==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.7.3", + "@astrojs/internal-helpers": "0.7.5", "send": "^1.2.0", "server-destroy": "^1.0.1" }, "peerDependencies": { - "astro": "^5.7.0" + "astro": "^5.14.3" } }, "node_modules/@astrojs/prism": { @@ -256,15 +256,15 @@ } }, "node_modules/@astrojs/react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.3.1.tgz", - "integrity": "sha512-Jhv35TsDHuQLvwof2z10P3g1s9wIR4UN9jE7O4NZBJNXOt/+qk+L0rY9th4SX7VzccKmRltUGxAhI1cXH52gXw==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.2.tgz", + "integrity": "sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==", "dev": true, "license": "MIT", "dependencies": { "@vitejs/plugin-react": "^4.7.0", "ultrahtml": "^1.6.0", - "vite": "^6.3.6" + "vite": "^6.4.1" }, "engines": { "node": "18.20.8 || ^20.3.0 || >=22.0.0" @@ -507,9 +507,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -540,12 +540,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -633,57 +633,28 @@ } }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@bundled-es-modules/cookie": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", - "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cookie": "^0.7.2" - } - }, - "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@bundled-es-modules/statuses": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", - "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "statuses": "^2.0.1" - } - }, "node_modules/@capsizecss/unpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-2.4.0.tgz", - "integrity": "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-3.0.1.tgz", + "integrity": "sha512-8XqW8xGn++Eqqbz3e9wKuK7mxryeRjs4LOHLxbh2lwKeSbuNR4NFifDZT4KzvjU6HMOPbiNTsWpniK5EJfTWkg==", "license": "MIT", "dependencies": { - "blob-to-buffer": "^1.2.8", - "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" + }, + "engines": { + "node": ">=18" } }, "node_modules/@colors/colors": { @@ -770,13 +741,23 @@ "@csstools/css-tokenizer": "^3.0.3" } }, + "node_modules/@cyberalien/svg-utils": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@cyberalien/svg-utils/-/svg-utils-1.0.11.tgz", + "integrity": "sha512-qEE9mnyI+avfGT3emKuRs3ucYkITeaV0Xi7VlYN41f+uGnZBecQP3jwz/AF437H9J4Q7qPClHKm4NiTYpNE6hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0" + } + }, "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", "license": "MIT", "dependencies": { - "colorspace": "1.1.x", + "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } @@ -802,9 +783,9 @@ } }, "node_modules/@emmetio/css-parser": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emmetio/css-parser/-/css-parser-0.4.0.tgz", - "integrity": "sha512-z7wkxRSZgrQHXVzObGkXG+Vmj3uRlpM11oCZ9pbaz0nFejvCDmAiNDpY75+wgXOcffKpj4rzGtwGaZxfJKsJxw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@emmetio/css-parser/-/css-parser-0.4.1.tgz", + "integrity": "sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1283,12 +1264,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1301,6 +1283,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1311,6 +1294,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1319,19 +1303,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1403,9 +1390,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -1416,22 +1403,23 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.2", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -1577,20 +1565,37 @@ } }, "node_modules/@iconify/tailwind4": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@iconify/tailwind4/-/tailwind4-1.0.6.tgz", - "integrity": "sha512-43ZXe+bC7CuE2LCgROdqbQeFYJi/J7L/k1UpSy8KDQlWVsWxPzLSWbWhlJx4uRYLOh1NRyw02YlDOgzBOFNd+A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@iconify/tailwind4/-/tailwind4-1.2.0.tgz", + "integrity": "sha512-+t7XqfojOB0zzZdd8gV7IQZGq1AaIHTlsxMVzagxYR0hAlJCLUD63o3iSlNKRMH3ZR7gZ8y5c9dJ7J431avRbA==", "dev": true, "license": "MIT", "dependencies": { + "@iconify/tools": "^5.0.0", "@iconify/types": "^2.0.0", - "@iconify/utils": "^2.2.1" + "@iconify/utils": "^3.1.0" }, "funding": { "url": "https://github.com/sponsors/cyberalien" }, "peerDependencies": { - "tailwindcss": ">= 4" + "tailwindcss": ">= 4.0.0" + } + }, + "node_modules/@iconify/tools": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@iconify/tools/-/tools-5.0.0.tgz", + "integrity": "sha512-GY/FsuNdWA/FbkLqgQ8b1PHFkNvjMeSFWaVJdLldYGHBp0lZ64HJlcS0qzLfglacHTd8zYdfQjF74RxGqyGMgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cyberalien/svg-utils": "^1.0.11", + "@iconify/types": "^2.0.0", + "@iconify/utils": "^3.1.0", + "fflate": "^0.8.2", + "modern-tar": "^0.7.2", + "pathe": "^2.0.3", + "svgo": "^4.0.0" } }, "node_modules/@iconify/types": { @@ -1601,20 +1606,15 @@ "license": "MIT" }, "node_modules/@iconify/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", "dev": true, "license": "MIT", "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@antfu/utils": "^8.1.0", + "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", - "debug": "^4.4.0", - "globals": "^15.14.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "mlly": "^1.7.4" + "mlly": "^1.8.0" } }, "node_modules/@img/sharp-darwin-arm64": { @@ -2163,19 +2163,6 @@ } } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2265,9 +2252,9 @@ } }, "node_modules/@mswjs/interceptors": { - "version": "0.39.2", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.2.tgz", - "integrity": "sha512-RuzCup9Ct91Y7V79xwCb146RaBRHZ7NBbrIUySumd1rpKqHL5OonaqrGIbug5hNwP/fRyxFMA6ISgw4FTtYFYg==", + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.40.0.tgz", + "integrity": "sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2374,13 +2361,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz", - "integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", + "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.55.0" + "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" @@ -2686,60 +2673,60 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz", - "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.20.0.tgz", + "integrity": "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz", - "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.20.0.tgz", + "integrity": "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.3" + "oniguruma-to-es": "^4.3.4" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz", - "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.20.0.tgz", + "integrity": "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0", + "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz", - "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.20.0.tgz", + "integrity": "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0" + "@shikijs/types": "3.20.0" } }, "node_modules/@shikijs/themes": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz", - "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.20.0.tgz", + "integrity": "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.13.0" + "@shikijs/types": "3.20.0" } }, "node_modules/@shikijs/types": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz", - "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.20.0.tgz", + "integrity": "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -2752,6 +2739,62 @@ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", "license": "MIT" }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, + "node_modules/@so-ric/colorspace/node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@so-ric/colorspace/node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/@so-ric/colorspace/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/@so-ric/colorspace/node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@swc/helpers": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", @@ -2762,54 +2805,49 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", - "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", - "jiti": "^2.5.1", - "lightningcss": "1.30.1", - "magic-string": "^0.30.18", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.13" + "tailwindcss": "4.1.18" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", - "integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-x64": "4.1.13", - "@tailwindcss/oxide-freebsd-x64": "4.1.13", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-x64-musl": "4.1.13", - "@tailwindcss/oxide-wasm32-wasi": "4.1.13", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", - "integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", "cpu": [ "arm64" ], @@ -2824,9 +2862,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", - "integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", "cpu": [ "arm64" ], @@ -2841,9 +2879,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", - "integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", "cpu": [ "x64" ], @@ -2858,9 +2896,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", - "integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", "cpu": [ "x64" ], @@ -2875,9 +2913,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", - "integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", "cpu": [ "arm" ], @@ -2892,9 +2930,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", - "integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", "cpu": [ "arm64" ], @@ -2909,9 +2947,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", - "integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", "cpu": [ "arm64" ], @@ -2926,9 +2964,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", - "integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", "cpu": [ "x64" ], @@ -2943,9 +2981,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", - "integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", "cpu": [ "x64" ], @@ -2960,9 +2998,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", - "integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -2978,30 +3016,30 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.5", - "@emnapi/runtime": "^1.4.5", - "@emnapi/wasi-threads": "^1.0.4", - "@napi-rs/wasm-runtime": "^0.2.12", - "@tybys/wasm-util": "^0.10.0", - "tslib": "^2.8.0" + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.0", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.4.5", + "version": "1.7.1", "dev": true, "inBundle": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.4", + "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.4.5", + "version": "1.7.1", "dev": true, "inBundle": true, "license": "MIT", @@ -3011,7 +3049,7 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", + "version": "1.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -3021,19 +3059,19 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", + "version": "1.1.0", "dev": true, "inBundle": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.0", + "version": "0.10.1", "dev": true, "inBundle": true, "license": "MIT", @@ -3043,16 +3081,16 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.0", + "version": "2.8.1", "dev": true, "inBundle": true, "license": "0BSD", "optional": true }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", - "integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", "cpu": [ "arm64" ], @@ -3067,9 +3105,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", - "integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", "cpu": [ "x64" ], @@ -3084,28 +3122,28 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.13.tgz", - "integrity": "sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.13", - "@tailwindcss/oxide": "4.1.13", - "tailwindcss": "4.1.13" + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "node_modules/@tanstack/eslint-plugin-query": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.90.1.tgz", - "integrity": "sha512-Ki4hl+8ZtnMFZ3amZbQl6sSMUq6L8oSJ14vmi3j5t1/SqXclL5SI/1kcuH36iIk05B/bN5pEOS1PTO3Ut/FbVA==", + "version": "5.91.2", + "resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.91.2.tgz", + "integrity": "sha512-UPeWKl/Acu1IuuHJlsN+eITUHqAaa9/04geHHPedY8siVarSaWprY0SVMKrkpKfk5ehRT7+/MZ5QwWuEtkWrFw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.44.0" + "@typescript-eslint/utils": "^8.44.1" }, "funding": { "type": "github", @@ -3116,9 +3154,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.1.tgz", - "integrity": "sha512-hmi8i+mWP3QnD8yq3+6LWri9IEZAlFbpbM/UVB+TJtp5RIxUfzuARqyW39b+HCfBKKnFKSHWMXNB5YN8lo/E/Q==", + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", + "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", "license": "MIT", "funding": { "type": "github", @@ -3126,12 +3164,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.1.tgz", - "integrity": "sha512-tN7Fx2HuV2SBhl+STgL8enbfSInRoNU1B1+5LIU62klcMElE4lFzol4aReuRSUeD6ntzPayK0KrM6w9+ZlHEkw==", + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", + "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.90.1" + "@tanstack/query-core": "5.90.12" }, "funding": { "type": "github", @@ -3176,9 +3214,9 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz", - "integrity": "sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", "dev": true, "license": "MIT", "dependencies": { @@ -3203,9 +3241,9 @@ "license": "MIT" }, "node_modules/@testing-library/react": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", - "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.1.tgz", + "integrity": "sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==", "dev": true, "license": "MIT", "dependencies": { @@ -3306,13 +3344,6 @@ "@types/deep-eql": "*" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -3448,9 +3479,9 @@ } }, "node_modules/@types/statuses": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", + "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==", "dev": true, "license": "MIT" }, @@ -3483,18 +3514,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", - "integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz", + "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/type-utils": "8.44.1", - "@typescript-eslint/utils": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", - "graphemer": "^1.4.0", + "@typescript-eslint/scope-manager": "8.50.0", + "@typescript-eslint/type-utils": "8.50.0", + "@typescript-eslint/utils": "8.50.0", + "@typescript-eslint/visitor-keys": "8.50.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" @@ -3507,7 +3537,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.44.1", + "@typescript-eslint/parser": "^8.50.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -3523,17 +3553,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", - "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz", + "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", + "@typescript-eslint/scope-manager": "8.50.0", + "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/typescript-estree": "8.50.0", + "@typescript-eslint/visitor-keys": "8.50.0", "debug": "^4.3.4" }, "engines": { @@ -3549,14 +3579,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", - "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz", + "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.44.1", - "@typescript-eslint/types": "^8.44.1", + "@typescript-eslint/tsconfig-utils": "^8.50.0", + "@typescript-eslint/types": "^8.50.0", "debug": "^4.3.4" }, "engines": { @@ -3571,14 +3601,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", - "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz", + "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1" + "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/visitor-keys": "8.50.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3589,9 +3619,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", - "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz", + "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==", "dev": true, "license": "MIT", "engines": { @@ -3606,15 +3636,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", - "integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz", + "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1", + "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/typescript-estree": "8.50.0", + "@typescript-eslint/utils": "8.50.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3631,9 +3661,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", - "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz", + "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==", "dev": true, "license": "MIT", "engines": { @@ -3645,21 +3675,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", - "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz", + "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.44.1", - "@typescript-eslint/tsconfig-utils": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", + "@typescript-eslint/project-service": "8.50.0", + "@typescript-eslint/tsconfig-utils": "8.50.0", + "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/visitor-keys": "8.50.0", "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", + "tinyglobby": "^0.2.15", "ts-api-utils": "^2.1.0" }, "engines": { @@ -3674,16 +3703,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", - "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz", + "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1" + "@typescript-eslint/scope-manager": "8.50.0", + "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/typescript-estree": "8.50.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3698,13 +3727,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", - "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz", + "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/types": "8.50.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3918,14 +3947,14 @@ } }, "node_modules/@volar/kit": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.11.tgz", - "integrity": "sha512-ups5RKbMzMCr6RKafcCqDRnJhJDNWqo2vfekwOAj6psZ15v5TlcQFQAyokQJ3wZxVkzxrQM+TqTRDENfQEXpmA==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.27.tgz", + "integrity": "sha512-ilZoQDMLzqmSsImJRWx4YiZ4FcvvPrPnFVmL6hSsIWB6Bn3qc7k88J9yP32dagrs5Y8EXIlvvD/mAFaiuEOACQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-service": "2.4.11", - "@volar/typescript": "2.4.11", + "@volar/language-service": "2.4.27", + "@volar/typescript": "2.4.27", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" @@ -3935,25 +3964,25 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz", - "integrity": "sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.27.tgz", + "integrity": "sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.11" + "@volar/source-map": "2.4.27" } }, "node_modules/@volar/language-server": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.11.tgz", - "integrity": "sha512-W9P8glH1M8LGREJ7yHRCANI5vOvTrRO15EMLdmh5WNF9sZYSEbQxiHKckZhvGIkbeR1WAlTl3ORTrJXUghjk7g==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.27.tgz", + "integrity": "sha512-SymGNkErcHg8GjiG65iQN8sLkhqu1pwKhFySmxeBuYq5xFYagKBW36eiNITXQTdvT0tutI1GXcXdq/FdE/IyjA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.11", - "@volar/language-service": "2.4.11", - "@volar/typescript": "2.4.11", + "@volar/language-core": "2.4.27", + "@volar/language-service": "2.4.27", + "@volar/typescript": "2.4.27", "path-browserify": "^1.0.1", "request-light": "^0.7.0", "vscode-languageserver": "^9.0.1", @@ -3963,33 +3992,33 @@ } }, "node_modules/@volar/language-service": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.11.tgz", - "integrity": "sha512-KIb6g8gjUkS2LzAJ9bJCLIjfsJjeRtmXlu7b2pDFGD3fNqdbC53cCAKzgWDs64xtQVKYBU13DLWbtSNFtGuMLQ==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.27.tgz", + "integrity": "sha512-SxKZ8yLhpWa7Y5e/RDxtNfm7j7xsXp/uf2urijXEffRNpPSmVdfzQrFFy5d7l8PNpZy+bHg+yakmqBPjQN+MOw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.11", + "@volar/language-core": "2.4.27", "vscode-languageserver-protocol": "^3.17.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" } }, "node_modules/@volar/source-map": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.11.tgz", - "integrity": "sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.27.tgz", + "integrity": "sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.11.tgz", - "integrity": "sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==", + "version": "2.4.27", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.27.tgz", + "integrity": "sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.11", + "@volar/language-core": "2.4.27", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } @@ -4388,31 +4417,31 @@ } }, "node_modules/astro": { - "version": "5.13.10", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.13.10.tgz", - "integrity": "sha512-PgIrIYvrR7fCoSPPt1sGlpoYK/FNil1BwKazND1DyaZC7SbWLi9hdIHM3ApdrL2SWK7oiADRPw7cTn80UyDWqA==", + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.5.tgz", + "integrity": "sha512-QeuM4xzTR0QuXFDNlGVW0BW7rcquKFIkylaPeM4ufii0/RRiPTYtwxDYVZ3KfiMRuuc+nbLD0214kMKTvz/yvQ==", "license": "MIT", "peer": true, "dependencies": { - "@astrojs/compiler": "^2.12.2", - "@astrojs/internal-helpers": "0.7.3", - "@astrojs/markdown-remark": "6.3.7", + "@astrojs/compiler": "^2.13.0", + "@astrojs/internal-helpers": "0.7.5", + "@astrojs/markdown-remark": "6.3.10", "@astrojs/telemetry": "3.3.0", - "@capsizecss/unpack": "^2.4.0", + "@capsizecss/unpack": "^3.0.1", "@oslojs/encoding": "^1.1.0", - "@rollup/pluginutils": "^5.2.0", + "@rollup/pluginutils": "^5.3.0", "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", - "ci-info": "^4.3.0", + "ci-info": "^4.3.1", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", - "debug": "^4.4.1", + "debug": "^4.4.3", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.3.2", + "devalue": "^5.5.0", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", @@ -4420,41 +4449,42 @@ "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", - "fontace": "~0.3.0", + "fontace": "~0.3.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "import-meta-resolve": "^4.2.0", - "js-yaml": "^4.1.0", - "kleur": "^4.1.5", - "magic-string": "^0.30.18", - "magicast": "^0.3.5", + "js-yaml": "^4.1.1", + "magic-string": "^0.30.21", + "magicast": "^0.5.1", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", - "p-queue": "^8.1.0", - "package-manager-detector": "^1.3.0", + "p-queue": "^8.1.1", + "package-manager-detector": "^1.5.0", + "piccolore": "^0.1.3", "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", - "semver": "^7.7.2", - "shiki": "^3.12.0", - "smol-toml": "^1.4.2", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", + "semver": "^7.7.3", + "shiki": "^3.15.0", + "smol-toml": "^1.5.2", + "svgo": "^4.0.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", - "unifont": "~0.5.2", + "unifont": "~0.6.0", "unist-util-visit": "^5.0.0", - "unstorage": "^1.17.0", + "unstorage": "^1.17.3", "vfile": "^6.0.3", - "vite": "^6.3.6", + "vite": "^6.4.1", "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.3", "zod": "^3.25.76", - "zod-to-json-schema": "^3.24.6", + "zod-to-json-schema": "^3.25.0", "zod-to-ts": "^1.2.0" }, "bin": { @@ -4528,16 +4558,19 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, - "node_modules/astro/node_modules/package-manager-detector": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", - "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", - "license": "MIT" + "node_modules/astro/node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/astro/node_modules/unstorage": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.1.tgz", - "integrity": "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz", + "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==", "license": "MIT", "dependencies": { "anymatch": "^3.1.3", @@ -4546,7 +4579,7 @@ "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", - "ofetch": "^1.4.1", + "ofetch": "^1.5.1", "ufo": "^1.6.1" }, "peerDependencies": { @@ -4671,15 +4704,6 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/auth-astro": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/auth-astro/-/auth-astro-4.2.0.tgz", @@ -4713,9 +4737,9 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -4746,6 +4770,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/base-64": { @@ -4774,25 +4799,11 @@ ], "license": "MIT" }, - "node_modules/blob-to-buffer": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", - "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" }, "node_modules/boxen": { "version": "8.0.1", @@ -5125,20 +5136,10 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/ci-info": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", - "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "funding": [ { "type": "github", @@ -5295,46 +5296,12 @@ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", + "optional": true, "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "node_modules/colorspace/node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "node_modules/colorspace/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/colorspace/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5379,12 +5346,13 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, "license": "MIT" }, "node_modules/confbox": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.1.tgz", - "integrity": "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", "dev": true, "license": "MIT" }, @@ -5396,12 +5364,16 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "license": "MIT", "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cookie-es": { @@ -5410,15 +5382,6 @@ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", "license": "MIT" }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5442,6 +5405,22 @@ "uncrypto": "^0.1.3" } }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css-tree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", @@ -5455,6 +5434,18 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -5474,6 +5465,39 @@ "node": ">=4" } }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, "node_modules/cssstyle": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", @@ -5570,9 +5594,9 @@ } }, "node_modules/daisyui": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.1.14.tgz", - "integrity": "sha512-c9Op7tB8vLzzazFaLeyFsmmVMLrU8sYo1sHuStBGTbaAzLVxrulelGQBROo/lS2ZxWm/CnCb9NWdKbTL+MaKFA==", + "version": "5.5.14", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.14.tgz", + "integrity": "sha512-L47rvw7I7hK68TA97VB8Ee0woHew+/ohR6Lx6Ah/krfISOqcG4My7poNpX5Mo5/ytMxiR40fEaz6njzDi7cuSg==", "dev": true, "license": "MIT", "funding": { @@ -5660,15 +5684,15 @@ } }, "node_modules/dayjs": { - "version": "1.11.18", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", - "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5817,9 +5841,9 @@ } }, "node_modules/devalue": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz", - "integrity": "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", + "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==", "license": "MIT" }, "node_modules/devlop": { @@ -5876,15 +5900,82 @@ "dev": true, "license": "MIT" }, - "node_modules/dompurify": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.5.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", @@ -5989,9 +6080,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6264,26 +6355,25 @@ } }, "node_modules/eslint": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", - "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.36.0", - "@eslint/plugin-kit": "^0.3.5", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -6392,9 +6482,9 @@ } }, "node_modules/eslint-plugin-astro": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-astro/-/eslint-plugin-astro-1.3.1.tgz", - "integrity": "sha512-2XaLCMQm8htW1UvJvy1Zcmg8l0ziskitiUfJTn/w1Mk7r4Mxj0fZeNpN6UTNrm64XBIXSa5h8UCGrg8mdu47+g==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-astro/-/eslint-plugin-astro-1.5.0.tgz", + "integrity": "sha512-IWy4kY3DKTJxd7g652zIWpBGFuxw7NIIt16kyqc8BlhnIKvI8yGJj+Maua0DiNYED3F/D8AmzoTTTA6A95WX9g==", "dev": true, "license": "MIT", "dependencies": { @@ -6403,7 +6493,7 @@ "@typescript-eslint/types": "^7.7.1 || ^8", "astro-eslint-parser": "^1.0.2", "eslint-compat-utils": "^0.6.0", - "globals": "^15.0.0", + "globals": "^16.0.0", "postcss": "^8.4.14", "postcss-selector-parser": "^7.0.0" }, @@ -6771,13 +6861,6 @@ "node": ">=12.0.0" } }, - "node_modules/exsolve": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.1.tgz", - "integrity": "sha512-Smf0iQtkQVJLaph8r/qS8C8SWfQkaq9Q/dFcD44MLbJj6DNhlWefVuaS21SjfqOsBbjVlKtbCj6L9ekXK6EZUg==", - "dev": true, - "license": "MIT" - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6835,9 +6918,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -6862,10 +6945,13 @@ } }, "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6881,6 +6967,13 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -7004,9 +7097,9 @@ } }, "node_modules/fontace": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.0.tgz", - "integrity": "sha512-czoqATrcnxgWb/nAkfyIrRp6Q8biYj7nGnL6zfhTcX+JKKpWHFBnb8uNMw/kZr7u++3Y3wYSYoZgHkCcsuBpBg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.1.tgz", + "integrity": "sha512-9f5g4feWT1jWT8+SbL85aLIRLIXUaDygaM2xPXRmzPYxrOMNok79Lr3FGJoKVNKibE0WCunNiEVG2mwuE+2qEg==", "license": "MIT", "dependencies": { "@types/fontkit": "^2.0.8", @@ -7072,26 +7165,19 @@ } }, "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -7239,27 +7325,6 @@ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", "license": "ISC" }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -7273,32 +7338,10 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -7343,17 +7386,10 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/graphql": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", - "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", + "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", "dev": true, "license": "MIT", "engines": { @@ -7588,15 +7624,15 @@ } }, "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" @@ -7606,16 +7642,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", @@ -7822,17 +7848,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -7885,7 +7900,8 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/is-async-function": { "version": "2.1.1", @@ -8386,9 +8402,9 @@ } }, "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "devOptional": true, "license": "MIT", "bin": { @@ -8411,9 +8427,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -8562,9 +8578,9 @@ "license": "MIT" }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -8599,9 +8615,9 @@ } }, "node_modules/katex": { - "version": "0.16.25", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.25.tgz", - "integrity": "sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==", + "version": "0.16.27", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", + "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -8646,18 +8662,12 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true, - "license": "MIT" - }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -8685,9 +8695,9 @@ } }, "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "devOptional": true, "license": "MPL-2.0", "dependencies": { @@ -8701,22 +8711,43 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", "cpu": [ "arm64" ], @@ -8734,9 +8765,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", "cpu": [ "x64" ], @@ -8754,9 +8785,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", "cpu": [ "x64" ], @@ -8774,9 +8805,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", "cpu": [ "arm" ], @@ -8794,9 +8825,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", "cpu": [ "arm64" ], @@ -8814,9 +8845,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", "cpu": [ "arm64" ], @@ -8834,9 +8865,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", "cpu": [ "x64" ], @@ -8854,9 +8885,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", "cpu": [ "x64" ], @@ -8874,9 +8905,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", "cpu": [ "arm64" ], @@ -8894,9 +8925,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", "cpu": [ "x64" ], @@ -8944,24 +8975,6 @@ "@types/trusted-types": "^2.0.2" } }, - "node_modules/local-pkg": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz", - "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.0.1", - "quansync": "^0.2.8" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -9059,23 +9072,23 @@ } }, "node_modules/magic-string": { - "version": "0.30.19", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", - "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magicast": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", - "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", + "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "source-map-js": "^1.2.1" } }, "node_modules/markdown-table": { @@ -9994,75 +10007,27 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" } }, - "node_modules/mlly/node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mlly/node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "node_modules/modern-tar": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.2.tgz", + "integrity": "sha512-TGG1ZRk1TAQ3neuZwahAHke3rKsSlro+ooMYtjh9sl2gGPVMLMuWiHgwC7im9T5bSM566RSo2Dko56ETgEvZcA==", "dev": true, "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" + "engines": { + "node": ">=18.0.0" } }, "node_modules/moment": { @@ -10090,31 +10055,29 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.11.3.tgz", - "integrity": "sha512-878imp8jxIpfzuzxYfX0qqTq1IFQz/1/RBHs/PyirSjzi+xKM/RRfIpIqHSCWjH0GxidrjhgiiXC+DWXNDvT9w==", + "version": "2.12.4", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.4.tgz", + "integrity": "sha512-rHNiVfTyKhzc0EjoXUBVGteNKBevdjOlVC6GlIRXpy+/3LHEIGRovnB5WPjcvmNODVQ1TNFnoa7wsGbd0V3epg==", "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { - "@bundled-es-modules/cookie": "^2.0.1", - "@bundled-es-modules/statuses": "^1.0.1", "@inquirer/confirm": "^5.0.0", - "@mswjs/interceptors": "^0.39.1", + "@mswjs/interceptors": "^0.40.0", "@open-draft/deferred-promise": "^2.2.0", - "@types/cookie": "^0.6.0", - "@types/statuses": "^2.0.4", - "graphql": "^16.8.1", + "@types/statuses": "^2.0.6", + "cookie": "^1.0.2", + "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.7.0", + "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", - "type-fest": "^4.26.1", + "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, @@ -10136,6 +10099,32 @@ } } }, + "node_modules/msw/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.3.1.tgz", + "integrity": "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/muggle-string": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", @@ -10200,58 +10189,16 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-fetch-native": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", "license": "MIT" }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-mock-http": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", - "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", "license": "MIT" }, "node_modules/node-releases": { @@ -10270,6 +10217,18 @@ "node": ">=0.10.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nwsapi": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", @@ -10418,14 +10377,14 @@ } }, "node_modules/ofetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", - "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", "license": "MIT", "dependencies": { - "destr": "^2.0.3", - "node-fetch-native": "^1.6.4", - "ufo": "^1.5.4" + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" } }, "node_modules/ohash": { @@ -10446,15 +10405,6 @@ "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/one-time": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", @@ -10471,9 +10421,9 @@ "license": "MIT" }, "node_modules/oniguruma-to-es": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", - "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", + "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", "license": "MIT", "dependencies": { "oniguruma-parser": "^0.12.1", @@ -10542,15 +10492,6 @@ "node": ">= 0.8.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -10637,9 +10578,9 @@ } }, "node_modules/p-queue": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.1", @@ -10665,14 +10606,10 @@ } }, "node_modules/package-manager-detector": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", - "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "quansync": "^0.2.7" - } + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" }, "node_modules/pako": { "version": "0.2.9", @@ -10736,9 +10673,9 @@ } }, "node_modules/patch-package": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", - "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", "license": "MIT", "dependencies": { "@yarnpkg/lockfile": "^1.1.0", @@ -10746,15 +10683,14 @@ "ci-info": "^3.7.0", "cross-spawn": "^7.0.3", "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", + "fs-extra": "^10.0.0", "json-stable-stringify": "^1.0.2", "klaw-sync": "^6.0.0", "minimist": "^1.2.6", "open": "^7.4.2", - "rimraf": "^2.6.3", "semver": "^7.5.3", "slash": "^2.0.0", - "tmp": "^0.0.33", + "tmp": "^0.2.4", "yaml": "^2.2.2" }, "bin": { @@ -10797,15 +10733,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -10846,6 +10773,12 @@ "node": ">= 14.16" } }, + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", + "license": "ISC" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -10865,25 +10798,25 @@ } }, "node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", "dev": true, "license": "MIT", "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", - "pathe": "^2.0.3" + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" } }, "node_modules/playwright": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz", - "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.55.0" + "playwright-core": "1.57.0" }, "bin": { "playwright": "cli.js" @@ -10896,9 +10829,9 @@ } }, "node_modules/playwright-core": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz", - "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==", + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10991,10 +10924,11 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, + "license": "MIT", "peer": true, "bin": { "prettier": "bin/prettier.cjs" @@ -11023,13 +10957,13 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.14", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz", - "integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz", + "integrity": "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.21.3" + "node": ">=20.19" }, "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", @@ -11042,14 +10976,12 @@ "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", - "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", - "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "peerDependenciesMeta": { @@ -11080,9 +11012,6 @@ "prettier-plugin-css-order": { "optional": true }, - "prettier-plugin-import-sort": { - "optional": true - }, "prettier-plugin-jsdoc": { "optional": true }, @@ -11101,9 +11030,6 @@ "prettier-plugin-sort-imports": { "optional": true }, - "prettier-plugin-style-order": { - "optional": true - }, "prettier-plugin-svelte": { "optional": true } @@ -11219,23 +11145,6 @@ "node": ">=6" } }, - "node_modules/quansync": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.8.tgz", - "integrity": "sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/antfu" - }, - { - "type": "individual", - "url": "https://github.com/sponsors/sxzz" - } - ], - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11412,9 +11321,9 @@ "license": "MIT" }, "node_modules/regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", - "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" @@ -11741,19 +11650,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/rollup": { "version": "4.34.9", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", @@ -11934,6 +11830,12 @@ "suf-log": "^2.5.3" } }, + "node_modules/sax": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -11958,9 +11860,9 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -12143,17 +12045,17 @@ } }, "node_modules/shiki": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz", - "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.20.0.tgz", + "integrity": "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.13.0", - "@shikijs/engine-javascript": "3.13.0", - "@shikijs/engine-oniguruma": "3.13.0", - "@shikijs/langs": "3.13.0", - "@shikijs/themes": "3.13.0", - "@shikijs/types": "3.13.0", + "@shikijs/core": "3.20.0", + "@shikijs/engine-javascript": "3.20.0", + "@shikijs/engine-oniguruma": "3.20.0", + "@shikijs/langs": "3.20.0", + "@shikijs/themes": "3.20.0", + "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } @@ -12259,6 +12161,7 @@ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "license": "MIT", + "optional": true, "dependencies": { "is-arrayish": "^0.3.1" } @@ -12294,9 +12197,9 @@ } }, "node_modules/smol-toml": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", - "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.5.2.tgz", + "integrity": "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -12633,6 +12536,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgo": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", + "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.4.1" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -12658,18 +12595,31 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tailwindcss": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", - "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { @@ -12680,34 +12630,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -12731,16 +12653,17 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -12802,15 +12725,12 @@ "optional": true }, "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=14.14" } }, "node_modules/to-regex-range": { @@ -13110,9 +13030,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", "peer": true, "bin": { @@ -13124,9 +13044,9 @@ } }, "node_modules/typescript-auto-import-cache": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.5.tgz", - "integrity": "sha512-fAIveQKsoYj55CozUiBoj4b/7WpN0i4o74wiGY5JVUEoD0XiqDk1tJqTEjgzL2/AizKQrXxyRosSebyDzBZKjw==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.6.tgz", + "integrity": "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13134,16 +13054,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.44.1.tgz", - "integrity": "sha512-0ws8uWGrUVTjEeN2OM4K1pLKHK/4NiNP/vz6ns+LjT/6sqpaYzIVFajZb1fj/IDwpsrrHb3Jy0Qm5u9CPcKaeg==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.50.0.tgz", + "integrity": "sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.44.1", - "@typescript-eslint/parser": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1", - "@typescript-eslint/utils": "8.44.1" + "@typescript-eslint/eslint-plugin": "8.50.0", + "@typescript-eslint/parser": "8.50.0", + "@typescript-eslint/typescript-estree": "8.50.0", + "@typescript-eslint/utils": "8.50.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -13240,9 +13160,9 @@ } }, "node_modules/unifont": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.5.2.tgz", - "integrity": "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.6.0.tgz", + "integrity": "sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA==", "license": "MIT", "dependencies": { "css-tree": "^3.0.0", @@ -13360,9 +13280,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -13495,9 +13415,9 @@ } }, "node_modules/vite": { - "version": "6.3.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", - "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", "peer": true, "dependencies": { @@ -13729,9 +13649,9 @@ } }, "node_modules/volar-service-css": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.62.tgz", - "integrity": "sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.67.tgz", + "integrity": "sha512-zV7C6enn9T9tuvQ6iSUyYEs34iPXR69Pf9YYWpbFYPWzVs22w96BtE8p04XYXbmjU6unt5oFt+iLL77bMB5fhA==", "dev": true, "license": "MIT", "dependencies": { @@ -13749,13 +13669,13 @@ } }, "node_modules/volar-service-emmet": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.62.tgz", - "integrity": "sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.67.tgz", + "integrity": "sha512-UDBL5x7KptmuJZNCCXMlCndMhFult/tj+9jXq3FH1ZGS1E4M/1U5hC06pg1c6e4kn+vnR6bqmvX0vIhL4f98+A==", "dev": true, "license": "MIT", "dependencies": { - "@emmetio/css-parser": "^0.4.0", + "@emmetio/css-parser": "^0.4.1", "@emmetio/html-matcher": "^1.3.0", "@vscode/emmet-helper": "^2.9.3", "vscode-uri": "^3.0.8" @@ -13770,9 +13690,9 @@ } }, "node_modules/volar-service-html": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.62.tgz", - "integrity": "sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.67.tgz", + "integrity": "sha512-ljREMF79JbcjNvObiv69HK2HCl5UT7WTD10zi6CRFUHMbPfiF2UZ42HGLsEGSzaHGZz6H4IFjSS/qfENRLUviQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13790,9 +13710,9 @@ } }, "node_modules/volar-service-prettier": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.62.tgz", - "integrity": "sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.67.tgz", + "integrity": "sha512-B4KnPJPNWFTkEDa6Fn08i5PpO6T1CecmLLTFZoXz2eI4Fxwba/3nDaaVSsEP7e/vEe+U5YqV9fBzayJT71G5xg==", "dev": true, "license": "MIT", "dependencies": { @@ -13812,15 +13732,15 @@ } }, "node_modules/volar-service-typescript": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.62.tgz", - "integrity": "sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.67.tgz", + "integrity": "sha512-rfQBy36Rm1PU9vLWHk8BYJ4r2j/CI024vocJcH4Nb6K2RTc2Irmw6UOVY5DdGiPRV5r+e10wLMK5njj/EcL8sA==", "dev": true, "license": "MIT", "dependencies": { "path-browserify": "^1.0.1", "semver": "^7.6.2", - "typescript-auto-import-cache": "^0.3.3", + "typescript-auto-import-cache": "^0.3.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" @@ -13835,9 +13755,9 @@ } }, "node_modules/volar-service-typescript-twoslash-queries": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.62.tgz", - "integrity": "sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.67.tgz", + "integrity": "sha512-LD2R7WivDYp1SPgZrxx/0222xVTitDjm36oKo5+bfYG5kEgnw+BOPVHdwmvpJKg/RfssfxDI1ouwD4XkEDEfbA==", "dev": true, "license": "MIT", "dependencies": { @@ -13853,14 +13773,14 @@ } }, "node_modules/volar-service-yaml": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.62.tgz", - "integrity": "sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==", + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.67.tgz", + "integrity": "sha512-jkdP/RF6wPIXEE3Ktnd81oJPn7aAvnVSiaqQHThC2Hrvo6xd9pEcqtbBUI+YfqVgvcMtXAkbtNO61K2GPhAiuA==", "dev": true, "license": "MIT", "dependencies": { "vscode-uri": "^3.0.8", - "yaml-language-server": "~1.15.0" + "yaml-language-server": "~1.19.2" }, "peerDependencies": { "@volar/language-service": "~2.4.0" @@ -13872,29 +13792,29 @@ } }, "node_modules/vscode-css-languageservice": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.2.tgz", - "integrity": "sha512-GEpPxrUTAeXWdZWHev1OJU9lz2Q2/PPBxQ2TIRmLGvQiH3WZbqaNoute0n0ewxlgtjzTW3AKZT+NHySk5Rf4Eg==", + "version": "6.3.9", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.9.tgz", + "integrity": "sha512-1tLWfp+TDM5ZuVWht3jmaY5y7O6aZmpeXLoHl5bv1QtRsRKt4xYGRMmdJa5Pqx/FTkgRbsna9R+Gn2xE+evVuA==", "dev": true, "license": "MIT", "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", - "vscode-uri": "^3.0.8" + "vscode-uri": "^3.1.0" } }, "node_modules/vscode-html-languageservice": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.3.1.tgz", - "integrity": "sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.6.1.tgz", + "integrity": "sha512-5Mrqy5CLfFZUgkyhNZLA1Ye5g12Cb/v6VM7SxUzZUaRKWMDz4md+y26PrfRTSU0/eQAl3XpO9m2og+GGtDMuaA==", "dev": true, "license": "MIT", "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.0.8" + "vscode-uri": "^3.1.0" } }, "node_modules/vscode-json-languageservice": { @@ -14032,17 +13952,6 @@ "node": ">=18" } }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/whatwg-url": { "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", @@ -14204,14 +14113,14 @@ } }, "node_modules/winston": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", - "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", "license": "MIT", "peer": true, "dependencies": { "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", + "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", @@ -14297,12 +14206,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -14368,40 +14271,42 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yaml-language-server": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.15.0.tgz", - "integrity": "sha512-N47AqBDCMQmh6mBLmI6oqxryHRzi33aPFPsJhYy3VTUGCdLHYjGh4FZzpUjRlphaADBBkDmnkM/++KNIOHi5Rw==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.19.2.tgz", + "integrity": "sha512-9F3myNmJzUN/679jycdMxqtydPSDRAarSj3wPiF7pchEPnO9Dg07Oc+gIYLqXR4L+g+FSEVXXv2+mr54StLFOg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^8.11.0", + "@vscode/l10n": "^0.0.18", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", "lodash": "4.17.21", + "prettier": "^3.5.0", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", - "vscode-languageserver": "^7.0.0", + "vscode-languageserver": "^9.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", - "vscode-nls": "^5.0.0", "vscode-uri": "^3.0.2", - "yaml": "2.2.2" + "yaml": "2.7.1" }, "bin": { "yaml-language-server": "bin/yaml-language-server" - }, - "optionalDependencies": { - "prettier": "2.8.7" } }, "node_modules/yaml-language-server/node_modules/ajv": { @@ -14410,6 +14315,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -14421,6 +14327,21 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/yaml-language-server/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/yaml-language-server/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -14428,23 +14349,6 @@ "dev": true, "license": "MIT" }, - "node_modules/yaml-language-server/node_modules/prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/yaml-language-server/node_modules/request-light": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz", @@ -14452,53 +14356,15 @@ "dev": true, "license": "MIT" }, - "node_modules/yaml-language-server/node_modules/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/yaml-language-server/node_modules/vscode-languageserver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", - "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.16.0" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/yaml-language-server/node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "node_modules/yaml-language-server/node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", - "dev": true, - "license": "MIT" - }, "node_modules/yaml-language-server/node_modules/yaml": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", - "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "dev": true, "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -14629,12 +14495,12 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.24.6", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", - "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", + "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", "license": "ISC", "peerDependencies": { - "zod": "^3.24.1" + "zod": "^3.25 || ^4" } }, "node_modules/zod-to-ts": { diff --git a/website/package.json b/website/package.json index c5a791dc5..ccb5cf6c4 100644 --- a/website/package.json +++ b/website/package.json @@ -23,64 +23,64 @@ "e2e": "playwright test" }, "dependencies": { - "@astrojs/node": "^9.4.4", + "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.1", + "@tanstack/react-query": "^5.90.12", "astro": "^5.13.10", "auth-astro": "^4.2.0", - "axios": "^1.12.2", - "cookie": "^1.0.2", - "dayjs": "^1.11.18", - "katex": "^0.16.25", - "patch-package": "^8.0.0", + "axios": "^1.13.2", + "cookie": "^1.1.1", + "dayjs": "^1.11.19", + "katex": "^0.16.27", + "patch-package": "^8.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-katex": "^3.1.0", "react-toastify": "^11.0.5", "uuid": "^11.1.0", - "winston": "^3.17.0", + "winston": "^3.19.0", "winston-daily-rotate-file": "^5.0.0", - "yaml": "^2.8.1" + "yaml": "^2.8.2" }, "devDependencies": { - "@astrojs/check": "^0.9.4", - "@astrojs/react": "^4.3.1", - "@eslint/js": "^9.36.0", + "@astrojs/check": "^0.9.6", + "@astrojs/react": "^4.4.2", + "@eslint/js": "^9.39.2", "@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi-light": "^1.2.2", - "@iconify/tailwind4": "^1.0.6", - "@playwright/test": "^1.55.0", - "@tailwindcss/vite": "^4.1.13", - "@tanstack/eslint-plugin-query": "^5.90.1", + "@iconify/tailwind4": "^1.2.0", + "@playwright/test": "^1.57.0", + "@tailwindcss/vite": "^4.1.18", + "@tanstack/eslint-plugin-query": "^5.91.2", "@testing-library/dom": "^10.4.1", - "@testing-library/jest-dom": "^6.8.0", - "@testing-library/react": "^16.3.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.1", "@testing-library/user-event": "^14.6.1", "@types/node": "^24.5.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.44.1", - "@typescript-eslint/parser": "^8.44.1", + "@typescript-eslint/eslint-plugin": "^8.50.0", + "@typescript-eslint/parser": "^8.50.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", - "daisyui": "^5.1.14", + "daisyui": "^5.5.14", "dotenv": "^16.5.0", - "eslint": "^9.36.0", - "eslint-plugin-astro": "^1.3.1", + "eslint": "^9.39.2", + "eslint-plugin-astro": "^1.5.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", - "msw": "^2.11.3", + "msw": "^2.12.4", "playwright": "^1.55.0", - "prettier": "^3.6.2", + "prettier": "^3.7.4", "prettier-plugin-astro": "^0.14.1", - "prettier-plugin-tailwindcss": "^0.6.14", + "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", - "typescript": "^5.9.2", - "typescript-eslint": "^8.44.1", + "typescript": "^5.9.3", + "typescript-eslint": "^8.50.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" From cd368ae2c2196edec8e8a83fe0c77aae9d4b1e90 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer Date: Tue, 16 Dec 2025 09:25:09 +0100 Subject: [PATCH 11/26] chore(website): format --- website/src/pages/index.astro | 4 ++-- website/src/views/BaseView.ts | 3 +-- .../pageStateHandlers/SequencingEffortsPageStateHandler.ts | 6 +++--- .../pageStateHandlers/SingleVariantPageStateHandler.ts | 6 +++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index 6887477bc..f7c21db3e 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -110,8 +110,8 @@ import { Page } from '../types/pages'; Feedback, suggestions, bug reports and active contributions are highly welcome, please create an issue in our Github repository - . For general questions, please contact Chaoran Chen (chaoran.chen@bsse.ethz.ch). For media requests, please - reach out to ETH Zurich Media Relations (mediarelations@hk.ethz.ch). A list of all team members can be found + . For general questions, please contact Chaoran Chen (chaoran.chen@bsse.ethz.ch). For media requests, please reach + out to ETH Zurich Media Relations (mediarelations@hk.ethz.ch). A list of all team members can be found here . diff --git a/website/src/views/BaseView.ts b/website/src/views/BaseView.ts index 11381f4e4..492d416fd 100644 --- a/website/src/views/BaseView.ts +++ b/website/src/views/BaseView.ts @@ -19,8 +19,7 @@ export abstract class BaseView< PageState extends object, Constants extends OrganismConstants, StateHandler extends PageStateHandler, -> implements View -{ +> implements View { public readonly pathname; public readonly viewTitle; public readonly viewBreadcrumbEntries; diff --git a/website/src/views/pageStateHandlers/SequencingEffortsPageStateHandler.ts b/website/src/views/pageStateHandlers/SequencingEffortsPageStateHandler.ts index 9016e37fc..6cb6acae8 100644 --- a/website/src/views/pageStateHandlers/SequencingEffortsPageStateHandler.ts +++ b/website/src/views/pageStateHandlers/SequencingEffortsPageStateHandler.ts @@ -16,9 +16,9 @@ import { parseTextFiltersFromUrl, setSearchFromTextFilters } from './textFilterF import { advancedQueryUrlParam } from '../../components/genspectrum/AdvancedQueryFilter.tsx'; import { formatUrl } from '../../util/formatUrl.ts'; -export class SequencingEffortsStateHandler - implements PageStateHandler -{ +export class SequencingEffortsStateHandler< + PageState extends DatasetAndVariantData = DatasetAndVariantData, +> implements PageStateHandler { protected readonly pathname; constructor( diff --git a/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.ts b/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.ts index 7577f0f0c..79518b758 100644 --- a/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.ts +++ b/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.ts @@ -19,9 +19,9 @@ import { toLapisFilterWithoutVariant } from './toLapisFilterWithoutVariant.ts'; import { advancedQueryUrlParam } from '../../components/genspectrum/AdvancedQueryFilter.tsx'; import { formatUrl } from '../../util/formatUrl.ts'; -export class SingleVariantPageStateHandler - implements PageStateHandler -{ +export class SingleVariantPageStateHandler< + PageState extends DatasetAndVariantData = DatasetAndVariantData, +> implements PageStateHandler { protected readonly pathname; constructor( From 90aa99ebe15195a24bfa8cb342cb5c1346f12156 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer Date: Tue, 16 Dec 2025 09:44:51 +0100 Subject: [PATCH 12/26] chore(website): fix lints --- website/src/components/genspectrum/GsMutationFilter.tsx | 2 +- website/src/components/pageStateSelectors/DynamicDateFilter.tsx | 2 +- website/src/components/views/wasap/WasapPage.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/components/genspectrum/GsMutationFilter.tsx b/website/src/components/genspectrum/GsMutationFilter.tsx index a8d97e663..ea4a63f96 100644 --- a/website/src/components/genspectrum/GsMutationFilter.tsx +++ b/website/src/components/genspectrum/GsMutationFilter.tsx @@ -13,7 +13,7 @@ export function GsMutationFilter({ initialValue, width, enabledMutationTypes, - onMutationChange = () => {}, + onMutationChange, }: { width?: string; initialValue?: MutationFilter | string[] | undefined; diff --git a/website/src/components/pageStateSelectors/DynamicDateFilter.tsx b/website/src/components/pageStateSelectors/DynamicDateFilter.tsx index 26a966a73..61c447345 100644 --- a/website/src/components/pageStateSelectors/DynamicDateFilter.tsx +++ b/website/src/components/pageStateSelectors/DynamicDateFilter.tsx @@ -46,7 +46,7 @@ export function DynamicDateFilter({ // When the value has a "Custom" label, try to match it back to one of the generated options // by comparing dateFrom and dateTo. If there's a match, use that option's label instead of "Custom". const normalizedValue = useMemo(() => { - if (value === undefined || value.label !== CustomDateRangeLabel) { + if (value?.label !== CustomDateRangeLabel) { return value; } diff --git a/website/src/components/views/wasap/WasapPage.tsx b/website/src/components/views/wasap/WasapPage.tsx index 0f87beea0..52f94c8c7 100644 --- a/website/src/components/views/wasap/WasapPage.tsx +++ b/website/src/components/views/wasap/WasapPage.tsx @@ -79,7 +79,7 @@ export const WasapPageInner: FC = ({ wastewaterOrganism, current ) : (
- {displayMutations !== undefined && displayMutations.length === 0 ? ( + {displayMutations?.length === 0 ? ( ) : ( Date: Tue, 16 Dec 2025 11:34:24 +0100 Subject: [PATCH 13/26] refactor(website): migrate "compare to baseline" page to React (#966) * refactor(website): migrate "compare to baseline" page to React resolves #965 * chore(website): fix * chore(website): better memo --- .../GenericCompareToBaselineDataDisplay.tsx | 53 +++++++++++++++++++ .../GenericCompareToBaselinePage.astro | 41 +++++--------- .../compareToBaseline/SelectBaseline.astro | 15 ------ .../compareToBaseline/SelectBaseline.tsx | 19 +++++++ website/tests/CompareToBaselinePage.ts | 38 +++++++++++++ website/tests/compareToBaseline.spec.ts | 27 ++++++++++ website/tests/compareVariants.spec.ts | 23 +------- website/tests/e2e.fixture.ts | 5 ++ website/tests/helpers.ts | 22 +++++++- 9 files changed, 176 insertions(+), 67 deletions(-) create mode 100644 website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx delete mode 100644 website/src/components/views/compareToBaseline/SelectBaseline.astro create mode 100644 website/src/components/views/compareToBaseline/SelectBaseline.tsx create mode 100644 website/tests/CompareToBaselinePage.ts create mode 100644 website/tests/compareToBaseline.spec.ts diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx b/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx new file mode 100644 index 000000000..39dc1bb01 --- /dev/null +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx @@ -0,0 +1,53 @@ +import { type FC, useMemo } from 'react'; + +import { SelectBaseline } from './SelectBaseline.tsx'; +import type { OrganismsConfig } from '../../../config.ts'; +import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; +import { ComponentHeight } from '../../../views/OrganismConstants.ts'; +import type { CompareToBaselineData } from '../../../views/View.ts'; +import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; +import { compareToBaselineViewKey } from '../../../views/viewKeys.ts'; +import { ComponentsGrid } from '../../ComponentsGrid.tsx'; +import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; + +export type GenericCompareToBaselineDisplayProps = { + organismViewKey: `${OrganismWithViewKey}.${typeof compareToBaselineViewKey}`; + organismsConfig: OrganismsConfig; + pageState: CompareToBaselineData; +}; + +export const GenericCompareToBaselineDataDisplay: FC = ({ + organismViewKey, + organismsConfig, + pageState, +}) => { + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const baselineLapisFilter = view.pageStateHandler.baselineFilterToLapisFilter(pageState); + const timeGranularity = chooseGranularityBasedOnDateRange({ + earliestDate: new Date(view.organismConstants.earliestDate), + dateRange: pageState.datasetFilter.dateFilters[view.organismConstants.mainDateField], + }); + + const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); + const noVariantSelected = pageState.variants.size < 1; + + return noVariantSelected ? ( + + ) : ( + + + + ); +}; diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro b/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro index 9229c10c3..5095db10d 100644 --- a/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro @@ -1,14 +1,10 @@ --- -import SelectBaseline from './SelectBaseline.astro'; +import { GenericCompareToBaselineDataDisplay } from './GenericCompareToBaselineDataDisplay'; import { isStaging, getDashboardsConfig } from '../../../config'; import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange'; -import { ComponentHeight } from '../../../views/OrganismConstants'; import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareToBaselineViewKey } from '../../../views/viewKeys'; -import ComponentsGrid from '../../ComponentsGrid.astro'; -import GsPrevalenceOverTime from '../../genspectrum/GsPrevalenceOverTime.astro'; import { CompareVariantsToBaselineStateSelector } from '../../pageStateSelectors/CompareVariantsToBaselineStateSelector'; import { CompareToBaselineSelectorFallback } from '../../pageStateSelectors/FallbackElement'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; @@ -24,12 +20,6 @@ const view = ServerSide.routing.getOrganismView(organismViewKey); const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); -const baselineLapisFilter = view.pageStateHandler.baselineFilterToLapisFilter(pageState); -const timeGranularity = chooseGranularityBasedOnDateRange({ - earliestDate: new Date(view.organismConstants.earliestDate), - dateRange: pageState.datasetFilter.dateFilters[view.organismConstants.mainDateField], -}); - const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); const noVariantSelected = pageState.variants.size < 1; @@ -40,6 +30,8 @@ const downloadLinks = noVariantSelected filter: lapisFilter, downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, })); + +const organismConfig = getDashboardsConfig().dashboards.organisms; --- @@ -47,27 +39,18 @@ const downloadLinks = noVariantSelected slot='filters' initialPageState={pageState} organismViewKey={organismViewKey} - organismsConfig={getDashboardsConfig().dashboards.organisms} + organismsConfig={organismConfig} enableAdvancedQueryFilter={isStaging()} client:only='react' > - { - noVariantSelected ? ( - - ) : ( - - - - ) - } +
+ +
diff --git a/website/src/components/views/compareToBaseline/SelectBaseline.astro b/website/src/components/views/compareToBaseline/SelectBaseline.astro deleted file mode 100644 index c01f303b1..000000000 --- a/website/src/components/views/compareToBaseline/SelectBaseline.astro +++ /dev/null @@ -1,15 +0,0 @@ ---- -import { PageHeadline } from '../../../styles/containers/PageHeadline'; ---- - -
- Analyze a variant compared to a baseline -
-

To proceed, please select a variant filter.

-

- If no baseline is selected all sequences will be used as a baseline for comparing against sequences with a - specified variant. Note that the dataset filter is applied to the entire dataset including both the baseline - and variant subsets. Adjust the dataset filter as needed to refine your selection. -

-
-
diff --git a/website/src/components/views/compareToBaseline/SelectBaseline.tsx b/website/src/components/views/compareToBaseline/SelectBaseline.tsx new file mode 100644 index 000000000..c2132159c --- /dev/null +++ b/website/src/components/views/compareToBaseline/SelectBaseline.tsx @@ -0,0 +1,19 @@ +import type { FC } from 'react'; + +import { PageHeadline } from '../../../styles/containers/PageHeadline.tsx'; + +export const SelectBaseline: FC = () => { + return ( +
+ Analyze a variant compared to a baseline +
+

To proceed, please select a variant filter.

+

+ If no baseline is selected all sequences will be used as a baseline for comparing against sequences + with a specified variant. Note that the dataset filter is applied to the entire dataset including + both the baseline and variant subsets. Adjust the dataset filter as needed to refine your selection. +

+
+
+ ); +}; diff --git a/website/tests/CompareToBaselinePage.ts b/website/tests/CompareToBaselinePage.ts new file mode 100644 index 000000000..9f41d2784 --- /dev/null +++ b/website/tests/CompareToBaselinePage.ts @@ -0,0 +1,38 @@ +import { type Page } from '@playwright/test'; + +import { CompareVariantsPage } from './CompareVariantsPage.ts'; +import { paths } from '../src/types/Organism.ts'; +import { type OrganismWithViewKey } from '../src/views/routing'; +import { compareToBaselineViewKey } from '../src/views/viewKeys'; + +export class CompareToBaselinePage extends CompareVariantsPage { + public readonly selectVariantsMessage; + public readonly mutationField; + + constructor(page: Page) { + super(page); + this.selectVariantsMessage = this.page.getByText('Analyze a variant compared to a baseline', { exact: false }); + this.mutationField = this.page.getByRole('combobox', { name: 'Enter a mutation', exact: false }); + } + + public async goto(organism: OrganismWithViewKey) { + await this.page.goto(`${paths[organism].basePath}/compare-to-baseline`); + } + + public async selectBaseline(options: { lineage?: string; lineageFieldPlaceholder?: string; mutation?: string }) { + if (options.lineage && options.lineageFieldPlaceholder) { + const { lineage, lineageFieldPlaceholder } = options; + + const lineageFieldLocator = this.page.getByPlaceholder(lineageFieldPlaceholder); + await lineageFieldLocator.first().fill(lineage); + + const selectedLineage = this.page.getByRole('option', { name: lineage, exact: false }); + await selectedLineage.first().click(); + } + + if (options.mutation) { + await this.mutationField.first().fill(options.mutation); + await this.mutationField.first().press('Enter'); + } + } +} diff --git a/website/tests/compareToBaseline.spec.ts b/website/tests/compareToBaseline.spec.ts new file mode 100644 index 000000000..b78929117 --- /dev/null +++ b/website/tests/compareToBaseline.spec.ts @@ -0,0 +1,27 @@ +import { expect } from '@playwright/test'; + +import { test } from './e2e.fixture.ts'; +import { organismOptions, organismsWithView } from './helpers.ts'; +import { compareToBaselineViewKey } from '../src/views/viewKeys'; + +test.describe('The Compare To Baseline page', () => { + for (const organism of organismsWithView(compareToBaselineViewKey)) { + test(`should show diagrams after selecting two variants and a baseline - ${organism}`, async ({ + compareToBaselinePage, + }) => { + const options = organismOptions[organism]; + + await compareToBaselinePage.goto(organism); + await expect(compareToBaselinePage.selectVariantsMessage).toBeVisible(); + await expect(compareToBaselinePage.diagramTitle('Prevalence Over Time')).not.toBeVisible(); + + await compareToBaselinePage.selectDateRange('All times'); + await compareToBaselinePage.selectBaseline(options); + await compareToBaselinePage.addVariant(options); + await compareToBaselinePage.submitFilters(); + + await expect(compareToBaselinePage.diagramTitle('Prevalence Over Time')).toBeVisible(); + await compareToBaselinePage.expectToSeeNoComponentErrors(); + }); + } +}); diff --git a/website/tests/compareVariants.spec.ts b/website/tests/compareVariants.spec.ts index eef8b89c7..8ffbdd53f 100644 --- a/website/tests/compareVariants.spec.ts +++ b/website/tests/compareVariants.spec.ts @@ -1,30 +1,9 @@ import { expect } from '@playwright/test'; import { test } from './e2e.fixture.ts'; -import { organismsWithView } from './helpers.ts'; -import { Organisms } from '../src/types/Organism.ts'; +import { organismOptions, organismsWithView } from './helpers.ts'; import { compareVariantsViewKey } from '../src/views/viewKeys'; -const organismOptions = { - [Organisms.covid]: { lineage: 'JN.1*', lineageFieldPlaceholder: 'Nextclade pango lineage' }, - [Organisms.h5n1]: { lineage: '2.3.4.4b', lineageFieldPlaceholder: 'Clade' }, - [Organisms.h1n1pdm]: { lineage: '6B.1A.5a.2a.1', lineageFieldPlaceholder: 'Clade HA' }, - [Organisms.h3n2]: { lineage: '3C.2a1b', lineageFieldPlaceholder: 'Clade HA' }, - [Organisms.victoria]: { lineage: 'V1A.3a.2', lineageFieldPlaceholder: 'Clade HA' }, - [Organisms.westNile]: { lineage: '1A', lineageFieldPlaceholder: 'Lineage' }, - [Organisms.rsvA]: { lineage: 'A.D.5.2', lineageFieldPlaceholder: 'Lineage' }, - [Organisms.rsvB]: { lineage: 'B.D.E.1', lineageFieldPlaceholder: 'Lineage' }, - [Organisms.mpox]: { lineage: 'F.1', lineageFieldPlaceholder: 'Lineage' }, - [Organisms.ebolaSudan]: { mutation: 'G5902T' }, - [Organisms.ebolaZaire]: { mutation: 'T18365C' }, - [Organisms.cchf]: { mutation: 'M:G3565A' }, - [Organisms.denv1]: { lineage: '1I_K.1.1', lineageFieldPlaceholder: 'Clade' }, - [Organisms.denv2]: { lineage: '2II_F.1.1', lineageFieldPlaceholder: 'Clade' }, - [Organisms.denv3]: { lineage: '3III_B.3.2', lineageFieldPlaceholder: 'Clade' }, - [Organisms.denv4]: { lineage: '4II_B.1.2', lineageFieldPlaceholder: 'Clade' }, - [Organisms.measles]: { lineage: 'B3', lineageFieldPlaceholder: 'Genotype' }, -}; - test.describe('The Compare Variants page', () => { for (const organism of organismsWithView(compareVariantsViewKey)) { test(`should show diagrams after selecting two variants ${organism}`, async ({ compareVariantsPage }) => { diff --git a/website/tests/e2e.fixture.ts b/website/tests/e2e.fixture.ts index 561452517..6a655f331 100644 --- a/website/tests/e2e.fixture.ts +++ b/website/tests/e2e.fixture.ts @@ -1,11 +1,13 @@ import { test as base } from '@playwright/test'; +import { CompareToBaselinePage } from './CompareToBaselinePage.ts'; import { CompareVariantsPage } from './CompareVariantsPage.ts'; import { SequencingEffortsPage } from './SequencingEffortsPage.ts'; type E2EFixture = { compareVariantsPage: CompareVariantsPage; sequencingEffortsPage: SequencingEffortsPage; + compareToBaselinePage: CompareToBaselinePage; }; export const test = base.extend({ @@ -15,4 +17,7 @@ export const test = base.extend({ sequencingEffortsPage: async ({ page }, use) => { await use(new SequencingEffortsPage(page)); }, + compareToBaselinePage: async ({ page }, use) => { + await use(new CompareToBaselinePage(page)); + }, }); diff --git a/website/tests/helpers.ts b/website/tests/helpers.ts index 55120cbc5..2e3edba44 100644 --- a/website/tests/helpers.ts +++ b/website/tests/helpers.ts @@ -1,7 +1,27 @@ -import { allOrganisms } from '../src/types/Organism.ts'; +import { allOrganisms, Organisms } from '../src/types/Organism.ts'; import type { OrganismWithViewKey } from '../src/views/routing.ts'; import { ServerSide } from '../src/views/serverSideRouting.ts'; export function organismsWithView(viewKey: ViewKey): OrganismWithViewKey[] { return allOrganisms.filter((organism) => ServerSide.routing.isOrganismWithViewKey(organism, viewKey)); } + +export const organismOptions = { + [Organisms.covid]: { lineage: 'JN.1*', lineageFieldPlaceholder: 'Nextclade pango lineage' }, + [Organisms.h5n1]: { lineage: '2.3.4.4b', lineageFieldPlaceholder: 'Clade' }, + [Organisms.h1n1pdm]: { lineage: '6B.1A.5a.2a.1', lineageFieldPlaceholder: 'Clade HA' }, + [Organisms.h3n2]: { lineage: '3C.2a1b', lineageFieldPlaceholder: 'Clade HA' }, + [Organisms.victoria]: { lineage: 'V1A.3a.2', lineageFieldPlaceholder: 'Clade HA' }, + [Organisms.westNile]: { lineage: '1A', lineageFieldPlaceholder: 'Lineage' }, + [Organisms.rsvA]: { lineage: 'A.D.5.2', lineageFieldPlaceholder: 'Lineage' }, + [Organisms.rsvB]: { lineage: 'B.D.E.1', lineageFieldPlaceholder: 'Lineage' }, + [Organisms.mpox]: { lineage: 'F.1', lineageFieldPlaceholder: 'Lineage' }, + [Organisms.ebolaSudan]: { mutation: 'G5902T' }, + [Organisms.ebolaZaire]: { mutation: 'T18365C' }, + [Organisms.cchf]: { mutation: 'M:G3565A' }, + [Organisms.denv1]: { lineage: '1I_K.1.1', lineageFieldPlaceholder: 'Clade' }, + [Organisms.denv2]: { lineage: '2II_F.1.1', lineageFieldPlaceholder: 'Clade' }, + [Organisms.denv3]: { lineage: '3III_B.3.2', lineageFieldPlaceholder: 'Clade' }, + [Organisms.denv4]: { lineage: '4II_B.1.2', lineageFieldPlaceholder: 'Clade' }, + [Organisms.measles]: { lineage: 'B3', lineageFieldPlaceholder: 'Genotype' }, +}; From ae2e48eb4fc6d19e7094a95fbecff474b9118069 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Wed, 17 Dec 2025 09:59:36 +0100 Subject: [PATCH 14/26] ci(website): only execute e2e tests against Chromium on feature branches (#976) to speed up tests --- .github/workflows/e2e.yml | 7 ++++++- website/package.json | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index fc416fcdd..5f6f2e4c0 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -57,9 +57,14 @@ jobs: WEBSITE_TAG: ${{ steps.branchTag.outputs.branchTag }} BACKEND_TAG: ${{ steps.branchTag.outputs.branchTag }} - - name: Run Playwright tests + - name: Run Playwright tests (all browsers) + if: github.ref == 'refs/heads/main' run: npm run e2e + - name: Run Playwright tests (chromium only) + if: github.ref != 'refs/heads/main' + run: npm run e2e:chromium + - uses: actions/upload-artifact@v6 if: ${{ !cancelled() }} with: diff --git a/website/package.json b/website/package.json index ccb5cf6c4..1d2a59d63 100644 --- a/website/package.json +++ b/website/package.json @@ -20,7 +20,8 @@ "test:headed": "vitest --browser.headless false", "test:browser": "vitest --project browser", "test:browser:headed": "vitest --project browser --browser.headless false", - "e2e": "playwright test" + "e2e": "playwright test", + "e2e:chromium": "playwright test --project=chromium" }, "dependencies": { "@astrojs/node": "^9.5.1", From 12820ec49a426096a656ed2cad9fde600680bff0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:22:08 +0100 Subject: [PATCH 15/26] chore(website): bump the minorandpatch group across 1 directory with 6 updates (#988) Bumps the minorandpatch group with 6 updates in the /website directory: | Package | From | To | | --- | --- | --- | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.90.12` | `5.90.15` | | [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `5.16.5` | `5.16.6` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.50.0` | `8.51.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.50.0` | `8.51.0` | | [msw](https://github.com/mswjs/msw) | `2.12.4` | `2.12.7` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.50.0` | `8.51.0` | Updates `@tanstack/react-query` from 5.90.12 to 5.90.15 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.90.15/packages/react-query) Updates `astro` from 5.16.5 to 5.16.6 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/astro@5.16.6/packages/astro) Updates `@typescript-eslint/eslint-plugin` from 8.50.0 to 8.51.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.50.0 to 8.51.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/parser) Updates `msw` from 2.12.4 to 2.12.7 - [Release notes](https://github.com/mswjs/msw/releases) - [Changelog](https://github.com/mswjs/msw/blob/main/CHANGELOG.md) - [Commits](https://github.com/mswjs/msw/compare/v2.12.4...v2.12.7) Updates `typescript-eslint` from 8.50.0 to 8.51.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.51.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@tanstack/react-query" dependency-version: 5.90.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: astro dependency-version: 5.16.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.51.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@typescript-eslint/parser" dependency-version: 8.51.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: msw dependency-version: 2.12.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: typescript-eslint dependency-version: 8.51.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- website/package-lock.json | 172 +++++++++++++++++++------------------- website/package.json | 12 +-- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index 54a935833..62b2c6c83 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -12,8 +12,8 @@ "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.12", - "astro": "^5.13.10", + "@tanstack/react-query": "^5.90.15", + "astro": "^5.16.6", "auth-astro": "^4.2.0", "axios": "^1.13.2", "cookie": "^1.1.1", @@ -48,8 +48,8 @@ "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.50.0", - "@typescript-eslint/parser": "^8.50.0", + "@typescript-eslint/eslint-plugin": "^8.51.0", + "@typescript-eslint/parser": "^8.51.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", "daisyui": "^5.5.14", @@ -59,14 +59,14 @@ "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", - "msw": "^2.12.4", + "msw": "^2.12.7", "playwright": "^1.55.0", "prettier": "^3.7.4", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", "typescript": "^5.9.3", - "typescript-eslint": "^8.50.0", + "typescript-eslint": "^8.51.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" @@ -3154,9 +3154,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.90.12", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", - "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", + "version": "5.90.15", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.15.tgz", + "integrity": "sha512-mInIZNUZftbERE+/Hbtswfse49uUQwch46p+27gP9DWJL927UjnaWEF2t3RMOqBcXbfMdcNkPe06VyUIAZTV1g==", "license": "MIT", "funding": { "type": "github", @@ -3164,12 +3164,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.12", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", - "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", + "version": "5.90.15", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.15.tgz", + "integrity": "sha512-uQvnDDcTOgJouNtAyrgRej+Azf0U5WDov3PXmHFUBc+t1INnAYhIlpZtCGNBLwCN41b43yO7dPNZu8xWkUFBwQ==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.90.12" + "@tanstack/query-core": "5.90.15" }, "funding": { "type": "github", @@ -3514,20 +3514,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz", - "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.51.0.tgz", + "integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/type-utils": "8.50.0", - "@typescript-eslint/utils": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/type-utils": "8.51.0", + "@typescript-eslint/utils": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3537,7 +3537,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.50.0", + "@typescript-eslint/parser": "^8.51.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -3553,17 +3553,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz", - "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.51.0.tgz", + "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", "debug": "^4.3.4" }, "engines": { @@ -3579,14 +3579,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz", - "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", + "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.50.0", - "@typescript-eslint/types": "^8.50.0", + "@typescript-eslint/tsconfig-utils": "^8.51.0", + "@typescript-eslint/types": "^8.51.0", "debug": "^4.3.4" }, "engines": { @@ -3601,14 +3601,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz", - "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", + "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0" + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3619,9 +3619,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz", - "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", + "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", "dev": true, "license": "MIT", "engines": { @@ -3636,17 +3636,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz", - "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.51.0.tgz", + "integrity": "sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/utils": "8.50.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/utils": "8.51.0", "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3661,9 +3661,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz", - "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", + "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", "dev": true, "license": "MIT", "engines": { @@ -3675,21 +3675,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz", - "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", + "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.50.0", - "@typescript-eslint/tsconfig-utils": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/project-service": "8.51.0", + "@typescript-eslint/tsconfig-utils": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", "debug": "^4.3.4", "minimatch": "^9.0.4", "semver": "^7.6.0", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3703,16 +3703,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz", - "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", + "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0" + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3727,13 +3727,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz", - "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", + "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/types": "8.51.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -4417,9 +4417,9 @@ } }, "node_modules/astro": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.5.tgz", - "integrity": "sha512-QeuM4xzTR0QuXFDNlGVW0BW7rcquKFIkylaPeM4ufii0/RRiPTYtwxDYVZ3KfiMRuuc+nbLD0214kMKTvz/yvQ==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.6.tgz", + "integrity": "sha512-6mF/YrvwwRxLTu+aMEa5pwzKUNl5ZetWbTyZCs9Um0F12HUmxUiF5UHiZPy4rifzU3gtpM3xP2DfdmkNX9eZRg==", "license": "MIT", "peer": true, "dependencies": { @@ -10055,9 +10055,9 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.12.4", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.4.tgz", - "integrity": "sha512-rHNiVfTyKhzc0EjoXUBVGteNKBevdjOlVC6GlIRXpy+/3LHEIGRovnB5WPjcvmNODVQ1TNFnoa7wsGbd0V3epg==", + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.7.tgz", + "integrity": "sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -12855,9 +12855,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.3.0.tgz", + "integrity": "sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==", "dev": true, "license": "MIT", "engines": { @@ -13054,16 +13054,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.50.0.tgz", - "integrity": "sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.51.0.tgz", + "integrity": "sha512-jh8ZuM5oEh2PSdyQG9YAEM1TCGuWenLSuSUhf/irbVUNW9O5FhbFVONviN2TgMTBnUmyHv7E56rYnfLZK6TkiA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.50.0", - "@typescript-eslint/parser": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/utils": "8.50.0" + "@typescript-eslint/eslint-plugin": "8.51.0", + "@typescript-eslint/parser": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0", + "@typescript-eslint/utils": "8.51.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/website/package.json b/website/package.json index 1d2a59d63..15fe68425 100644 --- a/website/package.json +++ b/website/package.json @@ -27,8 +27,8 @@ "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.12", - "astro": "^5.13.10", + "@tanstack/react-query": "^5.90.15", + "astro": "^5.16.6", "auth-astro": "^4.2.0", "axios": "^1.13.2", "cookie": "^1.1.1", @@ -63,8 +63,8 @@ "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.50.0", - "@typescript-eslint/parser": "^8.50.0", + "@typescript-eslint/eslint-plugin": "^8.51.0", + "@typescript-eslint/parser": "^8.51.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", "daisyui": "^5.5.14", @@ -74,14 +74,14 @@ "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", - "msw": "^2.12.4", + "msw": "^2.12.7", "playwright": "^1.55.0", "prettier": "^3.7.4", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", "typescript": "^5.9.3", - "typescript-eslint": "^8.50.0", + "typescript-eslint": "^8.51.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" From 8e7c7832d8603074831f5c883d96ba2cad21a09d Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Wed, 7 Jan 2026 10:49:12 +0100 Subject: [PATCH 16/26] refactor(website): migrate "compare side-by-side" to React (#975) * refactor(website): migrate "compare side-by-side" to React * chore(website): add test * chore(website): fix lints * chore(website): fix type name --- .../GenericCompareSideBySideDataDisplay.tsx | 85 +++++++++++++++++++ .../GenericCompareSideBySidePage.astro | 72 +++------------- website/tests/CompareSideBySidePage.ts | 50 +++++++++++ website/tests/CompareToBaselinePage.ts | 8 +- website/tests/CompareVariantsPage.ts | 8 +- website/tests/ViewPage.ts | 13 ++- website/tests/compareSideBySide.spec.ts | 38 +++++++++ website/tests/e2e.fixture.ts | 5 ++ website/tests/helpers.ts | 2 + 9 files changed, 207 insertions(+), 74 deletions(-) create mode 100644 website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx create mode 100644 website/tests/CompareSideBySidePage.ts create mode 100644 website/tests/compareSideBySide.spec.ts diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx new file mode 100644 index 000000000..4b84d3b47 --- /dev/null +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx @@ -0,0 +1,85 @@ +import { type FC, useMemo } from 'react'; + +import type { OrganismsConfig } from '../../../config.ts'; +import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; +import { ComponentHeight } from '../../../views/OrganismConstants.ts'; +import type { DatasetAndVariantData } from '../../../views/View.ts'; +import { toLapisFilterWithoutVariant } from '../../../views/pageStateHandlers/toLapisFilterWithoutVariant.ts'; +import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; +import { compareSideBySideViewKey } from '../../../views/viewKeys.ts'; +import { GsAggregate } from '../../genspectrum/GsAggregate.tsx'; +import { GsMutations } from '../../genspectrum/GsMutations.tsx'; +import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; + +export type GenericCompareSideBySideDataDisplayProps = { + organismViewKey: `${OrganismWithViewKey}.${typeof compareSideBySideViewKey}`; + organismsConfig: OrganismsConfig; + datasetAndVariantData: DatasetAndVariantData; + hideMutationComponents?: boolean; +}; + +export const GenericCompareSideBySideDataDisplay: FC = ({ + organismViewKey, + organismsConfig, + datasetAndVariantData, + hideMutationComponents, +}) => { + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const { datasetFilter, variantFilter } = datasetAndVariantData; + + const datasetLapisFilter = toLapisFilterWithoutVariant(datasetFilter, view.organismConstants.additionalFilters); + const timeGranularity = chooseGranularityBasedOnDateRange({ + earliestDate: new Date(view.organismConstants.earliestDate), + dateRange: datasetFilter.dateFilters[view.organismConstants.mainDateField], + }); + const numeratorFilter = view.pageStateHandler.variantFilterToLapisFilter(datasetFilter, variantFilter); + + return ( + <> + + {hideMutationComponents !== true && ( + <> + + + + )} + + {view.organismConstants.aggregatedVisualizations.compareSideBySide.map(({ label, fields, views }) => ( + + ))} + + ); +}; diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro index 81058b693..5fd6fcb31 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro @@ -1,16 +1,11 @@ --- +import { GenericCompareSideBySideDataDisplay } from './GenericCompareSideBySideDataDisplay.tsx'; import { toDownloadLink } from './toDownloadLink'; import { isStaging, getDashboardsConfig, getLapisUrl } from '../../../config'; import OrganismViewPageLayout from '../../../layouts/OrganismPage/OrganismViewPageLayout.astro'; -import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange'; -import { ComponentHeight } from '../../../views/OrganismConstants'; -import { toLapisFilterWithoutVariant } from '../../../views/pageStateHandlers/toLapisFilterWithoutVariant'; import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareSideBySideViewKey } from '../../../views/viewKeys'; -import GsAggregate from '../../genspectrum/GsAggregate.astro'; -import GsMutations from '../../genspectrum/GsMutations.astro'; -import GsPrevalenceOverTime from '../../genspectrum/GsPrevalenceOverTime.astro'; import { CompareSideBySidePageStateSelector } from '../../pageStateSelectors/CompareSideBySidePageStateSelector'; import { CompareSideBySideSelectorFallback } from '../../pageStateSelectors/FallbackElement'; @@ -26,6 +21,8 @@ const view = ServerSide.routing.getOrganismView(organismViewKey); const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); +const organismConfig = getDashboardsConfig().dashboards.organisms; + const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.pageStateHandler, organism)); --- @@ -33,20 +30,7 @@ const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.p
{ - Array.from(pageState.filters).map(([id, { variantFilter, datasetFilter }]) => { - const datasetLapisFilter = toLapisFilterWithoutVariant( - datasetFilter, - view.organismConstants.additionalFilters, - ); - const timeGranularity = chooseGranularityBasedOnDateRange({ - earliestDate: new Date(view.organismConstants.earliestDate), - dateRange: datasetFilter.dateFilters[view.organismConstants.mainDateField], - }); - const numeratorFilter = view.pageStateHandler.variantFilterToLapisFilter( - datasetFilter, - variantFilter, - ); - + Array.from(pageState.filters).map(([id, datasetAndVariantData]) => { return (
@@ -63,7 +47,7 @@ const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.p
- - {!hideMutationComponents && ( - <> - - - - )} - - {view.organismConstants.aggregatedVisualizations.compareSideBySide.map( - ({ label, fields, views }) => ( - - ), - )}
); }) diff --git a/website/tests/CompareSideBySidePage.ts b/website/tests/CompareSideBySidePage.ts new file mode 100644 index 000000000..3b93102a0 --- /dev/null +++ b/website/tests/CompareSideBySidePage.ts @@ -0,0 +1,50 @@ +import { expect } from '@playwright/test'; + +import { ViewPage } from './ViewPage.ts'; +import { paths } from '../src/types/Organism.ts'; +import { type OrganismWithViewKey } from '../src/views/routing'; +import { compareSideBySideViewKey } from '../src/views/viewKeys'; + +export class CompareSideBySidePage extends ViewPage { + public readonly removeColumnButton = this.page.getByRole('link', { name: 'Remove column' }); + public readonly addColumnButton = this.page.getByRole('link', { name: 'Add column' }); + public readonly mutationField = this.page.getByRole('combobox', { name: 'Enter a mutation', exact: false }); + + public async goto(organism: OrganismWithViewKey) { + await this.page.goto(`${paths[organism].basePath}/compare-side-by-side`); + } + + public async addColumn(options: { + dateRangeOption: string; + expectedColumnCount: number; + lineage?: string; + lineageFieldPlaceholder?: string; + mutation?: string; + }) { + await expect(this.addColumnButton).toBeVisible(); + + await this.addColumnButton.click(); + await expect(this.mutationField).toHaveCount(options.expectedColumnCount); + + await this.page + .locator('gs-date-range-filter') + .getByRole('combobox') + .last() + .selectOption(options.dateRangeOption); + + if (options.lineage && options.lineageFieldPlaceholder) { + const { lineage, lineageFieldPlaceholder } = options; + + const lineageFieldLocator = this.page.getByPlaceholder(lineageFieldPlaceholder); + await expect(lineageFieldLocator).toHaveCount(options.expectedColumnCount); + + await this.fillLineageField(lineageFieldLocator.last(), lineage); + } + + if (options.mutation) { + await this.fillMutationField(this.mutationField.last(), options.mutation); + } + + await this.page.getByRole('button', { name: 'Apply filters' }).last().click(); + } +} diff --git a/website/tests/CompareToBaselinePage.ts b/website/tests/CompareToBaselinePage.ts index 9f41d2784..a5a091b3b 100644 --- a/website/tests/CompareToBaselinePage.ts +++ b/website/tests/CompareToBaselinePage.ts @@ -24,15 +24,11 @@ export class CompareToBaselinePage extends CompareVariantsPage { const { lineage, lineageFieldPlaceholder } = options; const lineageFieldLocator = this.page.getByPlaceholder(lineageFieldPlaceholder); - await lineageFieldLocator.first().fill(lineage); - - const selectedLineage = this.page.getByRole('option', { name: lineage, exact: false }); - await selectedLineage.first().click(); + await this.fillLineageField(lineageFieldLocator.first(), lineage); } if (options.mutation) { - await this.mutationField.first().fill(options.mutation); - await this.mutationField.first().press('Enter'); + await this.fillMutationField(this.mutationField.first(), options.mutation); } } } diff --git a/website/tests/CompareVariantsPage.ts b/website/tests/CompareVariantsPage.ts index 16b7585aa..d566f074c 100644 --- a/website/tests/CompareVariantsPage.ts +++ b/website/tests/CompareVariantsPage.ts @@ -33,15 +33,11 @@ export class CompareVariantsPage extends ViewPage { const lineageFieldLocator = this.page.getByPlaceholder(lineageFieldPlaceholder); await expect(lineageFieldLocator).toHaveCount(numberMutationFields + 1); - await lineageFieldLocator.last().fill(lineage); - - const selectedLineage = this.page.getByRole('option', { name: lineage, exact: false }); - await selectedLineage.first().click(); + await this.fillLineageField(lineageFieldLocator.last(), lineage); } if (options.mutation) { - await this.mutationField.last().fill(options.mutation); - await this.mutationField.last().press('Enter'); + await this.fillMutationField(this.mutationField.last(), options.mutation); } } } diff --git a/website/tests/ViewPage.ts b/website/tests/ViewPage.ts index be146eb78..43ee2549e 100644 --- a/website/tests/ViewPage.ts +++ b/website/tests/ViewPage.ts @@ -1,4 +1,4 @@ -import { expect, type Page } from '@playwright/test'; +import { expect, type Locator, type Page } from '@playwright/test'; import { type Organism } from '../src/types/Organism.ts'; @@ -23,4 +23,15 @@ export abstract class ViewPage { public async selectDateRange(dateRangeOption: string) { await this.page.locator('gs-date-range-filter').getByRole('combobox').first().selectOption(dateRangeOption); } + + public async fillLineageField(locator: Locator, lineage: string) { + await locator.fill(lineage); + const selectedLineage = this.page.getByRole('option', { name: lineage, exact: false }); + await selectedLineage.first().click(); + } + + public async fillMutationField(locator: Locator, mutation: string) { + await locator.first().fill(mutation); + await locator.first().press('Enter'); + } } diff --git a/website/tests/compareSideBySide.spec.ts b/website/tests/compareSideBySide.spec.ts new file mode 100644 index 000000000..2ccfa925e --- /dev/null +++ b/website/tests/compareSideBySide.spec.ts @@ -0,0 +1,38 @@ +import { expect } from '@playwright/test'; + +import { test } from './e2e.fixture.ts'; +import { organismOptions, organismsWithView } from './helpers.ts'; +import { compareSideBySideViewKey } from '../src/views/viewKeys'; + +test.describe('The Compare Side-By-Side page', () => { + for (const organism of organismsWithView(compareSideBySideViewKey)) { + test(`should show diagrams after selecting a variant in both columns - ${organism}`, async ({ + compareSideBySidePage, + }) => { + const options = organismOptions[organism]; + + await compareSideBySidePage.goto(organism); + await expect(compareSideBySidePage.removeColumnButton).not.toBeVisible(); + await expect(compareSideBySidePage.addColumnButton).toBeVisible(); + + await expect(compareSideBySidePage.diagramTitle('Prevalence Over Time')).not.toBeVisible(); + + await compareSideBySidePage.addColumn({ + dateRangeOption: 'All times', + expectedColumnCount: 1, + ...options, + }); + await expect(compareSideBySidePage.removeColumnButton).not.toBeVisible(); + + await compareSideBySidePage.addColumn({ + dateRangeOption: 'All times', + expectedColumnCount: 2, + ...options, + }); + await expect(compareSideBySidePage.removeColumnButton).toHaveCount(2); + + await expect(compareSideBySidePage.diagramTitle('Prevalence Over Time')).toHaveCount(2); + await compareSideBySidePage.expectToSeeNoComponentErrors(); + }); + } +}); diff --git a/website/tests/e2e.fixture.ts b/website/tests/e2e.fixture.ts index 6a655f331..3e4dbf6dc 100644 --- a/website/tests/e2e.fixture.ts +++ b/website/tests/e2e.fixture.ts @@ -1,5 +1,6 @@ import { test as base } from '@playwright/test'; +import { CompareSideBySidePage } from './CompareSideBySidePage.ts'; import { CompareToBaselinePage } from './CompareToBaselinePage.ts'; import { CompareVariantsPage } from './CompareVariantsPage.ts'; import { SequencingEffortsPage } from './SequencingEffortsPage.ts'; @@ -8,6 +9,7 @@ type E2EFixture = { compareVariantsPage: CompareVariantsPage; sequencingEffortsPage: SequencingEffortsPage; compareToBaselinePage: CompareToBaselinePage; + compareSideBySidePage: CompareSideBySidePage; }; export const test = base.extend({ @@ -20,4 +22,7 @@ export const test = base.extend({ compareToBaselinePage: async ({ page }, use) => { await use(new CompareToBaselinePage(page)); }, + compareSideBySidePage: async ({ page }, use) => { + await use(new CompareSideBySidePage(page)); + }, }); diff --git a/website/tests/helpers.ts b/website/tests/helpers.ts index 2e3edba44..5dfda525f 100644 --- a/website/tests/helpers.ts +++ b/website/tests/helpers.ts @@ -8,9 +8,11 @@ export function organismsWithView(viewKey: ViewKey): Org export const organismOptions = { [Organisms.covid]: { lineage: 'JN.1*', lineageFieldPlaceholder: 'Nextclade pango lineage' }, + [Organisms.influenzaA]: { lineage: 'H1', lineageFieldPlaceholder: 'HA subtype' }, [Organisms.h5n1]: { lineage: '2.3.4.4b', lineageFieldPlaceholder: 'Clade' }, [Organisms.h1n1pdm]: { lineage: '6B.1A.5a.2a.1', lineageFieldPlaceholder: 'Clade HA' }, [Organisms.h3n2]: { lineage: '3C.2a1b', lineageFieldPlaceholder: 'Clade HA' }, + [Organisms.influenzaB]: { lineage: 'vic', lineageFieldPlaceholder: 'Lineage' }, [Organisms.victoria]: { lineage: 'V1A.3a.2', lineageFieldPlaceholder: 'Clade HA' }, [Organisms.westNile]: { lineage: '1A', lineageFieldPlaceholder: 'Lineage' }, [Organisms.rsvA]: { lineage: 'A.D.5.2', lineageFieldPlaceholder: 'Lineage' }, From b3cd25bf982d2118343cd13f4ab962fda0779226 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Wed, 7 Jan 2026 11:01:30 +0100 Subject: [PATCH 17/26] refactor(website): migrate covid "compare side-by-side" to React (#982) resolves #981 --- .../GenericCompareSideBySideDataDisplay.tsx | 10 ++ .../pages/covid/compare-side-by-side.astro | 130 +----------------- 2 files changed, 13 insertions(+), 127 deletions(-) diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx index 4b84d3b47..53921b476 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx @@ -1,6 +1,7 @@ import { type FC, useMemo } from 'react'; import type { OrganismsConfig } from '../../../config.ts'; +import { Organisms } from '../../../types/Organism.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; import { ComponentHeight } from '../../../views/OrganismConstants.ts'; import type { DatasetAndVariantData } from '../../../views/View.ts'; @@ -10,6 +11,7 @@ import { compareSideBySideViewKey } from '../../../views/viewKeys.ts'; import { GsAggregate } from '../../genspectrum/GsAggregate.tsx'; import { GsMutations } from '../../genspectrum/GsMutations.tsx'; import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; +import { GsRelativeGrowthAdvantage } from '../../genspectrum/GsRelativeGrowthAdvantage.tsx'; export type GenericCompareSideBySideDataDisplayProps = { organismViewKey: `${OrganismWithViewKey}.${typeof compareSideBySideViewKey}`; @@ -53,6 +55,14 @@ export const GenericCompareSideBySideDataDisplay: FC + {view.organismConstants.organism === Organisms.covid && ( + + )} {hideMutationComponents !== true && ( <> - -
- { - Array.from(pageState.filters).map(([id, { variantFilter, datasetFilter }]) => { - const baselineLapisFilter = toLapisFilterWithoutVariant( - datasetFilter, - view.organismConstants.additionalFilters, - ); - const timeGranularity = chooseGranularityBasedOnDateRange({ - earliestDate: new Date(view.organismConstants.earliestDate), - dateRange: datasetFilter.dateFilters[view.organismConstants.mainDateField], - }); - const numeratorFilter = { - ...variantFilter.lineages, - ...variantFilter.mutations, - variantQuery: variantFilter.variantQuery, - ...baselineLapisFilter, - }; - - return ( -
-
- {pageState.filters.size > 1 && ( - - Remove column - - )} - - - -
- - - - - - {view.organismConstants.aggregatedVisualizations.compareSideBySide.map( - ({ label, fields, views }) => ( - - ), - )} -
- ); - }) - } - - Add column - -
-
- + From bba733a36965c37ff356c97c4fc4c1f1aa2c595c Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Wed, 7 Jan 2026 12:34:01 +0000 Subject: [PATCH 18/26] feat(website): display clinical sequence count on variant explorer, with warning for small numbers (#980) --- .../wasap/filters/VariantExplorerFilter.tsx | 11 ++- .../src/components/views/wasap/WasapPage.tsx | 94 +++++++++++++++++-- .../views/wasap/useWasapPageData.ts | 26 ++--- .../components/views/wasap/wasapPageConfig.ts | 12 +++ website/src/types/wastewaterConfig.ts | 2 + .../WasapPageStateHandler.spec.ts | 1 + 6 files changed, 120 insertions(+), 26 deletions(-) diff --git a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx index 1186e83d8..635f01fb7 100644 --- a/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx +++ b/website/src/components/pageStateSelectors/wasap/filters/VariantExplorerFilter.tsx @@ -2,6 +2,7 @@ import { Inset } from '../../../../styles/Inset'; import { GsLineageFilter } from '../../../genspectrum/GsLineageFilter'; import { VARIANT_TIME_FRAME, + variantTimeFrameLabel, type VariantTimeFrame, type WasapVariantFilter, } from '../../../views/wasap/wasapPageConfig'; @@ -80,9 +81,13 @@ export function VariantExplorerFilter({ value={pageState.timeFrame} onChange={(e) => setPageState({ ...pageState, timeFrame: e.target.value as VariantTimeFrame })} > - - - + + + diff --git a/website/src/components/views/wasap/WasapPage.tsx b/website/src/components/views/wasap/WasapPage.tsx index 52f94c8c7..70cc2d2f5 100644 --- a/website/src/components/views/wasap/WasapPage.tsx +++ b/website/src/components/views/wasap/WasapPage.tsx @@ -4,8 +4,13 @@ import { useMemo } from 'react'; import { type FC } from 'react'; import { toMutationAnnotations } from './resistanceMutations'; -import { useWasapPageData } from './useWasapPageData'; -import type { WasapAnalysisFilter, WasapPageConfig } from './wasapPageConfig'; +import { getLapisFilterForTimeFrame, useWasapPageData } from './useWasapPageData'; +import { + variantTimeFrameLabel, + type WasapAnalysisFilter, + type WasapPageConfig, + type WasapVariantFilter, +} from './wasapPageConfig'; import { getDateRange } from '../../../lapis/getDateRange'; import { getTotalCount } from '../../../lapis/getTotalCount'; import { wastewaterOrganismConfigs, type WastewaterOrganismName } from '../../../types/wastewaterConfig'; @@ -95,6 +100,15 @@ export const WasapPageInner: FC = ({ wastewaterOrganism, current customColumns={customColumns} /> )} + {analysis.mode === 'variant' && config.variantAnalysisModeEnabled && ( + + )}
)} @@ -130,6 +144,71 @@ const NoDataHelperText = ({ analysisFilter }: { analysisFilter: WasapAnalysisFil ); }; +/** + * Info stat about the amount of sequences used during the computation of the clinical variant signature. + * Will also show a warning of the count is small. + */ +const VariantFetchInfo = ({ + analysis, + clinicalLapisBaseUrl, + clinicalLapisLineageField, + clinicalLapisDateField, + warningThreshold, +}: { + analysis: WasapVariantFilter; + clinicalLapisBaseUrl: string; + clinicalLapisLineageField: string; + clinicalLapisDateField: string; + warningThreshold: number; +}) => { + const lapisFilter = { + ...getLapisFilterForTimeFrame(analysis.timeFrame, clinicalLapisDateField), + [clinicalLapisLineageField]: analysis.variant, + }; + + const { data, isPending, isError, error } = useQuery({ + queryKey: ['variantFetchInfo'], + queryFn: () => getTotalCount(clinicalLapisBaseUrl, lapisFilter), + }); + + const isHighlighted = data !== undefined && data < warningThreshold; + + let message = `The number of clinical sequences for ${analysis.variant}`; + if (analysis.timeFrame !== 'all') { + message += ` during the past ${variantTimeFrameLabel(analysis.timeFrame)}`; + } + if (isHighlighted) { + message += '. Clinical signature calculation with this few sequences is not recommended.'; + } + + return ( +
+
+
Clinical sequences for {analysis.variant}
+
+ {isPending ? ( + '…' + ) : isError ? ( + 'Error' + ) : isHighlighted ? ( + {data.toLocaleString('en-us')} + ) : ( + data.toLocaleString('en-us') + )} +
+
{isPending ? 'Loading …' : isError ? error.message : message}
+
+
+ ); +}; + +const WasapStats = ({ config }: { config: WasapPageConfig }) => ( +
+ + +
+); + const TotalCount = ({ config }: { config: WasapPageConfig }) => { const { data, isPending, isError, error } = useQuery({ queryKey: ['aggregatedCount'], @@ -139,7 +218,9 @@ const TotalCount = ({ config }: { config: WasapPageConfig }) => { return (
Amplicon sequences
-
{isPending ? '…' : isError ? 'Error' : data.toLocaleString()}
+
+ {isPending ? '…' : isError ? 'Error' : data.toLocaleString('en-us')} +
{isPending ? 'Loading total amplicon sequences count…' @@ -173,10 +254,3 @@ const DateRange = ({ config }: { config: WasapPageConfig }) => {
); }; - -const WasapStats = ({ config }: { config: WasapPageConfig }) => ( -
- - -
-); diff --git a/website/src/components/views/wasap/useWasapPageData.ts b/website/src/components/views/wasap/useWasapPageData.ts index 01082e8a7..309a169f9 100644 --- a/website/src/components/views/wasap/useWasapPageData.ts +++ b/website/src/components/views/wasap/useWasapPageData.ts @@ -6,6 +6,18 @@ import type { VariantTimeFrame, WasapAnalysisFilter, WasapPageConfig } from './w import { getCladeLineages } from '../../../lapis/getCladeLineages'; import { getMutations, getMutationsForVariant } from '../../../lapis/getMutations'; +/** + * Hook that fetches and returns `WasapPageData` for the W-ASAP page, + * depending on the analysis mode and analysis mode settings. + */ +export function useWasapPageData(config: WasapPageConfig, analysis: WasapAnalysisFilter) { + return useQuery({ + queryKey: ['wasap', analysis], + queryFn: () => + fetchMutationSelection(config, analysis).then((data) => wasapPageDataFromMutationSelection(data)), + }); +} + type AllMutations = { type: 'all'; }; @@ -99,7 +111,7 @@ async function fetchMutationSelection( } } -function getLapisFilterForTimeFrame(timeFrame: VariantTimeFrame, dateFieldName: string): LapisFilter { +export function getLapisFilterForTimeFrame(timeFrame: VariantTimeFrame, dateFieldName: string): LapisFilter { let fromDate = undefined; switch (timeFrame) { case 'all': @@ -161,15 +173,3 @@ function wasapPageDataFromMutationSelection(mutationSelection: MutationSelection }; } } - -/** - * Hook that fetches and returns `WasapPageData` for the W-ASAP page, - * depending on the analysis mode and analysis mode settings. - */ -export function useWasapPageData(config: WasapPageConfig, analysis: WasapAnalysisFilter) { - return useQuery({ - queryKey: ['wasap', analysis], - queryFn: () => - fetchMutationSelection(config, analysis).then((data) => wasapPageDataFromMutationSelection(data)), - }); -} diff --git a/website/src/components/views/wasap/wasapPageConfig.ts b/website/src/components/views/wasap/wasapPageConfig.ts index 52c98df41..1ff438119 100644 --- a/website/src/components/views/wasap/wasapPageConfig.ts +++ b/website/src/components/views/wasap/wasapPageConfig.ts @@ -77,6 +77,7 @@ type VariantAnalysisModeConfig = filterDefaults: { variant: WasapVariantFilter; }; + clinicalSequenceCountWarningThreshold: number; }; type ResistanceAnalysisModeConfig = @@ -166,6 +167,17 @@ export const VARIANT_TIME_FRAME = { export type VariantTimeFrame = (typeof VARIANT_TIME_FRAME)[keyof typeof VARIANT_TIME_FRAME]; +export function variantTimeFrameLabel(timeFrame: VariantTimeFrame): string { + switch (timeFrame) { + case VARIANT_TIME_FRAME.all: + return 'All'; + case VARIANT_TIME_FRAME.sixMonths: + return '6 months'; + case VARIANT_TIME_FRAME.threeMonths: + return '3 months'; + } +} + export type WasapVariantFilter = { mode: 'variant'; sequenceType: SequenceType; diff --git a/website/src/types/wastewaterConfig.ts b/website/src/types/wastewaterConfig.ts index 3b9ac3c0b..1c95f9cbd 100644 --- a/website/src/types/wastewaterConfig.ts +++ b/website/src/types/wastewaterConfig.ts @@ -40,6 +40,7 @@ export const wastewaterOrganismConfigs: Record Date: Thu, 8 Jan 2026 08:37:35 +0100 Subject: [PATCH 19/26] refactor(website): refactor footer to pull "download data" button closer to React-rendered content (#978) * refactor(website): refactor footer to pull "download data" button closer to React-rendered content so that in a next step, that part of the footer can actually be rendered in React (since it depends on the page state) resolves #977 * refactor(website): move it back --- .../GenericCompareSideBySidePage.astro | 98 +++++++++---------- .../layouts/OrganismPage/DataPageLayout.astro | 46 +++++---- .../OrganismPage/OrganismViewPageLayout.astro | 7 +- .../SingleVariantOrganismPageLayout.astro | 16 +-- website/src/layouts/base/BaseLayout.astro | 5 +- website/src/layouts/base/footer/Footer.astro | 4 - .../layouts/base/footer/SecondaryFooter.astro | 7 -- website/src/pages/index.astro | 4 +- 8 files changed, 89 insertions(+), 98 deletions(-) delete mode 100644 website/src/layouts/base/footer/SecondaryFooter.astro diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro index 5fd6fcb31..fe397ea9d 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro @@ -1,7 +1,7 @@ --- import { GenericCompareSideBySideDataDisplay } from './GenericCompareSideBySideDataDisplay.tsx'; import { toDownloadLink } from './toDownloadLink'; -import { isStaging, getDashboardsConfig, getLapisUrl } from '../../../config'; +import { isStaging, getDashboardsConfig } from '../../../config'; import OrganismViewPageLayout from '../../../layouts/OrganismPage/OrganismViewPageLayout.astro'; import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; @@ -27,56 +27,54 @@ const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.p --- - -
- { - Array.from(pageState.filters).map(([id, datasetAndVariantData]) => { - return ( -
-
- {pageState.filters.size > 1 && ( - - Remove column - - )} - + { + Array.from(pageState.filters).map(([id, datasetAndVariantData]) => { + return ( + - ); - }) - } - - Add column - -
- + + +
+ ); + }) + } + + Add column + +
diff --git a/website/src/layouts/OrganismPage/DataPageLayout.astro b/website/src/layouts/OrganismPage/DataPageLayout.astro index 4cca64d02..fbd92a1cf 100644 --- a/website/src/layouts/OrganismPage/DataPageLayout.astro +++ b/website/src/layouts/OrganismPage/DataPageLayout.astro @@ -1,11 +1,11 @@ --- import type { ComponentProps } from 'astro/types'; -import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; -import LastUpdatedInfo from './LastUpdatedInfo.astro'; import LapisUnreachableWrapperClient from '../../components/LapisUnreachableWrapperClient'; -import type { DataOrigin } from '../../types/dataOrigins'; import { type BreadcrumbElement, Breadcrumbs } from '../Breadcrumbs'; +import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; +import LastUpdatedInfo from './LastUpdatedInfo.astro'; +import type { DataOrigin } from '../../types/dataOrigins.ts'; import BaseLayout from '../base/BaseLayout.astro'; import DataInfo from '../base/footer/DataInfo.astro'; @@ -22,23 +22,27 @@ const { title, breadcrumbs, dataOrigins, lapisUrl, downloadLinks = [], accession --- -
- -
- - - -
- { - downloadLinks.length > 0 && ( - - ) - } - - +
+
+ +
+
+ + + +
+
+ { + downloadLinks.length > 0 && ( + + ) + } + + +
diff --git a/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro b/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro index 38d752847..11d51ab7b 100644 --- a/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro +++ b/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro @@ -24,5 +24,10 @@ const { view, downloadLinks } = Astro.props; lapisUrl={getLapisUrl(view.organismConstants.organism)} accessionDownloadFields={view.organismConstants.accessionDownloadFields} > - + + + diff --git a/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro b/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro index 2841b7624..514a91a78 100644 --- a/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro +++ b/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro @@ -3,7 +3,6 @@ import type { ComponentProps } from 'astro/types'; import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; import OrganismViewPageLayout from './OrganismViewPageLayout.astro'; -import { getLapisUrl } from '../../config'; import type { OrganismConstants } from '../../views/OrganismConstants'; import type { View } from '../../views/View'; import { type PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler'; @@ -17,15 +16,10 @@ const { view, downloadLinks } = Astro.props; --- - -
-
- -
- +
+
+
- + +
diff --git a/website/src/layouts/base/BaseLayout.astro b/website/src/layouts/base/BaseLayout.astro index 8f8bccc9c..bcf85d40f 100644 --- a/website/src/layouts/base/BaseLayout.astro +++ b/website/src/layouts/base/BaseLayout.astro @@ -34,14 +34,13 @@ const { title, forceLoggedOutState = false } = Astro.props; - + +
-
-
diff --git a/website/src/layouts/base/footer/Footer.astro b/website/src/layouts/base/footer/Footer.astro index 0b90db516..918a8612d 100644 --- a/website/src/layouts/base/footer/Footer.astro +++ b/website/src/layouts/base/footer/Footer.astro @@ -1,12 +1,8 @@ --- import PrimaryFooter from './PrimaryFooter.astro'; -import SecondaryFooter from './SecondaryFooter.astro'; ---
- - - diff --git a/website/src/layouts/base/footer/SecondaryFooter.astro b/website/src/layouts/base/footer/SecondaryFooter.astro deleted file mode 100644 index 1725a6973..000000000 --- a/website/src/layouts/base/footer/SecondaryFooter.astro +++ /dev/null @@ -1,7 +0,0 @@ ---- - ---- - -
- -
diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index f7c21db3e..be85c87ee 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -117,5 +117,7 @@ import { Page } from '../types/pages';
- +
+ +
From 12abdce27a6ef1cf5ec8766ce56f6c4d35db5994 Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Mon, 12 Jan 2026 13:03:37 +0000 Subject: [PATCH 20/26] fix(website): fix untracked mutations (#992) --- website/src/components/views/wasap/useWasapPageData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/components/views/wasap/useWasapPageData.ts b/website/src/components/views/wasap/useWasapPageData.ts index 309a169f9..e9a2531db 100644 --- a/website/src/components/views/wasap/useWasapPageData.ts +++ b/website/src/components/views/wasap/useWasapPageData.ts @@ -94,7 +94,7 @@ async function fetchMutationSelection( config.clinicalLapis.lapisBaseUrl, analysis.sequenceType, { - [config.clinicalLapis.lapisBaseUrl]: variant, + [config.clinicalLapis.lineageField]: variant, }, 0.8, 9, From d7f6010a33a7e56accdf6e6978e31bb37eaecfb8 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Tue, 13 Jan 2026 08:20:13 +0100 Subject: [PATCH 21/26] refactor(website): render the whole layout in React (#983) * 979 also render the layouts in React * 979 fix stuff * 979 fix test --- ...sUnreachableWrapperClient.browser.spec.tsx | 53 ++++---- .../LapisUnreachableWrapperClient.tsx | 7 +- .../pageStateSelectors/FallbackElement.tsx | 38 ------ .../CovidSingleVariantReactPage.tsx | 78 ++++++++++++ .../GenericAnalyseSingleVariantReactPage.tsx | 76 +++++++++++ .../GenericAnalyzeSingleVariantPage.astro | 68 ++-------- .../GenericCompareSideBySidePage.astro | 82 +++--------- .../GenericCompareSideBySideReactPage.tsx | 87 +++++++++++++ .../GenericCompareToBaselinePage.astro | 55 ++------ .../GenericCompareToBaselineReactPage.tsx | 63 ++++++++++ .../GenericCompareVariantsPage.astro | 54 ++------ .../GenericCompareVariantsReactPage.tsx | 63 ++++++++++ .../GenericSequencingEffortsPage.astro | 55 ++------ .../GenericSequencingEffortsReactPage.tsx | 61 +++++++++ .../src/components/views/wasap/Wasap.astro | 28 +---- .../src/components/views/wasap/WasapPage.tsx | 118 ++++++++++-------- website/src/lapis/getLastUpdatedDate.spec.ts | 4 +- website/src/lapis/getLastUpdatedDate.ts | 10 +- .../AccessionsDownloadButton.astro | 53 -------- .../OrganismPage/AccessionsDownloadButton.tsx | 63 ++++++++++ .../layouts/OrganismPage/DataPageLayout.astro | 48 ------- .../layouts/OrganismPage/DataPageLayout.tsx | 50 ++++++++ .../OrganismPage/LastUpdatedInfo.astro | 13 -- .../layouts/OrganismPage/LastUpdatedInfo.tsx | 18 +++ .../OrganismPage/OrganismViewPageLayout.astro | 33 ----- .../OrganismPage/OrganismViewPageLayout.tsx | 34 +++++ .../SingleVariantOrganismPageLayout.astro | 25 ---- .../SingleVariantOrganismPageLayout.tsx | 37 ++++++ .../src/layouts/base/footer/DataInfo.astro | 26 ---- website/src/layouts/base/footer/DataInfo.tsx | 38 ++++++ .../layouts/base/footer/DataOriginLink.astro | 12 -- website/src/pages/covid/single-variant.astro | 76 ++--------- website/src/pages/index.astro | 2 +- website/src/pages/swiss-wastewater/flu.astro | 90 ++++++------- website/src/pages/swiss-wastewater/rsv.astro | 92 +++++++------- 35 files changed, 942 insertions(+), 768 deletions(-) delete mode 100644 website/src/components/pageStateSelectors/FallbackElement.tsx create mode 100644 website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx create mode 100644 website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx create mode 100644 website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx create mode 100644 website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx create mode 100644 website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx create mode 100644 website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx delete mode 100644 website/src/layouts/OrganismPage/AccessionsDownloadButton.astro create mode 100644 website/src/layouts/OrganismPage/AccessionsDownloadButton.tsx delete mode 100644 website/src/layouts/OrganismPage/DataPageLayout.astro create mode 100644 website/src/layouts/OrganismPage/DataPageLayout.tsx delete mode 100644 website/src/layouts/OrganismPage/LastUpdatedInfo.astro create mode 100644 website/src/layouts/OrganismPage/LastUpdatedInfo.tsx delete mode 100644 website/src/layouts/OrganismPage/OrganismViewPageLayout.astro create mode 100644 website/src/layouts/OrganismPage/OrganismViewPageLayout.tsx delete mode 100644 website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro create mode 100644 website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx delete mode 100644 website/src/layouts/base/footer/DataInfo.astro create mode 100644 website/src/layouts/base/footer/DataInfo.tsx delete mode 100644 website/src/layouts/base/footer/DataOriginLink.astro diff --git a/website/src/components/LapisUnreachableWrapperClient.browser.spec.tsx b/website/src/components/LapisUnreachableWrapperClient.browser.spec.tsx index 3108cf7b0..c33f73371 100644 --- a/website/src/components/LapisUnreachableWrapperClient.browser.spec.tsx +++ b/website/src/components/LapisUnreachableWrapperClient.browser.spec.tsx @@ -1,31 +1,28 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { describe, expect } from 'vitest'; import { render } from 'vitest-browser-react'; -import LapisUnreachableWrapperClient from './LapisUnreachableWrapperClient'; +import { LapisUnreachableWrapperClient } from './LapisUnreachableWrapperClient'; import { DUMMY_LAPIS_URL } from '../../routeMocker'; import { it } from '../../test-extend'; +const queryClient = new QueryClient(); + describe('LapisUnreachableWrapperClient', () => { it('displays children when LAPIS is reachable', async ({ routeMockers: { lapis } }) => { lapis.mockPostAggregated({}, { data: [{ count: 100 }] }); - const { getByText } = render( - -
Content is visible
-
, - ); + const content = 'Content is visible'; + + const { getByText } = renderWithContent(content); - await expect.element(getByText('Content is visible')).toBeVisible(); + await expect.element(getByText(content)).toBeVisible(); }); it('displays error message when LAPIS is unreachable', async ({ routeMockers: { lapis } }) => { lapis.mockLapisDown(); - const { getByText } = render( - -
Content is visible
-
, - ); + const { getByText } = renderWithContent('Content is visible'); await expect.element(getByText('Data Source Unreachable')).toBeVisible(); await expect.element(getByText('Unable to connect to the data source')).toBeVisible(); @@ -34,23 +31,17 @@ describe('LapisUnreachableWrapperClient', () => { it('does not display children when LAPIS is unreachable', async ({ routeMockers: { lapis } }) => { lapis.mockLapisDown(); - const { getByText } = render( - -
Content should not be visible
-
, - ); + const content = 'Content is visible'; - await expect.poll(() => getByText('Content should not be visible').query()).not.toBeInTheDocument(); + const { getByText } = renderWithContent(content); + + await expect.poll(() => getByText(content).query()).not.toBeInTheDocument(); }); it('displays error when LAPIS returns invalid response', async ({ routeMockers: { lapis } }) => { lapis.mockPostAggregated({}, { data: [] }, 200); - const { getByText } = render( - -
Content is visible
-
, - ); + const { getByText } = renderWithContent('Content is visible'); await expect.element(getByText('Data Source Unreachable')).toBeVisible(); }); @@ -58,12 +49,18 @@ describe('LapisUnreachableWrapperClient', () => { it('displays error when LAPIS returns 500', async ({ routeMockers: { lapis } }) => { lapis.mockPostAggregated({}, { data: [{ count: 100 }] }, 500); - const { getByText } = render( - -
Content is visible
-
, - ); + const { getByText } = renderWithContent('Content is visible'); await expect.element(getByText('Data Source Unreachable')).toBeVisible(); }); }); + +function renderWithContent(content: string) { + return render( + + +
{content}
+
+
, + ); +} diff --git a/website/src/components/LapisUnreachableWrapperClient.tsx b/website/src/components/LapisUnreachableWrapperClient.tsx index 18307c761..ddec59b3a 100644 --- a/website/src/components/LapisUnreachableWrapperClient.tsx +++ b/website/src/components/LapisUnreachableWrapperClient.tsx @@ -2,14 +2,13 @@ import { useQuery } from '@tanstack/react-query'; import { type FC, type ReactNode } from 'react'; import { checkLapisHealth } from '../lapis/checkLapisHealth'; -import { withQueryProvider } from './subscriptions/backendApi/withQueryProvider'; type LapisUnreachableWrapperClientProps = { lapisUrl: string; children: ReactNode; }; -const LapisUnreachableWrapperClientInner: FC = ({ lapisUrl, children }) => { +export const LapisUnreachableWrapperClient: FC = ({ lapisUrl, children }) => { const { data: isReachable, isLoading } = useQuery({ queryKey: ['lapis-reachable', lapisUrl], queryFn: () => checkLapisHealth(lapisUrl), @@ -37,7 +36,3 @@ const LapisUnreachableWrapperClientInner: FC return <>{children}; }; - -const LapisUnreachableWrapperClient = withQueryProvider(LapisUnreachableWrapperClientInner); - -export default LapisUnreachableWrapperClient; diff --git a/website/src/components/pageStateSelectors/FallbackElement.tsx b/website/src/components/pageStateSelectors/FallbackElement.tsx deleted file mode 100644 index ed5d3090e..000000000 --- a/website/src/components/pageStateSelectors/FallbackElement.tsx +++ /dev/null @@ -1,38 +0,0 @@ -export function SequencingEffortsSelectorFallback() { - return
; -} - -export function AnalyzeSingleVariantSelectorFallback() { - return
; -} - -export function CompareSideBySideSelectorFallback({ numFilters }: { numFilters: number }) { - return ( -
- {numFilters > 2 &&
} - {numFilters <= 2 &&
} -
- ); -} - -export function CompareToBaselineSelectorFallback({ numFilters }: { numFilters: number }) { - return ( - <> -
- {Array.from({ length: numFilters }).map((_, index) => ( -
- ))} - - ); -} - -export function CompareVariantsSelectorFallback({ numFilters }: { numFilters: number }) { - return ( - <> -
- {Array.from({ length: numFilters }).map((_, index) => ( -
- ))} - - ); -} diff --git a/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx new file mode 100644 index 000000000..35b12bad5 --- /dev/null +++ b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx @@ -0,0 +1,78 @@ +import { type FC, useMemo } from 'react'; + +import { CollectionsList } from './CollectionsList.tsx'; +import { CovidSingleVariantDataDisplay } from './CovidSingleVariantDataDisplay.tsx'; +import type { OrganismsConfig } from '../../../config.ts'; +import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx'; +import { hasOnlyUndefinedValues } from '../../../util/hasOnlyUndefinedValues.ts'; +import { toDisplayName } from '../../../views/pageStateHandlers/PageStateHandler.ts'; +import { type OrganismViewKey, Routing } from '../../../views/routing.ts'; +import { SelectorHeadline } from '../../pageStateSelectors/SelectorHeadline.tsx'; +import { SingleVariantPageStateSelector } from '../../pageStateSelectors/SingleVariantPageStateSelector.tsx'; +import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink.ts'; + +export type CovidSingleVariantReactPageProps = { + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const CovidSingleVariantReactPage: FC = ({ organismsConfig, isStaging }) => { + const organismViewKey: OrganismViewKey = 'covid.singleVariantView'; + const view = useMemo(() => new Routing(organismsConfig).getOrganismView(organismViewKey), [organismsConfig]); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const variantFilter = view.pageStateHandler.toLapisFilter(pageState); + + const noVariantSelected = hasOnlyUndefinedValues(pageState.variantFilter); + + const displayName = toDisplayName(pageState.variantFilter); + const downloadLinks = noVariantSelected + ? [ + { + label: 'Download all accessions', + filter: variantFilter, + downloadFileBasename: `${view.organismConstants.organism}_accessions`, + }, + ] + : [ + { + label: `Download accessions of ${displayName}`, + filter: variantFilter, + downloadFileBasename: `${view.organismConstants.organism}_${sanitizeForFilename(displayName)}_accessions`, + }, + ]; + + return ( + + +
+
+ Collections + +
+ + } + dataDisplay={ + + } + /> + ); +}; diff --git a/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx new file mode 100644 index 000000000..3a9c770f8 --- /dev/null +++ b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx @@ -0,0 +1,76 @@ +import { type FC, useMemo } from 'react'; + +import { GenericAnalyseSingleVariantDataDisplay } from './GenericAnalyseSingleVariantDataDisplay'; +import { type OrganismsConfig } from '../../../config'; +import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx'; +import { Organisms } from '../../../types/Organism'; +import { hasOnlyUndefinedValues } from '../../../util/hasOnlyUndefinedValues'; +import { toDisplayName } from '../../../views/pageStateHandlers/PageStateHandler'; +import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; +import { singleVariantViewKey } from '../../../views/viewKeys'; +import { SingleVariantPageStateSelector } from '../../pageStateSelectors/SingleVariantPageStateSelector'; +import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; + +export type GenericAnalyseSingleVariantReactPageProps = { + organism: Exclude, typeof Organisms.covid>; + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const GenericAnalyseSingleVariantReactPage: FC = ({ + organism, + organismsConfig, + isStaging, +}) => { + const organismViewKey = `${organism}.${singleVariantViewKey}` satisfies OrganismViewKey; + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const variantLapisFilter = view.pageStateHandler.toLapisFilter(pageState); + + const noVariantSelected = hasOnlyUndefinedValues(pageState.variantFilter); + + const displayName = toDisplayName(pageState.variantFilter); + const downloadLinks = noVariantSelected + ? [ + { + label: 'Download all accessions', + filter: variantLapisFilter, + downloadFileBasename: `${view.organismConstants.organism}_accessions`, + }, + ] + : [ + { + label: `Download accessions of "${displayName}"`, + filter: variantLapisFilter, + downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, + }, + ]; + + return ( + + } + dataDisplay={ + + } + /> + ); +}; diff --git a/website/src/components/views/analyzeSingleVariant/GenericAnalyzeSingleVariantPage.astro b/website/src/components/views/analyzeSingleVariant/GenericAnalyzeSingleVariantPage.astro index 256b7079a..83fe543bf 100644 --- a/website/src/components/views/analyzeSingleVariant/GenericAnalyzeSingleVariantPage.astro +++ b/website/src/components/views/analyzeSingleVariant/GenericAnalyzeSingleVariantPage.astro @@ -1,70 +1,26 @@ --- -import { GenericAnalyseSingleVariantDataDisplay } from './GenericAnalyseSingleVariantDataDisplay'; +import { GenericAnalyseSingleVariantReactPage } from './GenericAnalyseSingleVariantReactPage'; import { isStaging, getDashboardsConfig } from '../../../config'; -import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; import { Organisms } from '../../../types/Organism'; -import { hasOnlyUndefinedValues } from '../../../util/hasOnlyUndefinedValues'; -import { toDisplayName } from '../../../views/pageStateHandlers/PageStateHandler'; -import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; +import { type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { singleVariantViewKey } from '../../../views/viewKeys'; -import { AnalyzeSingleVariantSelectorFallback } from '../../pageStateSelectors/FallbackElement'; -import { SingleVariantPageStateSelector } from '../../pageStateSelectors/SingleVariantPageStateSelector'; -import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; -type OrganismViewCompareVariant = OrganismWithViewKey; interface Props { - organism: Exclude; + organism: Exclude, typeof Organisms.covid>; } const { organism } = Astro.props; -const organismViewKey = `${organism}.${singleVariantViewKey}` satisfies OrganismViewKey; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const variantLapisFilter = view.pageStateHandler.toLapisFilter(pageState); - -const noVariantSelected = hasOnlyUndefinedValues(pageState.variantFilter); - -const organismConfig = getDashboardsConfig().dashboards.organisms; - -const displayName = toDisplayName(pageState.variantFilter); -const downloadLinks = noVariantSelected - ? [ - { - label: 'Download all accessions', - filter: variantLapisFilter, - downloadFileBasename: `${view.organismConstants.organism}_accessions`, - }, - ] - : [ - { - label: `Download accessions of "${displayName}"`, - filter: variantLapisFilter, - downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, - }, - ]; +const view = ServerSide.routing.getOrganismView(`${organism}.${singleVariantViewKey}`); --- - - + - - - -
- -
-
+ /> + diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro index fe397ea9d..e6216e72e 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySidePage.astro @@ -1,80 +1,28 @@ --- -import { GenericCompareSideBySideDataDisplay } from './GenericCompareSideBySideDataDisplay.tsx'; -import { toDownloadLink } from './toDownloadLink'; +import { GenericCompareSideBySideReactPage } from './GenericCompareSideBySideReactPage'; import { isStaging, getDashboardsConfig } from '../../../config'; -import OrganismViewPageLayout from '../../../layouts/OrganismPage/OrganismViewPageLayout.astro'; -import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; +import { type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareSideBySideViewKey } from '../../../views/viewKeys'; -import { CompareSideBySidePageStateSelector } from '../../pageStateSelectors/CompareSideBySidePageStateSelector'; -import { CompareSideBySideSelectorFallback } from '../../pageStateSelectors/FallbackElement'; -type OrganismViewCompareVariant = OrganismWithViewKey; interface Props { - organism: OrganismViewCompareVariant; + organism: OrganismWithViewKey; hideMutationComponents?: boolean; } const { organism, hideMutationComponents } = Astro.props; -const organismViewKey = `${organism}.${compareSideBySideViewKey}` satisfies OrganismViewKey; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const organismConfig = getDashboardsConfig().dashboards.organisms; - -const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.pageStateHandler, organism)); +const view = ServerSide.routing.getOrganismView(`${organism}.${compareSideBySideViewKey}`); +const organismsConfig = getDashboardsConfig().dashboards.organisms; --- - -
- { - Array.from(pageState.filters).map(([id, datasetAndVariantData]) => { - return ( -
-
- {pageState.filters.size > 1 && ( - - Remove column - - )} - - - -
- - -
- ); - }) - } - - Add column - -
-
+ + + diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx b/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx new file mode 100644 index 000000000..20e72eede --- /dev/null +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx @@ -0,0 +1,87 @@ +import { type FC, useMemo } from 'react'; + +import { GenericCompareSideBySideDataDisplay } from './GenericCompareSideBySideDataDisplay.tsx'; +import { toDownloadLink } from './toDownloadLink'; +import { type OrganismsConfig } from '../../../config'; +import { OrganismViewPageLayout } from '../../../layouts/OrganismPage/OrganismViewPageLayout.tsx'; +import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; +import { compareSideBySideViewKey } from '../../../views/viewKeys'; +import { CompareSideBySidePageStateSelector } from '../../pageStateSelectors/CompareSideBySidePageStateSelector'; + +export type GenericCompareSideBySideReactPageProps = { + organism: OrganismWithViewKey; + hideMutationComponents?: boolean; + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const GenericCompareSideBySideReactPage: FC = ({ + organism, + hideMutationComponents, + organismsConfig, + isStaging, +}) => { + const organismViewKey = `${organism}.${compareSideBySideViewKey}` satisfies OrganismViewKey; + + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const downloadLinks = [...pageState.filters.entries()].map(toDownloadLink(view.pageStateHandler, organism)); + + return ( + +
+ {Array.from(pageState.filters).map(([id, datasetAndVariantData]) => { + return ( +
+
+ {pageState.filters.size > 1 && ( + + Remove column + + )} + +
+ + +
+ ); + })} + + Add column + +
+
+ ); +}; diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro b/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro index 5095db10d..650f35d58 100644 --- a/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselinePage.astro @@ -1,56 +1,25 @@ --- -import { GenericCompareToBaselineDataDisplay } from './GenericCompareToBaselineDataDisplay'; +import { GenericCompareToBaselineReactPage } from './GenericCompareToBaselineReactPage'; import { isStaging, getDashboardsConfig } from '../../../config'; -import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; +import { type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareToBaselineViewKey } from '../../../views/viewKeys'; -import { CompareVariantsToBaselineStateSelector } from '../../pageStateSelectors/CompareVariantsToBaselineStateSelector'; -import { CompareToBaselineSelectorFallback } from '../../pageStateSelectors/FallbackElement'; -import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; -type OrganismViewCompareVariant = OrganismWithViewKey; interface Props { - organism: OrganismViewCompareVariant; + organism: OrganismWithViewKey; } const { organism } = Astro.props; -const organismViewKey = `${organism}.${compareToBaselineViewKey}` satisfies OrganismViewKey; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); -const noVariantSelected = pageState.variants.size < 1; - -const downloadLinks = noVariantSelected - ? [] - : numeratorLapisFilters.map(({ lapisFilter, displayName }) => ({ - label: `Download accessions of "${displayName}"`, - filter: lapisFilter, - downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, - })); - -const organismConfig = getDashboardsConfig().dashboards.organisms; +const view = ServerSide.routing.getOrganismView(`${organism}.${compareToBaselineViewKey}`); --- - - + - - -
- -
-
+ /> + diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx b/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx new file mode 100644 index 000000000..b1afb1c0b --- /dev/null +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx @@ -0,0 +1,63 @@ +import { type FC, useMemo } from 'react'; + +import { GenericCompareToBaselineDataDisplay } from './GenericCompareToBaselineDataDisplay'; +import { type OrganismsConfig } from '../../../config'; +import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx'; +import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; +import { compareToBaselineViewKey } from '../../../views/viewKeys'; +import { CompareVariantsToBaselineStateSelector } from '../../pageStateSelectors/CompareVariantsToBaselineStateSelector'; +import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; + +export type GenericCompareToBaselineReactPageProps = { + organism: OrganismWithViewKey; + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const GenericCompareToBaselineReactPage: FC = ({ + organism, + organismsConfig, + isStaging, +}) => { + const organismViewKey = `${organism}.${compareToBaselineViewKey}` satisfies OrganismViewKey; + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); + const noVariantSelected = pageState.variants.size < 1; + + const downloadLinks = noVariantSelected + ? [] + : numeratorLapisFilters.map(({ lapisFilter, displayName }) => ({ + label: `Download accessions of "${displayName}"`, + filter: lapisFilter, + downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, + })); + + return ( + + } + dataDisplay={ + + } + /> + ); +}; diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro b/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro index 76727768d..4b5a062e1 100644 --- a/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro +++ b/website/src/components/views/compareVariants/GenericCompareVariantsPage.astro @@ -1,55 +1,25 @@ --- -import { GenericCompareVariantsDataDisplay } from './GenericCompareVariantsDataDisplay'; +import { GenericCompareVariantsReactPage } from './GenericCompareVariantsReactPage'; import { isStaging, getDashboardsConfig } from '../../../config'; -import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; +import { type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { compareVariantsViewKey } from '../../../views/viewKeys'; -import { CompareVariantsPageStateSelector } from '../../pageStateSelectors/CompareVariantsPageStateSelector'; -import { CompareVariantsSelectorFallback } from '../../pageStateSelectors/FallbackElement'; -import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; -type OrganismViewCompareVariant = OrganismWithViewKey; interface Props { - organism: OrganismViewCompareVariant; + organism: OrganismWithViewKey; } const { organism } = Astro.props; -const organismViewKey = `${organism}.${compareVariantsViewKey}` satisfies OrganismViewKey; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); -const notEnoughVariantsSelected = pageState.variants.size < 2; -const downloadLinks = notEnoughVariantsSelected - ? [] - : numeratorLapisFilters.map(({ lapisFilter, displayName }) => ({ - label: `Download accessions of "${displayName}"`, - filter: lapisFilter, - downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, - })); - -const organismConfig = getDashboardsConfig().dashboards.organisms; +const view = ServerSide.routing.getOrganismView(`${organism}.${compareVariantsViewKey}`); --- - - + - - -
- -
-
+ /> + diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx b/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx new file mode 100644 index 000000000..d1b970481 --- /dev/null +++ b/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx @@ -0,0 +1,63 @@ +import { type FC, useMemo } from 'react'; + +import { GenericCompareVariantsDataDisplay } from './GenericCompareVariantsDataDisplay'; +import { type OrganismsConfig } from '../../../config'; +import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx'; +import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; +import { compareVariantsViewKey } from '../../../views/viewKeys'; +import { CompareVariantsPageStateSelector } from '../../pageStateSelectors/CompareVariantsPageStateSelector'; +import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; + +export type GenericCompareVariantsReactPageProps = { + organism: OrganismWithViewKey; + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const GenericCompareVariantsReactPage: FC = ({ + organism, + organismsConfig, + isStaging, +}) => { + const organismViewKey = `${organism}.${compareVariantsViewKey}` satisfies OrganismViewKey; + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const numeratorLapisFilters = view.pageStateHandler.variantFiltersToNamedLapisFilters(pageState); + const notEnoughVariantsSelected = pageState.variants.size < 2; + + const downloadLinks = notEnoughVariantsSelected + ? [] + : numeratorLapisFilters.map(({ lapisFilter, displayName }) => ({ + label: `Download accessions of "${displayName}"`, + filter: lapisFilter, + downloadFileBasename: `${organism}_${sanitizeForFilename(displayName)}_accessions`, + })); + + return ( + + } + dataDisplay={ + + } + /> + ); +}; diff --git a/website/src/components/views/sequencingEfforts/GenericSequencingEffortsPage.astro b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsPage.astro index 45418e0a1..b23520e33 100644 --- a/website/src/components/views/sequencingEfforts/GenericSequencingEffortsPage.astro +++ b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsPage.astro @@ -1,56 +1,25 @@ --- -import { GenericSequencingEffortsDataDisplay } from './GenericSequencingEffortsDataDisplay'; +import { GenericSequencingEffortsReactPage } from './GenericSequencingEffortsReactPage'; import { isStaging, getDashboardsConfig } from '../../../config'; -import SingleVariantOrganismPageLayout from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { type OrganismViewKey, type OrganismWithViewKey } from '../../../views/routing'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; +import { type OrganismWithViewKey } from '../../../views/routing'; import { ServerSide } from '../../../views/serverSideRouting'; import { sequencingEffortsViewKey } from '../../../views/viewKeys'; -import { SequencingEffortsSelectorFallback } from '../../pageStateSelectors/FallbackElement'; -import { SequencingEffortsPageStateSelector } from '../../pageStateSelectors/SequencingEffortsPageStateSelector'; -type OrganismViewCompareVariant = OrganismWithViewKey; interface Props { - organism: OrganismViewCompareVariant; + organism: OrganismWithViewKey; } const { organism } = Astro.props; -const organismViewKey: OrganismViewKey = `${organism}.${sequencingEffortsViewKey}` satisfies OrganismViewKey; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const lapisFilter = view.pageStateHandler.toLapisFilter(pageState); - -const organismConfig = getDashboardsConfig().dashboards.organisms; +const view = ServerSide.routing.getOrganismView(`${organism}.${sequencingEffortsViewKey}`); --- - - + - - - -
- -
-
+ /> + diff --git a/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx new file mode 100644 index 000000000..8dea17a2e --- /dev/null +++ b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx @@ -0,0 +1,61 @@ +import { type FC, useMemo } from 'react'; + +import { GenericSequencingEffortsDataDisplay } from './GenericSequencingEffortsDataDisplay'; +import { type OrganismsConfig } from '../../../config'; +import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx'; +import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; +import { sequencingEffortsViewKey } from '../../../views/viewKeys'; +import { SequencingEffortsPageStateSelector } from '../../pageStateSelectors/SequencingEffortsPageStateSelector'; + +export type GenericSequencingEffortsReactPageProps = { + organism: OrganismWithViewKey; + organismsConfig: OrganismsConfig; + isStaging: boolean; +}; + +export const GenericSequencingEffortsReactPage: FC = ({ + organism, + organismsConfig, + isStaging, +}) => { + const organismViewKey = `${organism}.${sequencingEffortsViewKey}` satisfies OrganismViewKey; + const view = useMemo( + () => new Routing(organismsConfig).getOrganismView(organismViewKey), + [organismsConfig, organismViewKey], + ); + + const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + + const lapisFilter = view.pageStateHandler.toLapisFilter(pageState); + + const downloadLinks = [ + { + label: 'Download accessions', + filter: lapisFilter, + downloadFileBasename: `${organism}_sequencing_efforts_accessions`, + }, + ]; + + return ( + + } + dataDisplay={ + + } + /> + ); +}; diff --git a/website/src/components/views/wasap/Wasap.astro b/website/src/components/views/wasap/Wasap.astro index 2a9c7196f..4c24593d2 100644 --- a/website/src/components/views/wasap/Wasap.astro +++ b/website/src/components/views/wasap/Wasap.astro @@ -1,36 +1,18 @@ --- import { WasapPage } from './WasapPage'; -import { defaultBreadcrumbs } from '../../../layouts/Breadcrumbs'; -import DataPageLayout from '../../../layouts/OrganismPage/DataPageLayout.astro'; -import { dataOrigins } from '../../../types/dataOrigins'; -import { - wastewaterBreadcrumb, - wastewaterOrganismConfigs, - type WastewaterOrganismName, -} from '../../../types/wastewaterConfig'; +import BaseLayout from '../../../layouts/base/BaseLayout.astro'; +import { wastewaterOrganismConfigs, type WastewaterOrganismName } from '../../../types/wastewaterConfig'; type Props = { wastewaterOrganism: WastewaterOrganismName; }; const { wastewaterOrganism } = Astro.props; -const { name, path: href, lapisBaseUrl } = wastewaterOrganismConfigs[wastewaterOrganism]; +const { name } = wastewaterOrganismConfigs[wastewaterOrganism]; const url = Astro.url; --- - + - + diff --git a/website/src/components/views/wasap/WasapPage.tsx b/website/src/components/views/wasap/WasapPage.tsx index 70cc2d2f5..5067ec857 100644 --- a/website/src/components/views/wasap/WasapPage.tsx +++ b/website/src/components/views/wasap/WasapPage.tsx @@ -13,7 +13,14 @@ import { } from './wasapPageConfig'; import { getDateRange } from '../../../lapis/getDateRange'; import { getTotalCount } from '../../../lapis/getTotalCount'; -import { wastewaterOrganismConfigs, type WastewaterOrganismName } from '../../../types/wastewaterConfig'; +import { defaultBreadcrumbs } from '../../../layouts/Breadcrumbs.tsx'; +import { DataPageLayout } from '../../../layouts/OrganismPage/DataPageLayout.tsx'; +import { dataOrigins } from '../../../types/dataOrigins.ts'; +import { + wastewaterBreadcrumb, + wastewaterOrganismConfigs, + type WastewaterOrganismName, +} from '../../../types/wastewaterConfig'; import { Loading } from '../../../util/Loading'; import { WasapPageStateHandler } from '../../../views/pageStateHandlers/WasapPageStateHandler'; import { GsMutationsOverTime } from '../../genspectrum/GsMutationsOverTime'; @@ -64,56 +71,69 @@ export const WasapPageInner: FC = ({ wastewaterOrganism, current const memoizedLinkTemplate = useMemo(() => JSON.stringify(config.linkTemplate), [config.linkTemplate]); return ( - -
-
- -
- {isError ? ( - There was an error fetching the mutations to display. - ) : isPending ? ( - - ) : ( -
- {displayMutations?.length === 0 ? ( - - ) : ( - - )} - {analysis.mode === 'variant' && config.variantAnalysisModeEnabled && ( - - )} - + +
+
+
- )} -
-
+ {isError ? ( + There was an error fetching the mutations to display. + ) : isPending ? ( + + ) : ( +
+ {displayMutations?.length === 0 ? ( + + ) : ( + + )} + {analysis.mode === 'variant' && config.variantAnalysisModeEnabled && ( + + )} + +
+ )} +
+ + ); }; diff --git a/website/src/lapis/getLastUpdatedDate.spec.ts b/website/src/lapis/getLastUpdatedDate.spec.ts index 410ee68a8..4dea079e4 100644 --- a/website/src/lapis/getLastUpdatedDate.spec.ts +++ b/website/src/lapis/getLastUpdatedDate.spec.ts @@ -28,7 +28,7 @@ describe('getLastUpdatedDate', () => { const result = await getLastUpdatedDate(DUMMY_LAPIS_URL); - expect(result).toBeUndefined(); + expect(result).toBeNull(); }); test('should handle non-numeric data versions gracefully', async () => { @@ -36,6 +36,6 @@ describe('getLastUpdatedDate', () => { const result = await getLastUpdatedDate(DUMMY_LAPIS_URL); - expect(result).toBeUndefined(); + expect(result).toBeNull(); }); }); diff --git a/website/src/lapis/getLastUpdatedDate.ts b/website/src/lapis/getLastUpdatedDate.ts index 4fcdac581..013724881 100644 --- a/website/src/lapis/getLastUpdatedDate.ts +++ b/website/src/lapis/getLastUpdatedDate.ts @@ -2,14 +2,14 @@ import axios from 'axios'; import dayjs from 'dayjs'; import { z } from 'zod'; -import { getInstanceLogger } from '../logger.ts'; +import { getClientLogger } from '../clientLogger.ts'; const lapisInfoSchema = z.object({ dataVersion: z.string(), }); export type LapisInfo = z.infer; -const logger = getInstanceLogger('getLastUpdatedDate'); +const logger = getClientLogger('getLastUpdatedDate'); export async function getLastUpdatedDate(lapisUrl: string) { try { @@ -20,7 +20,7 @@ export async function getLastUpdatedDate(lapisUrl: string) { const timestamp = Number(parsedLapisInfo.data.dataVersion); if (isNaN(timestamp)) { logger.error(`Got invalid timestamp from lapis info: '${parsedLapisInfo.data.dataVersion}'`); - return undefined; + return null; } return dayjs.unix(timestamp).locale('de').calendar(null, { sameElse: '[on] YYYY-MM-DD' }); } @@ -28,9 +28,9 @@ export async function getLastUpdatedDate(lapisUrl: string) { logger.error( `Failed to parse lapis info: ${JSON.stringify(parsedLapisInfo)} (was ${JSON.stringify(response.data)})`, ); - return undefined; + return null; } catch (error) { logger.error(`Failed to fetch lapis info: ${JSON.stringify(error)}`); - return undefined; + return null; } } diff --git a/website/src/layouts/OrganismPage/AccessionsDownloadButton.astro b/website/src/layouts/OrganismPage/AccessionsDownloadButton.astro deleted file mode 100644 index 3457d3132..000000000 --- a/website/src/layouts/OrganismPage/AccessionsDownloadButton.astro +++ /dev/null @@ -1,53 +0,0 @@ ---- -import type { LapisFilter } from '@genspectrum/dashboard-components/util'; - -import { assembleDownloadUrl } from './assembleDownloadUrl'; -import { Modal } from '../../styles/containers/Modal'; -import { ModalContent } from '../../styles/containers/ModalContent'; -import { ModalHeader } from '../../styles/containers/ModalHeader'; - -type DownloadLink = { - label: string; - filter: LapisFilter; - downloadFileBasename: string; -}; - -interface Props { - accessionDownloadFields: string[]; - downloadLinks: DownloadLink[]; - lapisUrl: string; -} - -const { accessionDownloadFields, downloadLinks, lapisUrl } = Astro.props; - -const modalId = 'accessionDownloadModal'; ---- - - - - - -

You can download a list of accessions that are used for the visualizations on this page:

-
- { - downloadLinks - .map(({ label, filter, downloadFileBasename }) => ({ - label, - url: assembleDownloadUrl(accessionDownloadFields, filter, downloadFileBasename, lapisUrl), - })) - .map(({ label, url }) => ( - - - {label} - - )) - } -
-
- -
-
-
diff --git a/website/src/layouts/OrganismPage/AccessionsDownloadButton.tsx b/website/src/layouts/OrganismPage/AccessionsDownloadButton.tsx new file mode 100644 index 000000000..4bb1fd7a3 --- /dev/null +++ b/website/src/layouts/OrganismPage/AccessionsDownloadButton.tsx @@ -0,0 +1,63 @@ +import type { LapisFilter } from '@genspectrum/dashboard-components/util'; +import type { FC } from 'react'; + +import { assembleDownloadUrl } from './assembleDownloadUrl'; +import { Modal, useModalRef } from '../../styles/containers/Modal'; +import { ModalContent } from '../../styles/containers/ModalContent'; +import { ModalHeader } from '../../styles/containers/ModalHeader'; + +export type DownloadLink = { + label: string; + filter: LapisFilter; + downloadFileBasename: string; +}; + +export type AccessionsDownloadButtonProps = { + accessionDownloadFields: string[]; + downloadLinks: DownloadLink[]; + lapisUrl: string; +}; + +export const AccessionsDownloadButton: FC = ({ + accessionDownloadFields, + downloadLinks, + lapisUrl, +}) => { + const modalRef = useModalRef(); + + return ( + <> + + + + +

You can download a list of accessions that are used for the visualizations on this page:

+
+ {downloadLinks + .map(({ label, filter, downloadFileBasename }) => ({ + label, + url: assembleDownloadUrl( + accessionDownloadFields, + filter, + downloadFileBasename, + lapisUrl, + ), + })) + .map(({ label, url }) => ( + + + {label} + + ))} +
+
+ +
+
+
+ + ); +}; diff --git a/website/src/layouts/OrganismPage/DataPageLayout.astro b/website/src/layouts/OrganismPage/DataPageLayout.astro deleted file mode 100644 index fbd92a1cf..000000000 --- a/website/src/layouts/OrganismPage/DataPageLayout.astro +++ /dev/null @@ -1,48 +0,0 @@ ---- -import type { ComponentProps } from 'astro/types'; - -import LapisUnreachableWrapperClient from '../../components/LapisUnreachableWrapperClient'; -import { type BreadcrumbElement, Breadcrumbs } from '../Breadcrumbs'; -import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; -import LastUpdatedInfo from './LastUpdatedInfo.astro'; -import type { DataOrigin } from '../../types/dataOrigins.ts'; -import BaseLayout from '../base/BaseLayout.astro'; -import DataInfo from '../base/footer/DataInfo.astro'; - -interface Props { - title: string; - breadcrumbs: BreadcrumbElement[]; - dataOrigins: DataOrigin[]; - lapisUrl: string; - downloadLinks?: ComponentProps['downloadLinks']; - accessionDownloadFields?: string[]; -} - -const { title, breadcrumbs, dataOrigins, lapisUrl, downloadLinks = [], accessionDownloadFields = [] } = Astro.props; ---- - - -
-
- -
-
- - - -
-
- { - downloadLinks.length > 0 && ( - - ) - } - - -
-
-
diff --git a/website/src/layouts/OrganismPage/DataPageLayout.tsx b/website/src/layouts/OrganismPage/DataPageLayout.tsx new file mode 100644 index 000000000..969d87802 --- /dev/null +++ b/website/src/layouts/OrganismPage/DataPageLayout.tsx @@ -0,0 +1,50 @@ +import type { FC, PropsWithChildren } from 'react'; + +import { LapisUnreachableWrapperClient } from '../../components/LapisUnreachableWrapperClient.tsx'; +import type { DataOrigin } from '../../types/dataOrigins.ts'; +import { type BreadcrumbElement, Breadcrumbs } from '../Breadcrumbs.tsx'; +import { AccessionsDownloadButton, type DownloadLink } from './AccessionsDownloadButton.tsx'; +import { LastUpdatedInfo } from './LastUpdatedInfo.tsx'; +import { withQueryProvider } from '../../components/subscriptions/backendApi/withQueryProvider.tsx'; +import { DataInfo } from '../base/footer/DataInfo.tsx'; + +export type DataPageLayoutProps = PropsWithChildren<{ + breadcrumbs: BreadcrumbElement[]; + dataOrigins: DataOrigin[]; + lapisUrl: string; + downloadLinks?: DownloadLink[]; + accessionDownloadFields?: string[]; +}>; + +export const DataPageLayoutInner: FC = ({ + breadcrumbs, + dataOrigins, + lapisUrl, + downloadLinks = [], + accessionDownloadFields = [], + children, +}) => { + return ( +
+
+ +
+
+ {children} +
+
+ {downloadLinks.length > 0 && ( + + )} + + +
+
+ ); +}; + +export const DataPageLayout = withQueryProvider(DataPageLayoutInner); diff --git a/website/src/layouts/OrganismPage/LastUpdatedInfo.astro b/website/src/layouts/OrganismPage/LastUpdatedInfo.astro deleted file mode 100644 index 1d29acab1..000000000 --- a/website/src/layouts/OrganismPage/LastUpdatedInfo.astro +++ /dev/null @@ -1,13 +0,0 @@ ---- -import { getLastUpdatedDate } from '../../lapis/getLastUpdatedDate'; - -interface Props { - lapisUrl: string; -} - -const { lapisUrl } = Astro.props; - -const lastUpdatedDate = await getLastUpdatedDate(lapisUrl); ---- - -Data last updated: {lastUpdatedDate ?? 'unknown'} diff --git a/website/src/layouts/OrganismPage/LastUpdatedInfo.tsx b/website/src/layouts/OrganismPage/LastUpdatedInfo.tsx new file mode 100644 index 000000000..67eeeae5e --- /dev/null +++ b/website/src/layouts/OrganismPage/LastUpdatedInfo.tsx @@ -0,0 +1,18 @@ +import { useQuery } from '@tanstack/react-query'; +import type { FC } from 'react'; + +import { getLastUpdatedDate } from '../../lapis/getLastUpdatedDate'; + +interface LastUpdatedInfoProps { + lapisUrl: string; +} + +export const LastUpdatedInfo: FC = ({ lapisUrl }) => { + const { data: lastUpdatedDate } = useQuery({ + queryKey: ['lastUpdatedDate', lapisUrl], + queryFn: () => getLastUpdatedDate(lapisUrl), + throwOnError: true, + }); + + return Data last updated: {lastUpdatedDate ?? 'unknown'}; +}; diff --git a/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro b/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro deleted file mode 100644 index 11d51ab7b..000000000 --- a/website/src/layouts/OrganismPage/OrganismViewPageLayout.astro +++ /dev/null @@ -1,33 +0,0 @@ ---- -import type { ComponentProps } from 'astro/types'; - -import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; -import DataPageLayout from './DataPageLayout.astro'; -import { getLapisUrl } from '../../config'; -import type { OrganismConstants } from '../../views/OrganismConstants'; -import { type View } from '../../views/View'; -import type { PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler'; - -interface Props { - view: View>; - downloadLinks: ComponentProps['downloadLinks']; -} - -const { view, downloadLinks } = Astro.props; ---- - - - - - - diff --git a/website/src/layouts/OrganismPage/OrganismViewPageLayout.tsx b/website/src/layouts/OrganismPage/OrganismViewPageLayout.tsx new file mode 100644 index 000000000..d14a6f850 --- /dev/null +++ b/website/src/layouts/OrganismPage/OrganismViewPageLayout.tsx @@ -0,0 +1,34 @@ +import type { FC, PropsWithChildren } from 'react'; + +import { type DownloadLink } from './AccessionsDownloadButton.tsx'; +import { DataPageLayout } from './DataPageLayout.tsx'; +import type { OrganismConstants } from '../../views/OrganismConstants'; +import { type View } from '../../views/View'; +import type { PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler'; + +export type OrganismViewPageLayoutProps = PropsWithChildren<{ + view: View>; + downloadLinks: DownloadLink[]; + lapisUrl: string; +}>; + +export const OrganismViewPageLayout: FC = ({ + view, + downloadLinks, + lapisUrl, + children, +}) => { + return ( + + + {children} + + + ); +}; diff --git a/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro b/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro deleted file mode 100644 index 514a91a78..000000000 --- a/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.astro +++ /dev/null @@ -1,25 +0,0 @@ ---- -import type { ComponentProps } from 'astro/types'; - -import AccessionsDownloadButton from './AccessionsDownloadButton.astro'; -import OrganismViewPageLayout from './OrganismViewPageLayout.astro'; -import type { OrganismConstants } from '../../views/OrganismConstants'; -import type { View } from '../../views/View'; -import { type PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler'; - -interface Props { - view: View>; - downloadLinks: ComponentProps['downloadLinks']; -} - -const { view, downloadLinks } = Astro.props; ---- - - -
-
- -
- -
-
diff --git a/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx b/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx new file mode 100644 index 000000000..ceebf3a44 --- /dev/null +++ b/website/src/layouts/OrganismPage/SingleVariantOrganismPageLayout.tsx @@ -0,0 +1,37 @@ +import type { FC, ReactNode } from 'react'; + +import { type DownloadLink } from './AccessionsDownloadButton.tsx'; +import { OrganismViewPageLayout } from './OrganismViewPageLayout.tsx'; +import type { OrganismsConfig } from '../../config.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants'; +import type { View } from '../../views/View'; +import { type PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler'; + +export type SingleVariantOrganismPageLayoutProps = { + view: View>; + downloadLinks: DownloadLink[]; + organismsConfig: OrganismsConfig; + filters: ReactNode; + dataDisplay: ReactNode; +}; + +export const SingleVariantOrganismPageLayout: FC = ({ + view, + downloadLinks, + organismsConfig, + filters, + dataDisplay, +}) => { + return ( + +
+
{filters}
+ {dataDisplay} +
+
+ ); +}; diff --git a/website/src/layouts/base/footer/DataInfo.astro b/website/src/layouts/base/footer/DataInfo.astro deleted file mode 100644 index 93cc13254..000000000 --- a/website/src/layouts/base/footer/DataInfo.astro +++ /dev/null @@ -1,26 +0,0 @@ ---- -import DataOriginLink from './DataOriginLink.astro'; -import { type DataOrigin, dataOriginConfig } from '../../../types/dataOrigins'; - -interface Props { - dataOrigins: DataOrigin[]; -} - -const { dataOrigins } = Astro.props; ---- - -
-
- Enabled by data from: - { - dataOrigins.map((dataOrigin, index) => ( - - {index > 0 && (index === dataOrigins.length - 1 ? ' and ' : ', ')} - - {dataOriginConfig[dataOrigin].name} - - - )) - } -
-
diff --git a/website/src/layouts/base/footer/DataInfo.tsx b/website/src/layouts/base/footer/DataInfo.tsx new file mode 100644 index 000000000..ae7b3bd6b --- /dev/null +++ b/website/src/layouts/base/footer/DataInfo.tsx @@ -0,0 +1,38 @@ +import { type FC, type PropsWithChildren } from 'react'; + +import { externalLinkIconCss } from '../../../components/iconCss.ts'; +import { type DataOrigin, dataOriginConfig } from '../../../types/dataOrigins'; + +export type DataInfoProps = { + dataOrigins: DataOrigin[]; +}; + +export const DataInfo: FC = ({ dataOrigins }) => { + return ( +
+
+ Enabled by data from: + {dataOrigins.map((dataOrigin, index) => ( + + {index > 0 && (index === dataOrigins.length - 1 ? ' and ' : ', ')} + + {dataOriginConfig[dataOrigin].name} + + + ))} +
+
+ ); +}; + +type DataOriginLinkProps = PropsWithChildren<{ + href: string; +}>; + +const DataOriginLink: FC = ({ href, children }) => { + return ( + + {children} + + ); +}; diff --git a/website/src/layouts/base/footer/DataOriginLink.astro b/website/src/layouts/base/footer/DataOriginLink.astro deleted file mode 100644 index 3e0700e55..000000000 --- a/website/src/layouts/base/footer/DataOriginLink.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- -import { externalLinkIconCss } from '../../../components/iconCss'; -interface Props { - href: string; -} - -const { href } = Astro.props; ---- - - - - diff --git a/website/src/pages/covid/single-variant.astro b/website/src/pages/covid/single-variant.astro index 0a56d0eaa..fa95aaefb 100644 --- a/website/src/pages/covid/single-variant.astro +++ b/website/src/pages/covid/single-variant.astro @@ -1,72 +1,16 @@ --- -import { AnalyzeSingleVariantSelectorFallback } from '../../components/pageStateSelectors/FallbackElement'; -import { SelectorHeadline } from '../../components/pageStateSelectors/SelectorHeadline'; -import { SingleVariantPageStateSelector } from '../../components/pageStateSelectors/SingleVariantPageStateSelector'; -import { CollectionsList } from '../../components/views/analyzeSingleVariant/CollectionsList'; -import { CovidSingleVariantDataDisplay } from '../../components/views/analyzeSingleVariant/CovidSingleVariantDataDisplay'; -import { sanitizeForFilename } from '../../components/views/compareSideBySide/toDownloadLink'; +import { CovidSingleVariantReactPage } from '../../components/views/analyzeSingleVariant/CovidSingleVariantReactPage'; import { isStaging, getDashboardsConfig } from '../../config'; -import SingleVariantOrganismPageLayout from '../../layouts/OrganismPage/SingleVariantOrganismPageLayout.astro'; -import { hasOnlyUndefinedValues } from '../../util/hasOnlyUndefinedValues'; -import { toDisplayName } from '../../views/pageStateHandlers/PageStateHandler'; -import { type OrganismViewKey } from '../../views/routing'; +import BaseLayout from '../../layouts/base/BaseLayout.astro'; import { ServerSide } from '../../views/serverSideRouting'; -const organismViewKey: OrganismViewKey = 'covid.singleVariantView'; -const view = ServerSide.routing.getOrganismView(organismViewKey); -const pageState = view.pageStateHandler.parsePageStateFromUrl(Astro.url); - -const variantFilter = view.pageStateHandler.toLapisFilter(pageState); - -const noVariantSelected = hasOnlyUndefinedValues(pageState.variantFilter); - -const displayName = toDisplayName(pageState.variantFilter); -const downloadLinks = noVariantSelected - ? [ - { - label: 'Download all accessions', - filter: variantFilter, - downloadFileBasename: `${view.organismConstants.organism}_accessions`, - }, - ] - : [ - { - label: `Download accessions of ${displayName}`, - filter: variantFilter, - downloadFileBasename: `${view.organismConstants.organism}_${sanitizeForFilename(displayName)}_accessions`, - }, - ]; -const organismConfig = getDashboardsConfig().dashboards.organisms; +const view = ServerSide.routing.getOrganismView('covid.singleVariantView'); --- - -
- - - -
-
- Collections - -
-
- -
- -
-
+ + + diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index be85c87ee..1f93fad8f 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -2,7 +2,7 @@ import Link from '../components/Link.astro'; import MainMenu from '../components/MainMenu.astro'; import BaseLayout from '../layouts/base/BaseLayout.astro'; -import DataInfo from '../layouts/base/footer/DataInfo.astro'; +import { DataInfo } from '../layouts/base/footer/DataInfo.tsx'; import { BrandName } from '../layouts/base/header/Brand'; import { getPathogenMegaMenuSections } from '../layouts/base/header/getPathogenMegaMenuSections'; import { dataOrigins } from '../types/dataOrigins'; diff --git a/website/src/pages/swiss-wastewater/flu.astro b/website/src/pages/swiss-wastewater/flu.astro index 9395dd487..119324242 100644 --- a/website/src/pages/swiss-wastewater/flu.astro +++ b/website/src/pages/swiss-wastewater/flu.astro @@ -4,7 +4,8 @@ import type { SequenceType } from '@genspectrum/dashboard-components/util'; import InfluenzaWastewaterInfo from '../../components/InfluenzaWastewaterInfo.astro'; import GsWastewaterMutationsOverTime from '../../components/genspectrum/GsWastewaterMutationsOverTime.astro'; import { defaultBreadcrumbs } from '../../layouts/Breadcrumbs'; -import DataPageLayout from '../../layouts/OrganismPage/DataPageLayout.astro'; +import { DataPageLayout } from '../../layouts/OrganismPage/DataPageLayout.tsx'; +import BaseLayout from '../../layouts/base/BaseLayout.astro'; import { dataOrigins } from '../../types/dataOrigins'; import { getMutationAnnotation, @@ -16,48 +17,49 @@ import { const lapisUrl = `${wastewaterConfig.lapisBaseUrl}/influenza`; --- - + { - name: 'Influenza', - href: wastewaterConfig.pages.influenza.path, - }, - ]} - dataOrigins={[dataOrigins.wise]} - lapisUrl={lapisUrl} -> - { - InfluenzaTypes.map((reference) => { - const mutationAnnotations = getMutationAnnotation(reference); - return ( - -
-

{reference}

- {(['nucleotide', 'amino acid'] satisfies SequenceType[]).map((sequenceType) => ( - - { + const mutationAnnotations = getMutationAnnotation(reference); + return ( + +
+

{reference}

+ {(['nucleotide', 'amino acid'] satisfies SequenceType[]).map((sequenceType) => ( + - - ))} -
-
- ); - }) - } - + collapsible={sequenceType === 'nucleotide'} + linkSuffix={reference} + > + +
+ ))} +
+
+ ); + }) + } +
+ diff --git a/website/src/pages/swiss-wastewater/rsv.astro b/website/src/pages/swiss-wastewater/rsv.astro index b8ca93065..0a37abb92 100644 --- a/website/src/pages/swiss-wastewater/rsv.astro +++ b/website/src/pages/swiss-wastewater/rsv.astro @@ -4,56 +4,58 @@ import type { SequenceType } from '@genspectrum/dashboard-components/util'; import RsvWastewaterInfo from '../../components/RsvWastewaterInfo.astro'; import GsWastewaterMutationsOverTime from '../../components/genspectrum/GsWastewaterMutationsOverTime.astro'; import { defaultBreadcrumbs } from '../../layouts/Breadcrumbs'; -import DataPageLayout from '../../layouts/OrganismPage/DataPageLayout.astro'; +import { DataPageLayout } from '../../layouts/OrganismPage/DataPageLayout.tsx'; +import BaseLayout from '../../layouts/base/BaseLayout.astro'; import { dataOrigins } from '../../types/dataOrigins'; import { wastewaterConfig, RSVTypes, wastewaterBreadcrumb } from '../../types/wastewaterConfig'; const lapisUrl = `${wastewaterConfig.lapisBaseUrl}/rsv`; --- - - -
+ + ( - <> -
-

{reference}

- {(['nucleotide', 'amino acid'] satisfies SequenceType[]).map((sequenceType) => ( - - + +
+ { + RSVTypes.map((reference) => ( + <> +
+

{reference}

+ {(['nucleotide', 'amino acid'] satisfies SequenceType[]).map((sequenceType) => ( + - - ))} -
- - )) - } -
-
- + collapsible={sequenceType === 'nucleotide'} + linkSuffix={reference} + > + +
+ ))} +
+ + )) + } +
+
+
+ From 5f769b8158d63623901674cd81aed54edf10db83 Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer <92720311+fengelniederhammer@users.noreply.github.com> Date: Tue, 13 Jan 2026 08:20:37 +0100 Subject: [PATCH 22/26] ci: lint PR title instead of commits (#989) * lint PR title instead of commits * remove obsolete scripts * also on "edited" * typo * prevent command line injection * prevent command line injection --- .github/workflows/commitlint.yml | 7 +++++-- CONTRIBUTING.md | 4 +++- package.json | 4 ---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 54d7437f9..c3579d2a6 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -4,6 +4,7 @@ on: pull_request: types: - opened + - edited - reopened - synchronize - ready_for_review @@ -29,5 +30,7 @@ jobs: - name: Install npm packages run: npm ci - - name: Validate PR commits with commitlint - run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --verbose + - name: Lint PR title + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: echo "$PR_TITLE" | npx commitlint --verbose \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3bbffc9a..bda464925 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,9 @@ Contributions are very welcome! Just fork the repository, develop in a branch an ## Commit Messages -We follow [conventional commits](https://www.conventionalcommits.org) when writing commit messages. +Commits on the `main` branch should follow [conventional commits](https://www.conventionalcommits.org). +Since we squash-merge pull requests, the PR title should also follow conventional commits +(because it will become the commit message of the squashed commit). The messages themselves should help future developers understand **why** changes were made. ## Code Style diff --git a/package.json b/package.json index 4b7274c65..007e273f1 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,5 @@ "@commitlint/cli": "^19.4.0", "@commitlint/config-conventional": "^19.2.2", "@commitlint/types": "^19.0.3" - }, - "scripts": { - "commitlint:last-commit": "commitlint --from=HEAD~1 --verbose", - "commitlint:merge-base": "commitlint --from=$(git merge-base HEAD main) --verbose" } } From a29532729e982ef3552ce7f7a4f5e8160ef29498 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 08:21:23 +0100 Subject: [PATCH 23/26] chore(website): bump the minorandpatch group in /website with 5 updates (#993) Bumps the minorandpatch group in /website with 5 updates: | Package | From | To | | --- | --- | --- | | [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) | `5.90.15` | `5.90.16` | | [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `5.16.6` | `5.16.9` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.51.0` | `8.53.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.51.0` | `8.53.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.51.0` | `8.53.0` | Updates `@tanstack/react-query` from 5.90.15 to 5.90.16 - [Release notes](https://github.com/TanStack/query/releases) - [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md) - [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.90.16/packages/react-query) Updates `astro` from 5.16.6 to 5.16.9 - [Release notes](https://github.com/withastro/astro/releases) - [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md) - [Commits](https://github.com/withastro/astro/commits/astro@5.16.9/packages/astro) Updates `@typescript-eslint/eslint-plugin` from 8.51.0 to 8.53.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.51.0 to 8.53.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.0/packages/parser) Updates `typescript-eslint` from 8.51.0 to 8.53.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.53.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@tanstack/react-query" dependency-version: 5.90.16 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: astro dependency-version: 5.16.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: minorandpatch - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.53.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: "@typescript-eslint/parser" dependency-version: 8.53.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch - dependency-name: typescript-eslint dependency-version: 8.53.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minorandpatch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- website/package-lock.json | 863 +++++++------------------------------- website/package.json | 10 +- 2 files changed, 157 insertions(+), 716 deletions(-) diff --git a/website/package-lock.json b/website/package-lock.json index 62b2c6c83..7d73e8fb0 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -12,8 +12,8 @@ "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.15", - "astro": "^5.16.6", + "@tanstack/react-query": "^5.90.16", + "astro": "^5.16.9", "auth-astro": "^4.2.0", "axios": "^1.13.2", "cookie": "^1.1.1", @@ -48,8 +48,8 @@ "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.51.0", - "@typescript-eslint/parser": "^8.51.0", + "@typescript-eslint/eslint-plugin": "^8.53.0", + "@typescript-eslint/parser": "^8.53.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", "daisyui": "^5.5.14", @@ -66,7 +66,7 @@ "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", "typescript": "^5.9.3", - "typescript-eslint": "^8.51.0", + "typescript-eslint": "^8.53.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" @@ -103,29 +103,6 @@ "node": ">=18" } }, - "node_modules/@asamuzakjp/css-color": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", - "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@csstools/css-calc": "^2.1.2", - "@csstools/css-color-parser": "^3.0.8", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" - } - }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC", - "optional": true - }, "node_modules/@astrojs/check": { "version": "0.9.6", "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.6.tgz", @@ -149,8 +126,7 @@ "version": "2.13.0", "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { "version": "0.7.5", @@ -309,7 +285,6 @@ "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.37.4.tgz", "integrity": "sha512-HOXJwXWXQRhbBDHlMU0K/6FT1v+wjtzdKhsNg0ZN7/gne6XPsIrjZ4daMcFnbq0Z/vsAbYBinQhhua0d77v7qw==", "license": "ISC", - "peer": true, "dependencies": { "@panva/hkdf": "^1.2.1", "jose": "^5.9.6", @@ -365,7 +340,6 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -646,12 +620,12 @@ } }, "node_modules/@capsizecss/unpack": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-3.0.1.tgz", - "integrity": "sha512-8XqW8xGn++Eqqbz3e9wKuK7mxryeRjs4LOHLxbh2lwKeSbuNR4NFifDZT4KzvjU6HMOPbiNTsWpniK5EJfTWkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", + "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", "license": "MIT", "dependencies": { - "fontkit": "^2.0.2" + "fontkitten": "^1.0.0" }, "engines": { "node": ">=18" @@ -666,81 +640,6 @@ "node": ">=0.1.90" } }, - "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/css-calc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", - "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", - "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@csstools/color-helpers": "^5.0.2", - "@csstools/css-calc": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" - } - }, "node_modules/@cyberalien/svg-utils": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@cyberalien/svg-utils/-/svg-utils-1.0.11.tgz", @@ -1235,9 +1134,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1254,9 +1153,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -2795,15 +2694,6 @@ "node": ">=18" } }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, "node_modules/@tailwindcss/node": { "version": "4.1.18", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", @@ -3154,9 +3044,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.90.15", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.15.tgz", - "integrity": "sha512-mInIZNUZftbERE+/Hbtswfse49uUQwch46p+27gP9DWJL927UjnaWEF2t3RMOqBcXbfMdcNkPe06VyUIAZTV1g==", + "version": "5.90.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.16.tgz", + "integrity": "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww==", "license": "MIT", "funding": { "type": "github", @@ -3164,12 +3054,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.90.15", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.15.tgz", - "integrity": "sha512-uQvnDDcTOgJouNtAyrgRej+Azf0U5WDov3PXmHFUBc+t1INnAYhIlpZtCGNBLwCN41b43yO7dPNZu8xWkUFBwQ==", + "version": "5.90.16", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.16.tgz", + "integrity": "sha512-bpMGOmV4OPmif7TNMteU/Ehf/hoC0Kf98PDc0F4BZkFrEapRMEqI/V6YS0lyzwSV6PQpY1y4xxArUIfBW5LVxQ==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.90.15" + "@tanstack/query-core": "5.90.16" }, "funding": { "type": "github", @@ -3198,7 +3088,6 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3366,15 +3255,6 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, - "node_modules/@types/fontkit": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/fontkit/-/fontkit-2.0.8.tgz", - "integrity": "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/geojson": { "version": "7946.0.16", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", @@ -3433,6 +3313,7 @@ "version": "24.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.12.0" @@ -3451,7 +3332,6 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3463,7 +3343,6 @@ "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -3514,20 +3393,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.51.0.tgz", - "integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz", + "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/type-utils": "8.51.0", - "@typescript-eslint/utils": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.53.0", + "@typescript-eslint/type-utils": "8.53.0", + "@typescript-eslint/utils": "8.53.0", + "@typescript-eslint/visitor-keys": "8.53.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.2.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3537,15 +3416,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.51.0", + "@typescript-eslint/parser": "^8.53.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -3553,18 +3432,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.51.0.tgz", - "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz", + "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.53.0", + "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/typescript-estree": "8.53.0", + "@typescript-eslint/visitor-keys": "8.53.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3579,15 +3457,15 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", - "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz", + "integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.51.0", - "@typescript-eslint/types": "^8.51.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.53.0", + "@typescript-eslint/types": "^8.53.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3601,14 +3479,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", - "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", + "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0" + "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/visitor-keys": "8.53.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3619,9 +3497,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", - "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz", + "integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==", "dev": true, "license": "MIT", "engines": { @@ -3636,17 +3514,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.51.0.tgz", - "integrity": "sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz", + "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0", - "@typescript-eslint/utils": "8.51.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.2.0" + "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/typescript-estree": "8.53.0", + "@typescript-eslint/utils": "8.53.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3661,9 +3539,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", - "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", + "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", "dev": true, "license": "MIT", "engines": { @@ -3675,21 +3553,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", - "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", + "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.51.0", - "@typescript-eslint/tsconfig-utils": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@typescript-eslint/project-service": "8.53.0", + "@typescript-eslint/tsconfig-utils": "8.53.0", + "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/visitor-keys": "8.53.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.2.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3703,16 +3581,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", - "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", + "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.53.0", + "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/typescript-estree": "8.53.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3727,13 +3605,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", - "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", + "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/types": "8.53.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3800,7 +3678,6 @@ "integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@testing-library/dom": "^10.4.0", "@testing-library/user-event": "^14.6.1", @@ -4055,7 +3932,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4073,17 +3949,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4417,17 +4282,16 @@ } }, "node_modules/astro": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.6.tgz", - "integrity": "sha512-6mF/YrvwwRxLTu+aMEa5pwzKUNl5ZetWbTyZCs9Um0F12HUmxUiF5UHiZPy4rifzU3gtpM3xP2DfdmkNX9eZRg==", + "version": "5.16.9", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.9.tgz", + "integrity": "sha512-gJvoZv0v8xCcKBcsxz1ZfXqoJ7sJJcyoKP8bUTjkuD4vDShLe0N26em4LQxitVv/2HLOpldQg67bEHB/qGoxJA==", "license": "MIT", - "peer": true, "dependencies": { "@astrojs/compiler": "^2.13.0", "@astrojs/internal-helpers": "0.7.5", "@astrojs/markdown-remark": "6.3.10", "@astrojs/telemetry": "3.3.0", - "@capsizecss/unpack": "^3.0.1", + "@capsizecss/unpack": "^4.0.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "acorn": "^8.15.0", @@ -4437,11 +4301,11 @@ "ci-info": "^4.3.1", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", - "cookie": "^1.0.2", + "cookie": "^1.1.1", "cssesc": "^3.0.0", "debug": "^4.4.3", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.5.0", + "devalue": "^5.6.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", @@ -4449,7 +4313,7 @@ "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", - "fontace": "~0.3.1", + "fontace": "~0.4.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", @@ -4461,20 +4325,20 @@ "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.1", - "package-manager-detector": "^1.5.0", + "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.3", - "shiki": "^3.15.0", - "smol-toml": "^1.5.2", + "shiki": "^3.20.0", + "smol-toml": "^1.6.0", "svgo": "^4.0.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", - "unifont": "~0.6.0", + "unifont": "~0.7.1", "unist-util-visit": "^5.0.0", "unstorage": "^1.17.3", "vfile": "^6.0.3", @@ -4484,7 +4348,7 @@ "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.3", "zod": "^3.25.76", - "zod-to-json-schema": "^3.25.0", + "zod-to-json-schema": "^3.25.1", "zod-to-ts": "^1.2.0" }, "bin": { @@ -4779,26 +4643,6 @@ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -4861,15 +4705,6 @@ "node": ">=8" } }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.1.2" - } - }, "node_modules/browserslist": { "version": "4.25.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", @@ -4890,7 +4725,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -5082,7 +4916,6 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", "license": "MIT", - "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -5241,15 +5074,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -5498,21 +5322,6 @@ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "license": "CC0-1.0" }, - "node_modules/cssstyle": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", - "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@asamuzakjp/css-color": "^3.1.1", - "rrweb-cssom": "^0.8.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -5563,6 +5372,16 @@ "node": ">=12" } }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", @@ -5603,32 +5422,6 @@ "url": "https://github.com/saadeghi/daisyui?sponsor=1" } }, - "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-urls/node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -5706,14 +5499,6 @@ } } }, - "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/decode-named-character-reference": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", @@ -5859,12 +5644,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dfa": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", - "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", - "license": "MIT" - }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -6360,7 +6139,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -6871,6 +6649,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -7097,30 +6876,24 @@ } }, "node_modules/fontace": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.1.tgz", - "integrity": "sha512-9f5g4feWT1jWT8+SbL85aLIRLIXUaDygaM2xPXRmzPYxrOMNok79Lr3FGJoKVNKibE0WCunNiEVG2mwuE+2qEg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.0.tgz", + "integrity": "sha512-moThBCItUe2bjZip5PF/iZClpKHGLwMvR79Kp8XpGRBrvoRSnySN4VcILdv3/MJzbhvUA5WeiUXF5o538m5fvg==", "license": "MIT", "dependencies": { - "@types/fontkit": "^2.0.8", - "fontkit": "^2.0.4" + "fontkitten": "^1.0.0" } }, - "node_modules/fontkit": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", - "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", + "node_modules/fontkitten": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.0.tgz", + "integrity": "sha512-b0RdzQeztiiUFWEDzq6Ka26qkNVNLCehoRtifOIGNbQ4CfxyYRh73fyWaQX/JshPVcueITOEeoSWPy5XQv8FUg==", "license": "MIT", "dependencies": { - "@swc/helpers": "^0.5.12", - "brotli": "^1.3.2", - "clone": "^2.1.2", - "dfa": "^1.2.0", - "fast-deep-equal": "^3.1.3", - "restructure": "^3.0.0", - "tiny-inflate": "^1.0.3", - "unicode-properties": "^1.4.0", - "unicode-trie": "^2.0.0" + "tiny-inflate": "^1.0.3" + }, + "engines": { + "node": ">=20" } }, "node_modules/for-each": { @@ -7695,20 +7468,6 @@ "dev": true, "license": "MIT" }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -7747,50 +7506,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -8191,14 +7906,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -8438,72 +8145,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/jsdom/node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -10229,14 +9870,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/nwsapi": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", - "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/oauth4webapi": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.3.0.tgz", @@ -10611,12 +10244,6 @@ "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", "license": "MIT" }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "license": "MIT" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10898,7 +10525,6 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -10929,7 +10555,6 @@ "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -10946,7 +10571,6 @@ "integrity": "sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@astrojs/compiler": "^2.9.1", "prettier": "^3.0.0", @@ -11106,7 +10730,6 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -11186,7 +10809,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -11199,7 +10821,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -11565,12 +11186,6 @@ "node": ">=4" } }, - "node_modules/restructure": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", - "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", - "license": "MIT" - }, "node_modules/retext": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", @@ -11655,7 +11270,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", "integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.6" }, @@ -11689,14 +11303,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11812,14 +11418,6 @@ "node": ">=10" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/sass-formatter": { "version": "0.7.9", "resolved": "https://registry.npmjs.org/sass-formatter/-/sass-formatter-0.7.9.tgz", @@ -11836,20 +11434,6 @@ "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", "license": "BlueOak-1.0.0" }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -12197,9 +11781,9 @@ } }, "node_modules/smol-toml": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.5.2.tgz", - "integrity": "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", + "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -12570,14 +12154,6 @@ "node": ">=16" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/synckit": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", @@ -12613,8 +12189,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tapable": { "version": "2.3.0", @@ -12702,28 +12277,6 @@ "node": ">=14.0.0" } }, - "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tldts-core": "^6.1.86" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", @@ -12811,20 +12364,6 @@ "dev": true, "license": "MIT" }, - "node_modules/tr46": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", - "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -12855,9 +12394,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.3.0.tgz", - "integrity": "sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -13034,7 +12573,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13054,16 +12592,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.51.0.tgz", - "integrity": "sha512-jh8ZuM5oEh2PSdyQG9YAEM1TCGuWenLSuSUhf/irbVUNW9O5FhbFVONviN2TgMTBnUmyHv7E56rYnfLZK6TkiA==", + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.53.0.tgz", + "integrity": "sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.51.0", - "@typescript-eslint/parser": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0", - "@typescript-eslint/utils": "8.51.0" + "@typescript-eslint/eslint-plugin": "8.53.0", + "@typescript-eslint/parser": "8.53.0", + "@typescript-eslint/typescript-estree": "8.53.0", + "@typescript-eslint/utils": "8.53.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -13118,28 +12656,9 @@ "version": "7.12.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", + "devOptional": true, "license": "MIT" }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "license": "MIT", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -13160,14 +12679,14 @@ } }, "node_modules/unifont": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.6.0.tgz", - "integrity": "sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.1.tgz", + "integrity": "sha512-0lg9M1cMYvXof8//wZBq6EDEfbwv4++t7+dYpXeS2ypaLuZJmUFYEwTm412/1ED/Wfo/wyzSu6kNZEr9hgRNfg==", "license": "MIT", "dependencies": { - "css-tree": "^3.0.0", - "ofetch": "^1.4.1", - "ohash": "^2.0.0" + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" } }, "node_modules/unist-util-find-after": { @@ -13419,7 +12938,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -13551,7 +13069,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -13903,20 +13420,6 @@ "dev": true, "license": "MIT" }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", @@ -13927,46 +13430,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14117,7 +13580,6 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", @@ -14228,25 +13690,6 @@ } } }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/xxhash-wasm": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", @@ -14315,7 +13758,6 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -14489,15 +13931,14 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", "license": "ISC", "peerDependencies": { "zod": "^3.25 || ^4" diff --git a/website/package.json b/website/package.json index 15fe68425..1421e1070 100644 --- a/website/package.json +++ b/website/package.json @@ -27,8 +27,8 @@ "@astrojs/node": "^9.5.1", "@auth/core": "^0.37.4", "@genspectrum/dashboard-components": "^1.12.0", - "@tanstack/react-query": "^5.90.15", - "astro": "^5.16.6", + "@tanstack/react-query": "^5.90.16", + "astro": "^5.16.9", "auth-astro": "^4.2.0", "axios": "^1.13.2", "cookie": "^1.1.1", @@ -63,8 +63,8 @@ "@types/react-dom": "^18.3.1", "@types/react-katex": "^3.0.4", "@types/topojson-specification": "^1.0.5", - "@typescript-eslint/eslint-plugin": "^8.51.0", - "@typescript-eslint/parser": "^8.51.0", + "@typescript-eslint/eslint-plugin": "^8.53.0", + "@typescript-eslint/parser": "^8.53.0", "@vitest/browser": "^3.2.4", "astro-eslint-parser": "^1.2.2", "daisyui": "^5.5.14", @@ -81,7 +81,7 @@ "prettier-plugin-tailwindcss": "^0.7.2", "tailwindcss": "^4.0.9", "typescript": "^5.9.3", - "typescript-eslint": "^8.51.0", + "typescript-eslint": "^8.53.0", "vitest": "^3.2.4", "vitest-browser-react": "^1.0.1", "zod": "^3.25.74" From d87f1520673ece0d5a54674229633cfe05f9d152 Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Tue, 13 Jan 2026 08:44:24 +0000 Subject: [PATCH 24/26] feat(website): connect real RSV-A backend (#991) --- website/src/types/wastewaterConfig.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/src/types/wastewaterConfig.ts b/website/src/types/wastewaterConfig.ts index 1c95f9cbd..1cbc8f9b4 100644 --- a/website/src/types/wastewaterConfig.ts +++ b/website/src/types/wastewaterConfig.ts @@ -28,7 +28,7 @@ export const wastewaterOrganismConfigs: Record Date: Wed, 14 Jan 2026 09:41:53 +0100 Subject: [PATCH 25/26] feat(website): don't reload the whole page when applying the filters (#985) * 984 wip * 984 wip * 984 wip * 984 wip * 984 fix test * 984 fix test * 984 fix lints * 984 rename function * 984 fix map * 984 set type button * 984 fix state update * 984 docstring --- .../genspectrum/GsSequencesByLocation.tsx | 2 + .../ApplyFilterButton.browser.spec.tsx | 77 ++++++++++++------- .../pageStateSelectors/ApplyFilterButton.tsx | 12 ++- .../CompareSideBySidePageStateSelector.tsx | 43 ++++++----- .../CompareVariantsPageStateSelector.tsx | 42 +++++----- ...CompareVariantsToBaselineStateSelector.tsx | 46 +++++------ .../SequencingEffortsPageStateSelector.tsx | 39 +++++----- ...eVariantPageStateSelector.browser.spec.tsx | 43 +++++++---- .../SingleVariantPageStateSelector.tsx | 39 +++++----- .../wasap/WasapPageStateSelector.tsx | 10 ++- .../analyzeSingleVariant/CollectionsList.tsx | 61 ++++++++------- .../CovidSingleVariantDataDisplay.tsx | 21 ++--- .../CovidSingleVariantReactPage.tsx | 18 ++--- ...GenericAnalyseSingleVariantDataDisplay.tsx | 18 ++--- .../GenericAnalyseSingleVariantReactPage.tsx | 15 ++-- .../analyzeSingleVariant/QuickstartLinks.tsx | 23 +++--- .../GenericCompareSideBySideDataDisplay.tsx | 22 ++---- .../GenericCompareSideBySideReactPage.tsx | 12 +-- .../GenericCompareToBaselineDataDisplay.tsx | 22 ++---- .../GenericCompareToBaselineReactPage.tsx | 17 ++-- .../GenericCompareVariantsDataDisplay.tsx | 21 ++--- .../GenericCompareVariantsReactPage.tsx | 17 ++-- .../GenericSequencingEffortsReactPage.tsx | 9 ++- website/src/components/views/usePageState.ts | 34 ++++++++ .../src/components/views/wasap/Wasap.astro | 4 +- .../src/components/views/wasap/WasapPage.tsx | 14 ++-- website/src/views/OrganismConstants.ts | 1 + .../CompareSideBySidePageStateHandler.spec.ts | 1 + .../CompareToBaselinePageStateHandler.spec.ts | 1 + .../CompareVariantsPageStateHandler.spec.ts | 1 + .../SingleVariantPageStateHandler.spec.ts | 1 + 31 files changed, 367 insertions(+), 319 deletions(-) create mode 100644 website/src/components/views/usePageState.ts diff --git a/website/src/components/genspectrum/GsSequencesByLocation.tsx b/website/src/components/genspectrum/GsSequencesByLocation.tsx index 54c51e378..9848e7bed 100644 --- a/website/src/components/genspectrum/GsSequencesByLocation.tsx +++ b/website/src/components/genspectrum/GsSequencesByLocation.tsx @@ -28,6 +28,7 @@ export const GsSequencesByLocation: FC = ({ {mapData === undefined ? ( = ({ /> ) : ( { const handler = new DummyPageStateHandler(); - it('should render enabled link for short URL', () => { + it('should render enabled link for short URL', async () => { const shortState: DummyPageState = { data: 'short' }; - const { getByRole, container } = render( - , + const { result: state } = renderHook(() => useState({ data: 'initial' })); + + const { getByRole } = render( + , ); - const link = getByRole('button'); - expect(link.element()).toBeInTheDocument(); - expect(link.element()).toHaveAttribute('href', '/test?data=short'); - expect(container.textContent).not.toMatch(urlTooLongMessage); + await clickApply(getByRole); + + expect(state.current[0].data).toEqual('short'); }); - it('should render disabled span and error message for long URL', () => { + it('should render disabled span and error message for long URL', async () => { const longData = 'x'.repeat(2000); const longState: DummyPageState = { data: longData }; + const { result: state } = renderHook(() => useState({ data: 'initial' })); + const { getByRole, container } = render( - , + , ); - const button = getByRole('button'); - expect(button.element()).not.toHaveAttribute('href'); expect(container.textContent).toMatch(urlTooLongMessage); + expect(getByRole('button', { name: 'Apply filters' }).element()).not.toHaveAttribute('onClick'); + + await clickApply(getByRole); + expect(state.current[0].data).toEqual('initial'); }); - it('should update when state changes from short to long', () => { + it('should update when state changes from short to long', async () => { const shortState: DummyPageState = { data: 'short' }; + const { result: state } = renderHook(() => useState({ data: 'initial' })); + const { getByRole, container, rerender } = render( - , + , ); - const button = getByRole('button'); - expect(button.element()).toHaveAttribute('href', '/test?data=short'); + await clickApply(getByRole); + expect(state.current[0].data).toEqual('short'); expect(container.textContent).not.toMatch(urlTooLongMessage); const longData = 'x'.repeat(2000); const longState: DummyPageState = { data: longData }; - rerender(); + rerender( + , + ); - const updatedButton = getByRole('button'); - expect(updatedButton.element()).not.toHaveAttribute('href'); expect(container.textContent).toMatch(urlTooLongMessage); + expect(getByRole('button', { name: 'Apply filters' }).element()).not.toHaveAttribute('onClick'); + + await clickApply(getByRole); + expect(state.current[0].data).toEqual('short'); }); - it('should update when state changes from long to short', () => { + it('should update when state changes from long to short', async () => { const longData = 'x'.repeat(2000); const longState: DummyPageState = { data: longData }; + const { result: state } = renderHook(() => useState({ data: 'initial' })); + const { getByRole, container, rerender } = render( - , + , ); - const button = getByRole('button'); - expect(button.element()).not.toHaveAttribute('href'); + expect(getByRole('button', { name: 'Apply filters' }).element()).not.toHaveAttribute('onClick'); expect(container.textContent).toMatch(urlTooLongMessage); + await clickApply(getByRole); + expect(state.current[0].data).toEqual('initial'); const shortState: DummyPageState = { data: 'short' }; - rerender(); + rerender( + , + ); - const updatedButton = getByRole('button'); - expect(updatedButton.element()).toHaveAttribute('href', '/test?data=short'); expect(container.textContent).not.toMatch(urlTooLongMessage); + await clickApply(getByRole); + expect(state.current[0].data).toEqual('short'); }); }); + +async function clickApply(getByRole: RenderResult['getByRole']) { + await act(async () => { + await getByRole('button', { name: 'Apply filters' }).click(); + }); +} diff --git a/website/src/components/pageStateSelectors/ApplyFilterButton.tsx b/website/src/components/pageStateSelectors/ApplyFilterButton.tsx index d01b61b8f..d3d7b5736 100644 --- a/website/src/components/pageStateSelectors/ApplyFilterButton.tsx +++ b/website/src/components/pageStateSelectors/ApplyFilterButton.tsx @@ -1,3 +1,5 @@ +import type { Dispatch, SetStateAction } from 'react'; + import type { WithClassName } from '../../types/WithClassName.ts'; import type { PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler.ts'; @@ -8,15 +10,21 @@ const MAX_URL_LENGTH = 2000; export function ApplyFilterButton({ pageStateHandler, newPageState, + setPageState, className = '', }: WithClassName<{ pageStateHandler: PageStateHandler; newPageState: PageState; + setPageState: Dispatch>; }>) { const url = pageStateHandler.toUrl(newPageState); const fullUrl = `${window.location.origin}${url}`; const urlTooLong = fullUrl.length > MAX_URL_LENGTH; + const applyFilters = () => { + setPageState(newPageState); + }; + return urlTooLong ? ( <> @@ -30,8 +38,8 @@ export function ApplyFilterButton({
) : ( - + ); } diff --git a/website/src/components/pageStateSelectors/CompareSideBySidePageStateSelector.tsx b/website/src/components/pageStateSelectors/CompareSideBySidePageStateSelector.tsx index a71cfc05e..014046f0e 100644 --- a/website/src/components/pageStateSelectors/CompareSideBySidePageStateSelector.tsx +++ b/website/src/components/pageStateSelectors/CompareSideBySidePageStateSelector.tsx @@ -1,37 +1,38 @@ -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react'; import { ApplyFilterButton } from './ApplyFilterButton.tsx'; import { BaselineSelector } from './BaselineSelector.tsx'; import { SelectorHeadline } from './SelectorHeadline.tsx'; import { makeVariantFilterConfig, VariantSelector } from './VariantSelector.tsx'; -import type { OrganismsConfig } from '../../config.ts'; import { Inset } from '../../styles/Inset.tsx'; +import { BaseView } from '../../views/BaseView.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants.ts'; import type { CompareSideBySideData } from '../../views/View.ts'; -import { type OrganismViewKey, Routing } from '../../views/routing.ts'; -import type { compareSideBySideViewKey } from '../../views/viewKeys.ts'; +import { CompareSideBySideStateHandler } from '../../views/pageStateHandlers/CompareSideBySidePageStateHandler.ts'; export function CompareSideBySidePageStateSelector({ + view, filterId, - initialPageState, - organismViewKey, - organismsConfig, + pageState, + setPageState, enableAdvancedQueryFilter, }: { + view: BaseView; filterId: number; - initialPageState: CompareSideBySideData; - organismViewKey: OrganismViewKey & `${string}.${typeof compareSideBySideViewKey}`; - organismsConfig: OrganismsConfig; + pageState: CompareSideBySideData; + setPageState: Dispatch>; enableAdvancedQueryFilter: boolean; }) { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); + const [draftPageState, setDraftPageState] = useState(pageState); + useEffect(() => setDraftPageState(pageState), [pageState]); + const variantFilterConfig = useMemo( () => makeVariantFilterConfig(view.organismConstants), [view.organismConstants], ); - const [pageState, setPageState] = useState(initialPageState); const { filterOfCurrentId, currentLapisFilter } = useMemo(() => { - const filterOfCurrentId = pageState.filters.get(filterId) ?? { + const filterOfCurrentId = draftPageState.filters.get(filterId) ?? { datasetFilter: { locationFilters: {}, dateFilters: {}, @@ -47,7 +48,7 @@ export function CompareSideBySidePageStateSelector({ filterOfCurrentId.variantFilter, ), }; - }, [pageState, filterId, view.pageStateHandler]); + }, [draftPageState, filterId, view.pageStateHandler]); return (
@@ -60,8 +61,8 @@ export function CompareSideBySidePageStateSelector({ lapisFilter={currentLapisFilter} datasetFilter={filterOfCurrentId.datasetFilter} setDatasetFilter={(newDatasetFilter) => { - setPageState((previousState) => { - const updatedFilters = new Map(initialPageState.filters); + setDraftPageState((previousState) => { + const updatedFilters = new Map(previousState.filters); updatedFilters.set(filterId, { ...filterOfCurrentId, datasetFilter: newDatasetFilter, @@ -78,8 +79,8 @@ export function CompareSideBySidePageStateSelector({ { - setPageState((previousState) => { - const updatedFilters = new Map(initialPageState.filters); + setDraftPageState((previousState) => { + const updatedFilters = new Map(previousState.filters); updatedFilters.set(filterId, { ...filterOfCurrentId, variantFilter: newVariantFilter, @@ -96,7 +97,11 @@ export function CompareSideBySidePageStateSelector({
- +
); diff --git a/website/src/components/pageStateSelectors/CompareVariantsPageStateSelector.tsx b/website/src/components/pageStateSelectors/CompareVariantsPageStateSelector.tsx index cbfd106aa..0d03db9c8 100644 --- a/website/src/components/pageStateSelectors/CompareVariantsPageStateSelector.tsx +++ b/website/src/components/pageStateSelectors/CompareVariantsPageStateSelector.tsx @@ -1,39 +1,38 @@ -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react'; import { ApplyFilterButton } from './ApplyFilterButton.tsx'; import { BaselineSelector } from './BaselineSelector.tsx'; import { SelectorHeadline } from './SelectorHeadline.tsx'; import { makeVariantFilterConfig } from './VariantSelector.tsx'; import { VariantsSelector } from './VariantsSelector.tsx'; -import { type OrganismsConfig } from '../../config.ts'; import { Inset } from '../../styles/Inset.tsx'; +import { GenericCompareVariantsView } from '../../views/BaseView.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants.ts'; import type { CompareVariantsData, Id, VariantFilter } from '../../views/View.ts'; -import { type OrganismViewKey, Routing } from '../../views/routing.ts'; -import type { compareVariantsViewKey } from '../../views/viewKeys.ts'; export function CompareVariantsPageStateSelector({ - organismViewKey, - organismsConfig, - initialPageState, + view, + pageState, + setPageState, enableAdvancedQueryFilter, }: { - organismViewKey: OrganismViewKey & `${string}.${typeof compareVariantsViewKey}`; - organismsConfig: OrganismsConfig; - initialPageState: CompareVariantsData; + view: GenericCompareVariantsView; + pageState: CompareVariantsData; + setPageState: Dispatch>; enableAdvancedQueryFilter: boolean; }) { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); - const [pageState, setPageState] = useState(initialPageState); + const [draftPageState, setDraftPageState] = useState(pageState); + useEffect(() => setDraftPageState(pageState), [pageState]); const variantFilterConfigs = useMemo(() => { return new Map( - pageState.variants.entries().map(([id]) => [id, makeVariantFilterConfig(view.organismConstants)]), + draftPageState.variants.entries().map(([id]) => [id, makeVariantFilterConfig(view.organismConstants)]), ); - }, [pageState.variants, view.organismConstants]); + }, [draftPageState.variants, view.organismConstants]); const currentLapisFilter = useMemo(() => { - return view.pageStateHandler.datasetFilterToLapisFilter(pageState.datasetFilter); - }, [pageState, view.pageStateHandler]); + return view.pageStateHandler.datasetFilterToLapisFilter(draftPageState.datasetFilter); + }, [draftPageState, view.pageStateHandler]); return (
@@ -43,9 +42,9 @@ export function CompareVariantsPageStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, datasetFilter: newDatasetFilter, })); @@ -58,10 +57,10 @@ export function CompareVariantsPageStateSelector({ Variant Filters ) => { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, variants: newVariantFilters, })); @@ -75,7 +74,8 @@ export function CompareVariantsPageStateSelector({
diff --git a/website/src/components/pageStateSelectors/CompareVariantsToBaselineStateSelector.tsx b/website/src/components/pageStateSelectors/CompareVariantsToBaselineStateSelector.tsx index 5aa4cb498..d57cb6bc5 100644 --- a/website/src/components/pageStateSelectors/CompareVariantsToBaselineStateSelector.tsx +++ b/website/src/components/pageStateSelectors/CompareVariantsToBaselineStateSelector.tsx @@ -1,29 +1,28 @@ -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react'; import { ApplyFilterButton } from './ApplyFilterButton.tsx'; import { BaselineSelector } from './BaselineSelector.tsx'; import { SelectorHeadline } from './SelectorHeadline.tsx'; import { makeVariantFilterConfig, VariantSelector } from './VariantSelector.tsx'; import { VariantsSelector } from './VariantsSelector.tsx'; -import { type OrganismsConfig } from '../../config.ts'; import { Inset } from '../../styles/Inset.tsx'; +import { GenericCompareToBaselineView } from '../../views/BaseView.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants.ts'; import type { CompareToBaselineData, Id, VariantFilter } from '../../views/View.ts'; -import { type OrganismViewKey, Routing } from '../../views/routing.ts'; -import { type compareToBaselineViewKey } from '../../views/viewKeys.ts'; export function CompareVariantsToBaselineStateSelector({ - organismViewKey, - organismsConfig, - initialPageState, + view, + pageState, + setPageState, enableAdvancedQueryFilter, }: { - organismViewKey: OrganismViewKey & `${string}.${typeof compareToBaselineViewKey}`; - organismsConfig: OrganismsConfig; - initialPageState: CompareToBaselineData; + view: GenericCompareToBaselineView; + pageState: CompareToBaselineData; + setPageState: Dispatch>; enableAdvancedQueryFilter: boolean; }) { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); - const [pageState, setPageState] = useState(initialPageState); + const [draftPageState, setDraftPageState] = useState(pageState); + useEffect(() => setDraftPageState(pageState), [pageState]); const variantFilterConfig = useMemo( () => makeVariantFilterConfig(view.organismConstants), @@ -31,12 +30,12 @@ export function CompareVariantsToBaselineStateSelector({ ); const variantFilterConfigs = useMemo(() => { - return new Map(pageState.variants.entries().map(([id]) => [id, { ...variantFilterConfig }])); - }, [pageState.variants, variantFilterConfig]); + return new Map(draftPageState.variants.entries().map(([id]) => [id, { ...variantFilterConfig }])); + }, [draftPageState.variants, variantFilterConfig]); const currentLapisFilter = useMemo(() => { - return view.pageStateHandler.baselineFilterToLapisFilter(pageState); - }, [pageState, view.pageStateHandler]); + return view.pageStateHandler.baselineFilterToLapisFilter(draftPageState); + }, [draftPageState, view.pageStateHandler]); return (
@@ -47,9 +46,9 @@ export function CompareVariantsToBaselineStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, datasetFilter: newDatasetFilter, })); @@ -64,13 +63,13 @@ export function CompareVariantsToBaselineStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, baselineFilter: newVariantFilter, })); }} variantFilterConfig={variantFilterConfig} - variantFilter={pageState.baselineFilter} + variantFilter={draftPageState.baselineFilter} lapisFilter={currentLapisFilter} enableAdvancedQueryFilter={enableAdvancedQueryFilter} /> @@ -81,10 +80,10 @@ export function CompareVariantsToBaselineStateSelector({ Variant Filters ) => { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, variants: newVariantFilters, })); @@ -98,7 +97,8 @@ export function CompareVariantsToBaselineStateSelector({
diff --git a/website/src/components/pageStateSelectors/SequencingEffortsPageStateSelector.tsx b/website/src/components/pageStateSelectors/SequencingEffortsPageStateSelector.tsx index ee58b8bca..e095837a5 100644 --- a/website/src/components/pageStateSelectors/SequencingEffortsPageStateSelector.tsx +++ b/website/src/components/pageStateSelectors/SequencingEffortsPageStateSelector.tsx @@ -1,33 +1,31 @@ -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react'; import { ApplyFilterButton } from './ApplyFilterButton.tsx'; import { BaselineSelector } from './BaselineSelector.tsx'; import { LineageFilterInput } from './LineageFilterInput.tsx'; import { SelectorHeadline } from './SelectorHeadline.tsx'; -import { type OrganismsConfig } from '../../config.ts'; import { Inset } from '../../styles/Inset.tsx'; +import { GenericSequencingEffortsView } from '../../views/BaseView.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants.ts'; import type { DatasetAndVariantData } from '../../views/View.ts'; -import { type OrganismViewKey, Routing } from '../../views/routing.ts'; -import type { sequencingEffortsViewKey } from '../../views/viewKeys.ts'; export function SequencingEffortsPageStateSelector({ - organismViewKey, - organismsConfig, - initialPageState, + view, + pageState, + setPageState, enableAdvancedQueryFilter, }: { - organismViewKey: OrganismViewKey & `${string}.${typeof sequencingEffortsViewKey}`; - organismsConfig: OrganismsConfig; - initialPageState: DatasetAndVariantData; + view: GenericSequencingEffortsView; + pageState: DatasetAndVariantData; + setPageState: Dispatch>; enableAdvancedQueryFilter: boolean; }) { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); - - const [pageState, setPageState] = useState(initialPageState); + const [draftPageState, setDraftPageState] = useState(pageState); + useEffect(() => setDraftPageState(pageState), [pageState]); const currentLapisFilter = useMemo(() => { - return view.pageStateHandler.toLapisFilter(pageState); - }, [pageState, view.pageStateHandler]); + return view.pageStateHandler.toLapisFilter(draftPageState); + }, [draftPageState, view.pageStateHandler]); return (
@@ -37,9 +35,9 @@ export function SequencingEffortsPageStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, datasetFilter: newDatasetFilter, })); @@ -50,7 +48,7 @@ export function SequencingEffortsPageStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, variantFilter: { lineages: { @@ -62,7 +60,7 @@ export function SequencingEffortsPageStateSelector({ }} key={lineageFilterConfig.lapisField} lapisFilter={currentLapisFilter} - value={pageState.variantFilter.lineages?.[lineageFilterConfig.lapisField]} + value={draftPageState.variantFilter.lineages?.[lineageFilterConfig.lapisField]} /> ))} @@ -71,7 +69,8 @@ export function SequencingEffortsPageStateSelector({
diff --git a/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.browser.spec.tsx b/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.browser.spec.tsx index b3e4d6b0f..ad9f50fa8 100644 --- a/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.browser.spec.tsx +++ b/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.browser.spec.tsx @@ -1,40 +1,51 @@ +import { act } from '@testing-library/react'; +import { useState } from 'react'; import { describe, expect } from 'vitest'; -import { render } from 'vitest-browser-react'; +import { render, renderHook } from 'vitest-browser-react'; import { SingleVariantPageStateSelector } from './SingleVariantPageStateSelector.tsx'; import { DUMMY_LAPIS_URL, testOrganismsConfig } from '../../../routeMocker.ts'; import { it } from '../../../test-extend'; +import type { CovidVariantData } from '../../views/covid.ts'; +import { Routing } from '../../views/routing.ts'; describe('SingleVariantPageStateSelector', () => { - it('should remember the covid collection id', ({ routeMockers }) => { + it('should remember the covid collection id', async ({ routeMockers }) => { routeMockers.lapis.mockPostAggregated({}, { data: [] }); routeMockers.lapis.mockReferenceGenome({ nucleotideSequences: [{ name: 'main', sequence: 'ATGC' }], genes: [], }); + routeMockers.lapis.mockLineageDefinition('nextcladePangoLineage', {}); - const initialPageState = { - datasetFilter: { - locationFilters: {}, - dateFilters: {}, - textFilters: {}, - numberFilters: {}, - }, - variantFilter: {}, - collectionId: 5, - }; + const { result } = renderHook(() => + useState({ + datasetFilter: { + locationFilters: {}, + dateFilters: {}, + textFilters: {}, + numberFilters: {}, + }, + variantFilter: {}, + collectionId: 5, + }), + ); const { getByRole } = render( , ); - expect(getByRole('button').element()).toHaveAttribute('href', expect.stringContaining('collectionId=5')); + await act(async () => { + await getByRole('button', { name: 'Apply filters' }).click(); + }); + + expect(result.current[0].collectionId).equals(5); }); }); diff --git a/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.tsx b/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.tsx index d9a75c966..cc40f5e0a 100644 --- a/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.tsx +++ b/website/src/components/pageStateSelectors/SingleVariantPageStateSelector.tsx @@ -1,38 +1,38 @@ -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react'; import { ApplyFilterButton } from './ApplyFilterButton.tsx'; import { BaselineSelector } from './BaselineSelector.tsx'; import { SelectorHeadline } from './SelectorHeadline.tsx'; import { makeVariantFilterConfig, VariantSelector } from './VariantSelector.tsx'; -import { type OrganismsConfig } from '../../config.ts'; import { Inset } from '../../styles/Inset.tsx'; +import type { GenericSingleVariantView } from '../../views/BaseView.ts'; +import type { OrganismConstants } from '../../views/OrganismConstants.ts'; import { type DatasetAndVariantData } from '../../views/View.ts'; -import { type OrganismViewKey, Routing } from '../../views/routing.ts'; -import type { singleVariantViewKey } from '../../views/viewKeys.ts'; export function SingleVariantPageStateSelector({ - organismViewKey, - organismsConfig, - initialPageState, + view, + pageState, + setPageState, enableAdvancedQueryFilter, }: { - organismViewKey: OrganismViewKey & `${string}.${typeof singleVariantViewKey}`; - organismsConfig: OrganismsConfig; - initialPageState: DatasetAndVariantData; + view: GenericSingleVariantView; + pageState: DatasetAndVariantData; + setPageState: Dispatch>; enableAdvancedQueryFilter: boolean; }) { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); const variantFilterConfig = useMemo( () => makeVariantFilterConfig(view.organismConstants), [view.organismConstants], ); - const [pageState, setPageState] = useState(initialPageState); + + const [draftPageState, setDraftPageState] = useState(pageState); + useEffect(() => setDraftPageState(pageState), [pageState]); const baselineFilterConfigs = view.organismConstants.baselineFilterConfigs; const currentLapisFilter = useMemo(() => { - return view.pageStateHandler.toLapisFilter(pageState); - }, [pageState, view.pageStateHandler]); + return view.pageStateHandler.toLapisFilter(draftPageState); + }, [draftPageState, view.pageStateHandler]); return (
@@ -42,9 +42,9 @@ export function SingleVariantPageStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, datasetFilter: newDatasetFilter, })); @@ -59,13 +59,13 @@ export function SingleVariantPageStateSelector({ { - setPageState((previousState) => ({ + setDraftPageState((previousState) => ({ ...previousState, variantFilter: newVariantFilter, })); }} variantFilterConfig={variantFilterConfig} - variantFilter={pageState.variantFilter} + variantFilter={draftPageState.variantFilter} lapisFilter={currentLapisFilter} enableAdvancedQueryFilter={enableAdvancedQueryFilter} /> @@ -76,7 +76,8 @@ export function SingleVariantPageStateSelector({
diff --git a/website/src/components/pageStateSelectors/wasap/WasapPageStateSelector.tsx b/website/src/components/pageStateSelectors/wasap/WasapPageStateSelector.tsx index 811c21333..62d18f6de 100644 --- a/website/src/components/pageStateSelectors/wasap/WasapPageStateSelector.tsx +++ b/website/src/components/pageStateSelectors/wasap/WasapPageStateSelector.tsx @@ -1,5 +1,5 @@ import { useQuery } from '@tanstack/react-query'; -import { useState } from 'react'; +import { type Dispatch, type SetStateAction, useState } from 'react'; import { ApplyFilterButton } from '../ApplyFilterButton'; import { DynamicDateFilter } from '../DynamicDateFilter'; @@ -34,11 +34,13 @@ export function WasapPageStateSelector({ pageStateHandler, initialBaseFilterState, initialAnalysisFilterState, + setPageState, }: { config: WasapPageConfig; pageStateHandler: PageStateHandler; initialBaseFilterState: WasapBaseFilter; initialAnalysisFilterState: WasapAnalysisFilter; + setPageState: Dispatch>; }) { const [baseFilterState, setBaseFilterState] = useState(initialBaseFilterState); @@ -201,7 +203,11 @@ export function WasapPageStateSelector({ } })()} - + ); } diff --git a/website/src/components/views/analyzeSingleVariant/CollectionsList.tsx b/website/src/components/views/analyzeSingleVariant/CollectionsList.tsx index 0af04924c..d20b9b051 100644 --- a/website/src/components/views/analyzeSingleVariant/CollectionsList.tsx +++ b/website/src/components/views/analyzeSingleVariant/CollectionsList.tsx @@ -1,15 +1,12 @@ import { useQuery } from '@tanstack/react-query'; -import { useMemo, useState } from 'react'; +import { type Dispatch, type SetStateAction, useState } from 'react'; import { z } from 'zod'; import { getClientLogger } from '../../../clientLogger.ts'; -import type { OrganismsConfig } from '../../../config.ts'; import { type CovidVariantData } from '../../../views/covid.ts'; -import { Routing } from '../../../views/routing.ts'; import { useErrorToast } from '../../ErrorReportInstruction.tsx'; -import { withQueryProvider } from '../../subscriptions/backendApi/withQueryProvider.tsx'; -export const collectionVariantClassName = 'border bg-white px-4 py-2 hover:bg-cyan border-gray-200'; +export const collectionVariantClassName = 'border bg-white px-4 py-2 hover:bg-cyan border-gray-200 cursor-pointer'; type CollectionVariant = { name: string; @@ -25,12 +22,11 @@ type Collection = { type CollectionsListProps = { initialCollectionId?: number; - organismsConfig: OrganismsConfig; + pageState: CovidVariantData; + setPageState: Dispatch>; }; -export const CollectionsList = withQueryProvider(CollectionsListInner); - -function CollectionsListInner({ initialCollectionId, organismsConfig }: CollectionsListProps) { +export function CollectionsList({ initialCollectionId, pageState, setPageState }: CollectionsListProps) { const [selectedCollectionId, setSelectedCollectionId] = useState(initialCollectionId ?? 1); const query = useQuery({ @@ -56,7 +52,8 @@ function CollectionsListInner({ initialCollectionId, organismsConfig }: Collecti /> c.id === selectedCollectionId) ?? query.data[0]} - organismsConfig={organismsConfig} + pageState={pageState} + setPageState={setPageState} /> ); @@ -96,10 +93,11 @@ const querySchema = z.object({ type CollectionVariantListProps = { collection: Collection; - organismsConfig: OrganismsConfig; + pageState: CovidVariantData; + setPageState: Dispatch>; }; -function CollectionVariantList({ collection, organismsConfig }: CollectionVariantListProps) { +function CollectionVariantList({ collection, pageState, setPageState }: CollectionVariantListProps) { const variants = collection.variants; return ( @@ -108,8 +106,9 @@ function CollectionVariantList({ collection, organismsConfig }: CollectionVarian ))} @@ -118,32 +117,37 @@ function CollectionVariantList({ collection, organismsConfig }: CollectionVarian type VariantLinkProps = { variant: CollectionVariant; - organismsConfig: OrganismsConfig; collectionId: number; + pageState: CovidVariantData; + setPageState: Dispatch>; }; -function VariantLink({ variant, organismsConfig, collectionId }: VariantLinkProps) { - const variantLink = useVariantLink(organismsConfig, collectionId, variant); +function VariantLink({ variant, collectionId, pageState, setPageState }: VariantLinkProps) { + const newPageState = useVariantLinkPageState(pageState, collectionId, variant); + + const applyFilters = () => { + if (newPageState === undefined) { + return; + } + setPageState(newPageState); + }; return ( - + ); } const logger = getClientLogger('CollectionList'); -function useVariantLink(organismsConfig: OrganismsConfig, collectionId: number, variant: CollectionVariant) { - const routing = useMemo(() => new Routing(organismsConfig), [organismsConfig]); - +function useVariantLinkPageState( + currentPageState: CovidVariantData, + collectionId: number, + variant: CollectionVariant, +): CovidVariantData | undefined { const { showErrorToast } = useErrorToast(logger); - const currentPageState = routing - .getOrganismView('covid.singleVariantView') - .pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); - let newPageState: CovidVariantData; - const queryParseResult = querySchema.safeParse(JSON.parse(variant.query)); if (!queryParseResult.success) { @@ -158,7 +162,7 @@ function useVariantLink(organismsConfig: OrganismsConfig, collectionId: number, const query = queryParseResult.data; if (query.variantQuery !== undefined) { - newPageState = { + return { ...currentPageState, collectionId: collectionId, variantFilter: { @@ -168,7 +172,7 @@ function useVariantLink(organismsConfig: OrganismsConfig, collectionId: number, }, }; } else { - newPageState = { + return { ...currentPageState, collectionId: collectionId, variantFilter: { @@ -184,5 +188,4 @@ function useVariantLink(organismsConfig: OrganismsConfig, collectionId: number, }, }; } - return routing.getOrganismView('covid.singleVariantView').pageStateHandler.toUrl(newPageState); } diff --git a/website/src/components/views/analyzeSingleVariant/CovidSingleVariantDataDisplay.tsx b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantDataDisplay.tsx index b07241b50..8ee878318 100644 --- a/website/src/components/views/analyzeSingleVariant/CovidSingleVariantDataDisplay.tsx +++ b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantDataDisplay.tsx @@ -1,17 +1,13 @@ import { views } from '@genspectrum/dashboard-components/util'; -import { type FC, useMemo } from 'react'; +import { type Dispatch, type FC, type SetStateAction } from 'react'; import { CollectionsList } from './CollectionsList.tsx'; import { SelectVariant } from './SelectVariant.tsx'; -import type { OrganismsConfig } from '../../../config.ts'; -import type { Organisms } from '../../../types/Organism.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; import { hasOnlyUndefinedValues } from '../../../util/hasOnlyUndefinedValues.ts'; -import type { CovidVariantData } from '../../../views/covid.ts'; +import { CovidAnalyzeSingleVariantView, type CovidVariantData } from '../../../views/covid.ts'; import { getLocationSubdivision } from '../../../views/locationHelpers.ts'; import { locationFieldsToFilterIdentifier } from '../../../views/pageStateHandlers/locationFilterFromToUrl.ts'; -import { Routing } from '../../../views/routing.ts'; -import type { singleVariantViewKey } from '../../../views/viewKeys.ts'; import { ComponentsGrid } from '../../ComponentsGrid.tsx'; import { GsAggregate } from '../../genspectrum/GsAggregate.tsx'; import { GsMutations } from '../../genspectrum/GsMutations.tsx'; @@ -21,18 +17,16 @@ import { GsRelativeGrowthAdvantage } from '../../genspectrum/GsRelativeGrowthAdv import { GsStatistics } from '../../genspectrum/GsStatistics.tsx'; export type CovidSingleVariantDataDisplayProps = { - organismViewKey: `${typeof Organisms.covid}.${typeof singleVariantViewKey}`; - organismsConfig: OrganismsConfig; + view: CovidAnalyzeSingleVariantView; pageState: CovidVariantData; + setPageState: Dispatch>; }; export const CovidSingleVariantDataDisplay: FC = ({ - organismViewKey, - organismsConfig, + view, pageState, + setPageState, }) => { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); - const variantFilter = view.pageStateHandler.toLapisFilter(pageState); const datasetLapisFilter = view.pageStateHandler.toLapisFilterWithoutVariant(pageState); const timeGranularity = chooseGranularityBasedOnDateRange({ @@ -55,7 +49,8 @@ export const CovidSingleVariantDataDisplay: FC diff --git a/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx index 35b12bad5..438ea46b9 100644 --- a/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx +++ b/website/src/components/views/analyzeSingleVariant/CovidSingleVariantReactPage.tsx @@ -10,6 +10,7 @@ import { type OrganismViewKey, Routing } from '../../../views/routing.ts'; import { SelectorHeadline } from '../../pageStateSelectors/SelectorHeadline.tsx'; import { SingleVariantPageStateSelector } from '../../pageStateSelectors/SingleVariantPageStateSelector.tsx'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink.ts'; +import { usePageState } from '../usePageState.ts'; export type CovidSingleVariantReactPageProps = { organismsConfig: OrganismsConfig; @@ -20,7 +21,7 @@ export const CovidSingleVariantReactPage: FC = const organismViewKey: OrganismViewKey = 'covid.singleVariantView'; const view = useMemo(() => new Routing(organismsConfig).getOrganismView(organismViewKey), [organismsConfig]); - const pageState = view.pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)); + const { pageState, setPageState } = usePageState(view.pageStateHandler); const variantFilter = view.pageStateHandler.toLapisFilter(pageState); @@ -51,9 +52,9 @@ export const CovidSingleVariantReactPage: FC = filters={ <>
@@ -61,17 +62,14 @@ export const CovidSingleVariantReactPage: FC = Collections } dataDisplay={ - + } /> ); diff --git a/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantDataDisplay.tsx b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantDataDisplay.tsx index 8dbdf3865..0bd266e27 100644 --- a/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantDataDisplay.tsx +++ b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantDataDisplay.tsx @@ -1,16 +1,15 @@ import { views } from '@genspectrum/dashboard-components/util'; -import { type FC, useMemo } from 'react'; +import { type Dispatch, type FC, type SetStateAction } from 'react'; import { QuickstartLinks } from './QuickstartLinks.tsx'; import { SelectVariant } from './SelectVariant.tsx'; -import type { OrganismsConfig } from '../../../config.ts'; import { Organisms } from '../../../types/Organism.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; import { hasOnlyUndefinedValues } from '../../../util/hasOnlyUndefinedValues.ts'; import type { DatasetAndVariantData } from '../../../views/View.ts'; import { getLocationSubdivision } from '../../../views/locationHelpers.ts'; import { locationFieldsToFilterIdentifier } from '../../../views/pageStateHandlers/locationFilterFromToUrl.ts'; -import { type OrganismViewKey, Routing, type SingleVariantOrganism } from '../../../views/routing.ts'; +import { type SingleVariantOrganism, type ViewsMap } from '../../../views/routing.ts'; import type { singleVariantViewKey } from '../../../views/viewKeys.ts'; import { ComponentsGrid } from '../../ComponentsGrid.tsx'; import { GsAggregate } from '../../genspectrum/GsAggregate.tsx'; @@ -20,19 +19,16 @@ import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx import { GsStatistics } from '../../genspectrum/GsStatistics.tsx'; export type GenericAnalyseSingleVariantDataDisplayProps = { - organismViewKey: OrganismViewKey & - `${Exclude}.${typeof singleVariantViewKey}`; - organismsConfig: OrganismsConfig; + view: ViewsMap[Exclude][typeof singleVariantViewKey]; pageState: DatasetAndVariantData; + setPageState: Dispatch>; }; export const GenericAnalyseSingleVariantDataDisplay: FC = ({ - organismViewKey, - organismsConfig, + view, pageState, + setPageState, }) => { - const view = useMemo(() => new Routing(organismsConfig), [organismsConfig]).getOrganismView(organismViewKey); - const variantLapisFilter = view.pageStateHandler.toLapisFilter(pageState); const datasetLapisFilter = view.pageStateHandler.toLapisFilterWithoutVariant(pageState); const timeGranularity = chooseGranularityBasedOnDateRange({ @@ -52,7 +48,7 @@ export const GenericAnalyseSingleVariantDataDisplay: FC {noVariantSelected && ( - + )} diff --git a/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx index 3a9c770f8..477e9a5a8 100644 --- a/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx +++ b/website/src/components/views/analyzeSingleVariant/GenericAnalyseSingleVariantReactPage.tsx @@ -10,6 +10,7 @@ import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../. import { singleVariantViewKey } from '../../../views/viewKeys'; import { SingleVariantPageStateSelector } from '../../pageStateSelectors/SingleVariantPageStateSelector'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; +import { usePageState } from '../usePageState.ts'; export type GenericAnalyseSingleVariantReactPageProps = { organism: Exclude, typeof Organisms.covid>; @@ -28,7 +29,7 @@ export const GenericAnalyseSingleVariantReactPage: FC } dataDisplay={ - + } /> ); diff --git a/website/src/components/views/analyzeSingleVariant/QuickstartLinks.tsx b/website/src/components/views/analyzeSingleVariant/QuickstartLinks.tsx index 9745d57d8..86eac39e9 100644 --- a/website/src/components/views/analyzeSingleVariant/QuickstartLinks.tsx +++ b/website/src/components/views/analyzeSingleVariant/QuickstartLinks.tsx @@ -1,8 +1,8 @@ -import type { FC } from 'react'; +import type { Dispatch, FC, SetStateAction } from 'react'; import { collectionVariantClassName } from './CollectionsList'; import { Organisms } from '../../../types/Organism'; -import type { DatasetFilter } from '../../../views/View.ts'; +import type { DatasetAndVariantData, DatasetFilter } from '../../../views/View.ts'; import { toDisplayName } from '../../../views/pageStateHandlers/PageStateHandler'; import type { SingleVariantOrganism, ViewsMap } from '../../../views/routing'; import { singleVariantViewKey } from '../../../views/viewKeys'; @@ -10,9 +10,10 @@ import { singleVariantViewKey } from '../../../views/viewKeys'; export type QuickstartLinksProps = { view: ViewsMap[Exclude][typeof singleVariantViewKey]; datasetFilter: DatasetFilter; + setPageState: Dispatch>; }; -export const QuickstartLinks: FC = ({ view, datasetFilter }) => { +export const QuickstartLinks: FC = ({ view, datasetFilter, setPageState }) => { const variants = view.organismConstants.predefinedVariants; return ( @@ -21,13 +22,17 @@ export const QuickstartLinks: FC = ({ view, datasetFilter
{variants.map((variant) => { - const href = view.pageStateHandler.toUrl({ - datasetFilter: datasetFilter, - variantFilter: variant, - }); + const applyFilters = () => { + setPageState({ + datasetFilter: datasetFilter, + variantFilter: variant, + }); + }; + + const displayName = toDisplayName(variant); return ( - - {toDisplayName(variant)} + + {displayName} ); })} diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx index 53921b476..76e5da97c 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySideDataDisplay.tsx @@ -1,36 +1,28 @@ -import { type FC, useMemo } from 'react'; +import { type FC } from 'react'; -import type { OrganismsConfig } from '../../../config.ts'; import { Organisms } from '../../../types/Organism.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; -import { ComponentHeight } from '../../../views/OrganismConstants.ts'; -import type { DatasetAndVariantData } from '../../../views/View.ts'; +import { BaseView } from '../../../views/BaseView.ts'; +import { ComponentHeight, type OrganismConstants } from '../../../views/OrganismConstants.ts'; +import type { CompareSideBySideData, DatasetAndVariantData } from '../../../views/View.ts'; +import { CompareSideBySideStateHandler } from '../../../views/pageStateHandlers/CompareSideBySidePageStateHandler.ts'; import { toLapisFilterWithoutVariant } from '../../../views/pageStateHandlers/toLapisFilterWithoutVariant.ts'; -import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; -import { compareSideBySideViewKey } from '../../../views/viewKeys.ts'; import { GsAggregate } from '../../genspectrum/GsAggregate.tsx'; import { GsMutations } from '../../genspectrum/GsMutations.tsx'; import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; import { GsRelativeGrowthAdvantage } from '../../genspectrum/GsRelativeGrowthAdvantage.tsx'; export type GenericCompareSideBySideDataDisplayProps = { - organismViewKey: `${OrganismWithViewKey}.${typeof compareSideBySideViewKey}`; - organismsConfig: OrganismsConfig; + view: BaseView; datasetAndVariantData: DatasetAndVariantData; hideMutationComponents?: boolean; }; export const GenericCompareSideBySideDataDisplay: FC = ({ - organismViewKey, - organismsConfig, + view, datasetAndVariantData, hideMutationComponents, }) => { - const view = useMemo( - () => new Routing(organismsConfig).getOrganismView(organismViewKey), - [organismsConfig, organismViewKey], - ); - const { datasetFilter, variantFilter } = datasetAndVariantData; const datasetLapisFilter = toLapisFilterWithoutVariant(datasetFilter, view.organismConstants.additionalFilters); diff --git a/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx b/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx index 20e72eede..e4f3b5a2c 100644 --- a/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx +++ b/website/src/components/views/compareSideBySide/GenericCompareSideBySideReactPage.tsx @@ -7,6 +7,7 @@ import { OrganismViewPageLayout } from '../../../layouts/OrganismPage/OrganismVi import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; import { compareSideBySideViewKey } from '../../../views/viewKeys'; import { CompareSideBySidePageStateSelector } from '../../pageStateSelectors/CompareSideBySidePageStateSelector'; +import { usePageState } from '../usePageState.ts'; export type GenericCompareSideBySideReactPageProps = { organism: OrganismWithViewKey; @@ -28,7 +29,7 @@ export const GenericCompareSideBySideReactPage: FC )}
diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx b/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx index 39dc1bb01..f2f7163ee 100644 --- a/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselineDataDisplay.tsx @@ -1,31 +1,19 @@ -import { type FC, useMemo } from 'react'; +import { type FC } from 'react'; import { SelectBaseline } from './SelectBaseline.tsx'; -import type { OrganismsConfig } from '../../../config.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; -import { ComponentHeight } from '../../../views/OrganismConstants.ts'; +import { GenericCompareToBaselineView } from '../../../views/BaseView.ts'; +import { ComponentHeight, type OrganismConstants } from '../../../views/OrganismConstants.ts'; import type { CompareToBaselineData } from '../../../views/View.ts'; -import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; -import { compareToBaselineViewKey } from '../../../views/viewKeys.ts'; import { ComponentsGrid } from '../../ComponentsGrid.tsx'; import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; export type GenericCompareToBaselineDisplayProps = { - organismViewKey: `${OrganismWithViewKey}.${typeof compareToBaselineViewKey}`; - organismsConfig: OrganismsConfig; + view: GenericCompareToBaselineView; pageState: CompareToBaselineData; }; -export const GenericCompareToBaselineDataDisplay: FC = ({ - organismViewKey, - organismsConfig, - pageState, -}) => { - const view = useMemo( - () => new Routing(organismsConfig).getOrganismView(organismViewKey), - [organismsConfig, organismViewKey], - ); - +export const GenericCompareToBaselineDataDisplay: FC = ({ view, pageState }) => { const baselineLapisFilter = view.pageStateHandler.baselineFilterToLapisFilter(pageState); const timeGranularity = chooseGranularityBasedOnDateRange({ earliestDate: new Date(view.organismConstants.earliestDate), diff --git a/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx b/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx index b1afb1c0b..b6b71b463 100644 --- a/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx +++ b/website/src/components/views/compareToBaseline/GenericCompareToBaselineReactPage.tsx @@ -7,6 +7,7 @@ import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../. import { compareToBaselineViewKey } from '../../../views/viewKeys'; import { CompareVariantsToBaselineStateSelector } from '../../pageStateSelectors/CompareVariantsToBaselineStateSelector'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; +import { usePageState } from '../usePageState.ts'; export type GenericCompareToBaselineReactPageProps = { organism: OrganismWithViewKey; @@ -25,7 +26,7 @@ export const GenericCompareToBaselineReactPage: FC - } - dataDisplay={ - } + dataDisplay={} /> ); }; diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx b/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx index 2b57434cd..6610477b3 100644 --- a/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx +++ b/website/src/components/views/compareVariants/GenericCompareVariantsDataDisplay.tsx @@ -1,33 +1,22 @@ -import { type FC, useMemo } from 'react'; +import { type FC } from 'react'; import { SelectVariants } from './SelectVariants.tsx'; -import type { OrganismsConfig } from '../../../config.ts'; import { chooseGranularityBasedOnDateRange } from '../../../util/chooseGranularityBasedOnDateRange.ts'; +import { GenericCompareVariantsView } from '../../../views/BaseView.ts'; +import type { OrganismConstants } from '../../../views/OrganismConstants.ts'; import type { CompareVariantsData } from '../../../views/View.ts'; -import { type OrganismWithViewKey, Routing } from '../../../views/routing.ts'; -import { compareVariantsViewKey } from '../../../views/viewKeys.ts'; import { ComponentsGrid } from '../../ComponentsGrid.tsx'; import { GsMutationComparison } from '../../genspectrum/GsMutationComparison.tsx'; import { GsPrevalenceOverTime } from '../../genspectrum/GsPrevalenceOverTime.tsx'; export type GenericCompareVariantsDataDisplayProps = { - organismViewKey: `${OrganismWithViewKey}.${typeof compareVariantsViewKey}`; - organismsConfig: OrganismsConfig; + view: GenericCompareVariantsView; pageState: CompareVariantsData; }; const componentHeight = '540px'; // prevalence over time table with 10 rows -export const GenericCompareVariantsDataDisplay: FC = ({ - organismViewKey, - organismsConfig, - pageState, -}) => { - const view = useMemo( - () => new Routing(organismsConfig).getOrganismView(organismViewKey), - [organismsConfig, organismViewKey], - ); - +export const GenericCompareVariantsDataDisplay: FC = ({ view, pageState }) => { const datasetLapisFilter = view.pageStateHandler.datasetFilterToLapisFilter(pageState.datasetFilter); const timeGranularity = chooseGranularityBasedOnDateRange({ earliestDate: new Date(view.organismConstants.earliestDate), diff --git a/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx b/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx index d1b970481..cffaa97fe 100644 --- a/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx +++ b/website/src/components/views/compareVariants/GenericCompareVariantsReactPage.tsx @@ -7,6 +7,7 @@ import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../. import { compareVariantsViewKey } from '../../../views/viewKeys'; import { CompareVariantsPageStateSelector } from '../../pageStateSelectors/CompareVariantsPageStateSelector'; import { sanitizeForFilename } from '../compareSideBySide/toDownloadLink'; +import { usePageState } from '../usePageState.ts'; export type GenericCompareVariantsReactPageProps = { organism: OrganismWithViewKey; @@ -25,7 +26,7 @@ export const GenericCompareVariantsReactPage: FC - } - dataDisplay={ - } + dataDisplay={} /> ); }; diff --git a/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx index 8dea17a2e..865a06470 100644 --- a/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx +++ b/website/src/components/views/sequencingEfforts/GenericSequencingEffortsReactPage.tsx @@ -6,6 +6,7 @@ import { SingleVariantOrganismPageLayout } from '../../../layouts/OrganismPage/S import { type OrganismViewKey, type OrganismWithViewKey, Routing } from '../../../views/routing'; import { sequencingEffortsViewKey } from '../../../views/viewKeys'; import { SequencingEffortsPageStateSelector } from '../../pageStateSelectors/SequencingEffortsPageStateSelector'; +import { usePageState } from '../usePageState.ts'; export type GenericSequencingEffortsReactPageProps = { organism: OrganismWithViewKey; @@ -24,7 +25,7 @@ export const GenericSequencingEffortsReactPage: FC } diff --git a/website/src/components/views/usePageState.ts b/website/src/components/views/usePageState.ts new file mode 100644 index 000000000..0dafacecc --- /dev/null +++ b/website/src/components/views/usePageState.ts @@ -0,0 +1,34 @@ +import { type Dispatch, type SetStateAction, useCallback, useMemo, useState } from 'react'; + +import type { PageStateHandler } from '../../views/pageStateHandlers/PageStateHandler.ts'; + +/** + * Given a `PageStateHandler`, this hook initially parses the page state from the current URL. + * It returns a `pageState` object and a `setPageState` function. + * When the function is called, + * the new page state is turned into a URL and set as the current URL (added to the page history). + * This way, the URL and current page state are kept in sync. + */ +export function usePageState>(pageStateHandler: StateHandler) { + type PageState = StateHandler extends PageStateHandler ? PS : never; + + const [pageState, setPageStateRaw] = useState( + () => pageStateHandler.parsePageStateFromUrl(new URL(window.location.href)) as PageState, + ); + + const setPageState: Dispatch> = useCallback( + (newPageStateOrUpdater) => { + setPageStateRaw((prevState) => { + const newPageState = + typeof newPageStateOrUpdater === 'function' + ? newPageStateOrUpdater(prevState) + : newPageStateOrUpdater; + window.history.pushState(undefined, '', pageStateHandler.toUrl(newPageState)); + return newPageState; + }); + }, + [pageStateHandler], + ); + + return useMemo(() => ({ pageState, setPageState }), [pageState, setPageState]); +} diff --git a/website/src/components/views/wasap/Wasap.astro b/website/src/components/views/wasap/Wasap.astro index 4c24593d2..4535ed13f 100644 --- a/website/src/components/views/wasap/Wasap.astro +++ b/website/src/components/views/wasap/Wasap.astro @@ -9,10 +9,8 @@ type Props = { const { wastewaterOrganism } = Astro.props; const { name } = wastewaterOrganismConfigs[wastewaterOrganism]; - -const url = Astro.url; --- - + diff --git a/website/src/components/views/wasap/WasapPage.tsx b/website/src/components/views/wasap/WasapPage.tsx index 5067ec857..296b85aed 100644 --- a/website/src/components/views/wasap/WasapPage.tsx +++ b/website/src/components/views/wasap/WasapPage.tsx @@ -26,20 +26,21 @@ import { WasapPageStateHandler } from '../../../views/pageStateHandlers/WasapPag import { GsMutationsOverTime } from '../../genspectrum/GsMutationsOverTime'; import { WasapPageStateSelector } from '../../pageStateSelectors/wasap/WasapPageStateSelector'; import { withQueryProvider } from '../../subscriptions/backendApi/withQueryProvider'; +import { usePageState } from '../usePageState.ts'; export type WasapPageProps = { wastewaterOrganism: WastewaterOrganismName; - currentUrl: URL; }; -export const WasapPageInner: FC = ({ wastewaterOrganism, currentUrl }) => { +export const WasapPageInner: FC = ({ wastewaterOrganism }) => { const config = wastewaterOrganismConfigs[wastewaterOrganism]; // initialize page state from the URL const pageStateHandler = useMemo(() => new WasapPageStateHandler(config), [config]); - const { base, analysis } = useMemo( - () => pageStateHandler.parsePageStateFromUrl(currentUrl), - [pageStateHandler, currentUrl], - ); + + const { + pageState: { base, analysis }, + setPageState, + } = usePageState(pageStateHandler); // fetch which mutations should be analyzed const { data, isPending, isError } = useWasapPageData(config, analysis); @@ -95,6 +96,7 @@ export const WasapPageInner: FC = ({ wastewaterOrganism, current pageStateHandler={pageStateHandler} initialBaseFilterState={base} initialAnalysisFilterState={analysis} + setPageState={setPageState} /> {isError ? ( diff --git a/website/src/views/OrganismConstants.ts b/website/src/views/OrganismConstants.ts index e3c32330c..b6c349517 100644 --- a/website/src/views/OrganismConstants.ts +++ b/website/src/views/OrganismConstants.ts @@ -24,6 +24,7 @@ type AggregatedVisualizations = { export interface OrganismConstants { readonly organism: Organism; + readonly earliestDate: string; readonly dataOrigins: DataOrigin[]; readonly accessionDownloadFields: string[]; readonly mainDateField: string; diff --git a/website/src/views/pageStateHandlers/CompareSideBySidePageStateHandler.spec.ts b/website/src/views/pageStateHandlers/CompareSideBySidePageStateHandler.spec.ts index a369acc58..99e178fb6 100644 --- a/website/src/views/pageStateHandlers/CompareSideBySidePageStateHandler.spec.ts +++ b/website/src/views/pageStateHandlers/CompareSideBySidePageStateHandler.spec.ts @@ -9,6 +9,7 @@ const mockDateRangeOption = { label: 'Last 7 Days', dateFrom: '2024-11-22', date const mockConstants: OrganismConstants = { organism: Organisms.covid, + earliestDate: 'earliestDate', dataOrigins: [], locationFields: ['country', 'region'], mainDateField: 'date', diff --git a/website/src/views/pageStateHandlers/CompareToBaselinePageStateHandler.spec.ts b/website/src/views/pageStateHandlers/CompareToBaselinePageStateHandler.spec.ts index 174923786..29f131f63 100644 --- a/website/src/views/pageStateHandlers/CompareToBaselinePageStateHandler.spec.ts +++ b/website/src/views/pageStateHandlers/CompareToBaselinePageStateHandler.spec.ts @@ -9,6 +9,7 @@ const mockDateRangeOption = { label: 'Last 7 Days', dateFrom: '2024-11-22', date const mockConstants: OrganismConstants = { organism: Organisms.covid, + earliestDate: 'earliestDate', dataOrigins: [], locationFields: ['country', 'region'], mainDateField: 'date', diff --git a/website/src/views/pageStateHandlers/CompareVariantsPageStateHandler.spec.ts b/website/src/views/pageStateHandlers/CompareVariantsPageStateHandler.spec.ts index 5d05f6de0..fbdce1b4f 100644 --- a/website/src/views/pageStateHandlers/CompareVariantsPageStateHandler.spec.ts +++ b/website/src/views/pageStateHandlers/CompareVariantsPageStateHandler.spec.ts @@ -9,6 +9,7 @@ const mockDateRangeOption = { label: 'Last 7 Days', dateFrom: '2024-11-22', date const mockConstants: OrganismConstants = { organism: Organisms.covid, + earliestDate: 'earliestDate', dataOrigins: [], locationFields: ['country', 'region'], mainDateField: 'date', diff --git a/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.spec.ts b/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.spec.ts index cc9f7ce34..785986390 100644 --- a/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.spec.ts +++ b/website/src/views/pageStateHandlers/SingleVariantPageStateHandler.spec.ts @@ -9,6 +9,7 @@ const mockDateRangeOption = { label: 'Last 7 Days', dateFrom: '2024-11-22', date const mockConstants: OrganismConstants = { organism: Organisms.covid, + earliestDate: 'earliestDate', dataOrigins: [], locationFields: ['country', 'region'], mainDateField: 'date', From 33494f03d399ec3cd5439bfbbb136e04d883e4b1 Mon Sep 17 00:00:00 2001 From: Felix Hennig Date: Wed, 14 Jan 2026 12:09:44 +0000 Subject: [PATCH 26/26] fix(tests): increase timeout (#994) --- website/tests/compareSideBySide.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/tests/compareSideBySide.spec.ts b/website/tests/compareSideBySide.spec.ts index 2ccfa925e..102df74d4 100644 --- a/website/tests/compareSideBySide.spec.ts +++ b/website/tests/compareSideBySide.spec.ts @@ -9,6 +9,8 @@ test.describe('The Compare Side-By-Side page', () => { test(`should show diagrams after selecting a variant in both columns - ${organism}`, async ({ compareSideBySidePage, }) => { + test.setTimeout(60_000); // there is a lot of data to load, so we need the test to run longer + const options = organismOptions[organism]; await compareSideBySidePage.goto(organism);