mirror of
https://github.com/johndoe6345789/snippet-pastebin.git
synced 2026-04-24 13:34:55 +00:00
Split SnippetViewer.tsx (158 LOC) into 2 focused components
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
@@ -2,18 +2,12 @@ import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Copy, Pencil, Check, SplitVertical } from '@phosphor-icons/react'
|
||||
import { Snippet } from '@/lib/types'
|
||||
import { MonacoEditor } from '@/components/features/snippet-editor/MonacoEditor'
|
||||
import { ReactPreview } from '@/components/features/snippet-editor/ReactPreview'
|
||||
import { PythonOutput } from '@/components/features/python-runner/PythonOutput'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useState } from 'react'
|
||||
import { strings, appConfig, LANGUAGE_COLORS } from '@/lib/config'
|
||||
import { appConfig } from '@/lib/config'
|
||||
import { SnippetViewerHeader } from './SnippetViewerHeader'
|
||||
import { SnippetViewerContent } from './SnippetViewerContent'
|
||||
|
||||
interface SnippetViewerProps {
|
||||
snippet: Snippet | null
|
||||
@@ -47,110 +41,24 @@ export function SnippetViewer({ snippet, open, onOpenChange, onEdit, onCopy }: S
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[95vw] sm:max-h-[95vh] h-[95vh] overflow-hidden flex flex-col p-0">
|
||||
<DialogHeader className="px-6 pt-6 pb-4 pr-14 border-b border-border">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex-1 min-w-0 space-y-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<DialogTitle className="text-2xl font-bold truncate">
|
||||
{snippet.title}
|
||||
</DialogTitle>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={cn(
|
||||
"shrink-0 border font-medium text-xs px-2 py-1",
|
||||
LANGUAGE_COLORS[snippet.language] || LANGUAGE_COLORS['Other']
|
||||
)}
|
||||
>
|
||||
{snippet.language}
|
||||
</Badge>
|
||||
</div>
|
||||
{snippet.description && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{snippet.description}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{strings.snippetViewer.lastUpdated}: {new Date(snippet.updatedAt).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2 shrink-0">
|
||||
{canPreview && (
|
||||
<Button
|
||||
variant={showPreview ? "default" : "outline"}
|
||||
size="sm"
|
||||
onClick={() => setShowPreview(!showPreview)}
|
||||
className="gap-2"
|
||||
>
|
||||
<SplitVertical className="h-4 w-4" />
|
||||
{showPreview ? strings.snippetViewer.buttons.hidePreview : strings.snippetViewer.buttons.showPreview}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleCopy}
|
||||
className="gap-2"
|
||||
>
|
||||
{isCopied ? (
|
||||
<>
|
||||
<Check className="h-4 w-4" weight="bold" />
|
||||
{strings.snippetViewer.buttons.copied}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Copy className="h-4 w-4" />
|
||||
{strings.snippetViewer.buttons.copy}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleEdit}
|
||||
className="gap-2"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
{strings.snippetViewer.buttons.edit}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<SnippetViewerHeader
|
||||
snippet={snippet}
|
||||
isCopied={isCopied}
|
||||
canPreview={canPreview}
|
||||
showPreview={showPreview}
|
||||
onCopy={handleCopy}
|
||||
onEdit={handleEdit}
|
||||
onTogglePreview={() => setShowPreview(!showPreview)}
|
||||
/>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 overflow-hidden flex">
|
||||
{canPreview && showPreview ? (
|
||||
<>
|
||||
<div className="flex-1 overflow-hidden border-r border-border">
|
||||
<MonacoEditor
|
||||
value={snippet.code}
|
||||
onChange={() => {}}
|
||||
language={snippet.language}
|
||||
height="100%"
|
||||
readOnly={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{isPython ? (
|
||||
<PythonOutput code={snippet.code} />
|
||||
) : (
|
||||
<ReactPreview
|
||||
code={snippet.code}
|
||||
language={snippet.language}
|
||||
functionName={snippet.functionName}
|
||||
inputParameters={snippet.inputParameters}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<MonacoEditor
|
||||
value={snippet.code}
|
||||
onChange={() => {}}
|
||||
language={snippet.language}
|
||||
height="100%"
|
||||
readOnly={true}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<SnippetViewerContent
|
||||
snippet={snippet}
|
||||
canPreview={canPreview}
|
||||
showPreview={showPreview}
|
||||
isPython={isPython}
|
||||
/>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Snippet } from '@/lib/types'
|
||||
import { MonacoEditor } from '@/components/features/snippet-editor/MonacoEditor'
|
||||
import { ReactPreview } from '@/components/features/snippet-editor/ReactPreview'
|
||||
import { PythonOutput } from '@/components/features/python-runner/PythonOutput'
|
||||
|
||||
interface SnippetViewerContentProps {
|
||||
snippet: Snippet
|
||||
canPreview: boolean
|
||||
showPreview: boolean
|
||||
isPython: boolean
|
||||
}
|
||||
|
||||
export function SnippetViewerContent({
|
||||
snippet,
|
||||
canPreview,
|
||||
showPreview,
|
||||
isPython,
|
||||
}: SnippetViewerContentProps) {
|
||||
if (canPreview && showPreview) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex-1 overflow-hidden border-r border-border">
|
||||
<MonacoEditor
|
||||
value={snippet.code}
|
||||
onChange={() => {}}
|
||||
language={snippet.language}
|
||||
height="100%"
|
||||
readOnly={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{isPython ? (
|
||||
<PythonOutput code={snippet.code} />
|
||||
) : (
|
||||
<ReactPreview
|
||||
code={snippet.code}
|
||||
language={snippet.language}
|
||||
functionName={snippet.functionName}
|
||||
inputParameters={snippet.inputParameters}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<MonacoEditor
|
||||
value={snippet.code}
|
||||
onChange={() => {}}
|
||||
language={snippet.language}
|
||||
height="100%"
|
||||
readOnly={true}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Copy, Pencil, Check, SplitVertical } from '@phosphor-icons/react'
|
||||
import { Snippet } from '@/lib/types'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { strings, LANGUAGE_COLORS } from '@/lib/config'
|
||||
|
||||
interface SnippetViewerHeaderProps {
|
||||
snippet: Snippet
|
||||
isCopied: boolean
|
||||
canPreview: boolean
|
||||
showPreview: boolean
|
||||
onCopy: () => void
|
||||
onEdit: () => void
|
||||
onTogglePreview: () => void
|
||||
}
|
||||
|
||||
export function SnippetViewerHeader({
|
||||
snippet,
|
||||
isCopied,
|
||||
canPreview,
|
||||
showPreview,
|
||||
onCopy,
|
||||
onEdit,
|
||||
onTogglePreview,
|
||||
}: SnippetViewerHeaderProps) {
|
||||
return (
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex-1 min-w-0 space-y-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<h2 className="text-2xl font-bold truncate">
|
||||
{snippet.title}
|
||||
</h2>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={cn(
|
||||
"shrink-0 border font-medium text-xs px-2 py-1",
|
||||
LANGUAGE_COLORS[snippet.language] || LANGUAGE_COLORS['Other']
|
||||
)}
|
||||
>
|
||||
{snippet.language}
|
||||
</Badge>
|
||||
</div>
|
||||
{snippet.description && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{snippet.description}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{strings.snippetViewer.lastUpdated}: {new Date(snippet.updatedAt).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2 shrink-0">
|
||||
{canPreview && (
|
||||
<Button
|
||||
variant={showPreview ? "default" : "outline"}
|
||||
size="sm"
|
||||
onClick={onTogglePreview}
|
||||
className="gap-2"
|
||||
>
|
||||
<SplitVertical className="h-4 w-4" />
|
||||
{showPreview ? strings.snippetViewer.buttons.hidePreview : strings.snippetViewer.buttons.showPreview}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={onCopy}
|
||||
className="gap-2"
|
||||
>
|
||||
{isCopied ? (
|
||||
<>
|
||||
<Check className="h-4 w-4" weight="bold" />
|
||||
{strings.snippetViewer.buttons.copied}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Copy className="h-4 w-4" />
|
||||
{strings.snippetViewer.buttons.copy}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={onEdit}
|
||||
className="gap-2"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
{strings.snippetViewer.buttons.edit}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user