Skip to content

Releases: measuredco/puck

v0.18.2

31 Jan 12:52
Compare
Choose a tag to compare

Bug Fixes

  • add missing types for root render method (0f52caf)
  • address ownerDocument permission error in Firefox (c22b3a9)
  • address prop name collision regression (3a69ad4)
  • correctly infer types when using Render with RSC (ad7fbf4)
  • don't jump to end of textarea fields during change (36c27a9)
  • don't trigger clicks when dropping array items (29a7f1d)
  • don't trigger drag when interacting with array fields (c7cd341)
  • ensure ctrl+i interactive toggle hotkey works on Windows (5db6f4d)
  • ensure renderDropZone provided correctly to root render (b9ce5b7)
  • fix RTL drag-and-drop behaviour (28f518a)
  • improve behaviour of array drag-and-drop (565fabd)
  • provide empty readOnly object instead of undefined to root resolveFields (8992a94)
  • provide updated props to resolveFields (b7ff689)
  • reinstate padding for external field filters (28ccfda)
  • tidy up stale items on drag cancellation (de48691)
  • update styles for RTL (23c8dda)
  • use correct type for onChange args when overriding fieldTypes (daff71e)

New Contributors

Full Changelog: v0.18.0...v0.18.2

v0.18.1

24 Jan 19:45
Compare
Choose a tag to compare

Bug Fixes

  • address React 19 peer dependency issues (7649086)
  • address ResizeObserver loop error (d3e6b57)
  • don't access selectedItem if undefined right after drop (0573b18)
  • ensure nested drag-and-drop works in Firefox (f077a37)

Full Changelog: v0.18.0...v0.18.1

v0.18.0

22 Jan 11:32
Compare
Choose a tag to compare

Puck 0.18 introduces a new drag-and-drop engine with native support for CSS grid and flexbox, enabling you to embed a design-in-browser experience directly within your React application or page builder.

the new drag-and-drop engine in action

TLDR

  • New drag-and-drop engine: Multi-dimensional drag-and-drop across any CSS layout to create a sophisticated page building experience. Read the docs.
  • Dynamic DropZone height: DropZones now shrink to the height of their children, with a configurable height when empty.
  • Toggle interactive hotkey: Make your components interactive in Preview mode with the cmd+i hotkey.
  • Parent selector: A new action allows you to quickly select the component's parent directly from the action bar.
  • No more position: fixed: We've removed this pesky style from the default layout so it's easier to embed in your app.
  • New ActionBar.Label component: Create sections in your action bar with the new <ActionBar.Label> component.

Highlights

New drag-and-drop engine

Our flagship feature is a new drag-and-drop engine for Puck with full CSS grid & flexbox support to enable advanced layouts. We call these fluid layouts, and they are fully backwards compatible.

Thanks to @clauderic at dnd-kit for all the support in making this possible, and the Puck community for all the feedback! 🙏

Fluid layouts

To implement a fluid layout, add your display property of choice (e.g. display: flex) to your DropZone via the style or className props and off you go—Puck will gracefully handle drag-and-drop across all dimensions.

const config = {
  components: {
    Example: {
      render: () => (
        <DropZone
          zone="my-content"
          style={{ display: "flex" }} // Use flexbox in this DropZone
        />
      ),
    },
    Card: {
      render: ({ text }) => (
        <div>{text}</div>
      ),
    },
  },
};

dragging items in a fluid layout with flexbox

See the Multi-column Layouts docs for the full documentation.

Remove wrapping elements

The new inline and dragRef APIs enable you to remove the wrapping element from Puck components entirely, which can be useful if you need to treat your component as a direct descendant of its parent (such as if you need to use CSS properties like flex-grow).

Here's an example implementing an advanced grid layout, where the children can specify their position using the grid-column and grid-row properties:

const config = {
  components: {
    Example: {
      render: () => (
        <DropZone
          zone="my-content"
          style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" }} // Use CSS grid in this DropZone
        />
      ),
    },
    Card: {
      inline: true, // Enable inline mode, removing the Puck wrapper
      render: ({ text, puck }) => (
        <div
          ref={puck.dragRef} // Let Puck know this element is draggable
          style={{ gridColumn: `span ${spanCol}`, gridRow: `span ${spanRow}` }} // Apply styles
        >
          {text}
        </div>
      ),
    },
  },
};

Advanced grid example

Dragging between nested DropZones

The new engine makes it possible to drag between nested DropZones, which resolves one of the longest standing limitations of Puck's drag-and-drop experience.

dragging-between-nested-components

Dynamic DropZone height

DropZones now shrink to the height of their children so that the preview is a faithful representation of the final output, with a new configurable height when empty.

<DropZone
  zone="my-content"
  minEmptyHeight={256} // The DropZone will grow to 256px when empty
