{"version":3,"file":"link.cjs","names":[],"sources":["../../src/utils/link.ts"],"sourcesContent":["import { computed, type Readable } from '@vielzeug/ripple';\n\nimport type { LinkTarget } from '../shared';\n\n/**\n * Computes a safe `rel` attribute value for anchor elements.\n *\n * When `target=\"_blank\"`, automatically injects `noopener` and `noreferrer`\n * to prevent reverse tabnapping attacks (the opened page accessing\n * `window.opener` to redirect the origin).\n *\n * @param rel    - The explicit `rel` prop value (may be undefined).\n * @param target - The link `target` prop value (may be undefined).\n * @returns A `rel` string with security tokens merged in, or `null` when no\n *          rel is needed.\n */\nexport function computeSafeRel(rel: string | undefined, target: string | undefined): string | null {\n  const base = rel ?? '';\n\n  if (target !== '_blank') return base || null;\n\n  const parts = new Set(base.split(/\\s+/).filter(Boolean));\n\n  parts.add('noopener');\n  parts.add('noreferrer');\n\n  return [...parts].join(' ');\n}\n\n/**\n * Props required by any component that renders as an anchor when `href` is set.\n * Import and spread into your component's props type to get consistent link support.\n */\nexport type LinkProps = {\n  /** When set, the component renders as an `<a>` instead of its default element. */\n  href?: string;\n  /** Anchor `rel` attribute. `noopener noreferrer` is automatically added for `target=\"_blank\"`. */\n  rel?: string;\n  /** Anchor browsing context. */\n  target?: LinkTarget;\n};\n\n/**\n * Derives computed link state from reactive `href`, `rel`, and `target` signals.\n *\n * Returns:\n * - `isLink` — true when `href` is set (and optionally not disabled)\n * - `effectiveRel` — `rel` merged with security tokens when `target=\"_blank\"`\n *\n * @example\n * ```ts\n * const { isLink, effectiveRel } = useLinkProps(props.href, props.rel, props.target);\n * ```\n */\nexport function useLinkProps(\n  href: Readable<string | undefined>,\n  rel: Readable<string | undefined>,\n  target: Readable<LinkTarget | undefined>,\n  disabled?: Readable<boolean>,\n) {\n  const isLink = computed(() => !!href.value && !disabled?.value);\n  const effectiveRel = computed(() => computeSafeRel(rel.value, target.value));\n\n  return { effectiveRel, isLink };\n}\n"],"mappings":"kCAgBA,SAAgB,EAAe,EAAyB,EAA2C,CACjG,IAAM,EAAO,GAAO,GAEpB,GAAI,IAAW,SAAU,OAAO,GAAQ,KAExC,IAAM,EAAQ,IAAI,IAAI,EAAK,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,CAAC,EAKvD,OAHA,EAAM,IAAI,UAAU,EACpB,EAAM,IAAI,YAAY,EAEf,CAAC,GAAG,CAAK,CAAC,CAAC,KAAK,GAAG,CAC5B,CA2BA,SAAgB,EACd,EACA,EACA,EACA,EACA,CACA,IAAM,GAAA,EAAS,EAAA,SAAA,KAAe,CAAC,CAAC,EAAK,OAAS,CAAC,GAAU,KAAK,EAG9D,MAAO,CAAE,cAAA,EAFY,EAAA,SAAA,KAAe,EAAe,EAAI,MAAO,EAAO,KAAK,CAEjE,EAAc,QAAO,CAChC"}