From a864434b4b684fc6f9190453cc7484edca856ed8 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 17 Mar 2026 16:01:50 +0100 Subject: [PATCH] feat(login): update to nextjs 16, improve caching, change default colors (#11629) # Which Problems Are Solved Updated the project to use the latest versions of Next.js and React, and implemented a SWR caching strategy for key settings API calls to improve performance. Adjusted configuration to ensure compatibility with Next.js 16. # How the Problems Are Solved - Updated next to 16.1.6, react & react-dom to 19.2.4, and next-intl to 4.8.3. - Implemented `API_CACHE_ENABLED` and `API_CACHE_CONFIG` (replacing deprecated unstable_cacheLife) for: - getBrandingSettings - getSecuritySettings - getPasswordComplexitySettings - getLoginSettings ... - Updated default theme colors from blue to a more neutral black and white # Additional changes - Updated login docker image to node 24 --------- Co-authored-by: Ramon --- apps/login/Dockerfile | 2 +- apps/login/next-env-vars.d.ts | 18 ++ apps/login/next-env.d.ts | 2 +- apps/login/package.json | 4 +- .../(login)/idp/[provider]/process/page.tsx | 42 ++- apps/login/src/app/login/route.ts | 2 - apps/login/src/app/otel-test/route.ts | 1 - .../src/components/idp-process-handler.tsx | 2 +- apps/login/src/helpers/colors.ts | 4 +- apps/login/src/lib/theme.test.ts | 6 + apps/login/src/lib/zitadel.ts | 260 +++++++++++----- apps/login/src/{middleware.ts => proxy.ts} | 4 +- apps/login/src/styles/globals.scss | 3 - apps/login/src/styles/vars.scss | 174 ----------- apps/login/tsconfig.json | 2 +- package.json | 4 +- pnpm-lock.yaml | 291 ++++++------------ 17 files changed, 330 insertions(+), 491 deletions(-) rename apps/login/src/{middleware.ts => proxy.ts} (97%) delete mode 100644 apps/login/src/styles/vars.scss diff --git a/apps/login/Dockerfile b/apps/login/Dockerfile index dc51b39df..081ce95e6 100644 --- a/apps/login/Dockerfile +++ b/apps/login/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-alpine +FROM node:24-alpine WORKDIR /app RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs diff --git a/apps/login/next-env-vars.d.ts b/apps/login/next-env-vars.d.ts index 05c4f240b..153aba1fe 100644 --- a/apps/login/next-env-vars.d.ts +++ b/apps/login/next-env-vars.d.ts @@ -83,6 +83,24 @@ declare namespace NodeJS { * which is safer for environments with enterprise email link scanners. */ NEXT_PUBLIC_AUTO_SUBMIT_CODE?: string; + + /** + * Optional: Enable the SWR in-memory cache for API requests globally. + * Defaults to true. Set to "false" to disable completely. + */ + API_CACHE_ENABLED?: string; + + /** + * Optional: JSON string to configure the cache TTLs (in minutes) for specific backend API routes or global fallbacks. + * Example: '{"defaultMinutes": 15, "longMinutes": 60, "getBrandingSettings": 120}' + * + * Properties: + * - \`defaultMinutes\`: The globally utilized default TTL in minutes (falls back to 15 if not set). + * - \`longMinutes\`: The TTL utilized string for long-cached routes, like branding/translation (falls back to 60 if not set). + * - \`[route_name]\`: Explicit overrides per specific API method (e.g., \`getHostedLoginTranslation\`). + */ + API_CACHE_CONFIG?: string; + /** * Optional: Disable OpenTelemetry instrumentation. * Set to "true" to bypass OTEL initialization. diff --git a/apps/login/next-env.d.ts b/apps/login/next-env.d.ts index 830fb594c..c4b7818fb 100755 --- a/apps/login/next-env.d.ts +++ b/apps/login/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -/// +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/login/package.json b/apps/login/package.json index 827ff2510..47d76533f 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -41,8 +41,8 @@ "escape-html": "^1.0.3", "lucide-react": "^0.562.0", "moment": "^2.30.1", - "next": "15.5.10", - "next-intl": "^3.26.5", + "next": "16.1.6", + "next-intl": "^4.8.3", "next-themes": "^0.2.1", "nice-grpc": "^2.1.14", "qrcode.react": "^4.2.0", diff --git a/apps/login/src/app/(login)/idp/[provider]/process/page.tsx b/apps/login/src/app/(login)/idp/[provider]/process/page.tsx index 8e64023d7..2ad0a56ed 100644 --- a/apps/login/src/app/(login)/idp/[provider]/process/page.tsx +++ b/apps/login/src/app/(login)/idp/[provider]/process/page.tsx @@ -1,4 +1,9 @@ +import { DynamicTheme } from "@/components/dynamic-theme"; import { IdpProcessHandler } from "@/components/idp-process-handler"; +import { getServiceConfig } from "@/lib/service-url"; +import { getBrandingSettings, getDefaultOrg } from "@/lib/zitadel"; +import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; +import { headers } from "next/headers"; /** * This page handles the initial IDP callback with the single-use token. @@ -20,17 +25,32 @@ export default async function ProcessPage(props: { throw new Error("Missing required IDP callback parameters"); } + const _headers = await headers(); + const { serviceConfig } = getServiceConfig(_headers); + + let defaultOrganization; + if (!organization) { + const org: Organization | null = await getDefaultOrg({ serviceConfig }); + if (org) { + defaultOrganization = org.id; + } + } + + const branding = await getBrandingSettings({ serviceConfig, organization: organization ?? defaultOrganization }); + return ( - + + + ); } diff --git a/apps/login/src/app/login/route.ts b/apps/login/src/app/login/route.ts index 6d04e6f6b..a68fe86d6 100644 --- a/apps/login/src/app/login/route.ts +++ b/apps/login/src/app/login/route.ts @@ -10,8 +10,6 @@ import { NextRequest, NextResponse } from "next/server"; export const dynamic = "force-dynamic"; export const revalidate = false; export const fetchCache = "default-no-store"; -// Add this to prevent RSC requests -export const runtime = "nodejs"; async function loadSessions({ serviceConfig, ids }: { serviceConfig: ServiceConfig; ids: string[] }): Promise { const response = await listSessions({ serviceConfig, ids: ids.filter((id: string | undefined) => !!id) }); diff --git a/apps/login/src/app/otel-test/route.ts b/apps/login/src/app/otel-test/route.ts index 109eda03b..7bee82709 100644 --- a/apps/login/src/app/otel-test/route.ts +++ b/apps/login/src/app/otel-test/route.ts @@ -10,7 +10,6 @@ import { import { metrics, SpanStatusCode, trace } from "@opentelemetry/api"; import { NextResponse } from "next/server"; -export const runtime = "nodejs"; const logger = createLogger("otel-test"); export async function GET() { diff --git a/apps/login/src/components/idp-process-handler.tsx b/apps/login/src/components/idp-process-handler.tsx index 7e9c6e2bf..23f6b892a 100644 --- a/apps/login/src/components/idp-process-handler.tsx +++ b/apps/login/src/components/idp-process-handler.tsx @@ -94,7 +94,7 @@ export function IdpProcessHandler({ }, [provider, id, token, requestId, organization, link, sessionId, linkFingerprint, postErrorRedirectUrl, router, t]); return ( -
+
{samlData && } {loading && (
diff --git a/apps/login/src/helpers/colors.ts b/apps/login/src/helpers/colors.ts index eafa25351..c3a92132d 100644 --- a/apps/login/src/helpers/colors.ts +++ b/apps/login/src/helpers/colors.ts @@ -30,13 +30,13 @@ export type ColorMap = { [_key in MapName]: Color[]; }; -export const DARK_PRIMARY = "#2073c4"; +export const DARK_PRIMARY = "#eeeeee"; export const PRIMARY = "#5469d4"; export const DARK_WARN = "#ff3b5b"; export const WARN = "#cd3d56"; -export const DARK_BACKGROUND = "#111827"; +export const DARK_BACKGROUND = "#252526"; export const BACKGROUND = "#fafafa"; export const DARK_TEXT = "#ffffff"; diff --git a/apps/login/src/lib/theme.test.ts b/apps/login/src/lib/theme.test.ts index 9351e6ff9..f5df8bdd5 100644 --- a/apps/login/src/lib/theme.test.ts +++ b/apps/login/src/lib/theme.test.ts @@ -78,6 +78,12 @@ describe("Theme Configuration", () => { describe("getThemeConfig", () => { it("should return default theme when no environment variables are set", () => { + delete process.env.NEXT_PUBLIC_THEME_ROUNDNESS; + delete process.env.NEXT_PUBLIC_THEME_LAYOUT; + delete process.env.NEXT_PUBLIC_THEME_APPEARANCE; + delete process.env.NEXT_PUBLIC_THEME_SPACING; + delete process.env.NEXT_PUBLIC_THEME_BACKGROUND_IMAGE; + const config = getThemeConfig(); expect(config.roundness).toBe(DEFAULT_THEME.roundness); diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 7001be94b..a46232c48 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -30,7 +30,7 @@ import { VerifyU2FRegistrationRequest, } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { getTranslations } from "next-intl/server"; -import { unstable_cacheLife as cacheLife } from "next/cache"; + import { getUserAgent } from "./fingerprint"; import { createLogger } from "./logger"; @@ -40,13 +40,55 @@ import { createServiceForHost } from "./service"; const logger = createLogger("zitadel"); -const useCache = process.env.DEBUG !== "true"; +const useCache = process.env.API_CACHE_ENABLED !== "false"; -async function cacheWrapper(callback: Promise) { - "use cache"; - cacheLife("hours"); +let cacheConfig: Record = {}; +try { + if (process.env.API_CACHE_CONFIG) { + cacheConfig = JSON.parse(process.env.API_CACHE_CONFIG); + } +} catch (e) { + console.error("Failed to parse API_CACHE_CONFIG", e); +} - return callback; +const defaultCacheTTL = (cacheConfig.defaultMinutes ?? 15) * 60 * 1000; // 15 mins default +const longCacheTTL = (cacheConfig.longMinutes ?? 60) * 60 * 1000; // 1 hour default + +/** + * Helper to determine the TTL for a specific API method. + * Allows overriding per-resource via the API_CACHE_CONFIG environment variable. + */ +function getTTLForKey(keyPrefix: string, fallbackTtl: number) { + const configTTL = cacheConfig[keyPrefix]; + if (typeof configTTL === "number" && !isNaN(configTTL)) { + return configTTL * 60 * 1000; // Config expects minutes + } + return fallbackTtl; +} + +const promiseCache = new Map; expiresAt: number }>(); + +/** + * A stale-while-revalidate in-memory cache to keep data fresh and deduplicate concurrent requests. + * We cache the Promise, so concurrent requests share the exact same execution. + */ +function freshCache(key: string, fetcher: () => Promise, ttlMs: number): Promise { + if (!useCache) { + return fetcher(); + } + + const now = Date.now(); + const cached = promiseCache.get(key); + if (cached && now < cached.expiresAt) { + return cached.promise; + } + + const promise = fetcher(); + promiseCache.set(key, { promise, expiresAt: now + ttlMs }); + + promise.catch(() => promiseCache.delete(key)); + + return promise; } export async function getHostedLoginTranslation({ @@ -57,29 +99,35 @@ export async function getHostedLoginTranslation({ organization?: string; locale?: string; }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getHostedLoginTranslation( - { - level: organization - ? { - case: "organizationId", - value: organization, - } - : { - case: "instance", - value: true, - }, - locale: locale, - }, - {}, - ) - .then((resp) => { - return resp.translations ? resp.translations : undefined; - }); + return settingsService + .getHostedLoginTranslation( + { + level: organization + ? { + case: "organizationId", + value: organization, + } + : { + case: "instance", + value: true, + }, + locale: locale, + }, + {}, + ) + .then((resp) => { + return resp.translations ? resp.translations : undefined; + }); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getHostedLoginTranslation-${organization || "instance"}-${locale || "default"}`, + fetcher, + getTTLForKey("getHostedLoginTranslation", longCacheTTL), + ); } export async function getBrandingSettings({ @@ -88,13 +136,19 @@ export async function getBrandingSettings({ }: WithServiceConfig<{ organization?: string; }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getBrandingSettings-${organization || "instance"}`, + fetcher, + getTTLForKey("getBrandingSettings", longCacheTTL), + ); } export async function getLoginSettings({ @@ -103,41 +157,61 @@ export async function getLoginSettings({ }: WithServiceConfig<{ organization?: string; }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getLoginSettings({ ctx: makeReqCtx(organization) }, {}) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getLoginSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getLoginSettings-${organization || "instance"}`, + fetcher, + getTTLForKey("getLoginSettings", defaultCacheTTL), + ); } export async function getSecuritySettings({ serviceConfig }: WithServiceConfig) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService.getSecuritySettings({}).then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService.getSecuritySettings({}).then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache(`getSecuritySettings-instance`, fetcher, getTTLForKey("getSecuritySettings", defaultCacheTTL)); } export async function getLockoutSettings({ serviceConfig, orgId }: WithServiceConfig<{ orgId?: string }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getLockoutSettings({ ctx: makeReqCtx(orgId) }, {}) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getLockoutSettings({ ctx: makeReqCtx(orgId) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getLockoutSettings-${orgId || "instance"}`, + fetcher, + getTTLForKey("getLockoutSettings", defaultCacheTTL), + ); } export async function getPasswordExpirySettings({ serviceConfig, orgId }: WithServiceConfig<{ orgId?: string }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getPasswordExpirySettings({ ctx: makeReqCtx(orgId) }, {}) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getPasswordExpirySettings({ ctx: makeReqCtx(orgId) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getPasswordExpirySettings-${orgId || "instance"}`, + fetcher, + getTTLForKey("getPasswordExpirySettings", defaultCacheTTL), + ); } export async function listIDPLinks({ serviceConfig, userId }: WithServiceConfig<{ userId: string }>) { @@ -165,16 +239,18 @@ export async function registerTOTP({ serviceConfig, userId }: WithServiceConfig< } export async function getAllowedLanguages({ serviceConfig }: WithServiceConfig) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService.getGeneralSettings({}, {}).then((resp) => { - return { - allowedLanguages: resp.allowedLanguages, - defaultLanguage: resp.defaultLanguage, - }; - }); + return settingsService.getGeneralSettings({}, {}).then((resp) => { + return { + allowedLanguages: resp.allowedLanguages, + defaultLanguage: resp.defaultLanguage, + }; + }); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache(`getGeneralSettings-instance`, fetcher, getTTLForKey("getGeneralSettings", longCacheTTL)); } export async function getLegalAndSupportSettings({ @@ -183,13 +259,19 @@ export async function getLegalAndSupportSettings({ }: WithServiceConfig<{ organization?: string; }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getLegalAndSupportSettings-${organization || "instance"}`, + fetcher, + getTTLForKey("getLegalAndSupportSettings", longCacheTTL), + ); } export async function getPasswordComplexitySettings({ @@ -198,13 +280,19 @@ export async function getPasswordComplexitySettings({ }: WithServiceConfig<{ organization?: string; }>) { - const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); + const fetcher = async () => { + const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig); - const callback = settingsService - .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) - .then((resp) => (resp.settings ? resp.settings : undefined)); + return settingsService + .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) + .then((resp) => (resp.settings ? resp.settings : undefined)); + }; - return useCache ? cacheWrapper(callback) : callback; + return freshCache( + `getPasswordComplexitySettings-${organization || "instance"}`, + fetcher, + getTTLForKey("getPasswordComplexitySettings", defaultCacheTTL), + ); } export async function createSessionFromChecksAndChallenges({ @@ -740,23 +828,29 @@ export async function searchUsers({ } export async function getDefaultOrg({ serviceConfig }: WithServiceConfig): Promise { - const orgService: Client = await createServiceForHost(OrganizationService, serviceConfig); + const fetcher = async () => { + const orgService: Client = await createServiceForHost(OrganizationService, serviceConfig); - return orgService - .listOrganizations( - { - queries: [ - { - query: { - case: "defaultQuery", - value: {}, + return orgService + .listOrganizations( + { + queries: [ + { + query: { + case: "defaultQuery", + value: {}, + }, }, - }, - ], - }, - {}, - ) - .then((resp) => (resp?.result && resp.result[0] ? resp.result[0] : null)); + ], + }, + {}, + ) + .then((resp) => (resp?.result && resp.result[0] ? resp.result[0] : null)); + }; + + return useCache + ? freshCache(`getDefaultOrg-${"instance"}`, fetcher, getTTLForKey("getDefaultOrg", defaultCacheTTL)) + : fetcher(); } export async function getOrgsByDomain({ serviceConfig, domain }: WithServiceConfig<{ domain: string }>) { diff --git a/apps/login/src/middleware.ts b/apps/login/src/proxy.ts similarity index 97% rename from apps/login/src/middleware.ts rename to apps/login/src/proxy.ts index b4bf90bf6..b713b13b6 100644 --- a/apps/login/src/middleware.ts +++ b/apps/login/src/proxy.ts @@ -6,8 +6,6 @@ import { buildCSP } from "./lib/csp"; import { createLogger } from "./lib/logger"; import { getServiceConfig } from "./lib/service-url"; -export const runtime = "nodejs"; - const logger = createLogger("middleware"); export const config = { matcher: ["/.well-known/:path*", "/oauth/:path*", "/oidc/:path*", "/idps/callback/:path*", "/saml/:path*", "/:path*"], @@ -31,7 +29,7 @@ async function loadSecuritySettings(request: NextRequest): Promise=18.14.0'} hasBin: true - '@next/env@15.5.10': - resolution: {integrity: sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==} - '@next/env@16.1.6': resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} '@next/eslint-plugin-next@16.1.6': resolution: {integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==} - '@next/swc-darwin-arm64@15.5.7': - resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - '@next/swc-darwin-arm64@16.1.6': resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.7': - resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - '@next/swc-darwin-x64@16.1.6': resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.7': - resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@next/swc-linux-arm64-gnu@16.1.6': resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==} engines: {node: '>= 10'} @@ -3112,13 +3081,6 @@ packages: os: [linux] libc: [glibc] - '@next/swc-linux-arm64-musl@15.5.7': - resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [musl] - '@next/swc-linux-arm64-musl@16.1.6': resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==} engines: {node: '>= 10'} @@ -3126,13 +3088,6 @@ packages: os: [linux] libc: [musl] - '@next/swc-linux-x64-gnu@15.5.7': - resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [glibc] - '@next/swc-linux-x64-gnu@16.1.6': resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==} engines: {node: '>= 10'} @@ -3140,13 +3095,6 @@ packages: os: [linux] libc: [glibc] - '@next/swc-linux-x64-musl@15.5.7': - resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [musl] - '@next/swc-linux-x64-musl@16.1.6': resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==} engines: {node: '>= 10'} @@ -3154,24 +3102,12 @@ packages: os: [linux] libc: [musl] - '@next/swc-win32-arm64-msvc@15.5.7': - resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - '@next/swc-win32-arm64-msvc@16.1.6': resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.7': - resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@next/swc-win32-x64-msvc@16.1.6': resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==} engines: {node: '>= 10'} @@ -5198,6 +5134,9 @@ packages: resolution: {integrity: sha512-WkhW1HO8pA8JT8e27tvjQHQg8eO5KaOz+WsGkN00RyL5DwHgPSzu4a3eYug+b3rW7OGFub7jadXBuGSrzqgonA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@schummar/icu-type-parser@1.21.5': + resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==} + '@shikijs/core@3.21.0': resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==} @@ -8530,6 +8469,9 @@ packages: resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} engines: {node: '>=0.10.0'} + icu-minify@4.8.3: + resolution: {integrity: sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA==} + identifier-regex@1.0.1: resolution: {integrity: sha512-ZrYyM0sozNPZlvBvE7Oq9Bn44n0qKGrYu5sQ0JzMUnjIhpgWYE2JB6aBoFwEYdPjqj7jPyxXTMJiHDOxDfd8yw==} engines: {node: '>=18'} @@ -8617,8 +8559,8 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - intl-messageformat@10.7.16: - resolution: {integrity: sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==} + intl-messageformat@11.1.2: + resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==} ip-address@10.0.1: resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} @@ -9880,11 +9822,18 @@ packages: peerDependencies: typescript: '5' - next-intl@3.26.5: - resolution: {integrity: sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg==} + next-intl-swc-plugin-extractor@4.8.3: + resolution: {integrity: sha512-YcaT+R9z69XkGhpDarVFWUprrCMbxgIQYPUaXoE6LGVnLjGdo8hu3gL6bramDVjNKViYY8a/pXPy7Bna0mXORg==} + + next-intl@4.8.3: + resolution: {integrity: sha512-PvdBDWg+Leh7BR7GJUQbCDVVaBRn37GwDBWc9sv0rVQOJDQ5JU1rVzx9EEGuOGYo0DHAl70++9LQ7HxTawdL7w==} peerDependencies: - next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 + next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true next-themes@0.2.1: resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} @@ -9902,27 +9851,6 @@ packages: next-validate-link@1.6.4: resolution: {integrity: sha512-wR/VKyJlaTbUT5k1uujEnk6O616YtWGt52s9FJa3tRCQ2qL2TGFTAklXJ0QdX1NTAEeP6rGFOTtHEDwveFrc2g==} - next@15.5.10: - resolution: {integrity: sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - next@16.1.6: resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==} engines: {node: '>=20.9.0'} @@ -10441,6 +10369,9 @@ packages: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} + po-parser@2.1.1: + resolution: {integrity: sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -12079,10 +12010,10 @@ packages: '@types/react': optional: true - use-intl@3.26.5: - resolution: {integrity: sha512-OdsJnC/znPvHCHLQH/duvQNXnP1w0hPfS+tkSi3mAbfjYBGh4JnyfdwkQBfIVf7t8gs9eSX/CntxUMvtKdG2MQ==} + use-intl@4.8.3: + resolution: {integrity: sha512-nLxlC/RH+le6g3amA508Itnn/00mE+J22ui21QhOWo5V9hCEC43+WtnRAITbJW0ztVZphev5X9gvOf2/Dk9PLA==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 use-isomorphic-layout-effect@1.2.1: resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==} @@ -14085,38 +14016,26 @@ snapshots: - '@vue/composition-api' - vue - '@formatjs/ecma402-abstract@2.3.4': + '@formatjs/ecma402-abstract@3.1.1': dependencies: - '@formatjs/fast-memoize': 2.2.7 - '@formatjs/intl-localematcher': 0.6.1 + '@formatjs/fast-memoize': 3.1.0 + '@formatjs/intl-localematcher': 0.8.1 decimal.js: 10.6.0 tslib: 2.8.1 - '@formatjs/fast-memoize@2.2.7': - dependencies: - tslib: 2.8.1 - '@formatjs/fast-memoize@3.1.0': dependencies: tslib: 2.8.1 - '@formatjs/icu-messageformat-parser@2.11.2': + '@formatjs/icu-messageformat-parser@3.5.1': dependencies: - '@formatjs/ecma402-abstract': 2.3.4 - '@formatjs/icu-skeleton-parser': 1.8.14 + '@formatjs/ecma402-abstract': 3.1.1 + '@formatjs/icu-skeleton-parser': 2.1.1 tslib: 2.8.1 - '@formatjs/icu-skeleton-parser@1.8.14': - dependencies: - '@formatjs/ecma402-abstract': 2.3.4 - tslib: 2.8.1 - - '@formatjs/intl-localematcher@0.5.10': - dependencies: - tslib: 2.8.1 - - '@formatjs/intl-localematcher@0.6.1': + '@formatjs/icu-skeleton-parser@2.1.1': dependencies: + '@formatjs/ecma402-abstract': 3.1.1 tslib: 2.8.1 '@formatjs/intl-localematcher@0.8.1': @@ -14949,59 +14868,33 @@ snapshots: yaml: 2.8.1 yargs: 17.7.2 - '@next/env@15.5.10': {} - '@next/env@16.1.6': {} '@next/eslint-plugin-next@16.1.6': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.5.7': - optional: true - '@next/swc-darwin-arm64@16.1.6': optional: true - '@next/swc-darwin-x64@15.5.7': - optional: true - '@next/swc-darwin-x64@16.1.6': optional: true - '@next/swc-linux-arm64-gnu@15.5.7': - optional: true - '@next/swc-linux-arm64-gnu@16.1.6': optional: true - '@next/swc-linux-arm64-musl@15.5.7': - optional: true - '@next/swc-linux-arm64-musl@16.1.6': optional: true - '@next/swc-linux-x64-gnu@15.5.7': - optional: true - '@next/swc-linux-x64-gnu@16.1.6': optional: true - '@next/swc-linux-x64-musl@15.5.7': - optional: true - '@next/swc-linux-x64-musl@16.1.6': optional: true - '@next/swc-win32-arm64-msvc@15.5.7': - optional: true - '@next/swc-win32-arm64-msvc@16.1.6': optional: true - '@next/swc-win32-x64-msvc@15.5.7': - optional: true - '@next/swc-win32-x64-msvc@16.1.6': optional: true @@ -16088,7 +15981,6 @@ snapshots: '@parcel/watcher-win32-arm64': 2.5.1 '@parcel/watcher-win32-ia32': 2.5.1 '@parcel/watcher-win32-x64': 2.5.1 - optional: true '@phosphor-icons/core@2.1.1': {} @@ -17541,6 +17433,8 @@ snapshots: transitivePeerDependencies: - chokidar + '@schummar/icu-type-parser@1.21.5': {} + '@shikijs/core@3.21.0': dependencies: '@shikijs/types': 3.21.0 @@ -17755,10 +17649,8 @@ snapshots: '@swc/core-win32-ia32-msvc': 1.15.3 '@swc/core-win32-x64-msvc': 1.15.3 '@swc/helpers': 0.5.17 - optional: true - '@swc/counter@0.1.3': - optional: true + '@swc/counter@0.1.3': {} '@swc/helpers@0.5.15': dependencies: @@ -17771,7 +17663,6 @@ snapshots: '@swc/types@0.1.25': dependencies: '@swc/counter': 0.1.3 - optional: true '@tailwindcss/forms@0.5.11(tailwindcss@3.4.14)': dependencies: @@ -20948,7 +20839,7 @@ snapshots: '@types/react': 19.2.14 algoliasearch: 5.37.0 lucide-react: 0.574.0(react@19.2.4) - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) + next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) zod: 4.3.6 @@ -20979,7 +20870,7 @@ snapshots: '@types/mdast': 4.0.4 '@types/mdx': 2.0.13 '@types/react': 19.2.14 - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) + next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) react: 19.2.4 vite: 7.1.11(@types/node@25.2.3)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1) transitivePeerDependencies: @@ -21049,7 +20940,7 @@ snapshots: optionalDependencies: '@types/mdx': 2.0.13 '@types/react': 19.2.14 - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) + next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) transitivePeerDependencies: - '@emotion/is-prop-valid' - '@types/react-dom' @@ -21569,6 +21460,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + icu-minify@4.8.3: + dependencies: + '@formatjs/icu-messageformat-parser': 3.5.1 + identifier-regex@1.0.1: dependencies: reserved-identifiers: 1.2.0 @@ -21632,11 +21527,11 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - intl-messageformat@10.7.16: + intl-messageformat@11.1.2: dependencies: - '@formatjs/ecma402-abstract': 2.3.4 - '@formatjs/fast-memoize': 2.2.7 - '@formatjs/icu-messageformat-parser': 2.11.2 + '@formatjs/ecma402-abstract': 3.1.1 + '@formatjs/fast-memoize': 3.1.0 + '@formatjs/icu-messageformat-parser': 3.5.1 tslib: 2.8.1 ip-address@10.0.1: {} @@ -23224,17 +23119,28 @@ snapshots: dependencies: typescript: 5.9.3 - next-intl@3.26.5(next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react@19.2.4): - dependencies: - '@formatjs/intl-localematcher': 0.5.10 - negotiator: 1.0.0 - next: 15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) - react: 19.2.4 - use-intl: 3.26.5(react@19.2.4) + next-intl-swc-plugin-extractor@4.8.3: {} - next-themes@0.2.1(next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next-intl@4.8.3(@swc/helpers@0.5.17)(next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react@19.2.4)(typescript@5.9.3): dependencies: - next: 15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) + '@formatjs/intl-localematcher': 0.8.1 + '@parcel/watcher': 2.5.1 + '@swc/core': 1.15.3(@swc/helpers@0.5.17) + icu-minify: 4.8.3 + negotiator: 1.0.0 + next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) + next-intl-swc-plugin-extractor: 4.8.3 + po-parser: 2.1.1 + react: 19.2.4 + use-intl: 4.8.3(react@19.2.4) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@swc/helpers' + + next-themes@0.2.1(next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -23255,33 +23161,7 @@ snapshots: transitivePeerDependencies: - supports-color - next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3): - dependencies: - '@next/env': 15.5.10 - '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001760 - postcss: 8.4.31 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.2.4) - optionalDependencies: - '@next/swc-darwin-arm64': 15.5.7 - '@next/swc-darwin-x64': 15.5.7 - '@next/swc-linux-arm64-gnu': 15.5.7 - '@next/swc-linux-arm64-musl': 15.5.7 - '@next/swc-linux-x64-gnu': 15.5.7 - '@next/swc-linux-x64-musl': 15.5.7 - '@next/swc-win32-arm64-msvc': 15.5.7 - '@next/swc-win32-x64-msvc': 15.5.7 - '@opentelemetry/api': 1.9.0 - '@playwright/test': 1.58.0 - sass: 1.97.3 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3): + next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3): dependencies: '@next/env': 16.1.6 '@swc/helpers': 0.5.15 @@ -23329,8 +23209,7 @@ snapshots: node-addon-api@6.1.0: optional: true - node-addon-api@7.1.1: - optional: true + node-addon-api@7.1.1: {} node-domexception@1.0.0: {} @@ -23920,6 +23799,8 @@ snapshots: pngjs@5.0.0: {} + po-parser@2.1.1: {} + possible-typed-array-names@1.1.0: {} postcss-import@15.1.0(postcss@8.5.6): @@ -25872,10 +25753,12 @@ snapshots: optionalDependencies: '@types/react': 19.2.14 - use-intl@3.26.5(react@19.2.4): + use-intl@4.8.3(react@19.2.4): dependencies: - '@formatjs/fast-memoize': 2.2.7 - intl-messageformat: 10.7.16 + '@formatjs/fast-memoize': 3.1.0 + '@schummar/icu-type-parser': 1.21.5 + icu-minify: 4.8.3 + intl-messageformat: 11.1.2 react: 19.2.4 use-isomorphic-layout-effect@1.2.1(@types/react@19.2.14)(react@19.2.4):