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:
1 parent
2089ad40ea
commit
564497ec2a
3 files changed
+123
No files matched your search
@@ -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;
|
||||
Reference in new issue
Block a user