content.tsx72 lines · main
1import { Copy } from 'lucide-react'
2import { useMemo, useState } from 'react'
3import { Button, copyToClipboard } from 'ui'
4
5import {
6 EXTRA_PACKAGES,
7 INSTALL_COMMANDS,
8} from '@/components/interfaces/ConnectSheet/connect.schema'
9import type { StepContentProps } from '@/components/interfaces/ConnectSheet/Connect.types'
10import { 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 */
17function 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
37function 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
72export default InstallContent