content.tsx 2.2 KB

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