<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Chris Villa</title>
    <description>The latest articles on Forem by Chris Villa (@chrisvxd).</description>
    <link>https://forem.com/chrisvxd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153172%2Fe55c2d51-1876-4ee6-962b-ffb111debab2.jpeg</url>
      <title>Forem: Chris Villa</title>
      <link>https://forem.com/chrisvxd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chrisvxd"/>
    <language>en</language>
    <item>
      <title>Puck 0.19: Slots API &amp; performance gains</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Tue, 10 Jun 2025 10:17:15 +0000</pubDate>
      <link>https://forem.com/puckeditor/puck-019-slots-api-performance-gains-1eik</link>
      <guid>https://forem.com/puckeditor/puck-019-slots-api-performance-gains-1eik</guid>
      <description>&lt;p&gt;Puck 0.19 introduces the &lt;a href="https://puckeditor.com/docs/api-reference/fields/slot?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Slots API&lt;/a&gt;, the powerful successor to DropZones that lets you nest components using a field. This new approach allows you to define drop areas and their content programmatically using &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#defaultprops?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;defaultProps&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#resolvedatadata-params?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;resolveData&lt;/code&gt;&lt;/a&gt;, enabling sophisticated patterns like component templates:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvh579sasp9okvv0cs04s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvh579sasp9okvv0cs04s.gif" alt="The Puck demo showcasing the template pattern" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to Slots, this release brings major performance improvements, a new metadata API for passing data into every component, and many quality-of-life upgrades.&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through everything new in Puck 0.19 and how to start using it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's new in Puck 0.19&lt;/li&gt;
&lt;li&gt;Other changes&lt;/li&gt;
&lt;li&gt;How to upgrade&lt;/li&gt;
&lt;li&gt;Full changelog&lt;/li&gt;
&lt;li&gt;Contributors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're upgrading from a previous version, be sure to check the &lt;a href="https://puckeditor.com/blog/upgrading-to-puck-019?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt; for breaking changes and migration tips. &lt;/p&gt;

&lt;p&gt;You can also find detailed docs for each new feature in our &lt;a href="https://puckeditor.com/docs?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new in Puck 0.19
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Slots API
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/fields/slot?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;slots API&lt;/a&gt; is a new field type you can use to render drop zones and nest components, replacing the &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;DropZone API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It works like any other field: you define it in your &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;component config&lt;/a&gt;, and get access to its value in the component &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#renderprops?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;render&lt;/code&gt;&lt;/a&gt; function. The slot field is converted to a component that you can use to render the drop zone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Flexbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gekk8md9flj1on7f2kn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gekk8md9flj1on7f2kn.gif" alt="Flexbox component with slots" width="899" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The slot component provided to the render function accepts most of the same props as the &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;DropZone /&amp;gt;&lt;/code&gt;&lt;/a&gt; component, making migration straightforward. See the &lt;a href="https://puckeditor.com/docs/api-reference/fields/slot#render-function?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;slots documentation&lt;/a&gt; for a full breakdown of all available render props.&lt;/p&gt;

&lt;p&gt;The components inside a slot are stored within the props of the parent component as an array of &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;ComponentData&lt;/code&gt;&lt;/a&gt;, making slots completely portable and straightforward to work with for data transformation or schema validation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Flexbox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"props"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Flexbox-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Header-2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nested header"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since slots are regular fields, you can take full advantage of other field APIs, like &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#defaultprops?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;defaultProps&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#resolvedatadata-params?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;resolveData&lt;/code&gt;&lt;/a&gt;, to programmatically set the components they contain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Flexbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="c1"&gt;// Include a Header in this slot when the Flexbox is added to the page&lt;/span&gt;
      &lt;span class="na"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Items&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr0kosd1wf0madz4skhs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr0kosd1wf0madz4skhs.gif" alt="Flexbox component with default props for slot fields" width="899" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slots are now the recommended way to handle nested components in Puck. The &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;DropZone&lt;/code&gt;&lt;/a&gt; component has been deprecated and will be removed in a future release. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep in mind: &lt;em&gt;slots introduce a new model for representing components&lt;/em&gt;. Existing &lt;code&gt;DropZone&lt;/code&gt; data, and advanced use-cases that parse or manipulate the Puck &lt;a href="https://puckeditor.com/docs/api-reference/data-model/data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;data payload&lt;/a&gt; may need to be updated. You can find guidance on how to migrate from DropZones to Slots in the &lt;a href="https://puckeditor.com/blog/upgrading-to-puck-019?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  New function: &lt;code&gt;walkTree&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The new &lt;a href="https://puckeditor.com/docs/api-reference/functions/walk-tree?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;walkTree&lt;/code&gt;&lt;/a&gt; utility recursively walks all slots in the entire tree of the &lt;a href="https://puckeditor.com/docs/api-reference/data-model/data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;data payload&lt;/a&gt; or a single &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;ComponentData&lt;/code&gt;&lt;/a&gt; node, and optionally modifies the nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;walkTree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@measured/puck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transformedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;walkTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nestedComponents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Add the "example" prop to all children&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;nestedComponents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Selectors for &lt;code&gt;usePuck&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Puck 0.19 introduces &lt;a href="https://puckeditor.com/docs/api-reference/functions/use-puck#selectordata?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;selectors&lt;/a&gt; for &lt;a href="https://puckeditor.com/docs/api-reference/functions/use-puck?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;usePuck&lt;/code&gt;&lt;/a&gt;, letting you subscribe to the parts of the internal &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Puck API&lt;/a&gt; you need in order to avoid unnecessary re-renders. To use selectors, use the new &lt;code&gt;createUsePuck&lt;/code&gt; helper, and pick which part of the &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;API&lt;/a&gt; you want to listen to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createUsePuck&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@measured/puck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usePuck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUsePuck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LeftSideBarButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Will only re-render when closing or opening the left sidebar&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePuck&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leftSideBarVisible&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOpen&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original &lt;code&gt;usePuck&lt;/code&gt; hook is still available and won’t be deprecated.&lt;/p&gt;

&lt;p&gt;For a breakdown of how selectors compare with the original &lt;code&gt;usePuck&lt;/code&gt;, check out the &lt;a href="https://puckeditor.com/blog/upgrading-to-puck-019?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  New hook: &lt;code&gt;useGetPuck()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To make it possible to access the internal &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Puck API&lt;/a&gt; outside of the render lifecycle, we've added a new hook called &lt;a href="https://puckeditor.com/docs/api-reference/functions/use-get-puck?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;useGetPuck()&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGetPuck&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@measured/puck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SaveDataButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPuck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetPuck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Access the latest appState only when the button gets clicked&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPuck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;saveData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;getPuck&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save your page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useGetPuck&lt;/code&gt; returns a function that can be called to fetch the latest &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Puck API&lt;/a&gt; without triggering re-renders.&lt;/p&gt;

&lt;p&gt;For a breakdown of how &lt;code&gt;useGetPuck&lt;/code&gt; compares with the original &lt;code&gt;usePuck&lt;/code&gt;, check out the &lt;a href="https://puckeditor.com/blog/upgrading-to-puck-019?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metadata API
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This was a contribution made by: &lt;a href="https://github.com/jsjexpert" rel="noopener noreferrer"&gt;@jsjexpert&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#puckmetadata?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;metadata API&lt;/a&gt; lets you inject data into every component within your config, without relying on context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;pageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;puck&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Page ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;puck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt; &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metadata can also be accessed within &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#resolvedatadata-params?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;resolveData&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;pageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1234&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolveData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Page ID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt; &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New recipe: &lt;code&gt;react-router&lt;/code&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This was a contribution made by: &lt;a href="https://github.com/matthewlynch" rel="noopener noreferrer"&gt;@matthewlynch&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This version also includes a recipe for using Puck with the &lt;a href="https://reactrouter.com/start/framework/installation" rel="noopener noreferrer"&gt;react-router framework&lt;/a&gt;, so you can scaffold new projects with everything pre-configured.&lt;/p&gt;

&lt;p&gt;To use it, run &lt;code&gt;create-puck-app&lt;/code&gt; and enter &lt;code&gt;react-router&lt;/code&gt; when asked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx create-puck-app my-app

&lt;span class="c"&gt;# Type "react-router"&lt;/span&gt;
? Which recipe would you like to use? react-router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Improved performance
&lt;/h3&gt;

&lt;p&gt;A big focus for this release was performance. Puck 0.19 drastically reduces the number of unnecessary re-renders, making the editor significantly faster and smoother, especially in larger projects.&lt;/p&gt;

