state-in-url 3.0.7 → 3.1.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 +30 -38
- package/dist/next/useUrlState/useUrlState.d.ts +22 -10
- package/dist/next/useUrlState/useUrlState.mjs +1 -1
- package/dist/react-router/useUrlState/useUrlState.d.ts +23 -11
- package/dist/react-router/useUrlState/useUrlState.mjs +1 -1
- package/dist/useUrlStateBase/useUrlStateBase.mjs +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -144,31 +144,28 @@ import { useUrlState } from 'state-in-url/next';
|
|
|
144
144
|
import { userState } from './userState';
|
|
145
145
|
|
|
146
146
|
function MyComponent() {
|
|
147
|
-
// can pass `replace` arg, it's control will `
|
|
148
|
-
//
|
|
149
|
-
const {
|
|
147
|
+
// can pass `replace` arg, it's control will `setUrl` will use `rounter.push` or `router.replace`, default replace=true
|
|
148
|
+
// can pass `searchParams` from server components
|
|
149
|
+
const { urlState, setUrl } = useUrlState({ defaultState: userState });
|
|
150
150
|
|
|
151
151
|
// won't let you to accidently mutate state directly, requires TS
|
|
152
|
-
//
|
|
152
|
+
// urlState.name = 'John' // <- error
|
|
153
153
|
|
|
154
154
|
return (
|
|
155
155
|
<div>
|
|
156
|
-
<input value={
|
|
157
|
-
onChange={(ev) => {
|
|
158
|
-
onBlur={() => updateUrl()}
|
|
156
|
+
<input value={urlState.name}
|
|
157
|
+
onChange={(ev) => { setUrl({ name: ev.target.value }) }}
|
|
159
158
|
/>
|
|
160
|
-
<input value={
|
|
161
|
-
onChange={(ev) => {
|
|
162
|
-
onBlur={() => updateUrl()}
|
|
159
|
+
<input value={urlState.age}
|
|
160
|
+
onChange={(ev) => { setUrl({ age: +ev.target.value }) }}
|
|
163
161
|
/>
|
|
164
162
|
|
|
165
163
|
// same api as React.useState
|
|
166
|
-
<input value={
|
|
167
|
-
onChange={(ev) => {
|
|
168
|
-
onBlur={() => updateUrl()}
|
|
164
|
+
<input value={urlState.name}
|
|
165
|
+
onChange={(ev) => { setUrl(curr => ({ ...curr, name: ev.target.value })) }}
|
|
169
166
|
/>
|
|
170
167
|
|
|
171
|
-
<button onClick={() =>
|
|
168
|
+
<button onClick={() => setUrl(userState)}>
|
|
172
169
|
Reset
|
|
173
170
|
</button>
|
|
174
171
|
|
|
@@ -181,7 +178,7 @@ function MyComponent() {
|
|
|
181
178
|
|
|
182
179
|
<details>
|
|
183
180
|
<Summary>Example</Summary>
|
|
184
|
-
|
|
181
|
+
|
|
185
182
|
```typescript
|
|
186
183
|
export const form: Form = {
|
|
187
184
|
name: '',
|
|
@@ -205,19 +202,19 @@ import { useUrlState } from 'state-in-url/next';
|
|
|
205
202
|
import { form } from './form';
|
|
206
203
|
|
|
207
204
|
function TagsComponent() {
|
|
208
|
-
// `
|
|
209
|
-
const {
|
|
205
|
+
// `urlState` will infer from Form type!
|
|
206
|
+
const { urlState, setUrl } = useUrlState({ defaultState: form });
|
|
210
207
|
|
|
211
208
|
const onChangeTags = React.useCallback(
|
|
212
209
|
(tag: (typeof tags)[number]) => {
|
|
213
|
-
|
|
210
|
+
setUrl((curr) => ({
|
|
214
211
|
...curr,
|
|
215
212
|
tags: curr.tags.find((t) => t.id === tag.id)
|
|
216
213
|
? curr.tags.filter((t) => t.id !== tag.id)
|
|
217
214
|
: curr.tags.concat(tag),
|
|
218
215
|
}));
|
|
219
216
|
},
|
|
220
|
-
[
|
|
217
|
+
[setUrl],
|
|
221
218
|
);
|
|
222
219
|
|
|
223
220
|
return (
|
|
@@ -226,7 +223,7 @@ function TagsComponent() {
|
|
|
226
223
|
<div className="flex flex-wrap gap-2">
|
|
227
224
|
{tags.map((tag) => (
|
|
228
225
|
<Tag
|
|
229
|
-
active={!!
|
|
226
|
+
active={!!urlState.tags.find((t) => t.id === tag.id)}
|
|
230
227
|
text={tag.value.text}
|
|
231
228
|
onClick={() => onChangeTags(tag)}
|
|
232
229
|
key={tag.id}
|
|
@@ -257,26 +254,25 @@ const tags = [
|
|
|
257
254
|
[Demo page example code](https://github.com/asmyshlyaev177/state-in-url/blob/master/packages/example-nextjs14/src/app/Form.tsx)
|
|
258
255
|
</details>
|
|
259
256
|
|
|
260
|
-
|
|
261
|
-
#### Auto sync state
|
|
257
|
+
#### Update state only and sync to URL manually
|
|
262
258
|
|
|
263
259
|
<details>
|
|
264
260
|
<Summary>Example</Summary>
|
|
265
261
|
|
|
266
262
|
```typescript
|
|
267
|
-
|
|
263
|
+
|
|
268
264
|
const timer = React.useRef(0 as unknown as NodeJS.Timeout);
|
|
269
265
|
React.useEffect(() => {
|
|
270
266
|
clearTimeout(timer.current);
|
|
271
267
|
timer.current = setTimeout(() => {
|
|
272
268
|
// will compare state by content not by reference and fire update only for new values
|
|
273
|
-
|
|
269
|
+
setUrl(urlState);
|
|
274
270
|
}, 500);
|
|
275
271
|
|
|
276
272
|
return () => {
|
|
277
273
|
clearTimeout(timer.current);
|
|
278
274
|
};
|
|
279
|
-
}, [
|
|
275
|
+
}, [urlState, setUrl]);
|
|
280
276
|
```
|
|
281
277
|
|
|
282
278
|
Syncing state `onBlur` will be more aligned with real world usage.
|
|
@@ -287,13 +283,11 @@ Syncing state `onBlur` will be more aligned with real world usage.
|
|
|
287
283
|
|
|
288
284
|
</details>
|
|
289
285
|
|
|
290
|
-
|
|
291
|
-
|
|
292
286
|
#### With server side rendering
|
|
293
287
|
|
|
294
288
|
<details>
|
|
295
289
|
<Summary>Example</Summary>
|
|
296
|
-
|
|
290
|
+
|
|
297
291
|
```typescript
|
|
298
292
|
export default async function Home({ searchParams }: { searchParams: object }) {
|
|
299
293
|
return (
|
|
@@ -308,7 +302,7 @@ import { useUrlState } from 'state-in-url/next';
|
|
|
308
302
|
import { form } from './form';
|
|
309
303
|
|
|
310
304
|
const Form = ({ searchParams }: { searchParams: object }) => {
|
|
311
|
-
const {
|
|
305
|
+
const { urlState, setState, setUrl } = useUrlState({ defaultState: form, searchParams });
|
|
312
306
|
}
|
|
313
307
|
```
|
|
314
308
|
|
|
@@ -362,6 +356,7 @@ export default async function Layout({
|
|
|
362
356
|
|
|
363
357
|
|
|
364
358
|
```
|
|
359
|
+
|
|
365
360
|
</details>
|
|
366
361
|
|
|
367
362
|
#### With arbitrary state shape (not recommended)
|
|
@@ -376,12 +371,11 @@ import { useUrlState } from 'state-in-url/next';
|
|
|
376
371
|
const someObj = {};
|
|
377
372
|
|
|
378
373
|
function SettingsComponent() {
|
|
379
|
-
const {
|
|
374
|
+
const { urlState, setUrl, setState } = useUrlState<object>(someObj);
|
|
380
375
|
}
|
|
381
376
|
```
|
|
382
|
-
</details>
|
|
383
|
-
|
|
384
377
|
|
|
378
|
+
</details>
|
|
385
379
|
|
|
386
380
|
## useUrlState hook for React-Router
|
|
387
381
|
|
|
@@ -414,18 +408,18 @@ import { useUrlState } from 'state-in-url/react-router';
|
|
|
414
408
|
import { form } from './form';
|
|
415
409
|
|
|
416
410
|
function TagsComponent() {
|
|
417
|
-
const {
|
|
411
|
+
const { urlState, setUrl } = useUrlState({ defaultState: form });
|
|
418
412
|
|
|
419
413
|
const onChangeTags = React.useCallback(
|
|
420
414
|
(tag: (typeof tags)[number]) => {
|
|
421
|
-
|
|
415
|
+
setUrl((curr) => ({
|
|
422
416
|
...curr,
|
|
423
417
|
tags: curr.tags.find((t) => t.id === tag.id)
|
|
424
418
|
? curr.tags.filter((t) => t.id !== tag.id)
|
|
425
419
|
: curr.tags.concat(tag),
|
|
426
420
|
}));
|
|
427
421
|
},
|
|
428
|
-
[
|
|
422
|
+
[setUrl],
|
|
429
423
|
);
|
|
430
424
|
|
|
431
425
|
return (
|
|
@@ -434,7 +428,7 @@ function TagsComponent() {
|
|
|
434
428
|
<div className="flex flex-wrap gap-2">
|
|
435
429
|
{tags.map((tag) => (
|
|
436
430
|
<Tag
|
|
437
|
-
active={!!
|
|
431
|
+
active={!!urlState.tags.find((t) => t.id === tag.id)}
|
|
438
432
|
text={tag.value.text}
|
|
439
433
|
onClick={() => onChangeTags(tag)}
|
|
440
434
|
key={tag.id}
|
|
@@ -506,8 +500,6 @@ function SettingsComponent() {
|
|
|
506
500
|
- Define your state shape as a constant
|
|
507
501
|
- Use TypeScript for enhanced type safety and autocomplete
|
|
508
502
|
- Avoid storing sensitive information in URL parameters (SSN, API keys etc)
|
|
509
|
-
- Use `updateState` for frequent updates and `updateUrl` to sync changes to url
|
|
510
|
-
- Use `Suspence` to wrap client components in Next.js
|
|
511
503
|
- Use this [extension](https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors) for readable TS errors
|
|
512
504
|
|
|
513
505
|
## Gothas
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useRouter } from "next/navigation";
|
|
2
2
|
import { type DeepReadonly, type JSONCompatible } from "../../utils";
|
|
3
3
|
/**
|
|
4
|
-
* NextJS hook. Returns `
|
|
4
|
+
* NextJS hook. Returns `urlState`, `setState`, and `setUrl` functions
|
|
5
5
|
*
|
|
6
6
|
* @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
|
|
7
7
|
* @param {?SearchParams<T>} [searchParams] searchParams from Next server component
|
|
@@ -9,15 +9,15 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
|
|
|
9
9
|
* * Example:
|
|
10
10
|
* ```ts
|
|
11
11
|
* export const form = { name: '', age: 0 };
|
|
12
|
-
* const {
|
|
12
|
+
* const { urlState, setState, setUrl } = useUrlState({ defaultState: form });
|
|
13
13
|
* // for nextjs seerver components
|
|
14
|
-
* // const {
|
|
14
|
+
* // const { urlState, setState, setUrl } = useUrlState({ defaultState: form, searchParams });
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* setState({ name: 'test' });
|
|
17
17
|
* // by default it's uses router.push with scroll: false
|
|
18
|
-
*
|
|
18
|
+
* setUrl({ name: 'test' }, { replace: true, scroll: true });
|
|
19
19
|
* // similar to React.useState
|
|
20
|
-
*
|
|
20
|
+
* setUrl(curr => ({ ...curr, name: 'test' }), { replace: true, scroll: true });
|
|
21
21
|
* ```
|
|
22
22
|
*
|
|
23
23
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#api}
|
|
@@ -31,25 +31,37 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, se
|
|
|
31
31
|
/**
|
|
32
32
|
* * Example:
|
|
33
33
|
* ```ts
|
|
34
|
-
*
|
|
34
|
+
* setState({ name: 'test' });
|
|
35
35
|
* // or
|
|
36
|
-
*
|
|
36
|
+
* setState(curr => ({ ...curr, name: 'test' }) );
|
|
37
37
|
* ```
|
|
38
38
|
*
|
|
39
39
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updatestate}
|
|
40
40
|
*/
|
|
41
|
+
setState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated use `setState`
|
|
44
|
+
*/
|
|
41
45
|
updateState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
|
|
42
46
|
/**
|
|
43
47
|
* * Example:
|
|
44
48
|
* ```ts
|
|
45
|
-
*
|
|
49
|
+
* setUrl({ name: 'test' });
|
|
46
50
|
* // or
|
|
47
|
-
*
|
|
51
|
+
* setUrl(curr => ({ ...curr, name: 'test' }), { replace: true, scroll: false } );
|
|
48
52
|
* ```
|
|
49
53
|
*
|
|
50
54
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updateurl}
|
|
51
55
|
*/
|
|
56
|
+
setUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated use `setUrl`
|
|
59
|
+
*/
|
|
52
60
|
updateUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
|
|
61
|
+
urlState: DeepReadonly<DeepReadonly<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated use `urlState`
|
|
64
|
+
*/
|
|
53
65
|
state: DeepReadonly<DeepReadonly<T>>;
|
|
54
66
|
getState: () => T;
|
|
55
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useRouter as t,useSearchParams as e}from"next/navigation";import a from"react";import{parseSPObj as r}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{isSSR as o,filterUnknownParams as m,filterUnknownParamsClient as
|
|
1
|
+
import{useRouter as t,useSearchParams as e}from"next/navigation";import a from"react";import{parseSPObj as r}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{isSSR as o,filterUnknownParams as m,filterUnknownParamsClient as l}from"../../utils.mjs";function p({defaultState:p,searchParams:c,...i}){const n=t(),{state:f,updateState:S,updateUrl:d,getState:j}=s(p,n,(({parse:t})=>o()?r(m(p,c),p):t(l(p)))),U=a.useCallback(((t,e)=>{const a={...u,...i,...e};d(t,a)}),[d,i]),b=e();return a.useEffect((()=>{S(m(p,r(Object.fromEntries([...b.entries()]),p)))}),[b]),{setState:S,updateState:S,setUrl:U,updateUrl:U,urlState:f,state:f,getState:j}}const u={replace:!0,scroll:!1};export{p as useUrlState};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { type NavigateOptions } from "react-router-dom";
|
|
2
2
|
import { type DeepReadonly, type JSONCompatible } from "../../utils";
|
|
3
3
|
/**
|
|
4
|
-
* React-router hook. Returns `
|
|
4
|
+
* React-router hook. Returns `urlState`, `setState`, and `setUrl` functions
|
|
5
5
|
*
|
|
6
6
|
* @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
|
|
7
7
|
* @param {NavigateOptions} [NavigateOptions] See type from `react-router-dom`
|
|
8
8
|
* * Example:
|
|
9
9
|
* ```ts
|
|
10
10
|
* export const form = { name: '', age: 0 };
|
|
11
|
-
* const {
|
|
11
|
+
* const { urlState, setState, setUrl } = useUrlState({ defaultState: form, replace: false, preventScrollReset: false });
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* setState({ name: 'test' });
|
|
14
|
+
* setUrl({ name: 'test' }, { replace: true });
|
|
15
15
|
* // similar to React.useState
|
|
16
|
-
*
|
|
16
|
+
* setUrl(curr => ({ ...curr, name: 'test' }), { replace: true });
|
|
17
17
|
* ```
|
|
18
18
|
*
|
|
19
19
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#api}
|
|
@@ -24,29 +24,41 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, ..
|
|
|
24
24
|
/**
|
|
25
25
|
* * Example:
|
|
26
26
|
* ```ts
|
|
27
|
-
*
|
|
27
|
+
* setUrlState({ name: 'test' });
|
|
28
28
|
* // or
|
|
29
|
-
*
|
|
29
|
+
* setUrlState(curr => ({ ...curr, name: 'test' }) );
|
|
30
30
|
* // can pass optional React-Router `NavigateOptions`
|
|
31
|
-
*
|
|
31
|
+
* setUrlState(curr => ({ ...curr, name: 'test', preventScrollReset: false }) );
|
|
32
32
|
* ```
|
|
33
33
|
*
|
|
34
34
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updatestate}
|
|
35
35
|
*/
|
|
36
|
+
setState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
|
|
37
|
+
/**
|
|
38
|
+
* @deprecated use `setState`
|
|
39
|
+
*/
|
|
36
40
|
updateState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
|
|
37
41
|
/**
|
|
38
42
|
* * Example:
|
|
39
43
|
* ```ts
|
|
40
|
-
*
|
|
44
|
+
* setUrl({ name: 'test' });
|
|
41
45
|
* // or
|
|
42
|
-
*
|
|
46
|
+
* setUrl(curr => ({ ...curr, name: 'test' }), { replace: true } );
|
|
43
47
|
* // can pass optional React-Router `NavigateOptions`
|
|
44
|
-
*
|
|
48
|
+
* setState(curr => ({ ...curr, name: 'test', preventScrollReset: false }) );
|
|
45
49
|
* ```
|
|
46
50
|
*
|
|
47
51
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updateurl}
|
|
48
52
|
*/
|
|
53
|
+
setUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
|
|
54
|
+
/**
|
|
55
|
+
* @deprecated use `setUrl`
|
|
56
|
+
*/
|
|
49
57
|
updateUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
|
|
58
|
+
urlState: DeepReadonly<DeepReadonly<T>>;
|
|
59
|
+
/**
|
|
60
|
+
* @deprecated use `urlState`
|
|
61
|
+
*/
|
|
50
62
|
state: DeepReadonly<DeepReadonly<T>>;
|
|
51
63
|
getState: () => T;
|
|
52
64
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useNavigate as e,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{filterUnknownParamsClient as o,assignValue as m,filterUnknownParams as p}from"../../utils.mjs";function u({defaultState:u,...
|
|
1
|
+
import t from"react";import{useNavigate as e,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{filterUnknownParamsClient as o,assignValue as m,filterUnknownParams as p}from"../../utils.mjs";function u({defaultState:u,...c}){const S=e(),f=t.useMemo((()=>({replace:(t,e)=>S(t,{...l,...c,...e}),push:(t,e)=>S(t,{...l,...c,...e})})),[S,c]),{state:i,updateState:n,updateUrl:d,getState:j}=s(u,f,(({parse:t})=>t(o(u)))),U=t.useCallback(((t,e)=>{const r={...l,...c,...e};d(t,r)}),[c]),[b]=r();return t.useEffect((()=>{n(m(u,i,p(u,a(Object.fromEntries([...b.entries()]),u))))}),[b]),{setState:n,updateState:n,setUrl:U,updateUrl:U,urlState:i,state:i,getState:j}}const l={replace:!0,preventScrollReset:!0};export{u as useUrlState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useInsertionEffect as e}from"../useInsertionEffect.mjs";import{useSharedState as
|
|
1
|
+
import t from"react";import{useInsertionEffect as e}from"../useInsertionEffect.mjs";import{useSharedState as n}from"../useSharedState/useSharedState.mjs";import{useUrlEncode as o}from"../useUrlEncode/useUrlEncode.mjs";import{filterUnknownParamsClient as r}from"../utils.mjs";function s(s,c,i){const{parse:u,stringify:f}=o(s),{state:h,getState:l,setState:m}=n(s,(()=>i?.({parse:u})||s));e((()=>{const t=()=>{const t=u(r(s));m(t)};return window.addEventListener(a,t),()=>{window.removeEventListener(a,t)}}),[m]);const p=t.useRef([]),d=t.useCallback(((t,e)=>{const n="function"==typeof t?t(l()):t?{...l(),...t}:l(),o=f(n,function(t){const e=Object.keys(t),n=window.location.search,o=new URLSearchParams(n),r=new URLSearchParams;return o.forEach(((t,n)=>!e.includes(n)&&r.set(n,t))),r}(s)),r=`${window.location.pathname}${o.length?"?":""}${o}${window.location.hash}`;if(r===`${window.location.pathname}${window.location.search}${window.location.hash}`)return;let a;m(n);const{replace:i,...u}=e||{};p.current.push([i?"replace":"push",r,u]),1===p.current.length&&queueMicrotask((()=>{for(;p.current.length;){const t=p.current.shift();if(!t)break;t?.[1]!==a?.[1]&&(a=t)}if(!a)return;const[t,e,n]=a;a=void 0,c[t](e,n)}))}),[c,f,l]);return{updateState:m,updateUrl:d,state:h,getState:l}}const a="popstate";export{s as useUrlStateBase};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-in-url",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Easily share complex state objects between unrelated React components, preserve types and structure, with TS validation. Deep links and url state synchronization wthout any hasssle or boilerplate.",
|
|
5
5
|
"homepage": "https://state-in-url.dev",
|
|
6
6
|
"keywords": [
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
"@babel/preset-typescript": "^7.24.7",
|
|
351
351
|
"@commitlint/cli": "^19.0.3",
|
|
352
352
|
"@commitlint/config-conventional": "^19.0.3",
|
|
353
|
-
"@playwright/test": "^1.
|
|
353
|
+
"@playwright/test": "^1.48.2",
|
|
354
354
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
355
355
|
"@rollup/plugin-terser": "^0.4.4",
|
|
356
356
|
"@rollup/plugin-typescript": "^12.1.0",
|
|
@@ -386,7 +386,7 @@
|
|
|
386
386
|
"jest-environment-jsdom": "^29.7.0",
|
|
387
387
|
"lint-staged": "^15.2.9",
|
|
388
388
|
"only-allow": "^1.2.1",
|
|
389
|
-
"playwright": "^1.
|
|
389
|
+
"playwright": "^1.48.2",
|
|
390
390
|
"prettier": "^3.2.5",
|
|
391
391
|
"prettier-plugin-tailwindcss": "^0.6.8",
|
|
392
392
|
"release-it": "^17.6.0",
|