'use strict'; var chunkKNSPBEHI_cjs = require('./chunk-KNSPBEHI.cjs'); var Mitt = require('mitt'); var navigation_js = require('next/navigation.js'); var React2 = require('react'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var Mitt__default = /*#__PURE__*/_interopDefault(Mitt); var React2__default = /*#__PURE__*/_interopDefault(React2); // src/deprecated.ts var queryTypes = { /** * @deprecated use `parseAsString` instead. */ string: chunkKNSPBEHI_cjs.parseAsString, /** * @deprecated use `parseAsInteger` instead. */ integer: chunkKNSPBEHI_cjs.parseAsInteger, /** * @deprecated use `parseAsFloat` instead. */ float: chunkKNSPBEHI_cjs.parseAsFloat, /** * @deprecated use `parseAsBoolean` instead. */ boolean: chunkKNSPBEHI_cjs.parseAsBoolean, /** * @deprecated use `parseAsTimestamp` instead. */ timestamp: chunkKNSPBEHI_cjs.parseAsTimestamp, /** * @deprecated use `parseAsIsoDateTime` instead. */ isoDateTime: chunkKNSPBEHI_cjs.parseAsIsoDateTime, /** * @deprecated use `parseAsStringEnum` instead. */ stringEnum: chunkKNSPBEHI_cjs.parseAsStringEnum, /** * @deprecated use `parseAsJson` instead. */ json: chunkKNSPBEHI_cjs.parseAsJson, /** * @deprecated use `parseAsArrayOf` instead. */ array: chunkKNSPBEHI_cjs.parseAsArrayOf }; // src/update-queue.ts var FLUSH_RATE_LIMIT_MS = chunkKNSPBEHI_cjs.getDefaultThrottle(); var updateQueue = /* @__PURE__ */ new Map(); var queueOptions = { history: "replace", scroll: false, shallow: true, throttleMs: FLUSH_RATE_LIMIT_MS }; var transitionsQueue = /* @__PURE__ */ new Set(); var lastFlushTimestamp = 0; var flushPromiseCache = null; function enqueueQueryStringUpdate(key, value, serialize, options) { const serializedOrNull = value === null ? null : serialize(value); chunkKNSPBEHI_cjs.debug("[nuqs queue] Enqueueing %s=%s %O", key, serializedOrNull, options); updateQueue.set(key, serializedOrNull); if (options.history === "push") { queueOptions.history = "push"; } if (options.scroll) { queueOptions.scroll = true; } if (options.shallow === false) { queueOptions.shallow = false; } if (options.startTransition) { transitionsQueue.add(options.startTransition); queueOptions.shallow = false; } queueOptions.throttleMs = Math.max( options.throttleMs ?? FLUSH_RATE_LIMIT_MS, Number.isFinite(queueOptions.throttleMs) ? queueOptions.throttleMs : 0 ); return serializedOrNull; } function getQueuedValue(key) { return updateQueue.get(key) ?? null; } function scheduleFlushToURL(router) { if (flushPromiseCache === null) { flushPromiseCache = new Promise((resolve, reject) => { if (!Number.isFinite(queueOptions.throttleMs)) { chunkKNSPBEHI_cjs.debug("[nuqs queue] Skipping flush due to throttleMs=Infinity"); resolve(new URLSearchParams(location.search)); setTimeout(() => { flushPromiseCache = null; }, 0); return; } function flushNow() { lastFlushTimestamp = performance.now(); const [search, error2] = flushUpdateQueue(router); if (error2 === null) { resolve(search); } else { reject(search); } flushPromiseCache = null; } function runOnNextTick() { const now = performance.now(); const timeSinceLastFlush = now - lastFlushTimestamp; const throttleMs = queueOptions.throttleMs; const flushInMs = Math.max( 0, Math.min(throttleMs, throttleMs - timeSinceLastFlush) ); chunkKNSPBEHI_cjs.debug( "[nuqs queue] Scheduling flush in %f ms. Throttled at %f ms", flushInMs, throttleMs ); if (flushInMs === 0) { flushNow(); } else { setTimeout(flushNow, flushInMs); } } setTimeout(runOnNextTick, 0); }); } return flushPromiseCache; } function flushUpdateQueue(router) { const search = new URLSearchParams(location.search); if (updateQueue.size === 0) { return [search, null]; } const items = Array.from(updateQueue.entries()); const options = { ...queueOptions }; const transitions = Array.from(transitionsQueue); updateQueue.clear(); transitionsQueue.clear(); queueOptions.history = "replace"; queueOptions.scroll = false; queueOptions.shallow = true; queueOptions.throttleMs = FLUSH_RATE_LIMIT_MS; chunkKNSPBEHI_cjs.debug("[nuqs queue] Flushing queue %O with options %O", items, options); for (const [key, value] of items) { if (value === null) { search.delete(key); } else { search.set(key, value); } } try { const nextRouter = window.next?.router; const isPagesRouter = typeof nextRouter?.state?.asPath === "string"; if (isPagesRouter) { const url = renderURL(nextRouter.state.asPath.split("?")[0] ?? "", search); chunkKNSPBEHI_cjs.debug("[nuqs queue (pages)] Updating url: %s", url); const method = options.history === "push" ? nextRouter.push : nextRouter.replace; method.call(nextRouter, url, url, { scroll: options.scroll, shallow: options.shallow }); } else { const url = renderURL(location.origin + location.pathname, search); chunkKNSPBEHI_cjs.debug("[nuqs queue (app)] Updating url: %s", url); const updateMethod = options.history === "push" ? history.pushState : history.replaceState; const state = (window.next?.version ?? "") >= "14.1.0" ? null : history.state; updateMethod.call( history, state, // Our own updates have a marker to prevent syncing // when the URL changes (we've already sync'd them up // via `emitter.emit(key, newValue)` above, without // going through the parsers). NOSYNC_MARKER, url ); if (options.scroll) { window.scrollTo(0, 0); } if (!options.shallow) { compose(transitions, () => { router.replace(url, { scroll: false }); }); } } return [search, null]; } catch (err) { console.error(chunkKNSPBEHI_cjs.error(429), items.map(([key]) => key).join(), err); return [search, err]; } } function renderURL(base, search) { const hashlessBase = base.split("#")[0] ?? ""; const query = chunkKNSPBEHI_cjs.renderQueryString(search); const hash = location.hash; return hashlessBase + query + hash; } function compose(fns, final) { const recursiveCompose = (index) => { if (index === fns.length) { return final(); } const fn = fns[index]; if (!fn) { throw new Error("Invalid transition function"); } fn(() => recursiveCompose(index + 1)); }; recursiveCompose(0); } // src/sync.ts var SYNC_EVENT_KEY = Symbol("__nuqs__SYNC__"); var NOSYNC_MARKER = "__nuqs__NO_SYNC__"; var NOTIFY_EVENT_KEY = Symbol("__nuqs__NOTIFY__"); var emitter = Mitt__default.default(); function subscribeToQueryUpdates(callback) { emitter.on(NOTIFY_EVENT_KEY, callback); return () => emitter.off(NOTIFY_EVENT_KEY, callback); } if (typeof history === "object") { patchHistory(); } function patchHistory() { const version = "1.20.0"; const patched = history.__nuqs_patched; if (patched) { if (patched !== version) { console.error(chunkKNSPBEHI_cjs.error(409), patched, version); } return; } chunkKNSPBEHI_cjs.debug("[nuqs] Patching history with %s", version); for (const method of ["pushState", "replaceState"]) { const original = history[method].bind(history); history[method] = function nuqs_patchedHistory(state, title, url) { if (!url) { chunkKNSPBEHI_cjs.debug("[nuqs] history.%s(null) (%s) %O", method, title, state); return original(state, title, url); } const source = title === NOSYNC_MARKER ? "internal" : "external"; const search = new URL(url, location.origin).searchParams; chunkKNSPBEHI_cjs.debug("[nuqs] history.%s(%s) (%s) %O", method, url, source, state); if (source === "external") { for (const [key, value] of search.entries()) { const queueValue = getQueuedValue(key); if (queueValue !== null && queueValue !== value) { chunkKNSPBEHI_cjs.debug( "[nuqs] Overwrite detected for key: %s, Server: %s, queue: %s", key, value, queueValue ); search.set(key, queueValue); } } setTimeout(() => { chunkKNSPBEHI_cjs.debug( "[nuqs] External history.%s call: triggering sync with %s", method, search ); emitter.emit(SYNC_EVENT_KEY, search); emitter.emit(NOTIFY_EVENT_KEY, { search, source }); }, 0); } else { setTimeout(() => { emitter.emit(NOTIFY_EVENT_KEY, { search, source }); }, 0); } return original(state, title === NOSYNC_MARKER ? "" : title, url); }; } Object.defineProperty(history, "__nuqs_patched", { value: version, writable: false, enumerable: false, configurable: false }); } function useQueryState(key, { history: history2 = "replace", shallow = true, scroll = false, throttleMs = FLUSH_RATE_LIMIT_MS, parse = (x) => x, serialize = String, eq = (a, b) => a === b, defaultValue = void 0, clearOnDefault = false, startTransition } = { history: "replace", scroll: false, shallow: true, throttleMs: FLUSH_RATE_LIMIT_MS, parse: (x) => x, serialize: String, eq: (a, b) => a === b, clearOnDefault: false, defaultValue: void 0 }) { const router = navigation_js.useRouter(); const initialSearchParams = navigation_js.useSearchParams(); const queryRef = React2__default.default.useRef(null); const [internalState, setInternalState] = React2__default.default.useState(() => { const queueValue = getQueuedValue(key); const urlValue = initialSearchParams?.get(key) ?? null; const value = queueValue ?? urlValue; queryRef.current = value; return value === null ? null : chunkKNSPBEHI_cjs.safeParse(parse, value, key); }); const stateRef = React2__default.default.useRef(internalState); chunkKNSPBEHI_cjs.debug( "[nuqs `%s`] render - state: %O, iSP: %s", key, internalState, initialSearchParams?.get(key) ?? null ); React2__default.default.useEffect(() => { if (window.next?.version !== "14.0.3") { return; } const query = initialSearchParams.get(key) ?? null; if (query === queryRef.current) { return; } const state = query === null ? null : chunkKNSPBEHI_cjs.safeParse(parse, query, key); chunkKNSPBEHI_cjs.debug("[nuqs `%s`] syncFromUseSearchParams %O", key, state); stateRef.current = state; queryRef.current = query; setInternalState(state); }, [initialSearchParams?.get(key), key]); React2__default.default.useInsertionEffect(() => { function updateInternalState({ state, query }) { chunkKNSPBEHI_cjs.debug("[nuqs `%s`] updateInternalState %O", key, state); stateRef.current = state; queryRef.current = query; setInternalState(state); } function syncFromURL(search) { const query = search.get(key); if (query === queryRef.current) { return; } const state = query === null ? null : chunkKNSPBEHI_cjs.safeParse(parse, query, key); chunkKNSPBEHI_cjs.debug("[nuqs `%s`] syncFromURL %O", key, state); updateInternalState({ state, query }); } chunkKNSPBEHI_cjs.debug("[nuqs `%s`] subscribing to sync", key); emitter.on(SYNC_EVENT_KEY, syncFromURL); emitter.on(key, updateInternalState); return () => { chunkKNSPBEHI_cjs.debug("[nuqs `%s`] unsubscribing from sync", key); emitter.off(SYNC_EVENT_KEY, syncFromURL); emitter.off(key, updateInternalState); }; }, [key]); const update = React2__default.default.useCallback( (stateUpdater, options = {}) => { let newValue = isUpdaterFunction(stateUpdater) ? stateUpdater(stateRef.current ?? defaultValue ?? null) : stateUpdater; if ((options.clearOnDefault ?? clearOnDefault) && newValue !== null && defaultValue !== void 0 && eq(newValue, defaultValue)) { newValue = null; } queryRef.current = enqueueQueryStringUpdate(key, newValue, serialize, { // Call-level options take precedence over hook declaration options. history: options.history ?? history2, shallow: options.shallow ?? shallow, scroll: options.scroll ?? scroll, throttleMs: options.throttleMs ?? throttleMs, startTransition: options.startTransition ?? startTransition }); emitter.emit(key, { state: newValue, query: queryRef.current }); return scheduleFlushToURL(router); }, [key, history2, shallow, scroll, throttleMs, startTransition] ); return [internalState ?? defaultValue ?? null, update]; } function isUpdaterFunction(stateUpdater) { return typeof stateUpdater === "function"; } var defaultUrlKeys = {}; function useQueryStates(keyMap, { history: history2 = "replace", scroll = false, shallow = true, throttleMs = FLUSH_RATE_LIMIT_MS, clearOnDefault = false, startTransition, urlKeys = defaultUrlKeys } = {}) { const stateKeys = Object.keys(keyMap).join(","); const resolvedUrlKeys = React2__default.default.useMemo( () => Object.fromEntries( Object.keys(keyMap).map((key) => [key, urlKeys[key] ?? key]) ), [stateKeys, urlKeys] ); const router = navigation_js.useRouter(); const initialSearchParams = navigation_js.useSearchParams(); const queryRef = React2__default.default.useRef({}); const [internalState, setInternalState] = React2__default.default.useState(() => { const source = initialSearchParams ?? new URLSearchParams(); queryRef.current = Object.fromEntries(source.entries()); return parseMap(keyMap, urlKeys, source); }); const stateRef = React2__default.default.useRef(internalState); chunkKNSPBEHI_cjs.debug( "[nuq+ `%s`] render - state: %O, iSP: %s", stateKeys, internalState, initialSearchParams ); React2__default.default.useEffect(() => { if (window.next?.version !== "14.0.3") { return; } const state = parseMap( keyMap, urlKeys, initialSearchParams, queryRef.current, stateRef.current ); setInternalState(state); }, [ Object.keys(resolvedUrlKeys).map((key) => initialSearchParams?.get(key)).join("&"), stateKeys ]); React2__default.default.useInsertionEffect(() => { function updateInternalState(state) { chunkKNSPBEHI_cjs.debug("[nuq+ `%s`] updateInternalState %O", stateKeys, state); stateRef.current = state; setInternalState(state); } function syncFromURL(search) { const state = parseMap( keyMap, urlKeys, search, queryRef.current, stateRef.current ); chunkKNSPBEHI_cjs.debug("[nuq+ `%s`] syncFromURL %O", stateKeys, state); updateInternalState(state); } const handlers = Object.keys(keyMap).reduce( (handlers2, stateKey) => { handlers2[stateKey] = ({ state, query }) => { const { defaultValue } = keyMap[stateKey]; const urlKey = resolvedUrlKeys[stateKey]; stateRef.current = { ...stateRef.current, [stateKey]: state ?? defaultValue ?? null }; queryRef.current[urlKey] = query; chunkKNSPBEHI_cjs.debug( "[nuq+ `%s`] Cross-hook key sync %s: %O (default: %O). Resolved: %O", stateKeys, urlKey, state, defaultValue, stateRef.current ); updateInternalState(stateRef.current); }; return handlers2; }, {} ); emitter.on(SYNC_EVENT_KEY, syncFromURL); for (const stateKey of Object.keys(keyMap)) { const urlKey = resolvedUrlKeys[stateKey]; chunkKNSPBEHI_cjs.debug("[nuq+ `%s`] Subscribing to sync for `%s`", stateKeys, urlKey); emitter.on(urlKey, handlers[stateKey]); } return () => { emitter.off(SYNC_EVENT_KEY, syncFromURL); for (const stateKey of Object.keys(keyMap)) { const urlKey = resolvedUrlKeys[stateKey]; chunkKNSPBEHI_cjs.debug("[nuq+ `%s`] Unsubscribing to sync for `%s`", stateKeys, urlKey); emitter.off(urlKey, handlers[stateKey]); } }; }, [keyMap, resolvedUrlKeys]); const update = React2__default.default.useCallback( (stateUpdater, callOptions = {}) => { const newState = typeof stateUpdater === "function" ? stateUpdater(stateRef.current) : stateUpdater === null ? Object.fromEntries( Object.keys(keyMap).map((key) => [key, null]) ) : stateUpdater; chunkKNSPBEHI_cjs.debug("[nuq+ `%s`] setState: %O", stateKeys, newState); for (let [stateKey, value] of Object.entries(newState)) { const parser = keyMap[stateKey]; const urlKey = resolvedUrlKeys[stateKey]; if (!parser) { continue; } if ((callOptions.clearOnDefault ?? parser.clearOnDefault ?? clearOnDefault) && value !== null && parser.defaultValue !== void 0 && (parser.eq ?? ((a, b) => a === b))(value, parser.defaultValue)) { value = null; } queryRef.current[urlKey] = enqueueQueryStringUpdate( urlKey, value, parser.serialize ?? String, { // Call-level options take precedence over individual parser options // which take precedence over global options history: callOptions.history ?? parser.history ?? history2, shallow: callOptions.shallow ?? parser.shallow ?? shallow, scroll: callOptions.scroll ?? parser.scroll ?? scroll, throttleMs: callOptions.throttleMs ?? parser.throttleMs ?? throttleMs, startTransition: callOptions.startTransition ?? parser.startTransition ?? startTransition } ); emitter.emit(urlKey, { state: value, query: queryRef.current[urlKey] ?? null }); } return scheduleFlushToURL(router); }, [ keyMap, history2, shallow, scroll, throttleMs, startTransition, resolvedUrlKeys ] ); return [internalState, update]; } function parseMap(keyMap, urlKeys, searchParams, cachedQuery, cachedState) { return Object.keys(keyMap).reduce((obj, stateKey) => { const urlKey = urlKeys?.[stateKey] ?? stateKey; const { defaultValue, parse } = keyMap[stateKey]; const urlQuery = searchParams?.get(urlKey) ?? null; const queueQuery = getQueuedValue(urlKey); const query = queueQuery ?? urlQuery; if (cachedQuery && cachedState && cachedQuery[urlKey] === query) { obj[stateKey] = cachedState[stateKey] ?? defaultValue ?? null; return obj; } const value = query === null ? null : chunkKNSPBEHI_cjs.safeParse(parse, query, stateKey); obj[stateKey] = value ?? defaultValue ?? null; if (cachedQuery) { cachedQuery[urlKey] = query; } return obj; }, {}); } Object.defineProperty(exports, "createParser", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.createParser; } }); Object.defineProperty(exports, "createSerializer", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.createSerializer; } }); Object.defineProperty(exports, "parseAsArrayOf", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsArrayOf; } }); Object.defineProperty(exports, "parseAsBoolean", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsBoolean; } }); Object.defineProperty(exports, "parseAsFloat", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsFloat; } }); Object.defineProperty(exports, "parseAsHex", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsHex; } }); Object.defineProperty(exports, "parseAsInteger", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsInteger; } }); Object.defineProperty(exports, "parseAsIsoDateTime", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsIsoDateTime; } }); Object.defineProperty(exports, "parseAsJson", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsJson; } }); Object.defineProperty(exports, "parseAsNumberLiteral", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsNumberLiteral; } }); Object.defineProperty(exports, "parseAsString", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsString; } }); Object.defineProperty(exports, "parseAsStringEnum", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsStringEnum; } }); Object.defineProperty(exports, "parseAsStringLiteral", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsStringLiteral; } }); Object.defineProperty(exports, "parseAsTimestamp", { enumerable: true, get: function () { return chunkKNSPBEHI_cjs.parseAsTimestamp; } }); exports.queryTypes = queryTypes; exports.subscribeToQueryUpdates = subscribeToQueryUpdates; exports.useQueryState = useQueryState; exports.useQueryStates = useQueryStates;