{"version":3,"sources":["../src/components/ActiveLink/ActiveLink.tsx","../src/components/ActiveLink/useAddActiveClassName.hook.ts","../src/components/ActiveLink/ActiveLink.helpers.ts"],"sourcesContent":["import Link from 'next/link'\nimport { Children, cloneElement } from 'react'\n\nimport { useAddActiveClassName } from './useAddActiveClassName.hook'\n\nimport type { LinkProps } from 'next/link'\n\n\n/**\n * A link that adds an active class name when the link is active.\n */\nexport type ActiveLinkProps = {\n  /**\n   * It must be a Single Component to be rendered (Child).\n   *\n   * NOTE: If you are using a Custom component instead of <a></a>,\n   *       remember to use 'passHref' prop to propagate href\n   */\n  children: JSX.Element\n\n\n  /**\n   * Active class name to be added.\n   */\n  activeClassName: string\n\n\n  /**\n   * A set of options which specify how to determine if a url is active\n   */\n  activeMatchOptions?: {\n    exact: boolean\n  } | {\n    paths?: 'exact' | 'partial'\n    queryParams?: 'exact' | 'partial'\n    fragment?: 'exact'\n  }\n\n\n  /**\n   * You can use the output onActiveChange to get notified\n   * each time the link becomes active or inactive.\n   */\n  onActiveChange?: (isActive: boolean) => unknown\n} & LinkProps\n\n\n\n\n\n\n/**\n * A Link Component wrapper that adds an active class name when the link is active.\n */\nexport const ActiveLink = ({ children, activeClassName, ...props }: ActiveLinkProps): JSX.Element => {\n  const child = Children.only(children)\n  const childClassName = (child.props.className ?? '') as string\n\n  /**\n   * as => Dynamic routes and rewrites\n   * href => Static routes\n   */\n  const { as, href, activeMatchOptions, onActiveChange } = props\n  const url = (as || href) as URL\n\n  const className = useAddActiveClassName({\n    activeClassName,\n    childClassName,\n    linkUrl: url,\n    activeMatchOptions,\n    onActiveChange,\n  })\n\n\n\n  return (\n    <Link {...props}>\n      {cloneElement(child, {\n        className: className || null,\n      })}\n    </Link>\n  )\n}\n","import { useRouter } from 'next/router'\nimport { useEffect, useState } from 'react'\nimport { cn } from 'tiny-cn'\n\nimport { isLinkActive } from './ActiveLink.helpers'\n\nimport type { ActiveLinkProps } from './ActiveLink'\n\n\n\ninterface Params {\n  activeClassName: string\n  childClassName: string\n  linkUrl: string | URL\n  activeMatchOptions: ActiveLinkProps['activeMatchOptions']\n  onActiveChange: ActiveLinkProps['onActiveChange']\n}\n\nexport const useAddActiveClassName = ({\n  activeClassName,\n  childClassName,\n  linkUrl,\n  activeMatchOptions,\n  onActiveChange,\n}: Params): string => {\n  const [className, setClassName] = useState(childClassName)\n  const { asPath, isReady } = useRouter()\n\n  useEffect(() => {\n    /** Whether the router fields are updated client-side and ready for use  */\n    if (isReady) {\n      const isActive = isLinkActive(linkUrl, asPath, activeMatchOptions)\n\n      if (onActiveChange) onActiveChange(isActive)\n\n      const newClassName = cn({\n        [childClassName]: true,\n        [activeClassName]: isActive,\n      })\n\n      const shouldUpdateLinkClassName = newClassName !== className\n\n      if (shouldUpdateLinkClassName) setClassName(newClassName)\n    }\n  }, [\n    asPath,\n    isReady,\n    linkUrl,\n    childClassName,\n    activeClassName,\n    setClassName,\n    className,\n  ])\n\n\n  return className\n}\n","import type { ActiveLinkProps } from './ActiveLink'\n\n\n\nconst ACTIVE_MATCH_OPTIONS_DEFAULT: ActiveLinkProps['activeMatchOptions'] = {\n  fragment: undefined,\n  paths: undefined,\n  queryParams: undefined,\n}\n\nexport const isLinkActive = (\n  linkUrl: string | URL,\n  currentLink: string,\n  activeMatchOptions: ActiveLinkProps['activeMatchOptions'] = {\n    exact: true,\n  },\n): boolean => {\n  const currentLinkObj = new URL(currentLink, location.href)\n  const linkUrlObj = new URL(linkUrl, location.href)\n\n  if ('exact' in activeMatchOptions) {\n    return activeMatchOptions.exact\n      ? currentLinkObj.href === linkUrlObj.href\n      : currentLinkObj.href.includes(linkUrlObj.pathname)\n  } else {\n    let isActive = false\n    const { fragment, paths, queryParams } = { ...ACTIVE_MATCH_OPTIONS_DEFAULT, ...activeMatchOptions }\n\n    if (fragment) {\n      isActive = currentLinkObj.hash === linkUrlObj.hash\n    }\n\n    if (paths) {\n      const pathList = currentLinkObj.pathname.split('/')\n      const linkPathList = linkUrlObj.pathname.split('/')\n\n      isActive = paths === 'exact'\n        ? currentLinkObj.pathname === linkUrlObj.pathname\n        : pathList.some((path) => linkPathList.includes(path))\n    }\n\n    if (queryParams) {\n      const currentQueryParams = Object.fromEntries(currentLinkObj.searchParams.entries())\n      const linkQueryParams = Object.fromEntries(linkUrlObj.searchParams.entries())\n\n      isActive = queryParams === 'exact'\n        ? currentLinkObj.search === linkUrlObj.search\n        : Object.entries(currentQueryParams).some(([key, value]) => {\n          return linkQueryParams[key] === value\n        })\n    }\n    return isActive\n  }\n}\n"],"mappings":"2fAAA,yBACA,mDCDA,wCACA,gDACA,6BCEA,GAAM,GAAsE,CAC1E,SAAU,OACV,MAAO,OACP,YAAa,MACf,EAEa,EAAe,CAC1B,EACA,EACA,EAA4D,CAC1D,MAAO,EACT,IACY,CACZ,GAAM,GAAiB,GAAI,KAAI,EAAa,SAAS,IAAI,EACnD,EAAa,GAAI,KAAI,EAAS,SAAS,IAAI,EAEjD,GAAI,SAAW,GACb,MAAO,GAAmB,MACtB,EAAe,OAAS,EAAW,KACnC,EAAe,KAAK,SAAS,EAAW,QAAQ,EAC/C,CACL,GAAI,GAAW,GACT,CAAE,WAAU,QAAO,eAAgB,OAAK,GAAiC,GAM/E,GAJI,GACF,GAAW,EAAe,OAAS,EAAW,MAG5C,EAAO,CACT,GAAM,GAAW,EAAe,SAAS,MAAM,GAAG,EAC5C,EAAe,EAAW,SAAS,MAAM,GAAG,EAElD,EAAW,IAAU,QACjB,EAAe,WAAa,EAAW,SACvC,EAAS,KAAK,AAAC,GAAS,EAAa,SAAS,CAAI,CAAC,CACzD,CAEA,GAAI,EAAa,CACf,GAAM,GAAqB,OAAO,YAAY,EAAe,aAAa,QAAQ,CAAC,EAC7E,EAAkB,OAAO,YAAY,EAAW,aAAa,QAAQ,CAAC,EAE5E,EAAW,IAAgB,QACvB,EAAe,SAAW,EAAW,OACrC,OAAO,QAAQ,CAAkB,EAAE,KAAK,CAAC,CAAC,EAAK,KACxC,EAAgB,KAAS,CACjC,CACL,CACA,MAAO,EACT,CACF,EDnCO,GAAM,GAAwB,CAAC,CACpC,kBACA,iBACA,UACA,qBACA,oBACoB,CACpB,GAAM,CAAC,EAAW,GAAgB,EAAS,CAAc,EACnD,CAAE,SAAQ,WAAY,EAAU,EAEtC,SAAU,IAAM,CAEd,GAAI,EAAS,CACX,GAAM,GAAW,EAAa,EAAS,EAAQ,CAAkB,EAEjE,AAAI,GAAgB,EAAe,CAAQ,EAE3C,GAAM,GAAe,EAAG,EACrB,GAAiB,IACjB,GAAkB,CACrB,CAAC,EAID,AAAI,AAF8B,IAAiB,GAEpB,EAAa,CAAY,CAC1D,CACF,EAAG,CACD,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC,EAGM,CACT,EDFO,GAAM,GAAa,AAAC,GAA0E,CAA1E,QAAE,YAAU,mBAAZ,EAAgC,IAAhC,EAAgC,CAA9B,WAAU,oBAtDvC,MAuDE,GAAM,GAAQ,EAAS,KAAK,CAAQ,EAC9B,EAAkB,KAAM,MAAM,YAAZ,OAAyB,GAM3C,CAAE,KAAI,OAAM,qBAAoB,kBAAmB,EAGnD,EAAY,EAAsB,CACtC,kBACA,iBACA,QALW,GAAM,EAMjB,qBACA,gBACF,CAAC,EAID,MACE,qBAAC,OAAS,GACP,EAAa,EAAO,CACnB,UAAW,GAAa,IAC1B,CAAC,CACH,CAEJ","names":[]}