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.71 kB
JavaScript
;const a=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=a(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)=>c(e,t[s]))};const g=(n,t)=>{const e=Object.keys(n);const s=Object.keys(t);if(e.length!==s.length)return false;return e.every(r=>c(n[r],t[r]))};const c=(n,t)=>{if(n===t)return true;if(n==null||t==null)return false;const e=a(n);const s=a(t);if(e!==s)return false;if(w(n))return false;if(e==="array"){return p(n,t)}if(e==="object"){return g(n,t)}return JSON.stringify(n)===JSON.stringify(t)};function S(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 P(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 U={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 O=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 k(n){if(i)return()=>void 0;v();l.add(n);window.addEventListener(u,n);return()=>{l.delete(n);window.removeEventListener(u,n)}}exports.assignValue=P;exports.filterUnknown=f;exports.filterUnknownParams=m;exports.filterUnknownParamsClient=S;exports.getOtherParams=b;exports.getParams=y;exports.getSearch=j;exports.isEqual=c;exports.isPrimitive=w;exports.isSSR=i;exports.isWebKit=O;exports.isWebKitUserAgent=d;exports.popstateEv=u;exports.routerHistory=U;exports.subscribeToUrl=k;exports.typeOf=a;