Started working on the blogs
This commit is contained in:
40
frontend/components/editable-text.tsx
Normal file
40
frontend/components/editable-text.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useState, ReactNode, cloneElement } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
interface EditableTextProps {
|
||||
children: ReactNode;
|
||||
onChange: (newText: string) => void;
|
||||
}
|
||||
|
||||
export default function EditableText({
|
||||
children,
|
||||
onChange,
|
||||
}: EditableTextProps) {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const child = Array.isArray(children) ? children[0] : children;
|
||||
|
||||
const text = child?.props.children || "";
|
||||
|
||||
const handleBlur = () => {
|
||||
setIsEditing(false);
|
||||
};
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div onClick={() => setIsEditing(true)}>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
autoFocus
|
||||
value={text}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
) : (
|
||||
cloneElement(child, {}, text)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { EditorContent, useEditor } from "@tiptap/react";
|
||||
import { Editor, EditorContent, useEditor } from "@tiptap/react";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import Underline from "@tiptap/extension-underline";
|
||||
import Link from "@tiptap/extension-link";
|
||||
@@ -16,11 +16,28 @@ import { EditorMenu } from "./editor-menu";
|
||||
|
||||
interface EditorProps {
|
||||
content: string;
|
||||
onChange?: (markdown: string) => void;
|
||||
onChange?: (content: string) => void;
|
||||
className?: string;
|
||||
setTitle?: React.Dispatch<React.SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export function Editor({ content, onChange, className }: EditorProps) {
|
||||
export function LocalEditor({
|
||||
content,
|
||||
onChange,
|
||||
className,
|
||||
setTitle,
|
||||
}: EditorProps) {
|
||||
const getTitle = (editor: Editor) => {
|
||||
const h1s: string[] = [];
|
||||
editor.state.doc.descendants((node, pos) => {
|
||||
if (node.type.name === "heading" && node.attrs.level === 1) {
|
||||
h1s.push(node.textContent);
|
||||
}
|
||||
});
|
||||
|
||||
return h1s.length > 0 ? h1s[0] : null;
|
||||
};
|
||||
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
@@ -46,9 +63,16 @@ export function Editor({ content, onChange, className }: EditorProps) {
|
||||
class: "prose prose-sm sm:prose-base lg:prose-lg xl:prose-2xl m-5 focus:outline-none dark:prose-invert",
|
||||
},
|
||||
},
|
||||
|
||||
onCreate: ({ editor }) => {
|
||||
const title = getTitle(editor);
|
||||
setTitle?.(title ?? "");
|
||||
},
|
||||
onUpdate: ({ editor }) => {
|
||||
console.log("Update");
|
||||
localStorage.setItem("blog_draft", editor.getHTML());
|
||||
// Set the first H1 if it exists
|
||||
const title = getTitle(editor);
|
||||
setTitle?.(title ?? "");
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user