state-in-url 0.2.1 → 0.2.2
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
|
@@ -74,6 +74,7 @@ Add a ⭐️ to support the project!
|
|
|
74
74
|
- [Inspiration](#inspiration)
|
|
75
75
|
|
|
76
76
|
## installation
|
|
77
|
+
### 1. Install package
|
|
77
78
|
```sh
|
|
78
79
|
# npm
|
|
79
80
|
npm install --save state-in-url
|
|
@@ -82,6 +83,8 @@ yarn add state-in-url
|
|
|
82
83
|
# pnpm
|
|
83
84
|
pnpm add state-in-url
|
|
84
85
|
```
|
|
86
|
+
### 2. Edit tsconfig.json
|
|
87
|
+
set `"moduleResolution": "Node16"` or `"moduleResolution": "NodeNext"` in your `tsconfig.json`
|
|
85
88
|
|
|
86
89
|
|
|
87
90
|
## useUrlState hook for Next.js
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +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 c=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},u=()=>"undefined"==typeof window,o=e=>new URLSearchParams("string"==typeof e?e:e?.toString?.()||""),a=(e,t)=>JSON.stringify(e)===JSON.stringify(t),s={string:"◖",boolean:"🗵",null:"∙null",undefined:"∙undefined",number:"∓",date:"⏲"};function i(e){switch(c(e)){case"function":case"symbol":return"";case"date":return s.date+e.toISOString();case"string":return e.match(/^◖/)?encodeURIComponent(e):`${s.string}${encodeURIComponent(e)}`;case"number":return s.number+String(e);case"boolean":return s.boolean+String(e);case"object":case"array":return JSON.stringify(e,f).replaceAll('"',"'");case"null":return s.null;case"undefined":return s.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=c(t);return e&&"object"!==n&&"array"!==n?i(t):t},d=e=>e===s.null?null:e!==s.undefined?e?.startsWith?.(s.number)?Number.parseFloat(e.replace(s.number,"")):e?.startsWith?.(s.boolean)?!!e.includes("true"):e?.startsWith?.(s.date)?new Date(e.slice(1)):e?.startsWith?.(s.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=o(n);return Object.entries(e||{}).forEach((([e,n])=>{const c=t?.[e];JSON.stringify(n)!==JSON.stringify(c)&&r.set(e,i(n))})),r.toString()}function h(e,t){return{...t||{},...Object.fromEntries([...o(e).entries()].map((([e,n])=>{const r=t?.[e];return[e,l(n,r)??r]})))}}function m(e){const t=r.default.useCallback((function(t,n){return"object"===c(t)?S(t,e,n):""}),[e]);return{parse:r.default.useCallback((function(t){return h(t,e)}),[e]),stringify:t}}const w=new WeakMap,O=new WeakMap;exports.decode=l,exports.decodeState=h,exports.encode=i,exports.encodeState=S,exports.useUrlEncode=m,exports.useUrlState=function(e,n){const{state:c,getState:o,setState:s,stringify:i}=function(e){const t=r.default.useRef(e),{parse:n,stringify:c}=m(t.current),[o,s]=r.default.useState((()=>{const e=w.get(t.current),r=n(u()?"":window.location.search);return e||w.set(t.current,r),r}));return r.default.useInsertionEffect((()=>{const n=O.get(t.current)||[],r=()=>{s(w.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:o,getState:r.default.useCallback((()=>w.get(t.current)||t.current),[]),setState:r.default.useCallback((e=>{const n=w.get(t.current)||t.current;if("function"==typeof e){const r=e(n);if(a(n,r))return!1;w.set(t.current,r),(O.get(t.current)||[]).forEach((e=>{e()}))}else{if(a(n,e))return!1;w.set(t.current,e),(O.get(t.current)||[]).forEach((e=>{e()}))}}),[]),parse:n,stringify:c}}(u()?function(e,t){return{...t,...b(JSON.stringify(e),t)}}(n,e):e),l=t.useRouter();return{updateUrl:r.default.useCallback(((e,t)=>{e&&s(e);const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`,c=i("function"==typeof e?e(o()):o()),u=`${window.location.pathname}${c.length?"?":""}${c}`;if(r!==u){const{replace:e,...n}=t||{};l[e?"replace":"push"](u,{scroll:!1,...n})}}),[l,i,o]),updateState:s,state:c}};
|
|
@@ -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,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 p=(t,e)=>{const n="string"==typeof e,r=n&&u(e?.replaceAll?.("'",'"'));return r===f?e:t&&n?r:e};function d(t,e){try{return JSON.parse(t,p)}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,h=new WeakMap;function w(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=m.get(n.current),e=c(r()?"":window.location.search);return t||m.set(n.current,e),e}));return t.useInsertionEffect((()=>{const t=h.get(n.current)||[],r=()=>{u(m.get(n.current)||e)};return h.set(n.current,t.concat(r)),()=>{const t=h.get(n.current)||[];h.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),(h.get(n.current)||[]).forEach((t=>{t()}))}else{if(o(e,t))return!1;m.set(n.current,t),(h.get(n.current)||[]).forEach((t=>{t()}))}}),[]),parse:c,stringify:s}}(r()?function(t,e){return{...e,...d(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}`,c=i("function"==typeof t?t(a()):a()),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,w 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 p=(t,e)=>{const n="string"==typeof e,r=n&&u(e?.replaceAll?.("'",'"'));return r===f?e:t&&n?r:e};function d(t,e){try{return JSON.parse(t,p)}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,h=new WeakMap;function w(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=m.get(n.current),e=c(r()?"":window.location.search);return t||m.set(n.current,e),e}));return t.useInsertionEffect((()=>{const t=h.get(n.current)||[],r=()=>{u(m.get(n.current)||e)};return h.set(n.current,t.concat(r)),()=>{const t=h.get(n.current)||[];h.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),(h.get(n.current)||[]).forEach((t=>{t()}))}else{if(o(e,t))return!1;m.set(n.current,t),(h.get(n.current)||[]).forEach((t=>{t()}))}}),[]),parse:c,stringify:s}}(r()?function(t,e){return{...e,...d(JSON.stringify(t),e)}}(c,n):n),l=e();return{updateUrl:t.useCallback(((t,e)=>{t&&u(t);const n=window.location.search,r=`${window.location.pathname}${n.length&&!n.includes("?")?"?":""}${n}`,c=i("function"==typeof t?t(a()):a()),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,w as useUrlState};
|
package/dist/urlstate/state.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type JSONCompatible, type DeepReadonly } from './utils';
|
|
|
2
2
|
export declare function useState<T>(defaultState: JSONCompatible<T>): {
|
|
3
3
|
state: JSONCompatible<T>;
|
|
4
4
|
getState: () => JSONCompatible<T>;
|
|
5
|
-
setState: (value: JSONCompatible<T> |
|
|
6
|
-
parse: (strOrSearchParams: string | URLSearchParams) =>
|
|
7
|
-
stringify: (state: 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;
|
|
8
8
|
};
|
|
@@ -20,6 +20,6 @@ import { type JSONCompatible, type DeepReadonly } from './utils';
|
|
|
20
20
|
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
21
21
|
*/
|
|
22
22
|
export declare function useUrlEncode<T>(stateShape: JSONCompatible<T>): {
|
|
23
|
-
parse: (strOrSearchParams: string | URLSearchParams) =>
|
|
24
|
-
stringify: (state: typeof stateShape |
|
|
23
|
+
parse: (strOrSearchParams: string | URLSearchParams) => DeepReadonly<JSONCompatible<T>>;
|
|
24
|
+
stringify: (state: typeof stateShape | DeepReadonly<typeof stateShape>, paramsToKeep?: string | URLSearchParams) => string;
|
|
25
25
|
};
|
|
@@ -19,9 +19,9 @@ import { DeepReadonly, type JSONCompatible } from './utils';
|
|
|
19
19
|
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
20
20
|
*/
|
|
21
21
|
export declare function useUrlState<T>(defaultState: JSONCompatible<T>, sp?: object): {
|
|
22
|
-
updateUrl: (value?:
|
|
23
|
-
updateState: (value: JSONCompatible<T> |
|
|
24
|
-
state: JSONCompatible<T
|
|
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>>;
|
|
25
25
|
};
|
|
26
26
|
type Router = ReturnType<typeof useRouter>;
|
|
27
27
|
type RouterOptions = NonNullable<Parameters<Router['push']>[1]>;
|
package/dist/urlstate/utils.d.ts
CHANGED
|
@@ -17,9 +17,9 @@ type NotAssignableToJson = bigint | symbol | Function;
|
|
|
17
17
|
export type JSONCompatible<T> = unknown extends T ? never : {
|
|
18
18
|
[P in keyof T]: T[P] extends JSONValue ? T[P] : T[P] extends NotAssignableToJson ? never : JSONCompatible<T[P]>;
|
|
19
19
|
};
|
|
20
|
-
export type DeepReadonly<T> =
|
|
21
|
-
readonly [
|
|
22
|
-
}
|
|
20
|
+
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 ? {
|
|
21
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
22
|
+
} : T;
|
|
23
23
|
export declare const getParams: (strOrSearchParams?: string | URLSearchParams) => URLSearchParams;
|
|
24
24
|
export type UnknownObj = {
|
|
25
25
|
[key: string]: unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-in-url",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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": [
|
|
@@ -41,19 +41,26 @@
|
|
|
41
41
|
"files": [
|
|
42
42
|
"dist"
|
|
43
43
|
],
|
|
44
|
-
"main": "dist/index.
|
|
45
|
-
"type": "module",
|
|
44
|
+
"main": "dist/index.cjs",
|
|
46
45
|
"exports": {
|
|
47
46
|
"import": {
|
|
48
47
|
"types": "./dist/index.d.ts",
|
|
49
|
-
"default": "./dist/index.
|
|
48
|
+
"default": "./dist/index.mjs"
|
|
49
|
+
},
|
|
50
|
+
"node": {
|
|
51
|
+
"types": "./dist/index.d.ts",
|
|
52
|
+
"default": "./dist/index.mjs"
|
|
53
|
+
},
|
|
54
|
+
"require": {
|
|
55
|
+
"types": "./dist/index.d.ts",
|
|
56
|
+
"default": "./dist/index.cjs"
|
|
50
57
|
},
|
|
51
58
|
"module": {
|
|
52
|
-
"types": "./dist/index.
|
|
59
|
+
"types": "./dist/index.mjs",
|
|
53
60
|
"default": "./dist/index.d.ts"
|
|
54
61
|
},
|
|
55
62
|
"default": {
|
|
56
|
-
"types": "./dist/index.
|
|
63
|
+
"types": "./dist/index.mjs",
|
|
57
64
|
"default": "./dist/index.d.ts"
|
|
58
65
|
}
|
|
59
66
|
},
|