import { Tabs } from "@cloudflare/kumo/components/tabs"; import { useId, useRef, useState } from "react"; import { useMarkdownPreview } from "~/hooks/use-markdown-preview"; import { useAttachmentUpload } from "~/hooks/use-attachment-upload"; import { Markdown } from "~/ui/Markdown"; import { FieldError } from "~/ui/Field"; const TABS = [ { id: "write", label: "Write" }, { id: "preview", label: "Preview" }, ] as const; type Props = { value: string; onChange: (value: string) => void; owner?: string; repo?: string; placeholder?: string; rows?: number; label?: string; }; export function MarkdownEditor({ value, onChange, owner, repo, placeholder = "Leave a comment", rows = 6, label = "Comment", }: Props) { const id = useId(); const [tab, setTab] = useState<(typeof TABS)[number]["id"]>("write"); const preview = useMarkdownPreview(owner ?? null, repo ?? null); const attachments = useAttachmentUpload(owner, repo); const textarea = useRef(null); const fileInput = useRef(null); async function attach(files: FileList | File[]) { const snippets = await attachments.upload(files); if (snippets.length === 0) return; const at = textarea.current?.selectionStart ?? value.length; const insert = `${at > 0 && !value.slice(0, at).endsWith("\n") ? "\n" : ""}${snippets.join("\n")}\n`; onChange(value.slice(0, at) + insert + value.slice(at)); } function select(next: (typeof TABS)[number]["id"]) { setTab(next); if (next === "preview") preview.load(value); } return (
select(next === "preview" ? "preview" : "write")} tabs={TABS.map((item) => ({ value: item.id, label: item.label }))} /> Markdown supported
{tab === "write" ? ( <>