📝 Lexical Builder 🛠️
A Unified Model for Extending Lexical
Solved Problems
- Modularized editor configuration
- Each Plan 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
- A Plan is completely self-contained, and specifies all dependencies to make it work. If you want checklists, add CheckListPlan as a dependency to your editor's plan. 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 Plans can provide an error if a suitable framework host is not available (e.g.
ReactPlan
is used, but there's noLexicalPlanComposer
orReactPluginHostPlan
) - 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
ReactPluginHostPlan
to use React Plans 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 Plan can specify its own optional typed configuration of any kind, that can be specified by any other plan, 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
- A Plan can specify type-safe outputs, which are computed when the plan 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 Plan in your editor!