v3: code quality and visual consistency pass (refactored all forms across the app), fixed filename-related upload bug
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 47s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 47s
This commit is contained in:
81
src/components/form/RichTextField.tsx
Normal file
81
src/components/form/RichTextField.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { useId } from "react";
|
||||
import {
|
||||
Controller,
|
||||
type FieldValues,
|
||||
type Path,
|
||||
type RegisterOptions,
|
||||
useFormContext,
|
||||
} from "react-hook-form";
|
||||
|
||||
import { TextEditor, type TextEditorHandle } from "../TextEditor.tsx";
|
||||
|
||||
interface RichTextFieldProps<T extends FieldValues> {
|
||||
name: Path<T>;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
rows?: number;
|
||||
maxLength?: number;
|
||||
autoResize?: boolean;
|
||||
disabled?: boolean;
|
||||
rules?: RegisterOptions<T, Path<T>>;
|
||||
/** Forwarded to the underlying TextEditor so callers can focus it. */
|
||||
editorRef?: React.Ref<TextEditorHandle>;
|
||||
/** Ctrl/Cmd+Enter handler (e.g. submit the comment). */
|
||||
onSubmit?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rich-text field: a `Controller`-wrapped {@link TextEditor} (mentions, emoji,
|
||||
* image upload, char count) bound to react-hook-form via the surrounding
|
||||
* `FormProvider`.
|
||||
*/
|
||||
export function RichTextField<T extends FieldValues>({
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
rows,
|
||||
maxLength,
|
||||
autoResize,
|
||||
disabled,
|
||||
rules,
|
||||
editorRef,
|
||||
onSubmit,
|
||||
}: RichTextFieldProps<T>) {
|
||||
const id = useId();
|
||||
const { control, formState: { errors } } = useFormContext<T>();
|
||||
const error = errors[name];
|
||||
|
||||
return (
|
||||
<div className="form-field">
|
||||
{label && (
|
||||
<label className="form-label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<Controller
|
||||
name={name}
|
||||
control={control}
|
||||
rules={rules}
|
||||
render={({ field }) => (
|
||||
<TextEditor
|
||||
ref={editorRef}
|
||||
id={id}
|
||||
value={field.value ?? ""}
|
||||
onChange={field.onChange}
|
||||
placeholder={placeholder}
|
||||
rows={rows}
|
||||
maxLength={maxLength}
|
||||
autoResize={autoResize}
|
||||
disabled={disabled}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{error?.message && (
|
||||
<span className="form-hint form-hint--error">
|
||||
{String(error.message)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user