import * as React from 'react' ; import { HistoryLocation , PushReplaceHistory } from './types' ; import { LocationProvider } from './LocationProvider' ; import { ExtendedStringifyOptions } from 'serialize-query-params' ; import shallowEqual from './shallowEqual' ; let cachedWindowHistory ; let cachedAdaptedWindowHistory ; param history function adaptWindowHistory ( history ) { if ( history === cachedWindowHistory && cachedAdaptedWindowHistory != null ) { return cachedAdaptedWindowHistory ; } const adaptedWindowHistory = { replace ( location ) { history . replaceState ( ( location as any ) . state , '' , `${ location . protocol }//${ location . host }${ location . pathname }${ location . search }` ) ; } , push ( location ) { history . pushState ( ( location as any ) . state , '' , `${ location . protocol }//${ location . host }${ location . pathname }${ location . search }` ) ; } , get location ( ) { return window . location ; } , } ; cachedWindowHistory = history ; cachedAdaptedWindowHistory = adaptedWindowHistory ; return adaptedWindowHistory ; } /**
 * Subset of a @reach/router history object. We only
 * care about the navigate function.
 */ interface ReachHistory { navigate : ( to : string , options ? : { state ? : any ; replace ? : boolean ; } ) => void ; location : Location ; } let cachedReachHistory ; let cachedAdaptedReachHistory ; param history reach function adaptReachHistory ( history ) { if ( history === cachedReachHistory && cachedAdaptedReachHistory != null ) { return cachedAdaptedReachHistory ; } const adaptedReachHistory = { replace ( location ) { history . navigate ( `${ location . protocol }//${ location . host }${ location . pathname }${ location . search }` , { replace : true } ) ; } , push ( location ) { history . navigate ( `${ location . protocol }//${ location . host }${ location . pathname }${ location . search }` , { replace : false } ) ; } , get location ( ) { return history . location ; } , } ; cachedReachHistory = history ; cachedAdaptedReachHistory = adaptedReachHistory ; return adaptedReachHistory ; } /**
 * Helper to produce the context value falling back to
 * window history and location if not provided.
 */ export function getLocationProps ( { history , location , } = { } ) { const hasWindow = typeof window !== 'undefined' ; if ( hasWindow ) { if ( ! history ) { history = adaptWindowHistory ( window . history ) ; } if ( ! location ) { location = window . location ; } } if ( ! location ) { throw new Error ( `
        Could not read the location. Is the router wired up correctly?
      ` ) ; } return { history , location } ; } /**
 * Props for the Provider component, used to hook the active routing
 * system into our controls.
 */ interface QueryParamProviderProps { /** Main app goes here */ children : React . ReactNode ; /** `Route` from react-router */ ReactRouterRoute ? : React . ComponentClass | React . FunctionComponent ; /** `globalHistory` from @reach/router */ reachHistory ? : ReachHistory ; /** Manually provided history that meets the { replace, push } interface */ history ? : PushReplaceHistory ; /**
     * Override location object, otherwise window.location or the
     * location provided by the active routing system is used.
     */ location ? : Location ; /**
     * Options to customize the stringifying of the query string
     * These are passed directly to query-string.stringify, with
     * the exception of transformSearchString which runs on the result
     * of stringify if provided.
     */ stringifyOptions ? : ExtendedStringifyOptions ; } /**
 * Context provider for query params to have access to the
 * active routing system, enabling updates to the URL.
 */ export function QueryParamProvider ( { children , ReactRouterRoute , reachHistory , history , location , stringifyOptions , } ) { const stringifyOptionsRef = React . useRef ( stringifyOptions ) ; const hasNewStringifyOptions = ! shallowEqual ( stringifyOptionsRef . current , stringifyOptions ) ; const stringifyOptionsCached = hasNewStringifyOptions ? stringifyOptions : stringifyOptionsRef . current ; React . useEffect ( ( ) => { stringifyOptionsRef . current = stringifyOptionsCached ; } , [ stringifyOptionsCached ] ) ; if ( ReactRouterRoute ) { return ( < ReactRouterRoute > { ( routeProps ) => { return ( < LocationProvider stringifyOptions = { stringifyOptionsCached } { ... getLocationProps ( routeProps ) } > { children } < /LocationProvider>); } } < /ReactRouterRoute>); } if ( reachHistory ) { return ( < LocationProvider stringifyOptions = { stringifyOptionsCached } { ... getLocationProps ( { history : adaptReachHistory ( reachHistory ) , location , } ) } > { children } < /LocationProvider>); } return ( < LocationProvider stringifyOptions = { stringifyOptionsCached } { ... getLocationProps ( { history , location } ) } > { children } < /LocationProvider>); } export default QueryParamProvider ;