Files
v0-v0app/components/markdown-editor.tsx
v0 efdedf1a34 feat: add complete Docker setup for markdown editor
Create Docker configuration files and setup commands

#VERCEL_SKIP

Co-authored-by: Anders Lehmann Pier <3219386+AndersPier@users.noreply.github.com>
2025-06-19 21:46:26 +00:00

99 lines
3.9 KiB
TypeScript

"use client"
import { useState, useCallback } from "react"
import { MarkdownToolbar } from "./markdown-toolbar"
import { MarkdownInput } from "./markdown-input"
import { MarkdownPreview } from "./markdown-preview"
import { FileText, Eye, Edit3, Sparkles } from "lucide-react"
interface MarkdownEditorProps {
initialContent?: string
}
export function MarkdownEditor({ initialContent = "" }: MarkdownEditorProps) {
const [content, setContent] = useState(initialContent)
const [textareaRef, setTextareaRef] = useState<HTMLTextAreaElement | null>(null)
const insertText = useCallback(
(before: string, after = "", placeholder = "") => {
if (!textareaRef) return
const start = textareaRef.selectionStart
const end = textareaRef.selectionEnd
const selectedText = content.substring(start, end)
const textToInsert = selectedText || placeholder
const newText = content.substring(0, start) + before + textToInsert + after + content.substring(end)
setContent(newText)
// Set cursor position after insertion
setTimeout(() => {
const newCursorPos = start + before.length + textToInsert.length
textareaRef.setSelectionRange(newCursorPos, newCursorPos)
textareaRef.focus()
}, 0)
},
[content, textareaRef],
)
return (
<div className="flex flex-col h-screen">
{/* Header */}
<header className="border-b bg-white/80 backdrop-blur-xl supports-[backdrop-filter]:bg-white/60 shadow-sm">
<div className="flex h-16 items-center px-6">
<div className="flex items-center gap-3">
<div className="relative">
<FileText className="h-7 w-7 text-blue-600" />
<Sparkles className="h-3 w-3 text-yellow-500 absolute -top-1 -right-1" />
</div>
<div>
<h1 className="text-xl font-bold bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 bg-clip-text text-transparent">
Markdown Editor
</h1>
<p className="text-xs text-muted-foreground">Write Preview Create</p>
</div>
</div>
</div>
</header>
{/* Toolbar */}
<div className="border-b bg-gradient-to-r from-blue-50/50 via-purple-50/50 to-pink-50/50 shadow-sm">
<MarkdownToolbar onInsertText={insertText} />
</div>
{/* Editor */}
<div className="flex flex-1 overflow-hidden">
{/* Input Panel */}
<div className="flex-1 flex flex-col border-r border-gray-200">
<div className="flex items-center gap-3 px-4 py-3 bg-gradient-to-r from-green-50 to-emerald-50 border-b">
<div className="p-1 rounded-full bg-green-100">
<Edit3 className="h-4 w-4 text-green-600" />
</div>
<span className="text-sm font-semibold text-green-700">Editor</span>
<div className="ml-auto flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-green-400 animate-pulse"></div>
<span className="text-xs text-green-600">Live</span>
</div>
</div>
<MarkdownInput content={content} onChange={setContent} onTextareaRef={setTextareaRef} />
</div>
{/* Preview Panel */}
<div className="flex-1 flex flex-col">
<div className="flex items-center gap-3 px-4 py-3 bg-gradient-to-r from-blue-50 to-indigo-50 border-b">
<div className="p-1 rounded-full bg-blue-100">
<Eye className="h-4 w-4 text-blue-600" />
</div>
<span className="text-sm font-semibold text-blue-700">Preview</span>
<div className="ml-auto flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-blue-400 animate-pulse"></div>
<span className="text-xs text-blue-600">Real-time</span>
</div>
</div>
<MarkdownPreview content={content} />
</div>
</div>
</div>
)
}