Files
zeekay 7af02e40e8 migrate: Hugo/PaperMod to fumadocs + Next.js
- Replace Hugo static site generator with Next.js 15 + fumadocs-mdx
- Convert 71 blog posts from Hugo format to MDX/MD
- Convert Hugo shortcodes (figure, button, video, example, fullwidth)
  to MDX components (Figure, LinkButton, Video, Fullwidth)
- Add remark-math + rehype-katex for LaTeX math rendering
- Copy JSON case files to public/cases/ for reference
- Update branding for Zen LM (site-nav, footer, metadata)
- Static export for Cloudflare Pages deployment
- Chinese (.zh.md) translations deferred for future migration
2026-03-26 23:21:21 -07:00

60 lines
1.3 KiB
TypeScript

"use client";
import { cn } from "@/lib/utils";
interface MediaViewerProps {
src: string;
alt?: string;
type?: "image" | "video";
className?: string;
width?: number;
height?: number;
}
export function MediaViewer({
src,
alt = "",
type = "image",
className,
width,
height,
}: MediaViewerProps) {
const mediaProps = {
src,
alt,
className: cn(
"w-full h-full object-cover rounded-lg border overflow-hidden aspect-video",
className
),
...(width && height ? { width, height } : {}),
};
const renderMedia = () => {
if (type === "video") {
return (
<video {...mediaProps} controls loop>
Your browser does not support the video tag.
</video>
);
}
// eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text
return <img {...mediaProps} />;
};
return (
<div className="my-6 w-full">
<div className="relative w-full aspect-video">{renderMedia()}</div>
</div>
);
}
// Helper components for easier MDX usage
export function ImageViewer(props: Omit<MediaViewerProps, "type">) {
return <MediaViewer {...props} type="image" />;
}
export function VideoViewer(props: Omit<MediaViewerProps, "type">) {
return <MediaViewer {...props} type="video" />;
}