/>

Dynamic DropZone resize

The <ActionBar.Label> component

The new <ActionBar.Label> component enables you to to label areas within a custom ActionBar:

<ActionBar>
  <ActionBar.Label label="Label 1" />
  <ActionBar.Group>
    <ActionBar.Label label="Label 2" />
    <ActionBar.Action></ActionBar.Action>
  </ActionBar.Group>
</ActionBar>
image

Parent selector

A new action allows you to quickly select the component's parent directly from the action bar. Tap the arrow to the left of the component label to jump to the parent.

parent-selector

Toggle interactive hotkey

Make your components interactive directly within Preview mode with the cmd+i (or ctrl+i on Windows) hotkey.

This can be programatically set via the new previewMode parameter on the app state.

No more position:fixed

We've removed this pesky style from the default layout so it's easier to embed in your app. Not much to show here, but let's pour one out for position:fixed 🥂

Breaking changes

Drawer direction no longer has any effect

The direction prop on Drawer no longer has any effect. Instead, use it to wrap a div with your chosen display mode:

<Drawer>
  <div style={{ display: "flex" }}>
    <Drawer.Item name="Orange" />
  </div>
</Drawer>

DropZones are consistently wrapped in a div

Previously, DropZones were only wrapped in a div within the editor (<Puck>) environment, whereas the render (<Render>) environment used a fragment. This could result in unexpected rendering differences between environments.

Now, both environments use a div. If you were relying on the render environment behaving like a Fragment, you may need to adjust your styles. This can be done by applying your styles directly to the DropZone.

Before

<div style={{ display: "flex" }}>
  <DropZone zone="my-zone"> {/* Previously rendered as a fragment in <Render>, but div in <Puck> */}
    <div>Item 1</div>
    <div>Item 2</div>
  </DropZone>
</div> 

After

<DropZone zone="my-zone" style={{ display: "flex" }}> {/* Now consistently renders as a div - apply your styles or class directly */}
  <div>Item 1</div>
  <div>Item 2</div>
</DropZone>

Deprecations

  • The index prop on Drawer.Item is no longer required and will be removed in a future version.
  • The droppableId prop on Drawer is no longer required and will be removed in a future version.

Full changelog

Features

  • add action to select parent component to ActionBar (7c910d5)
  • add ActionBar.Label component for adding labels to action bars (d2645fd)
  • add DropZone collisionAxis API for forcing collision direction (ba68732)
  • add meta+i hotkey and previewMode state to toggle interactivity (ec1eba5)
  • add wrapFields prop to control padding of fields in Puck.Fields (30f9a92)
  • control empty DropZone height with minEmptyHeight prop (96f8340)
  • deselect item on viewport change (e35585d)
  • forward the ref to the DropZone component (676aa1c)
  • introduce new drag-and-drop engine (6ebb3b8)
  • reduce DropZone to height of items unless empty (2b2595a)
  • remove position: fixed; from Puck layout (5deb774)
  • support inline Drawers, deprecating unnecessary props (f93b71e)

Bug Fixes

Read more

v0.17.4

19 Jan 12:20
Compare
Choose a tag to compare

Bug Fixes

  • handle null when provided to text/textarea/number fields (e778246)
  • improve stability of resolveFields API (5c60d6a)
  • respect DropZone allow prop for existing items (e414e34)

Full Changelog: v0.17.3...v0.17.4

v0.17.3

13 Jan 12:38
Compare
Choose a tag to compare

Bug Fixes

Full Changelog: v0.17.2...v0.17.3

0.17.2

10 Jan 20:04
Compare
Choose a tag to compare

Bug Fixes

  • always respect history hotkeys inside iframes (1134e8b)
  • clear old readOnly data when running resolveData (3e91adc)
  • don't trigger move action if source / destination the same (8a0b811)
  • ensure parent is not null on first render in resolveFields (773a81a)
  • factor in border when setting viewport size (cc3b3b8)
  • fix plugin-emotion-cache style sync when using initialData (ac8679c)
  • fix readOnly behaviour in nested fields (f6ab512)
  • remove unnecessary transpile from next recipe (a5f2d08)
  • respect min/max for freeform input in number field (715710a)
  • use correct label for array and object subfields (c00ea00)

Full Changelog: v0.17.1...v0.17.2

v0.17.1

18 Dec 16:46
Compare
Choose a tag to compare

Bug Fixes

  • respect falsey booleans types in select/radio fields (3406b01)

New Contributors

Full Changelog: v0.17.0...v0.17.1

v0.17.0

18 Dec 15:28
Compare
Choose a tag to compare

Puck v0.17.0 adds support for React 19, improves various field APIs and squashes some bugs.

This is our final feature release of the year! We're delaying the new drag-and-drop engine release until January while we iron out the last few kinks. Happy holidays, and thanks for being a wonderful community 🎄

