{"version":3,"file":"navigation.mjs","names":[],"sources":["../../../../package/common/utils/navigation.ts"],"sourcesContent":["import { useContext, type MouseEvent } from 'react';\n\nimport { NavigateContext } from '../configProvider/configProvider';\n\ntype Navigate = (path: string) => void;\n\nfunction parseUrl(href: string): URL | null {\n  try {\n    return new URL(href, document.baseURI);\n  } catch {\n    return null;\n  }\n}\n\n/**\n * The path to hand to the router, or null where the browser has to take the URL: another site, or\n * another protocol. Protocol and origin are both checked because a `blob:` URL, which an app opens\n * a generated PDF through, carries the page's own origin. A jump to an anchor on the current page\n * stays with the browser too, which scrolls to it.\n */\nfunction routerPath(url: URL): string | null {\n  if (url.protocol !== 'http:' && url.protocol !== 'https:') return null;\n  if (url.origin !== window.location.origin) return null;\n  const samePage = url.pathname === window.location.pathname && url.search === window.location.search;\n  // Not `url.hash`, which is empty for a bare `#` that still jumps to the top.\n  if (samePage && url.href.includes('#')) return null;\n  return url.pathname + url.search + url.hash;\n}\n\n/** The checks react-router's own `<Link>` makes, plus `download`, which it leaves to the browser. */\nfunction isPlainClick(event: MouseEvent<HTMLAnchorElement>): boolean {\n  const anchor = event.currentTarget;\n  return (\n    !event.defaultPrevented &&\n    event.button === 0 &&\n    !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) &&\n    (!anchor.target || anchor.target === '_self') &&\n    !anchor.hasAttribute('download')\n  );\n}\n\n/**\n * The click handler for an `<a>` a component renders: a plain click on a link within the app goes\n * to `ConfigProvider`'s `navigate`, everything else to the browser. Call it after the consumer's own\n * `onClick`, so a `preventDefault()` there still wins.\n */\nexport function useLinkClick(): (event: MouseEvent<HTMLAnchorElement>) => void {\n  const navigate = useContext(NavigateContext);\n  return (event) => {\n    if (!navigate || !isPlainClick(event)) return;\n    // `.href` rather than the attribute: the browser has already resolved a relative link against\n    // the page, as it does for a middle click, which the router would resolve against the route.\n    const url = parseUrl(event.currentTarget.href);\n    const path = url && routerPath(url);\n    if (path === null) return;\n    event.preventDefault();\n    navigate(path);\n  };\n}\n\n/** Follows a link from code, where no anchor was clicked: through the router where it can. */\nexport function followHref(href: string, navigate?: Navigate): void {\n  const url = parseUrl(href);\n  if (!url) return;\n  // React refuses a javascript: URL on an <a>, so the same link must not run one here. Parsed,\n  // not matched, because the parser strips the spaces and control characters that can hide one.\n  if (url.protocol === 'javascript:') return;\n  const path = navigate ? routerPath(url) : null;\n  if (navigate && path !== null) navigate(path);\n  else window.location.assign(url);\n}\n\nexport function useFollowHref(): (href: string) => void {\n  const navigate = useContext(NavigateContext);\n  return (href) => followHref(href, navigate);\n}\n"],"mappings":"uHAMA,SAAS,EAAS,EAA0B,CAC1C,GAAI,CACF,OAAO,IAAI,IAAI,EAAM,SAAS,OAAO,CACvC,MAAQ,CACN,OAAO,IACT,CACF,CAQA,SAAS,EAAW,EAAyB,CAM3C,OALI,EAAI,WAAa,SAAW,EAAI,WAAa,UAC7C,EAAI,SAAW,OAAO,SAAS,QAClB,EAAI,WAAa,OAAO,SAAS,UAAY,EAAI,SAAW,OAAO,SAAS,QAE7E,EAAI,KAAK,SAAS,GAAG,EAAU,KACxC,EAAI,SAAW,EAAI,OAAS,EAAI,IACzC,CAGA,SAAS,EAAa,EAA+C,CACnE,IAAM,EAAS,EAAM,cACrB,MACE,CAAC,EAAM,kBACP,EAAM,SAAW,GACjB,EAAE,EAAM,SAAW,EAAM,SAAW,EAAM,UAAY,EAAM,UAC3D,CAAC,EAAO,QAAU,EAAO,SAAW,UACrC,CAAC,EAAO,aAAa,UAAU,CAEnC,CAOA,SAAgB,GAA+D,CAC7E,IAAM,EAAW,EAAW,CAAe,EAC3C,MAAQ,IAAU,CAChB,GAAI,CAAC,GAAY,CAAC,EAAa,CAAK,EAAG,OAGvC,IAAM,EAAM,EAAS,EAAM,cAAc,IAAI,EACvC,EAAO,GAAO,EAAW,CAAG,EAC9B,IAAS,OACb,EAAM,eAAe,EACrB,EAAS,CAAI,EACf,CACF,CAGA,SAAgB,EAAW,EAAc,EAA2B,CAClE,IAAM,EAAM,EAAS,CAAI,EAIzB,GAHI,CAAC,GAGD,EAAI,WAAa,cAAe,OACpC,IAAM,EAAO,EAAW,EAAW,CAAG,EAAI,KACtC,GAAY,IAAS,KAAM,EAAS,CAAI,EACvC,OAAO,SAAS,OAAO,CAAG,CACjC,CAEA,SAAgB,GAAwC,CACtD,IAAM,EAAW,EAAW,CAAe,EAC3C,MAAQ,IAAS,EAAW,EAAM,CAAQ,CAC5C"}