state-in-url 0.1.6 → 0.2.0
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 +76 -24
- package/dist/index.js +1 -1
- package/dist/urlstate/encodeState.d.ts +4 -0
- package/dist/urlstate/encoder.d.ts +18 -10
- package/dist/urlstate/index.d.ts +3 -3
- package/dist/urlstate/state.d.ts +8 -0
- package/dist/urlstate/subscribers.d.ts +3 -0
- package/dist/urlstate/useUrlEncode.d.ts +5 -5
- package/dist/urlstate/useUrlState.d.ts +8 -33
- package/dist/urlstate/utils.d.ts +2 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -6,13 +6,28 @@
|
|
|
6
6
|
<img src="/assets/logo.svg?raw=true" alt="Library logo"/>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
<div align="center">
|
|
11
|
+
|
|
12
|
+
[](https://www.linkedin.com/in/asmyshlyaev177/)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
[](https://www.npmjs.com/package/state-in-url)
|
|
16
|
+

|
|
17
|
+
[](https://github.com/asmyshlyaev177/state-in-url/)
|
|
18
|
+

|
|
19
|
+
</div>
|
|
20
|
+
|
|
9
21
|
<div align="center">
|
|
10
22
|
Seamlessly store complex React state object in URL query parameters without losing types. Works with Next.js/React.js applications.
|
|
11
23
|
|
|
12
24
|
<h4 align="center">Don't hesitate to open issue if you found a bug</h4>
|
|
13
25
|
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
https://github.com/asmyshlyaev177/state-in-url/assets/19854148/10456887-f149-4745-b3f1-e799e70b16cd
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
<a href="https://state-in-url-asmyshlyaev177.vercel.app/" target="_blank">DEMO</a>
|
|
16
31
|
|
|
17
32
|
|
|
18
33
|
<hr />
|
|
@@ -21,32 +36,33 @@ Add a ⭐️ to support the project!
|
|
|
21
36
|
|
|
22
37
|
<hr />
|
|
23
38
|
|
|
39
|
+
</div>
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
## Why use state-in-url?
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-

|
|
30
|
-
[](https://github.com/asmyshlyaev177/state-in-url/)
|
|
31
|
-

|
|
43
|
+
`state-in-url` lets you use URI string for state management.
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
# Use cases
|
|
46
|
+
- 🔗 Shareable URLs with full application state
|
|
47
|
+
- 🔄 Easy state persistence across page reloads
|
|
48
|
+
- 🧠 Pass data between unrelated client components
|
|
49
|
+
- 🧮 Store unsaved user forms in URL
|
|
34
50
|
|
|
35
51
|
# Features
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
|
|
41
|
-
- **Efficient updates with minimal re-renders.**
|
|
42
|
-
- **Lightweight, no dependencies.**
|
|
52
|
+
- 🧩 **Simple**: Handles complex objects without extra effort
|
|
53
|
+
- 📘 **Typescript support and type Safety**: Preserves data types and structure, enhances developer experience with strong typing and JSDoc comments
|
|
54
|
+
- ⚛️ **Framework Flexibility**: Separate hooks for Next.js and React.js applications, and functions for pure JS
|
|
55
|
+
- 🪶 **Lightweight**: Zero dependencies for a smaller footprint
|
|
56
|
+
|
|
43
57
|
|
|
44
58
|
## Table of content
|
|
45
59
|
- [Installation](#installation)
|
|
46
60
|
- [`useUrlState` for Next.js](#useurlstate-hook-for-nextjs)
|
|
47
61
|
- [`useUrlEncode` for React.js](#useurlencode-hook-for-reactjs)
|
|
48
62
|
- [`encodeState` and `decodeState` for pure JS usage](#encodestate-and-decodestate-helpers)
|
|
63
|
+
- [auto sync state with url](#auto-sync-state)
|
|
49
64
|
- [Low-level `encode` and `decode` functions](#encode-and-decode-helpers)
|
|
65
|
+
- [Best practices](#best-practices)
|
|
50
66
|
- [Gothas](#gothas)
|
|
51
67
|
- [Contact & Support](#contact--support)
|
|
52
68
|
- [Changelog](#changelog)
|
|
@@ -63,12 +79,6 @@ yarn add state-in-url
|
|
|
63
79
|
pnpm add state-in-url
|
|
64
80
|
```
|
|
65
81
|
|
|
66
|
-
## Run locally
|
|
67
|
-
Clone this repo, run `npm install` and
|
|
68
|
-
```sh
|
|
69
|
-
npm run dev
|
|
70
|
-
```
|
|
71
|
-
Go to [localhost:3000](http://localhost:3000)
|
|
72
82
|
|
|
73
83
|
## useUrlState hook for Next.js
|
|
74
84
|
|
|
@@ -84,9 +94,12 @@ Go to [localhost:3000](http://localhost:3000)
|
|
|
84
94
|
import { useUrlState } from 'state-in-url';
|
|
85
95
|
|
|
86
96
|
// State shape should be stored in a constant, don't pass an object directly
|
|
87
|
-
const countState = { count: 0 };
|
|
97
|
+
const countState: { count: number } = { count: 0 };
|
|
88
98
|
|
|
89
99
|
function MyComponent() {
|
|
100
|
+
// for use searchParams from server component
|
|
101
|
+
// e.g. export default async function Home({ searchParams }: { searchParams: object }) {
|
|
102
|
+
// const { state, updateState, updateUrl } = useUrlState(countState, searchParams);
|
|
90
103
|
const { state, updateState, updateUrl } = useUrlState(countState);
|
|
91
104
|
|
|
92
105
|
// won't let you to accidently mutate state directly, requires TS
|
|
@@ -103,9 +116,13 @@ function MyComponent() {
|
|
|
103
116
|
<button onClick={() => updateState({ count: state.count + 1 })}>
|
|
104
117
|
Increment (Local Only)
|
|
105
118
|
</button>
|
|
106
|
-
<button onClick={() => updateUrl(
|
|
119
|
+
<button onClick={() => updateUrl()}>
|
|
107
120
|
Sync changes to url
|
|
108
121
|
</button>
|
|
122
|
+
|
|
123
|
+
<button onClick={() => updateUrl(state)}>
|
|
124
|
+
Reset
|
|
125
|
+
</button>
|
|
109
126
|
</div>
|
|
110
127
|
)
|
|
111
128
|
}
|
|
@@ -164,6 +181,23 @@ function Component() {
|
|
|
164
181
|
}
|
|
165
182
|
```
|
|
166
183
|
|
|
184
|
+
#### Auto sync state
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const timer = React.useRef(0 as unknown as NodeJS.Timeout);
|
|
188
|
+
React.useEffect(() => {
|
|
189
|
+
clearTimeout(timer.current);
|
|
190
|
+
timer.current = setTimeout(() => {
|
|
191
|
+
// will compare state by content not by reference and fire update only for new values
|
|
192
|
+
updateUrl(state);
|
|
193
|
+
}, 500);
|
|
194
|
+
|
|
195
|
+
return () => {
|
|
196
|
+
clearTimeout(timer.current);
|
|
197
|
+
};
|
|
198
|
+
}, [state, updateUrl]);
|
|
199
|
+
```
|
|
200
|
+
|
|
167
201
|
#### With arbitrary state shape (not recommended)
|
|
168
202
|
|
|
169
203
|
```typescript
|
|
@@ -248,9 +282,25 @@ const obj = Object.fromEntries(
|
|
|
248
282
|
)
|
|
249
283
|
```
|
|
250
284
|
|
|
285
|
+
## Best Practices
|
|
286
|
+
|
|
287
|
+
- Define your state shape as a constant to ensure consistency
|
|
288
|
+
- Use TypeScript for enhanced type safety and autocomplete
|
|
289
|
+
- Avoid storing sensitive information in URL parameters
|
|
290
|
+
- Use `updateState` for frequent updates and `updateUrl` to sync changes to url
|
|
291
|
+
|
|
251
292
|
## Gothas
|
|
252
293
|
|
|
253
294
|
1. Can pass only serializable values, `Function`, `BigInt` or `Symbol` won't work, probably things like `ArrayBuffer` neither.
|
|
295
|
+
2. Vercel servers limit size of headers (query string and other stuff) to **14KB**, so keep your URL state under ~5000 words. https://vercel.com/docs/errors/URL_TOO_LONG
|
|
296
|
+
|
|
297
|
+
## Run locally
|
|
298
|
+
Clone this repo, run `npm install` and
|
|
299
|
+
```sh
|
|
300
|
+
npm run dev
|
|
301
|
+
```
|
|
302
|
+
Go to [localhost:3000](http://localhost:3000)
|
|
303
|
+
|
|
254
304
|
|
|
255
305
|
## Contact & Support
|
|
256
306
|
|
|
@@ -263,6 +313,8 @@ const obj = Object.fromEntries(
|
|
|
263
313
|
This project is licensed under the [MIT license](https://github.com/asmyshlyaev177/state-in-url/blob/main/LICENSE).
|
|
264
314
|
|
|
265
315
|
## Inspiration
|
|
266
|
-
[
|
|
316
|
+
[Using URL to store state in Vue ](https://dev.to/jacobandrewsky/using-url-to-store-state-in-vue-275c)
|
|
317
|
+
|
|
318
|
+
[Storing state in the URL](https://antonz.org/storing-state/)
|
|
267
319
|
|
|
268
320
|
[NextJS useSearchParams](https://nextjs.org/docs/app/api-reference/functions/use-search-params)
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useRouter as
|
|
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};function p(t,e){return{...e,...y(JSON.stringify(t),e)}}const d=(t,e)=>{const n="string"==typeof e,r=n&&u(e?.replaceAll?.("'",'"'));return r===f?e:t&&n?r:e};function y(t,e){try{return JSON.parse(t,d)}catch{const n=l(t);return n!==f?n:e}}function b(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 S(t,e){return{...e||{},...Object.fromEntries([...c(t).entries()].map((([t,n])=>{const r=e?.[t];return[t,u(n,r)??r]})))}}function m(e){const r=t.useCallback((function(t,r){return"object"===n(t)?b(t,e,r):""}),[e]);return{parse:t.useCallback((function(t){return S(t,e)}),[e]),stringify:r}}const h=new WeakMap,w=new WeakMap;function O(n,c){const{state:s,getState:a,setState:u,stringify:i}=function(e){const n=t.useRef(e),{parse:c,stringify:s}=m(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}));return t.useInsertionEffect((()=>{const t=w.get(n.current)||[],r=()=>{u(h.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((()=>h.get(n.current)||n.current),[]),setState:t.useCallback((t=>{const e=h.get(n.current)||n.current;if("function"==typeof t){const r=t(e);if(o(e,r))return!1;h.set(n.current,r),(w.get(n.current)||[]).forEach((t=>{t()}))}else{if(o(e,t))return!1;h.set(n.current,t),(w.get(n.current)||[]).forEach((t=>{t()}))}}),[]),parse:c,stringify:s}}(n),l=e();return{updateUrl:t.useCallback(((t,e)=>{const n=window.location.search,r=`${window.location.pathname}${n.length?"?":""}${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:r()?p(c,n):s}}export{u as decode,S as decodeState,a as encode,b as encodeState,m as useUrlEncode,O as useUrlState};
|
|
@@ -11,6 +11,8 @@ import { type JSONCompatible, type UnknownObj } from './utils';
|
|
|
11
11
|
* export const form = { name: '' };
|
|
12
12
|
* encodeState({ name: 'test' }, form, 'someExistingParam=123');
|
|
13
13
|
* ```
|
|
14
|
+
*
|
|
15
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
14
16
|
*/
|
|
15
17
|
export declare function encodeState<T>(state: never extends T ? object : JSONCompatible<T>, defaults?: JSONCompatible<T>, paramsToKeep?: string | URLSearchParams): string;
|
|
16
18
|
/**
|
|
@@ -24,5 +26,7 @@ export declare function encodeState<T>(state: never extends T ? object : JSONCom
|
|
|
24
26
|
* export const form = { name: '' };
|
|
25
27
|
* decodeState('key=value&name=Alex', form);
|
|
26
28
|
* ```
|
|
29
|
+
*
|
|
30
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
27
31
|
*/
|
|
28
32
|
export declare function decodeState<T>(uriString: string | URLSearchParams, defaults?: JSONCompatible<T>): undefined extends T ? UnknownObj : T;
|
|
@@ -3,25 +3,33 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @param {unknown} payload any value to serialize
|
|
5
5
|
* @returns {string} URLSearchParams compatible value string
|
|
6
|
+
*
|
|
7
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
6
8
|
*/
|
|
7
9
|
export declare function encode(payload: unknown): string;
|
|
8
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Decode value part of URLSearchParams back to JS value
|
|
12
|
+
*
|
|
13
|
+
* @param {string} payload URLSearchParams compatible value string
|
|
14
|
+
* @param {any} fallback optional fallback value
|
|
15
|
+
* @returns {unknown} decoded object
|
|
16
|
+
*
|
|
17
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
18
|
+
*/
|
|
19
|
+
export declare function decode<T>(payload: string, fallback?: T): T | Primitive;
|
|
20
|
+
export declare const replacer: (key: string, value: unknown) => unknown;
|
|
21
|
+
export type Primitive = Exclude<ReturnType<typeof decodePrimitive>, typeof errorSym>;
|
|
9
22
|
export declare const decodePrimitive: (str: string) => string | number | boolean | Date | typeof errorSym | null | undefined;
|
|
10
23
|
export declare const errorSym: unique symbol;
|
|
24
|
+
export declare const reviver: (key: string, value: unknown) => unknown;
|
|
11
25
|
/**
|
|
12
26
|
* Parses a JSON string into a TypeScript object.
|
|
13
27
|
*
|
|
14
28
|
* @param {string} jsonString - The JSON string to parse.
|
|
15
29
|
* @param {T} [fallbackValue] - The fallback value to use if parsing fails.
|
|
16
30
|
* @return {T | Primitive | undefined} - The parsed object or a primitive value, or undefined if parsing fails.
|
|
17
|
-
*/
|
|
18
|
-
export declare function parseJSON<T>(jsonString: string, fallbackValue?: T): T | Primitive | undefined;
|
|
19
|
-
/**
|
|
20
|
-
* Decode value part of URLSearchParams back to JS value
|
|
21
31
|
*
|
|
22
|
-
* @
|
|
23
|
-
* @param {any} fallback optional fallback value
|
|
24
|
-
* @returns {unknown} decoded object
|
|
32
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
25
33
|
*/
|
|
26
|
-
export declare function
|
|
27
|
-
export
|
|
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;
|
package/dist/urlstate/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { encode, decode } from './encoder';
|
|
2
|
-
import { type Type, type JSONCompatible, typeOf } from './utils';
|
|
1
|
+
import { encode, decode, parseSsrQs } from './encoder';
|
|
2
|
+
import { type Type, type JSONCompatible, typeOf, isSSR } from './utils';
|
|
3
3
|
import { useUrlEncode } from './useUrlEncode';
|
|
4
4
|
import { useUrlState } from './useUrlState';
|
|
5
5
|
import { encodeState, decodeState } from './encodeState';
|
|
6
|
-
export { encode, decode, typeOf, useUrlEncode, useUrlState, encodeState, decodeState, };
|
|
6
|
+
export { encode, decode, typeOf, useUrlEncode, useUrlState, encodeState, decodeState, isSSR, parseSsrQs, };
|
|
7
7
|
export type { Type, JSONCompatible };
|
|
@@ -0,0 +1,8 @@
|
|
|
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> | Readonly<JSONCompatible<T> extends infer T ? { readonly [P in keyof T]: Readonly<JSONCompatible<T>[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<JSONCompatible<T>[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<JSONCompatible<T>[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<JSONCompatible<T>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never> | ((currState: typeof defaultState) => typeof defaultState)) => false | undefined;
|
|
6
|
+
parse: (strOrSearchParams: string | URLSearchParams) => Readonly<NonNullable<JSONCompatible<T>> extends infer T_11 ? { readonly [P_11 in keyof T_11]: Readonly<NonNullable<JSONCompatible<T>>[P_11] extends infer T_12 ? { readonly [P_12 in keyof T_12]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12] extends infer T_13 ? { readonly [P_13 in keyof T_13]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13] extends infer T_14 ? { readonly [P_14 in keyof T_14]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14] extends infer T_15 ? { readonly [P_15 in keyof T_15]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15] extends infer T_16 ? { readonly [P_16 in keyof T_16]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16] extends infer T_17 ? { readonly [P_17 in keyof T_17]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17] extends infer T_18 ? { readonly [P_18 in keyof T_18]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18] extends infer T_19 ? { readonly [P_19 in keyof T_19]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19] extends infer T_20 ? { readonly [P_20 in keyof T_20]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19][P_20] extends infer T_21 ? { readonly [P_21 in keyof T_21]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>;
|
|
7
|
+
stringify: (state: JSONCompatible<T> | NonNullable<JSONCompatible<T>> | Readonly<NonNullable<JSONCompatible<T>> extends infer T_22 ? { readonly [P_11 in keyof T_22]: Readonly<NonNullable<JSONCompatible<T>>[P_11] extends infer T_23 ? { readonly [P_12 in keyof T_23]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12] extends infer T_24 ? { readonly [P_13 in keyof T_24]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13] extends infer T_25 ? { readonly [P_14 in keyof T_25]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14] extends infer T_26 ? { readonly [P_15 in keyof T_26]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15] extends infer T_27 ? { readonly [P_16 in keyof T_27]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16] extends infer T_28 ? { readonly [P_17 in keyof T_28]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17] extends infer T_29 ? { readonly [P_18 in keyof T_29]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18] extends infer T_30 ? { readonly [P_19 in keyof T_30]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19] extends infer T_31 ? { readonly [P_20 in keyof T_31]: Readonly<NonNullable<JSONCompatible<T>>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19][P_20] extends infer T_32 ? { readonly [P_21 in keyof T_32]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>, paramsToKeep?: string | URLSearchParams | undefined) => string;
|
|
8
|
+
};
|
|
@@ -4,7 +4,7 @@ import { type JSONCompatible, type DeepReadonly } from './utils';
|
|
|
4
4
|
* to and from URL search parameters.
|
|
5
5
|
*
|
|
6
6
|
* @template T - The type of the state shape
|
|
7
|
-
* @param {JSONCompatible<T>} [stateShape]
|
|
7
|
+
* @param {JSONCompatible<T>} [stateShape] Fallback values for state
|
|
8
8
|
* @returns {} `stringify` and `parse` functions
|
|
9
9
|
*
|
|
10
10
|
* * Example:
|
|
@@ -16,10 +16,10 @@ import { type JSONCompatible, type DeepReadonly } from './utils';
|
|
|
16
16
|
* // by default it's uses router.push with scroll: false
|
|
17
17
|
* parse('name=Tom');
|
|
18
18
|
* ```
|
|
19
|
+
*
|
|
20
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
19
21
|
*/
|
|
20
|
-
export declare function useUrlEncode<T>(stateShape
|
|
21
|
-
parse: (strOrSearchParams: string | URLSearchParams) =>
|
|
22
|
-
readonly [x: string]: Readonly<{}>;
|
|
23
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T ? { readonly [P in keyof T]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>;
|
|
22
|
+
export declare function useUrlEncode<T>(stateShape: JSONCompatible<T>): {
|
|
23
|
+
parse: (strOrSearchParams: string | URLSearchParams) => Readonly<NonNullable<JSONCompatible<T>> extends infer T ? { readonly [P in keyof T]: Readonly<NonNullable<JSONCompatible<T>>[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>;
|
|
24
24
|
stringify: (state: typeof stateShape | NonNullable<typeof stateShape> | DeepReadonly<NonNullable<typeof stateShape>>, paramsToKeep?: string | URLSearchParams) => string;
|
|
25
25
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useRouter } from 'next/navigation';
|
|
2
|
-
import { type JSONCompatible } from './utils';
|
|
2
|
+
import { DeepReadonly, type JSONCompatible } from './utils';
|
|
3
3
|
/**
|
|
4
4
|
* NextJS hook. Returns `state`, `updateState`, and `updateUrl` functions
|
|
5
5
|
*
|
|
6
|
-
* @param {
|
|
6
|
+
* @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
|
|
7
|
+
* @param {?SearchParams<T>} [searchParams] searchParams from Next server component
|
|
7
8
|
*
|
|
8
9
|
* * Example:
|
|
9
10
|
* ```ts
|
|
@@ -14,39 +15,13 @@ import { type JSONCompatible } from './utils';
|
|
|
14
15
|
* // by default it's uses router.push with scroll: false
|
|
15
16
|
* updateUrl({ name: 'test' }, { replace: true, scroll: true });
|
|
16
17
|
* ```
|
|
17
|
-
* * Auto update URL
|
|
18
|
-
* ```ts
|
|
19
|
-
* const timer = React.useRef(0 as unknown as NodeJS.Timeout);
|
|
20
|
-
* React.useEffect(() => {
|
|
21
|
-
* clearTimeout(timer.current);
|
|
22
|
-
* timer.current = setTimeout(() => {
|
|
23
|
-
* updateUrl(state);
|
|
24
|
-
* }, 500);
|
|
25
18
|
*
|
|
26
|
-
*
|
|
27
|
-
* clearTimeout(timer.current);
|
|
28
|
-
* };
|
|
29
|
-
* }, [state, updateUrl]);
|
|
30
|
-
* ```
|
|
19
|
+
* * Github {@link https://github.com/asmyshlyaev177/state-in-url}
|
|
31
20
|
*/
|
|
32
|
-
export declare function useUrlState<T>(defaultState
|
|
33
|
-
updateUrl: (value:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
readonly [x: string]: Readonly<{}>;
|
|
37
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T ? { readonly [P in keyof T]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>) => undefined extends T ? Readonly<{
|
|
38
|
-
readonly [x: string]: Readonly<{}>;
|
|
39
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T ? { readonly [P in keyof T]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>), options?: Options) => void;
|
|
40
|
-
updateState: (value: (undefined extends T ? Readonly<{
|
|
41
|
-
readonly [x: string]: Readonly<{}>;
|
|
42
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T_11 ? { readonly [P in keyof T_11]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_12 ? { readonly [P_1 in keyof T_12]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_13 ? { readonly [P_2 in keyof T_13]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_14 ? { readonly [P_3 in keyof T_14]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_15 ? { readonly [P_4 in keyof T_15]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_16 ? { readonly [P_5 in keyof T_16]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_17 ? { readonly [P_6 in keyof T_17]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_18 ? { readonly [P_7 in keyof T_18]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_19 ? { readonly [P_8 in keyof T_19]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_20 ? { readonly [P_9 in keyof T_20]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_21 ? { readonly [P_10 in keyof T_21]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>) | ((currState: undefined extends T ? Readonly<{
|
|
43
|
-
readonly [x: string]: Readonly<{}>;
|
|
44
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T_11 ? { readonly [P in keyof T_11]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_12 ? { readonly [P_1 in keyof T_12]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_13 ? { readonly [P_2 in keyof T_13]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_14 ? { readonly [P_3 in keyof T_14]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_15 ? { readonly [P_4 in keyof T_15]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_16 ? { readonly [P_5 in keyof T_16]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_17 ? { readonly [P_6 in keyof T_17]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_18 ? { readonly [P_7 in keyof T_18]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_19 ? { readonly [P_8 in keyof T_19]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_20 ? { readonly [P_9 in keyof T_20]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_21 ? { readonly [P_10 in keyof T_21]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>) => undefined extends T ? Readonly<{
|
|
45
|
-
readonly [x: string]: Readonly<{}>;
|
|
46
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T_11 ? { readonly [P in keyof T_11]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_12 ? { readonly [P_1 in keyof T_12]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_13 ? { readonly [P_2 in keyof T_13]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_14 ? { readonly [P_3 in keyof T_14]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_15 ? { readonly [P_4 in keyof T_15]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_16 ? { readonly [P_5 in keyof T_16]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_17 ? { readonly [P_6 in keyof T_17]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_18 ? { readonly [P_7 in keyof T_18]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_19 ? { readonly [P_8 in keyof T_19]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_20 ? { readonly [P_9 in keyof T_20]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_21 ? { readonly [P_10 in keyof T_21]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>)) => void;
|
|
47
|
-
state: undefined extends T ? Readonly<{
|
|
48
|
-
readonly [x: string]: Readonly<{}>;
|
|
49
|
-
}> : Readonly<JSONCompatible<T> & {} extends infer T_22 ? { readonly [P in keyof T_22]: Readonly<(JSONCompatible<T> & {})[P] extends infer T_23 ? { readonly [P_1 in keyof T_23]: Readonly<(JSONCompatible<T> & {})[P][P_1] extends infer T_24 ? { readonly [P_2 in keyof T_24]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2] extends infer T_25 ? { readonly [P_3 in keyof T_25]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3] extends infer T_26 ? { readonly [P_4 in keyof T_26]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4] extends infer T_27 ? { readonly [P_5 in keyof T_27]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5] extends infer T_28 ? { readonly [P_6 in keyof T_28]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_29 ? { readonly [P_7 in keyof T_29]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_30 ? { readonly [P_8 in keyof T_30]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_31 ? { readonly [P_9 in keyof T_31]: Readonly<(JSONCompatible<T> & {})[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_32 ? { readonly [P_10 in keyof T_32]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>;
|
|
21
|
+
export declare function useUrlState<T>(defaultState: JSONCompatible<T>, sp?: object): {
|
|
22
|
+
updateUrl: (value?: NonNullable<JSONCompatible<T>> | Readonly<NonNullable<JSONCompatible<T>> extends infer T ? { readonly [P in keyof T]: Readonly<NonNullable<JSONCompatible<T>>[P] extends infer T_1 ? { readonly [P_1 in keyof T_1]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1] extends infer T_2 ? { readonly [P_2 in keyof T_2]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2] extends infer T_3 ? { readonly [P_3 in keyof T_3]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3] extends infer T_4 ? { readonly [P_4 in keyof T_4]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4] extends infer T_5 ? { readonly [P_5 in keyof T_5]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5] extends infer T_6 ? { readonly [P_6 in keyof T_6]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6] extends infer T_7 ? { readonly [P_7 in keyof T_7]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7] extends infer T_8 ? { readonly [P_8 in keyof T_8]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8] extends infer T_9 ? { readonly [P_9 in keyof T_9]: Readonly<NonNullable<JSONCompatible<T>>[P][P_1][P_2][P_3][P_4][P_5][P_6][P_7][P_8][P_9] extends infer T_10 ? { readonly [P_10 in keyof T_10]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never> | ((currState: typeof defaultState | DeepReadonly<typeof defaultState>) => typeof defaultState) | undefined, options?: Options) => void;
|
|
23
|
+
updateState: (value: JSONCompatible<T> | Readonly<JSONCompatible<T> extends infer T_11 ? { readonly [P_11 in keyof T_11]: Readonly<JSONCompatible<T>[P_11] extends infer T_12 ? { readonly [P_12 in keyof T_12]: Readonly<JSONCompatible<T>[P_11][P_12] extends infer T_13 ? { readonly [P_13 in keyof T_13]: Readonly<JSONCompatible<T>[P_11][P_12][P_13] extends infer T_14 ? { readonly [P_14 in keyof T_14]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14] extends infer T_15 ? { readonly [P_15 in keyof T_15]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15] extends infer T_16 ? { readonly [P_16 in keyof T_16]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15][P_16] extends infer T_17 ? { readonly [P_17 in keyof T_17]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15][P_16][P_17] extends infer T_18 ? { readonly [P_18 in keyof T_18]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18] extends infer T_19 ? { readonly [P_19 in keyof T_19]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19] extends infer T_20 ? { readonly [P_20 in keyof T_20]: Readonly<JSONCompatible<T>[P_11][P_12][P_13][P_14][P_15][P_16][P_17][P_18][P_19][P_20] extends infer T_21 ? { readonly [P_21 in keyof T_21]: Readonly<any>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never>; } : never> | ((currState: JSONCompatible<T>) => JSONCompatible<T>)) => false | undefined;
|
|
24
|
+
state: JSONCompatible<T>;
|
|
50
25
|
};
|
|
51
26
|
type Router = ReturnType<typeof useRouter>;
|
|
52
27
|
type RouterOptions = NonNullable<Parameters<Router['push']>[1]>;
|
package/dist/urlstate/utils.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type Type = 'string' | 'date' | 'boolean' | 'number' | 'bigint' | 'undefi
|
|
|
8
8
|
* `function`, `symbol`, `array`
|
|
9
9
|
*/
|
|
10
10
|
export declare const typeOf: (val: unknown) => Type;
|
|
11
|
+
export declare const isSSR: () => boolean;
|
|
11
12
|
type JSONPrimitive = string | number | boolean | Date | null | undefined;
|
|
12
13
|
type JSONValue = JSONPrimitive | JSONValue[] | {
|
|
13
14
|
[key: string]: JSONValue;
|
|
@@ -23,4 +24,5 @@ export declare const getParams: (strOrSearchParams?: string | URLSearchParams) =
|
|
|
23
24
|
export type UnknownObj = {
|
|
24
25
|
[key: string]: unknown;
|
|
25
26
|
};
|
|
27
|
+
export declare const isEqual: (val1: unknown, val2: unknown) => boolean;
|
|
26
28
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-in-url",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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": [
|
|
@@ -76,10 +76,11 @@
|
|
|
76
76
|
"bump:ex": "npm i state-in-url@latest --workspace=packages/example-nextjs",
|
|
77
77
|
"build": "wireit",
|
|
78
78
|
"build:demo": "cd packages/example-nextjs && npx cross-env DEMO=true npm run build",
|
|
79
|
-
"start:demo": "cd packages/example-nextjs && npm run build &&
|
|
79
|
+
"start:demo": "npm run build && cd packages/example-nextjs && npm run build && npm run start",
|
|
80
80
|
"cleanup": "rm -rf dist",
|
|
81
81
|
"setup": "playwright install --with-deps",
|
|
82
82
|
"cleanupDist": "wireit",
|
|
83
|
+
"prepack": "npm run test:unit && npm run build",
|
|
83
84
|
"prepare": "npx husky"
|
|
84
85
|
},
|
|
85
86
|
"wireit": {
|
|
@@ -157,7 +158,7 @@
|
|
|
157
158
|
"devDependencies": {
|
|
158
159
|
"@commitlint/cli": "^19.0.3",
|
|
159
160
|
"@commitlint/config-conventional": "^19.0.3",
|
|
160
|
-
"@playwright/test": "^1.
|
|
161
|
+
"@playwright/test": "^1.45.1",
|
|
161
162
|
"@rollup/plugin-commonjs": "^25.0.7",
|
|
162
163
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
163
164
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
@@ -179,7 +180,7 @@
|
|
|
179
180
|
"jest": "^29.7.0",
|
|
180
181
|
"jest-environment-jsdom": "^29.7.0",
|
|
181
182
|
"lint-staged": "^15.2.2",
|
|
182
|
-
"playwright": "^1.
|
|
183
|
+
"playwright": "^1.45.1",
|
|
183
184
|
"prettier": "^3.2.5",
|
|
184
185
|
"rollup": "^2.79.1",
|
|
185
186
|
"rollup-plugin-copy": "^3.5.0",
|