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-15, react-router@6-7, and remix@2.
2 lines (1 loc) • 2.45 kB
JavaScript
;const a=n=>{if(n===null)return"null";const e=typeof n;if(e!=="object")return e;if(Array.isArray(n))return"array";if(n instanceof Date)return"date";return"object"};const w=n=>{const e=a(n);return e!=="object"&&e!=="array"};const o=typeof window==="undefined";const y=n=>{if(n instanceof URLSearchParams){return n}if(typeof n==="string"){const e=n.indexOf("?");return new URLSearchParams(e===-1?n:n.slice(e+1))}return new URLSearchParams};const p=(n,e)=>{if(n.length!==e.length)return false;return n.every((r,s)=>c(r,e[s]))};const h=(n,e)=>{const r=Object.keys(n);const s=Object.keys(e);if(r.length!==s.length)return false;return r.every(t=>c(n[t],e[t]))};const c=(n,e)=>{if(n===e)return true;if(n==null||e==null)return false;const r=a(n);const s=a(e);if(r!==s)return false;if(w(n))return false;if(r==="array"){return p(n,e)}if(r==="object"){return h(n,e)}return JSON.stringify(n)===JSON.stringify(e)};function S(n,e){const r=new URLSearchParams;const s=f(n,[...new URLSearchParams(e||"").entries()]);for(const[t,i]of s){r.set(t,i)}return r.toString()}function g(n,e){const r=e instanceof URLSearchParams?[...e.entries()]:Object.entries(e||{});return Object.fromEntries(f(n,r))}function f(n,e){const r=Object.keys(n);const s=[];for(let t=0;t<e.length;t++){if(r.includes(e[t]?.[0])){s.push([e[t][0].replace(/\+/g," "),e[t][1]])}}return s}function m(n,e){const r=Object.assign({},n);for(const[s]of Object.entries(n)){const t=s;const i=e[t]!==void 0;r[t]=i?e[t]:n[t]}return r}const b={push:n=>{if(typeof window!=="undefined"){window.history.pushState(null,"",n)}},replace:n=>{if(typeof window!=="undefined"){window.history.replaceState(null,"",n)}}};const P=/apple/i.test(!o&&navigator?.userAgent||"");const u="popstate";function U(){return o?"":window.location.search}const l=new Set;let d=false;function v(){if(d||o)return;d=true;for(const n of["pushState","replaceState"]){const e=window.history[n];window.history[n]=function r(...s){const t=e.apply(this,s);for(const i of[...l])i();return t}}}function O(n){if(o)return()=>void 0;v();l.add(n);window.addEventListener(u,n);return()=>{l.delete(n);window.removeEventListener(u,n)}}exports.assignValue=m;exports.filterUnknown=f;exports.filterUnknownParams=g;exports.filterUnknownParamsClient=S;exports.getParams=y;exports.getSearch=U;exports.isEqual=c;exports.isPrimitive=w;exports.isSSR=o;exports.isSafari=P;exports.popstateEv=u;exports.routerHistory=b;exports.subscribeToUrl=O;exports.typeOf=a;