viz primitives for data structures
This commit is contained in:
94
frontend/src/components/visualization/code-pane.tsx
Normal file
94
frontend/src/components/visualization/code-pane.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||
import { useVisualization } from "./visualization-context";
|
||||
|
||||
interface CodePaneProps {
|
||||
code: string;
|
||||
language?: string;
|
||||
}
|
||||
|
||||
export function CodePane({ code, language = "python" }: CodePaneProps) {
|
||||
const { currentStep } = useVisualization();
|
||||
|
||||
const highlightedLines = useMemo(() => {
|
||||
if (!currentStep?.codeHighlight) return new Set<number>();
|
||||
const { startLine, endLine } = currentStep.codeHighlight;
|
||||
const lines = new Set<number>();
|
||||
for (let i = startLine; i <= endLine; i++) {
|
||||
lines.add(i);
|
||||
}
|
||||
return lines;
|
||||
}, [currentStep]);
|
||||
|
||||
const languageMap: Record<string, string> = {
|
||||
python: "python",
|
||||
javascript: "javascript",
|
||||
typescript: "typescript",
|
||||
java: "java",
|
||||
cpp: "cpp",
|
||||
c: "c",
|
||||
go: "go",
|
||||
rust: "rust",
|
||||
};
|
||||
|
||||
const prismLanguage = languageMap[language.toLowerCase()] || language;
|
||||
|
||||
const customStyle = useMemo(
|
||||
() => ({
|
||||
margin: 0,
|
||||
padding: "0.75rem 0",
|
||||
fontSize: "0.8125rem",
|
||||
borderRadius: "0.5rem",
|
||||
background: "var(--code-bg, #282c34)",
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="rounded-lg overflow-hidden border border-border">
|
||||
<div className="bg-muted/50 px-3 py-1.5 border-b border-border">
|
||||
<span className="text-xs font-medium text-muted-foreground capitalize">
|
||||
{language}
|
||||
</span>
|
||||
</div>
|
||||
<SyntaxHighlighter
|
||||
language={prismLanguage}
|
||||
style={oneDark}
|
||||
customStyle={customStyle}
|
||||
showLineNumbers
|
||||
wrapLines
|
||||
lineNumberStyle={(lineNumber) => ({
|
||||
minWidth: "2.5em",
|
||||
paddingRight: "1em",
|
||||
textAlign: "right",
|
||||
userSelect: "none",
|
||||
color: highlightedLines.has(lineNumber)
|
||||
? "var(--primary)"
|
||||
: "var(--muted-foreground)",
|
||||
fontWeight: highlightedLines.has(lineNumber) ? 600 : 400,
|
||||
})}
|
||||
lineProps={(lineNumber) => {
|
||||
const isHighlighted = highlightedLines.has(lineNumber);
|
||||
return {
|
||||
style: {
|
||||
display: "block",
|
||||
padding: "0 0.75rem",
|
||||
backgroundColor: isHighlighted
|
||||
? "rgba(var(--primary-rgb, 59, 130, 246), 0.15)"
|
||||
: "transparent",
|
||||
borderLeft: isHighlighted
|
||||
? "3px solid var(--primary)"
|
||||
: "3px solid transparent",
|
||||
transition: "background-color 0.2s ease, border-color 0.2s ease",
|
||||
},
|
||||
};
|
||||
}}
|
||||
>
|
||||
{code.trim()}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user