{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "preview-link",
  "title": "Preview Link",
  "description": "A link wrapper that shows a static page preview card on hover.",
  "dependencies": [
    "motion",
    "radix-ui"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/corr/components/preview-link.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n  PreviewLinkCard,\n  PreviewLinkCardContent,\n  PreviewLinkCardImage,\n  PreviewLinkCardTrigger,\n  type PreviewLinkCardContentProps,\n  type PreviewLinkCardProps,\n} from \"@/components/animate-ui/components/radix/preview-link-card\"\nimport { cn } from \"@/lib/utils\"\n\nexport type PreviewLinkProps = Omit<PreviewLinkCardProps, \"children\"> & {\n  children?: React.ReactNode\n  trigger?: React.ReactNode\n  className?: string\n  contentClassName?: string\n  imageClassName?: string\n  contentProps?: Omit<PreviewLinkCardContentProps, \"children\" | \"className\">\n}\n\nexport function PreviewLink({\n  href,\n  src,\n  width = 420,\n  height = 236,\n  viewportWidth = 1440,\n  viewportHeight = 900,\n  viewportIsMobile = false,\n  deviceScaleFactor = 1,\n  colorScheme = \"light\",\n  forceRefresh,\n  children,\n  trigger,\n  className,\n  contentClassName,\n  imageClassName,\n  contentProps,\n  ...props\n}: PreviewLinkProps) {\n  return (\n    <PreviewLinkCard\n      href={href}\n      src={src}\n      width={width}\n      height={height}\n      viewportWidth={viewportWidth}\n      viewportHeight={viewportHeight}\n      viewportIsMobile={viewportIsMobile}\n      deviceScaleFactor={deviceScaleFactor}\n      colorScheme={colorScheme}\n      forceRefresh={forceRefresh}\n      {...props}\n    >\n      <PreviewLinkCardTrigger asChild>\n        {trigger ?? (\n          <a\n            href={href}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className={cn(\n              \"font-medium underline underline-offset-4 transition-colors hover:text-muted-foreground focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none\",\n              className\n            )}\n          >\n            {children ?? href}\n          </a>\n        )}\n      </PreviewLinkCardTrigger>\n      <PreviewLinkCardContent\n        className={cn(\"bg-background p-0\", contentClassName)}\n        {...contentProps}\n      >\n        <PreviewLinkCardImage\n          alt={`${href} preview`}\n          className={cn(\"block rounded-md object-cover\", imageClassName)}\n        />\n      </PreviewLinkCardContent>\n    </PreviewLinkCard>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/animate-ui/components/radix/preview-link-card.tsx",
      "content": "import {\n  PreviewLinkCard as PreviewLinkCardPrimitive,\n  PreviewLinkCardTrigger as PreviewLinkCardTriggerPrimitive,\n  PreviewLinkCardPortal as PreviewLinkCardPortalPrimitive,\n  PreviewLinkCardContent as PreviewLinkCardContentPrimitive,\n  PreviewLinkCardImage as PreviewLinkCardImagePrimitive,\n  type PreviewLinkCardProps as PreviewLinkCardPrimitiveProps,\n  type PreviewLinkCardTriggerProps as PreviewLinkCardTriggerPrimitiveProps,\n  type PreviewLinkCardContentProps as PreviewLinkCardContentPrimitiveProps,\n  type PreviewLinkCardImageProps as PreviewLinkCardImagePrimitiveProps,\n} from '@/components/animate-ui/primitives/radix/preview-link-card';\nimport { cn } from '@/lib/utils';\n\ntype PreviewLinkCardProps = PreviewLinkCardPrimitiveProps;\n\nfunction PreviewLinkCard(props: PreviewLinkCardProps) {\n  return <PreviewLinkCardPrimitive {...props} />;\n}\n\ntype PreviewLinkCardTriggerProps = PreviewLinkCardTriggerPrimitiveProps;\n\nfunction PreviewLinkCardTrigger(props: PreviewLinkCardTriggerProps) {\n  return <PreviewLinkCardTriggerPrimitive {...props} />;\n}\n\ntype PreviewLinkCardContentProps = PreviewLinkCardContentPrimitiveProps;\n\nfunction PreviewLinkCardContent({\n  className,\n  align = 'center',\n  sideOffset = 4,\n  ...props\n}: PreviewLinkCardContentProps) {\n  return (\n    <PreviewLinkCardPortalPrimitive>\n      <PreviewLinkCardContentPrimitive\n        align={align}\n        sideOffset={sideOffset}\n        className={cn(\n          'z-50 origin-(--radix-hover-card-content-transform-origin) rounded-md border shadow-md outline-hidden overflow-hidden',\n          className,\n        )}\n        {...props}\n      />\n    </PreviewLinkCardPortalPrimitive>\n  );\n}\n\ntype PreviewLinkCardImageProps = PreviewLinkCardImagePrimitiveProps;\n\nfunction PreviewLinkCardImage(props: PreviewLinkCardImageProps) {\n  return <PreviewLinkCardImagePrimitive {...props} />;\n}\n\nexport {\n  PreviewLinkCard,\n  PreviewLinkCardTrigger,\n  PreviewLinkCardContent,\n  PreviewLinkCardImage,\n  type PreviewLinkCardProps,\n  type PreviewLinkCardTriggerProps,\n  type PreviewLinkCardContentProps,\n  type PreviewLinkCardImageProps,\n};\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/animate-ui/primitives/radix/preview-link-card.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\n\nimport {\n  HoverCard as HoverCardPrimitive,\n  HoverCardTrigger as HoverCardTriggerPrimitive,\n  HoverCardContent as HoverCardContentPrimitive,\n  HoverCardPortal as HoverCardPortalPrimitive,\n  HoverCardArrow as HoverCardArrowPrimitive,\n  type HoverCardProps as HoverCardPropsPrimitive,\n  type HoverCardTriggerProps as HoverCardTriggerPropsPrimitive,\n  type HoverCardContentProps as HoverCardContentPropsPrimitive,\n  type HoverCardPortalProps as HoverCardPortalPropsPrimitive,\n  type HoverCardArrowProps as HoverCardArrowPropsPrimitive,\n} from '@/components/animate-ui/primitives/radix/hover-card';\nimport { getStrictContext } from '@/lib/get-strict-context';\n\ntype PreviewLinkCardContextType = {\n  href: string;\n  src?: string;\n  width?: number;\n  height?: number;\n};\n\nconst [PreviewLinkCardProvider, usePreviewLinkCard] =\n  getStrictContext<PreviewLinkCardContextType>('PreviewLinkCardContext');\n\ntype PreviewLinkCardProps = HoverCardPropsPrimitive & {\n  href: string;\n  src?: string;\n  width?: number;\n  height?: number;\n  viewportWidth?: number;\n  viewportHeight?: number;\n  viewportIsMobile?: boolean;\n  deviceScaleFactor?: number;\n  colorScheme?: 'light' | 'dark';\n  forceRefresh?: boolean;\n};\n\nfunction PreviewLinkCard({\n  href,\n  src,\n  width = 240,\n  height = 135,\n  viewportWidth,\n  viewportHeight,\n  viewportIsMobile = false,\n  deviceScaleFactor = 1,\n  colorScheme = 'light',\n  forceRefresh = false,\n  ...props\n}: PreviewLinkCardProps) {\n  const imageSrc =\n    src ??\n    `https://api.microlink.io/?${buildQueryString({\n      url: href,\n      screenshot: true,\n      meta: false,\n      embed: 'screenshot.url',\n      colorScheme,\n      force: forceRefresh,\n      'viewport.isMobile': viewportIsMobile ? true : undefined,\n      'viewport.deviceScaleFactor': deviceScaleFactor,\n      'viewport.width': viewportWidth ?? width * 3,\n      'viewport.height': viewportHeight ?? height * 3,\n    })}`;\n\n  React.useEffect(() => {\n    const link = document.createElement('link');\n    link.rel = 'preload';\n    link.as = 'image';\n    link.href = imageSrc;\n    document.head.appendChild(link);\n    return () => {\n      document.head.removeChild(link);\n    };\n  }, [imageSrc]);\n\n  return (\n    <PreviewLinkCardProvider value={{ href, src: imageSrc, width, height }}>\n      <HoverCardPrimitive data-slot=\"preview-link-card\" {...props} />\n    </PreviewLinkCardProvider>\n  );\n}\n\ntype PreviewLinkCardTriggerProps = HoverCardTriggerPropsPrimitive &\n  React.ComponentProps<'a'>;\n\nfunction PreviewLinkCardTrigger({\n  asChild,\n  children,\n  href: hrefProp,\n  ...props\n}: PreviewLinkCardTriggerProps) {\n  const { href } = usePreviewLinkCard();\n\n  return (\n    <HoverCardTriggerPrimitive\n      data-slot=\"preview-link-card-trigger\"\n      asChild\n      {...props}\n    >\n      {asChild ? children : <a href={hrefProp ?? href}>{children}</a>}\n    </HoverCardTriggerPrimitive>\n  );\n}\n\ntype PreviewLinkCardPortalProps = HoverCardPortalPropsPrimitive;\n\nfunction PreviewLinkCardPortal(props: PreviewLinkCardPortalProps) {\n  return (\n    <HoverCardPortalPrimitive data-slot=\"preview-link-card-portal\" {...props} />\n  );\n}\n\nfunction buildQueryString(\n  params: Record<string, string | number | boolean | undefined | null>,\n) {\n  const sp = new URLSearchParams();\n  for (const [k, v] of Object.entries(params)) {\n    if (v === undefined || v === null) continue;\n    sp.append(k, String(v));\n  }\n  return sp.toString();\n}\n\ntype PreviewLinkCardContentProps = HoverCardContentPropsPrimitive &\n  React.ComponentProps<'a'>;\n\nfunction PreviewLinkCardContent({\n  side = 'top',\n  sideOffset = 10,\n  align = 'center',\n  alignOffset,\n  avoidCollisions,\n  collisionBoundary,\n  collisionPadding,\n  arrowPadding,\n  sticky,\n  hideWhenDetached,\n  transition = { type: 'spring', stiffness: 300, damping: 25 },\n  asChild,\n  children,\n  href: hrefProp,\n  style,\n  ...props\n}: PreviewLinkCardContentProps) {\n  const { href } = usePreviewLinkCard();\n\n  return (\n    <HoverCardContentPrimitive\n      data-slot=\"preview-link-card-content\"\n      side={side}\n      sideOffset={sideOffset}\n      align={align}\n      alignOffset={alignOffset}\n      avoidCollisions={avoidCollisions}\n      collisionBoundary={collisionBoundary}\n      collisionPadding={collisionPadding}\n      arrowPadding={arrowPadding}\n      sticky={sticky}\n      hideWhenDetached={hideWhenDetached}\n      transition={transition}\n      asChild={asChild}\n      {...(asChild ? { style, ...props } : {})}\n    >\n      {asChild ? (\n        children\n      ) : (\n        <a\n          style={{\n            display: 'block',\n            ...style,\n          }}\n          href={hrefProp ?? href}\n          {...props}\n        >\n          {children}\n        </a>\n      )}\n    </HoverCardContentPrimitive>\n  );\n}\n\ntype PreviewLinkCardImageProps = Omit<\n  React.ComponentProps<'img'>,\n  'src' | 'width' | 'height'\n>;\n\nfunction PreviewLinkCardImage({\n  alt = 'preview image',\n  ...props\n}: PreviewLinkCardImageProps) {\n  const { src, width, height } = usePreviewLinkCard();\n\n  return <img src={src} width={width} height={height} alt={alt} {...props} />;\n}\n\ntype PreviewLinkCardArrowProps = HoverCardArrowPropsPrimitive;\n\nfunction PreviewLinkCardArrow(props: PreviewLinkCardArrowProps) {\n  return (\n    <HoverCardArrowPrimitive data-slot=\"preview-link-card-arrow\" {...props} />\n  );\n}\n\nexport {\n  PreviewLinkCard,\n  PreviewLinkCardTrigger,\n  PreviewLinkCardPortal,\n  PreviewLinkCardContent,\n  PreviewLinkCardImage,\n  PreviewLinkCardArrow,\n  usePreviewLinkCard,\n  type PreviewLinkCardProps,\n  type PreviewLinkCardTriggerProps,\n  type PreviewLinkCardPortalProps,\n  type PreviewLinkCardContentProps,\n  type PreviewLinkCardImageProps,\n  type PreviewLinkCardArrowProps,\n  type PreviewLinkCardContextType,\n};\n",
      "type": "registry:component"
    },
    {
      "path": "src/components/animate-ui/primitives/radix/hover-card.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { HoverCard as HoverCardPrimitive } from 'radix-ui';\nimport {\n  AnimatePresence,\n  motion,\n  useMotionValue,\n  useSpring,\n  type MotionValue,\n  type HTMLMotionProps,\n  type SpringOptions,\n} from 'motion/react';\n\nimport { getStrictContext } from '@/lib/get-strict-context';\nimport { useControlledState } from '@/hooks/use-controlled-state';\n\ntype HoverCardContextType = {\n  isOpen: boolean;\n  setIsOpen: (isOpen: boolean) => void;\n  x: MotionValue<number>;\n  y: MotionValue<number>;\n  followCursor?: boolean | 'x' | 'y';\n  followCursorSpringOptions?: SpringOptions;\n};\n\nconst [HoverCardProvider, useHoverCard] =\n  getStrictContext<HoverCardContextType>('HoverCardContext');\n\ntype HoverCardProps = React.ComponentProps<typeof HoverCardPrimitive.Root> & {\n  followCursor?: boolean | 'x' | 'y';\n  followCursorSpringOptions?: SpringOptions;\n};\n\nfunction HoverCard({\n  followCursor = false,\n  followCursorSpringOptions = { stiffness: 200, damping: 17 },\n  ...props\n}: HoverCardProps) {\n  const [isOpen, setIsOpen] = useControlledState({\n    value: props?.open,\n    defaultValue: props?.defaultOpen,\n    onChange: props?.onOpenChange,\n  });\n  const x = useMotionValue(0);\n  const y = useMotionValue(0);\n\n  return (\n    <HoverCardProvider\n      value={{\n        isOpen,\n        setIsOpen,\n        x,\n        y,\n        followCursor,\n        followCursorSpringOptions,\n      }}\n    >\n      <HoverCardPrimitive.Root\n        data-slot=\"hover-card\"\n        {...props}\n        onOpenChange={setIsOpen}\n      />\n    </HoverCardProvider>\n  );\n}\n\ntype HoverCardTriggerProps = React.ComponentProps<\n  typeof HoverCardPrimitive.Trigger\n>;\n\nfunction HoverCardTrigger({ onMouseMove, ...props }: HoverCardTriggerProps) {\n  const { x, y, followCursor } = useHoverCard();\n\n  const handleMouseMove = (event: React.MouseEvent<HTMLAnchorElement>) => {\n    onMouseMove?.(event);\n\n    const target = event.currentTarget.getBoundingClientRect();\n\n    if (followCursor === 'x' || followCursor === true) {\n      const eventOffsetX = event.clientX - target.left;\n      const offsetXFromCenter = (eventOffsetX - target.width / 2) / 2;\n      x.set(offsetXFromCenter);\n    }\n\n    if (followCursor === 'y' || followCursor === true) {\n      const eventOffsetY = event.clientY - target.top;\n      const offsetYFromCenter = (eventOffsetY - target.height / 2) / 2;\n      y.set(offsetYFromCenter);\n    }\n  };\n\n  return (\n    <HoverCardPrimitive.Trigger\n      data-slot=\"hover-card-trigger\"\n      onMouseMove={handleMouseMove}\n      {...props}\n    />\n  );\n}\n\ntype HoverCardPortalProps = Omit<\n  React.ComponentProps<typeof HoverCardPrimitive.Portal>,\n  'forceMount'\n>;\n\nfunction HoverCardPortal(props: HoverCardPortalProps) {\n  const { isOpen } = useHoverCard();\n\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <HoverCardPrimitive.Portal\n          forceMount\n          data-slot=\"hover-card-portal\"\n          {...props}\n        />\n      )}\n    </AnimatePresence>\n  );\n}\n\ntype HoverCardContentProps = React.ComponentProps<\n  typeof HoverCardPrimitive.Content\n> &\n  HTMLMotionProps<'div'>;\n\nfunction HoverCardContent({\n  align,\n  alignOffset,\n  side,\n  sideOffset,\n  avoidCollisions,\n  collisionBoundary,\n  collisionPadding,\n  arrowPadding,\n  sticky,\n  hideWhenDetached,\n  style,\n  transition = { type: 'spring', stiffness: 300, damping: 25 },\n  ...props\n}: HoverCardContentProps) {\n  const { x, y, followCursor, followCursorSpringOptions } = useHoverCard();\n  const translateX = useSpring(x, followCursorSpringOptions);\n  const translateY = useSpring(y, followCursorSpringOptions);\n\n  return (\n    <HoverCardPrimitive.Content\n      asChild\n      forceMount\n      align={align}\n      alignOffset={alignOffset}\n      side={side}\n      sideOffset={sideOffset}\n      avoidCollisions={avoidCollisions}\n      collisionBoundary={collisionBoundary}\n      collisionPadding={collisionPadding}\n      arrowPadding={arrowPadding}\n      sticky={sticky}\n      hideWhenDetached={hideWhenDetached}\n    >\n      <motion.div\n        key=\"hover-card-content\"\n        data-slot=\"hover-card-content\"\n        initial={{ opacity: 0, scale: 0.5 }}\n        animate={{ opacity: 1, scale: 1 }}\n        exit={{ opacity: 0, scale: 0.5 }}\n        transition={transition}\n        style={{\n          x:\n            followCursor === 'x' || followCursor === true\n              ? translateX\n              : undefined,\n          y:\n            followCursor === 'y' || followCursor === true\n              ? translateY\n              : undefined,\n          ...style,\n        }}\n        {...props}\n      />\n    </HoverCardPrimitive.Content>\n  );\n}\n\ntype HoverCardArrowProps = React.ComponentProps<\n  typeof HoverCardPrimitive.Arrow\n>;\n\nfunction HoverCardArrow(props: HoverCardArrowProps) {\n  return <HoverCardPrimitive.Arrow data-slot=\"hover-card-arrow\" {...props} />;\n}\n\nexport {\n  HoverCard,\n  HoverCardTrigger,\n  HoverCardPortal,\n  HoverCardContent,\n  HoverCardArrow,\n  useHoverCard,\n  type HoverCardProps,\n  type HoverCardTriggerProps,\n  type HoverCardPortalProps,\n  type HoverCardContentProps,\n  type HoverCardArrowProps,\n  type HoverCardContextType,\n};\n",
      "type": "registry:component"
    },
    {
      "path": "src/lib/get-strict-context.tsx",
      "content": "import * as React from 'react';\n\nfunction getStrictContext<T>(\n  name?: string,\n): readonly [\n  ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => React.JSX.Element,\n  () => T,\n] {\n  const Context = React.createContext<T | undefined>(undefined);\n\n  const Provider = ({\n    value,\n    children,\n  }: {\n    value: T;\n    children?: React.ReactNode;\n  }) => <Context.Provider value={value}>{children}</Context.Provider>;\n\n  const useSafeContext = () => {\n    const ctx = React.useContext(Context);\n    if (ctx === undefined) {\n      throw new Error(`useContext must be used within ${name ?? 'a Provider'}`);\n    }\n    return ctx;\n  };\n\n  return [Provider, useSafeContext] as const;\n}\n\nexport { getStrictContext };\n",
      "type": "registry:lib"
    },
    {
      "path": "src/hooks/use-controlled-state.tsx",
      "content": "import * as React from 'react';\n\ninterface CommonControlledStateProps<T> {\n  value?: T;\n  defaultValue?: T;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useControlledState<T, Rest extends any[] = []>(\n  props: CommonControlledStateProps<T> & {\n    onChange?: (value: T, ...args: Rest) => void;\n  },\n): readonly [T, (next: T, ...args: Rest) => void] {\n  const { value, defaultValue, onChange } = props;\n\n  const [state, setInternalState] = React.useState<T>(\n    value !== undefined ? value : (defaultValue as T),\n  );\n\n  React.useEffect(() => {\n    if (value !== undefined) setInternalState(value);\n  }, [value]);\n\n  const setState = React.useCallback(\n    (next: T, ...args: Rest) => {\n      setInternalState(next);\n      onChange?.(next, ...args);\n    },\n    [onChange],\n  );\n\n  return [state, setState] as const;\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:component"
}