{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ask-ai",
  "title": "Ask AI",
  "description": "A source-aware handoff that opens a prepared prompt in an AI assistant or copies it for another one.",
  "dependencies": [
    "lucide-react@^1.31.0"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/default/ask-ai/ask-ai.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Check, Copy, TriangleAlert } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\nconst brandPaths = {\n  chatgpt:\n    \"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z\",\n  claude:\n    \"m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z\",\n  perplexity:\n    \"M22.3977 7.0896h-2.3106V.0676l-7.5094 6.3542V.1577h-1.1554v6.1966L4.4904 0v7.0896H1.6023v10.3976h2.8882V24l6.932-6.3591v6.2005h1.1554v-6.0469l6.9318 6.1807v-6.4879h2.8882V7.0896zm-3.4657-4.531v4.531h-5.355l5.355-4.531zm-13.2862.0676 4.8691 4.4634H5.6458V2.6262zM2.7576 16.332V8.245h7.8476l-6.1149 6.1147v1.9723H2.7576zm2.8882 5.0404v-3.8852h.0001v-2.6488l5.7763-5.7764v7.0111l-5.7764 5.2993zm12.7086.0248-5.7766-5.1509V9.0618l5.7766 5.7766v6.5588zm2.8882-5.0652h-1.733v-1.9723L13.3948 8.245h7.8478v8.087Z\",\n  grok: \"M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815\",\n} as const\n\nexport function AskAiLogo({\n  id,\n  name,\n  className,\n}: Pick<AskAiTarget, \"id\" | \"name\"> & { className?: string }) {\n  const path = brandPaths[id as keyof typeof brandPaths]\n\n  if (!path) {\n    return (\n      <span aria-hidden=\"true\" className={className}>\n        {name.slice(0, 1)}\n      </span>\n    )\n  }\n\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={cn(\"size-5 fill-current\", className)}\n      viewBox=\"0 0 24 24\"\n    >\n      <path d={path} />\n    </svg>\n  )\n}\n\nexport interface AskAiTarget {\n  href: string\n  id: string\n  name: string\n}\n\nexport function createAskAiTargets(prompt: string): AskAiTarget[] {\n  const query = encodeURIComponent(prompt)\n\n  return [\n    {\n      id: \"chatgpt\",\n      name: \"ChatGPT\",\n      href: `https://chatgpt.com/?hints=search&q=${query}`,\n    },\n    {\n      id: \"claude\",\n      name: \"Claude\",\n      href: `https://claude.ai/new?q=${query}`,\n    },\n    {\n      id: \"perplexity\",\n      name: \"Perplexity\",\n      href: `https://www.perplexity.ai/search?q=${query}`,\n    },\n    {\n      id: \"grok\",\n      name: \"Grok\",\n      href: `https://grok.com/?q=${query}`,\n    },\n  ]\n}\n\nexport interface AskAiProps extends Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"children\"\n> {\n  copyLabel?: string\n  description?: React.ReactNode\n  onPromptCopied?: (prompt: string) => void\n  prompt: string\n  subject: string\n  targets?: readonly AskAiTarget[]\n}\n\ntype CopyState = \"idle\" | \"copied\" | \"error\"\n\nexport const AskAi = React.forwardRef<HTMLDivElement, AskAiProps>(\n  function AskAi(\n    {\n      className,\n      copyLabel = \"Copy prompt\",\n      description = \"Choose an assistant, or copy the prompt for another one.\",\n      onPromptCopied,\n      prompt,\n      subject,\n      targets,\n      ...rootProps\n    },\n    forwardedRef\n  ) {\n    const [copyState, setCopyState] = React.useState<CopyState>(\"idle\")\n    const resetTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n    const resolvedTargets = React.useMemo(\n      () => targets ?? createAskAiTargets(prompt),\n      [prompt, targets]\n    )\n\n    React.useEffect(() => {\n      return () => {\n        if (resetTimer.current) clearTimeout(resetTimer.current)\n      }\n    }, [])\n\n    async function copyPrompt() {\n      try {\n        await navigator.clipboard.writeText(prompt)\n        setCopyState(\"copied\")\n        onPromptCopied?.(prompt)\n      } catch {\n        setCopyState(\"error\")\n      }\n\n      if (resetTimer.current) clearTimeout(resetTimer.current)\n      resetTimer.current = setTimeout(() => setCopyState(\"idle\"), 1800)\n    }\n\n    const statusLabel =\n      copyState === \"copied\"\n        ? \"Prompt copied\"\n        : copyState === \"error\"\n          ? \"Copy failed\"\n          : copyLabel\n\n    return (\n      <div\n        className={cn(\n          \"bg-card text-card-foreground border-border flex flex-col gap-4 rounded-xl border p-4 sm:flex-row sm:items-center sm:justify-between\",\n          className\n        )}\n        data-slot=\"ask-ai\"\n        ref={forwardedRef}\n        {...rootProps}\n      >\n        <div data-slot=\"ask-ai-content\" className=\"min-w-0\">\n          <p data-slot=\"ask-ai-title\" className=\"font-semibold\">\n            Ask an AI about {subject}\n          </p>\n          {description && (\n            <p\n              data-slot=\"ask-ai-description\"\n              className=\"text-muted-foreground mt-1 max-w-[34rem] text-sm leading-relaxed\"\n            >\n              {description}\n            </p>\n          )}\n        </div>\n\n        <div\n          data-slot=\"ask-ai-actions\"\n          aria-label={`Choose an AI assistant to ask about ${subject}`}\n          className=\"flex flex-wrap items-center gap-2\"\n          role=\"group\"\n        >\n          {resolvedTargets.map((target) => (\n            <a\n              data-slot=\"ask-ai-target\"\n              aria-label={`Ask ${target.name} about ${subject}, opens in a new tab`}\n              className=\"bg-background text-foreground border-border hover:bg-muted inline-flex size-11 shrink-0 items-center justify-center rounded-full border no-underline transition-[background-color,transform] duration-150 hover:-translate-y-0.5 active:translate-y-0 active:scale-[0.96] motion-reduce:transition-none\"\n              href={target.href}\n              key={target.id}\n              rel=\"noopener noreferrer nofollow\"\n              target=\"_blank\"\n              title={`Ask ${target.name}`}\n            >\n              <AskAiLogo id={target.id} name={target.name} />\n            </a>\n          ))}\n\n          <button\n            data-slot=\"ask-ai-copy\"\n            aria-label={`${copyLabel} about ${subject}`}\n            className=\"bg-foreground text-background inline-flex min-h-11 items-center gap-2 rounded-lg border border-transparent px-3 text-sm font-semibold transition-transform duration-150 hover:-translate-y-0.5 active:translate-y-0 active:scale-[0.98] motion-reduce:transition-none\"\n            onClick={copyPrompt}\n            type=\"button\"\n          >\n            {copyState === \"copied\" ? (\n              <Check aria-hidden=\"true\" size={15} />\n            ) : copyState === \"error\" ? (\n              <TriangleAlert aria-hidden=\"true\" size={15} />\n            ) : (\n              <Copy aria-hidden=\"true\" size={15} />\n            )}\n            {statusLabel}\n          </button>\n        </div>\n\n        <span\n          data-slot=\"ask-ai-status\"\n          aria-live=\"polite\"\n          className=\"sr-only\"\n          role=\"status\"\n        >\n          {copyState === \"copied\"\n            ? \"Prompt copied to clipboard.\"\n            : copyState === \"error\"\n              ? \"The prompt could not be copied.\"\n              : \"\"}\n        </span>\n      </div>\n    )\n  }\n)\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ai",
    "button",
    "links",
    "copy"
  ],
  "type": "registry:ui"
}