DEV Community

Chris Villa for Measured

Posted on • Edited on • Originally published at measured.co

Puck 0.15: Dynamic fields

Puck v0.15 introduces powerful new field APIs and numerous quality-of-life features.

  1. Dynamic fields: Use the resolveFields API to dynamically define your fields - great for showing fields conditionally or loading external APIs.
  2. AutoField component: Build custom fields using Puck's own field component for a seamless UI.
  3. Override the Publish button: Swap out the publish button without swapping out the entire header.
  4. Context-aware components: Modify component behaviour based on whether it's inside <Puck> or <Render>.

Upgrade today or get started with:

npx create-puck-app@latest
Enter fullscreen mode Exit fullscreen mode

Dynamic fields

Dynamic field resolution via the resolveFields API allows you to change the field configuration whenever the props change. You can use this to show and hide fields or even load data from an API.

Code example:

const config = {
  components: {
    MyComponent: {
      // ...
      resolveFields: (data) => ({
        myField: {
          type: "radio",
          options: [],  // Populate dynamically
        },
      }),
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

AutoField component

The AutoField component lets you render a Puck field based on a Field object. Use this when building custom fields that need to use Puck-style fields internally.

const CustomField = ({ onChange, value }) => (
  <AutoField field={{ type: "text" }} onChange={onChange} value={value} />
);
Enter fullscreen mode Exit fullscreen mode

Override the Publish button

It's now possible to implement a custom Publish button without overriding the entire header by using the headerActions override.

<Puck
  overrides={{
    headerActions: ({ children }) => (
      <>
        {/* children will render default Publish button */}
        {children}
        {/* Or you can define your own */}
        <button>Click me</button>
      </>
    ),
  }}
/>;
Enter fullscreen mode Exit fullscreen mode

This creates a breaking change for existing headerActions overrides, which will now need to render children to show the default Publish button.

Context-aware components

Components now receive the puck.isEditing prop. Use this to toggle functionality based on whether the component is being rendered in the <Puck> or <Render> context.

const config = {
  components: {
    MyComponent: {
      render: ({ puck }) => (
        <div style={{ background: puck.isEditing ? "hotpink" : "transparent" }}>
          Hello, world
        </div>
      ),
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Breaking changes & deprecations

headerActions override must now render {children} (BREAKING CHANGE)

In order to support custom Publish buttons, the headerActions override will no longer render the default Publish button unless children are rendered.

<Puck
  overrides={{
    headerActions: ({ children }) => (
      <>
        {/* Render default Publish button */}
        {children}
      </>
    ),
  }}
/>;
Enter fullscreen mode Exit fullscreen mode

Undocumented editMode API deprecated

The undocumented editMode prop is now deprecated in favor of puck.isEditing.

Full Changelog

Features

  • add AutoField component for using Puck fields inside custom fields (106028b)
  • add isEditing flag to puck object prop (13bb1bd)
  • add resolveFields API for dynamic fields (0a18bdb)
  • allow data prop to accept an empty object (aedd401)
  • bump next recipe to Next@14 (47a27ed)
  • enable override of publish button (breaking change) (480467a)
  • expose previous data to resolveData via lastData param (dd7051e)
  • replace history chevrons with undo/redo icons (91dff22)

Bug Fixes

  • align Drawer behaviour and docs with expectation (e2cd445)
  • animate loader in iframe (151a267)
  • don't inline link stylesheets for more predictable behaviour (c0a331d)
  • don't overflow external inputs inside arrays/objects (42ef582)
  • don't throw warning when user is correctly specifying root props (46aa8ff)
  • don't unintentionally use read-only styles in external fields (acaf727)
  • fix defaultProps for root (9a1cc7c)
  • infer correct value types in Custom fields (5c8c0e1)
  • position field loader relative to sidebar, not fields (2e8936e)
  • show external field modal when using custom interfaces (6e97a0e)
  • show field loader when using field overrides (8ccfa4c)
  • still load iframe if styles fail to load (3e56bc1)

See the GitHub release for the full changelog.

Community

We're grateful for the community's support and contributions. Join the conversation on GitHub and Discord.

Contributors

A huge thanks to all our existing and new contributors:

Top comments (0)