Default Implementation Overview
Throughout the tutorial, DefaultEditorComponent was a black box: hand it an editor core and
a working editing interface appears. This part of the documentation opens the box. This page covers where
the default implementation sits in the library, why it is built as a layer you can replace wholesale, and
what that one component actually assembles for you. The pages that follow take the interface, the
keyboard, the renderer factories, customization and the printer side in turn.
The two halves of the library
The library splits into two parts. One is the core: the definitions of concepts and nodes, the editor core, the printer core. They are concerned only with what a document tree is, how it gets modified and how it gets rendered, and they make no decisions about the interface. There is not a single button, not one colour, not one shortcut anywhere in the core.
The other part is the default implementation. It is one complete answer to the question of what the interface should look like: a sheet of paper, a sidebar, a row of buttons on every node, two draggable floating panels, a full keyboard scheme, and a set of typesetting widgets on the printer side. That answer takes a position. It assumes you are building an editor for long, serious documents whose structure gets manipulated often. If that is not your situation, this whole layer can go.
Where that line falls explains a design that looks odd at first sight: both the editor and the printer
are split into a core object and a component object. EditorCore goes with
EditorComponent, Printer goes with PrinterComponent. The core
holds information but never draws; the component draws but holds nothing.
The benefit of separating them is that several components can share one core. The floating window that edits abstract nodes is a ready example: it is another editor component sharing the main editor's core, so both sides see identical concept definitions and renderers, and a theorem inserted inside a footnote goes through exactly the same code as one inserted in the body.
Three levels of depth
For you as a user, that dividing line means three levels of depth, increasing in both cost and freedom.
| Approach | What you write | Suits |
|---|---|---|
| Use the default implementation as it comes | Concept definitions, renderers, and a few props on DefaultEditorComponent | The large majority of cases |
| Modify the default implementation | Custom buttons, a replaced renderer here and there, config and theme | When you need operations or an appearance of your own |
| Skip the default implementation | Your own interface built on EditorComponent | When your interface differs fundamentally |
Few people need the third level, but it is available: the default implementation uses no private interfaces, so everything it calls, you can call.
What DefaultEditorComponent assembles
The component itself holds almost no logic of its own. Its value is that it stacks seven or eight things that all have to be present, in an order that cannot be varied. Peeling its rendered structure from the outside in:
| Layer | Role |
|---|---|
EditorConfigContext.Provider | Hands the style config (fonts, margins, widths) to everything downstream; renderers read it with useEditorConfig() |
SnackbarProvider | The container for toast messages, from notistack |
IdxConflictSolver | Watches for duplicate node indices and renumbers when it finds them |
KeyEventManager | The global key dispatcher, from @ftyyy/mouseless |
EditorComponent | The editor proper, the sheet you type on |
EditorGlobalInfo.Provider | Hands the editor instance downstream; the sidebar, the floating panels and your own buttons all get the editor from here |
DefaultSidebar / Areas / AbstractEditorArea | The sidebar, the two floating panels, the floating editor for abstract nodes |
Three of these layers deserve their own explanation.
The first is SnackbarProvider. It is here because the default implementation's buttons
report success and failure with toast messages, and those need a container. Since it sits inside the
editor, your own buttons can call useSnackbar() with no further setup. The other way round:
raising a toast from outside the editor, from a top bar for instance, needs another
SnackbarProvider further out.
The second is IdxConflictSolver. Tutorial chapter 1 established that every concept node
carries an idx unique within the document, and that cross references locate their targets by
it. Copy and paste breaks that uniqueness as a matter of course: copy a theorem, paste it, and the
document holds two nodes with the same idx, so references point at the wrong one. This component checks
after every change and renumbers one of the offenders. It is work that has to be done and that nobody
wants to write, so the default implementation does it.
The third is KeyEventManager, the hub of the whole keyboard scheme. Every keystroke reaches
it first and is dispatched from there to the right part of the interface. The default editor registers
four groups of interface elements with it and lists the combinations whose browser default must be
suppressed. That mechanism has a page of its own, Keyboard Operation.
How to read this part
The remaining five pages stand on their own and can be read as needed, roughly ordered from what you see to what you change:
| Page | Contents |
|---|---|
| The Editing Interface | The paper, the eight buttons on a node, the parameter drawer, abstract nodes, the sidebar, the two floating panels, and the AreaContainer you must place yourself |
| Keyboard Operation | The model behind spatial navigation, every combination, and the hint mechanism |
| Editor Renderer Factories | A factory per node type and its options, UniversalExtra, and the hooks available inside renderers |
| Customizing the Default Editor | Style config, added buttons, theme, and replacing an individual renderer |
| The Printer Side | DefaultPrinterComponent, the printer configuration, the typesetting widgets |
The source of the live demo, in the repository's demo/ directory, is a complete worked
example of everything in this part. When a passage feels abstract, that is the place to compare against.