feat: enhance SkillEditDialog with ContentEditor and improve MarkdownEditor toolbar logic
This commit is contained in:
+1
-1
Submodule docs updated: 6e7ec786d0...f48e9d76da
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { type Resolver, useForm } from "react-hook-form";
|
import { Controller, type Resolver, useForm } from "react-hook-form";
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
|
import { ContentEditor } from "@/components/content-editor";
|
||||||
import { OptionCombobox } from "@/components/option-combobox";
|
import { OptionCombobox } from "@/components/option-combobox";
|
||||||
import { ProjectDialog } from "@/components/project-dialog";
|
import { ProjectDialog } from "@/components/project-dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -155,6 +156,7 @@ function SkillEditDialogBody({
|
|||||||
handleSubmit,
|
handleSubmit,
|
||||||
reset,
|
reset,
|
||||||
register,
|
register,
|
||||||
|
control,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = form;
|
} = form;
|
||||||
|
|
||||||
@@ -316,14 +318,21 @@ function SkillEditDialogBody({
|
|||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field data-invalid={!!errors.instruction}>
|
<Field data-invalid={!!errors.instruction}>
|
||||||
<FieldLabel htmlFor="skill-instruction">{t("skillDefinition.instruction")}</FieldLabel>
|
<FieldLabel>{t("skillDefinition.instruction")}</FieldLabel>
|
||||||
<FieldContent>
|
<FieldContent>
|
||||||
<Textarea
|
<Controller
|
||||||
id="skill-instruction"
|
control={control}
|
||||||
rows={12}
|
name="instruction"
|
||||||
placeholder={t("skillDefinition.instructionPlaceholder")}
|
render={({ field }) => (
|
||||||
aria-invalid={!!errors.instruction}
|
<ContentEditor
|
||||||
{...register("instruction")}
|
value={{ mode: "markdown", raw: field.value ?? "" }}
|
||||||
|
onChange={(next) => field.onChange(next.raw)}
|
||||||
|
placeholder={t("skillDefinition.instructionPlaceholder")}
|
||||||
|
disabled={saving || loading}
|
||||||
|
allowedModes={["markdown"]}
|
||||||
|
height={360}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<FieldError errors={[errors.instruction]} />
|
<FieldError errors={[errors.instruction]} />
|
||||||
</FieldContent>
|
</FieldContent>
|
||||||
|
|||||||
@@ -56,29 +56,67 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
|
|||||||
const editorId = useId()
|
const editorId = useId()
|
||||||
const editorRef = useRef<ExposeParam>(null)
|
const editorRef = useRef<ExposeParam>(null)
|
||||||
const { resolvedTheme } = useTheme()
|
const { resolvedTheme } = useTheme()
|
||||||
|
const showModeSwitch = allowedModes.length > 1
|
||||||
const defToolbars = useMemo(
|
const defToolbars = useMemo(
|
||||||
() => [
|
() => {
|
||||||
<EditorModeSwitch
|
const fullscreenToolbar = (
|
||||||
key="mode-switch"
|
<NormalToolbar
|
||||||
value={mode}
|
|
||||||
allowedModes={allowedModes}
|
|
||||||
disabled={disabled}
|
|
||||||
onChange={onModeChange}
|
|
||||||
/>,
|
|
||||||
<NormalToolbar
|
|
||||||
key="toggle-fullscreen"
|
key="toggle-fullscreen"
|
||||||
title={fullscreen ? t("editor.exitFullscreen") : t("editor.fullscreen")}
|
title={fullscreen ? t("editor.exitFullscreen") : t("editor.fullscreen")}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={onToggleFullscreen}
|
onClick={onToggleFullscreen}
|
||||||
>
|
>
|
||||||
{fullscreen ? (
|
{fullscreen ? (
|
||||||
<Minimize2Icon className="h-[16px] w-[16px]" />
|
<Minimize2Icon className="h-[16px] w-[16px]" />
|
||||||
) : (
|
) : (
|
||||||
<Maximize2Icon className="h-[16px] w-[16px]" />
|
<Maximize2Icon className="h-[16px] w-[16px]" />
|
||||||
)}
|
)}
|
||||||
</NormalToolbar>,
|
</NormalToolbar>
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!showModeSwitch) {
|
||||||
|
return [fullscreenToolbar]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
<EditorModeSwitch
|
||||||
|
key="mode-switch"
|
||||||
|
value={mode}
|
||||||
|
allowedModes={allowedModes}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={onModeChange}
|
||||||
|
/>,
|
||||||
|
fullscreenToolbar,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
[allowedModes, disabled, fullscreen, mode, onModeChange, onToggleFullscreen, showModeSwitch, t]
|
||||||
|
)
|
||||||
|
const toolbars = useMemo(
|
||||||
|
() => [
|
||||||
|
...(showModeSwitch ? [0, "-"] : []),
|
||||||
|
"bold",
|
||||||
|
"underline",
|
||||||
|
"italic",
|
||||||
|
"strikeThrough",
|
||||||
|
"-",
|
||||||
|
"title",
|
||||||
|
"quote",
|
||||||
|
"unorderedList",
|
||||||
|
"orderedList",
|
||||||
|
"-",
|
||||||
|
"codeRow",
|
||||||
|
"code",
|
||||||
|
"link",
|
||||||
|
"image",
|
||||||
|
"-",
|
||||||
|
"revoke",
|
||||||
|
"next",
|
||||||
|
showModeSwitch ? 1 : 0,
|
||||||
|
"=",
|
||||||
|
"preview",
|
||||||
|
"previewOnly",
|
||||||
],
|
],
|
||||||
[allowedModes, disabled, fullscreen, mode, onModeChange, onToggleFullscreen, t]
|
[showModeSwitch]
|
||||||
)
|
)
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@@ -99,31 +137,7 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
theme={resolvedTheme === "dark" ? "dark" : "light"}
|
theme={resolvedTheme === "dark" ? "dark" : "light"}
|
||||||
preview={false}
|
preview={false}
|
||||||
toolbars={[
|
toolbars={toolbars}
|
||||||
0,
|
|
||||||
"-",
|
|
||||||
"bold",
|
|
||||||
"underline",
|
|
||||||
"italic",
|
|
||||||
"strikeThrough",
|
|
||||||
"-",
|
|
||||||
"title",
|
|
||||||
"quote",
|
|
||||||
"unorderedList",
|
|
||||||
"orderedList",
|
|
||||||
"-",
|
|
||||||
"codeRow",
|
|
||||||
"code",
|
|
||||||
"link",
|
|
||||||
"image",
|
|
||||||
"-",
|
|
||||||
"revoke",
|
|
||||||
"next",
|
|
||||||
1,
|
|
||||||
"=",
|
|
||||||
"preview",
|
|
||||||
"previewOnly",
|
|
||||||
]}
|
|
||||||
defToolbars={defToolbars}
|
defToolbars={defToolbars}
|
||||||
footers={[]}
|
footers={[]}
|
||||||
noMermaid
|
noMermaid
|
||||||
|
|||||||
Reference in New Issue
Block a user