diff --git a/src/components/ChangelogEditor.tsx b/src/components/ChangelogEditor.tsx new file mode 100644 index 0000000..64207d3 --- /dev/null +++ b/src/components/ChangelogEditor.tsx @@ -0,0 +1,157 @@ +"use client"; + +import { useState } from "react"; +import dynamic from "next/dynamic"; +import { theme } from "antd"; +import { commands, type ICommand } from "@uiw/react-md-editor"; +import "@uiw/react-md-editor/markdown-editor.css"; +import "@uiw/react-markdown-preview/markdown.css"; + +// @uiw/react-md-editor accesses browser APIs on import — skip SSR +const MDEditor = dynamic(() => import("@uiw/react-md-editor"), { + ssr: false, +}); + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +type EditorMode = "edit" | "preview"; + +interface ChangelogEditorProps { + value: string; + onChange: (value: string) => void; +} + +// --------------------------------------------------------------------------- +// GitHub-style Code / Preview tabs +// --------------------------------------------------------------------------- + +function ModeTab({ + label, + active, + onClick, +}: { + label: string; + active: boolean; + onClick: () => void; +}) { + const { token } = theme.useToken(); + return ( + + {label} + + ); +} + +function buildTabCommand( + key: string, + label: string, + active: boolean, + onSwitch: () => void, +): ICommand { + return { + name: key, + keyCommand: key, + icon: , + buttonProps: null, + execute: (state, api, dispatch) => { + dispatch?.({ preview: key === "preview" ? "preview" : "edit" }); + }, + }; +} + +// Formatting commands, like GitHub's toolbar — hidden in Preview mode +const FORMAT_COMMANDS: ICommand[] = [ + commands.bold, + commands.italic, + commands.strikethrough, + commands.divider, + commands.link, + commands.code, + commands.codeBlock, + commands.image, + commands.divider, + commands.unorderedListCommand, + commands.orderedListCommand, + commands.checkedListCommand, + commands.quote, + commands.table, +]; + +// --------------------------------------------------------------------------- +// Component +// --------------------------------------------------------------------------- + +export function ChangelogEditor({ value, onChange }: ChangelogEditorProps) { + const { token } = theme.useToken(); + const [mode, setMode] = useState("edit"); + + const toolbarCommands: ICommand[] = + mode === "edit" + ? [ + buildTabCommand("code", "Code", true, () => setMode("edit")), + buildTabCommand("preview", "Preview", false, () => setMode("preview")), + commands.divider, + ...FORMAT_COMMANDS, + ] + : [ + buildTabCommand("code", "Code", false, () => setMode("edit")), + buildTabCommand("preview", "Preview", true, () => setMode("preview")), + ]; + + return ( +
+ onChange(val ?? "")} + preview={mode} + height={520} + minHeight={400} + maxHeight={900} + visibleDragbar={false} + textareaProps={{ + placeholder: "输入 Markdown 格式的更新日志…", + }} + commands={toolbarCommands} + extraCommands={[]} + style={{ + borderRadius: token.borderRadius, + fontFamily: token.fontFamily, + }} + /> +
+ ); +} diff --git a/src/components/PublishModal.tsx b/src/components/PublishModal.tsx index e1e6874..0b77465 100644 --- a/src/components/PublishModal.tsx +++ b/src/components/PublishModal.tsx @@ -25,6 +25,7 @@ import { Template } from "@/lib/utils/template"; import type { McVersionEntry } from "@/lib/utils/mcVersion"; import { computeVersionRanges } from "@/lib/utils/mcVersion"; import { getModrinthMcVersions, getCurseForgeMcVersions } from "@/services/meta"; +import { ChangelogEditor } from "./ChangelogEditor"; const { Text } = Typography; @@ -384,21 +385,7 @@ export function PublishModal({ Changelog (Markdown) - {/* TODO: Replace with @uiw/react-md-editor */} -