This commit is contained in:
natib21
2026-07-10 11:25:59 +00:00
parent 2696ca7498
commit e6e44e773b
1146 changed files with 200266 additions and 90527 deletions

View File

@@ -0,0 +1,148 @@
// @ts-ignore - Tiptap type declarations issue
import { useEditor, EditorContent } from "@tiptap/react";
// @ts-ignore - Tiptap type declarations issue
import StarterKit from "@tiptap/starter-kit";
// @ts-ignore - Tiptap type declarations issue
import Underline from "@tiptap/extension-underline";
// @ts-ignore - Tiptap type declarations issue
import Link from "@tiptap/extension-link";
// @ts-ignore - Tiptap type declarations issue
import TextAlign from "@tiptap/extension-text-align";
// @ts-ignore - Tiptap type declarations issue
import Image from "@tiptap/extension-image";
// @ts-ignore - Tiptap type declarations issue
import { Color } from "@tiptap/extension-color";
// @ts-ignore - Tiptap type declarations issue
import { TextStyle } from "@tiptap/extension-text-style";
// @ts-ignore - Tiptap type declarations issue
import Highlight from "@tiptap/extension-highlight";
import { useEffect } from "react";
import { cn } from "@/shared/lib/utils";
interface RichTextViewerProps {
content: string;
minHeight?: number;
className?: string;
variant?: "default" | "minimal" | "bordered";
}
const RichTextViewer = ({
content,
minHeight = 200,
className,
variant = "default",
}: RichTextViewerProps) => {
// @ts-ignore - Tiptap type declarations issue
const extensions = [
// @ts-ignore
StarterKit.configure({
heading: {
levels: [1, 2, 3],
},
}),
// @ts-ignore
Underline.configure(),
// @ts-ignore
TextStyle.configure(),
// @ts-ignore
Highlight.configure({ multicolor: true }),
// @ts-ignore
Color.configure(),
// @ts-ignore
Link.configure({
openOnClick: false,
HTMLAttributes: {
rel: "noopener noreferrer",
target: "_blank",
class: "text-blue-600 hover:text-blue-800 underline",
},
}),
// @ts-ignore
TextAlign.configure({
types: ["heading", "paragraph"],
alignments: ["left", "center", "right", "justify"],
}),
// @ts-ignore
Image.configure({
inline: true,
allowBase64: true,
HTMLAttributes: {
class: "rounded-md max-w-full h-auto",
},
}),
];
const editor = useEditor({
extensions,
content,
editable: false,
});
useEffect(() => {
if (editor && content !== editor.getHTML()) {
editor.commands.setContent(content);
}
}, [content, editor]);
if (!editor) {
return (
<div
className={cn(
"animate-pulse bg-gray-200 rounded-md",
"dark:bg-gray-700",
className
)}
style={{ minHeight: `${minHeight}px` }}
/>
);
}
const variantStyles = {
default:
"border border-gray-200 rounded-md bg-white shadow-sm dark:border-gray-700 dark:bg-gray-900",
minimal: "bg-transparent",
bordered: "border border-gray-200 rounded-md dark:border-gray-700",
};
return (
<div
className={cn(variantStyles[variant], className)}
style={{ minHeight: `${minHeight}px` }}>
<EditorContent
editor={editor}
className={cn(
"px-6 py-4 min-h-[200px]",
// Base typography styles
"[&_.tiptap]:outline-none",
"[&_.tiptap_h1]:text-2xl [&_.tiptap_h1]:font-bold [&_.tiptap_h1]:my-4",
"[&_.tiptap_h2]:text-xl [&_.tiptap_h2]:font-bold [&_.tiptap_h2]:my-3",
"[&_.tiptap_h3]:text-lg [&_.tiptap_h3]:font-bold [&_.tiptap_h3]:my-2",
"[&_.tiptap_p]:my-2 [&_.tiptap_p]:leading-relaxed",
"[&_.tiptap_ul]:my-2 [&_.tiptap_ul]:list-disc [&_.tiptap_ul]:pl-6",
"[&_.tiptap_ol]:my-2 [&_.tiptap_ol]:list-decimal [&_.tiptap_ol]:pl-6",
"[&_.tiptap_li]:my-1",
"[&_.tiptap_blockquote]:border-l-4 [&_.tiptap_blockquote]:border-gray-300",
"[&_.tiptap_blockquote]:pl-4 [&_.tiptap_blockquote]:italic [&_.tiptap_blockquote]:my-2",
"[&_.tiptap_code]:bg-gray-100 [&_.tiptap_code]:px-1 [&_.tiptap_code]:rounded",
"[&_.tiptap_code]:text-sm dark:[&_.tiptap_code]:bg-gray-800",
"[&_.tiptap_pre]:bg-gray-900 [&_.tiptap_pre]:text-white [&_.tiptap_pre]:p-4",
"[&_.tiptap_pre]:rounded-md [&_.tiptap_pre]:my-2 dark:[&_.tiptap_pre]:bg-gray-800",
"[&_.tiptap_strong]:font-bold",
"[&_.tiptap_em]:italic",
"[&_.tiptap_underline]:underline",
"[&_.tiptap_highlight]:bg-yellow-200 dark:[&_.tiptap_highlight]:bg-yellow-800",
"[&_.tiptap_table]:border-collapse [&_.tiptap_table]:border [&_.tiptap_table]:border-gray-300",
"[&_.tiptap_th]:bg-gray-100 [&_.tiptap_th]:p-2 dark:[&_.tiptap_th]:bg-gray-800",
"[&_.tiptap_td]:p-2 [&_.tiptap_td]:border [&_.tiptap_td]:border-gray-300",
"dark:[&_.tiptap_td]:border-gray-700",
"[&_.tiptap_img]:rounded-md [&_.tiptap_img]:max-w-full [&_.tiptap_img]:h-auto",
// Dark mode support
"dark:[&_.tiptap]:text-gray-100",
"dark:[&_.tiptap_blockquote]:border-gray-600"
)}
/>
</div>
);
};
export default RichTextViewer;