nuqs
Version:
112 lines (111 loc) • 4.8 kB
JavaScript
import { createContext, createElement, useContext } from "react";
//#region src/lib/errors.ts
const errors = {
303: "Multiple adapter contexts detected. This might happen in monorepos.",
404: "nuqs requires an adapter to work with your framework.",
409: "Multiple versions of the library are loaded. This may lead to unexpected behavior. Currently using `%s`, but `%s` (via the %s adapter) was about to load on top.",
414: "Max safe URL length exceeded. Some browsers may not be able to accept this URL. Consider limiting the amount of state stored in the URL.",
429: "URL update rate-limited by the browser. Consider increasing `throttleMs` for key(s) `%s`. %O",
500: "Empty search params cache. Search params can't be accessed in Layouts.",
501: "Search params cache already populated. Have you called `parse` twice?",
502: "`processUrlSearchParams` threw while processing key(s) `%s`. %O"
};
function error(code) {
return `[nuqs] ${errors[code]}
See https://nuqs.dev/NUQS-${code}`;
}
//#endregion
//#region src/lib/url-encoding.ts
function renderQueryString(search) {
if (search.size === 0) return "";
const query = [];
for (const [key, value] of search.entries()) {
const safeKey = key.replace(/#/g, "%23").replace(/&/g, "%26").replace(/\+/g, "%2B").replace(/=/g, "%3D").replace(/\?/g, "%3F");
query.push(`${safeKey}=${encodeQueryValue(value)}`);
}
const queryString = "?" + query.join("&");
warnIfURLIsTooLong(queryString);
return queryString;
}
function encodeQueryValue(input) {
return input.replace(/%/g, "%25").replace(/\+/g, "%2B").replace(/ /g, "+").replace(/#/g, "%23").replace(/&/g, "%26").replace(/"/g, "%22").replace(/'/g, "%27").replace(/`/g, "%60").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/[\x00-\x1F]/g, (char) => encodeURIComponent(char));
}
const URL_MAX_LENGTH = 2e3;
function warnIfURLIsTooLong(queryString) {
if (typeof location === "undefined") return;
if (process.env.NODE_ENV === "production") return;
const url = new URL(location.href);
url.search = queryString;
if (url.href.length > URL_MAX_LENGTH) console.warn(error(414));
}
//#endregion
//#region src/lib/version.ts
const version = "2.9.5";
//#endregion
//#region src/lib/global-singleton.ts
const fallbackRegistry = {};
/**
* Store a module-level singleton on globalThis, keyed by library version,
* so that duplicate copies of the library loaded side by side (e.g. in
* monorepos, see issue #798) share the same instance instead of each
* creating their own. Copies of different versions deliberately keep
* separate instances, as internal state shapes may differ across versions.
*/
function globalSingleton(scope, create) {
const key = Symbol.for(`nuqs.${version}.${scope}`);
const registry = globalThis;
if (registry[key] != null) return registry[key];
const target = Object.isExtensible(registry) ? registry : fallbackRegistry;
return target[key] ??= create();
}
/**
* Like globalSingleton, but additionally keyed by the identity of a
* runtime object, for singletons that must not be shared across distinct
* runtimes (e.g. one React context per React instance).
*/
function globalWeakSingleton(scope, key, create) {
const instances = globalSingleton(scope, () => /* @__PURE__ */ new WeakMap());
if (!instances.has(key)) instances.set(key, create());
return instances.get(key);
}
//#endregion
//#region src/adapters/lib/context.ts
const context = globalWeakSingleton("adapter-context", createContext, () => {
const ctx = createContext({ useAdapter() {
throw new Error(error(404));
} });
ctx.displayName = "NuqsAdapterContext";
return ctx;
});
if (typeof window !== "undefined") {
if (window.__NuqsAdapterContext && window.__NuqsAdapterContext !== context) console.error(error(303));
window.__NuqsAdapterContext = context;
}
/**
* Create a custom adapter (context provider) for nuqs to work with your framework / router.
*
* Adapters are based on React Context,
*
* @param useAdapter
* @returns
*/
function createAdapterProvider(useAdapter) {
return ({ children, defaultOptions, processUrlSearchParams, ...props }) => createElement(context.Provider, {
...props,
value: {
useAdapter,
defaultOptions,
processUrlSearchParams
}
}, children);
}
function useAdapter(watchKeys) {
const value = useContext(context);
if (!("useAdapter" in value)) throw new Error(error(404));
return value.useAdapter(watchKeys);
}
const useAdapterDefaultOptions = () => useContext(context).defaultOptions;
const useAdapterProcessUrlSearchParams = () => useContext(context).processUrlSearchParams;
//#endregion
export { useAdapterProcessUrlSearchParams as a, renderQueryString as c, useAdapterDefaultOptions as i, error as l, createAdapterProvider as n, globalSingleton as o, useAdapter as r, version as s, context as t };
//# sourceMappingURL=context-Mu913OAK.js.map