docs/(guides)/plugin-methods.mdx
When extending plugins, all properties are deeply merged by default, with two exceptions: arrays are replaced entirely, and the options object is shallow merged.
The .configure method allows you to override the plugin's configuration.
const ConfiguredPlugin = MyPlugin.configure({
options: {
myOption: 'new value',
},
});
You can also use a function to access the current configuration:
const ConfiguredPlugin = MyPlugin.configure(({ getOptions }) => ({
options: {
...getOptions(),
myOption: `${getOptions().myOption} + extra`,
},
}));
The .configurePlugin method allows you to configure the properties of a nested plugin:
const TablePlugin = createPlatePlugin({
key: 'table',
plugins: [TableCellPlugin],
}).configurePlugin(TableCellPlugin, {
options: {
cellOption: 'modified',
},
});
.configure, it modifies existing properties but doesn't add new ones.The .extend method allows you to extend the plugin's configuration and functionality.
const ExtendedPlugin = MyPlugin.extend({
options: {
newOption: 'new value',
},
});
You can also use a function to access the current configuration and editor:
const ExtendedPlugin = MyPlugin.extend(({ editor, plugin }) => ({
options: {
newOption: 'new value',
},
handlers: {
onKeyDown: () => {
// Custom key down logic
},
},
}));
The .extendPlugin method allows you to extend the configuration and functionality of a nested plugin:
const TablePlugin = createPlatePlugin({
key: 'table',
plugins: [TableCellPlugin],
}).extendPlugin(TableCellPlugin, {
options: {
newCellOption: 'added',
},
handlers: {
onKeyDown: () => {
// Custom key down logic for table cells
},
},
});
While both methods can be used to modify plugin configuration, they have some key differences:
.extend is chainable, while .configure is not..extend returns a new plugin instance with extended types, while .configure maintains the original type..extend can add new properties to the plugin configuration, while .configure only modifies existing ones.Choose the appropriate method based on whether you need to extend the plugin's type and functionality (use .extend) or simply modify existing configuration (use .configure).
The extendSelectors method allows you to add subscribable selectors to your plugin:
const CounterPlugin = createPlatePlugin({
key: 'counter',
options: {
count: 0,
},
}).extendSelectors(({ getOptions }) => ({
doubleCount: () => getOptions().count * 2,
isEven: () => getOptions().count % 2 === 0,
}));
You can then use those selectors in your components or other plugin methods:
const CounterComponent = () => {
const count = usePluginOption(CounterPlugin, 'count');
const doubleCount = usePluginOption(CounterPlugin, 'doubleCount');
const isEven = usePluginOption(CounterPlugin, 'isEven');
return (
<div>
<p>Count: {count}</p>
<p>Double Count: {doubleCount}</p>
<p>Is Even: {isEven ? 'Yes' : 'No'}</p>
</div>
);
};
getOptionusePluginOption, recomputed whenever options change, re-rendering only when the result changes. This is the main difference with .extendApi.The withComponent method allows you to set or replace the component associated with a plugin.
const ParagraphPlugin = createPlatePlugin({
key: 'p',
node: {
isElement: true,
type: 'p',
},
}).withComponent(ParagraphElement);
Plugins can define their own API methods and transforms that will be merged into the editor's API and transforms. This is done using the extendApi, extendEditorApi, extendTransforms, and extendEditorTransforms methods.
Use extendApi to add plugin-specific API methods:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
}).extendApi(() => ({
pluginMethod: () => 'plugin method result',
}));
// Access the plugin's API
editor.api.myPlugin.api.pluginMethod();
Use extendEditorApi to add root-level API methods:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
}).extendEditorApi(({ getOptions }) => ({
editorMethod: () => getOptions().someOption,
}));
// Access the plugin's API
editor.api.editorMethod();
Use extendTransforms to add plugin-specific transform methods:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
}).extendTransforms(() => ({
pluginTransform: () => {
// Custom transform logic
},
}));
// Access the plugin's transform
editor.tf.myPlugin.pluginTransform();
// NOTE: `editor.tf` in a short alias to `editor.transforms`
editor.transforms.myPlugin.pluginTransform();
Use extendEditorTransforms to add root-level transform methods:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
}).extendEditorTransforms(({ editor }) => ({
editorTransform: () => {
// Custom editor transform logic
},
}));
// Access the plugin's transform
editor.tf.editorTransform();
The overrideEditor method is used specifically for overriding existing editor methods without altering the plugin's type:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
}).overrideEditor(({ editor, tf: { insertText }, api: { isInline } }) => ({
transforms: {
insertText(text, options) {
// Override insertText behavior
insertText(text, options);
},
},
api: {
isInline(element) {
// Override isInline behavior
return isInline(element);
},
},
}));
transforms or api objectsextendEditorTransforms or extendEditorApi instead)While there is currently no core difference between API and Transforms in Plate, they serve distinct purposes and are designed with future extensibility in mind:
Transforms:
editor.tf.toggleBlock(), editor.tf.toggleMark('bold')API:
editor.api.save(), editor.api.debug.log()You can chain these methods to create a comprehensive plugin:
const MyPlugin = createPlatePlugin({
key: 'myPlugin',
options: {
baseValue: 5,
},
})
.extendApi(() => ({
pluginMethod: () => 'plugin method',
}))
.extendEditorApi(({ getOptions }) => ({
multiply: (factor: number) => getOptions().baseValue * factor,
}))
.extendTransforms(() => ({
pluginTransform: () => {
// Plugin-specific transform
},
}))
.extendEditorTransforms(({ editor }) => ({
editorTransform: () => {
// Editor-specific transform
},
}));
editor.api.myPlugin.api.pluginMethod();
editor.api.multiply(3);
editor.tf.myPlugin.pluginTransform();
editor.tf.editorTransform();
To convert a typed Slate plugin to a Plate plugin, you can use toPlatePlugin:
const CodeBlockPlugin = toPlatePlugin(createSlatePlugin({ key: 'code_block' }), {
handlers: {},
options: { hotkey: ['mod+opt+8', 'mod+shift+8'] },
});