chore(react/ribbon): use separate component for editor

This commit is contained in:
Elian Doran 2025-08-23 12:05:03 +03:00
parent 73038efccf
commit 1e00407864
No known key found for this signature in database
2 changed files with 72 additions and 47 deletions

View File

@ -0,0 +1,53 @@
import type { AttributeEditor, EditorConfig } from "@triliumnext/ckeditor5";
import { useEffect, useRef } from "preact/compat";
interface CKEditorOpts {
className: string;
tabIndex?: number;
config: EditorConfig;
editor: typeof AttributeEditor;
disableNewlines?: boolean;
disableSpellcheck?: boolean;
onChange?: () => void;
}
export default function CKEditor({ className, tabIndex, editor, config, disableNewlines, disableSpellcheck, onChange }: CKEditorOpts) {
const editorContainerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!editorContainerRef.current) return;
editor.create(editorContainerRef.current, config).then((textEditor) => {
if (disableNewlines) {
textEditor.editing.view.document.on(
"enter",
(event, data) => {
// disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422
data.preventDefault();
event.stop();
},
{ priority: "high" }
);
}
if (disableSpellcheck) {
const documentRoot = textEditor.editing.view.document.getRoot();
if (documentRoot) {
textEditor.editing.view.change((writer) => writer.setAttribute("spellcheck", "false", documentRoot));
}
}
if (onChange) {
textEditor.model.document.on("change:data", onChange);
}
});
}, []);
return (
<div
ref={editorContainerRef}
className={className}
tabIndex={tabIndex}
/>
)
}

View File

@ -1,8 +1,9 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks"
import { AttributeEditor as CKEditor, EditorConfig, MentionFeed } from "@triliumnext/ckeditor5";
import { AttributeEditor as CKEditorAttributeEditor, EditorConfig, MentionFeed } from "@triliumnext/ckeditor5";
import { t } from "../../../services/i18n";
import server from "../../../services/server";
import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
import CKEditor from "../../react/CKEditor";
const mentionSetup: MentionFeed[] = [
{
@ -48,57 +49,28 @@ const mentionSetup: MentionFeed[] = [
}
];
const editorConfig: EditorConfig = {
toolbar: {
items: []
},
placeholder: t("attribute_editor.placeholder"),
mention: {
feeds: mentionSetup
},
licenseKey: "GPL"
};
export default function AttributeEditor() {
const editorContainerRef = useRef<HTMLDivElement>(null);
const [ attributeDetailVisible, setAttributeDetailVisible ] = useState(false);
const onClick = useCallback(() => {
console.log("Clicked");
}, []);
useEffect(() => {
if (!editorContainerRef.current) return;
CKEditor.create(editorContainerRef.current, editorConfig).then((textEditor) => {
function onDataChanged() {
console.log("Data changed");
}
// Prevent newlines
textEditor.editing.view.document.on(
"enter",
(event, data) => {
// disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422
data.preventDefault();
event.stop();
},
{ priority: "high" }
);
// disable spellcheck for attribute editor
const documentRoot = textEditor.editing.view.document.getRoot();
if (documentRoot) {
textEditor.editing.view.change((writer) => writer.setAttribute("spellcheck", "false", documentRoot));
}
textEditor.model.document.on("change:data", onDataChanged);
});
}, []);
return (
<div style="position: relative; padding-top: 10px; padding-bottom: 10px" onClick={onClick}>
<div ref={editorContainerRef} class="attribute-list-editor" tabindex={200} />
<div style="position: relative; padding-top: 10px; padding-bottom: 10px">
<CKEditor
className="attribute-list-editor"
tabIndex={200}
editor={CKEditorAttributeEditor}
config={{
toolbar: { items: [] },
placeholder: t("attribute_editor.placeholder"),
mention: { feeds: mentionSetup },
licenseKey: "GPL"
}}
onChange={() => {
console.log("Data changed!");
}}
disableNewlines disableSpellcheck
/>
</div>
)
}