&lt;p&gt;To demonstrate this, we compared rendering times for common actions in 0.19 vs 0.18.3 using Puck with a test page containing 20 &lt;code&gt;HeadingBlock&lt;/code&gt; components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;HeadingBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These were the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobbokdoiw4kfeewn1d7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobbokdoiw4kfeewn1d7x.png" alt="0.19 vs 0.18.3 rendering times comparison for standard puck actions in milliseconds" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inserting a &lt;code&gt;HeadingBlock&lt;/code&gt; was &lt;strong&gt;82% faster&lt;/strong&gt; in 0.19.&lt;/li&gt;
&lt;li&gt;Replacing a &lt;code&gt;HeadingBlock&lt;/code&gt; prop was &lt;strong&gt;91% faster&lt;/strong&gt; in 0.19.&lt;/li&gt;
&lt;li&gt;Reordering a &lt;code&gt;HeadingBlock&lt;/code&gt; was &lt;strong&gt;79% faster&lt;/strong&gt; in 0.19.&lt;/li&gt;
&lt;li&gt;Deleting a &lt;code&gt;HeadingBlock&lt;/code&gt; was &lt;strong&gt;63% faster&lt;/strong&gt; in 0.19.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getters for item selectors
&lt;/h3&gt;

&lt;p&gt;The internal &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Puck API&lt;/a&gt; (accessed with &lt;code&gt;usePuck&lt;/code&gt; and &lt;code&gt;useGetPuck&lt;/code&gt;) now includes a set of utilities to get &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;component data&lt;/a&gt; from within the tree. These are useful when working with slots.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/puck-api#getitembyselectorselector?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;getItemBySelector&lt;/code&gt;&lt;/a&gt; gets an item’s &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;ComponentData&lt;/code&gt;&lt;/a&gt; by &lt;a href="https://puckeditor.com/docs/api-reference/data-model/item-selector?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;selector&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/puck-api#getitembyidid?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;getItemById&lt;/code&gt;&lt;/a&gt; gets an item’s &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;ComponentData&lt;/code&gt;&lt;/a&gt; by &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data#props?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;component id&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/puck-api#getselectorforidid?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;getSelectorForId&lt;/code&gt;&lt;/a&gt; gets an item’s &lt;a href="https://puckeditor.com/docs/api-reference/data-model/item-selector?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;selector&lt;/a&gt; by &lt;a href="https://puckeditor.com/docs/api-reference/data-model/component-data#props?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;component id&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;getItemBySelector&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// The item is in the "children" slot field of the component with id "Flex-123"&lt;/span&gt;
  &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flex-123:children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Returns: { type: "HeadingBlock", props: {...} }&lt;/span&gt;

&lt;span class="nf"&gt;getItemById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HeadingBlock-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Returns: { type: "HeadingBlock", props: {...} }&lt;/span&gt;

