Plugin API
The plugin API is highly experimental and is likely to experience breaking changes.
The plugin API enables developers to share extensions to Puck, and are generally built on top of existing APIs.
Official plugins
Puck provides official plugins for common use-cases:
emotion-cache
: Inject emotion cache into the Puck iframe.heading-analyzer
: Analyze the heading outline of your page and be warned when you’re not respecting WCAG 2 accessibility standards.
Please see the awesome-puck repo for a full list of community plugins.
Loading a Plugin
To load a plugin, provide it to the plugins
prop on the <Puck>
component.
import { Puck } from "@measured/puck";
import myPlugin from "my-puck-plugin";
export function Editor() {
return (
<Puck
// ...
plugins={[myPlugin]}
/>
);
}
Developing a Plugin
If you’re familiar with Puck, you can likely already build a Puck plugin. See the Plugin API reference for a full breakdown of available APIs.
Transforming fields
Plugins support Field Transforms, enabling you to modify prop data before it’s rendered in the <Puck>
preview.
const plugin = {
fieldTransforms: {
// Make all props powered by "text" field pink in the editor
text: ({ value }) => <span style={{ color: "hotpink" }}>{value}</span>,
},
};
Overriding the UI
Plugins support UI Overrides, enabling you to override discrete section of the Puck interface.
const plugin = {
overrides: {
// Make all drawer items pink
drawerItem: ({ name }) => <div style={{ color: "hotpink" }}>{name}</div>,
},
};
Plugin overrides are rendered in the order they are defined. Unless otherwise specified, all overrides are curried, meaning that the return node of one plugin will be passed as children
to the next plugin.
This may result in some incompatible plugin combinations. To improve your chance of building a widely compatible plugin, consider:
- Implementing as few override methods as you need
- Always rendering
children
if possible
Introducing new field types
Both the field transforms and overrides let you introduce entirely new field types. Plugins can combine this functionality to bundle up new field behavior in a convenient package.
This example uses Overlay Portals to create an interactive rich text field that can modified directly in the editor preview.
import { registerOverlayPortal } from "@measured/puck";
const plugin = {
overrides: {
// Add a richText field type
fieldTypes: {
richText: ({ name, value }) => <input name={name} value={value} />,
},
},
fieldTransforms: {
// Wrap the value in a span, create an overlay portal, and make it editable
richText: ({ value }) => {
const handleInput = useCallback(() => {}, []); // Implement your input behavior
return (
<span ref={registerOverlayPortal} contentEditable onInput={handleInput}>
{value}
</span>
);
},
},
};