All files use-link.ts

7.5% Statements 3/40
100% Branches 0/0
0% Functions 0/1
7.5% Lines 3/40

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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139  1x 1x                                                                                                                                                                                                 1x                                                                              
import type { RouterLinkProps, RouterLinkResolved } from '@esmx/router';
import { useMemo } from 'react';
import { useRouter } from './context';
 
/**
 * Hook to create reactive link helpers for custom navigation components.
 * Returns a resolved link object with attributes, state, and event handlers.
 *
 * This hook is useful when you need to build custom link components
 * with full control over rendering while retaining router functionality.
 *
 * @param props - RouterLink properties
 * @returns Resolved link object with attributes, state, and navigation methods
 *
 * @example
 * ```tsx
 * import { useLink } from '@esmx/router-react';
 *
 * function CustomNavButton({ to, children }) {
 *   const link = useLink({ to, type: 'push', exact: 'include' });
 *
 *   return (
 *     <button
 *       onClick={(e) => link.navigate(e)}
 *       className={link.isActive ? 'active' : ''}
 *       disabled={link.isExactActive}
 *     >
 *       {children}
 *       {link.isActive && <span>✓</span>}
 *     </button>
 *   );
 * }
 * ```
 *
 * @example
 * ```tsx
 * // Building a custom navigation card
 * import { useLink } from '@esmx/router-react';
 *
 * interface NavCardProps {
 *   to: string;
 *   title: string;
 *   description: string;
 *   icon: React.ReactNode;
 * }
 *
 * function NavCard({ to, title, description, icon }: NavCardProps) {
 *   const link = useLink({ to });
 *
 *   return (
 *     <div
 *       className={`nav-card ${link.isActive ? 'active' : ''}`}
 *       onClick={(e) => link.navigate(e)}
 *       role="link"
 *       tabIndex={0}
 *     >
 *       <div className="icon">{icon}</div>
 *       <h3>{title}</h3>
 *       <p>{description}</p>
 *       {link.isExternal && <span className="external-badge">↗</span>}
 *     </div>
 *   );
 * }
 * ```
 *
 * @example
 * ```tsx
 * // Using all resolved properties
 * import { useLink } from '@esmx/router-react';
 *
 * function DebugLink({ to }) {
 *   const link = useLink({ to, exact: 'exact' });
 *
 *   return (
 *     <div>
 *       <a
 *         href={link.attributes.href}
 *         target={link.attributes.target}
 *         rel={link.attributes.rel}
 *         className={link.attributes.class}
 *         onClick={(e) => {
 *           e.preventDefault();
 *           link.navigate(e);
 *         }}
 *       >
 *         Link Text
 *       </a>
 *       <pre>
 *         isActive: {String(link.isActive)}
 *         isExactActive: {String(link.isExactActive)}
 *         isExternal: {String(link.isExternal)}
 *         type: {link.type}
 *         tag: {link.tag}
 *       </pre>
 *     </div>
 *   );
 * }
 * ```
 */
export function useLink(props: RouterLinkProps): RouterLinkResolved {
    const router = useRouter();
    const {
        to,
        type,
        replace,
        exact,
        activeClass,
        event,
        tag,
        layerOptions,
        beforeNavigate
    } = props;
 
    return useMemo(() => {
        return router.resolveLink({
            to,
            type,
            replace,
            exact,
            activeClass,
            event,
            tag,
            layerOptions,
            beforeNavigate
        });
    }, [
        router,
        to,
        type,
        replace,
        exact,
        activeClass,
        event,
        tag,
        layerOptions,
        beforeNavigate
    ]);
}