Summary
Lexical is a modern JavaScript (JS) text editor framework designed for extensibility and high performance. They adopt reactive state model, which ensures optimized updates and predictable behavior, and also have nodes as flexible data model.
Lexical is an open source project and considered the successor of Draft.js. It is primarily developed by Meta, licensed under MIT. It is not restricted to React, but supports Vanilla JS, too. The flexibility enables us to integrate it with other JS libraries such as Svelte and Vue.
This post shows how to embed the editor in a Bun-powered Vite project handled by Vanilla JS.
Environment
- Web Editor: Lexical 0.24
- Builder / Bundler: Vite 6.1.0
- JavaScript runtime: Bun 1.2.2
- OS: CathyOS (Linux distribution)
Tutorial
1. Create a Vite project
First, run:
$ bun run create vite lexical-example
Some questions will be asked. Here are my responses as an example:
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript
Scaffolding project in /(...)/lexical-example...
Done. Now run:
cd lexical-example
bun install
bun run dev
Let’s come in:
$ cd lexical-example
$ bun install
2. Install the editor framework
Add the dependency:
$ bun add lexical
It printed out installed [email protected]
.
3. Embed it into app
Rewrite src/main.ts
as below:
import { createEditor, LexicalEditor } from 'lexical'
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
<div id="myeditor" contenteditable></div>
`
let editor: LexicalEditor
document.addEventListener('DOMContentLoaded', () => {
const editorElement = document.getElementById('myeditor')
editor = createEditor()
editor.setRootElement(editorElement)
})
There are three points:
- Prepare
<div>
which iscontenteidtable
. - Create
LexicalEditor
. - Set the
<div>
as root element in the editor.
4. Test it to fail
Open http://localhost:5173/
with your web browser.
Typing in it must not bring any update…😂
5. Implement an actual editor
The reason around the failure is that there is LexicalEditor
instance but are not any actual editors activated.
We can fix it by registering packages such as plain text editor. Optionally, history module useful to manage input history is also available.
$ bun add @lexical/plain-text @lexical/history
Edit src/main.ts
as below:
import { createEditor, LexicalEditor } from "lexical"
+ import { createEmptyHistoryState, registerHistory } from '@lexical/history'
+ import { registerPlainText } from '@lexical/plain-text'
(...)
document.addEventListener("DOMContentLoaded", () => {
(...)
+ registerPlainText(editor)
+ registerHistory(editor, createEmptyHistoryState(), 300)
})
Complete src/main.ts
import { createEditor, LexicalEditor } from "lexical"
import { createEmptyHistoryState, registerHistory } from '@lexical/history';
import { registerPlainText } from "@lexical/plain-text";
document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
<div id="myeditor" contenteditable></div>
`
let editor: LexicalEditor;
document.addEventListener("DOMContentLoaded", () => {
const editorElement = document.getElementById("myeditor")
editor = createEditor()
editor.setRootElement(editorElement)
registerPlainText(editor)
registerHistory(editor, createEmptyHistoryState(), 300);
})
6. Test it to succeed
Now we can type to dive in !!!
Conclusion
Lexical is an open source text editor framework designed for speed, reliability, and flexibility. It enables developers to create not only plain text editors but also rich text or WYSIWYG editors with structured content, plugins, and collaborative features.
Happy development :)