127 lines
2.5 KiB
TypeScript
127 lines
2.5 KiB
TypeScript
import { useMemo, useRef, useCallback, useLayoutEffect } from "react";
|
|
import ReactQuill from "react-quill-new";
|
|
import "react-quill-new/dist/quill.snow.css";
|
|
|
|
const COLORS = [
|
|
"#000000",
|
|
"#1a1a1a",
|
|
"#333333",
|
|
"#555555",
|
|
"#777777",
|
|
"#999999",
|
|
"#bbbbbb",
|
|
"#dddddd",
|
|
"#ffffff",
|
|
"#de3a3a",
|
|
"#e57373",
|
|
"#c62828",
|
|
"#1565c0",
|
|
"#42a5f5",
|
|
"#0d47a1",
|
|
"#2e7d32",
|
|
"#66bb6a",
|
|
"#1b5e20",
|
|
"#f57f17",
|
|
"#ffca28",
|
|
"#e65100",
|
|
"#6a1b9a",
|
|
"#ab47bc",
|
|
"#4a148c",
|
|
"#00695c",
|
|
"#26a69a",
|
|
"#004d40",
|
|
"#37474f",
|
|
"#78909c",
|
|
"#263238",
|
|
];
|
|
|
|
const TOOLBAR = [
|
|
["bold", "italic", "underline", "strike"],
|
|
[{ color: COLORS }, { background: COLORS }],
|
|
[{ list: "ordered" }, { list: "bullet" }],
|
|
[{ indent: "-1" }, { indent: "+1" }],
|
|
[{ align: [] }],
|
|
["link"],
|
|
["clean"],
|
|
];
|
|
|
|
const FORMATS = [
|
|
"bold",
|
|
"italic",
|
|
"underline",
|
|
"strike",
|
|
"color",
|
|
"background",
|
|
"list",
|
|
"indent",
|
|
"align",
|
|
"link",
|
|
];
|
|
|
|
interface RichEditorProps {
|
|
value: string;
|
|
onChange: (value: string) => void;
|
|
placeholder?: string;
|
|
minHeight?: string;
|
|
readOnly?: boolean;
|
|
}
|
|
|
|
export default function RichEditor({
|
|
value,
|
|
onChange,
|
|
placeholder = "Obsah...",
|
|
minHeight = "120px",
|
|
readOnly = false,
|
|
}: RichEditorProps) {
|
|
const quillRef = useRef<ReactQuill>(null);
|
|
const lastValueRef = useRef(value);
|
|
|
|
const modules = useMemo(
|
|
() => ({
|
|
toolbar: readOnly ? false : TOOLBAR,
|
|
clipboard: {
|
|
matchVisual: false,
|
|
},
|
|
}),
|
|
[readOnly],
|
|
);
|
|
|
|
const handleChange = useCallback(
|
|
(content: string, _delta: any, source: string) => {
|
|
if (source !== "user") return;
|
|
if (content === lastValueRef.current) return;
|
|
lastValueRef.current = content;
|
|
onChange(content);
|
|
},
|
|
[onChange],
|
|
);
|
|
|
|
useLayoutEffect(() => {
|
|
if (!quillRef.current) return;
|
|
const editor = quillRef.current.getEditor();
|
|
editor.format("font", "tahoma");
|
|
editor.format("size", "14px");
|
|
// Quill auto-focuses on mount with existing content, which scrolls
|
|
// the page to the editor. Blur to prevent unwanted scroll.
|
|
editor.blur();
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
className="admin-rich-editor"
|
|
style={{ "--re-min-height": minHeight } as React.CSSProperties}
|
|
>
|
|
<ReactQuill
|
|
ref={quillRef}
|
|
theme="snow"
|
|
value={value || ""}
|
|
onChange={handleChange}
|
|
modules={modules}
|
|
formats={FORMATS}
|
|
placeholder={placeholder}
|
|
readOnly={readOnly}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|