All files context.ts

65.21% Statements 15/23
75% Branches 3/4
75% Functions 3/4
65.21% Lines 15/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110  1x               1x 1x           1x 1x             1x 2x 2x                                                             1x 1x 1x                                                     1x 1x 1x                                   1x      
import type { Route, Router } from '@esmx/router';
import { createContext, useContext } from 'react';
import type { RouterContextValue } from './types';
 
/**
 * React Context for router state.
 * Contains the router instance and current route.
 * Using null as default to detect missing provider.
 */
export const RouterContext = createContext<RouterContextValue | null>(null);
RouterContext.displayName = 'RouterContext';
 
/**
 * React Context for RouterView depth tracking.
 * Used for nested routing to determine which matched route to render.
 */
export const RouterViewDepthContext = createContext<number>(0);
RouterViewDepthContext.displayName = 'RouterViewDepthContext';
 
/**
 * Get the router context value.
 * @throws {Error} If used outside of RouterProvider
 * @internal
 */
export function useRouterContext(): RouterContextValue {
    const context = useContext(RouterContext);
    if (!context) {
        throw new Error(
            '[@esmx/router-react] Router context not found. ' +
                'Please ensure your component is wrapped in a RouterProvider.'
        );
    }
    return context;
}
 
/**
 * Get the router instance for navigation.
 * Must be used within a RouterProvider.
 *
 * @returns Router instance with navigation methods
 * @throws {Error} If used outside of RouterProvider
 *
 * @example
 * ```tsx
 * import { useRouter } from '@esmx/router-react';
 *
 * function NavigationButton() {
 *   const router = useRouter();
 *
 *   const handleClick = () => {
 *     router.push('/dashboard');
 *   };
 *
 *   return <button onClick={handleClick}>Go to Dashboard</button>;
 * }
 * ```
 */
export function useRouter(): Router {
    return useRouterContext().router;
}
 
/**
 * Get the current route information.
 * Returns a reactive route object that updates when navigation occurs.
 * Must be used within a RouterProvider.
 *
 * @returns Current route object with path, params, query, etc.
 * @throws {Error} If used outside of RouterProvider
 *
 * @example
 * ```tsx
 * import { useRoute } from '@esmx/router-react';
 *
 * function CurrentPath() {
 *   const route = useRoute();
 *
 *   return (
 *     <div>
 *       <p>Path: {route.path}</p>
 *       <p>Params: {JSON.stringify(route.params)}</p>
 *       <p>Query: {JSON.stringify(route.query)}</p>
 *     </div>
 *   );
 * }
 * ```
 */
export function useRoute(): Route {
    return useRouterContext().route;
}
 
/**
 * Get the current RouterView depth.
 * Used internally by RouterView for nested routing.
 *
 * @returns Current depth level (0 for root, 1 for first nested, etc.)
 *
 * @example
 * ```tsx
 * import { useRouterViewDepth } from '@esmx/router-react';
 *
 * function DebugView() {
 *   const depth = useRouterViewDepth();
 *   return <div>Current depth: {depth}</div>;
 * }
 * ```
 */
export function useRouterViewDepth(): number {
    return useContext(RouterViewDepthContext);
}