diff --git a/packages/docs/content/docs/parsers/built-in.mdx b/packages/docs/content/docs/parsers/built-in.mdx index c23c3c968..9dda246b9 100644 --- a/packages/docs/content/docs/parsers/built-in.mdx +++ b/packages/docs/content/docs/parsers/built-in.mdx @@ -30,8 +30,8 @@ This is where **parsers** come in. import { parseAsString } from 'nuqs' ``` -}> - +}> + @@ -40,6 +40,7 @@ and will accept **any** value. If you're expecting a certain set of string values, like `'foo' | 'bar'{:ts}`, see [Literals](#literals) for ensuring type-runtime safety. + If search params are strings by default, what's the point of this _"parser"_ ? @@ -68,11 +69,10 @@ import { parseAsInteger } from 'nuqs' useQueryState('int', parseAsInteger.withDefault(0)) ``` -}> - +}> + - ### Floating point Same as integer, but uses `parseFloat` under the hood. @@ -83,11 +83,10 @@ import { parseAsFloat } from 'nuqs' useQueryState('float', parseAsFloat.withDefault(0)) ``` -}> - +}> + - ### Hexadecimal Encodes integers in hexadecimal. @@ -98,12 +97,12 @@ import { parseAsHex } from 'nuqs' useQueryState('hex', parseAsHex.withDefault(0x00)) ``` -}> - +}> + - Check out the [Hex Colors](/playground/hex-colors) playground for a demo. + Check out the [Hex Colors](/playground/hex-colors) playground for a demo. ## Boolean @@ -114,8 +113,8 @@ import { parseAsBoolean } from 'nuqs' useQueryState('bool', parseAsBoolean.withDefault(false)) ``` -}> - +}> + ## Literals @@ -139,14 +138,13 @@ const sortOrder = ['asc', 'desc'] as const parseAsStringLiteral(sortOrder) // Optional: extract the type from them -type SortOrder = (typeof sortOrder)[number]; // 'asc' | 'desc' +type SortOrder = (typeof sortOrder)[number] // 'asc' | 'desc' ``` -}> - +}> + - ### Numeric literals ```ts /as const/ @@ -175,8 +173,8 @@ parseAsStringEnum(Object.values(Direction)) ``` -The query string value will be the **value** of the enum, not its name -(here: `?direction=UP`). + The query string value will be the **value** of the enum, not its name (here: + `?direction=UP`). ## Dates & timestamps @@ -191,17 +189,19 @@ import { parseAsIsoDateTime } from 'nuqs' ``` - + ### ISO 8601 Date +Note: the Date is parsed without the time zone offset, making it at GMT 00:00:00 UTC. + ```ts import { parseAsIsoDate } from 'nuqs' ``` - + ### Timestamp @@ -213,7 +213,7 @@ import { parseAsTimestamp } from 'nuqs' ``` - + ## Arrays @@ -252,14 +252,14 @@ const schema = z.object({ const [json, setJson] = useQueryState('json', parseAsJson(schema.parse)) setJson({ - pkg: "nuqs", + pkg: 'nuqs', version: 2, - worksWith: ["Next.js", "React", "Remix", "React Router", "and more"], -}); + worksWith: ['Next.js', 'React', 'Remix', 'React Router', 'and more'] +}) ``` - + Using other validation libraries is possible, as long as they throw an error @@ -275,6 +275,6 @@ import { parseAsString } from 'nuqs/server' ``` -It used to be available under the alias import `nuqs/parsers`, -which will be dropped in the next major version. + It used to be available under the alias import `nuqs/parsers`, which will be + dropped in the next major version. diff --git a/packages/docs/content/docs/parsers/demos.tsx b/packages/docs/content/docs/parsers/demos.tsx index fb4242713..4f2132a7d 100644 --- a/packages/docs/content/docs/parsers/demos.tsx +++ b/packages/docs/content/docs/parsers/demos.tsx @@ -247,10 +247,12 @@ export function StringLiteralParserDemo() { export function DateParserDemo({ queryKey, - parser + parser, + type }: { queryKey: string parser: ParserBuilder + type: 'date' | 'datetime-local' }) { const [value, setValue] = useQueryState(queryKey, parser) return ( @@ -258,7 +260,7 @@ export function DateParserDemo({
{ @@ -292,15 +294,29 @@ export function DateParserDemo({ } export function DatetimeISOParserDemo() { - return + return ( + + ) } export function DateISOParserDemo() { - return + return ( + + ) } export function DateTimestampParserDemo() { - return + return ( + + ) } const jsonParserSchema = z.object({ diff --git a/packages/nuqs/src/parsers.test.ts b/packages/nuqs/src/parsers.test.ts index 027c6bf11..74d9d3d0c 100644 --- a/packages/nuqs/src/parsers.test.ts +++ b/packages/nuqs/src/parsers.test.ts @@ -55,9 +55,7 @@ describe('parsers', () => { const moment = '2020-01-01' const ref = new Date(moment) expect(parseAsIsoDate.parse(moment)).toStrictEqual(ref) - expect(parseAsIsoDate.parse(moment.slice(0, 10))).toStrictEqual(ref) - expect(parseAsIsoDate.serialize(ref).length).toBe(10) - expect(parseAsIsoDate.serialize(ref).length).not.toContain('T') + expect(parseAsIsoDate.serialize(ref)).toEqual(moment) }) test('parseAsArrayOf', () => { const parser = parseAsArrayOf(parseAsString) diff --git a/packages/nuqs/src/parsers.ts b/packages/nuqs/src/parsers.ts index ecaf7a40a..735687fb1 100644 --- a/packages/nuqs/src/parsers.ts +++ b/packages/nuqs/src/parsers.ts @@ -219,10 +219,13 @@ export const parseAsIsoDateTime = createParser({ * Querystring encoded as an ISO-8601 string (UTC) * without the time zone offset, and returned as * a Date object. + * + * The Date is parsed without the time zone offset, + * making it at GMT 00:00:00 UTC. */ export const parseAsIsoDate = createParser({ parse: v => { - const date = new Date(v + 'T00:00:00.000Z') + const date = new Date(v.slice(0, 10)) if (Number.isNaN(date.valueOf())) { return null }