mirror of
https://github.com/AndersPier/v0-v0app.git
synced 2025-10-27 18:16:53 +00:00
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>
This commit is contained in:
98
components/markdown-editor.tsx
Normal file
98
components/markdown-editor.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user