feat(lexicalEditor): custom enter-key plugin (#15952)

* fix(team-description): break lines rendering

* chore(EventTypeDescription): useBreakLine hook for handling html line breaks

* feat(lexicalEditor): custom enter-key plugin

* test(customEditorPlugin): enter key usage

* Update customEnterKeyPlugin.tsx

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
This commit is contained in:
Sy SagarandAnik Dhabal Babu authored and GitHub committed 2025-02-24 14:12:12 +05:30
1 parent 2089ad40ea
commit 564497ec2a
3 files changed
+123

No files matched your search

+2
View File
@@ -23,6 +23,7 @@ import AutoLinkPlugin from "./plugins/AutoLinkPlugin";
import EditablePlugin from "./plugins/EditablePlugin";
import PlainTextPlugin from "./plugins/PlainTextPlugin";
import ToolbarPlugin from "./plugins/ToolbarPlugin";
import CustomEnterKeyPlugin from "./plugins/customEnterKeyPlugin";
import "./stylesEditor.css";
/*
@@ -111,6 +112,7 @@ export const Editor = (props: TextEditorProps) => {
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<CustomEnterKeyPlugin />
{props?.variables ? <AddVariablesPlugin variables={props.variables} /> : null}
<HistoryPlugin />
<MarkdownShortcutPlugin
@@ -0,0 +1,81 @@
import { CodeHighlightNode, CodeNode } from "@lexical/code";
import { AutoLinkNode, LinkNode } from "@lexical/link";
import { ListItemNode, ListNode } from "@lexical/list";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
import { render } from "@testing-library/react";
import { fireEvent, waitFor } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import ExampleTheme from "../ExampleTheme";
import { VariableNode } from "../nodes/VariableNode";
import CustomEnterKeyPlugin from "./customEnterKeyPlugin";
const editorConfig = {
theme: ExampleTheme,
onError(error: Error) {
throw error;
},
namespace: "",
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode,
VariableNode,
],
};
const TestEditor = () => (
<LexicalComposer initialConfig={editorConfig}>
<RichTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter some text...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<CustomEnterKeyPlugin />
</LexicalComposer>
);
describe("Editor", () => {
describe("CustomEnterKeyPlugin", () => {
let container: HTMLElement | null = null;
beforeEach(() => {
container = render(<TestEditor />).container;
});
afterEach(() => {
container = null;
});
it("should insert a line break on Enter key press", async () => {
if (container === null) {
throw new Error("Container is null");
}
const editorElement = container.querySelector('[contenteditable="true"]') as HTMLElement;
editorElement.focus();
const paragraphElement = editorElement.querySelector("p") as HTMLElement;
fireEvent.keyDown(editorElement, { key: "Enter", code: "Enter", keycode: 13 });
await waitFor(() => {
const brElements = paragraphElement?.querySelectorAll("br");
expect(brElements?.length).toBe(1);
});
});
});
});
@@ -0,0 +1,40 @@
"use client";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import {
$createLineBreakNode,
$getSelection,
$isRangeSelection,
COMMAND_PRIORITY_HIGH,
KEY_ENTER_COMMAND,
} from "lexical";
import { useEffect } from "react";
const CustomEnterKeyPlugin = () => {
const [editor] = useLexicalComposerContext();
useEffect(() => {
const removeEnterCommand = editor.registerCommand(
KEY_ENTER_COMMAND,
(event: any) => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
event.preventDefault();
const lineBreakNode = $createLineBreakNode();
selection.insertNodes([lineBreakNode]);
return true;
}
return false; // any failure case of not selection
},
COMMAND_PRIORITY_HIGH
);
return () => {
removeEnterCommand();
};
}, [editor]);
return null;
};
export default CustomEnterKeyPlugin;