feat: resolve the codeblock overflow issue
This commit is contained in:
parent
75e667c1d7
commit
c35dacf64c
|
|
@ -6,13 +6,11 @@ import { Button } from '@/components/ui/button';
|
|||
|
||||
interface CodeBlockProps {
|
||||
code: string;
|
||||
type: 'bash' | 'sql' | 'text';
|
||||
type: 'bash' | 'sql' | 'text' | 'branch';
|
||||
showLineNumbers?: boolean;
|
||||
}
|
||||
|
||||
export function CodeBlock({ code, type, showLineNumbers = true }: CodeBlockProps) {
|
||||
console.log('[CodeBlock] Render - code length:', code?.length, 'code preview:', code?.substring(0, 50), 'type:', type);
|
||||
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
// Compute highlighted code synchronously
|
||||
|
|
@ -30,17 +28,14 @@ export function CodeBlock({ code, type, showLineNumbers = true }: CodeBlockProps
|
|||
require('prismjs/components/prism-bash');
|
||||
}
|
||||
|
||||
const language = type === 'text' ? 'text' : type;
|
||||
const language = type === 'text' || type === 'branch' ? 'text' : type;
|
||||
const grammar = Prism.languages[language] || Prism.languages.text;
|
||||
return Prism.highlight(code, grammar, language);
|
||||
} catch (e) {
|
||||
console.error('[CodeBlock] Prism error:', e);
|
||||
return code.replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
}, [code, type]);
|
||||
|
||||
console.log('[CodeBlock] highlighted length:', highlighted?.length);
|
||||
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(code);
|
||||
setCopied(true);
|
||||
|
|
@ -52,48 +47,37 @@ export function CodeBlock({ code, type, showLineNumbers = true }: CodeBlockProps
|
|||
const highlightedLines = highlighted ? highlighted.split('\n') : [];
|
||||
|
||||
return (
|
||||
<div className="relative group">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity z-10"
|
||||
onClick={handleCopy}
|
||||
>
|
||||
{copied ? (
|
||||
<Check className="w-4 h-4 text-green-500" />
|
||||
) : (
|
||||
<Copy className="w-4 h-4" />
|
||||
)}
|
||||
</Button>
|
||||
<div className="rounded-lg bg-slate-900 p-4 overflow-x-auto text-sm">
|
||||
<pre className={`language-${type} m-0`}>
|
||||
{showLineNumbers ? (
|
||||
<div className="flex">
|
||||
{/* Line numbers column */}
|
||||
<div className="flex flex-col text-slate-500 text-right pr-4 select-none min-w-[3rem]">
|
||||
{lines.map((_: string, i: number) => (
|
||||
<span key={i}>{i + 1}</span>
|
||||
))}
|
||||
</div>
|
||||
{/* Code column */}
|
||||
<div className="flex flex-col">
|
||||
{highlightedLines.map((line: string, i: number) => (
|
||||
<span
|
||||
key={i}
|
||||
className="text-slate-100 whitespace-pre"
|
||||
dangerouslySetInnerHTML={{ __html: line || ' ' }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
className="rounded-lg bg-slate-900 p-4 text-sm overflow-x-auto"
|
||||
style={{ maxWidth: '100%' }}
|
||||
>
|
||||
<pre className={`language-${type} m-0`} style={{ minWidth: '100%' }}>
|
||||
{showLineNumbers ? (
|
||||
<div className="flex" style={{ minWidth: 0 }}>
|
||||
{/* Line numbers column - fixed width */}
|
||||
<div className="flex flex-col text-slate-500 text-right pr-4 select-none w-12 shrink-0">
|
||||
{lines.map((_: string, i: number) => (
|
||||
<span key={i}>{i + 1}</span>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<code
|
||||
className="text-slate-100 whitespace-pre"
|
||||
dangerouslySetInnerHTML={{ __html: highlighted || code || '' }}
|
||||
/>
|
||||
)}
|
||||
</pre>
|
||||
</div>
|
||||
{/* Code column */}
|
||||
<div className="flex flex-col" style={{ minWidth: 0 }}>
|
||||
{highlightedLines.map((line: string, i: number) => (
|
||||
<span
|
||||
key={i}
|
||||
className="text-slate-100 whitespace-pre"
|
||||
dangerouslySetInnerHTML={{ __html: line || ' ' }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<code
|
||||
className="text-slate-100 whitespace-pre"
|
||||
dangerouslySetInnerHTML={{ __html: highlighted || code || '' }}
|
||||
/>
|
||||
)}
|
||||
</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,13 +73,7 @@ export function StepDetailPanel({
|
|||
|
||||
// Sync state when step changes
|
||||
useEffect(() => {
|
||||
console.log('[StepDetailPanel] useEffect triggered, step?.id:', step?.id);
|
||||
if (step) {
|
||||
console.log('[StepDetailPanel] Syncing state with step:', {
|
||||
stepId: step.id,
|
||||
stepName: step.name,
|
||||
stepContent: step.content?.substring(0, 50),
|
||||
});
|
||||
setNotes(step.notes || '');
|
||||
setEditContent(step.content || '');
|
||||
setIsEditing(false);
|
||||
|
|
@ -89,8 +83,6 @@ export function StepDetailPanel({
|
|||
}
|
||||
}, [step?.id]);
|
||||
|
||||
console.log('[StepDetailPanel] Render - step:', step?.id, 'step.content:', step?.content?.substring(0, 50), 'editContent:', editContent?.substring(0, 50));
|
||||
|
||||
if (!step) return null;
|
||||
|
||||
const isCustom = step.isCustom;
|
||||
|
|
@ -189,7 +181,7 @@ export function StepDetailPanel({
|
|||
|
||||
return (
|
||||
<Sheet open={isOpen} onOpenChange={onClose}>
|
||||
<SheetContent key={step?.id} className="w-[600px] sm:max-w-[600px]">
|
||||
<SheetContent key={step?.id} className="w-[600px] sm:max-w-[600px] overflow-hidden">
|
||||
<SheetHeader className="px-6">
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
|
|
@ -205,8 +197,9 @@ export function StepDetailPanel({
|
|||
</div>
|
||||
</SheetHeader>
|
||||
|
||||
<ScrollArea className="h-[calc(100vh-180px)] mt-6 px-6">
|
||||
<div className="space-y-6">
|
||||
<div style={{ width: '552px', maxWidth: '552px' }}>
|
||||
<ScrollArea className="h-[calc(100vh-180px)] mt-6 px-6 w-full">
|
||||
<div className="space-y-6" style={{ width: '504px', maxWidth: '504px' }}>
|
||||
{/* Status & Type */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
@ -226,7 +219,7 @@ export function StepDetailPanel({
|
|||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div>
|
||||
<div className="min-w-0" style={{ maxWidth: '100%' }}>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<label className="text-sm font-medium text-slate-500">Content</label>
|
||||
{!isEditing && (
|
||||
|
|
@ -263,7 +256,9 @@ export function StepDetailPanel({
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<CodeBlock code={step.content} type={step.type} />
|
||||
<div className="overflow-hidden" style={{ maxWidth: '100%', width: '100%' }}>
|
||||
<CodeBlock code={step.content} type={step.type} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Show original content if overridden */}
|
||||
|
|
@ -375,7 +370,8 @@ export function StepDetailPanel({
|
|||
</>
|
||||
)}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ function ScrollArea({
|
|||
<ScrollAreaPrimitive.Viewport
|
||||
data-slot="scroll-area-viewport"
|
||||
className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
||||
style={{ maxWidth: '100%' }}
|
||||
>
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
|
|
|
|||
Loading…
Reference in New Issue