&lt;span class="nf"&gt;getSelectorForId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HeadingBlock-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Returns: { index: 0, zone: "Flex-123:children" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Trigger event in resolveData
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#resolvedatadata-params?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;resolveData&lt;/code&gt;&lt;/a&gt; now receives a trigger parameter that tells you why it ran, whether it was because Puck was loaded ("load"), the component was dropped in the canvas (”insert”), props were updated ("replace"), or you forced it via &lt;a href="https://puckeditor.com/docs/api-reference/functions/resolve-all-data?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;resolveAllData&lt;/code&gt;&lt;/a&gt; ("force").&lt;/p&gt;

&lt;p&gt;This gives you more control over how and when your data is resolved, so you can skip unnecessary fetches or run specific logic depending on the event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolveData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Resolve and add the title only when the Header is first dropped in&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trigger&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvedTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resolvedTitle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Custom label icons for fields
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This was a contribution made by: &lt;a href="https://github.com/DamianKocjan" rel="noopener noreferrer"&gt;@DamianKocjan&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now provide your own icons for field labels by passing a React node to the new &lt;a href="https://puckeditor.com/docs/api-reference/fields/base#labelicon?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;labelIcon&lt;/code&gt;&lt;/a&gt; config parameter. If you're using the &lt;a href="https://puckeditor.com/docs/api-reference/components/field-label?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;FieldLabel&lt;/code&gt;&lt;/a&gt; component directly, you can provide the icon via the &lt;a href="https://puckeditor.com/docs/api-reference/components/field-label#icon?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;icon&lt;/code&gt;&lt;/a&gt; prop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TextCursor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucide-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;labelIcon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextCursor&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u4q4v1kolocvd5y8gov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u4q4v1kolocvd5y8gov.png" alt="A Puck text field with a custom Lucide " width="362" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Field placeholders
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This was a contribution made by: &lt;a href="https://github.com/DamianKocjan" rel="noopener noreferrer"&gt;@DamianKocjan&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fields now support &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/placeholder" rel="noopener noreferrer"&gt;placeholders&lt;/a&gt; for &lt;a href="https://puckeditor.com/docs/api-reference/fields/text#placeholder?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;text&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://puckeditor.com/docs/api-reference/fields/textarea#placeholder?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;textarea&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://puckeditor.com/docs/api-reference/fields/number#placeholder?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;number&lt;/code&gt;&lt;/a&gt; fields.&lt;/p&gt;

&lt;p&gt;To provide a placeholder, define the &lt;code&gt;placeholder&lt;/code&gt; config parameter with the text you want to show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;CompanyInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your company name here...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5ba3jxj62t2gopuv1o9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5ba3jxj62t2gopuv1o9.png" alt="A Puck text field with the placeholder: " width="361" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step size for number fields
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This was a contribution made by: &lt;a href="https://github.com/shannonhochkins" rel="noopener noreferrer"&gt;@shannonhochkins&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now define a step value for &lt;a href="https://puckeditor.com/docs/api-reference/fields/number#step?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;number&lt;/code&gt;&lt;/a&gt; fields to control how much the value increases or decreases when using the input or keyboard arrow buttons. See &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/step" rel="noopener noreferrer"&gt;&lt;code&gt;step&lt;/code&gt;&lt;/a&gt; on MDN.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;EmptySpace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscvwl3a4n2vlxyt1bump.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscvwl3a4n2vlxyt1bump.gif" alt="A Puck number field with a step size of two" width="363" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiding fields
&lt;/h3&gt;

&lt;p&gt;It's now possible to hide fields from the UI by setting the &lt;a href="https://puckeditor.com/docs/api-reference/fields/base#visible?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;visible&lt;/code&gt;&lt;/a&gt; field parameter to &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;hiddenField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hiddenField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The field of this value is hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hiddenField&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hiddenField&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcwgkyakmfcv56iyq3cq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcwgkyakmfcv56iyq3cq.gif" alt="A Puck component with a hidden text field" width="805" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New &lt;code&gt;RootConfig&lt;/code&gt; type
&lt;/h3&gt;

&lt;p&gt;The new &lt;a href="https://github.com/measuredco/puck/blob/638e066fb655bc3e258093bf2428189f3afd88f9/packages/core/types/Config.tsx#L69" rel="noopener noreferrer"&gt;&lt;code&gt;RootConfig&lt;/code&gt;&lt;/a&gt; type lets you type your &lt;a href="https://puckeditor.com/docs/api-reference/configuration/config#root?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;root configuration&lt;/a&gt; with its expected props when using TypeScript. If you've broken up your config, this'll help you keep everything type-safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RootConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@measured/puck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rootConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RootConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;defaultProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My Page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  New &lt;code&gt;replaceRoot&lt;/code&gt; action
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;replaceRoot&lt;/code&gt; action is now available in the &lt;a href="https://puckeditor.com/docs/api-reference/puck-api?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;Puck API&lt;/a&gt; &lt;a href="https://puckeditor.com/docs/api-reference/puck-api#dispatchaction?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;&lt;code&gt;dispatcher&lt;/code&gt;&lt;/a&gt;, making it possible to update only the &lt;a href="https://puckeditor.com/docs/api-reference/data-model/data#root?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;root&lt;/a&gt; data without using an expensive &lt;code&gt;set&lt;/code&gt; action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGetPuck&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@measured/puck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RootTitleSetter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPuck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetPuck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the dispatcher&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPuck&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Dispatch the action to update the root&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;replaceRoot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;rootData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New Title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;getPuck&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Set Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to upgrade
&lt;/h2&gt;

&lt;p&gt;Check out the &lt;a href="https://puckeditor.com/blog/upgrading-to-puck-019?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=0_19_release_post" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt; for step-by-step instructions on upgrading to 0.19. It includes deprecated APIs, breaking changes, and common pitfalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full changelog
&lt;/h2&gt;

&lt;p&gt;See the full changelog for all changes via the &lt;a href="https://github.com/measuredco/puck/releases/tag/0.19.0" rel="noopener noreferrer"&gt;GitHub release&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/artemisclyde" rel="noopener noreferrer"&gt;artemisclyde&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/camhammel" rel="noopener noreferrer"&gt;camhammel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chillenberger" rel="noopener noreferrer"&gt;chillenberger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/christian-tchaikovsky" rel="noopener noreferrer"&gt;christian-tchaikovsky&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/DamianKocjan" rel="noopener noreferrer"&gt;DamianKocjan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/leweyse" rel="noopener noreferrer"&gt;leweyse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lukstei" rel="noopener noreferrer"&gt;lukstei&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/matthewlynch" rel="noopener noreferrer"&gt;matthewlynch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shannonhochkins" rel="noopener noreferrer"&gt;shannonhochkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/theophilhenry" rel="noopener noreferrer"&gt;theophilhenry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tlahmann" rel="noopener noreferrer"&gt;tlahmann&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>puck</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Thu, 27 Mar 2025 10:12:51 +0000</pubDate>
      <link>https://forem.com/chrisvxd/-2jmb</link>
      <guid>https://forem.com/chrisvxd/-2jmb</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/how-to-build-a-react-page-builder-puck-and-tailwind-v40-5e3o" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to Build a React Page Builder: Puck and Tailwind v4.0&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Mar 26&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>frontend</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Thu, 20 Mar 2025 10:59:51 +0000</pubDate>
      <link>https://forem.com/chrisvxd/-1bi7</link>
      <guid>https://forem.com/chrisvxd/-1bi7</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/integrating-a-page-builder-with-contentful-3ik" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Integrating a Page Builder with Contentful&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Mar 20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cms&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>cms</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Thu, 20 Feb 2025 13:55:37 +0000</pubDate>
      <link>https://forem.com/chrisvxd/-4mdn</link>
      <guid>https://forem.com/chrisvxd/-4mdn</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/top-5-drag-and-drop-libraries-for-react-24lb" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Top 5 Drag-and-Drop Libraries for React&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Feb 20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>frontend</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Fri, 14 Feb 2025 18:08:37 +0000</pubDate>
      <link>https://forem.com/chrisvxd/-3hg</link>
      <guid>https://forem.com/chrisvxd/-3hg</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/advanced-layouts-with-puck-018-harnessing-grid-and-flex-containers-o42" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Advanced Layouts with Puck 0.18: Harnessing Grid and Flex Containers&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Feb 14&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Wed, 12 Feb 2025 10:03:58 +0000</pubDate>
      <link>https://forem.com/chrisvxd/-10mg</link>
      <guid>https://forem.com/chrisvxd/-10mg</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/fede_bonel_tozzi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="fede_bonel_tozzi"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/fede_bonel_tozzi/top-5-page-builders-for-react-190g" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Top 5 Page Builders for React&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi ・ Feb 8&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cms&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>cms</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Puck 0.18: New drag-and-drop engine</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Wed, 22 Jan 2025 12:47:25 +0000</pubDate>
      <link>https://forem.com/puckeditor/puck-018-new-drag-and-drop-engine-3h2o</link>
      <guid>https://forem.com/puckeditor/puck-018-new-drag-and-drop-engine-3h2o</guid>
      <description>&lt;p&gt;&lt;em&gt;Puck is the open-source visual editor for React, powering the next generation of page builders and no-code products. Give us a star on &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! ⭐️&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/measuredco/puck/releases/" rel="noopener noreferrer"&gt;Puck 0.18&lt;/a&gt; launches a groundbreaking new drag-and-drop engine for page building with advanced CSS layouts.&lt;/p&gt;

&lt;p&gt;With native support for CSS grid and flexbox, &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;Puck 0.18&lt;/a&gt; enables powerful new paradigms for creating design-in-browser experiences directly within your React application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft09jk8jgso0x4hqt8i7t.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft09jk8jgso0x4hqt8i7t.gif" alt="New drag-and-drop engine" width="1200" height="905"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New drag-and-drop engine&lt;/strong&gt;: Multi-dimensional drag-and-drop across any CSS layout to create a sophisticated page building experience. &lt;a href="https://puckeditor.com/docs/integrating-puck/multi-column-layouts" rel="noopener noreferrer"&gt;Read the docs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic DropZone height&lt;/strong&gt;: DropZones now shrink to the height of their children, with a &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone#minemptyheight" rel="noopener noreferrer"&gt;configurable height&lt;/a&gt; when empty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toggle interactive hotkey&lt;/strong&gt;: Make your components interactive in Preview mode with the &lt;code&gt;cmd+i&lt;/code&gt; hotkey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent selector&lt;/strong&gt;: A new action allows you to quickly select the component's parent directly from the action bar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No more &lt;code&gt;position: fixed&lt;/code&gt;&lt;/strong&gt;: We've removed this pesky style from the default layout so it's easier to embed in your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New ActionBar.Label component&lt;/strong&gt;: Create sections in your action bar with the new &lt;a href="https://puckeditor.com/docs/api-reference/components/action-bar-label" rel="noopener noreferrer"&gt; component&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  New drag-and-drop engine
&lt;/h3&gt;

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

&lt;p&gt;Thanks to &lt;a class="mentioned-user" href="https://dev.to/clauderic"&gt;@clauderic&lt;/a&gt; at &lt;a href="https://github.com/clauderic/dnd-kit/" rel="noopener noreferrer"&gt;dnd-kit&lt;/a&gt; for all the support in making this possible, and the Puck community for all the feedback! 🙏 &lt;/p&gt;

&lt;h4&gt;
  
  
  Fluid layouts
&lt;/h4&gt;

&lt;p&gt;To implement a fluid layout, add your display property of choice (e.g. &lt;code&gt;display: flex&lt;/code&gt;) to your DropZone via the &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone#style" rel="noopener noreferrer"&gt;&lt;code&gt;style&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone#classname" rel="noopener noreferrer"&gt;&lt;code&gt;className&lt;/code&gt;&lt;/a&gt; props and off you go—Puck will gracefully handle drag-and-drop across all dimensions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt;
          &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-content"&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Use flexbox in this DropZone&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rpvm74iop60tgrrt83i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rpvm74iop60tgrrt83i.gif" alt="dragging items in a fluid layout with flexbox" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://puckeditor.com/docs/integrating-puck/multi-column-layouts" rel="noopener noreferrer"&gt;Multi-column Layouts docs&lt;/a&gt; for the full documentation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remove wrapping elements
&lt;/h4&gt;

&lt;p&gt;The new &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#inline" rel="noopener noreferrer"&gt;&lt;code&gt;inline&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://puckeditor.com/v/canary/docs/api-reference/configuration/component-config#puckdragref" rel="noopener noreferrer"&gt;&lt;code&gt;dragRef&lt;/code&gt;&lt;/a&gt; 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 &lt;code&gt;flex-grow&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here's an example implementing an advanced grid layout, where the children can specify their position using the &lt;code&gt;grid-column&lt;/code&gt; and &lt;code&gt;grid-row&lt;/code&gt; properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt;
          &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-content"&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gridTemplateColumns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1fr 1fr 1fr 1fr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Use CSS grid in this DropZone&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Enable inline mode, removing the Puck wrapper&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;puck&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;puck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dragRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Let Puck know this element is draggable&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;gridColumn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`span &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;spanCol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gridRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`span &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;spanRow&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Apply styles&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0qdzo6cj1eshzan91jn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0qdzo6cj1eshzan91jn.gif" alt="Advanced grid example" width="1440" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Dragging between nested DropZones
&lt;/h4&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2ae87gp529ba2mdhact.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2ae87gp529ba2mdhact.gif" alt="dragging-between-nested-components" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic DropZone height
&lt;/h3&gt;

&lt;p&gt;DropZones now shrink to the height of their children so that the preview is a faithful representation of the final output, with a new &lt;a href="https://puckeditor.com/docs/api-reference/components/drop-zone#minemptyheight" rel="noopener noreferrer"&gt;configurable height&lt;/a&gt; when empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt;
  &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-content"&lt;/span&gt;
  &lt;span class="na"&gt;minEmptyHeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// The DropZone will grow to 256px when empty&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn69ni79iazxhjs67m9f4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn69ni79iazxhjs67m9f4.gif" alt="Dynamic DropZone resize" width="768" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;&amp;lt;ActionBar.Label&amp;gt;&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;The new &lt;a href="https://puckeditor.com/docs/api-reference/components/action-bar-label" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;ActionBar.Label&amp;gt;&lt;/code&gt;&lt;/a&gt; component enables you to to label areas within a custom ActionBar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Label&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Label 1"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Label&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Label 2"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;★&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F79f7e5ac-1518-431b-99b6-e5ccdbae56f7" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F79f7e5ac-1518-431b-99b6-e5ccdbae56f7" width="442" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Parent selector
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04omqmkk8kalsltczfi4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04omqmkk8kalsltczfi4.gif" alt="parent-selector" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Toggle interactive hotkey
&lt;/h3&gt;

&lt;p&gt;Make your components interactive directly within Preview mode with the &lt;code&gt;cmd+i&lt;/code&gt; (or &lt;code&gt;ctrl+i&lt;/code&gt; on Windows) hotkey.&lt;/p&gt;

&lt;p&gt;This can be programatically set via the new &lt;a href="https://puckeditor.com/docs/api-reference/app-state" rel="noopener noreferrer"&gt;&lt;code&gt;previewMode&lt;/code&gt; parameter&lt;/a&gt; on the app state.&lt;/p&gt;

&lt;h3&gt;
  
  
  No more &lt;code&gt;position:fixed&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;position:fixed&lt;/code&gt; 🥂&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Drawer &lt;code&gt;direction&lt;/code&gt; no longer has any effect
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;direction&lt;/code&gt; prop on &lt;code&gt;Drawer&lt;/code&gt; no longer has any effect. Instead, use it to wrap a &lt;code&gt;div&lt;/code&gt; with your chosen display mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Drawer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Drawer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Orange"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Drawer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DropZones are consistently wrapped in a div
&lt;/h3&gt;

&lt;p&gt;Previously, DropZones were only wrapped in a div within the editor (&lt;code&gt;&amp;lt;Puck&amp;gt;&lt;/code&gt;) environment, whereas the render (&lt;code&gt;&amp;lt;Render&amp;gt;&lt;/code&gt;) environment used a fragment. This could result in unexpected rendering differences between environments.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Before&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt; &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-zone"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Previously rendered as a fragment in &amp;lt;Render&amp;gt;, but div in &amp;lt;Puck&amp;gt; */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;After&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt; &lt;span class="na"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-zone"&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Now consistently renders as a div - apply your styles or class directly */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DropZone&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deprecations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;index&lt;/code&gt; prop on &lt;code&gt;Drawer.Item&lt;/code&gt; is no longer required and will be removed in a future version.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;droppableId&lt;/code&gt; prop on &lt;code&gt;Drawer&lt;/code&gt; is no longer required and will be removed in a future version.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Full changelog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;add action to select parent component to ActionBar (&lt;a href="https://github.com/measuredco/puck/commit/7c910d5272e8d6d77819ccb3280dff143ea848fd" rel="noopener noreferrer"&gt;7c910d5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add ActionBar.Label component for adding labels to action bars (&lt;a href="https://github.com/measuredco/puck/commit/d2645fd68a57b4c07bb8a3948ab6a845c2ce1988" rel="noopener noreferrer"&gt;d2645fd&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add DropZone collisionAxis API for forcing collision direction (&lt;a href="https://github.com/measuredco/puck/commit/ba687329c6fac5085f78768bff6eb37bfd842f33" rel="noopener noreferrer"&gt;ba68732&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add meta+i hotkey and previewMode state to toggle interactivity (&lt;a href="https://github.com/measuredco/puck/commit/ec1eba58525e0245ee1214f8e401fa935c41fe23" rel="noopener noreferrer"&gt;ec1eba5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add wrapFields prop to control padding of fields in Puck.Fields (&lt;a href="https://github.com/measuredco/puck/commit/30f9a926d2640a5bf9f65d8f4c2b6018e73f8719" rel="noopener noreferrer"&gt;30f9a92&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;control empty DropZone height with minEmptyHeight prop (&lt;a href="https://github.com/measuredco/puck/commit/96f83408f4e6219dd35f5c29b204ef18e6d11d64" rel="noopener noreferrer"&gt;96f8340&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;deselect item on viewport change (&lt;a href="https://github.com/measuredco/puck/commit/e35585d767c857413ed5560f311d64bcab1218c4" rel="noopener noreferrer"&gt;e35585d&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;forward the ref to the DropZone component (&lt;a href="https://github.com/measuredco/puck/commit/676aa1c974bd1260aaa687aa3edc2c54ef34e22b" rel="noopener noreferrer"&gt;676aa1c&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;introduce new drag-and-drop engine (&lt;a href="https://github.com/measuredco/puck/commit/6ebb3b8724b8ed56cc76d3ce166b1dc87ed07dad" rel="noopener noreferrer"&gt;6ebb3b8&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;reduce DropZone to height of items unless empty (&lt;a href="https://github.com/measuredco/puck/commit/2b2595a4e3e1c5ed8352cdfbec704290a1b396e8" rel="noopener noreferrer"&gt;2b2595a&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;remove &lt;code&gt;position: fixed;&lt;/code&gt; from Puck layout (&lt;a href="https://github.com/measuredco/puck/commit/5deb7744c07fca12e6aa44d058b495f65b298eab" rel="noopener noreferrer"&gt;5deb774&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;support inline Drawers, deprecating unnecessary props (&lt;a href="https://github.com/measuredco/puck/commit/f93b71e1ad555184fc1a43f151ef1b161be148c6" rel="noopener noreferrer"&gt;f93b71e&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug Fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;deselect item on delete (&lt;a href="https://github.com/measuredco/puck/commit/f27871b5b63be8246cd281d93c49f7744d7e186f" rel="noopener noreferrer"&gt;f27871b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;improve heading-analyzer reliability (&lt;a href="https://github.com/measuredco/puck/commit/ab6c01862c35e27929b249a6d4bc4d2e9065dc12" rel="noopener noreferrer"&gt;ab6c018&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;never render FieldLabel with padding or borders (&lt;a href="https://github.com/measuredco/puck/commit/a97b54fd9427f3cd587951a0a30a95d56c5ff020" rel="noopener noreferrer"&gt;a97b54f&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent propagation of custom ActionBar actions by default (&lt;a href="https://github.com/measuredco/puck/commit/14909bdc5a782330af661a32bc80ab387ab12897" rel="noopener noreferrer"&gt;14909bd&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent user pollution of ActionBar styles (&lt;a href="https://github.com/measuredco/puck/commit/e154cb7c72c4fce735ccd60ccbdc862314f0ad26" rel="noopener noreferrer"&gt;e154cb7&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;render DropZones the same in Puck and Render (&lt;a href="https://github.com/measuredco/puck/commit/d975aaf90bf7d0956ccf1d6c377a6e20ba224801" rel="noopener noreferrer"&gt;d975aaf&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;reset resolveFields lastFields param when changing component (&lt;a href="https://github.com/measuredco/puck/commit/7fead35fddf8fef49b41508a27c0e6be458ab2c4" rel="noopener noreferrer"&gt;7fead35&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;select new item when dispatching duplicate action (&lt;a href="https://github.com/measuredco/puck/commit/e3d0025d08408103940c2f84c4524266288f38fd" rel="noopener noreferrer"&gt;e3d0025&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;set root DropZone to 100% height (&lt;a href="https://github.com/measuredco/puck/commit/3d93f46555372e83ead6f671e40970937802f5f4" rel="noopener noreferrer"&gt;3d93f46&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;stop actions from overflowing outside left of frame (&lt;a href="https://github.com/measuredco/puck/commit/c036b6d2036cc759e0a2eda6154bdec5b8a7784e" rel="noopener noreferrer"&gt;c036b6d&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;trigger iframe resize when closing devtools (&lt;a href="https://github.com/measuredco/puck/commit/2c0b782d41817caa2b6fae41fc52b1a7ccbb8d09" rel="noopener noreferrer"&gt;2c0b782&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Contributors
&lt;/h2&gt;

&lt;p&gt;Thanks to our contributors and sponsors for making this huge milestone possible. New contributors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@1benw made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/791" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/791&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like Puck? Give us a ⭐️ on &lt;a href="http://github.com/measuredco/puck/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Great write up on one of the most commonly asked Puck questions! Just use context!</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Tue, 14 Jan 2025 14:53:11 +0000</pubDate>
      <link>https://forem.com/chrisvxd/great-write-up-on-one-of-the-most-commonly-asked-puck-questionsjust-use-context-5gca</link>
      <guid>https://forem.com/chrisvxd/great-write-up-on-one-of-the-most-commonly-asked-puck-questionsjust-use-context-5gca</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/managing-application-state-in-puck-4nek" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Managing application state in Puck&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Jan 14&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Awesome overview for using CSS variables to implement themes with Puck! 🎨</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Wed, 08 Jan 2025 18:30:32 +0000</pubDate>
      <link>https://forem.com/chrisvxd/awesome-overview-for-using-css-variables-with-puck-103f</link>
      <guid>https://forem.com/chrisvxd/awesome-overview-for-using-css-variables-with-puck-103f</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/puckeditor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10097%2F188f3367-b6ae-4526-b765-576622cf29c2.jpg" alt="Puck" width="800" height="800"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2620135%2F3c294c70-07d5-4af4-8163-1329bb0138c4.jpeg" alt="" width="800" height="809"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/puckeditor/using-css-variables-to-create-dynamic-themes-in-puck-26lm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Using CSS variables to create dynamic themes in Puck&lt;/h2&gt;
      &lt;h3&gt;Fede Bonel Tozzi for Puck ・ Jan 8&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>css</category>
      <category>webdev</category>
      <category>design</category>
    </item>
    <item>
      <title>Puck 0.17 - React 19 and QOL improvements</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Wed, 18 Dec 2024 19:15:52 +0000</pubDate>
      <link>https://forem.com/puckeditor/puck-v017-react-19-and-qol-improvements-bfe</link>
      <guid>https://forem.com/puckeditor/puck-v017-react-19-and-qol-improvements-bfe</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://puckeditor.com" rel="noopener noreferrer"&gt;Puck&lt;/a&gt; is the open-source visual editor for React, empowering the next generation of page builders and no-code products. Give us a star on &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! ⭐️&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Puck v0.17 adds support for React 19, improves various field APIs and squashes some bugs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is our final feature release of the year! We're delaying the &lt;a href="https://github.com/measuredco/puck/pull/598" rel="noopener noreferrer"&gt;new drag-and-drop engine&lt;/a&gt; release until January while we iron out the last few kinks. Happy holidays, and thanks for being a wonderful community 🎄&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 19 support&lt;/strong&gt;: We've made &lt;a href="https://react.dev/blog/2024/12/05/react-19" rel="noopener noreferrer"&gt;React 19&lt;/a&gt; support official by adding it to the supported list of peer dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt;: Upgraded the next recipe to use &lt;a href="https://nextjs.org/blog/next-15" rel="noopener noreferrer"&gt;Next 15.1&lt;/a&gt; and React 19 by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://puckeditor.com/docs/api-reference/fields/external" rel="noopener noreferrer"&gt;New external field APIs&lt;/a&gt;&lt;/strong&gt;: External fields now support react elements as rows, and a custom footer, enabling much more customization. Thanks to &lt;a class="mentioned-user" href="https://dev.to/camhammel"&gt;@camhammel&lt;/a&gt; for these improvements!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://puckeditor.com/docs/api-reference/fields/array" rel="noopener noreferrer"&gt;Duplicate array items&lt;/a&gt;&lt;/strong&gt;: Added a new action to the array field so you can easily duplicate array items. Thank you @siarhei-zharnasek 🙏&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://puckeditor.com//docs/api-reference/configuration/component-config#paramsparent" rel="noopener noreferrer"&gt;resolveFields enhancement&lt;/a&gt;&lt;/strong&gt;: You can now access the DropZone parent data when using the &lt;code&gt;resolveFields&lt;/code&gt; API,  enabling you to customize the fields based on the container's type or props.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  React 19 support
&lt;/h3&gt;

&lt;p&gt;We've made &lt;a href="https://react.dev/blog/2024/12/05/react-19" rel="noopener noreferrer"&gt;React 19&lt;/a&gt; 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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next 15
&lt;/h3&gt;

&lt;p&gt;The official &lt;a href="https://github.com/measuredco/puck/tree/main/recipes/next" rel="noopener noreferrer"&gt;next recipe&lt;/a&gt; now uses  &lt;a href="https://nextjs.org/blog/next-15" rel="noopener noreferrer"&gt;Next 15.1&lt;/a&gt; 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 &lt;a href="https://nextjs.org/docs/app/building-your-application/upgrading/version-15" rel="noopener noreferrer"&gt;official Next.js upgrade guide&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h3&gt;
  
  
  New external field APIs
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/fields/external#maprowitem" rel="noopener noreferrer"&gt;&lt;code&gt;mapRow&lt;/code&gt; API&lt;/a&gt; now supports react elements, making it possible to add richer content to your external field table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;external&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fetchList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;imgUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/img.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Goodbye, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;imgUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/img.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;mapRow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;imgUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imgUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the new &lt;a href="https://puckeditor.com/v/canary/docs/api-reference/fields/external#renderfooterprops" rel="noopener noreferrer"&gt;&lt;code&gt;renderFooter&lt;/code&gt; API&lt;/a&gt; enables you to customise the footer of your external field modal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;external&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fetchList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Goodbye, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;renderFooter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Custom footer with &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; results&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Duplicate array items
&lt;/h3&gt;

&lt;p&gt;A new action in the array field allows you to easily duplicate array items.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fa69a608d-fecf-42c1-ac4f-87ca26c09cc4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fa69a608d-fecf-42c1-ac4f-87ca26c09cc4" alt="Cursor clicking the array item duplicate icon button, and the item duplicating, on loop" width="752" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Access parent data in resolveFields
&lt;/h3&gt;

&lt;p&gt;The new &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#paramsparent" rel="noopener noreferrer"&gt;&lt;code&gt;parent&lt;/code&gt; param&lt;/a&gt; on the &lt;code&gt;resolveFields&lt;/code&gt; API enables you to configure your fields based on the props of the parent item when using DropZones.&lt;/p&gt;

&lt;p&gt;Here's an example that shows a field called &lt;code&gt;flex&lt;/code&gt; when the parent component has a &lt;code&gt;display&lt;/code&gt; prop of &lt;code&gt;"flex"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolveFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Grow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shrink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shrink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Full changelog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;add duplicate action to array field (&lt;a href="https://github.com/measuredco/puck/commit/229cbddb7eed513c8ac9a2e36e3af3b53ff28d7e" rel="noopener noreferrer"&gt;229cbdd&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add renderFooter API to external field (&lt;a href="https://github.com/measuredco/puck/commit/ccec96e5ddf831fcd89a2af335449ad4cff1ea81" rel="noopener noreferrer"&gt;ccec96e&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;allow react elements in external field mapRow (&lt;a href="https://github.com/measuredco/puck/commit/2f781de0a910a193f0a4bae795725119476f8e94" rel="noopener noreferrer"&gt;2f781de&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;enable resolveFields to access parent data (&lt;a href="https://github.com/measuredco/puck/commit/196227bdf33ee678ce47b68fc624804448008cc1" rel="noopener noreferrer"&gt;196227b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;list React 19 as supported peer dependency (&lt;a href="https://github.com/measuredco/puck/commit/85e8cc1a6fcd29d9dd04e5e53c6e7f9a85f99959" rel="noopener noreferrer"&gt;85e8cc1&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;track focused field in app state (&lt;a href="https://github.com/measuredco/puck/commit/91bc97a760d1750d65dedbbffee962a6c6ee8d60" rel="noopener noreferrer"&gt;91bc97a&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;upgrade next recipe to v15.1 (&lt;a href="https://github.com/measuredco/puck/commit/8ef51c54e386528fca69be1e54b8a3ce69651bd0" rel="noopener noreferrer"&gt;8ef51c5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;use React 19 in next recipe (&lt;a href="https://github.com/measuredco/puck/commit/6b3d97f9f3d0cc2283178ba6f4bda3b23f1f718a" rel="noopener noreferrer"&gt;6b3d97f&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug Fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;always run field resolvers when item change (&lt;a href="https://github.com/measuredco/puck/commit/159d819e0263f4e91bff8a83adfa404601850aa5" rel="noopener noreferrer"&gt;159d819&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;always update fields when resolveData runs (&lt;a href="https://github.com/measuredco/puck/commit/39dd61934c15a452c59f26b0c6721802df0c1889" rel="noopener noreferrer"&gt;39dd619&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ensure radio fields are functional inside arrays (&lt;a href="https://github.com/measuredco/puck/commit/7736294d201f432799c0854be14b35edbad156d8" rel="noopener noreferrer"&gt;7736294&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent field name collision causing hook render mismatch (&lt;a href="https://github.com/measuredco/puck/commit/b51954a19875e1f3c87e0cdc03c10173e9786820" rel="noopener noreferrer"&gt;b51954a&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent flicker when using resolveData with arrays (&lt;a href="https://github.com/measuredco/puck/commit/1be9b886325a1515434759011e9e3514c583bd2e" rel="noopener noreferrer"&gt;1be9b88&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;provide better error when usePuck used inappropriately (&lt;a href="https://github.com/measuredco/puck/commit/9991c079b2b7d8f18ecb42efc3ebc32e5d679b88" rel="noopener noreferrer"&gt;9991c07&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;remove leading zeros in Number field (&lt;a href="https://github.com/measuredco/puck/commit/5ba9399e6546919ae744d7a4986b59faa1cd7aef" rel="noopener noreferrer"&gt;5ba9399&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;respect original value type in radio and select fields (&lt;a href="https://github.com/measuredco/puck/commit/00ccd1df6513d2420c87cd136577e1df1ac9a9a3" rel="noopener noreferrer"&gt;00ccd1d&lt;/a&gt; and &lt;a href="https://github.com/measuredco/puck/commit/6e5864a5df01a52fb4e6b23132d68d4496f1e64e" rel="noopener noreferrer"&gt;6e5864a&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New Contributors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;@ruofee made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/693" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/693&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@DevOfManyThings made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/698" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/698&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@benlife5 made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/695" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/695&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/camhammel"&gt;@camhammel&lt;/a&gt; made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/682" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/682&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@siarhei-zharnasek made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/676" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/676&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@antonva made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/707" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/707&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/jswhisperer"&gt;@jswhisperer&lt;/a&gt; made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/722" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/722&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Full Changelog&lt;/strong&gt;: &lt;a href="https://github.com/measuredco/puck/compare/v0.16.2...v0.17.1" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/compare/v0.16.2...v0.17.1&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>puck</category>
    </item>
    <item>
      <title>Puck 0.16: Permissions</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Tue, 17 Sep 2024 14:00:09 +0000</pubDate>
      <link>https://forem.com/puckeditor/puck-v016-permissions-3p5d</link>
      <guid>https://forem.com/puckeditor/puck-v016-permissions-3p5d</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://puckeditor.com" rel="noopener noreferrer"&gt;Puck&lt;/a&gt; is the open-source visual editor for React, empowering the next generation of page builders and no-code products. Give us a star on &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! ⭐️&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;We're celebrating 5,000 stars on GitHub! Thank you to our wonderful community!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/measuredco/puck/releases" rel="noopener noreferrer"&gt;Puck v0.16&lt;/a&gt; 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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/integrating-puck/feature-toggling" rel="noopener noreferrer"&gt;&lt;strong&gt;Permissions&lt;/strong&gt;&lt;/a&gt;: Toggle Puck features like duplication, dragging, deletion through the new permissions and resolvePermissions APIs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/overrides/action-bar" rel="noopener noreferrer"&gt;&lt;strong&gt;Action bar override&lt;/strong&gt;&lt;/a&gt;: Create custom action bars using the &lt;code&gt;actionBar&lt;/code&gt; override, or extend the default one using the new &lt;a href="https://puckeditor.com/docs/api-reference/components/action-bar" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;ActionBar&amp;gt;&lt;/code&gt; component&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/overrides/iframe" rel="noopener noreferrer"&gt;&lt;strong&gt;iframe style injection&lt;/strong&gt;&lt;/a&gt;: Access the iframe document to inject styles directly, or make other changes, via the new &lt;code&gt;iframe&lt;/code&gt; override. We also introduced the &lt;a href="https://github.com/measuredco/puck/tree/main/packages/plugin-emotion-cache" rel="noopener noreferrer"&gt;&lt;code&gt;emotion-cache&lt;/code&gt; plugin&lt;/a&gt; for the common Emotion use-case.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/components/puck#initialhistory" rel="noopener noreferrer"&gt;&lt;strong&gt;History injection&lt;/strong&gt;&lt;/a&gt;: Inject the undo/redo history via the a series of new APIs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/components/puck#onactionaction-appstate-prevappstate" rel="noopener noreferrer"&gt;&lt;strong&gt;React to actions&lt;/strong&gt;&lt;/a&gt;: React to actions dispatched by Puck via the &lt;code&gt;onAction&lt;/code&gt; callback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional fields&lt;/strong&gt;: Optional props are no longer required to define in fields, since they may be defined &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upgrade today or get started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-puck-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Permissions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://puckeditor.com/docs/api-reference/permissions" rel="noopener noreferrer"&gt;Permissions&lt;/a&gt; enable you to &lt;a href="https://puckeditor.com/docs/integrating-puck/feature-toggling" rel="noopener noreferrer"&gt;toggle core Puck functionality&lt;/a&gt; globally, on a per-component basis or dynamically.  Huge thanks to &lt;a class="mentioned-user" href="https://dev.to/xaviemirmon"&gt;@xaviemirmon&lt;/a&gt; for his efforts on this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt;
      &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;duplicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Action bar override
&lt;/h2&gt;

&lt;p&gt;The new &lt;a href="https://puckeditor.com/docs/api-reference/overrides/action-bar" rel="noopener noreferrer"&gt;&lt;code&gt;actionBar&lt;/code&gt; override&lt;/a&gt; enables you to create a custom action bar overlay, or extend the default one using the &lt;a href="https://puckeditor.com/docs/api-reference/components/action-bar" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;ActionBar&amp;gt;&lt;/code&gt; component&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;actionBar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Render default actions */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Render new actions */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Clicked!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          ★
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ActionBar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  iframe style injection
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/overrides/iframe" rel="noopener noreferrer"&gt;&lt;code&gt;iframe&lt;/code&gt; override&lt;/a&gt; enables you to access the iframe &lt;code&gt;document&lt;/code&gt;, making it possible to inject styles into the head:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background: hotpink;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new &lt;a href="https://github.com/measuredco/puck/tree/main/packages/plugin-emotion-cache" rel="noopener noreferrer"&gt;&lt;code&gt;emotion-cache&lt;/code&gt; plugin&lt;/a&gt; uses this API to create an emotion cache inside the iframe, making Puck easy to use with any Emotion-based component library.&lt;/p&gt;

&lt;h2&gt;
  
  
  History injection
&lt;/h2&gt;

&lt;p&gt;Use the new history injection APIs to provide your own undo/redo history via the &lt;a href="https://puckeditor.com/docs/api-reference/components/puck#initialhistory" rel="noopener noreferrer"&gt;&lt;code&gt;initialHistory&lt;/code&gt; prop&lt;/a&gt;, or dynamically via the &lt;a href="https://puckeditor.com/docs/api-reference/functions/use-puck#sethistories" rel="noopener noreferrer"&gt;&lt;code&gt;setHistories&lt;/code&gt; and &lt;code&gt;setHistoryIndex&lt;/code&gt; functions&lt;/a&gt; from &lt;code&gt;usePuck().history&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;historyState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;My History&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt;
      &lt;span class="na"&gt;initialHistory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;histories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;historyState&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  React to actions
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/components/puck#onactionaction-appstate-prevappstate" rel="noopener noreferrer"&gt;&lt;code&gt;onAction&lt;/code&gt; API&lt;/a&gt; enables you to react to Puck’s internal actions as they’re dispatched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt;
      &lt;span class="na"&gt;onAction&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prevAppState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insert&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New component was inserted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;history.data&lt;/code&gt; is now &lt;code&gt;history.state&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When using the usePuck &lt;code&gt;history&lt;/code&gt; API, &lt;code&gt;data&lt;/code&gt; is now renamed &lt;code&gt;state&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;history.id&lt;/code&gt; is now optional (TypeScript)
&lt;/h3&gt;

&lt;p&gt;When using the usePuck &lt;code&gt;history&lt;/code&gt; API &lt;code&gt;id&lt;/code&gt; is now optional. Puck will always generate an &lt;code&gt;id&lt;/code&gt;, but TypeScript may complain.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;lastData&lt;/code&gt; is now returned as &lt;code&gt;null&lt;/code&gt; instead of &lt;code&gt;{}&lt;/code&gt; when empty in resolvers
&lt;/h3&gt;

&lt;p&gt;When using the &lt;code&gt;lastData&lt;/code&gt; option provided to &lt;code&gt;resolveData&lt;/code&gt; or &lt;code&gt;resolveFields&lt;/code&gt; functions, and there is no previous data, &lt;code&gt;lastData&lt;/code&gt; will now be &lt;code&gt;null&lt;/code&gt; instead of &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full changelog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;add actionBar override for adding component controls (&lt;a href="https://github.com/measuredco/puck/commit/48ec0d786c7c589efc8b97152a5e1a4c065c0312" rel="noopener noreferrer"&gt;48ec0d7&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add automatic RSC export, replacing /rsc bundle (&lt;a href="https://github.com/measuredco/puck/commit/d21eba6185da8efcbcb5458eaaa5be6c321b3d1a" rel="noopener noreferrer"&gt;d21eba6&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add isDisabled prop to Drawer.Item (&lt;a href="https://github.com/measuredco/puck/commit/cad95b887c6b06a41a2bacf28792fd4dbc808d72" rel="noopener noreferrer"&gt;cad95b8&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add generic type to usePuck hook (&lt;a href="https://github.com/measuredco/puck/commit/01703a95093413a57af1314b1f31cc34f85c38e0" rel="noopener noreferrer"&gt;01703a9&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add iframe override for style injection (&lt;a href="https://github.com/measuredco/puck/commit/7cac3764d1f9336776b97fa08cbd48bec95e6a10" rel="noopener noreferrer"&gt;7cac376&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add initialHistory prop to Puck (&lt;a href="https://github.com/measuredco/puck/commit/54b5a871570120a3d0d55e96738746ec375dee0d" rel="noopener noreferrer"&gt;54b5a87&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add onAction API to track and react to state changes (&lt;a href="https://github.com/measuredco/puck/commit/c7007acab334ec2d08f95669d685edb8c3947bcc" rel="noopener noreferrer"&gt;c7007ac&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add permissions API (&lt;a href="https://github.com/measuredco/puck/commit/a43914dc36e70c5596c186d3c63b9497949365a9" rel="noopener noreferrer"&gt;a43914d&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add plugin for injecting Emotion cache (&lt;a href="https://github.com/measuredco/puck/commit/f8a88b9c2447c76f2f7a00ce5705f8fae07be58c" rel="noopener noreferrer"&gt;f8a88b9&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add resolvePermissions API (&lt;a href="https://github.com/measuredco/puck/commit/f0655f08a96b853cf18d681025f40e8d30df3013" rel="noopener noreferrer"&gt;f0655f0&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add waitForStyles option to iframe config (&lt;a href="https://github.com/measuredco/puck/commit/bc81d9c7de671fea0bc155911ee11598a1b920c2" rel="noopener noreferrer"&gt;bc81d9c&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;call resolveData when new item inserted (&lt;a href="https://github.com/measuredco/puck/commit/329883165c9e428b9f291add7b6009ba29680146" rel="noopener noreferrer"&gt;3298831&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't mandate fields for optional props (&lt;a href="https://github.com/measuredco/puck/commit/5a219eff0c2f4763ec1d9f48f45fe684e6482b8f" rel="noopener noreferrer"&gt;5a219ef&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;export ActionBar component for use in overrides (&lt;a href="https://github.com/measuredco/puck/commit/04fd6c5c7a65fc3ec9a05da277865341efe229af" rel="noopener noreferrer"&gt;04fd6c5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;infer Data type from user config (&lt;a href="https://github.com/measuredco/puck/commit/50045bbda2cf3b64e37e0e6bedcfce14f680cda1" rel="noopener noreferrer"&gt;50045bb&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;make ID optional in History type (BREAKING CHANGE) (&lt;a href="https://github.com/measuredco/puck/commit/d917229ae4f553bb54a420e1c708c1a509431106" rel="noopener noreferrer"&gt;d917229&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;provide ES Module build (&lt;a href="https://github.com/measuredco/puck/commit/ff9076b9d24d030ad47619b6a359b1f120422d70" rel="noopener noreferrer"&gt;ff9076b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;rename history.data to history.state (BREAKING CHANGE) (&lt;a href="https://github.com/measuredco/puck/commit/b09244c864fd049ceeda2b7eb20ec6cab9f40054" rel="noopener noreferrer"&gt;b09244c&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;show spinner if iframe load takes over 500ms (&lt;a href="https://github.com/measuredco/puck/commit/cfecf5499d06b8e90438dc151e5e915da06ccb87" rel="noopener noreferrer"&gt;cfecf54&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;streamline usePuck history API (&lt;a href="https://github.com/measuredco/puck/commit/c8b28075fde0081b8ac824eb256114c9b8836f9e" rel="noopener noreferrer"&gt;c8b2807&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;upgrade "next" recipe to &lt;a href="mailto:typescript@5.5.4"&gt;typescript@5.5.4&lt;/a&gt; (&lt;a href="https://github.com/measuredco/puck/commit/60fe63113f8ad8bbce52d8457ee4372aa4b09509" rel="noopener noreferrer"&gt;60fe631&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug Fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;add favicon to next recipe to prevent Puck 404 (&lt;a href="https://github.com/measuredco/puck/commit/2c52d271c6c20e9368a59eb1f2a5df184cef72bc" rel="noopener noreferrer"&gt;2c52d27&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add missing readOnly state to External fields (&lt;a href="https://github.com/measuredco/puck/commit/bf1449dd8b299a4f469986d94f8986b02b79a688" rel="noopener noreferrer"&gt;bf1449d&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;always record history on component insert (&lt;a href="https://github.com/measuredco/puck/commit/88c5ab6b545ecbd045de3ee0d43801c48f50e8b0" rel="noopener noreferrer"&gt;88c5ab6&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't cache /edit route in Next recipe (&lt;a href="https://github.com/measuredco/puck/commit/94f16b25efea86ff475683d3a21f5937e07b201c" rel="noopener noreferrer"&gt;94f16b2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't submit buttons if Puck used in form (&lt;a href="https://github.com/measuredco/puck/commit/f761e5fed63fc698e3a9d6ba94607364ed46f31b" rel="noopener noreferrer"&gt;f761e5f&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ensure demo types are satisfied with TypeScript@5 (&lt;a href="https://github.com/measuredco/puck/commit/958dc255ac5d285f98b6b592df677883b74e2830" rel="noopener noreferrer"&gt;958dc25&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;export missing Plugin type (&lt;a href="https://github.com/measuredco/puck/commit/eb427343fd58752861cac850f59c1098cf473f50" rel="noopener noreferrer"&gt;eb42734&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;fix crash if component in data is missing from config (&lt;a href="https://github.com/measuredco/puck/commit/0daf478d9ad8b14d2844ff6ae2db9bd72970d680" rel="noopener noreferrer"&gt;0daf478&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;improve resiliency of iframe CSS for some frameworks, like Mantine (&lt;a href="https://github.com/measuredco/puck/commit/538cb05606126c338e97c047b97065463e618d36" rel="noopener noreferrer"&gt;538cb05&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;make Config and Data types more robust (&lt;a href="https://github.com/measuredco/puck/commit/6bcf555da74d54d70f00f37878d35fa166bb7e4c" rel="noopener noreferrer"&gt;6bcf555&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent infinite loop when using plugins with some frameworks (&lt;a href="https://github.com/measuredco/puck/commit/38708716f32d65a9131b87fe664ba96b32aead15" rel="noopener noreferrer"&gt;3870871&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prevent Tailwind from clashing with viewport zoom select (&lt;a href="https://github.com/measuredco/puck/commit/91512553430b295c37c80a935f0db929bb37870c" rel="noopener noreferrer"&gt;9151255&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;remove body margin in remix recipe (&lt;a href="https://github.com/measuredco/puck/commit/0898b26cd021680dfb77a439b04140ce2fb8cb2c" rel="noopener noreferrer"&gt;0898b26&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;resize viewport when changed via app state (&lt;a href="https://github.com/measuredco/puck/commit/14419ecf1c606e6fa0d6d9c5198401eb01bc72dd" rel="noopener noreferrer"&gt;14419ec&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;resolve fields when switching between items of same type (&lt;a href="https://github.com/measuredco/puck/commit/a3518ca8560ba9fcdbe5086220490920ecf24fc0" rel="noopener noreferrer"&gt;a3518ca&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;return lastData as null instead of empty object in resolvers (BREAKING CHANGE) (&lt;a href="https://github.com/measuredco/puck/commit/648eb92b3d2c5be8f5fc99a22db5eff64cefb155" rel="noopener noreferrer"&gt;648eb92&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;show warning if heading-analyzer styles aren't loaded (&lt;a href="https://github.com/measuredco/puck/commit/4e7110b591a4a12e2b3c89eb1fa98faf5f9338d4" rel="noopener noreferrer"&gt;4e7110b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;use correct color in FieldLabel labels (&lt;a href="https://github.com/measuredco/puck/commit/b0469a1134ac8eafc9a3b16de4d7805241127947" rel="noopener noreferrer"&gt;b0469a1&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New Contributors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;@mkilpatrick made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/505" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/505&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@nova4u made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/538" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/538&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;@antonmalyavkin made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/585" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/585&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Full Changelog&lt;/strong&gt;: &lt;a href="https://github.com/measuredco/puck/compare/v0.15.0...v0.16.0" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/compare/v0.15.0...v0.16.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>puck</category>
    </item>
    <item>
      <title>Puck 0.15: Dynamic fields</title>
      <dc:creator>Chris Villa</dc:creator>
      <pubDate>Wed, 21 Aug 2024 08:31:11 +0000</pubDate>
      <link>https://forem.com/puckeditor/puck-015-dynamic-fields-ilc</link>
      <guid>https://forem.com/puckeditor/puck-015-dynamic-fields-ilc</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://puckeditor.com" rel="noopener noreferrer"&gt;Puck&lt;/a&gt; is the open-source visual editor for React, empowering the next generation of page builders and no-code products. Give us a star on &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! ⭐️&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;Puck v0.15&lt;/a&gt; introduces powerful new field APIs and numerous quality-of-life features.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/integrating-puck/dynamic-fields" rel="noopener noreferrer"&gt;&lt;strong&gt;Dynamic fields&lt;/strong&gt;&lt;/a&gt;: Use the &lt;code&gt;resolveFields&lt;/code&gt; API to dynamically define your fields - great for showing fields conditionally or loading external APIs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/components/auto-field" rel="noopener noreferrer"&gt;&lt;strong&gt;AutoField component&lt;/strong&gt;&lt;/a&gt;: Build custom fields using Puck's own field component for a seamless UI.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/overrides/header-actions" rel="noopener noreferrer"&gt;&lt;strong&gt;Override the Publish button&lt;/strong&gt;&lt;/a&gt;: Swap out the publish button without swapping out the entire header.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#puckisediting" rel="noopener noreferrer"&gt;&lt;strong&gt;Context-aware components&lt;/strong&gt;&lt;/a&gt;: Modify component behaviour based on whether it's inside &lt;code&gt;&amp;lt;Puck&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;Render&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Upgrade today or get started with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-puck-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dynamic fields
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://puckeditor.com/docs/integrating-puck/dynamic-fields" rel="noopener noreferrer"&gt;Dynamic field resolution&lt;/a&gt; via the &lt;code&gt;resolveFields&lt;/code&gt; API allows you to change the &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#fields" rel="noopener noreferrer"&gt;field configuration&lt;/a&gt; whenever the props change. You can use this to show and hide fields or even load data from an API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhxouge70kje9rbx9szo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhxouge70kje9rbx9szo.gif" alt="Dynamic field example" width="1080" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
      &lt;span class="na"&gt;resolveFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;myField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;  &lt;span class="c1"&gt;// Populate dynamically&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  AutoField component
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://puckeditor.com/docs/api-reference/components/auto-field" rel="noopener noreferrer"&gt;AutoField component&lt;/a&gt; lets you render a Puck field based on a &lt;a href="https://puckeditor.com/docs/api-reference/fields" rel="noopener noreferrer"&gt;Field&lt;/a&gt; object. Use this when building &lt;a href="https://puckeditor.com/docs/extending-puck/custom-fields" rel="noopener noreferrer"&gt;custom fields&lt;/a&gt; that need to use Puck-style fields internally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CustomField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AutoField&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Override the Publish button
&lt;/h2&gt;

&lt;p&gt;It's now possible to implement a custom Publish button without overriding the entire header by using the &lt;a href="https://puckeditor.com/docs/api-reference/overrides/header-actions" rel="noopener noreferrer"&gt;&lt;code&gt;headerActions&lt;/code&gt; override&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt;
  &lt;span class="na"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headerActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* children will render default Publish button */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Or you can define your own */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This creates a breaking change for existing &lt;code&gt;headerActions&lt;/code&gt; overrides, which will now need to render &lt;code&gt;children&lt;/code&gt; to show the default Publish button.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Context-aware components
&lt;/h2&gt;

&lt;p&gt;Components now receive the &lt;a href="https://puckeditor.com/docs/api-reference/configuration/component-config#puckisediting" rel="noopener noreferrer"&gt;&lt;code&gt;puck.isEditing&lt;/code&gt; prop&lt;/a&gt;. Use this to toggle functionality based on whether the component is being rendered in the &lt;code&gt;&amp;lt;Puck&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;Render&amp;gt;&lt;/code&gt; context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;puck&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;puck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEditing&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hotpink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transparent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Hello, world
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking changes &amp;amp; deprecations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;headerActions&lt;/code&gt; override must now render &lt;code&gt;{children}&lt;/code&gt; (BREAKING CHANGE)
&lt;/h3&gt;

&lt;p&gt;In order to support custom Publish buttons, the &lt;code&gt;headerActions&lt;/code&gt; override will no longer render the default Publish button unless &lt;code&gt;children&lt;/code&gt; are rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Puck&lt;/span&gt;
  &lt;span class="na"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headerActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Render default Publish button */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Undocumented &lt;code&gt;editMode&lt;/code&gt; API deprecated
&lt;/h3&gt;

&lt;p&gt;The undocumented &lt;code&gt;editMode&lt;/code&gt; prop is now deprecated in favor of &lt;code&gt;puck.isEditing&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Changelog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;add AutoField component for using Puck fields inside custom fields (&lt;a href="https://github.com/measuredco/puck/commit/106028b59bb1a02756645bb76ce400adc398430d" rel="noopener noreferrer"&gt;106028b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add isEditing flag to &lt;code&gt;puck&lt;/code&gt; object prop (&lt;a href="https://github.com/measuredco/puck/commit/13bb1bdf03a62000c07a7d49a56ad09c1433fda0" rel="noopener noreferrer"&gt;13bb1bd&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;add resolveFields API for dynamic fields (&lt;a href="https://github.com/measuredco/puck/commit/0a18bdb9387f302565f74fa30f09fd912ea0769b" rel="noopener noreferrer"&gt;0a18bdb&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;allow data prop to accept an empty object (&lt;a href="https://github.com/measuredco/puck/commit/aedd401dd415e9d7dc1cbd6e33e59f5264180374" rel="noopener noreferrer"&gt;aedd401&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;bump next recipe to Next@14 (&lt;a href="https://github.com/measuredco/puck/commit/47a27ed2c6aee80d4093975c399d96b950cb6956" rel="noopener noreferrer"&gt;47a27ed&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;enable override of publish button (breaking change) (&lt;a href="https://github.com/measuredco/puck/commit/480467ae2e06ae4d36c4fd67f75757557058f561" rel="noopener noreferrer"&gt;480467a&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;expose previous data to resolveData via &lt;code&gt;lastData&lt;/code&gt; param (&lt;a href="https://github.com/measuredco/puck/commit/dd7051e8fbb3770714100c92f7f5c69d0be5dab6" rel="noopener noreferrer"&gt;dd7051e&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;replace history chevrons with undo/redo icons (&lt;a href="https://github.com/measuredco/puck/commit/91dff227c382ddd5ad183cd69cb4d2fabd56f093" rel="noopener noreferrer"&gt;91dff22&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug Fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;align Drawer behaviour and docs with expectation (&lt;a href="https://github.com/measuredco/puck/commit/e2cd445f9d3abccca5b3daf95a4d92774a1dd47a" rel="noopener noreferrer"&gt;e2cd445&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;animate loader in iframe (&lt;a href="https://github.com/measuredco/puck/commit/151a2675bf8e700368aad0652192bc7d9fd2bbd6" rel="noopener noreferrer"&gt;151a267&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't inline link stylesheets for more predictable behaviour (&lt;a href="https://github.com/measuredco/puck/commit/c0a331de31c2d59e0e21ef342eb4c821850e10be" rel="noopener noreferrer"&gt;c0a331d&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't overflow external inputs inside arrays/objects (&lt;a href="https://github.com/measuredco/puck/commit/42ef582cac949f8a24f9cdad204baf24d808b410" rel="noopener noreferrer"&gt;42ef582&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't throw warning when user is correctly specifying root props (&lt;a href="https://github.com/measuredco/puck/commit/46aa8ff3a68dcbd4aec4ebfef246d400469ca4d4" rel="noopener noreferrer"&gt;46aa8ff&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;don't unintentionally use read-only styles in external fields (&lt;a href="https://github.com/measuredco/puck/commit/acaf72746c2c82881a753dab6350161c774cd13f" rel="noopener noreferrer"&gt;acaf727&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;fix defaultProps for root (&lt;a href="https://github.com/measuredco/puck/commit/9a1cc7c925f0b8a79b5f523fc7c8a6d6afdc2067" rel="noopener noreferrer"&gt;9a1cc7c&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;infer correct value types in Custom fields (&lt;a href="https://github.com/measuredco/puck/commit/5c8c0e1bfa9ca4da04e1cfac83c7a3ab5883fc5c" rel="noopener noreferrer"&gt;5c8c0e1&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;position field loader relative to sidebar, not fields (&lt;a href="https://github.com/measuredco/puck/commit/2e8936e4f416b0a04b273250cf3848447fb7e045" rel="noopener noreferrer"&gt;2e8936e&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;show external field modal when using custom interfaces (&lt;a href="https://github.com/measuredco/puck/commit/6e97a0e18aea72581ba466e8cf3f87e60f3a65f3" rel="noopener noreferrer"&gt;6e97a0e&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;show field loader when using field overrides (&lt;a href="https://github.com/measuredco/puck/commit/8ccfa4c0c3477b8e1d2db2fcc7a352b353643095" rel="noopener noreferrer"&gt;8ccfa4c&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;still load iframe if styles fail to load (&lt;a href="https://github.com/measuredco/puck/commit/3e56bc1816c40c555de2eb28148baf5dcdcacbea" rel="noopener noreferrer"&gt;3e56bc1&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href="https://github.com/measuredco/puck/releases/tag/v0.15.0" rel="noopener noreferrer"&gt;GitHub release&lt;/a&gt; for the full changelog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community
&lt;/h2&gt;

&lt;p&gt;We're grateful for the community's support and contributions. Join the conversation on &lt;a href="https://github.com/measuredco/puck" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://discord.gg/D9e4E3MQVZ" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributors
&lt;/h2&gt;

&lt;p&gt;A huge thanks to all our existing and new contributors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/goynang" rel="noopener noreferrer"&gt;@goynang&lt;/a&gt; made their first contribution in &lt;a href="https://github.com/measuredco/puck/pull/487" rel="noopener noreferrer"&gt;https://github.com/measuredco/puck/pull/487&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>puck</category>
    </item>
  </channel>
</rss>
