state-in-url
Version:
Store state in URL as in object, types and structure are preserved, with TS validation. Same API as React.useState, wthout any hasssle or boilerplate. Next.js@14-16, react-router@6-7, remix@2, and Astro.
2 lines (1 loc) • 2.62 kB
JavaScript
const c=n=>{if(n===null)return"null";const t=typeof n;if(t!=="object")return t;if(Array.isArray(n))return"array";if(n instanceof Date)return"date";return"object"};const w=n=>{const t=c(n);return t!=="object"&&t!=="array"};const i=typeof window==="undefined";const y=n=>{if(n instanceof URLSearchParams){return n}if(typeof n==="string"){const t=n.indexOf("?");return new URLSearchParams(t===-1?n:n.slice(t+1))}return new URLSearchParams};const p=(n,t)=>{if(n.length!==t.length)return false;return n.every((e,s)=>a(e,t[s]))};const S=(n,t)=>{const e=Object.keys(n);const s=Object.keys(t);if(e.length!==s.length)return false;return e.every(r=>a(n[r],t[r]))};const a=(n,t)=>{if(n===t)return true;if(n==null||t==null)return false;const e=c(n);const s=c(t);if(e!==s)return false;if(w(n))return false;if(e==="array"){return p(n,t)}if(e==="object"){return S(n,t)}return JSON.stringify(n)===JSON.stringify(t)};function g(n,t){const e=new URLSearchParams;const s=f(n,[...new URLSearchParams(t||"").entries()]);for(const[r,o]of s){e.set(r,o)}return e.toString()}function b(n,t){const e=Object.keys(n);const s=new URLSearchParams;for(const[r,o]of new URLSearchParams(t)){if(!e.includes(r))s.set(r,o)}return s}function m(n,t){const e=t instanceof URLSearchParams?[...t.entries()]:Object.entries(t||{});return Object.fromEntries(f(n,e))}function f(n,t){const e=Object.keys(n);const s=[];for(let r=0;r<t.length;r++){if(e.includes(t[r]?.[0])){s.push([t[r][0].replace(/\+/g," "),t[r][1]])}}return s}function O(n,t){const e=Object.assign({},n);for(const[s]of Object.entries(n)){const r=s;const o=t[r]!==void 0;e[r]=o?t[r]:n[r]}return e}const P={push:n=>{if(typeof window!=="undefined"){window.history.pushState(null,"",n)}},replace:n=>{if(typeof window!=="undefined"){window.history.replaceState(null,"",n)}}};const d=n=>/AppleWebKit\/[6-9]\d\d/.test(n);const U=d(!i&&navigator?.userAgent||"");const u="popstate";function j(){return i?"":window.location.search}const l=new Set;let h=false;function v(){if(h||i)return;h=true;for(const n of["pushState","replaceState"]){const t=window.history[n];window.history[n]=function e(...s){const r=t.apply(this,s);queueMicrotask(()=>{for(const o of[...l])o()});return r}}}function L(n){if(i)return()=>void 0;v();l.add(n);window.addEventListener(u,n);return()=>{l.delete(n);window.removeEventListener(u,n)}}export{O as assignValue,f as filterUnknown,m as filterUnknownParams,g as filterUnknownParamsClient,b as getOtherParams,y as getParams,j as getSearch,a as isEqual,w as isPrimitive,i as isSSR,U as isWebKit,d as isWebKitUserAgent,u as popstateEv,P as routerHistory,L as subscribeToUrl,c as typeOf};