content.tsx72 lines · main
| 1 | import { Copy } from 'lucide-react' |
| 2 | import { useMemo, useState } from 'react' |
| 3 | import { Button, copyToClipboard } from 'ui' |
| 4 | |
| 5 | import { |
| 6 | EXTRA_PACKAGES, |
| 7 | INSTALL_COMMANDS, |
| 8 | } from '@/components/interfaces/ConnectSheet/connect.schema' |
| 9 | import type { StepContentProps } from '@/components/interfaces/ConnectSheet/Connect.types' |
| 10 | import { resolveFrameworkLibraryKey } from '@/components/interfaces/ConnectSheet/Connect.utils' |
| 11 | |
| 12 | /** |
| 13 | * Gets the install command for the current framework selection. |
| 14 | * Appends any framework-specific extra packages from EXTRA_PACKAGES, |
| 15 | * checking the most specific key first (framework/variant), then framework-only. |
| 16 | */ |
| 17 | function getInstallCommand(state: StepContentProps['state']): string | null { |
| 18 | const libraryKey = resolveFrameworkLibraryKey(state) |
| 19 | if (!libraryKey || !INSTALL_COMMANDS[libraryKey]) return null |
| 20 | |
| 21 | let command = INSTALL_COMMANDS[libraryKey] |
| 22 | |
| 23 | const { framework, frameworkVariant } = state |
| 24 | if (framework) { |
| 25 | const extraMap = EXTRA_PACKAGES[libraryKey] |
| 26 | const extras = |
| 27 | (frameworkVariant && extraMap?.[`${framework}/${frameworkVariant}`]) || |
| 28 | extraMap?.[String(framework)] |
| 29 | if (extras?.length) { |
| 30 | command += ' ' + extras.join(' ') |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | return command |
| 35 | } |
| 36 | |
| 37 | function InstallContent({ state }: StepContentProps) { |
| 38 | const installCommand = useMemo(() => getInstallCommand(state), [state]) |
| 39 | const [copyLabel, setCopyLabel] = useState('Copy') |
| 40 | |
| 41 | if (!installCommand) { |
| 42 | return null |
| 43 | } |
| 44 | |
| 45 | const handleCopy = () => { |
| 46 | copyToClipboard(installCommand, () => { |
| 47 | setCopyLabel('Copied') |
| 48 | setTimeout(() => setCopyLabel('Copy'), 2000) |
| 49 | }) |
| 50 | } |
| 51 | |
| 52 | return ( |
| 53 | <div className="relative group"> |
| 54 | <div className="bg-surface-75 border rounded-lg p-3 pr-20 font-mono text-sm text-foreground-light overflow-x-auto"> |
| 55 | <code>{installCommand}</code> |
| 56 | </div> |
| 57 | <div className="absolute right-2 top-1/2 -translate-y-1/2"> |
| 58 | <Button |
| 59 | type="default" |
| 60 | size="tiny" |
| 61 | icon={<Copy size={14} />} |
| 62 | onClick={handleCopy} |
| 63 | className="opacity-0 group-hover:opacity-100 transition-opacity" |
| 64 | > |
| 65 | {copyLabel} |
| 66 | </Button> |
| 67 | </div> |
| 68 | </div> |
| 69 | ) |
| 70 | } |
| 71 | |
| 72 | export default InstallContent |