state-in-url 4.0.4 → 4.0.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
@@ -20,10 +20,14 @@ English | [한국어](./README.KO.md) | [简体中文](./README.CN.md)
20
20
  [![npm](https://img.shields.io/npm/v/state-in-url.svg)](https://www.npmjs.com/package/state-in-url)
21
21
  ![Tests](https://github.com/asmyshlyaev177/state-in-url/actions/workflows/tests.yml/badge.svg?branch=master)
22
22
  [![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)
23
+ [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/73be54068b7f41b0b74a252579ac09ec)](https://app.codacy.com/gh/asmyshlyaev177/state-in-url/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
23
24
  [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](https://github.com/asmyshlyaev177/state-in-url/)
24
25
  [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)]([https://github.com/semantic-release/semantic-release](https://github.com/asmyshlyaev177/state-in-url))
25
26
  ![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/state-in-url.svg)
26
27
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/asmyshlyaev177/state-in-url/badge)](https://scorecard.dev/viewer/?uri=github.com/asmyshlyaev177/state-in-url)
28
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9679/badge)](https://www.bestpractices.dev/projects/9679)
29
+ <!-- or by embedding this in your HTML:
30
+ <a href="https://www.bestpractices.dev/projects/9679"><img src="https://www.bestpractices.dev/projects/9679/badge"></a> -->
27
31
 
28
32
  </div>
29
33
 
@@ -147,6 +151,7 @@ All components that use the same `state` object are automatically synchronized.
147
151
  // Only parameters with value different from default will go to the url.
148
152
  export const userState: UserState = { name: '', age: 0 }
149
153
 
154
+ // use `Type` not `Interface`!
150
155
  type UserState = { name: string, age: number }
151
156
  ```
152
157
 
@@ -161,10 +166,7 @@ import { userState } from './userState';
161
166
  function MyComponent() {
162
167
  // can pass `replace` arg, it's control will `setUrl` will use `rounter.push` or `router.replace`, default replace=true
163
168
  // can pass `searchParams` from server components
164
- const { urlState, setUrl, setState } = useUrlState({ defaultState: userState });
165
-
166
- // won't let you to accidently mutate state directly, requires TS
167
- // urlState.name = 'John' // <- error
169
+ const { urlState, setUrl, setState } = useUrlState(userState);
168
170
 
169
171
  return (
170
172
  <div>
@@ -220,7 +222,7 @@ import { form } from './form';
220
222
 
221
223
  function TagsComponent() {
222
224
  // `urlState` will infer from Form type!
223
- const { urlState, setUrl } = useUrlState({ defaultState: form });
225
+ const { urlState, setUrl } = useUrlState(form);
224
226
 
225
227
  const onChangeTags = React.useCallback(
226
228
  (tag: (typeof tags)[number]) => {
@@ -319,7 +321,7 @@ import { useUrlState } from 'state-in-url/next';
319
321
  import { form } from './form';
320
322
 
321
323
  const Form = ({ searchParams }: { searchParams: object }) => {
322
- const { urlState, setState, setUrl } = useUrlState({ defaultState: form, searchParams });
324
+ const { urlState, setState, setUrl } = useUrlState(form, { searchParams });
323
325
  }
324
326
  ```
325
327
 
@@ -425,7 +427,7 @@ import { useUrlState } from 'state-in-url/react-router';
425
427
  import { form } from './form';
426
428
 
427
429
  function TagsComponent() {
428
- const { urlState, setUrl, setState } = useUrlState({ defaultState: form });
430
+ const { urlState, setUrl, setState } = useUrlState(form);
429
431
 
430
432
  const onChangeTags = React.useCallback(
431
433
  (tag: (typeof tags)[number]) => {
@@ -539,7 +541,7 @@ const userState = {
539
541
  };
540
542
 
541
543
  export const useUserState = () => {
542
- const { urlState, setUrl } = useUrlState({ defaultState: userState });
544
+ const { urlState, setUrl } = useUrlState(userState);
543
545
 
544
546
  return { userState: urlState, setUserState: setUrl };;
545
547
  }
@@ -561,8 +563,10 @@ See [Contributing doc](CONTRIBUTING.md)
561
563
  ## Roadmap
562
564
 
563
565
  - [x] hook for `Next.js`
564
- - [x] hook for 'react-router`
565
- - [ ] hook for 'remix`
566
+ - [x] hook for `react-router`
567
+ - [ ] hook for `remix`
568
+ - [ ] hook for `svelte`
569
+ - [ ] hook for `astro`
566
570
  - [ ] hook for store state in hash ?
567
571
 
568
572
  ## Contact & Support
@@ -1,18 +1,32 @@
1
- import { useRouter } from "next/navigation";
2
- import { type DeepReadonly, type JSONCompatible } from "../../utils";
1
+ import { type JSONCompatible } from "../../utils";
2
+ /**
3
+ * @deprecated .
4
+ * * use format `useUrlState(defaultState, { ...otherParams })`
5
+ *
6
+ * .
7
+ */
8
+ export declare function useUrlState<T extends JSONCompatible>({ defaultState: T, searchParams, replace, scroll, useHistory, }: OldParams<T>): {
9
+ state: T;
10
+ urlState: T;
11
+ updateState: (value: Partial<T> | ((currState: T) => T)) => void;
12
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
13
+ updateUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
14
+ setUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
15
+ };
3
16
  /**
4
17
  * NextJS hook. Returns `urlState`, `setState`, and `setUrl` functions
5
18
  *
6
19
  * @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
7
- * @param {?SearchParams<T>} [searchParams] searchParams from Next server component
8
- * @param {boolean} [useHistory] use window.history for navigation, no _rsc requests https://github.com/vercel/next.js/discussions/59167
20
+ * @param {Object} params - Object with other parameters
21
+ * @param {?SearchParams<T>} params.searchParams searchParams from Next server component
22
+ * @param {boolean} params.useHistory use window.history for navigation, default true, no _rsc requests https://github.com/vercel/next.js/discussions/59167
9
23
  *
10
24
  * * Example:
11
25
  * ```ts
12
26
  * export const form = { name: '', age: 0 };
13
- * const { urlState, setState, setUrl } = useUrlState({ defaultState: form });
14
- * // for nextjs seerver components
15
- * // const { urlState, setState, setUrl } = useUrlState({ defaultState: form, searchParams });
27
+ * const { urlState, setState, setUrl } = useUrlState(form);
28
+ * // for nextjs server components
29
+ * const { urlState, setState, setUrl } = useUrlState(form, { searchParams });
16
30
  *
17
31
  * setState({ name: 'test' });
18
32
  * // by default it's uses router.push with scroll: false
@@ -23,53 +37,22 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
23
37
  *
24
38
  * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#api}
25
39
  */
26
- export declare function useUrlState<T extends JSONCompatible>({ defaultState, searchParams, useHistory, ...opts }: {
40
+ export declare function useUrlState<T extends JSONCompatible>(defaultState: T, params?: Params): {
41
+ urlState: T;
42
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
43
+ setUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
44
+ };
45
+ interface OldParams<T> {
27
46
  defaultState: T;
28
47
  searchParams?: object;
29
48
  replace?: boolean;
30
49
  scroll?: boolean;
31
50
  useHistory?: boolean;
32
- }): {
33
- /**
34
- * * Example:
35
- * ```ts
36
- * setState({ name: 'test' });
37
- * // or
38
- * setState(curr => ({ ...curr, name: 'test' }) );
39
- * ```
40
- *
41
- * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updatestate}
42
- */
43
- setState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
44
- /**
45
- * @deprecated use `setState`
46
- */
47
- updateState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
48
- /**
49
- * * Example:
50
- * ```ts
51
- * setUrl({ name: 'test' });
52
- * // or
53
- * setUrl(curr => ({ ...curr, name: 'test' }), { replace: true, scroll: false } );
54
- * ```
55
- *
56
- * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updateurl}
57
- */
58
- setUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
59
- /**
60
- * @deprecated use `setUrl`
61
- */
62
- updateUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
63
- urlState: DeepReadonly<DeepReadonly<T>>;
64
- /**
65
- * @deprecated use `urlState`
66
- */
67
- state: DeepReadonly<DeepReadonly<T>>;
68
- getState: () => T;
69
- };
70
- type Router = ReturnType<typeof useRouter>;
71
- type RouterOptions = NonNullable<Parameters<Router["push"]>[1] | Parameters<Router["replace"]>[1]>;
72
- interface Options extends RouterOptions {
73
- replace?: boolean;
74
51
  }
52
+ type Params = {
53
+ searchParams?: object;
54
+ replace?: boolean;
55
+ scroll?: boolean;
56
+ useHistory?: boolean;
57
+ };
75
58
  export {};
@@ -1 +1 @@
1
- import{useRouter as t,useSearchParams as e}from"next/navigation";import r from"react";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as o,isSSR as m,filterUnknownParams as u,filterUnknownParamsClient as i}from"../../utils.mjs";function l({defaultState:l,searchParams:c,useHistory:f,...n}){const S=void 0===f||f?o:t(),{state:d,updateState:j,updateUrl:U,getState:b}=s(l,S,(({parse:t})=>m()?a(u(l,c),l):t(i(l)))),g=r.useCallback(((t,e)=>U(t,{...p,...n,...e})),[U,n]),v=e();return r.useEffect((()=>{j(u(l,a(Object.fromEntries([...v.entries()]),l)))}),[v]),{setState:j,updateState:j,setUrl:g,updateUrl:g,urlState:d,state:d,getState:b}}const p={replace:!0,scroll:!1};export{l as useUrlState};
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{routerHistory as l,isSSR as o,filterUnknownParams as c,filterUnknownParamsClient as u}from"../../utils.mjs";function i(i,m){const f="defaultState"in i?i.defaultState:i,n="defaultState"in i?i.searchParams:m?.searchParams,S="defaultState"in i?i.useHistory:m?.useHistory,d="defaultState"in i?{scroll:i.scroll,replace:i.replace}:{scroll:m?.scroll,replace:m?.replace},j=void 0===S||S?l:t(),{state:U,updateState:b,updateUrl:g,getState:P}=s(f,j,(({parse:t})=>o()?r(c(f,n),f):t(u(f)))),h=a.useCallback(((t,e)=>g(t,{...p,...d,...e})),[g,d]),v=e();return a.useEffect((()=>{b(c(f,r(Object.fromEntries([...v.entries()]),f)))}),[v]),{setState:b,updateState:b,setUrl:h,updateUrl:h,urlState:U,state:U,getState:P}}const p={replace:!0,scroll:!1};export{i as useUrlState};
@@ -1,15 +1,30 @@
1
1
  import { type NavigateOptions } from "react-router-dom";
2
- import { type DeepReadonly, type JSONCompatible } from "../../utils";
2
+ import { type JSONCompatible } from "../../utils";
3
+ /**
4
+ * @deprecated .
5
+ * * use format `useUrlState(defaultState, { ...otherParams })`
6
+ *
7
+ * .
8
+ */
9
+ export declare function useUrlState<T extends JSONCompatible>({ defaultState: T, searchParams, replace, useHistory, }: OldParams<T>): {
10
+ state: T;
11
+ urlState: T;
12
+ updateState: (value: Partial<T> | ((currState: T) => T)) => void;
13
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
14
+ updateUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
15
+ setUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
16
+ };
3
17
  /**
4
18
  * React-router hook. Returns `urlState`, `setState`, and `setUrl` functions
5
19
  *
6
20
  * @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
7
- * @param {NavigateOptions} [NavigateOptions] See type from `react-router-dom`
8
- * @param {boolean} [useHistory] use window.history for navigation
21
+ * @param {Object} params - Object with other parameters
22
+ * @param {NavigateOptions} params.NavigateOptions See type from `react-router-dom`
23
+ * @param {boolean} params.useHistory use window.history for navigation
9
24
  * * Example:
10
25
  * ```ts
11
26
  * export const form = { name: '', age: 0 };
12
- * const { urlState, setState, setUrl } = useUrlState({ defaultState: form, replace: false, preventScrollReset: false });
27
+ * const { urlState, setState, setUrl } = useUrlState(form, { replace: false, preventScrollReset: false });
13
28
  *
14
29
  * setState({ name: 'test' });
15
30
  * setUrl({ name: 'test' }, { replace: true });
@@ -19,48 +34,20 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
19
34
  *
20
35
  * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#api}
21
36
  */
22
- export declare function useUrlState<T extends JSONCompatible>({ defaultState, useHistory, ...initOpts }: {
37
+ export declare function useUrlState<T extends JSONCompatible>(defaultState: T, params?: Params): {
38
+ urlState: T;
39
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
40
+ setUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
41
+ };
42
+ type OldParams<T> = {
23
43
  defaultState: T;
24
44
  useHistory?: boolean;
25
- } & NavigateOptions): {
26
- /**
27
- * * Example:
28
- * ```ts
29
- * setState({ name: 'test' });
30
- * // or
31
- * setState(curr => ({ ...curr, name: 'test' }) );
32
- * // can pass optional React-Router `NavigateOptions`
33
- * setState(curr => ({ ...curr, name: 'test', preventScrollReset: false }) );
34
- * ```
35
- *
36
- * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updatestate}
37
- */
38
- setState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
39
- /**
40
- * @deprecated use `setState`
41
- */
42
- updateState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
43
- /**
44
- * * Example:
45
- * ```ts
46
- * setUrl({ name: 'test' });
47
- * // or
48
- * setUrl(curr => ({ ...curr, name: 'test' }), { replace: true } );
49
- * // can pass optional React-Router `NavigateOptions`
50
- * setState(curr => ({ ...curr, name: 'test', preventScrollReset: false }) );
51
- * ```
52
- *
53
- * * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updateurl}
54
- */
55
- setUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
56
- /**
57
- * @deprecated use `setUrl`
58
- */
59
- updateUrl: (value?: Parameters<(value?: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
60
- urlState: DeepReadonly<DeepReadonly<T>>;
61
- /**
62
- * @deprecated use `urlState`
63
- */
64
- state: DeepReadonly<DeepReadonly<T>>;
65
- getState: () => T;
66
- };
45
+ searchParams?: object;
46
+ replace?: boolean;
47
+ } & NavigateOptions;
48
+ interface Params extends NavigateOptions {
49
+ useHistory?: boolean;
50
+ searchParams?: object;
51
+ replace?: boolean;
52
+ }
53
+ export {};
@@ -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{routerHistory as o,filterUnknownParamsClient as u,assignValue as m,filterUnknownParams as p}from"../../utils.mjs";function l({defaultState:l,useHistory:S,...f}){const i=e(),n=t.useMemo((()=>S?o:{replace:(t,e)=>i(t,{...c,...f,...e}),push:(t,e)=>i(t,{...c,...f,...e})}),[i,f]),{state:d,updateState:j,updateUrl:U,getState:b}=s(l,n,(({parse:t})=>t(u(l)))),g=t.useCallback(((t,e)=>U(t,{...c,...f,...e})),[f]),[B]=r();return t.useEffect((()=>{j(m(l,d,p(l,a(Object.fromEntries([...B.entries()]),l))))}),[B]),{setState:j,updateState:j,setUrl:g,updateUrl:g,urlState:d,state:d,getState:b}}const c={replace:!0,preventScrollReset:!0};export{l as useUrlState};
1
+ import e from"react";import{useNavigate as t,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as l,filterUnknownParamsClient as o,assignValue as p,filterUnknownParams as u}from"../../utils.mjs";function c(c,m){const n="defaultState"in c?c.defaultState:c,i="defaultState"in c?c.useHistory:m?.useHistory,f="defaultState"in c?{replace:c.replace,preventScrollReset:c.preventScrollReset}:{replace:m?.replace,preventScrollReset:m?.preventScrollReset},d=t(),j=e.useMemo((()=>i?l:{replace:(e,t)=>d(e,{...S,...f,...t}),push:(e,t)=>d(e,{...S,...f,...t})}),[d,f]),{state:v,updateState:R,updateUrl:U,getState:b}=s(n,j,(({parse:e})=>e(o(n)))),g=e.useCallback(((e,t)=>U(e,{...S,...f,...t})),[f]),[y]=r();return e.useEffect((()=>{R(p(n,u(n,a(Object.fromEntries([...y.entries()]),n))))}),[y]),{setState:R,updateState:R,setUrl:g,updateUrl:g,urlState:v,state:v,getState:b}}const S={replace:!0,preventScrollReset:!0};export{c as useUrlState};
@@ -1,4 +1,4 @@
1
- import { type DeepReadonly, type JSONCompatible } from "../utils";
1
+ import { type JSONCompatible } from "../utils";
2
2
  /**
3
3
  * Custom React hook for sharing state between unrelated components.
4
4
  *
@@ -20,5 +20,5 @@ import { type DeepReadonly, type JSONCompatible } from "../utils";
20
20
  export declare function useSharedState<T extends JSONCompatible>(defaultState: T, _getInitial?: () => T): {
21
21
  state: T;
22
22
  getState: () => T;
23
- setState: (value: (Partial<T> | Partial<DeepReadonly<T>>) | ((currState: T) => T)) => void;
23
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
24
24
  };
@@ -1,5 +1,5 @@
1
1
  import { useUrlEncode } from "../useUrlEncode";
2
- import { type DeepReadonly, type JSONCompatible, type Router } from "../utils";
2
+ import { type JSONCompatible, type Router } from "../utils";
3
3
  /**
4
4
  * A custom React hook to create custom hooks.
5
5
  *
@@ -24,9 +24,9 @@ import { type DeepReadonly, type JSONCompatible, type Router } from "../utils";
24
24
  export declare function useUrlStateBase<T extends JSONCompatible>(defaultState: T, router: Router, getInitialState?: ({ parse, }: {
25
25
  parse: ReturnType<typeof useUrlEncode<T>>["parse"];
26
26
  }) => T): {
27
- updateState: (value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void;
28
- updateUrl: (value?: Parameters<(value: Partial<T> | Partial<DeepReadonly<T>> | ((currState: T) => T)) => void>[0], options?: Options) => void;
29
- state: DeepReadonly<T>;
27
+ updateState: (value: Partial<T> | ((currState: T) => T)) => void;
28
+ updateUrl: (value?: Parameters<(value: Partial<T> | ((currState: T) => T)) => void>[0], options?: Options) => void;
29
+ state: T;
30
30
  getState: () => T;
31
31
  };
32
32
  interface OptionsObject {
package/dist/utils.d.ts CHANGED
@@ -15,9 +15,6 @@ export type JSON = null | boolean | Date | number | string | {
15
15
  export type JSONCompatible = {
16
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 ? {
19
- readonly [K in keyof T]: DeepReadonly<T[K]>;
20
- } : T;
21
18
  export declare const getParams: (strOrSearchParams?: string | URLSearchParams) => URLSearchParams;
22
19
  export type UnknownObj = object | {
23
20
  [key: string]: unknown;
@@ -25,7 +22,7 @@ export type UnknownObj = object | {
25
22
  export declare const isEqual: (val1: unknown, val2: unknown) => boolean;
26
23
  export declare function filterUnknownParamsClient<T extends object>(shape: T): string;
27
24
  export declare function filterUnknownParams<T extends object>(shape: T, searchParams?: object): T;
28
- export declare function assignValue<T extends object>(shape: T, curr: Partial<T>, newVal: Partial<T>): T;
25
+ export declare function assignValue<T extends object>(shape: T, newVal: Partial<T>): T;
29
26
  export interface Router {
30
27
  push: (href: string, opts: object) => void;
31
28
  replace: (href: string, opts: object) => void;
package/dist/utils.mjs CHANGED
@@ -1 +1 @@
1
- const t=t=>{const n=typeof t,e=null===t,r=Array.isArray(t),o=t instanceof Date;return(e?"null":o&&"date")||r&&"array"||!e&&!o&&!r&&"object"===n&&"object"||n},n=()=>"undefined"==typeof window,e=t=>new URLSearchParams("string"==typeof t?r(t):t?.toString?.()||""),r=t=>t.split("?")?.[1]||t||"",o=(t,n)=>JSON.stringify(t)===JSON.stringify(n);function i(t){const n=new URLSearchParams;return s(t,[...new URLSearchParams(window.location.search).entries()]).forEach((([t,e])=>n.set(t,e))),n.toString()}function c(t,n){return Object.fromEntries(s(t,Object.entries(n||{})))}function s(t,n){const e=Object.keys(t);return n.filter((([t])=>e.includes(t))).map((([t,n])=>[t.replaceAll("+"," "),n]))}function a(t,n,e){const r=Object.assign({},t,n);return Object.entries(t).forEach((([n])=>{const o=n,i=void 0!==e[o];r[o]=i?e[o]:t[o]})),r}const l={push:t=>{window&&window.history.pushState(null,"",t)},replace:t=>{window&&window.history.replaceState(null,"",t)}};export{a as assignValue,c as filterUnknownParams,i as filterUnknownParamsClient,e as getParams,o as isEqual,n as isSSR,l as routerHistory,t as typeOf};
1
+ const t=t=>{const n=typeof t,e=null===t,r=Array.isArray(t),o=t instanceof Date;return(e?"null":o&&"date")||r&&"array"||!e&&!o&&!r&&"object"===n&&"object"||n},n=()=>"undefined"==typeof window,e=t=>new URLSearchParams("string"==typeof t?r(t):t?.toString?.()||""),r=t=>t.split("?")?.[1]||t||"",o=(t,n)=>JSON.stringify(t)===JSON.stringify(n);function i(t){const n=new URLSearchParams;return s(t,[...new URLSearchParams(window.location.search).entries()]).forEach((([t,e])=>n.set(t,e))),n.toString()}function c(t,n){return Object.fromEntries(s(t,Object.entries(n||{})))}function s(t,n){const e=Object.keys(t);return n.filter((([t])=>e.includes(t))).map((([t,n])=>[t.replaceAll("+"," "),n]))}function a(t,n){const e=Object.assign({},t);return Object.entries(t).forEach((([r])=>{const o=r,i=void 0!==n[o];e[o]=i?n[o]:t[o]})),e}const l={push:t=>{window&&window.history.pushState(null,"",t)},replace:t=>{window&&window.history.replaceState(null,"",t)}};export{a as assignValue,c as filterUnknownParams,i as filterUnknownParamsClient,e as getParams,o as isEqual,n as isSSR,l as routerHistory,t as typeOf};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-in-url",
3
- "version": "4.0.4",
3
+ "version": "4.0.6",
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
  "repository": {
@@ -103,6 +103,7 @@
103
103
  "reinstall": "npm run cleanup && npm install",
104
104
  "setup": "playwright install --with-deps",
105
105
  "prepack": "npm run build && cp package.json dist/package.json && npm run build:demo",
106
+ "pin-gh-deps": "pin-github-action .github/workflows/tests.yml",
106
107
  "prepare": "npx husky"
107
108
  },
108
109
  "wireit": {
@@ -363,6 +364,7 @@
363
364
  "jest-environment-jsdom": "^29.7.0",
364
365
  "lint-staged": "^15.2.9",
365
366
  "only-allow": "^1.2.1",
367
+ "pin-github-action": "^1.9.1",
366
368
  "playwright": "^1.48.2",
367
369
  "prettier": "^3.2.5",
368
370
  "prettier-plugin-tailwindcss": "^0.6.8",