> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumen.bjanczak.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Module API: Custom Toolbar Buttons in Lumen Editor

> The EditorModule interface, how to access and reuse built-in modules, and a complete walkthrough of building and registering custom toolbar buttons.

Modules are the building blocks of the Lumen Editor toolbar. Every button you see — bold, heading, image insert, undo — is a module: a plain object that describes the button's appearance and what happens when it is clicked. You can access the 17 built-in modules, override them, reorder them, and add your own using the same interface.

## `EditorModule` Interface

Every module — built-in or custom — implements the `EditorModule` interface:

```ts theme={null}
interface EditorModule {
  name: string;
  group: string;
  icon: string;
  label: string;
  exec: (editor: Editor) => void;
}
```

<ParamField body="name" type="string" required>
  A unique command identifier for the module. This is the string you reference in the `toolbar` option array to place the button. It must be unique across all registered modules.
</ParamField>

<ParamField body="group" type="string" required>
  The logical category of the command. Accepted values are `'inline'`, `'block'`, `'history'`, and `'insert'`. The group does not affect rendering — it is metadata for your own organisation and for any third-party plugins that inspect the module registry.
</ParamField>

<ParamField body="icon" type="string" required>
  An HTML string rendered as the inner content of the toolbar button. You can use an SVG literal, a Unicode character, an `<img>` tag, or any valid HTML fragment. The string is injected via `innerHTML`, so keep it trusted.
</ParamField>

<ParamField body="label" type="string" required>
  The tooltip text displayed on hover and used as the button's `aria-label`. Keep labels short and descriptive — they are the primary accessibility affordance for the toolbar button.
</ParamField>

<ParamField body="exec" type="(editor: Editor) => void" required>
  The function called when the toolbar button is clicked. Receives the live `Editor` instance so you can call any public method — `setHTML()`, `getHTML()`, `on()`, `focus()`, etc. — or interact with `document.execCommand` for low-level formatting.
</ParamField>

## Accessing Built-in Modules

Lumen Editor exports all built-in modules as a keyed record object:

```js theme={null}
import { Editor, modules } from 'lumen-editor';
// modules: Record<string, EditorModule>
```

Each built-in module is accessible by its name as a key:

```js theme={null}
console.log(modules.bold);
// {
//   name: 'bold',
//   group: 'inline',
//   icon: '<svg …>…</svg>',
//   label: 'Bold',
//   exec: [Function],
// }
```

You can spread `modules` into your own array, override individual entries, or pick specific ones to keep the toolbar minimal:

```js theme={null}
// Use only a subset of built-ins
const minimalModules = [
  modules.bold,
  modules.italic,
  modules.link,
  modules.undo,
  modules.redo,
];
```

## Built-in Module Names

All 17 built-in modules and their groups:

| Name            | Group     |
| --------------- | --------- |
| `undo`          | `history` |
| `redo`          | `history` |
| `bold`          | `inline`  |
| `italic`        | `inline`  |
| `underline`     | `inline`  |
| `strikethrough` | `inline`  |
| `h1`            | `block`   |
| `h2`            | `block`   |
| `h3`            | `block`   |
| `paragraph`     | `block`   |
| `ul`            | `block`   |
| `ol`            | `block`   |
| `blockquote`    | `block`   |
| `code`          | `block`   |
| `link`          | `insert`  |
| `image`         | `insert`  |
| `html`          | `insert`  |

## Registering Custom Modules

To add a custom module, include it in the `modules` array alongside the built-ins, and add its `name` to the `toolbar` layout. The example below adds a **Highlight** button that applies a yellow background to selected text:

```js theme={null}
import { Editor, modules } from 'lumen-editor';
import 'lumen-editor/theme.css';

const highlightModule = {
  name: 'highlight',
  group: 'inline',
  icon: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
          fill="none" stroke="currentColor" stroke-width="2">
          <path d="M12 20h9"/><path d="M16.5 3.5l4 4L7 21l-4 1 1-4Z"/>
        </svg>`,
  label: 'Highlight',
  exec: (editor) => {
    document.execCommand('hiliteColor', false, 'yellow');
  },
};

const editor = new Editor('#editor', {
  // Merge built-ins with your custom module
  modules: [
    ...Object.values(modules),
    highlightModule,
  ],

  // Add 'highlight' to the toolbar layout
  toolbar: [
    ['bold', 'italic', 'underline', 'highlight'],
    ['h1', 'h2', 'h3', 'paragraph'],
    ['ul', 'ol', 'blockquote'],
    ['link', 'image'],
    ['undo', 'redo'],
  ],
});
```

<Note>
  A module listed in the `toolbar` array but absent from `modules` is silently skipped — no button is rendered and no error is thrown. Always make sure every command name in `toolbar` has a corresponding entry in `modules`.
</Note>

<Tip>
  To override a built-in module's icon or behaviour, spread the original and replace only the properties you want to change:

  ```js theme={null}
  const customBold = {
    ...modules.bold,
    icon: '<strong>B</strong>',   // swap icon only
  };
  ```
</Tip>

## TypeScript Exports

Lumen Editor ships full TypeScript declarations. The following types are exported from the `lumen-editor` package and can be used to type plugins, modules, and editor options in your project:

```ts theme={null}
import {
  Editor,          // The editor class itself
  EditorOptions,   // Constructor options object
  EditorModule,    // Interface for toolbar module objects
  EditorPlugin,    // Type for plugin functions: (editor: Editor) => void
  EditorEvent,     // Union of all event name strings
  SanitizeConfig,  // Configuration object for the built-in HTML sanitizer
} from 'lumen-editor';
```

Using these types in a custom module ensures your code is checked at compile time:

```ts theme={null}
import { Editor, EditorModule, EditorPlugin } from 'lumen-editor';

const highlight: EditorModule = {
  name: 'highlight',
  group: 'inline',
  icon: '★',
  label: 'Highlight',
  exec: (editor: Editor) => {
    document.execCommand('hiliteColor', false, 'yellow');
  },
};

const myPlugin: EditorPlugin = (editor: Editor) => {
  editor.on('change', () => console.log(editor.getHTML()));
};
```
