|
| 1 | +'use client' |
| 2 | + |
| 3 | +import { useClipboard } from '@ark-ui/react/clipboard' |
| 4 | +import { Portal } from '@ark-ui/react/portal' |
| 5 | +import { SiMarkdown } from '@icons-pack/react-simple-icons' |
| 6 | +import { CheckIcon, ChevronDownIcon } from 'lucide-react' |
| 7 | +import { Box, HStack } from 'styled-system/jsx' |
| 8 | +import { Button } from '~/components/ui/button' |
| 9 | +import { IconButton } from '~/components/ui/icon-button' |
| 10 | +import { Menu } from '~/components/ui/menu' |
| 11 | +import { getPublicUrl } from '~/lib/get-public-url' |
| 12 | + |
| 13 | +interface CopyPageWidgetProps { |
| 14 | + slug: string |
| 15 | + content: string |
| 16 | +} |
| 17 | + |
| 18 | +export const CopyPageWidget = (props: CopyPageWidgetProps) => { |
| 19 | + const { slug, content } = props |
| 20 | + return ( |
| 21 | + <HStack gap="0" spaceX="-1px"> |
| 22 | + <CopyPageButton content={content} /> |
| 23 | + <ActionMenu slug={slug} /> |
| 24 | + </HStack> |
| 25 | + ) |
| 26 | +} |
| 27 | + |
| 28 | +const CopyPageButton = (props: { content: string }) => { |
| 29 | + const { content } = props |
| 30 | + const clipboard = useClipboard({ value: content, timeout: 1000 }) |
| 31 | + return ( |
| 32 | + <Button onClick={clipboard.copy} size="xs" variant="outline" borderEndRadius="0"> |
| 33 | + <HStack gap="2"> |
| 34 | + {clipboard.copied ? <CheckIcon size={16} /> : <SiMarkdown size={18} />} |
| 35 | + <Box as="span" textStyle="sm" fontWeight="medium"> |
| 36 | + Copy Page |
| 37 | + </Box> |
| 38 | + </HStack> |
| 39 | + </Button> |
| 40 | + ) |
| 41 | +} |
| 42 | + |
| 43 | +const ActionMenu = (props: { slug: string }) => { |
| 44 | + const { slug } = props |
| 45 | + |
| 46 | + const pageUrl = getPublicUrl(`/docs/${slug}`) |
| 47 | + const readUrl = encodeURIComponent( |
| 48 | + `Use web browsing to access links and information: ${pageUrl}\n\nI want to ask some questions`, |
| 49 | + ) |
| 50 | + |
| 51 | + const items = [ |
| 52 | + { |
| 53 | + label: 'View as markdown', |
| 54 | + href: `${pageUrl}.mdx`, |
| 55 | + icon: () => <SiMarkdown size={18} />, |
| 56 | + }, |
| 57 | + { |
| 58 | + label: 'Open in ChatGPT', |
| 59 | + href: `https://chatgpt.com/?hints=search&q=${readUrl}`, |
| 60 | + icon: () => ( |
| 61 | + <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"> |
| 62 | + <title>ChatGPT</title> |
| 63 | + <path d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a5.985 5.985 0 0 0-3.998 2.9 6.046 6.046 0 0 0 .743 7.097 5.98 5.98 0 0 0 .51 4.911 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.99 5.99 0 0 0 3.997-2.9 6.056 6.056 0 0 0-.747-7.073zM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.141-.081 4.779-2.758a.795.795 0 0 0 .392-.681v-6.737l2.02 1.168a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494zM3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085 4.783 2.759a.771.771 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646zM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.676l5.815 3.355-2.02 1.168a.076.076 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667zm2.01-3.023l-.141-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.795.795 0 0 0-.393.681zm1.097-2.365l2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5z" /> |
| 64 | + </svg> |
| 65 | + ), |
| 66 | + }, |
| 67 | + { |
| 68 | + label: 'Open in Claude', |
| 69 | + href: `https://claude.ai/new?q=${readUrl}`, |
| 70 | + icon: () => ( |
| 71 | + <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" role="img"> |
| 72 | + <title>Anthropic</title> |
| 73 | + <path d="M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z" /> |
| 74 | + </svg> |
| 75 | + ), |
| 76 | + }, |
| 77 | + ] |
| 78 | + |
| 79 | + return ( |
| 80 | + <Menu.Root size="sm" positioning={{ placement: 'bottom-end' }}> |
| 81 | + <Menu.Trigger asChild> |
| 82 | + <IconButton size="xs" variant="outline" borderStartRadius="0" borderStartWidth="0px"> |
| 83 | + <ChevronDownIcon size={16} /> |
| 84 | + </IconButton> |
| 85 | + </Menu.Trigger> |
| 86 | + <Portal> |
| 87 | + <Menu.Positioner> |
| 88 | + <Menu.Content minW="200px"> |
| 89 | + {items.map((item) => { |
| 90 | + const Icon = item.icon |
| 91 | + return ( |
| 92 | + <Menu.Item key={item.label} value={item.label} asChild> |
| 93 | + <a href={item.href} target="_blank" rel="noopener noreferrer"> |
| 94 | + <HStack gap="2" width="full"> |
| 95 | + <Icon /> |
| 96 | + <span>{item.label}</span> |
| 97 | + </HStack> |
| 98 | + </a> |
| 99 | + </Menu.Item> |
| 100 | + ) |
| 101 | + })} |
| 102 | + </Menu.Content> |
| 103 | + </Menu.Positioner> |
| 104 | + </Portal> |
| 105 | + </Menu.Root> |
| 106 | + ) |
| 107 | +} |
0 commit comments