state-in-url 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,7 @@
17
17
 
18
18
  [![npm](https://img.shields.io/npm/v/state-in-url.svg)](https://www.npmjs.com/package/state-in-url)
19
19
  ![Tests](https://github.com/asmyshlyaev177/state-in-url/actions/workflows/tests.yml/badge.svg?branch=main)
20
+ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/73be54068b7f41b0b74a252579ac09ec)](https://app.codacy.com/gh/asmyshlyaev177/state-in-url/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
20
21
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](https://github.com/asmyshlyaev177/state-in-url/)
21
22
  ![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/state-in-url.svg)
22
23
  </div>
@@ -25,8 +26,7 @@
25
26
 
26
27
  <h4 align="center">Don't hesitate to open issue if you found a bug</h4>
27
28
 
28
-
29
- https://github.com/asmyshlyaev177/state-in-url/assets/19854148/10456887-f149-4745-b3f1-e799e70b16cd
29
+ ![Demo-gif](https://github.com/asmyshlyaev177/state-in-url/assets/19854148/c9802601-4d42-4362-b3e4-37ff87c3b97f)
30
30
 
31
31
 
32
32
  <a href="https://state-in-url-asmyshlyaev177.vercel.app/" target="_blank">DEMO</a>
@@ -56,6 +56,7 @@ Add a ⭐️ to support the project!
56
56
  - 📘 **Typescript support and type Safety**: Preserves data types and structure, enhances developer experience with IDE suggestions, strong typing and JSDoc comments
57
57
  - ⚛️ **Framework Flexibility**: Separate hooks for Next.js and React.js applications, and functions for pure JS
58
58
  - ⚙ **Well tested**: Unit tests and Playwright tests
59
+ - ⚡ **Fast**: Minimal rerenders
59
60
  - 🪶 **Lightweight**: Zero dependencies for a smaller footprint
60
61
 
61
62
 
@@ -96,12 +97,21 @@ set `"moduleResolution": "Node16"` or `"moduleResolution": "NodeNext"` in your `
96
97
 
97
98
  #### Basic
98
99
 
100
+ 1. Define state shape
101
+ ```typescript
102
+ // countState.ts
103
+ // State shape should be stored in a constant, don't pass an object directly
104
+ export const countState: CountState = { count: 0 }
105
+
106
+ type CountState = { count: number }
107
+ ```
108
+
109
+ 2. Import it and use
99
110
  ```typescript
100
111
  'use client'
101
112
  import { useUrlState } from 'state-in-url';
102
113
 
103
- // State shape should be stored in a constant, don't pass an object directly
104
- const countState: { count: number } = { count: 0 };
114
+ import { countState } from './countState';
105
115
 
106
116
  function MyComponent() {
107
117
  // for use searchParams from server component
@@ -140,24 +150,28 @@ function MyComponent() {
140
150
  #### With complex state shape
141
151
 
142
152
  ```typescript
143
- 'use client'
144
- import { useUrlState } from 'state-in-url';
145
-
146
153
  interface UserSettings {
147
154
  theme: 'light' | 'dark';
148
155
  fontSize: number;
149
156
  notifications: boolean;
150
157
  }
151
158
 
152
- const defaultSettings: UserSettings {
159
+ export const userSettings: UserSettings {
153
160
  theme: 'light',
154
161
  fontSize: 16,
155
162
  notifications: true,
156
163
  }
164
+ ```
165
+
166
+ ```typescript
167
+ 'use client'
168
+ import { useUrlState } from 'state-in-url';
169
+
170
+ import { userSettings } from './userSettings';
157
171
 
158
172
  function SettingsComponent() {
159
173
  // `state` will infer from UserSettings type!
160
- const { state, updateUrl } = useUrlState(defaultSettings);
174
+ const { state, updateUrl } = useUrlState(userSettings);
161
175
 
162
176
  const toggleTheme = () => {
163
177
  updateUrl(current => ({
@@ -243,11 +257,14 @@ Accepts optional `defaultState` argument.
243
257
  ```typescript
244
258
  import { useUrlEncode } from 'state-in-url';
245
259
 
260
+ const ageState = { age: 0 };
261
+
246
262
  const Component = () => {
247
263
  const { parse, stringify } = useUrlEncode();
248
264
 
249
265
  const str = stringify({ age: 36 }); // age=∓36
250
- const obj = parse(str); // { age: 36 }
266
+ const obj = parse(str, ageState); // { age: 36 }
267
+ // Or const obj = parse(str); // { age: 36 }
251
268
 
252
269
  const currentParams = parse(window.location.search);
253
270
  // OR
@@ -328,7 +345,6 @@ Go to [localhost:3000](http://localhost:3000)
328
345
  ## Contact & Support
329
346
 
330
347
  - Create a [GitHub issue](https://github.com/asmyshlyaev177/state-in-url/issues) for bug reports, feature requests, or questions
331
- - Add a ⭐️ [star on GitHub](https://github.com/asmyshlyaev177/state-in-url) to support the project!
332
348
 
333
349
  ## [Changelog](https://github.com/asmyshlyaev177/state-in-url/blob/main/CHANGELOG.md)
334
350
 
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("next/navigation");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(e);const o=e=>{const t=null===e,n=Array.isArray(e),r=e instanceof Date;return(t?"null":r&&"date")||n&&"array"||!t&&!r&&!n&&"object"==typeof e&&"object"||typeof e},c=()=>"undefined"==typeof window,s=e=>new URLSearchParams("string"==typeof e?e:e?.toString?.()||""),u=(e,t)=>JSON.stringify(e)===JSON.stringify(t),a={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"};function i(e){switch(o(e)){case"function":case"symbol":return"";case"date":return a.date+e.toISOString();case"string":return e.match(/^◖/)?encodeURIComponent(e):`${a.string}${encodeURIComponent(e)}`;case"number":return a.number+String(e);case"boolean":return a.boolean+String(e);case"object":case"array":return JSON.stringify(e,f).replaceAll('"',"'");case"null":return a.null;case"undefined":return a.undefined;default:return String(e)}}function l(e,t){return function(e,t){try{return JSON.parse(e,g)}catch{const n=d(e);return n!==p?n:t}}(e.replaceAll("'",'"'),t)}const f=(e,t)=>{const n=o(t);return e&&"object"!==n&&"array"!==n?i(t):t},d=e=>e===a.null?null:e!==a.undefined?e?.startsWith?.(a.number)?Number.parseFloat(e.replace(a.number,"")):e?.startsWith?.(a.boolean)?!!e.includes("true"):e?.startsWith?.(a.date)?new Date(e.slice(1)):e?.startsWith?.(a.string)?decodeURIComponent(e).replace(/^◖/,""):p:void 0,p=Symbol("isError"),g=(e,t)=>{const n="string"==typeof t,r=n&&d(t);return r===p?t:e&&n?r:t};const y=(e,t)=>{const n="string"==typeof t,r=n&&l(t?.replaceAll?.("'",'"'));return r===p?t:e&&n?r:t};function b(e,t){try{return JSON.parse(e,y)}catch{const n=d(e);return n!==p?n:t}}function S(e,t,n){const r=s(n);return Object.entries(e||{}).forEach((([e,n])=>{const o=t?.[e];JSON.stringify(n)!==JSON.stringify(o)&&r.set(e,i(n))})),r.toString()}function w(e,t){return{...t||{},...Object.fromEntries([...s(e).entries()].map((([e,n])=>{const r=t?.[e];return[e,l(n,r)??r]})))}}function h(e){const t=r.default.useCallback((function(t,n){return"object"===o(t)?S(t,e,n):""}),[e]);return{parse:r.default.useCallback((function(t){return w(t,e)}),[e]),stringify:t}}const m=new WeakMap,O=new WeakMap;exports.decode=l,exports.decodeState=w,exports.encode=i,exports.encodeState=S,exports.useUrlEncode=h,exports.useUrlState=function(e,n){const{state:o,getState:s,setState:a,stringify:i,parse:l}=function(e){const t=r.default.useRef(e),{parse:n,stringify:o}=h(t.current),[s,a]=r.default.useState((()=>{const e=m.get(t.current),r=n(c()?"":window.location.search);return e||m.set(t.current,r),r}));return r.default.useInsertionEffect((()=>{const n=O.get(t.current)||[],r=()=>{a(m.get(t.current)||e)};return O.set(t.current,n.concat(r)),()=>{const e=O.get(t.current)||[];O.set(t.current,e.filter((e=>e!==r)))}}),[]),{state:s,getState:r.default.useCallback((()=>m.get(t.current)||t.current),[]),setState:r.default.useCallback((e=>{const n=m.get(t.current)||t.current;if("function"==typeof e){const r=e(n);if(u(n,r))return!1;m.set(t.current,r),(O.get(t.current)||[]).forEach((e=>{e()}))}else{if(u(n,e))return!1;m.set(t.current,e),(O.get(t.current)||[]).forEach((e=>{e()}))}}),[]),parse:n,stringify:o}}(c()?function(e,t){return{...t,...b(JSON.stringify(e),t)}}(n,e):e);r.default.useInsertionEffect((()=>{const e=()=>{if(c())return;const e=l(window.location.search);a(e)},t="popstate";return window.addEventListener(t,e),()=>{window.removeEventListener(t,e)}}),[]);const f=t.useRouter();return{updateUrl:r.default.useCallback(((e,t)=>{a(e??s());const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`,o=i("function"==typeof e?e(s()):e??s()),c=`${window.location.pathname}${o.length?"?":""}${o}`;if(r!==c){const{replace:e,...n}=t||{};f[e?"replace":"push"](c,{scroll:!1,...n})}}),[f,i,s]),updateState:a,state:o}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),e=require("next/navigation");function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var r=n(t);const o=t=>{const e=null===t,n=Array.isArray(t),r=t instanceof Date;return(e?"null":r&&"date")||n&&"array"||!e&&!r&&!n&&"object"==typeof t&&"object"||typeof t},c=()=>"undefined"==typeof window,s=t=>new URLSearchParams("string"==typeof t?t:t?.toString?.()||""),u=(t,e)=>JSON.stringify(t)===JSON.stringify(e),a={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"};function i(t){switch(o(t)){case"function":case"symbol":return"";case"date":return a.date+t.toISOString();case"string":return t.match(/^◖/)?encodeURIComponent(t):`${a.string}${encodeURIComponent(t)}`;case"number":return a.number+String(t);case"boolean":return a.boolean+String(t);case"object":case"array":return JSON.stringify(t,f).replaceAll('"',"'");case"null":return a.null;case"undefined":return a.undefined;default:return String(t)}}function l(t,e){return function(t,e){try{return JSON.parse(t,g)}catch{const n=d(t);return n!==p?n:e}}(t.replaceAll("'",'"'),e)}const f=(t,e)=>{const n=o(e);return t&&"object"!==n&&"array"!==n?i(e):e},d=t=>t===a.null?null:t!==a.undefined?t?.startsWith?.(a.number)?Number.parseFloat(t.replace(a.number,"")):t?.startsWith?.(a.boolean)?!!t.includes("true"):t?.startsWith?.(a.date)?new Date(t.slice(1)):t?.startsWith?.(a.string)?decodeURIComponent(t).replace(/^◖/,""):p:void 0,p=Symbol("isError"),g=(t,e)=>{const n="string"==typeof e,r=n&&d(e);return r===p?e:t&&n?r:e};const y=(t,e)=>{const n="string"==typeof e,r=n&&l(e?.replaceAll?.("'",'"'));return t&&n?r:e};function b(t,e){try{return JSON.parse(t,y)}catch{const n=d(t);return n!==p?n:e}}function S(t,e,n){const r=s(n);return Object.entries(t||{}).forEach((([t,n])=>{const o=e?.[t];JSON.stringify(n)!==JSON.stringify(o)&&r.set(t,i(n))})),r.toString()}function w(t,e){return{...e||{},...Object.fromEntries([...s(t).entries()].map((([t,n])=>{const r=e?.[t];return[t,l(n,r)??r]})))}}function h(t){const e=r.default.useCallback((function(e,n){return"object"===o(e)?S(e,t,n):""}),[t]);return{parse:r.default.useCallback((function(e){return w(e,t)}),[t]),stringify:e}}const m=new WeakMap,O=new WeakMap,j={get:function(t){return m.get(t)},set:function(t,e){m.set(t,e)}};exports.decode=l,exports.decodeState=w,exports.encode=i,exports.encodeState=S,exports.useUrlEncode=h,exports.useUrlState=function(t,n){const{state:o,getState:s,setState:a,stringify:i}=function(t){const e=r.default.useRef(t),{parse:n,stringify:o}=h(e.current),[s,a]=r.default.useState((()=>{const t=j.get(e.current),r=n(c()?"":window.location.search);return t||(j.set(e.current,r),r)})),i=r.default.useCallback((t=>{const n=j.get(e.current)||e.current;if("function"==typeof t){const r=t(n);if(u(n,r))return;j.set(e.current,r),(O.get(e.current)||[]).forEach((t=>{t()}))}else{if(u(n,t))return;j.set(e.current,t),(O.get(e.current)||[]).forEach((t=>{t()}))}}),[]);return r.default.useInsertionEffect((()=>{const r=O.get(e.current)||[],o=()=>{a(j.get(e.current)||t)};O.set(e.current,r.concat(o));const c=()=>{const t=n(window.location.search);i(t)},s="popstate";return window.addEventListener(s,c),()=>{const t=O.get(e.current)||[];O.set(e.current,t.filter((t=>t!==o))),window.removeEventListener(s,c)}}),[i]),{state:s,getState:r.default.useCallback((()=>j.get(e.current)||e.current),[]),setState:i,stringify:o}}(c()?function(t,e){return{...e,...b(JSON.stringify(t),e)}}(n,t):t),l=e.useRouter();return{updateUrl:r.default.useCallback(((t,e)=>{const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`;let o;if("function"==typeof t){const e=t(s());o=i(e),a(e)}else{const e=t??s();o=i(e),a(e)}const c=`${window.location.pathname}${o.length?"?":""}${o}`;if(r!==c){const{replace:t,...n}=e||{};l[t?"replace":"push"](c,{scroll:!1,...n})}}),[l,i,s]),updateState:a,state:o}};
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import t from"react";import{useRouter as e}from"next/navigation";const n=t=>{const e=null===t,n=Array.isArray(t),r=t instanceof Date;return(e?"null":r&&"date")||n&&"array"||!e&&!r&&!n&&"object"==typeof t&&"object"||typeof t},r=()=>"undefined"==typeof window,c=t=>new URLSearchParams("string"==typeof t?t:t?.toString?.()||""),o=(t,e)=>JSON.stringify(t)===JSON.stringify(e),s={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"};function a(t){switch(n(t)){case"function":case"symbol":return"";case"date":return s.date+t.toISOString();case"string":return t.match(/^◖/)?encodeURIComponent(t):`${s.string}${encodeURIComponent(t)}`;case"number":return s.number+String(t);case"boolean":return s.boolean+String(t);case"object":case"array":return JSON.stringify(t,i).replaceAll('"',"'");case"null":return s.null;case"undefined":return s.undefined;default:return String(t)}}function u(t,e){return function(t,e){try{return JSON.parse(t,p)}catch{const n=l(t);return n!==f?n:e}}(t.replaceAll("'",'"'),e)}const i=(t,e)=>{const r=n(e);return t&&"object"!==r&&"array"!==r?a(e):e},l=t=>t===s.null?null:t!==s.undefined?t?.startsWith?.(s.number)?Number.parseFloat(t.replace(s.number,"")):t?.startsWith?.(s.boolean)?!!t.includes("true"):t?.startsWith?.(s.date)?new Date(t.slice(1)):t?.startsWith?.(s.string)?decodeURIComponent(t).replace(/^◖/,""):f:void 0,f=Symbol("isError"),p=(t,e)=>{const n="string"==typeof e,r=n&&l(e);return r===f?e:t&&n?r:e};const d=(t,e)=>{const n="string"==typeof e,r=n&&u(e?.replaceAll?.("'",'"'));return r===f?e:t&&n?r:e};function g(t,e){try{return JSON.parse(t,d)}catch{const n=l(t);return n!==f?n:e}}function y(t,e,n){const r=c(n);return Object.entries(t||{}).forEach((([t,n])=>{const c=e?.[t];JSON.stringify(n)!==JSON.stringify(c)&&r.set(t,a(n))})),r.toString()}function b(t,e){return{...e||{},...Object.fromEntries([...c(t).entries()].map((([t,n])=>{const r=e?.[t];return[t,u(n,r)??r]})))}}function S(e){const r=t.useCallback((function(t,r){return"object"===n(t)?y(t,e,r):""}),[e]);return{parse:t.useCallback((function(t){return b(t,e)}),[e]),stringify:r}}const m=new WeakMap,w=new WeakMap;function h(n,c){const{state:s,getState:a,setState:u,stringify:i,parse:l}=function(e){const n=t.useRef(e),{parse:c,stringify:s}=S(n.current),[a,u]=t.useState((()=>{const t=m.get(n.current),e=c(r()?"":window.location.search);return t||m.set(n.current,e),e}));return t.useInsertionEffect((()=>{const t=w.get(n.current)||[],r=()=>{u(m.get(n.current)||e)};return w.set(n.current,t.concat(r)),()=>{const t=w.get(n.current)||[];w.set(n.current,t.filter((t=>t!==r)))}}),[]),{state:a,getState:t.useCallback((()=>m.get(n.current)||n.current),[]),setState:t.useCallback((t=>{const e=m.get(n.current)||n.current;if("function"==typeof t){const r=t(e);if(o(e,r))return!1;m.set(n.current,r),(w.get(n.current)||[]).forEach((t=>{t()}))}else{if(o(e,t))return!1;m.set(n.current,t),(w.get(n.current)||[]).forEach((t=>{t()}))}}),[]),parse:c,stringify:s}}(r()?function(t,e){return{...e,...g(JSON.stringify(t),e)}}(c,n):n);t.useInsertionEffect((()=>{const t=()=>{if(r())return;const t=l(window.location.search);u(t)},e="popstate";return window.addEventListener(e,t),()=>{window.removeEventListener(e,t)}}),[]);const f=e();return{updateUrl:t.useCallback(((t,e)=>{u(t??a());const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`,c=i("function"==typeof t?t(a()):t??a()),o=`${window.location.pathname}${c.length?"?":""}${c}`;if(r!==o){const{replace:t,...n}=e||{};f[t?"replace":"push"](o,{scroll:!1,...n})}}),[f,i,a]),updateState:u,state:s}}export{u as decode,b as decodeState,a as encode,y as encodeState,S as useUrlEncode,h as useUrlState};
1
+ import t from"react";import{useRouter as e}from"next/navigation";const n=t=>{const e=null===t,n=Array.isArray(t),r=t instanceof Date;return(e?"null":r&&"date")||n&&"array"||!e&&!r&&!n&&"object"==typeof t&&"object"||typeof t},r=()=>"undefined"==typeof window,c=t=>new URLSearchParams("string"==typeof t?t:t?.toString?.()||""),o=(t,e)=>JSON.stringify(t)===JSON.stringify(e),s={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"};function a(t){switch(n(t)){case"function":case"symbol":return"";case"date":return s.date+t.toISOString();case"string":return t.match(/^◖/)?encodeURIComponent(t):`${s.string}${encodeURIComponent(t)}`;case"number":return s.number+String(t);case"boolean":return s.boolean+String(t);case"object":case"array":return JSON.stringify(t,i).replaceAll('"',"'");case"null":return s.null;case"undefined":return s.undefined;default:return String(t)}}function u(t,e){return function(t,e){try{return JSON.parse(t,g)}catch{const n=l(t);return n!==f?n:e}}(t.replaceAll("'",'"'),e)}const i=(t,e)=>{const r=n(e);return t&&"object"!==r&&"array"!==r?a(e):e},l=t=>t===s.null?null:t!==s.undefined?t?.startsWith?.(s.number)?Number.parseFloat(t.replace(s.number,"")):t?.startsWith?.(s.boolean)?!!t.includes("true"):t?.startsWith?.(s.date)?new Date(t.slice(1)):t?.startsWith?.(s.string)?decodeURIComponent(t).replace(/^◖/,""):f:void 0,f=Symbol("isError"),g=(t,e)=>{const n="string"==typeof e,r=n&&l(e);return r===f?e:t&&n?r:e};const d=(t,e)=>{const n="string"==typeof e,r=n&&u(e?.replaceAll?.("'",'"'));return t&&n?r:e};function p(t,e){try{return JSON.parse(t,d)}catch{const n=l(t);return n!==f?n:e}}function y(t,e,n){const r=c(n);return Object.entries(t||{}).forEach((([t,n])=>{const c=e?.[t];JSON.stringify(n)!==JSON.stringify(c)&&r.set(t,a(n))})),r.toString()}function b(t,e){return{...e||{},...Object.fromEntries([...c(t).entries()].map((([t,n])=>{const r=e?.[t];return[t,u(n,r)??r]})))}}function S(e){const r=t.useCallback((function(t,r){return"object"===n(t)?y(t,e,r):""}),[e]);return{parse:t.useCallback((function(t){return b(t,e)}),[e]),stringify:r}}const m=new WeakMap,w=new WeakMap,h={get:function(t){return m.get(t)},set:function(t,e){m.set(t,e)}};function O(n,c){const{state:s,getState:a,setState:u,stringify:i}=function(e){const n=t.useRef(e),{parse:c,stringify:s}=S(n.current),[a,u]=t.useState((()=>{const t=h.get(n.current),e=c(r()?"":window.location.search);return t||(h.set(n.current,e),e)})),i=t.useCallback((t=>{const e=h.get(n.current)||n.current;if("function"==typeof t){const r=t(e);if(o(e,r))return;h.set(n.current,r),(w.get(n.current)||[]).forEach((t=>{t()}))}else{if(o(e,t))return;h.set(n.current,t),(w.get(n.current)||[]).forEach((t=>{t()}))}}),[]);return t.useInsertionEffect((()=>{const t=w.get(n.current)||[],r=()=>{u(h.get(n.current)||e)};w.set(n.current,t.concat(r));const o=()=>{const t=c(window.location.search);i(t)},s="popstate";return window.addEventListener(s,o),()=>{const t=w.get(n.current)||[];w.set(n.current,t.filter((t=>t!==r))),window.removeEventListener(s,o)}}),[i]),{state:a,getState:t.useCallback((()=>h.get(n.current)||n.current),[]),setState:i,stringify:s}}(r()?function(t,e){return{...e,...p(JSON.stringify(t),e)}}(c,n):n),l=e();return{updateUrl:t.useCallback(((t,e)=>{const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`;let c;if("function"==typeof t){const e=t(a());c=i(e),u(e)}else{const e=t??a();c=i(e),u(e)}const o=`${window.location.pathname}${c.length?"?":""}${c}`;if(r!==o){const{replace:t,...n}=e||{};l[t?"replace":"push"](o,{scroll:!1,...n})}}),[l,i,a]),updateState:u,state:s}}export{u as decode,b as decodeState,a as encode,y as encodeState,S as useUrlEncode,O as useUrlState};
@@ -14,7 +14,7 @@ import { type JSONCompatible, type UnknownObj } from './utils';
14
14
  *
15
15
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
16
16
  */
17
- export declare function encodeState<T>(state: never extends T ? object : JSONCompatible<T>, defaults?: JSONCompatible<T>, paramsToKeep?: string | URLSearchParams): string;
17
+ export declare function encodeState<T extends JSONCompatible>(state: T, defaults?: T, paramsToKeep?: string | URLSearchParams): string;
18
18
  /**
19
19
  * Decodes a URI string into an object of type T.
20
20
  *
@@ -29,4 +29,4 @@ export declare function encodeState<T>(state: never extends T ? object : JSONCom
29
29
  *
30
30
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
31
31
  */
32
- export declare function decodeState<T>(uriString: string | URLSearchParams, defaults?: JSONCompatible<T>): undefined extends T ? UnknownObj : T;
32
+ export declare function decodeState<T extends JSONCompatible>(uriString: string | URLSearchParams, defaults?: T): undefined extends T ? UnknownObj : T;
@@ -1,3 +1,4 @@
1
+ import { type JSONCompatible } from './utils';
1
2
  /**
2
3
  * Encode any JSON serializable value to URL friendly string
3
4
  *
@@ -16,7 +17,7 @@ export declare function encode(payload: unknown): string;
16
17
  *
17
18
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
18
19
  */
19
- export declare function decode<T>(payload: string, fallback?: T): T | Primitive;
20
+ export declare function decode<T>(payload: string, fallback?: T): JSONCompatible | Primitive;
20
21
  export declare const replacer: (key: string, value: unknown) => unknown;
21
22
  export type Primitive = Exclude<ReturnType<typeof decodePrimitive>, typeof errorSym>;
22
23
  export declare const decodePrimitive: (str: string) => string | number | boolean | Date | typeof errorSym | null | undefined;
@@ -31,5 +32,5 @@ export declare const reviver: (key: string, value: unknown) => unknown;
31
32
  *
32
33
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
33
34
  */
34
- export declare function parseJSON<T>(jsonString: string, fallbackValue?: T): T | Primitive | undefined;
35
- export declare function parseSsrQs<T>(sp: object | undefined, defaults: T): T;
35
+ export declare function parseJSON<T extends JSONCompatible>(jsonString: string, fallbackValue?: T): T | Primitive | undefined;
36
+ export declare function parseSsrQs<T extends JSONCompatible>(sp: object | undefined, defaults: T): T;
@@ -1,8 +1,7 @@
1
- import { type JSONCompatible, type DeepReadonly } from './utils';
2
- export declare function useState<T>(defaultState: JSONCompatible<T>): {
3
- state: JSONCompatible<T>;
4
- getState: () => JSONCompatible<T>;
5
- setState: (value: JSONCompatible<T> | DeepReadonly<JSONCompatible<T>> | ((currState: typeof defaultState | DeepReadonly<typeof defaultState>) => typeof defaultState | DeepReadonly<typeof defaultState>)) => false | undefined;
6
- parse: (strOrSearchParams: string | URLSearchParams) => DeepReadonly<JSONCompatible<T>>;
7
- stringify: (state: JSONCompatible<T> | DeepReadonly<JSONCompatible<T>>, paramsToKeep?: string | URLSearchParams | undefined) => string;
1
+ import { type JSONCompatible } from './utils';
2
+ export declare function useState<T extends JSONCompatible>(defaultState: T): {
3
+ state: T;
4
+ getState: () => T;
5
+ setState: (value: T | ((currState: typeof defaultState) => typeof defaultState)) => void;
6
+ stringify: (state: T, paramsToKeep?: string | URLSearchParams | undefined) => string;
8
7
  };
@@ -1,3 +1,7 @@
1
- export declare const stateMap: WeakMap<object, object>;
2
- export declare const subscribers: WeakMap<object, Cb[]>;
1
+ import { type JSONCompatible } from './utils';
2
+ export declare const subscribers: WeakMap<JSONCompatible, Cb[]>;
3
3
  export type Cb = () => void;
4
+ export declare const stateMap: {
5
+ get: <T extends JSONCompatible>(objKey: T) => T;
6
+ set: <T_1 extends JSONCompatible>(objKey: T_1, value: T_1) => void;
7
+ };
@@ -1,4 +1,4 @@
1
- import { type JSONCompatible, type DeepReadonly } from './utils';
1
+ import { type JSONCompatible } from './utils';
2
2
  /**
3
3
  * A hook that returns stringify and parse functions for encoding and decoding state
4
4
  * to and from URL search parameters.
@@ -19,7 +19,7 @@ import { type JSONCompatible, type DeepReadonly } from './utils';
19
19
  *
20
20
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
21
21
  */
22
- export declare function useUrlEncode<T>(stateShape: JSONCompatible<T>): {
23
- parse: (strOrSearchParams: string | URLSearchParams) => DeepReadonly<JSONCompatible<T>>;
24
- stringify: (state: typeof stateShape | DeepReadonly<typeof stateShape>, paramsToKeep?: string | URLSearchParams) => string;
22
+ export declare function useUrlEncode<T extends JSONCompatible>(stateShape: T): {
23
+ parse: (strOrSearchParams: string | URLSearchParams) => T;
24
+ stringify: (state: typeof stateShape, paramsToKeep?: string | URLSearchParams) => string;
25
25
  };
@@ -18,10 +18,10 @@ import { DeepReadonly, type JSONCompatible } from './utils';
18
18
  *
19
19
  * * Github {@link https://github.com/asmyshlyaev177/state-in-url}
20
20
  */
21
- export declare function useUrlState<T>(defaultState: JSONCompatible<T>, sp?: object): {
22
- updateUrl: (value?: JSONCompatible<T> | DeepReadonly<JSONCompatible<T>> | ((currState: typeof defaultState | DeepReadonly<typeof defaultState>) => typeof defaultState | DeepReadonly<typeof defaultState>) | undefined, options?: Options) => void;
23
- updateState: (value: JSONCompatible<T> | DeepReadonly<JSONCompatible<T>> | ((currState: JSONCompatible<T> | DeepReadonly<JSONCompatible<T>>) => JSONCompatible<T> | DeepReadonly<JSONCompatible<T>>)) => false | undefined;
24
- state: DeepReadonly<JSONCompatible<T>>;
21
+ export declare function useUrlState<T extends JSONCompatible>(defaultState: T, sp?: object): {
22
+ updateUrl: (value?: T | ((currState: typeof defaultState) => typeof defaultState) | undefined, options?: Options) => void;
23
+ updateState: (value: T | ((currState: T) => T)) => void;
24
+ state: DeepReadonly<T>;
25
25
  };
26
26
  type Router = ReturnType<typeof useRouter>;
27
27
  type RouterOptions = NonNullable<Parameters<Router['push']>[1]>;
@@ -9,13 +9,13 @@ export type Type = 'string' | 'date' | 'boolean' | 'number' | 'bigint' | 'undefi
9
9
  */
10
10
  export declare const typeOf: (val: unknown) => Type;
11
11
  export declare const isSSR: () => boolean;
12
- type JSONPrimitive = null | boolean | Date | number | string | JSONPrimitive[] | {
13
- [prop: string]: JSONPrimitive;
12
+ export type JSON = null | boolean | Date | number | string | {
13
+ [prop: string]: JSON | JSON[];
14
14
  };
15
- export type JSONCompatible<T> = {
16
- [P in keyof T]: T[P] extends JSONPrimitive ? T[P] : Pick<T, P> extends Required<Pick<T, P>> ? never : JSONCompatible<T[P]>;
15
+ export type JSONCompatible = {
16
+ [prop: string]: JSON | JSON[];
17
17
  };
18
- export type DeepReadonly<T> = T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends Set<infer S> ? ReadonlySet<DeepReadonly<S>> : T extends object ? {
18
+ export type DeepReadonly<T> = T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends Set<infer S> ? ReadonlySet<DeepReadonly<S>> : T extends JSONCompatible ? {
19
19
  readonly [K in keyof T]: DeepReadonly<T[K]>;
20
20
  } : T;
21
21
  export declare const getParams: (strOrSearchParams?: string | URLSearchParams) => URLSearchParams;
@@ -23,4 +23,3 @@ export type UnknownObj = {
23
23
  [key: string]: unknown;
24
24
  };
25
25
  export declare const isEqual: (val1: unknown, val2: unknown) => boolean;
26
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-in-url",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Library to store state in browser URL, includes hook for NextJS, hook for pure React, and low level helpers.",
5
5
  "homepage": "https://github.com/asmyshlyaev177/state-in-url#readme",
6
6
  "keywords": [
@@ -65,13 +65,6 @@
65
65
  }
66
66
  },
67
67
  "types": "./dist/index.d.ts",
68
- "typesVersions": {
69
- "*": {
70
- "*": [
71
- "dist/types/"
72
- ]
73
- }
74
- },
75
68
  "scripts": {
76
69
  "test:unit": "wireit",
77
70
  "test:int": "playwright test",