Puck is the open-source visual editor for React built by Measured - a self-hosted alternative to builder.io, WordPress and other WYSIWYG tools.
We're celebrating 5,000 stars on GitHub! Thank you to our wonderful community!
Puck v0.16 is a big release, introducing the headline permissions API and — you guessed it — quality of life improvements. This one took a while to put together, and we appreciate your patience and support.
- Permissions: Toggle Puck features like duplication, dragging, deletion through the new permissions and resolvePermissions APIs.
-
Action bar override: Create custom action bars using the
actionBar
override, or extend the default one using the new<ActionBar>
component. -
iframe style injection: Access the iframe document to inject styles directly, or make other changes, via the new
iframe
override. We also introduced theemotion-cache
plugin for the common Emotion use-case. - History injection: Inject the undo/redo history via the a series of new APIs
-
React to actions: React to actions dispatched by Puck via the
onAction
callback. - Optional fields: Optional props are no longer required to define in fields, since they may be defined
Upgrade today or get started with:
npx create-puck-app@latest
Permissions
Permissions enable you to toggle core Puck functionality globally, on a per-component basis or dynamically. Huge thanks to @xaviemirmon for his efforts on this.
export function Editor() {
return (
<Puck
permissions={{
delete: false,
duplicate: true
}}
/>
);
}
Action bar override
The new actionBar
override enables you to create a custom action bar overlay, or extend the default one using the <ActionBar>
component:
const overrides = {
actionBar: ({ children }) => (
<ActionBar label="Actions">
{/* Render default actions */}
<ActionBar.Group>{children}</ActionBar.Group>
{/* Render new actions */}
<ActionBar.Group>
<ActionBar.Action onClick={() => console.log("Clicked!")}>
★
</ActionBar.Action>
</ActionBar.Group>
</ActionBar>
),
};
iframe style injection
The iframe
override enables you to access the iframe document
, making it possible to inject styles into the head:
const overrides = {
iframe: ({ children, document }) => {
useEffect(() => {
if (document) {
document.body.setAttribute("style", "background: hotpink;");
}
}, [document]);
return <>{children}</>;
},
};
The new emotion-cache
plugin uses this API to create an emotion cache inside the iframe, making Puck easy to use with any Emotion-based component library.
History injection
Use the new history injection APIs to provide your own undo/redo history via the initialHistory
prop, or dynamically via the setHistories
and setHistoryIndex
functions from usePuck().history
.
const historyState = {
data: {
root: {
props: { title: "My History" },
},
},
};
export function Editor() {
return (
<Puck
initialHistory={{
histories: [{ state: historyState }],
index: 0,
}}
// ...
/>
);
}
React to actions
The onAction
API enables you to react to Puck’s internal actions as they’re dispatched:
export function Editor() {
return (
<Puck
onAction={(action, appState, prevAppState) => {
if (action.type === "insert") {
console.log("New component was inserted", appState);
}
}}
/>
);
}
Breaking changes
history.data
is now history.state
When using the usePuck history
API, data
is now renamed state
.
history.id
is now optional (TypeScript)
When using the usePuck history
API id
is now optional. Puck will always generate an id
, but TypeScript may complain.
lastData
is now returned as null
instead of {}
when empty in resolvers
When using the lastData
option provided to resolveData
or resolveFields
functions, and there is no previous data, lastData
will now be null
instead of {}
.
Full changelog
Features
- add actionBar override for adding component controls (48ec0d7)
- add automatic RSC export, replacing /rsc bundle (d21eba6)
- add isDisabled prop to Drawer.Item (cad95b8)
- add generic type to usePuck hook (01703a9)
- add iframe override for style injection (7cac376)
- add initialHistory prop to Puck (54b5a87)
- add onAction API to track and react to state changes (c7007ac)
- add permissions API (a43914d)
- add plugin for injecting Emotion cache (f8a88b9)
- add resolvePermissions API (f0655f0)
- add waitForStyles option to iframe config (bc81d9c)
- call resolveData when new item inserted (3298831)
- don't mandate fields for optional props (5a219ef)
- export ActionBar component for use in overrides (04fd6c5)
- infer Data type from user config (50045bb)
- make ID optional in History type (BREAKING CHANGE) (d917229)
- provide ES Module build (ff9076b)
- rename history.data to history.state (BREAKING CHANGE) (b09244c)
- show spinner if iframe load takes over 500ms (cfecf54)
- streamline usePuck history API (c8b2807)
- upgrade "next" recipe to typescript@5.5.4 (60fe631)
Bug Fixes
- add favicon to next recipe to prevent Puck 404 (2c52d27)
- add missing readOnly state to External fields (bf1449d)
- always record history on component insert (88c5ab6)
- don't cache /edit route in Next recipe (94f16b2)
- don't submit buttons if Puck used in form (f761e5f)
- ensure demo types are satisfied with TypeScript@5 (958dc25)
- export missing Plugin type (eb42734)
- fix crash if component in data is missing from config (0daf478)
- improve resiliency of iframe CSS for some frameworks, like Mantine (538cb05)
- make Config and Data types more robust (6bcf555)
- prevent infinite loop when using plugins with some frameworks (3870871)
- prevent Tailwind from clashing with viewport zoom select (9151255)
- remove body margin in remix recipe (0898b26)
- resize viewport when changed via app state (14419ec)
- resolve fields when switching between items of same type (a3518ca)
- return lastData as null instead of empty object in resolvers (BREAKING CHANGE) (648eb92)
- show warning if heading-analyzer styles aren't loaded (4e7110b)
- use correct color in FieldLabel labels (b0469a1)
New Contributors
- @mkilpatrick made their first contribution in https://github.com/measuredco/puck/pull/505
- @nova4u made their first contribution in https://github.com/measuredco/puck/pull/538
- @antonmalyavkin made their first contribution in https://github.com/measuredco/puck/pull/585
Full Changelog: https://github.com/measuredco/puck/compare/v0.15.0...v0.16.0
Top comments (0)