My Design System Lexical Rich Text Editor Implementation
About the Lexical Implementation
Things to note about this implementation of Lexical:
-
An editor instance will be created on any editor that looks like:
<div data-rich-text-editor>
-
All editors should be wrapped in an element that looks like
<div class="lexical-wrapper">
. This is because most of the time you will want a toolbar with buttons that dispatch actions, and these actions should be listened for and dispatched on the wrapper<div>
. Each one of these wrapper divs should have a unique id that is a valid javascript variable name. That is how we keep track of different editor instances in the client side javascript. - We use the wrapper div to add appropriate event listeners when registering Lexical Update Listeners, and when an ancestor of the editor is about to be removed form the DOM we use the id of the editor to get the editor instance and properly remove the editor.
-
When a LexicalEditor is focused, we get the input in the
<main>
element that looks like:<input id="LEXICAL_EDITOR_CURRENT" type="text" />
, and set the value of the input to be the id of the wrapper div of the focused editor instance so we can include dialogs on the page that have the ability to dispatch actions on the correct editor instance.
This allows us to have multiple rich text editors on a single page and only one set of dialogs. - When an editor is encountered and is in the process of being registered, we first check if the editor has any innerHTML, and id it does, then we try to derive lexical state from the innerHTML and apply that to the editor.
-
There are different kinds of lexical editors that register different Command / Update Listers on the editor. You can specify which kind of editor you want
by including different data-* attributes on the data-rich-text-editor element. Here are the ones that have been implemented so far (more will be added in the future):
-
data-rich-text-full
- Includes all the features that an editor can have - used for the article builder and to test out new features.
-
data-article
- Includes all the features that an editor can have - used for the article builder and for rendering articles. This kind of editor has its editable feature set to false after the Lexical State is applied to the div because it is meant to be read. I will need to add the ability for users to highlight specific portions of the article later so that they can highlight certain pieces of content they like / dislike and comment on it.
-
data-type="poll-question"
- Basically the same as the full editor except for different styling.
-
data-poll-response
- Used to allow users to respond to polls.
-
data-range-description
- Used to allow users to describe range inputs for poll questions.
-
data-rich-text-full
I need to look over how the editor nodes implement the exportDOM function because I may need to include the version of the Node in the data-* attributes for each element to prevent any errors when new versions of nodes are added to the editor.
TO DO:
- There needs to be a way for users to upload .csv or .xlsx information and get a rendered lexical table in return. Need to look into how to append data to the editor like that.
- Maybe look into inline-highlighted code.
- Need to include the context menu for highlighted text and implement that context menu for highlighted text on mobile. Look into the Context Menu event.
Example Lexical Implementation
<aside>
Element
<details>
Element
Lexical Output
Submit the Lexical Editor above and the output will be rendered in the div below. Make sure to look out for the CLS when the lexical output is initially shown (which shows the output of exportDOM per-node) vs when the actual node is rendered via JavaScript.