@@ -7,46 +7,30 @@ import { useContext, useMemo, useReducer, useLayoutEffect, useRef } from 'preact
77 * @typedef {import('./internal.d.ts').VNode } VNode
88 */
99
10- let push , scope ;
11- const UPDATE = ( state , url ) => {
12- push = undefined ;
13- if ( url && url . type === 'click' ) {
14- // ignore events the browser takes care of already:
15- if ( url . ctrlKey || url . metaKey || url . altKey || url . shiftKey || url . button !== 0 ) {
16- return state ;
17- }
18-
19- const link = url . target . closest ( 'a[href]' ) ,
20- href = link && link . getAttribute ( 'href' ) ;
21- if (
22- ! link ||
23- link . origin != location . origin ||
24- / ^ # / . test ( href ) ||
25- ! / ^ ( _ ? s e l f ) ? $ / i. test ( link . target ) ||
26- scope && ( typeof scope == 'string'
27- ? ! href . startsWith ( scope )
28- : ! scope . test ( href )
29- )
30- ) {
31- return state ;
32- }
10+ /** @type {string | RegExp | undefined } */
11+ let scope ;
3312
34- push = true ;
35- url . preventDefault ( ) ;
36- url = link . href . replace ( location . origin , '' ) ;
37- } else if ( typeof url === 'string' ) {
38- push = true ;
39- } else if ( url && url . url ) {
40- push = ! url . replace ;
41- url = url . url ;
42- } else {
43- url = location . pathname + location . search ;
13+ /**
14+ * @param {string } state
15+ * @param {NavigateEvent } e
16+ */
17+ function handleNav ( state , e ) {
18+ if ( ! e . canIntercept ) return state ;
19+ if ( e . hashChange || e . downloadRequest !== null ) return state ;
20+
21+ const url = new URL ( e . destination . url ) ;
22+ if (
23+ scope && ( typeof scope == 'string'
24+ ? ! url . pathname . startsWith ( scope )
25+ : ! scope . test ( url . pathname )
26+ )
27+ ) {
28+ return state ;
4429 }
4530
46- if ( push === true ) history . pushState ( null , '' , url ) ;
47- else if ( push === false ) history . replaceState ( null , '' , url ) ;
48- return url ;
49- } ;
31+ e . intercept ( ) ;
32+ return url . href . replace ( url . origin , '' ) ;
33+ }
5034
5135export const exec = ( url , route , matches = { } ) => {
5236 url = url . split ( '/' ) . filter ( Boolean ) ;
@@ -80,9 +64,8 @@ export const exec = (url, route, matches = {}) => {
8064 * @type {import('./router.d.ts').LocationProvider }
8165 */
8266export function LocationProvider ( props ) {
83- const [ url , route ] = useReducer ( UPDATE , location . pathname + location . search ) ;
67+ const [ url , route ] = useReducer ( handleNav , location . pathname + location . search ) ;
8468 if ( props . scope ) scope = props . scope ;
85- const wasPush = push === true ;
8669
8770 const value = useMemo ( ( ) => {
8871 const u = new URL ( url , location . origin ) ;
@@ -93,18 +76,14 @@ export function LocationProvider(props) {
9376 path,
9477 pathParams : { } ,
9578 searchParams : Object . fromEntries ( u . searchParams ) ,
96- route : ( url , replace ) => route ( { url, replace } ) ,
97- wasPush
9879 } ;
9980 } , [ url ] ) ;
10081
10182 useLayoutEffect ( ( ) => {
102- addEventListener ( 'click' , route ) ;
103- addEventListener ( 'popstate' , route ) ;
83+ navigation . addEventListener ( 'navigate' , route ) ;
10484
10585 return ( ) => {
106- removeEventListener ( 'click' , route ) ;
107- removeEventListener ( 'popstate' , route ) ;
86+ navigation . removeEventListener ( 'navigate' , route ) ;
10887 } ;
10988 } , [ ] ) ;
11089
@@ -116,7 +95,7 @@ const RESOLVED = Promise.resolve();
11695export function Router ( props ) {
11796 const [ c , update ] = useReducer ( c => c + 1 , 0 ) ;
11897
119- const { url, path, pathParams, searchParams, wasPush } = useLocation ( ) ;
98+ const { url, path, pathParams, searchParams } = useLocation ( ) ;
12099
121100 const isLoading = useRef ( false ) ;
122101 const prevRoute = useRef ( path ) ;
@@ -236,15 +215,15 @@ export function Router(props) {
236215
237216 // The route is loaded and rendered.
238217 if ( prevRoute . current !== path ) {
239- if ( wasPush ) scrollTo ( 0 , 0 ) ;
218+ scrollTo ( 0 , 0 ) ;
240219 if ( props . onRouteChange ) props . onRouteChange ( url ) ;
241220
242221 prevRoute . current = path ;
243222 }
244223
245224 if ( props . onLoadEnd && isLoading . current ) props . onLoadEnd ( url ) ;
246225 isLoading . current = false ;
247- } , [ path , wasPush , c ] ) ;
226+ } , [ path , c ] ) ;
248227
249228 // Note: cur MUST render first in order to set didSuspend & prev.
250229 return routeChanged
@@ -261,7 +240,7 @@ const RenderRef = ({ r }) => r.current;
261240Router . Provider = LocationProvider ;
262241
263242LocationProvider . ctx = createContext (
264- /** @type {import('./router.d.ts').LocationHook & { wasPush: boolean } } */ ( { } )
243+ /** @type {import('./router.d.ts').LocationHook }} */ ( { } )
265244) ;
266245
267246export const Route = props => h ( props . component , props ) ;
0 commit comments