state-in-url 4.0.5 → 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,6 +20,7 @@ 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)
@@ -165,7 +166,7 @@ import { userState } from './userState';
165
166
  function MyComponent() {
166
167
  // can pass `replace` arg, it's control will `setUrl` will use `rounter.push` or `router.replace`, default replace=true
167
168
  // can pass `searchParams` from server components
168
- const { urlState, setUrl, setState } = useUrlState({ defaultState: userState });
169
+ const { urlState, setUrl, setState } = useUrlState(userState);
169
170
 
170
171
  return (
171
172
  <div>
@@ -221,7 +222,7 @@ import { form } from './form';
221
222
 
222
223
  function TagsComponent() {
223
224
  // `urlState` will infer from Form type!
224
- const { urlState, setUrl } = useUrlState({ defaultState: form });
225
+ const { urlState, setUrl } = useUrlState(form);
225
226
 
226
227
  const onChangeTags = React.useCallback(
227
228
  (tag: (typeof tags)[number]) => {
@@ -320,7 +321,7 @@ import { useUrlState } from 'state-in-url/next';
320
321
  import { form } from './form';
321
322
 
322
323
  const Form = ({ searchParams }: { searchParams: object }) => {
323
- const { urlState, setState, setUrl } = useUrlState({ defaultState: form, searchParams });
324
+ const { urlState, setState, setUrl } = useUrlState(form, { searchParams });
324
325
  }
325
326
  ```
326
327
 
@@ -426,7 +427,7 @@ import { useUrlState } from 'state-in-url/react-router';
426
427
  import { form } from './form';
427
428
 
428
429
  function TagsComponent() {
429
- const { urlState, setUrl, setState } = useUrlState({ defaultState: form });
430
+ const { urlState, setUrl, setState } = useUrlState(form);
430
431
 
431
432
  const onChangeTags = React.useCallback(
432
433
  (tag: (typeof tags)[number]) => {
@@ -540,7 +541,7 @@ const userState = {
540
541
  };
541
542
 
542
543
  export const useUserState = () => {
543
- const { urlState, setUrl } = useUrlState({ defaultState: userState });
544
+ const { urlState, setUrl } = useUrlState(userState);
544
545
 
545
546
  return { userState: urlState, setUserState: setUrl };;
546
547
  }
@@ -562,8 +563,10 @@ See [Contributing doc](CONTRIBUTING.md)
562
563
  ## Roadmap
563
564
 
564
565
  - [x] hook for `Next.js`
565
- - [x] hook for 'react-router`
566
- - [ ] hook for 'remix`
566
+ - [x] hook for `react-router`
567
+ - [ ] hook for `remix`
568
+ - [ ] hook for `svelte`
569
+ - [ ] hook for `astro`
567
570
  - [ ] hook for store state in hash ?
568
571
 
569
572
  ## Contact & Support
@@ -1,18 +1,32 @@
1
- import { useRouter } from "next/navigation";
2
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,56 +37,22 @@ import { 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> | ((currState: T) => T)) => void;
44
- /**
45
- * @deprecated use `setState`
46
- */
47
- updateState: (value: Partial<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> | ((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> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
63
- /**
64
- * State object. Don't mutate directly, use `setState` or `setUrl`
65
- */
66
- urlState: T;
67
- /**
68
- * @deprecated use `urlState`
69
- */
70
- state: T;
71
- getState: () => T;
72
- };
73
- type Router = ReturnType<typeof useRouter>;
74
- type RouterOptions = NonNullable<Parameters<Router["push"]>[1] | Parameters<Router["replace"]>[1]>;
75
- interface Options extends RouterOptions {
76
- replace?: boolean;
77
51
  }
52
+ type Params = {
53
+ searchParams?: object;
54
+ replace?: boolean;
55
+ scroll?: boolean;
56
+ useHistory?: boolean;
57
+ };
78
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
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,51 +34,20 @@ import { 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 }: {
23
- defaultState: T;
24
- 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> | ((currState: T) => T)) => void;
39
- /**
40
- * @deprecated use `setState`
41
- */
42
- updateState: (value: Partial<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> | ((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> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
60
- /**
61
- * State object. Don't mutate directly, use `setState` or `setUrl`
62
- */
37
+ export declare function useUrlState<T extends JSONCompatible>(defaultState: T, params?: Params): {
63
38
  urlState: T;
64
- /**
65
- * @deprecated use `urlState`
66
- */
67
- state: T;
68
- getState: () => T;
39
+ setState: (value: Partial<T> | ((currState: T) => T)) => void;
40
+ setUrl: (value?: Partial<T> | ((currState: T) => T)) => void;
69
41
  };
42
+ type OldParams<T> = {
43
+ defaultState: T;
44
+ useHistory?: boolean;
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};
package/dist/utils.d.ts CHANGED
@@ -22,7 +22,7 @@ export type UnknownObj = object | {
22
22
  export declare const isEqual: (val1: unknown, val2: unknown) => boolean;
23
23
  export declare function filterUnknownParamsClient<T extends object>(shape: T): string;
24
24
  export declare function filterUnknownParams<T extends object>(shape: T, searchParams?: object): T;
25
- 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;
26
26
  export interface Router {
27
27
  push: (href: string, opts: object) => void;
28
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.5",
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": {