{"version":3,"sources":["../../src/components/Link.tsx"],"sourcesContent":["import { ReactNode, use } from 'react';\nimport { isBrowserGestureClick, useComposedAnchorClick } from '../anchorClick';\nimport { navigate } from '../routing';\nimport { scrollToId } from '../scrollToId';\nimport { TinkerableContext } from '../TinkerableContext';\nimport { constructOuterUrl, isInternalHref } from '../urlUtils';\n\n/** A same-page anchor (`#frag`): scrolls the addressed section into view on click\n *  **without a route change** (MARKDOWN_SYNTAX_SPEC §13.5). The default behavior of a\n *  bare `#`-href is intercepted so the sandbox URL the host owns is never mutated\n *  out from under it; a fragment that names nothing leaves the scroll position\n *  untouched (a soft failure). */\nexport const FragmentLink = ({\n  href,\n  children,\n  onClick,\n  ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n  const clickHandler = useComposedAnchorClick(\n    onClick,\n    (e) => {\n      if (href && href.startsWith('#')) {\n        e.preventDefault();\n        scrollToId(href.slice(1));\n      }\n    },\n    [href],\n  );\n  return (\n    <a href={href} onClick={clickHandler} {...props}>\n      {children}\n    </a>\n  );\n};\n\n/** An `<a>` that performs in-sandbox navigation on click (prevents the default\n *  full-page load and routes via {@link navigate}).\n *\n *  A consumer-supplied `onClick` is COMPOSED with the router interception, never\n *  substituted for it (`useComposedAnchorClick`, `../anchorClick`): it runs first, and\n *  calling `preventDefault()` opts out of routing. Regression guard: `...props`\n *  used to spread AFTER `onClick={clickHandler}`, so a consumer `onClick` (e.g. a\n *  drawer's close-on-navigate) silently REPLACED the interception — the default\n *  anchor action then navigated the sandboxed iframe itself to the host URL,\n *  reloading the whole app (and framing the host inside its own sandbox).\n *\n *  Modifier/middle clicks and explicit non-self `target`s keep the browser\n *  default: the rendered href is a real host URL, so open-in-new-tab works. */\nexport const InternalLink = ({\n  href,\n  children,\n  onClick,\n  target,\n  ...props\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n  const clickHandler = useComposedAnchorClick(\n    onClick,\n    (e) => {\n      if (!href) return;\n      // Open-in-new-tab gestures (and an explicit target) are the browser's.\n      if (isBrowserGestureClick(e)) return;\n      if (target && target !== '_self') return;\n      e.preventDefault();\n      navigate(href);\n    },\n    [href, target],\n  );\n  // Spread FIRST so no forwarded prop can clobber the interception or the href.\n  return (\n    <a {...props} href={href} target={target} onClick={clickHandler}>\n      {children}\n    </a>\n  );\n};\n\n/** A link that routes same-app hrefs through the sandbox router (as an\n *  {@link InternalLink}) and renders external hrefs as a plain `<a>`. */\nexport const Link = ({\n  href,\n  children,\n  ...properties\n}: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>): ReactNode => {\n  const { outerHref, navigationState } = use(TinkerableContext);\n  // A pure same-page fragment (`#sec-8-9`) scrolls in place — no route change (§13.5).\n  if (href && href.startsWith('#')) {\n    return (\n      <FragmentLink href={href} {...properties}>\n        {children}\n      </FragmentLink>\n    );\n  }\n  if (href && isInternalHref(outerHref, href, navigationState)) {\n    const targetHref = constructOuterUrl(outerHref, href, navigationState);\n    return (\n      <InternalLink href={targetHref} {...properties}>\n        {children}\n      </InternalLink>\n    );\n  } else {\n    // create a regular link to external resource\n    return <a {...{ href, ...properties }}>{children}</a>;\n  }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BI;AA7BJ,mBAA+B;AAC/B,yBAA8D;AAC9D,qBAAyB;AACzB,wBAA2B;AAC3B,+BAAkC;AAClC,sBAAkD;AAO3C,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,mBAAe;AAAA,IACnB;AAAA,IACA,CAAC,MAAM;AACL,UAAI,QAAQ,KAAK,WAAW,GAAG,GAAG;AAChC,UAAE,eAAe;AACjB,0CAAW,KAAK,MAAM,CAAC,CAAC;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AACA,SACE,4CAAC,OAAE,MAAY,SAAS,cAAe,GAAG,OACvC,UACH;AAEJ;AAeO,MAAM,eAAe,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,mBAAe;AAAA,IACnB;AAAA,IACA,CAAC,MAAM;AACL,UAAI,CAAC,KAAM;AAEX,cAAI,0CAAsB,CAAC,EAAG;AAC9B,UAAI,UAAU,WAAW,QAAS;AAClC,QAAE,eAAe;AACjB,mCAAS,IAAI;AAAA,IACf;AAAA,IACA,CAAC,MAAM,MAAM;AAAA,EACf;AAEA,SACE,4CAAC,OAAG,GAAG,OAAO,MAAY,QAAgB,SAAS,cAChD,UACH;AAEJ;AAIO,MAAM,OAAO,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA4G;AAC1G,QAAM,EAAE,WAAW,gBAAgB,QAAI,kBAAI,0CAAiB;AAE5D,MAAI,QAAQ,KAAK,WAAW,GAAG,GAAG;AAChC,WACE,4CAAC,gBAAa,MAAa,GAAG,YAC3B,UACH;AAAA,EAEJ;AACA,MAAI,YAAQ,gCAAe,WAAW,MAAM,eAAe,GAAG;AAC5D,UAAM,iBAAa,mCAAkB,WAAW,MAAM,eAAe;AACrE,WACE,4CAAC,gBAAa,MAAM,YAAa,GAAG,YACjC,UACH;AAAA,EAEJ,OAAO;AAEL,WAAO,4CAAC,OAAG,GAAG,EAAE,MAAM,GAAG,WAAW,GAAI,UAAS;AAAA,EACnD;AACF;","names":[]}