TLDR

  • React 19 support: We've made React 19 support official by adding it to the supported list of peer dependencies.
  • Next.js 15: Upgraded the next recipe to use Next 15.1 and React 19 by default.
  • New external field APIs: External fields now support react elements as rows, and a custom footer, enabling much more customization. Thanks to @camhammel for these improvements!
  • Duplicate array items: Added a new action to the array field so you can easily duplicate array items. Thank you @siarhei-zharnasek 🙏
  • resolveFields enhancement: You can now access the DropZone parent data when using the resolveFields API, enabling you to customize the fields based on the container's type or props.

Highlights

React 19 support

We've made React 19 support official by adding it to the supported list of peer dependencies. It turns out that earlier versions of Puck already play well with React 19, you don't need to upgrade Puck to use React 19 if you don't want to.

Next 15

The official next recipe now uses Next 15.1 and React 19 by default. If you're using the recipe and want to upgrade, make sure you also upgrade to React 19 as required by Next 15 when using the App Router. See the official Next.js upgrade guide for more info.

New external field APIs

The mapRow API now supports react elements, making it possible to add richer content to your external field table:

{
  type: "external",
  fetchList: async () => {
    return [
      { title: "Hello, world", imgUrl: "https://example.com/img.jpg" },
      { title: "Goodbye, world", imgUrl: "https://example.com/img.jpg" },
    ];
  },
  mapRow: (item) => ({ ...item, imgUrl: <img src={item.imgUrl} /> }),
}

And the new renderFooter API enables you to customise the footer of your external field modal.

{
  type: "external",
  fetchList: async () => {
    return [
      { title: "Hello, world" },
      { title: "Goodbye, world" },
    ];
  },
  renderFooter: ({ items }) => (
    <b>Custom footer with {items.length} results</b>
  ),
}

Duplicate array items

A new action in the array field allows you to easily duplicate array items.

Cursor clicking the array item duplicate icon button, and the item duplicating, on loop

Access parent data in resolveFields

The new parent param on the resolveFields API enables you to configure your fields based on the props of the parent item when using DropZones.

Here's an example that shows a field called flex when the parent component has a display prop of "flex":

const config = {
  components: {
    MyComponent: {
      resolveFields: (data, { fields, parent }) => {
        if (parent.props.display === "flex") {
          return {
            ...fields,
            flex: {
              type: "radio",
              options: [
                { label: "Grow", value: "grow" },
                { label: "Shrink", value: "shrink" },
              ],
            }
          }
        }
      
        return fields;
      },
      // ...
    },
  },
};

Full changelog

Features

  • add duplicate action to array field (229cbdd)
  • add renderFooter API to external field (ccec96e)
  • allow react elements in external field mapRow (2f781de)
  • enable resolveFields to access parent data (196227b)
  • list React 19 as supported peer dependency (85e8cc1)
  • track focused field in app state (91bc97a)
  • upgrade next recipe to v15.1 (8ef51c5)
  • use React 19 in next recipe (6b3d97f)

Bug Fixes

  • always run field resolvers when item change (159d819)
  • always update fields when resolveData runs (39dd619)
  • ensure radio fields are functional inside arrays (7736294)
  • prevent field name collision causing hook render mismatch (b51954a)
  • prevent flicker when using resolveData with arrays (1be9b88)
  • provide better error when usePuck used inappropriately (9991c07)
  • remove leading zeros in Number field (5ba9399)
  • respect original value type in radio and select fields (00ccd1d and 6e5864a)

New Contributors

Full Changelog: v0.16.2...v0.17.0

v0.16.2

07 Nov 19:12
Compare
Choose a tag to compare

Bug Fixes

  • always treat data as immutable, fixing Redux issues (51154e9)
  • don't crash if component definition missing (525b506)
  • don't crash when selecting component with no config (cb90f5d), closes #671
  • export missing resolveAllData lib in RSC bundle (2f5fb7b)
  • fix RTL styles in action bar overlay (bf5c5a3)
  • remove internal AutoField and FieldLabel components from bundle (5df1597)
  • remove unused label from AutoField type (18b6f1a)

New Contributors

Full Changelog: v0.16.1...v0.16.2

v0.16.1

07 Oct 21:37
Compare
Choose a tag to compare

Bug Fixes

  • don't delete array field on click in FieldLabel (ed282b9)
  • don't overwrite user input when field recently changed (6126040)
  • don't show field loader if no resolver defined (8c706cd)
  • hide ActionBar.Group border when empty (4345165)
  • prevent item click before iframe load (61e1653)
  • prevent flash of field loader when no data changed (20d7309)
  • respect readOnly styles in AutoField (9ffe817)

Full Changelog: v0.16.0...v0.16.1