@@ -7,38 +7,53 @@ import { useContext, useMemo, useReducer, useLayoutEffect, useRef } from 'preact
7
7
* @typedef {import('./internal.d.ts').VNode } VNode
8
8
*/
9
9
10
- let push , scope ;
11
- const UPDATE = ( state , url ) => {
10
+ /** @type {boolean } */
11
+ let push ;
12
+ /** @type {string | RegExp | undefined } */
13
+ let scope ;
14
+
15
+ /**
16
+ * @param {string } href
17
+ * @returns {boolean }
18
+ */
19
+ function isInScope ( href ) {
20
+ return ! scope || ( typeof scope == 'string'
21
+ ? href . startsWith ( scope )
22
+ : scope . test ( href )
23
+ ) ;
24
+ }
25
+
26
+ /**
27
+ * @param {string } state
28
+ * @param {MouseEvent | PopStateEvent | { url: string, replace?: boolean } } action
29
+ */
30
+ function handleNav ( state , action ) {
31
+ let url = '' ;
12
32
push = undefined ;
13
- if ( url && url . type === 'click' ) {
33
+ if ( action && action . type === 'click' ) {
14
34
// ignore events the browser takes care of already:
15
- if ( url . ctrlKey || url . metaKey || url . altKey || url . shiftKey || url . button !== 0 ) {
35
+ if ( action . ctrlKey || action . metaKey || action . altKey || action . shiftKey || action . button !== 0 ) {
16
36
return state ;
17
37
}
18
38
19
- const link = url . composedPath ( ) . find ( el => el . nodeName == 'A' && el . href ) ,
39
+ const link = action . composedPath ( ) . find ( el => el . nodeName == 'A' && el . href ) ,
20
40
href = link && link . getAttribute ( 'href' ) ;
21
41
if (
22
42
! link ||
23
43
link . origin != location . origin ||
24
44
/ ^ # / . test ( href ) ||
25
45
! / ^ ( _ ? s e l f ) ? $ / i. test ( link . target ) ||
26
- scope && ( typeof scope == 'string'
27
- ? ! href . startsWith ( scope )
28
- : ! scope . test ( href )
29
- )
46
+ ! isInScope ( href )
30
47
) {
31
48
return state ;
32
49
}
33
50
34
51
push = true ;
35
- url . preventDefault ( ) ;
52
+ action . preventDefault ( ) ;
36
53
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 ;
54
+ } else if ( action && action . url ) {
55
+ push = ! action . replace ;
56
+ url = action . url ;
42
57
} else {
43
58
url = location . pathname + location . search ;
44
59
}
@@ -77,11 +92,13 @@ export const exec = (url, route, matches = {}) => {
77
92
} ;
78
93
79
94
/**
80
- * @type {import('./router.d.ts').LocationProvider }
95
+ * @param {Object } props
96
+ * @param {string | RegExp } [props.scope]
97
+ * @param {import('preact').ComponentChildren } [props.children]
81
98
*/
82
99
export function LocationProvider ( props ) {
83
100
// @ts -expect-error - props.url is not implemented correctly & will be removed in the future
84
- const [ url , route ] = useReducer ( UPDATE , props . url || location . pathname + location . search ) ;
101
+ const [ url , route ] = useReducer ( handleNav , props . url || location . pathname + location . search ) ;
85
102
if ( props . scope ) scope = props . scope ;
86
103
const wasPush = push === true ;
87
104
0 commit comments