Skip to content

Commit

Permalink
chore(release): 4.0.0 [skip ci]
Browse files Browse the repository at this point in the history
# [4.0.0](v3.1.0...v4.0.0) (2024-11-02)

### Features

* `useHistory` option to use native window.history instead of Next.js router, true by default ([6cb1a41](6cb1a41))

### BREAKING CHANGES

* For Next.js, `useUrlState` hook will use `window.history` for navigation by
default, to opt out pass `useUrlState({ useHistory: false })`
  • Loading branch information
semantic-release-bot committed Nov 2, 2024
1 parent 6cb1a41 commit fcad4e5
Show file tree
Hide file tree
Showing 10 changed files with 30 additions and 12 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# [4.0.0](https://github.com/asmyshlyaev177/state-in-url/compare/v3.1.0...v4.0.0) (2024-11-02)


### Features

* `useHistory` option to use native window.history instead of Next.js router, true by default ([6cb1a41](https://github.com/asmyshlyaev177/state-in-url/commit/6cb1a41ee1ab43e9a9c2b0e18f85d40054a60405))


### BREAKING CHANGES

* For Next.js, `useUrlState` hook will use `window.history` for navigation by
default, to opt out pass `useUrlState({ useHistory: false })`

# [3.1.0](https://github.com/asmyshlyaev177/state-in-url/compare/v3.0.7...v3.1.0) (2024-11-02)


Expand Down
4 changes: 3 additions & 1 deletion dist/next/useUrlState/useUrlState.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
*
* @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
* @param {?SearchParams<T>} [searchParams] searchParams from Next server component
* @param {boolean} [useHistory] use window.history for navigation, no _rsc requests https://github.com/vercel/next.js/discussions/59167
*
* * Example:
* ```ts
Expand All @@ -22,11 +23,12 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
*
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#api}
*/
export declare function useUrlState<T extends JSONCompatible>({ defaultState, searchParams, ...opts }: {
export declare function useUrlState<T extends JSONCompatible>({ defaultState, searchParams, useHistory, ...opts }: {
defaultState: T;
searchParams?: object;
replace?: boolean;
scroll?: boolean;
useHistory?: boolean;
}): {
/**
* * Example:
Expand Down
2 changes: 1 addition & 1 deletion dist/next/useUrlState/useUrlState.mjs
Original file line number Diff line number Diff line change
@@ -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 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};
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:n,...f}){const S=void 0===n||n?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)=>{const r={...p,...f,...e};U(t,r)}),[U,f]),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};
4 changes: 3 additions & 1 deletion dist/react-router/useUrlState/useUrlState.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
*
* @param {JSONCompatible<T>} [defaultState] Fallback (default) values for state
* @param {NavigateOptions} [NavigateOptions] See type from `react-router-dom`
* @param {boolean} [useHistory] use window.history for navigation
* * Example:
* ```ts
* export const form = { name: '', age: 0 };
Expand All @@ -18,8 +19,9 @@ import { type DeepReadonly, type JSONCompatible } from "../../utils";
*
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#api}
*/
export declare function useUrlState<T extends JSONCompatible>({ defaultState, ...initOpts }: {
export declare function useUrlState<T extends JSONCompatible>({ defaultState, useHistory, ...initOpts }: {
defaultState: T;
useHistory?: boolean;
} & NavigateOptions): {
/**
* * Example:
Expand Down
2 changes: 1 addition & 1 deletion dist/react-router/useUrlState/useUrlState.mjs
Original file line number Diff line number Diff line change
@@ -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,...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};
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)=>{const r={...c,...f,...e};U(t,r)}),[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};
6 changes: 1 addition & 5 deletions dist/useUrlStateBase/useUrlStateBase.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useUrlEncode } from "../useUrlEncode";
import { type DeepReadonly, type JSONCompatible } from "../utils";
import { type DeepReadonly, type JSONCompatible, type Router } from "../utils";
/**
* A custom React hook to create custom hooks.
*
Expand Down Expand Up @@ -35,8 +35,4 @@ interface OptionsObject {
export interface Options extends OptionsObject {
replace?: boolean;
}
type Router = {
push: (href: string, opts: object) => void;
replace: (href: string, opts: object) => void;
};
export {};
2 changes: 1 addition & 1 deletion dist/useUrlStateBase/useUrlStateBase.mjs
Original file line number Diff line number Diff line change
@@ -1 +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};
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:h}=o(s),{state:l,getState:m,setState:p}=n(s,(()=>i?.({parse:u})||s));e((()=>{const t=()=>{const t=u(r(s));p(t)};return window.addEventListener(a,t),()=>{window.removeEventListener(a,t)}}),[p]);const d=t.useRef([]),w=t.useCallback(((t,e)=>{const n="function"==typeof t?t(m()):t?{...m(),...t}:m(),o=h(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;p(n);const{replace:i,...u}=e||{};d.current.push([i?"replace":"push",r,u]),1===d.current.length&&queueMicrotask((()=>{for(;d.current.length;){const t=d.current.shift();t&&t?.[1]!==a?.[1]&&(a=t)}const[t,e,n]=a||{};a=void 0,t&&c[t](e,n)}))}),[c,h,m]);return{updateState:p,updateUrl:w,state:l,getState:m}}const a="popstate";export{s as useUrlStateBase};
5 changes: 5 additions & 0 deletions dist/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ export declare const isEqual: (val1: unknown, val2: unknown) => boolean;
export declare function filterUnknownParamsClient<T extends object>(shape: T): string;
export declare function filterUnknownParams<T extends object>(shape: T, searchParams?: object): T;
export declare function assignValue<T extends object>(shape: T, curr: Partial<T>, newVal: Partial<T>): T;
export interface Router {
push: (href: string, opts: object) => void;
replace: (href: string, opts: object) => void;
}
export declare const routerHistory: Router;
2 changes: 1 addition & 1 deletion dist/utils.mjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const t=t=>{const n=typeof t,e=null===t,r=Array.isArray(t),c=t instanceof Date;return(e?"null":c&&"date")||r&&"array"||!e&&!c&&!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||"",c=(t,n)=>JSON.stringify(t)===JSON.stringify(n);function o(t){const n=new URLSearchParams;return s(t,[...new URLSearchParams(window.location.search).entries()]).forEach((([t,e])=>n.set(t,e))),n.toString()}function i(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 c=n,o=void 0!==e[c];r[c]=o?e[c]:t[c]})),r}export{a as assignValue,i as filterUnknownParams,o as filterUnknownParamsClient,e as getParams,c as isEqual,n as isSSR,t as typeOf};
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};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "state-in-url",
"version": "3.1.0",
"version": "4.0.0",
"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.",
"homepage": "https://state-in-url.dev",
"keywords": [
Expand Down

0 comments on commit fcad4e5

Please sign in to comment.