📝 Lexical Builder 🛠️
A Unified Model for Extending Lexical
Solved Problems
- Modularized editor configuration
- Each Extension can specify partial editor configuration (nodes, theme, DOM import/export, etc.) that are all merged to build the editor
- Combined config + registration
- Generally there are interdependencies between configuration and behavior, e.g. the ListPlugin requires ListNode and ListItemNode and vice versa.
- Hassle-free dependencies
- An Extension is completely self-contained, and specifies all dependencies to make it work. If you want checklists, add CheckListExtension as a dependency to your editor's extension. No more missing Node errors or silently absent behavior.
- Optional peer dependencies
- Have an optional dependency? No problem. You can even specify config overrides if peer dependencies are present! This is used internally so Extensions can provide an error if a suitable framework host is not available (e.g.
ReactExtension
is used, but there's noLexicalExtensionComposer
orReactPluginHostExtension
) - Framework independent
- Many Plugins don't really need React, but the only legacy convention is to expose as much behavior as possible in a React component even if it just calls some register functions and returns null.
- React anywhere
- Non-React users can use the
ReactPluginHostExtension
to use React Extensions or legacy Plugins! This of course still uses React at runtime, but does not force the user to learn React, use JSX syntax, or have any direct React dependency in their project. - Extensible config
- Each Extension can specify its own optional typed configuration of any kind, that can be specified by any other extension, and is accessible at runtime anywhere you can get an editor reference (even in a Node!). No need to shoehorn properties into the editor-global
EditorTheme { [key: string]: any }
or set up a module-globalWeakMap<Editor, Config>
workaround. - Outputs
- An Extension can specify type-safe outputs, which are computed when the extension is registered to the editor (so can take configuration, the editor, and dependencies into account). These can be used by dependencies, or anywhere you have an editor reference. Think of it like having a sort of React style context for each Extension in your editor!