import { defineHook , inject , InjectionKey , unref , computed , UnwrapNestedRefs } from '@kirei/element' ; import { RouteLocationNormalizedLoaded } from './type' ; import { Router , NavigationFailure , RouteLocationRaw , RouteRecord } from './types' ; const ROUTER_KEY = Symbol ( 'routerKey' ) ; const ROUTE_KEY = Symbol ( 'routeKey' ) ; export const onBeforeRouteLeave = defineHook ( 'beforeRouteLeave' ) ; export const onBeforeRouteUpdate = defineHook ( 'beforeRouteUpdate' ) ; function guardEvent ( e = { } as MouseEvent ) { if ( e . metaKey || e . altKey || e . ctrlKey || e . shiftKey ) return ; if ( e . defaultPrevented ) return ; if ( e . button !== undefined && e . button !== 0 ) return ; if ( e . currentTarget && e . currentTarget . getAttribute ) { const target = e . currentTarget . getAttribute ( 'target' ) ; if ( /\b_blank\b/i . test ( target ) ) return ; } e . preventDefault ( ) ; return true ; } export interface RouterLinkProps { /**
     * Route Location the link should navigate to when clicked on.
     */ to : RouteLocationRaw ; /**
     * Calls `router.replace` instead of `router.push`.
     */ replace ? : boolean ; } export type RouterLinkOptions = UnwrapNestedRefs < RouterLinkProps > ; export function useLink ( props ) { const router = useRouter ( ) ; const currentRoute = useRoute ( ) ; const route = computed ( ( ) => router . resolve ( unref ( props . to ) ) ) ; const activeRecordIndex = computed < number > ( ( ) => { let { matched } = route . value ; let { length } = matched ; const routeMatched = matched [ length - 1 ] ; const currentMatched = currentRoute . matched ; if ( ! routeMatched || ! currentMatched . length ) { return - 1 ; } const index = currentMatched . findIndex ( isSameRouteRecord . bind ( null , routeMatched ) ) ; if ( index > - 1 ) { return index ; } let parentRecordPath = getOriginalPath ( matched [ length - 2 ] as RouteRecord | undefined ) ; return ( length > 1 && getOriginalPath ( routeMatched ) === parentRecordPath && currentMatched [ currentMatched . length - 1 ] . path !== parentRecordPath ? currentMatched . findIndex ( isSameRouteRecord . bind ( null , matched [ length - 2 ] ) ) : index ) ; } ) ; const isActive = computed < boolean > ( ( ) => activeRecordIndex . value > - 1 && includesParams ( currentRoute . params , route . value . params ) ) ; const isExactActive = computed < boolean > ( ( ) => activeRecordIndex . value > - 1 && activeRecordIndex . value === currentRoute . matched . length - 1 && isSameRouteLocationParams ( currentRoute . params , route . value . params ) ) ; async function navigate ( e ? ) { if ( e != null ) { if ( e . metaKey || e . altKey || e . ctrlKey || e . shiftKey ) return ; if ( e . defaultPrevented ) return ; if ( e . button !== undefined && e . button !== 0 ) return ; if ( e . currentTarget && e . currentTarget . getAttribute ) { const target = e . currentTarget . getAttribute ( 'target' ) ; if ( /\b_blank\b/i . test ( target ) ) return ; } e . preventDefault ( ) ; } return router [ unref ( props . replace ) ? 'replace' : 'push' ] ( unref ( props . to ) ) ; } return { route , href : computed ( ( ) => route . value . href ) , isActive , isExactActive , navigate , } ; } /**
 * Returns the router instance. Equivalent to using `$router` inside
 * templates.
 */ export function useRouter ( ) { return inject ( ROUTER_KEY ) ; } /**
 * Returns the current route location. Equivalent to using `$route` inside
 * templates.
 */ export function useRoute ( ) { return inject ( ROUTE_KEY ) ; }