Skip to content

Presets Reference

All presets are imported from @vp-tw/nanostores-qs/presets. Every preset is a function that accepts an options object.

import * as presets from "@vp-tw/nanostores-qs/presets";

All built-in presets accept these options:

OptionTypeDescription
optionaltrueValue becomes T | undefined (no defaultValue)
defaultTOverride the type’s inherent default
arraytrueArray variant using multiple same-name params
maxItemsnumberCap on array items (only with array: true)

These options are mutually exclusive — pass exactly one of optional, default, or array (or none for the base variant).

presets.integer() and presets.float() support { numInput: true, default: n }. In this mode:

  • $value holds a string (bindable to <input>)
  • $resolved holds a number (parsed + validated, falls back to default on invalid input)
  • Clearing the input sets $value to "", and $resolved maps it to the default

This is useful for number inputs where the raw string must be preserved during editing (e.g., typing "19." should not immediately normalize to "19").

CallValue TypeDefault
presets.string()string""
presets.string({ optional: true })string | undefinedundefined
presets.string({ default: "all" })string"all"
presets.string({ array: true })Array<string>[]
OptionTypeDefaultDescription
maxLengthnumberMaximum string length
outOfRange"clamp" | "reject""clamp"Truncate or reject strings exceeding max
$values
{
  base: '',
  maxLen: '',
  optional: undefined
}
URL
(empty)
CallValue TypeDefault
presets.integer()numberNaN
presets.integer({ optional: true })number | undefinedundefined
presets.integer({ default: 1 })number1
presets.integer({ array: true })Array<number>[]
presets.integer({ numInput: true, default: 1 })NumInputResult""
OptionTypeDefaultDescription
round"round" | "ceil" | "floor" | "parse""round"Rounding mode ("parse" uses parseInt)
minnumberNumber.MIN_SAFE_INTEGERMinimum allowed value
maxnumberNumber.MAX_SAFE_INTEGERMaximum allowed value
outOfRange"clamp" | "reject""clamp"Clamp to range or reject out-of-range values
numInputtrueInput binding mode: $value is string, $resolved is number. Requires default

When outOfRange is "reject":

  • Decode (URL → store): out-of-range values throw → falls back to defaultValue (or undefined for optional)
  • Encode (store → URL): out-of-range values throw → parameter is removed from URL
integer() — round
integer({ round: "ceil" })
integer({ round: "parse" })
integer({ min: 0, max: 100 }) — clamp
integer({ ..., outOfRange: "reject" })
Input URL
(empty)
$values (decoded)
{
  round: NaN,
  ceil: NaN,
  parse: NaN,
  clamped: NaN,
  reject: NaN
}
Output URL
(empty)
CallValue TypeDefault
presets.float()numberNaN
presets.float({ optional: true })number | undefinedundefined
presets.float({ default: 0 })number0
presets.float({ array: true })Array<number>[]
presets.float({ numInput: true, default: 0 })NumInputResult""
OptionTypeDefaultDescription
fixednumberDecimal places (uses toFixed(n))
minnumber-InfinityMinimum allowed value
maxnumberInfinityMaximum allowed value
outOfRange"clamp" | "reject""clamp"Clamp to range or reject out-of-range values
numInputtrueInput binding mode: $value is string, $resolved is number. Requires default
float()
float({ fixed: 2 })
float({ fixed: 2, min: 0, max: 1 })
Input URL
(empty)
$values (decoded)
{
  base: NaN,
  fixed2: NaN,
  clamped: NaN
}
Output URL
(empty)
CallValue TypeDefault
presets.boolean()booleanfalse
presets.boolean({ optional: true })boolean | undefinedundefined
presets.boolean({ default: true })booleantrue
presets.boolean({ array: true })Array<boolean>[]

All variants use strict decode: only "true" and "false" are accepted. Any other value throws and falls back to defaultValue (or undefined for optional, filtered out for array).

  • Base (boolean()): default is false. Invalid → fallback to false. Encode omits value when it equals defaultValue.
  • boolean({ default: true }): default is true. Invalid → fallback to true. Encode omits true (the default), so false appears in URL — the encode logic flips compared to boolean().
  • Optional (boolean({ optional: true })): Invalid → fallback to undefined. Both "true" and "false" appear in URL; omitted means undefined.
$values
{
  base: false,
  defTrue: true,
  opt: undefined
}
URL
(empty)
CallValue TypeDefault
presets.enum(sortOptions)"newest" | "oldest" | "popular""newest"
presets.enum(sortOptions, { optional: true })... | undefinedundefined
presets.enum(sortOptions, { default: "popular" })same union"popular"
presets.enum(sortOptions, { array: true })Array<...>[]

The first element of enumArray is the inherent default. Invalid values throw (fall back to default in base, filtered out in array).

$values
{
  base: 'newest',
  optional: undefined,
  array: []
}
URL
(empty)
CallValue TypeDefault
presets.date()Datenew Date(NaN)
presets.date({ optional: true })Date | undefinedundefined
presets.date({ default: d })Dated
presets.date({ array: true })Array<Date>[]

Decode: new Date(String(value)), throws if getTime() is NaN. Encode: value.toISOString(). Guards against Invalid Date — returns undefined if the date is invalid, preventing RangeError from toISOString().

date()
date({ optional: true })
Input URL
(empty)
$values (decoded)
{
  base: Invalid Date,
  optional: undefined
}
Output URL
(empty)
CallValue TypeDefault
presets.ymd()string"0000-00-00"
presets.ymd({ optional: true })string | undefinedundefined
presets.ymd({ array: true })Array<string>[]

Format: YYYY-MM-DD. Validates both format and semantic correctness — rejects values like "2024-13-01" or "2024-02-30" that aren’t real calendar dates.

The default value "0000-00-00" is an intentional sentinel (like NaN for integer) — it signals “no date selected”. Use { optional: true } if you prefer undefined.

$values
{
  base: '0000-00-00',
  optional: undefined
}
URL
(empty)
CallValue TypeDefault
presets.hms()string"00:00:00"
presets.hms({ optional: true })string | undefinedundefined
presets.hms({ array: true })Array<string>[]

Format: HH:mm:ss. Validates hour 00-23, minute/second 00-59.

$values
{
  base: '00:00:00',
  optional: undefined
}
URL
(empty)

Combines multiple preset configs into a single array parameter. No optional, default, or array modifiers. Decode: each element decoded independently with its config. If an element throws, only that element falls back to its own defaultValue — other elements are unaffected.

tuple([float()]) — single
tuple([float(), float()]) — pair
tuple([string(), integer({ numInput, default: 0 }), boolean()]) — mixed with resolve
Input URL
(empty)
$value (decoded)
scale:  [ NaN ]
coord:  [ NaN, NaN ]
filter: [ '', '', false ]
$resolved (filter)
[ '', 0, false ]
Output URL
scale:  (empty)
coord:  (empty)
filter: (empty)

Use createPreset to build your own preset function with the same options API. See Custom Presets for live examples with enum validation and decimal.js.