Improved code block
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import MorphText from "@/components/Morph";
|
||||
import { Card } from "fumadocs-ui/components/card";
|
||||
import { BookOpenIcon, NewspaperIcon, RocketIcon } from "lucide-react";
|
||||
import MorphCode from "@/components/Morph";
|
||||
import { NewspaperIcon, RocketIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
@@ -152,11 +151,9 @@ export default function HomePage() {
|
||||
return (
|
||||
<div className="flex w-full flex-col md:flex-row">
|
||||
<div className="order-1 md:order-2 w-full md:w-[40vw] md:h-svh sticky top-20 md:top-0 flex items-center justify-center z-10 bg-background pb-4 md:pb-0">
|
||||
<Card className="w-full max-w-md h-auto md:h-100" title>
|
||||
<code className="whitespace-pre-wrap">
|
||||
<MorphText text={currentText} />
|
||||
</code>
|
||||
</Card>
|
||||
<div className="w-max h-auto border border-fd-border p-5 rounded-xl min-h-24">
|
||||
<MorphCode code={currentText} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 order-2 md:order-1">
|
||||
|
||||
+47
-37
@@ -1,60 +1,70 @@
|
||||
"use client";
|
||||
|
||||
import { BundledLanguage, codeToTokens } from "shiki";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface MorphTextProps {
|
||||
text: string;
|
||||
interface Props {
|
||||
code: string;
|
||||
lang?: BundledLanguage;
|
||||
}
|
||||
|
||||
const tokenize = (str: string) => {
|
||||
const counts: Record<string, number> = {};
|
||||
return str.split("").map((char) => {
|
||||
const displayChar = char === " " ? "\u00A0" : char;
|
||||
counts[char] = (counts[char] || 0) + 1;
|
||||
return { char: displayChar, id: `${char}-${counts[char]}` };
|
||||
export default function MorphCode({ code, lang = "rust" }: Props) {
|
||||
const [lines, setLines] = useState<any[][]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
async function run() {
|
||||
const result = await codeToTokens(code, {
|
||||
lang,
|
||||
theme: "github-dark",
|
||||
});
|
||||
};
|
||||
|
||||
export default function MorphText({ text }: MorphTextProps) {
|
||||
const lines = text.split("\n"); // 👈 split by newline
|
||||
const rawLines = code.split("\n");
|
||||
|
||||
const fixed = rawLines.map((_, i) => {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<AnimatePresence mode="popLayout">
|
||||
{lines.map((line, lineIndex) => {
|
||||
const tokens = tokenize(line);
|
||||
|
||||
// 👇 empty line = real vertical space
|
||||
if (line === "") {
|
||||
return (
|
||||
<div
|
||||
key={lineIndex}
|
||||
className="h-4" // adjust spacing as needed
|
||||
/>
|
||||
result.tokens[i] ?? [
|
||||
{
|
||||
content: "\n",
|
||||
color: undefined,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
setLines(fixed);
|
||||
}
|
||||
|
||||
run();
|
||||
}, [code, lang]);
|
||||
|
||||
return (
|
||||
<div key={lineIndex} className="flex flex-wrap">
|
||||
{tokens.map(({ char, id }) => (
|
||||
<pre className="text-sm">
|
||||
<code>
|
||||
<AnimatePresence mode="popLayout">
|
||||
{lines.map((line, lineIndex) => (
|
||||
<div key={lineIndex} className="flex min-h-[1em]">
|
||||
{line.map((token, tokenIndex) => (
|
||||
<motion.span
|
||||
key={`${lineIndex}-${id}`}
|
||||
layoutId={`${lineIndex}-${id}`}
|
||||
key={`${lineIndex}-${tokenIndex}`}
|
||||
layoutId={`${lineIndex}-${tokenIndex}`}
|
||||
layout
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
initial={{ opacity: 0, y: 6 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
transition={{
|
||||
type: "keyframes",
|
||||
duration: 0.6,
|
||||
exit={{ opacity: 0, y: -6 }}
|
||||
transition={{ duration: 0.35 }}
|
||||
style={{
|
||||
color: token.color,
|
||||
whiteSpace: "pre",
|
||||
}}
|
||||
className="inline-block"
|
||||
>
|
||||
{char}
|
||||
{token.content}
|
||||
</motion.span>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</code>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user