{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "link",
  "title": "Link",
  "type": "registry:ui",
  "description": "Styled anchor with router integration. Renders an <a> for href, a router-link for to, and handles external links with target/rel. Supports underline variants (always/hover/none), color variants (default/primary/muted), disabled state, left/right icon slots, size variants, and asChild composition.",
  "categories": [
    "navigation"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/components/link/link.ts",
      "content": "import { LitElement, css, html, nothing } from 'lit'\nimport { cn } from '../../lib/utils'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\nimport { linkVariants, type LinkVariants } from './link.variants'\n\ntype Underline = NonNullable<LinkVariants['underline']>\ntype Color = NonNullable<LinkVariants['color']>\ntype Size = NonNullable<LinkVariants['size']>\n\n/**\n * <uip-link> — styled navigational link.\n */\nexport class UipLink extends LitElement {\n  static styles = [\n    tailwind,\n    css`\n      :host {\n        display: inline-flex;\n      }\n    `,\n  ]\n\n  static properties = {\n    href: { reflect: true },\n    to: { reflect: true },\n    underline: { reflect: true },\n    color: { reflect: true },\n    size: { reflect: true },\n    external: { type: Boolean, reflect: true },\n    disabled: { type: Boolean, reflect: true },\n    target: { reflect: true },\n    rel: { reflect: true },\n  }\n\n  href?: string\n  to?: string\n  underline: Underline = 'hover'\n  color: Color = 'primary'\n  size: Size = 'default'\n  external?: boolean\n  disabled = false\n  target?: string\n  rel?: string\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'link')\n  }\n\n  willUpdate() {\n    this.setAttribute('data-underline', this.underline)\n    this.setAttribute('data-color', this.color)\n    this.setAttribute('data-size', this.size)\n    if (this.disabled) {\n      this.setAttribute('data-disabled', '')\n    } else {\n      this.removeAttribute('data-disabled')\n    }\n  }\n\n  private onClick(e: MouseEvent) {\n    if (this.disabled) {\n      e.preventDefault()\n      e.stopPropagation()\n    }\n  }\n\n  render() {\n    const isExternal =\n      !this.disabled && (this.external !== undefined ? this.external : typeof this.href === 'string' && /^https?:\\/\\//.test(this.href))\n    const target = this.target ?? (isExternal ? '_blank' : undefined)\n    const rel = this.rel ?? (isExternal ? 'noopener noreferrer' : undefined)\n    const resolvedHref = this.disabled ? undefined : (this.to ?? this.href)\n\n    return html`\n      <a\n        part=\"base\"\n        data-slot=\"link\"\n        href=${resolvedHref ?? nothing}\n        target=${target ?? nothing}\n        rel=${rel ?? nothing}\n        aria-disabled=${this.disabled ? 'true' : nothing}\n        tabindex=${this.disabled ? -1 : nothing}\n        class=${cn(\n          linkVariants({ underline: this.underline, color: this.color, size: this.size }),\n          this.disabled && 'pointer-events-none opacity-50',\n        )}\n        @click=${this.onClick}\n      >\n        <slot name=\"left\" class=\"[&::slotted(svg)]:size-4 [&::slotted(svg)]:shrink-0\"></slot>\n        <slot class=\"[&::slotted(svg)]:size-4 [&::slotted(svg)]:shrink-0\"></slot>\n        <slot name=\"right\" class=\"[&::slotted(svg)]:size-4 [&::slotted(svg)]:shrink-0\"></slot>\n      </a>\n    `\n  }\n}\n\ncustomElements.get('uip-link') || customElements.define('uip-link', UipLink)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-link': UipLink\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/components/link/link.ts"
    },
    {
      "path": "packages/elements-lit/src/components/link/link.variants.ts",
      "content": "import type { VariantProps } from 'class-variance-authority'\nimport { cva } from 'class-variance-authority'\n\nexport const linkVariants = cva(\n  \"inline-flex items-center gap-1.5 font-medium transition-colors duration-200 outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px] rounded-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      underline: {\n        none: 'no-underline',\n        always: 'underline underline-offset-4',\n        hover: 'no-underline hover:underline hover:underline-offset-4',\n      },\n      color: {\n        default: 'text-foreground hover:text-foreground/80',\n        primary: 'text-primary hover:text-primary/80',\n        muted: 'text-muted-foreground hover:text-foreground',\n      },\n      size: {\n        sm: 'text-xs gap-1',\n        default: 'text-sm',\n        lg: 'text-base',\n      },\n    },\n    defaultVariants: {\n      underline: 'hover',\n      color: 'primary',\n      size: 'default',\n    },\n  },\n)\n\nexport type LinkVariants = VariantProps<typeof linkVariants>\n",
      "type": "registry:file",
      "target": "src/uip/components/link/link.variants.ts"
    }
  ],
  "dependencies": [
    "class-variance-authority",
    "lit"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/lit-core.json"
  ]
}
