diff --git a/.vscode/settings.json b/.vscode/settings.json
index ebac3d3b1..1f95a140a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,6 @@
{
+ "editor.tabSize": 2,
+ "editor.insertSpaces": true,
"githubPullRequests.queries": [
{
"label": "Backlog",
diff --git a/packages/e2e/next/cypress/e2e/clearOnDefault.cy.js b/packages/e2e/next/cypress/e2e/clearOnDefault.cy.js
deleted file mode 100644
index 942322b8f..000000000
--- a/packages/e2e/next/cypress/e2e/clearOnDefault.cy.js
+++ /dev/null
@@ -1,10 +0,0 @@
-///
-
-it('Clears the URL when setting the default value when `clearOnDefault` is used', () => {
- cy.visit(
- '/app/clearOnDefault?a=a&b=b&array=1,2,3&json-ref={"egg":"spam"}&json-new={"egg":"spam"}&keepMe=init'
- )
- cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
- cy.get('button').click()
- cy.location('search').should('eq', '?a=&keepMe=')
-})
diff --git a/packages/e2e/next/cypress/e2e/repro-599.cy.js b/packages/e2e/next/cypress/e2e/repro-599.cy.js
deleted file mode 100644
index 01452371d..000000000
--- a/packages/e2e/next/cypress/e2e/repro-599.cy.js
+++ /dev/null
@@ -1,18 +0,0 @@
-///
-
-it('Reproduction for issue #599', () => {
- // Start without encoding for most characters
- cy.visit(
- '/app/repro-599?a %26b%3Fc%3Dd%23e%f%2Bg"h\'i`jl(m)n*o,p.q:r;s/t=init'
- )
- cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
- cy.get('input').should('have.value', 'init')
- cy.get('p').should('have.text', 'init')
- cy.get('button').click()
- cy.get('input').should('have.value', 'works')
- cy.get('p').should('have.text', 'works')
- cy.location('search').should(
- 'eq',
- '?a%20%26b%3Fc%3Dd%23e%f%2Bg%22h%27i`j%3Ck%3El(m)n*o,p.q:r;s/t=works'
- )
-})
diff --git a/packages/e2e/next/src/app/app/clearOnDefault/page.tsx b/packages/e2e/next/src/app/app/clearOnDefault/page.tsx
deleted file mode 100644
index 42f5df888..000000000
--- a/packages/e2e/next/src/app/app/clearOnDefault/page.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-'use client'
-
-import {
- parseAsArrayOf,
- parseAsInteger,
- parseAsJson,
- parseAsString,
- useQueryState
-} from 'nuqs'
-import { Suspense } from 'react'
-
-export default function Page() {
- return (
-
-
-
- )
-}
-
-const defaultJSON = { foo: 'bar' }
-const runtimePassthrough = (x: unknown) => x
-
-function Client() {
- const [, setA] = useQueryState('a')
- const [, setB] = useQueryState('b', {
- defaultValue: ''
- })
- const [, setArray] = useQueryState(
- 'array',
- parseAsArrayOf(parseAsInteger).withDefault([])
- )
- const [, setJsonRef] = useQueryState(
- 'json-ref',
- parseAsJson(runtimePassthrough).withDefault(defaultJSON)
- )
- const [, setJsonNew] = useQueryState(
- 'json-new',
- parseAsJson(runtimePassthrough).withDefault(defaultJSON)
- )
- const [, keepMe] = useQueryState(
- 'keepMe',
- parseAsString.withDefault('').withOptions({ clearOnDefault: false })
- )
- return (
- <>
-
- >
- )
-}
diff --git a/packages/e2e/next/src/app/app/repro-599/page.tsx b/packages/e2e/next/src/app/app/repro-599/page.tsx
deleted file mode 100644
index 80e824b51..000000000
--- a/packages/e2e/next/src/app/app/repro-599/page.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-'use client'
-
-import { parseAsString, useQueryState, useQueryStates } from 'nuqs'
-import { Suspense } from 'react'
-
-export default function Page() {
- return (
-
-
-
- )
-}
-
-const key = 'a &b?c=d#e%f+g"h\'i`jl(m)n*o,p.q:r;s/t'
-const parser = parseAsString.withDefault('')
-
-function Client() {
- const [a, setValue] = useQueryState(key, parser)
- const [{ [key]: b }] = useQueryStates({ [key]: parser })
- return (
- <>
- setValue(e.target.value)} />
- {b}
-
- >
- )
-}
diff --git a/packages/nuqs/package.json b/packages/nuqs/package.json
index 1f353b21e..fd61df73e 100644
--- a/packages/nuqs/package.json
+++ b/packages/nuqs/package.json
@@ -156,6 +156,7 @@
"@types/react": "catalog:react19",
"@types/react-dom": "catalog:react19",
"@vitejs/plugin-react": "^4.3.3",
+ "@vitest/coverage-v8": "^2.1.8",
"next": "15.0.3",
"react": "catalog:react19",
"react-dom": "catalog:react19",
diff --git a/packages/nuqs/src/useQueryState.test.ts b/packages/nuqs/src/useQueryState.test.ts
new file mode 100644
index 000000000..99b0741ba
--- /dev/null
+++ b/packages/nuqs/src/useQueryState.test.ts
@@ -0,0 +1,162 @@
+import { act, renderHook } from '@testing-library/react'
+import { describe, expect, it, vi } from 'vitest'
+import {
+ withNuqsTestingAdapter,
+ type OnUrlUpdateFunction
+} from './adapters/testing'
+import { parseAsArrayOf, parseAsJson, parseAsString } from './parsers'
+import { useQueryState } from './useQueryState'
+
+describe('useQueryState: referential equality', () => {
+ const defaults = {
+ str: 'foo',
+ obj: { initial: 'state' },
+ arr: [
+ {
+ initial: 'state'
+ }
+ ]
+ }
+
+ const useTestHookWithDefaults = (
+ { defaultValue } = { defaultValue: defaults.str }
+ ) => {
+ const str = useQueryState('str', parseAsString.withDefault(defaultValue))
+ const obj = useQueryState(
+ 'obj',
+ parseAsJson(x => x).withDefault(defaults.obj)
+ )
+ const arr = useQueryState(
+ 'arr',
+ parseAsArrayOf(parseAsJson(x => x)).withDefault(defaults.arr)
+ )
+ return { str, obj, arr }
+ }
+
+ it('should have referential equality on default values', () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter()
+ })
+ const { str, obj, arr } = result.current
+ expect(str[0]).toBe(defaults.str)
+ expect(obj[0]).toBe(defaults.obj)
+ expect(arr[0]).toBe(defaults.arr)
+ expect(arr[0][0]).toBe(defaults.arr[0])
+ })
+
+ it('should keep referential equality when resetting to defaults', async () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: {
+ str: 'foo',
+ obj: '{"hello":"world"}',
+ arr: '{"obj":true},{"arr":true}'
+ }
+ })
+ })
+ await act(() => {
+ const { str, arr, obj } = result.current
+ str[1](null)
+ obj[1](null)
+ return arr[1](null)
+ })
+ const { str, arr, obj } = result.current
+ expect(str[0]).toBe(defaults.str)
+ expect(obj[0]).toBe(defaults.obj)
+ expect(arr[0]).toBe(defaults.arr)
+ expect(arr[0][0]).toBe(defaults.arr[0])
+ })
+
+ it('should keep referential equality when unrelated keys change', async () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: {
+ str: 'foo',
+ obj: '{"hello":"world"}'
+ // Keep arr as default
+ }
+ })
+ })
+ const initialObj = result.current.obj[0]
+ const initialArr = result.current.arr[0]
+ await act(() => {
+ const { str } = result.current
+ return str[1]('bar')
+ })
+ const { str, obj, arr } = result.current
+ expect(str[0]).toBe('bar')
+ expect(obj[0]).toBe(initialObj)
+ expect(arr[0]).toBe(initialArr)
+ })
+
+ it('should keep referential equality when default changes for another key', () => {
+ const { result, rerender } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter()
+ })
+ expect(result.current.str[0]).toBe('foo')
+ rerender({ defaultValue: 'b' })
+ const { str, obj, arr } = result.current
+ expect(str[0]).toBe('b')
+ expect(obj[0]).toBe(defaults.obj)
+ expect(arr[0]).toBe(defaults.arr)
+ expect(arr[0][0]).toBe(defaults.arr[0])
+ })
+})
+
+describe('useQueryState: clearOnDefault', () => {
+ it('honors clearOnDefault: true by default', async () => {
+ const onUrlUpdate = vi.fn()
+ const { result } = renderHook(
+ () => useQueryState('test', parseAsString.withDefault('default')),
+ {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?test=init',
+ onUrlUpdate
+ })
+ }
+ )
+ await act(() => result.current[1]('default'))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('')
+ })
+
+ it('supports clearOnDefault: false (hook level)', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryState(
+ 'a',
+ parseAsString.withDefault('default').withOptions({
+ clearOnDefault: false
+ })
+ )
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?a=init',
+ onUrlUpdate
+ })
+ })
+ await act(() => result.current[1]('default'))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?a=default')
+ })
+
+ it('supports clearOnDefault: false (call level)', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryState(
+ 'a',
+ parseAsString.withDefault('default').withOptions({
+ clearOnDefault: true
+ })
+ )
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?a=init',
+ onUrlUpdate
+ })
+ })
+ await act(() => result.current[1]('default', { clearOnDefault: false }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?a=default')
+ })
+})
diff --git a/packages/nuqs/src/useQueryStates.test.ts b/packages/nuqs/src/useQueryStates.test.ts
new file mode 100644
index 000000000..a1b0958ef
--- /dev/null
+++ b/packages/nuqs/src/useQueryStates.test.ts
@@ -0,0 +1,235 @@
+import { act, renderHook } from '@testing-library/react'
+import { describe, expect, it, vi } from 'vitest'
+import {
+ withNuqsTestingAdapter,
+ type OnUrlUpdateFunction
+} from './adapters/testing'
+import { parseAsArrayOf, parseAsJson, parseAsString } from './parsers'
+import { useQueryStates } from './useQueryStates'
+
+describe('useQueryStates: referential equality', () => {
+ const defaults = {
+ str: 'foo',
+ obj: { initial: 'state' },
+ arr: [
+ {
+ initial: 'state'
+ }
+ ]
+ }
+
+ const useTestHookWithDefaults = (
+ { defaultValue } = { defaultValue: defaults.str }
+ ) => {
+ return useQueryStates({
+ str: parseAsString.withDefault(defaultValue),
+ obj: parseAsJson(x => x).withDefault(defaults.obj),
+ arr: parseAsArrayOf(parseAsJson(x => x)).withDefault(defaults.arr)
+ })
+ }
+
+ it('should have referential equality on default values', () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter()
+ })
+ const [state] = result.current
+ expect(state.str).toBe(defaults.str)
+ expect(state.obj).toBe(defaults.obj)
+ expect(state.arr).toBe(defaults.arr)
+ expect(state.arr[0]).toBe(defaults.arr[0])
+ })
+
+ it('should keep referential equality when resetting to defaults', async () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: {
+ str: 'foo',
+ obj: '{"hello":"world"}',
+ arr: '{"obj":true},{"arr":true}'
+ }
+ })
+ })
+ await act(() => result.current[1](null))
+ const [state] = result.current
+ expect(state.str).toBe(defaults.str)
+ expect(state.obj).toBe(defaults.obj)
+ expect(state.arr).toBe(defaults.arr)
+ expect(state.arr[0]).toBe(defaults.arr[0])
+ })
+
+ it('should keep referential equality when unrelated keys change', async () => {
+ const { result } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: {
+ str: 'foo',
+ obj: '{"hello":"world"}'
+ // Keep arr as default
+ }
+ })
+ })
+ const [{ obj: initialObj, arr: initialArr }] = result.current
+ await act(() => result.current[1]({ str: 'bar' }))
+ const [{ str, obj, arr }] = result.current
+ expect(str).toBe('bar')
+ expect(obj).toBe(initialObj)
+ expect(arr).toBe(initialArr)
+ })
+
+ it('should keep referential equality when default changes for another key', () => {
+ const { result, rerender } = renderHook(useTestHookWithDefaults, {
+ wrapper: withNuqsTestingAdapter()
+ })
+ expect(result.current[0].str).toBe('foo')
+ rerender({ defaultValue: 'b' })
+ const [state] = result.current
+ expect(state.str).toBe('b')
+ expect(state.obj).toBe(defaults.obj)
+ expect(state.arr).toBe(defaults.arr)
+ expect(state.arr[0]).toBe(defaults.arr[0])
+ })
+})
+
+describe('useQueryStates: urlKeys remapping', () => {
+ it('uses the object key names by default', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates({
+ foo: parseAsString,
+ bar: parseAsString
+ })
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?foo=init&bar=init',
+ onUrlUpdate
+ })
+ })
+ expect(result.current[0].foo).toEqual('init')
+ expect(result.current[0].bar).toEqual('init')
+ await act(() => result.current[1]({ foo: 'a', bar: 'b' }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?foo=a&bar=b')
+ })
+
+ it('allows remapping keys partially', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates(
+ {
+ foo: parseAsString,
+ bar: parseAsString
+ },
+ {
+ urlKeys: {
+ foo: 'f'
+ }
+ }
+ )
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?f=foo&bar=bar',
+ onUrlUpdate
+ })
+ })
+ expect(result.current[0].foo).toEqual('foo')
+ expect(result.current[0].bar).toEqual('bar')
+ await act(() => result.current[1]({ foo: 'a', bar: 'b' }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?f=a&bar=b')
+ })
+})
+
+describe('useQueryStates: clearOnDefault', () => {
+ it('honors clearOnDefault: true by default', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates({
+ test: parseAsString.withDefault('default')
+ })
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?test=init',
+ onUrlUpdate
+ })
+ })
+ await act(() => result.current[1]({ test: 'default' }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('')
+ })
+
+ it('supports clearOnDefault: false (parser level)', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates({
+ a: parseAsString.withDefault('default').withOptions({
+ clearOnDefault: false
+ }),
+ b: parseAsString.withDefault('default')
+ })
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?a=init&b=init',
+ onUrlUpdate
+ })
+ })
+ await act(() => result.current[1]({ a: 'default', b: 'default' }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?a=default')
+ })
+
+ it('supports clearOnDefault: false (hook level)', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates(
+ {
+ a: parseAsString.withDefault('default'),
+ b: parseAsString.withDefault('default').withOptions({
+ clearOnDefault: true // overrides hook options
+ })
+ },
+ {
+ clearOnDefault: false
+ }
+ )
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?a=init&b=init',
+ onUrlUpdate
+ })
+ })
+ await act(() => result.current[1]({ a: 'default', b: 'default' }))
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('?a=default')
+ })
+
+ it('supports clearOnDefault: false (call level)', async () => {
+ const onUrlUpdate = vi.fn()
+ const useTestHook = () =>
+ useQueryStates(
+ {
+ a: parseAsString.withDefault('default'),
+ b: parseAsString.withDefault('default').withOptions({
+ clearOnDefault: true // overrides hook options
+ })
+ },
+ {
+ clearOnDefault: false
+ }
+ )
+ const { result } = renderHook(useTestHook, {
+ wrapper: withNuqsTestingAdapter({
+ searchParams: '?a=init&b=init',
+ onUrlUpdate
+ })
+ })
+ await act(() =>
+ result.current[1](
+ { a: 'default', b: 'default' },
+ {
+ clearOnDefault: true
+ }
+ )
+ )
+ expect(onUrlUpdate).toHaveBeenCalledOnce()
+ expect(onUrlUpdate.mock.calls[0]![0].queryString).toEqual('')
+ })
+})
diff --git a/packages/nuqs/src/useQueryStates.test.tsx b/packages/nuqs/src/useQueryStates.test.tsx
deleted file mode 100644
index eda6b3623..000000000
--- a/packages/nuqs/src/useQueryStates.test.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { act, renderHook } from '@testing-library/react'
-import type { ReactNode } from 'react'
-import React from 'react'
-import { describe, expect, it } from 'vitest'
-import { NuqsTestingAdapter } from './adapters/testing'
-import { parseAsArrayOf, parseAsJson, parseAsString } from './parsers'
-import { useQueryStates } from './useQueryStates'
-
-function withSearchParams(
- searchParams?: string | URLSearchParams | Record
-) {
- return (props: { children: ReactNode }) => (
-
- )
-}
-
-const defaults = {
- str: 'foo',
- obj: { initial: 'state' },
- arr: [
- {
- initial: 'state'
- }
- ]
-}
-
-const hook = ({ defaultValue } = { defaultValue: defaults.str }) => {
- return useQueryStates({
- str: parseAsString.withDefault(defaultValue),
- obj: parseAsJson(x => x).withDefault(defaults.obj),
- arr: parseAsArrayOf(parseAsJson(x => x)).withDefault(defaults.arr)
- })
-}
-
-describe('useQueryStates', () => {
- it('should have referential equality on default values', () => {
- const { result } = renderHook(hook, {
- wrapper: NuqsTestingAdapter
- })
- const [state] = result.current
- expect(state.str).toBe(defaults.str)
- expect(state.obj).toBe(defaults.obj)
- expect(state.arr).toBe(defaults.arr)
- expect(state.arr[0]).toBe(defaults.arr[0])
- })
-
- it('should keep referential equality when resetting to defaults', () => {
- const { result } = renderHook(hook, {
- wrapper: withSearchParams({
- str: 'foo',
- obj: '{"hello":"world"}',
- arr: '{"obj":true},{"arr":true}'
- })
- })
- act(() => {
- result.current[1](null)
- })
- const [state] = result.current
- expect(state.str).toBe(defaults.str)
- expect(state.obj).toBe(defaults.obj)
- expect(state.arr).toBe(defaults.arr)
- expect(state.arr[0]).toBe(defaults.arr[0])
- })
-
- it('should keep referential equality when unrelated keys change', () => {
- const { result } = renderHook(hook, {
- wrapper: withSearchParams({
- str: 'foo',
- obj: '{"hello":"world"}'
- // Keep arr as default
- })
- })
- const [{ obj: initialObj, arr: initialArr }] = result.current
- act(() => {
- result.current[1]({ str: 'bar' })
- })
- const [{ str, obj, arr }] = result.current
- expect(str).toBe('bar')
- expect(obj).toBe(initialObj)
- expect(arr).toBe(initialArr)
- })
-
- it('should keep referential equality when default changes for another key', () => {
- const { result, rerender } = renderHook(hook, {
- wrapper: withSearchParams()
- })
- expect(result.current[0].str).toBe('foo')
- rerender({ defaultValue: 'b' })
- const [state] = result.current
- expect(state.str).toBe('b')
- expect(state.obj).toBe(defaults.obj)
- expect(state.arr).toBe(defaults.arr)
- expect(state.arr[0]).toBe(defaults.arr[0])
- })
-})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 59676037d..1fa3de811 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -526,9 +526,12 @@ importers:
'@vitejs/plugin-react':
specifier: ^4.3.3
version: 4.3.3(vite@5.4.11(@types/node@22.9.0)(lightningcss@1.27.0)(terser@5.34.1))
+ '@vitest/coverage-v8':
+ specifier: ^2.1.8
+ version: 2.1.8(vitest@2.1.5(@types/node@22.9.0)(jsdom@25.0.1)(lightningcss@1.27.0)(terser@5.34.1))
next:
specifier: 15.0.3
- version: 15.0.3(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@19.0.0-beta-a7bf2bd-20241110)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+ version: 15.0.3(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react:
specifier: catalog:react19
version: 19.0.0
@@ -752,6 +755,9 @@ packages:
resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==}
engines: {node: '>=6.9.0'}
+ '@bcoe/v8-coverage@0.2.3':
+ resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+
'@colors/colors@1.5.0':
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
engines: {node: '>=0.1.90'}
@@ -1765,6 +1771,10 @@ packages:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
+ '@istanbuljs/schema@0.1.3':
+ resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+ engines: {node: '>=8'}
+
'@jest/schemas@29.6.3':
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -3524,6 +3534,15 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0
+ '@vitest/coverage-v8@2.1.8':
+ resolution: {integrity: sha512-2Y7BPlKH18mAZYAW1tYByudlCYrQyl5RGvnnDYJKW5tCiO5qg3KSAy3XAxcxKz900a0ZXxWtKrMuZLe3lKBpJw==}
+ peerDependencies:
+ '@vitest/browser': 2.1.8
+ vitest: 2.1.8
+ peerDependenciesMeta:
+ '@vitest/browser':
+ optional: true
+
'@vitest/expect@2.1.5':
resolution: {integrity: sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==}
@@ -5471,6 +5490,9 @@ packages:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
+ html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
@@ -5850,6 +5872,22 @@ packages:
resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==}
engines: {node: ^18.17 || >=20.6.1}
+ istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-source-maps@5.0.6:
+ resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
+ engines: {node: '>=10'}
+
+ istanbul-reports@3.1.7:
+ resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
+ engines: {node: '>=8'}
+
iterator.prototype@1.1.3:
resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==}
engines: {node: '>= 0.4'}
@@ -6221,9 +6259,6 @@ packages:
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
hasBin: true
- magic-string@0.30.11:
- resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
-
magic-string@0.30.12:
resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
@@ -6231,6 +6266,13 @@ packages:
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
engines: {node: '>=12'}
+ magicast@0.3.5:
+ resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
+
+ make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
@@ -8352,6 +8394,10 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ test-exclude@7.0.1:
+ resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
+ engines: {node: '>=18'}
+
text-extensions@2.4.0:
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
engines: {node: '>=8'}
@@ -9368,6 +9414,8 @@ snapshots:
'@babel/helper-validator-identifier': 7.25.7
to-fast-properties: 2.0.0
+ '@bcoe/v8-coverage@0.2.3': {}
+
'@colors/colors@1.5.0':
optional: true
@@ -10070,6 +10118,8 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
+ '@istanbuljs/schema@0.1.3': {}
+
'@jest/schemas@29.6.3':
dependencies:
'@sinclair/typebox': 0.27.8
@@ -11414,7 +11464,7 @@ snapshots:
estree-walker: 2.0.2
glob: 10.4.5
is-reference: 1.2.1
- magic-string: 0.30.11
+ magic-string: 0.30.12
optionalDependencies:
rollup: 3.29.5
@@ -12323,6 +12373,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@vitest/coverage-v8@2.1.8(vitest@2.1.5(@types/node@22.9.0)(jsdom@25.0.1)(lightningcss@1.27.0)(terser@5.34.1))':
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@bcoe/v8-coverage': 0.2.3
+ debug: 4.3.7(supports-color@8.1.1)
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-report: 3.0.1
+ istanbul-lib-source-maps: 5.0.6
+ istanbul-reports: 3.1.7
+ magic-string: 0.30.12
+ magicast: 0.3.5
+ std-env: 3.8.0
+ test-exclude: 7.0.1
+ tinyrainbow: 1.2.0
+ vitest: 2.1.5(@types/node@22.9.0)(jsdom@25.0.1)(lightningcss@1.27.0)(terser@5.34.1)
+ transitivePeerDependencies:
+ - supports-color
+
'@vitest/expect@2.1.5':
dependencies:
'@vitest/spy': 2.1.5
@@ -14771,6 +14839,8 @@ snapshots:
dependencies:
whatwg-encoding: 3.1.1
+ html-escaper@2.0.2: {}
+
html-void-elements@3.0.0: {}
htmlparser2@8.0.2:
@@ -15099,6 +15169,27 @@ snapshots:
lodash.isstring: 4.0.1
lodash.uniqby: 4.7.0
+ istanbul-lib-coverage@3.2.2: {}
+
+ istanbul-lib-report@3.0.1:
+ dependencies:
+ istanbul-lib-coverage: 3.2.2
+ make-dir: 4.0.0
+ supports-color: 7.2.0
+
+ istanbul-lib-source-maps@5.0.6:
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ debug: 4.3.7(supports-color@8.1.1)
+ istanbul-lib-coverage: 3.2.2
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-reports@3.1.7:
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.1
+
iterator.prototype@1.1.3:
dependencies:
define-properties: 1.2.1
@@ -15438,10 +15529,6 @@ snapshots:
lz-string@1.5.0: {}
- magic-string@0.30.11:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.0
-
magic-string@0.30.12:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
@@ -15450,6 +15537,16 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
+ magicast@0.3.5:
+ dependencies:
+ '@babel/parser': 7.25.7
+ '@babel/types': 7.25.7
+ source-map-js: 1.2.1
+
+ make-dir@4.0.0:
+ dependencies:
+ semver: 7.6.3
+
make-error@1.3.6: {}
map-obj@1.0.1: {}
@@ -16393,6 +16490,32 @@ snapshots:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
+ next@15.0.3(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
+ dependencies:
+ '@next/env': 15.0.3
+ '@swc/counter': 0.1.3
+ '@swc/helpers': 0.5.13
+ busboy: 1.6.0
+ caniuse-lite: 1.0.30001667
+ postcss: 8.4.31
+ react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
+ styled-jsx: 5.1.6(@babel/core@7.25.7)(react@19.0.0)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 15.0.3
+ '@next/swc-darwin-x64': 15.0.3
+ '@next/swc-linux-arm64-gnu': 15.0.3
+ '@next/swc-linux-arm64-musl': 15.0.3
+ '@next/swc-linux-x64-gnu': 15.0.3
+ '@next/swc-linux-x64-musl': 15.0.3
+ '@next/swc-win32-arm64-msvc': 15.0.3
+ '@next/swc-win32-x64-msvc': 15.0.3
+ '@opentelemetry/api': 1.9.0
+ sharp: 0.33.5
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+
next@15.0.3(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@19.0.0-beta-a7bf2bd-20241110)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
'@next/env': 15.0.3
@@ -16403,7 +16526,7 @@ snapshots:
postcss: 8.4.31
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
- styled-jsx: 5.1.6(react@19.0.0)
+ styled-jsx: 5.1.6(@babel/core@7.25.7)(react@19.0.0)
optionalDependencies:
'@next/swc-darwin-arm64': 15.0.3
'@next/swc-darwin-x64': 15.0.3
@@ -17992,10 +18115,12 @@ snapshots:
dependencies:
inline-style-parser: 0.2.4
- styled-jsx@5.1.6(react@19.0.0):
+ styled-jsx@5.1.6(@babel/core@7.25.7)(react@19.0.0):
dependencies:
client-only: 0.0.1
react: 19.0.0
+ optionalDependencies:
+ '@babel/core': 7.25.7
sucrase@3.35.0:
dependencies:
@@ -18126,6 +18251,12 @@ snapshots:
commander: 2.20.3
source-map-support: 0.5.21
+ test-exclude@7.0.1:
+ dependencies:
+ '@istanbuljs/schema': 0.1.3
+ glob: 10.4.5
+ minimatch: 9.0.5
+
text-extensions@2.4.0: {}
text-table@0.2.0: {}