SqlMonacoBlock.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import Editor from '@monaco-editor/react'
  2. import { Check, Copy } from 'lucide-react'
  3. import { useMemo, useState } from 'react'
  4. import { Button, cn, copyToClipboard } from 'ui'
  5. type SqlMonacoBlockProps = {
  6. value?: string
  7. className?: string
  8. wrapperClassName?: string
  9. hideCopy?: boolean
  10. // Fixed height in px. Defaults to 310 to match previous CodeBlock max height
  11. height?: number
  12. // Show line numbers. Defaults to false to match previous CodeBlock
  13. lineNumbers?: 'on' | 'off'
  14. }
  15. export const SqlMonacoBlock = ({
  16. value,
  17. className,
  18. wrapperClassName,
  19. height = 310,
  20. lineNumbers = 'off',
  21. hideCopy = false,
  22. }: SqlMonacoBlockProps) => {
  23. const [copied, setCopied] = useState(false)
  24. const content = useMemo(() => value ?? '', [value])
  25. const handleCopy = (value: string) => {
  26. setCopied(true)
  27. copyToClipboard(value)
  28. setTimeout(() => setCopied(false), 1000)
  29. }
  30. return (
  31. <div
  32. className={cn('group relative border rounded-md overflow-hidden w-full', wrapperClassName)}
  33. >
  34. <Editor
  35. theme="briven"
  36. language="pgsql"
  37. value={content}
  38. height={height}
  39. className={className}
  40. wrapperProps={{
  41. className:
  42. '[&_.monaco-editor]:bg-transparent! [&_.monaco-editor-background]:bg-transparent! [&_.monaco-editor]:outline-transparent! [&_.cursor]:hidden!',
  43. }}
  44. options={{
  45. readOnly: true,
  46. domReadOnly: true,
  47. fontSize: 13,
  48. minimap: { enabled: false },
  49. lineNumbers,
  50. renderLineHighlight: 'none',
  51. scrollbar: { vertical: 'auto', horizontal: 'auto' },
  52. overviewRulerLanes: 0,
  53. overviewRulerBorder: false,
  54. glyphMargin: false,
  55. folding: false,
  56. lineDecorationsWidth: 0,
  57. lineNumbersMinChars: lineNumbers === 'off' ? 0 : 3,
  58. wordWrap: 'on',
  59. scrollBeyondLastLine: false,
  60. selectionHighlight: false,
  61. occurrencesHighlight: 'off',
  62. fixedOverflowWidgets: true,
  63. padding: { top: 12, bottom: 12 },
  64. tabIndex: -1,
  65. }}
  66. />
  67. {!hideCopy && (
  68. <div className="absolute right-2 top-2 opacity-0 group-hover:opacity-100 transition-opacity">
  69. <Button
  70. type="default"
  71. className="px-1.5"
  72. icon={copied ? <Check /> : <Copy />}
  73. onClick={() => handleCopy(content)}
  74. >
  75. {copied ? 'Copied' : ''}
  76. </Button>
  77. </div>
  78. )}
  79. </div>
  80. )
  81. }