Full Code of puckeditor/puck for AI

main edc819204441 cached
719 files
1.4 MB
385.0k tokens
492 symbols
1 requests
Download .txt
Showing preview only (1,581K chars total). Download the full file or copy to clipboard to get everything.
Repository: puckeditor/puck
Branch: main
Commit: edc819204441
Files: 719
Total size: 1.4 MB

Directory structure:
gitextract_c768lzuy/

├── .eslintrc.js
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── ci.yml
│       ├── publish-canary.yml
│       └── publish.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── .yarnrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps/
│   ├── demo/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── custom-ui/
│   │   │   │   └── [...puckPath]/
│   │   │   │       ├── client.tsx
│   │   │   │       └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── rsc/
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── config/
│   │   │   ├── blocks/
│   │   │   │   ├── Blank/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Button/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Card/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Flex/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Grid/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Heading/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Hero/
│   │   │   │   │   ├── Hero.tsx
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── quotes.ts
│   │   │   │   │   ├── server.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Logos/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── RichText/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Space/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Stats/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Template/
│   │   │   │   │   ├── Template.tsx
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── server.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   └── Text/
│   │   │   │       ├── index.tsx
│   │   │   │       └── styles.module.css
│   │   │   ├── components/
│   │   │   │   ├── Footer/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Header/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Layout/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   └── Section/
│   │   │   │       ├── index.tsx
│   │   │   │       └── styles.module.css
│   │   │   ├── index.tsx
│   │   │   ├── initial-data.ts
│   │   │   ├── options.ts
│   │   │   ├── root.tsx
│   │   │   ├── server.tsx
│   │   │   └── types.ts
│   │   ├── lib/
│   │   │   ├── resolve-puck-path.ts
│   │   │   └── use-demo-data.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   └── docs/
│       ├── .eslintrc.js
│       ├── .gitignore
│       ├── components/
│       │   ├── CtaCard/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── DiscoveryButton/
│       │   │   └── index.tsx
│       │   ├── FooterActions/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── Home/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── Preview/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── ReleaseSwitcher/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   └── Viewport/
│       │       ├── index.tsx
│       │       └── styles.module.css
│       ├── middleware.ts
│       ├── next-env.d.ts
│       ├── next-sitemap.config.js
│       ├── next.config.mjs
│       ├── package.json
│       ├── pages/
│       │   ├── _app.tsx
│       │   ├── _document.tsx
│       │   ├── _meta.js
│       │   ├── api/
│       │   │   └── releases.ts
│       │   ├── docs/
│       │   │   ├── _meta.js
│       │   │   ├── api-reference/
│       │   │   │   ├── _meta.js
│       │   │   │   ├── actions.mdx
│       │   │   │   ├── components/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── action-bar-action.mdx
│       │   │   │   │   ├── action-bar-group.mdx
│       │   │   │   │   ├── action-bar-label.mdx
│       │   │   │   │   ├── action-bar-separator.mdx
│       │   │   │   │   ├── action-bar.mdx
│       │   │   │   │   ├── auto-field.mdx
│       │   │   │   │   ├── drawer-item.mdx
│       │   │   │   │   ├── drawer.mdx
│       │   │   │   │   ├── drop-zone.mdx
│       │   │   │   │   ├── field-label.mdx
│       │   │   │   │   ├── puck-components.mdx
│       │   │   │   │   ├── puck-fields.mdx
│       │   │   │   │   ├── puck-layout.mdx
│       │   │   │   │   ├── puck-outline.mdx
│       │   │   │   │   ├── puck-preview.mdx
│       │   │   │   │   ├── puck.mdx
│       │   │   │   │   ├── render.mdx
│       │   │   │   │   ├── rich-text-menu-control.mdx
│       │   │   │   │   ├── rich-text-menu-group.mdx
│       │   │   │   │   └── rich-text-menu.mdx
│       │   │   │   ├── components.mdx
│       │   │   │   ├── configuration/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── component-config.mdx
│       │   │   │   │   └── config.mdx
│       │   │   │   ├── configuration.mdx
│       │   │   │   ├── data-model/
│       │   │   │   │   ├── app-state.mdx
│       │   │   │   │   ├── component-data.mdx
│       │   │   │   │   ├── data.mdx
│       │   │   │   │   ├── item-selector.mdx
│       │   │   │   │   └── root-data.mdx
│       │   │   │   ├── data-model.mdx
│       │   │   │   ├── field-transforms.mdx
│       │   │   │   ├── fields/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── array.mdx
│       │   │   │   │   ├── base.mdx
│       │   │   │   │   ├── custom.mdx
│       │   │   │   │   ├── external.mdx
│       │   │   │   │   ├── number.mdx
│       │   │   │   │   ├── object.mdx
│       │   │   │   │   ├── radio.mdx
│       │   │   │   │   ├── richtext.mdx
│       │   │   │   │   ├── select.mdx
│       │   │   │   │   ├── slot.mdx
│       │   │   │   │   ├── text.mdx
│       │   │   │   │   └── textarea.mdx
│       │   │   │   ├── fields.mdx
│       │   │   │   ├── functions/
│       │   │   │   │   ├── migrate.mdx
│       │   │   │   │   ├── register-overlay-portal.mdx
│       │   │   │   │   ├── resolve-all-data.mdx
│       │   │   │   │   ├── set-deep.mdx
│       │   │   │   │   ├── transform-props.mdx
│       │   │   │   │   ├── use-get-puck.mdx
│       │   │   │   │   ├── use-puck.mdx
│       │   │   │   │   └── walk-tree.mdx
│       │   │   │   ├── functions.mdx
│       │   │   │   ├── overrides/
│       │   │   │   │   ├── action-bar.mdx
│       │   │   │   │   ├── component-overlay.mdx
│       │   │   │   │   ├── drawer-item.mdx
│       │   │   │   │   ├── drawer.mdx
│       │   │   │   │   ├── field-label.mdx
│       │   │   │   │   ├── field-types.mdx
│       │   │   │   │   ├── fields.mdx
│       │   │   │   │   ├── header-actions.mdx
│       │   │   │   │   ├── header.mdx
│       │   │   │   │   ├── iframe.mdx
│       │   │   │   │   ├── outline.mdx
│       │   │   │   │   ├── preview.mdx
│       │   │   │   │   └── puck.mdx
│       │   │   │   ├── overrides.mdx
│       │   │   │   ├── permissions.mdx
│       │   │   │   ├── plugin.mdx
│       │   │   │   ├── plugins/
│       │   │   │   │   ├── blocks-plugin.mdx
│       │   │   │   │   ├── fields-plugin.mdx
│       │   │   │   │   ├── legacy-side-bar-plugin.mdx
│       │   │   │   │   └── outline-plugin.mdx
│       │   │   │   ├── puck-api.mdx
│       │   │   │   └── theming.mdx
│       │   │   ├── extending-puck/
│       │   │   │   ├── _meta.js
│       │   │   │   ├── composition.mdx
│       │   │   │   ├── custom-fields.mdx
│       │   │   │   ├── field-transforms.mdx
│       │   │   │   ├── internal-puck-api.mdx
│       │   │   │   ├── plugins.mdx
│       │   │   │   ├── theming/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── fonts.mdx
│       │   │   │   │   └── overview.mdx
│       │   │   │   └── ui-overrides.mdx
│       │   │   ├── getting-started.mdx
│       │   │   ├── guides/
│       │   │   │   ├── _meta.js
│       │   │   │   └── migrations/
│       │   │   │       ├── _meta.js
│       │   │   │       └── dropzones-to-slots.mdx
│       │   │   ├── index.mdx
│       │   │   └── integrating-puck/
│       │   │       ├── _meta.js
│       │   │       ├── categories.mdx
│       │   │       ├── component-configuration.mdx
│       │   │       ├── data-migration.mdx
│       │   │       ├── dynamic-fields.mdx
│       │   │       ├── dynamic-props.mdx
│       │   │       ├── external-data-sources.mdx
│       │   │       ├── feature-toggling.mdx
│       │   │       ├── multi-column-layouts.mdx
│       │   │       ├── overlay-portals.mdx
│       │   │       ├── rich-text-editing.mdx
│       │   │       ├── root-configuration.mdx
│       │   │       ├── server-components.mdx
│       │   │       └── viewports.mdx
│       │   └── index.mdx
│       ├── public/
│       │   ├── manifest.webmanifest
│       │   └── robots.txt
│       ├── releases.json
│       ├── styles.css
│       ├── theme.config.tsx
│       ├── tsconfig/
│       │   ├── base.json
│       │   └── nextjs.json
│       └── tsconfig.json
├── lerna.json
├── package.json
├── packages/
│   ├── core/
│   │   ├── .gitignore
│   │   ├── bundle/
│   │   │   ├── core.css
│   │   │   ├── core.ts
│   │   │   ├── index.css
│   │   │   ├── index.ts
│   │   │   ├── internal.ts
│   │   │   ├── no-external.css
│   │   │   ├── no-external.ts
│   │   │   └── rsc.tsx
│   │   ├── components/
│   │   │   ├── ActionBar/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── AutoField/
│   │   │   │   ├── FieldLabel.tsx
│   │   │   │   ├── context.tsx
│   │   │   │   ├── fields/
│   │   │   │   │   ├── ArrayField/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── DefaultField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExternalField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ObjectField/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── RadioField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── RichtextField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SelectField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TextareaField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   ├── use-deep-field.ts
│   │   │   │   │   ├── use-is-focused.ts
│   │   │   │   │   └── use-local-value.ts
│   │   │   │   ├── store.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── subfield.tsx
│   │   │   ├── AutoFrame/
│   │   │   │   └── index.tsx
│   │   │   ├── Breadcrumbs/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Button/
│   │   │   │   ├── Button.module.css
│   │   │   │   ├── Button.tsx
│   │   │   │   └── index.ts
│   │   │   ├── ComponentList/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DefaultOverride/
│   │   │   │   └── index.tsx
│   │   │   ├── DragDropContext/
│   │   │   │   └── index.tsx
│   │   │   ├── DragIcon/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DraggableComponent/
│   │   │   │   ├── index.tsx
│   │   │   │   ├── styles.css
│   │   │   │   └── styles.module.css
│   │   │   ├── Drawer/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DropZone/
│   │   │   │   ├── context.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   ├── use-content-with-preview.ts
│   │   │   │   │   ├── use-drag-axis.ts
│   │   │   │   │   └── use-min-empty-height.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── types.ts
│   │   │   ├── ExternalInput/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Heading/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── IconButton/
│   │   │   │   ├── IconButton.module.css
│   │   │   │   ├── IconButton.tsx
│   │   │   │   └── index.ts
│   │   │   ├── InlineTextField/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── LayerTree/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Loader/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── MemoizeComponent/
│   │   │   │   └── index.tsx
│   │   │   ├── MenuBar/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Modal/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── OutlineList/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Puck/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── __snapshots__/
│   │   │   │   │   │   └── index.tsx.snap
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── Canvas/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Components/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Fields/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Header/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Layout/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Nav/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Outline/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Preview/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── ResizeHandle/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── styles.css
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   └── Sidebar/
│   │   │   │   │       ├── index.tsx
│   │   │   │   │       └── styles.module.css
│   │   │   │   └── index.tsx
│   │   │   ├── Render/
│   │   │   │   └── index.tsx
│   │   │   ├── RichTextEditor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Editor.tsx
│   │   │   │   │   ├── EditorFallback.tsx
│   │   │   │   │   ├── EditorInner.tsx
│   │   │   │   │   ├── Render.tsx
│   │   │   │   │   └── RenderFallback.tsx
│   │   │   │   ├── extension.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── lib/
│   │   │   │   │   ├── mapDeep.ts
│   │   │   │   │   ├── use-richtext-props.tsx
│   │   │   │   │   └── use-synced-editor.ts
│   │   │   │   ├── selector.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── types.ts
│   │   │   ├── RichTextMenu/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Control/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   └── SelectControl/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── controls/
│   │   │   │   │   ├── AlignCenter.tsx
│   │   │   │   │   ├── AlignJustify.tsx
│   │   │   │   │   ├── AlignLeft.tsx
│   │   │   │   │   ├── AlignRight.tsx
│   │   │   │   │   ├── AlignSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── Blockquote.tsx
│   │   │   │   │   ├── Bold.tsx
│   │   │   │   │   ├── BulletList.tsx
│   │   │   │   │   ├── CodeBlock.tsx
│   │   │   │   │   ├── HeadingSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── HorizontalRule.tsx
│   │   │   │   │   ├── InlineCode.tsx
│   │   │   │   │   ├── Italic.tsx
│   │   │   │   │   ├── ListSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── OrderedList.tsx
│   │   │   │   │   ├── Strikethrough.tsx
│   │   │   │   │   ├── Underline.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── full.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── inner.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   └── use-control-context.ts
│   │   │   │   └── styles.module.css
│   │   │   ├── Select/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── ServerRender/
│   │   │   │   └── index.tsx
│   │   │   ├── SidebarSection/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── SlotRender/
│   │   │   │   ├── index.tsx
│   │   │   │   └── server.tsx
│   │   │   ├── Sortable/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.css
│   │   │   └── ViewportControls/
│   │   │       ├── default-viewports.ts
│   │   │       ├── index.tsx
│   │   │       └── styles.module.css
│   │   ├── globals.d.ts
│   │   ├── index.ts
│   │   ├── jest.config.ts
│   │   ├── lib/
│   │   │   ├── __tests__/
│   │   │   │   ├── insert-component.spec.tsx
│   │   │   │   ├── load-overrides.spec.tsx
│   │   │   │   ├── migrate.spec.tsx
│   │   │   │   ├── move-component.spec.tsx
│   │   │   │   ├── resolve-all-data.spec.tsx
│   │   │   │   ├── resolve-component-data.spec.tsx
│   │   │   │   ├── transform-props.spec.tsx
│   │   │   │   └── use-breadcrumbs.spec.tsx
│   │   │   ├── accumulate-transform.ts
│   │   │   ├── assign-refs.ts
│   │   │   ├── bubble-pointer-event.ts
│   │   │   ├── data/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── flatten-data.spec.tsx
│   │   │   │   │   ├── resolve-and-replace-data.spec.tsx
│   │   │   │   │   ├── resolve-data-by-id.spec.tsx
│   │   │   │   │   ├── resolve-data-by-selector.spec.tsx
│   │   │   │   │   ├── walk-app-state.spec.tsx
│   │   │   │   │   └── walk-tree.spec.tsx
│   │   │   │   ├── default-data.ts
│   │   │   │   ├── default-slots.ts
│   │   │   │   ├── find-zones-for-area.ts
│   │   │   │   ├── flatten-data.ts
│   │   │   │   ├── flatten-node.ts
│   │   │   │   ├── for-related-zones.ts
│   │   │   │   ├── get-deep.ts
│   │   │   │   ├── get-ids-for-parent.ts
│   │   │   │   ├── get-item.ts
│   │   │   │   ├── insert.ts
│   │   │   │   ├── make-state-public.ts
│   │   │   │   ├── map-fields.ts
│   │   │   │   ├── populate-ids.ts
│   │   │   │   ├── remove.ts
│   │   │   │   ├── reorder.ts
│   │   │   │   ├── replace.ts
│   │   │   │   ├── resolve-and-replace-data.ts
│   │   │   │   ├── resolve-data-by-id.ts
│   │   │   │   ├── resolve-data-by-selector.ts
│   │   │   │   ├── set-deep.ts
│   │   │   │   ├── setup-zone.ts
│   │   │   │   ├── strip-slots.ts
│   │   │   │   ├── to-component.ts
│   │   │   │   ├── to-root.ts
│   │   │   │   ├── walk-app-state.ts
│   │   │   │   └── walk-tree.ts
│   │   │   ├── dnd/
│   │   │   │   ├── NestedDroppablePlugin.ts
│   │   │   │   ├── collision/
│   │   │   │   │   ├── collision-debug.ts
│   │   │   │   │   ├── directional/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── dynamic/
│   │   │   │   │       ├── get-direction.ts
│   │   │   │   │       ├── get-midpoint-impact.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── store.ts
│   │   │   │   │       └── track-movement-interval.ts
│   │   │   │   ├── use-on-drag-finished.ts
│   │   │   │   ├── use-rendered-callback.ts
│   │   │   │   └── use-sensors.ts
│   │   │   ├── field-transforms/
│   │   │   │   ├── build-mappers.ts
│   │   │   │   ├── default-transforms/
│   │   │   │   │   ├── inline-text-transform.tsx
│   │   │   │   │   ├── rich-text-transform.tsx
│   │   │   │   │   └── slot-transform.tsx
│   │   │   │   ├── use-field-transforms-tracked.tsx
│   │   │   │   └── use-field-transforms.tsx
│   │   │   ├── filter-data-attrs.ts
│   │   │   ├── filter.ts
│   │   │   ├── frame-context.tsx
│   │   │   ├── generate-id.ts
│   │   │   ├── get-changed.ts
│   │   │   ├── get-class-name-factory.ts
│   │   │   ├── get-deep-dir.ts
│   │   │   ├── get-deep-scroll-position.ts
│   │   │   ├── get-frame.ts
│   │   │   ├── get-selector-for-id.ts
│   │   │   ├── get-zone-id.ts
│   │   │   ├── get-zoom-config.ts
│   │   │   ├── global-position.ts
│   │   │   ├── group-zones-by-component.ts
│   │   │   ├── index.ts
│   │   │   ├── insert-component.ts
│   │   │   ├── is-ios.ts
│   │   │   ├── load-overrides.ts
│   │   │   ├── migrate.ts
│   │   │   ├── move-component.ts
│   │   │   ├── on-scroll-end.ts
│   │   │   ├── overlay-portal/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.css
│   │   │   ├── plugin-debug.tsx
│   │   │   ├── resolve-all-data.ts
│   │   │   ├── resolve-component-data.ts
│   │   │   ├── root-droppable-id.ts
│   │   │   ├── scroll-into-view.ts
│   │   │   ├── shallow-equal.ts
│   │   │   ├── throttle.ts
│   │   │   ├── transform-props.ts
│   │   │   ├── use-breadcrumbs.ts
│   │   │   ├── use-component-list.tsx
│   │   │   ├── use-context-store.tsx
│   │   │   ├── use-delete-hotkeys.ts
│   │   │   ├── use-frame.ts
│   │   │   ├── use-hotkey.ts
│   │   │   ├── use-inject-css.ts
│   │   │   ├── use-loaded-overrides.ts
│   │   │   ├── use-on-value-change.ts
│   │   │   ├── use-parent.ts
│   │   │   ├── use-preview-mode-hotkeys.ts
│   │   │   ├── use-puck.ts
│   │   │   ├── use-reset-auto-zoom.ts
│   │   │   ├── use-safe-id.ts
│   │   │   ├── use-sidebar-resize.ts
│   │   │   ├── use-slots.tsx
│   │   │   └── use-why-render.ts
│   │   ├── package.json
│   │   ├── plugins/
│   │   │   ├── blocks/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── fields/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── legacy-side-bar/
│   │   │   │   └── index.tsx
│   │   │   └── outline/
│   │   │       ├── index.tsx
│   │   │       └── styles.module.css
│   │   ├── reducer/
│   │   │   ├── actions/
│   │   │   │   ├── __helpers__/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── duplicate.spec.ts
│   │   │   │   │   ├── insert.spec.ts
│   │   │   │   │   ├── move.spec.ts
│   │   │   │   │   ├── register-zone.spec.ts
│   │   │   │   │   ├── remove.spec.ts
│   │   │   │   │   ├── reorder.spec.ts
│   │   │   │   │   ├── replace.spec.ts
│   │   │   │   │   ├── set-ui.spec.ts
│   │   │   │   │   └── set.spec.ts
│   │   │   │   ├── duplicate.ts
│   │   │   │   ├── insert.ts
│   │   │   │   ├── move.ts
│   │   │   │   ├── register-zone.ts
│   │   │   │   ├── remove.ts
│   │   │   │   ├── reorder.ts
│   │   │   │   ├── replace-root.ts
│   │   │   │   ├── replace.ts
│   │   │   │   ├── set-data.ts
│   │   │   │   ├── set-ui.ts
│   │   │   │   └── set.ts
│   │   │   ├── actions.tsx
│   │   │   └── index.ts
│   │   ├── store/
│   │   │   ├── default-app-state.ts
│   │   │   ├── index.ts
│   │   │   └── slices/
│   │   │       ├── __tests__/
│   │   │       │   ├── fields.spec.tsx
│   │   │       │   ├── history.spec.tsx
│   │   │       │   ├── nodes.spec.tsx
│   │   │       │   └── permissions.spec.tsx
│   │   │       ├── fields.ts
│   │   │       ├── history.ts
│   │   │       ├── nodes.ts
│   │   │       └── permissions.ts
│   │   ├── styles/
│   │   │   ├── color.css
│   │   │   └── typography.css
│   │   ├── styles.css
│   │   ├── tsconfig.json
│   │   ├── tsup.config.ts
│   │   └── types/
│   │       ├── API/
│   │       │   ├── DropZone.ts
│   │       │   ├── FieldTransforms.ts
│   │       │   ├── Overrides.ts
│   │       │   ├── Viewports.ts
│   │       │   └── index.ts
│   │       ├── AppState.tsx
│   │       ├── Config.tsx
│   │       ├── Data.tsx
│   │       ├── Fields.ts
│   │       ├── Internal.tsx
│   │       ├── Props.tsx
│   │       ├── Utils.tsx
│   │       ├── __tests__/
│   │       │   └── internal.spec.ts
│   │       └── index.ts
│   ├── create-puck-app/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── generate.js
│   │   └── templates/
│   │       ├── next/
│   │       │   └── package.json.hbs
│   │       ├── next-ai/
│   │       │   └── package.json.hbs
│   │       ├── react-router/
│   │       │   ├── package.json.hbs
│   │       │   └── tsconfig.json.hbs
│   │       ├── react-router-ai/
│   │       │   ├── package.json.hbs
│   │       │   └── tsconfig.json.hbs
│   │       ├── remix/
│   │       │   └── package.json.hbs
│   │       └── remix-ai/
│   │           └── package.json.hbs
│   ├── eslint-config-custom/
│   │   ├── index.js
│   │   └── package.json
│   ├── field-contentful/
│   │   ├── README.md
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── plugin-emotion-cache/
│   │   ├── README.md
│   │   ├── index.tsx
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── plugin-heading-analyzer/
│   │   ├── README.md
│   │   ├── globals.d.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── HeadingAnalyzer.module.css
│   │   │   └── HeadingAnalyzer.tsx
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── tsconfig/
│   │   ├── base.json
│   │   ├── nextjs.json
│   │   ├── package.json
│   │   └── react-library.json
│   └── tsup-config/
│       ├── index.ts
│       ├── package.json
│       └── react-import.js
├── recipes/
│   ├── next/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── puck/
│   │   │   │   ├── [...puckPath]/
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   └── page.tsx
│   │   │   │   ├── api/
│   │   │   │   │   └── route.ts
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── database.json
│   │   ├── lib/
│   │   │   └── get-page.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── proxy.ts
│   │   ├── puck.config.tsx
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   ├── next-ai/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── api/
│   │   │   │   ├── pages/
│   │   │   │   │   └── route.ts
│   │   │   │   └── puck/
│   │   │   │       └── [...all]/
│   │   │   │           └── route.ts
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── puck/
│   │   │   │   ├── [...puckPath]/
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   └── page.tsx
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── database.json
│   │   ├── lib/
│   │   │   └── get-page.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── proxy.ts
│   │   ├── puck.config.tsx
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   ├── react-router/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── components/
│   │   │   │   └── puck-render.tsx
│   │   │   ├── lib/
│   │   │   │   ├── pages.server.ts
│   │   │   │   └── resolve-puck-path.server.ts
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── _index.tsx
│   │   │   │   └── puck-splat.tsx
│   │   │   └── routes.ts
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── puck.config.tsx
│   │   ├── react-router.config.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── react-router-ai/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── components/
│   │   │   │   └── puck-render.tsx
│   │   │   ├── lib/
│   │   │   │   ├── pages.server.ts
│   │   │   │   └── resolve-puck-path.server.ts
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── _index.tsx
│   │   │   │   ├── api.puck.ts
│   │   │   │   └── puck-splat.tsx
│   │   │   └── routes.ts
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── puck.config.tsx
│   │   ├── react-router.config.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── remix/
│   │   ├── .eslintrc.cjs
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── entry.client.tsx
│   │   │   ├── entry.server.tsx
│   │   │   ├── models/
│   │   │   │   └── page.server.ts
│   │   │   ├── puck.config.tsx
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── $puckPath.tsx
│   │   │   │   ├── $puckPath_.edit.tsx
│   │   │   │   ├── _index.tsx
│   │   │   │   └── edit.tsx
│   │   │   └── styles/
│   │   │       └── shared.css
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── remix.config.js
│   │   ├── remix.env.d.ts
│   │   └── tsconfig.json
│   └── remix-ai/
│       ├── .eslintrc.cjs
│       ├── .gitignore
│       ├── README.md
│       ├── app/
│       │   ├── entry.client.tsx
│       │   ├── entry.server.tsx
│       │   ├── models/
│       │   │   └── page.server.ts
│       │   ├── puck.config.tsx
│       │   ├── root.tsx
│       │   ├── routes/
│       │   │   ├── $puckPath.tsx
│       │   │   ├── $puckPath_.edit.tsx
│       │   │   ├── _index.tsx
│       │   │   ├── api.puck.$.tsx
│       │   │   └── edit.tsx
│       │   └── styles/
│       │       └── shared.css
│       ├── database.json
│       ├── package.json
│       ├── remix.config.js
│       ├── remix.env.d.ts
│       └── tsconfig.json
├── scripts/
│   ├── create-changelog.js
│   ├── e2e/
│   │   ├── smoke-framework.mjs
│   │   ├── smoke.mjs
│   │   └── utils/
│   │       ├── drag-and-drop.mjs
│   │       ├── get-box.mjs
│   │       ├── pause.mjs
│   │       └── setup.mjs
│   ├── get-unstable-version.js
│   └── publish.sh
└── turbo.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintrc.js
================================================
module.exports = {
  root: true,
  // This tells ESLint to load the config from the package `eslint-config-custom`
  extends: ["custom"],
  settings: {
    next: {
      rootDir: ["apps/*/"],
    },
  },
  rules: {
    "react-hooks/exhaustive-deps": "off",
  },
  // eslint-config-next causes warning on Remix's default remix.config.js
  ignorePatterns: ["recipes/remix/remix.config.js"],
};


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: "Bug Report 🐛"
about:
  Report a problem with Puck. Please provide enough information to reproduce
  the problem.
title: ""
labels: ["type: bug 🐛"]
assignees: ""
---

## Description

[Example: "The `<Puck />` component doesn't render correctly inside a CSS grid layout..."]

<!--
  Provide a clear and concise description of the bug.
  Don't assume we know anything about your repository or codebase.
  Keep it centered around Puck—avoid detailing your use case unless it directly helps explain the issue.
  Test the issue using the latest version of Puck to confirm it hasn't already been fixed.
-->

## Environment

- Puck version: [0.19.0, 1.0.0...]
- Browser version: [Chrome 135 (desktop), Firefox 133 (mobile)...]
- Additional environment info: [bundler, OS, device type...]

<!--
  Detail the environment where the bug is occurring.
-->

## Steps to reproduce

1. Render the `<Puck />` component in a grid layout...

```tsx
const Editor = () => {
  return (
    <div style={{ display: "grid" }}>
      <Puck config={config} data={data} />
    </div>
  );
};
```

2. Run the application in development mode...

<!--
  Provide clear steps with code examples so that we can reproduce the bug.
  Avoid including dependencies other than Puck.
  Issues without reproduction steps or code examples may be closed as not actionable.
  For help on providing minimal, reproducible examples: https://stackoverflow.com/help/mcve
-->

## What happens

[Example: "A white screen appears and the editor doesn't load..."]

<!--
  State what is the result of the steps above.
  Keep the explanation short and clear.
-->

## What I expect to happen

[Example: "The Puck component should render correctly in any CSS layout..."]

<!--
  State what was the result you expected from the steps above.
  Keep the explanation short and clear.
-->

## Additional Media

<!--
  Include any screenshots, videos, or other relevant media that may help
  visualize the issue or demonstrate the behavior.
-->


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
    - name: Guidance - Discord 👾
      url: https://discord.gg/V9mDAhuxyZ
      about: This issue tracker is not for guidance. Please refer to the Discord server for live help and general guidance.
    - name: Questions and Help - Github Discussions 💬
      url: https://github.com/puckeditor/puck/discussions
      about: This issue tracker is not for support questions. Please open a discussion for that.

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: "Feature Request ✨"
about: "Share ideas for new features."
title: ""
labels: ["type: feature"]
assignees: ""
---

## Description

[Example: "Currently, the `text` field doesn’t support validation for maximum and minimum lengths. However, in many cases, you need to limit user input to specific constraints..."]

<!--
  Describe the expected outcome and why you want that outcome.
  Don’t provide implementation details, save that for the 'Proposals' section.
  Assume the person reading this has zero context about your problem or use case.
-->

## Considerations

- This might be related to field validation, which is currently being tracked in issue: #1...
- The file implementing the `text` field lives at `core/text.tsx`...

<!--
  List any special considerations for this feature that might help or make the changes more difficult.
  List any other issues that might be related or affected by this feature.
-->

## Proposals

### Proposal 1

[Example: "Introduce `min` and `max` props for the field configuration object and the `<AutoField />` component..."]

<!--
  Add a high-level description of how you'd like to see the feature implemented.
  Include code examples if appropriate.
  Discuss the pros and cons of the approach where necessary.
-->


================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      # Check for updates to GitHub Actions every week
      interval: "weekly"


================================================
FILE: .github/pull_request_template.md
================================================
Closes #XXXX

<!--
  Replace XXXX with the actual issue number this PR closes.
  Every PR should be linked to an issue.
  PRs without an issue may take longer to review or may be closed as non-actionable.
-->

## Description

This PR adds a `style` prop to the `Puck` component to allow customization of the editor layout styles.

<!--
  Include a concise and clear description of what this PR does.
  Mention any considerations or reasons behind the changes.
  Highlight any breaking changes.
  Keep the explanation centered around Puck.
 -->

## Changes made

- The `Puck` component now receives an optional `style` prop and passes it to the editor `div` wrapper.

<!--
  List the key changes made and the reasons behind them.
 -->

## How to test

- Render the `Puck` component with a two-column grid layout using the `style` prop and confirm it renders in two columns:

```tsx
<Puck style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }} />
```

<!--
  List any manual tests you did to verify the behavior of the changes.
  Add any media or screenshots that may help verify the outcome.
 -->


================================================
FILE: .github/workflows/ci.yml
================================================
# This workflow will run all checks required for a PR to be merged.

name: Build and Test ci

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 20

      - name: Check Yarn Version
        run: yarn --version

      - name: Install dependencies
        run: yarn

      - name: Run tests
        run: yarn test

      - name: Check linting and formatting
        run: |
          if yarn lint && yarn format:check; then
            echo "Linting and formatting checks passed."
          else
            echo "Linting or formatting checks failed. Please fix the issues."
            exit 1
          fi

      - name: Build everything
        run: |
          yarn build

      - name: Check for build failures
        run: |
          if [ $? -ne 0 ]; then
            echo "Build failed. Please fix the issues."
            exit 1
          fi


================================================
FILE: .github/workflows/publish-canary.yml
================================================
name: Publish canary release
on:
  push:
    branches:
      - "main"
      - "releases/**"

jobs:
  tag-and-publish-to-npm:
    runs-on: ubuntu-latest

    # Don't run on regular releases
    if: "!startsWith(github.event.head_commit.message, 'release: ')"
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 20
          registry-url: "https://registry.npmjs.org"

      - name: Install dependencies
        run: yarn

      - name: Run release script
        run: yarn release:canary

      - name: Publish all packages
        run: ./scripts/publish.sh canary
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

    timeout-minutes: 10


================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish release
on:
  push:
    branches:
      - "releases/**"
permissions:
  contents: write
jobs:
  tag-and-publish-to-npm:
    runs-on: ubuntu-latest
    if: "startsWith(github.event.head_commit.message, 'release: ')"
    steps:
      - uses: actions/checkout@v6.0.2
      - name: Extract version
        shell: bash
        run: echo "TAG_NAME=$(git log -1 --oneline --pretty=%B | sed 's/release:\ //g')" >> $GITHUB_ENV
      - name: Tag commit
        uses: tvdias/github-tagger@v0.0.1
        with:
          repo-token: "${{ secrets.GH_TOKEN }}"
          tag: ${{ env.TAG_NAME }}

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 20
          registry-url: "https://registry.npmjs.org"

      - name: Install dependencies
        run: yarn

      - name: Publish all packages
        run: ./scripts/publish.sh latest
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      # Trigger a new build to ensure Vercel creates a distinct release branch, rather than reusing latest
      - name: Triggering new build
        run: |
          git config --global user.name 'chrisvxd'
          git config --global user.email 'chrisvxd@users.noreply.github.com'
          git commit -m "ci: trigger build" --allow-empty
          git push

    timeout-minutes: 10


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
node_modules
.pnp
.pnp.js

# testing
coverage

# next.js
.next/
out/
build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# turbo
.turbo

# vercel
.vercel

# webstorm
.idea

dist

================================================
FILE: .npmrc
================================================
auto-install-peers = true


================================================
FILE: .nvmrc
================================================
20

================================================
FILE: .prettierignore
================================================
CHANGELOG.md

/.nx/workspace-data


================================================
FILE: .prettierrc.json
================================================
{}


================================================
FILE: .yarnrc
================================================
version-git-message "release: v%s"

================================================
FILE: CHANGELOG.md
================================================
# CHANGELOG

<!--__CHANGELOG_ENTRY__-->

## [0.21.1](https://github.com/measuredco/puck/compare/v0.21.0...v0.21.1) (2026-01-23)


### Bug Fixes

* don't throw when disabling listItem rich text extension ([4ca0a46](https://github.com/measuredco/puck/commit/4ca0a46e895e8a378bc743c4c06451dca8c00838))
* enforce disabled styles for rich text menu with no options ([3d56139](https://github.com/measuredco/puck/commit/3d56139a84912fcc5cc13142bd31df8b2d187368))
* ensure consistent plugin ordering in Firefox ([274c5f6](https://github.com/measuredco/puck/commit/274c5f6abd8585d015ece2b59d11da0b4914b6d0))
* ensure nested richtext fields render in <Render/> ([501a164](https://github.com/measuredco/puck/commit/501a1649afbb5fb4125146541e63b0f3fec3a962))
* prevent array item expansion when empty ([1a6682a](https://github.com/measuredco/puck/commit/1a6682a3bc0eaaae2f6ffe1a2d20656d8d647a65))
* prevent block deletion on backspace in rich text in Firefox ([71c8664](https://github.com/measuredco/puck/commit/71c8664dd7f0fe7d971ebcd4992167df2e45bcc1)), closes [#1529](https://github.com/measuredco/puck/issues/1529)
* replace missed fast-deep-equals with fast-equals ([ffa5171](https://github.com/measuredco/puck/commit/ffa5171c1732875df9a82934a4924b0e86750161))




## [0.21.0](https://github.com/measuredco/puck/compare/v0.20.2...v0.21.0) (2026-01-14)


### Bug Fixes

* account for drags during slow resolveData on insert ([dfecd01](https://github.com/measuredco/puck/commit/dfecd012a0f1a7527f2d3b58449448d3f770dc6e))
* account for drags during slow resolveData on update ([304940a](https://github.com/measuredco/puck/commit/304940aedd9c7d8bf72686d923dc8c4d9b9b91b6))
* add missing ref prop to Slot render types ([ac9eba2](https://github.com/measuredco/puck/commit/ac9eba2f603bcea4bfa9508af3e57272ed23eafa))
* automatically set IDs for slots in root defaultProps ([f5820ce](https://github.com/measuredco/puck/commit/f5820ce9366bea60e02a62d8ed215dbb8a7d13fb))
* check the user provides a name in create-puck-app ([b1de8bf](https://github.com/measuredco/puck/commit/b1de8bf3c155e177e6ff3e600dad85232508aad6))
* don't unmount sidebars on hide ([ceebd0f](https://github.com/measuredco/puck/commit/ceebd0fb3deb5ce0853cbaf0aa37ffa8c24ed49c))
* handle exits gracefully from create-puck-app ([abfa3c3](https://github.com/measuredco/puck/commit/abfa3c3972ebd1487e6495cbf40614bb9f1503a7))
* memoize initialHistoryIndex and check the index provided by the user is not out of bounds ([ec77dd9](https://github.com/measuredco/puck/commit/ec77dd9f118f36f424be5695df95e8285d890102))
* mitigate CVE-2025-57822 in Next.js recipe ([74d9a16](https://github.com/measuredco/puck/commit/74d9a16040dcc135dbac9cdd82792ef35383680c))
* prevent empty objects from causing parent re-render ([a4bfae4](https://github.com/measuredco/puck/commit/a4bfae4f202ddaab12294cfffd2664d809e7cb54))
* prevent frame overflowing on small viewports when embedded ([5c9515c](https://github.com/measuredco/puck/commit/5c9515c9b45b926ceb07da0a4c1dd74146ad2e9f))
* prevent valueOf errors due to fast-deep-equals ([16a3eee](https://github.com/measuredco/puck/commit/16a3eee1a81f4df275dfbbb0903d4274ecaeb400))
* prioritize disableDrag in overlay portals ([1df9dde](https://github.com/measuredco/puck/commit/1df9ddebfaf400ad6a65f90d4750dd95009f2549))
* reset keystrokes when window is blurred ([5333fc7](https://github.com/measuredco/puck/commit/5333fc7e3d0a5b08b531aaccea60086f64d34b36))
* respect custom root label in breadcrumb navigation ([de0baf3](https://github.com/measuredco/puck/commit/de0baf3937f5c902472c97c03c59c994b20643e4))
* respect ui changes in replace action ([af2d5ac](https://github.com/measuredco/puck/commit/af2d5ac8534798f9460743f63f077b80019b2909))
* restore valid type for renderDropZone prop ([29ef713](https://github.com/measuredco/puck/commit/29ef7131cfb43172c9194d2ab74fa89cc4bb630a))
* retain overlay if dragRef changes ([e310a17](https://github.com/measuredco/puck/commit/e310a1755eda8dd1b60999c047bf0708440c9679))
* run resolve permissions in slots ([cf074bc](https://github.com/measuredco/puck/commit/cf074bc6cb52e66e08bf6e36199ad9e89b0f19fb))
* show title instead of undefined in React Router recipe ([68f8542](https://github.com/measuredco/puck/commit/68f8542800eae35f28863de2f53a31864e995618))
* use latest reference for onChange callback ([b818cb1](https://github.com/measuredco/puck/commit/b818cb1fa24ba673d9264f1525b75bc62599e301))


### Features

* add "as" API to change slot element type ([1cec93c](https://github.com/measuredco/puck/commit/1cec93c4e698fba94a80bf0b4f6354b7317714fc))
* add "richtext" field ([301595f](https://github.com/measuredco/puck/commit/301595f6232da4883eb3e5ed3b48aabeea7027ab))
* add ActionBar.Separator component ([410819e](https://github.com/measuredco/puck/commit/410819e7cc6b507e6b95a9d1f07dd2721f567c81))
* add active API to IconButton ([8116c86](https://github.com/measuredco/puck/commit/8116c86168a27a52655ff2dcdc7dfdda849abb22))
* add cache control to external fields ([a5160e5](https://github.com/measuredco/puck/commit/a5160e5d600989c1651ae85ea05628ab0ed5cd1a))
* add delete hotkeys for removing components ([20aafb6](https://github.com/measuredco/puck/commit/20aafb6a89f601c6a14fa0765f40288793977f4f))
* add disabled option to ActionBar.Action ([32d0666](https://github.com/measuredco/puck/commit/32d0666afa1be3e873a7a4f05c14eb5a9d57569e))
* add experimental full-screen canvas support ([c15c4f8](https://github.com/measuredco/puck/commit/c15c4f876c3fedba4146e6df226cd0d64fbd1832))
* add full-width viewport to fit to container ([7373a6b](https://github.com/measuredco/puck/commit/7373a6bdf06524f53dd7ac97d8fc3d79b8e95d22))
* add getParentById for getting the parent data for a child id ([38e79ba](https://github.com/measuredco/puck/commit/38e79ba80a1eef9fcd42f2d8b980c7a198306d57))
* add key parameter to force custom field remounting ([ace4c8b](https://github.com/measuredco/puck/commit/ace4c8b354107b8bf7b4cd54a3924911f23beb10))
* add parent to resolveData APIs and trigger resolveData on move ([7c2f928](https://github.com/measuredco/puck/commit/7c2f92837723cd772791e373b98a704de89b1214))
* add Plugin Rail, a menu for plugins ([86526e7](https://github.com/measuredco/puck/commit/86526e7c3d1afedf088b0cc31284f058c04ad698))
* add puck ai option to create-puck-app ([d1f05aa](https://github.com/measuredco/puck/commit/d1f05aa0ee05105b30c516198f8e3b84ce50ae95))
* add resolveDataById utility to Puck API ([12f0a21](https://github.com/measuredco/puck/commit/12f0a2194d4d76a18e9d54d101483777bb9db181))
* add resolveDataBySelector utility to Puck API ([4f0b390](https://github.com/measuredco/puck/commit/4f0b390e691b327038cf112a471f4ef9fe7844a9))
* de-select component on second click ([ccff0d8](https://github.com/measuredco/puck/commit/ccff0d8e33f5424556fff398667178a0d8bb79f7))
* enable modification of Puck height ([538f7bf](https://github.com/measuredco/puck/commit/538f7bffa8be556a828b5f5566a1fbfbc00702c3))
* export ConfigParams and ComponentConfigParams for convenience ([0f9606c](https://github.com/measuredco/puck/commit/0f9606c645afd9e1f5097cb05cc53f729bcbb803))
* expose default layout via Puck.Layout ([4a8e38f](https://github.com/measuredco/puck/commit/4a8e38f8d0356b59d04e41a47e1cc2138b61b63a))
* extend Plugin API with support for Plugin Rail ([d68edca](https://github.com/measuredco/puck/commit/d68edcae12f2740dd89b4c2206718f5ce0cb22bf))
* improve mobile interface ([3daa05e](https://github.com/measuredco/puck/commit/3daa05e762b241b4d8b739f4e2be4cfeaa8c94b1))
* provide metadata to resolveFields ([6dae6cb](https://github.com/measuredco/puck/commit/6dae6cb73d63dae6ad119f0c0721f4e69e989770))
* provide parent data to resolvePermissions API ([1b69a8f](https://github.com/measuredco/puck/commit/1b69a8f3ef2d5f44f592598c302cec5ebc787cde))
* rename package to @puckeditor/core ([d1c0d6a](https://github.com/measuredco/puck/commit/d1c0d6a25d01d51f2489391e65540566c72278ab))
* support CSS units for minEmptyHeight in slots ([79a2684](https://github.com/measuredco/puck/commit/79a2684949b6aaa98cd85c4ca6ed13e3e585124f))
* support dynamic props for default array items via function ([6c44fdb](https://github.com/measuredco/puck/commit/6c44fdb9704618d2189157edc183be9e21432436))
* support extending all field types via declaration merging ([26fd286](https://github.com/measuredco/puck/commit/26fd286164d41b14e90804187fa28adca1e1be43))
* support extending ComponentConfig via declaration merging ([3c46c44](https://github.com/measuredco/puck/commit/3c46c447b6dae5b6c23f4ad238820bf4c700e465))
* support overrides for custom fields ([89038d0](https://github.com/measuredco/puck/commit/89038d0c986f54c70202b27fb6ed836678828b8d))
* support React nodes in getItemSummary for array fields ([73b98fb](https://github.com/measuredco/puck/commit/73b98fb4671bbac87a408538f6561bbb402c9b1c))
* support typing metadata via declaration merging ([66c5aa3](https://github.com/measuredco/puck/commit/66c5aa399a197b1fef1a18a1bad106794dffdca5))
* use dashed outline for overlay portals ([f79baa9](https://github.com/measuredco/puck/commit/f79baa98320854af545be8f31b125af7e1733b83))
* use next@^16.0.8 in create-puck-app ([313bbb5](https://github.com/measuredco/puck/commit/313bbb53cb426c5c6ae0fbf519a1b7536c56141f))


### Performance Improvements

* don't remount slot when parent changes ([a7a6599](https://github.com/measuredco/puck/commit/a7a659972e4229050edc7d3cecf868146f5abf6d))
* eliminate unnecessary re-renders in fields ([b633e3b](https://github.com/measuredco/puck/commit/b633e3b5339ba660c769838054b2bbf1fa781e43))
* prevent re-rendering of user components on hover ([a62292f](https://github.com/measuredco/puck/commit/a62292fd052ba62f21b04b95148bdcb281ff2457))




## [0.20.2](https://github.com/measuredco/puck/compare/v0.20.1...v0.20.2) (2025-09-05)


### Bug Fixes

* add CommonJS export to emotion cache package.json ([fbf3bd1](https://github.com/measuredco/puck/commit/fbf3bd1038a4c39d4e0c5079c3af33dd515c590b))
* bypass resolveData cache when trigger is force ([eea53e0](https://github.com/measuredco/puck/commit/eea53e0464c15e7c2f964da973a16a04160224b8))
* preserve selection when switching viewports and using zoom select ([38514a1](https://github.com/measuredco/puck/commit/38514a169592a3ffbaaedcfcb5b92767ba07b0e7))
* prevent hidden category components from showing in 'Other' ([8333eaf](https://github.com/measuredco/puck/commit/8333eaf7e27d3225fb7133fe14326e1f8e93776a))




## [0.20.1](https://github.com/measuredco/puck/compare/v0.20.0...v0.20.1) (2025-08-19)


### Bug Fixes

* address type issues when using root ([38076a9](https://github.com/measuredco/puck/commit/38076a94bcafbb9905d197195a750928ade757ab))
* don't widen getItemSummary type for array fields ([92112b9](https://github.com/measuredco/puck/commit/92112b9f1e012cdd1ec9fdfe62e4573da36327f4))
* don't widen getItemSummary type for external fields ([e58ac42](https://github.com/measuredco/puck/commit/e58ac425398ec115456eda9b4650031359fffa6d))
* fix slots within array and object fields ([b7fba1b](https://github.com/measuredco/puck/commit/b7fba1b46ba2678e775632a4f5be4a9a1e5be7cf))
* render spaces/line breaks consistently in inline text fields ([6c58995](https://github.com/measuredco/puck/commit/6c58995b9db7897bd8994a3f2fb1b2456ef32b2f))
* strip line breaks when pasting into inline text field ([2533c55](https://github.com/measuredco/puck/commit/2533c552a3222e47ffcfb1450ecf95fc4e78fb4a))




## [0.20.0](https://github.com/measuredco/puck/compare/v0.19.3...v0.20.0) (2025-08-14)


### Features

* add componentOverlay override ([1a47857](https://github.com/measuredco/puck/commit/1a47857137a1fb7a4c52579e4687a6ae06606e99))
* add fieldTransform API for modifying field values rendering in canvas ([e67152b](https://github.com/measuredco/puck/commit/e67152bd3e9ef85e3550ee184a0238d6c0ae8da8))
* add inline text editing to custom fields ([042f4b2](https://github.com/measuredco/puck/commit/042f4b2fc06175d6ded53c83fd653c1eb9095c6a))
* add inline text editing to text and textarea fields ([ed7c12e](https://github.com/measuredco/puck/commit/ed7c12e3398e76f3c680344bfa6be87abb803afb))
* add no-external.css bundle without external fonts ([d97af5e](https://github.com/measuredco/puck/commit/d97af5ee2eb5ecd9c704b2b5c3f3c2cde6f660a5))
* add overlay portals for interactive UI under overlay ([7d50c23](https://github.com/measuredco/puck/commit/7d50c2325a16166021c0c99520816c55682a272b))
* add setDeep convenience utility ([676e2ab](https://github.com/measuredco/puck/commit/676e2aba846c0182d1079e0290e124255b9db0a8))
* enable resizing the sidebars ([8909f8c](https://github.com/measuredco/puck/commit/8909f8cc1451a1bf5bc0abe51a564f4a0daa6d75))
* export SlotComponent type ([d12fc3a](https://github.com/measuredco/puck/commit/d12fc3a9f4edbac5a556e9714bcf2118cc441f4d))
* extend migrate function to support dynamic DropZones to slots ([3da831b](https://github.com/measuredco/puck/commit/3da831b0975b065e0b9a0062a4c2ae8e8cc9d94a))
* make overrides optional in plugins ([baed208](https://github.com/measuredco/puck/commit/baed208b685639f3f1104def34408d8252b38dbe))
* rename components & componentList overrides to drawer & drawerItem ([e40fdfe](https://github.com/measuredco/puck/commit/e40fdfe14c366258ea6b83e415d1c510cf7b0e46))
* simplify generic type API on Config and ComponentConfig ([04fc574](https://github.com/measuredco/puck/commit/04fc574bc08129f60863fd4ca23f634f616ba6bb))
* support object, null and undefined in select/radio options ([6dace1c](https://github.com/measuredco/puck/commit/6dace1cf3d49c6fd78eaf2e397399dc38f53412c))
* support theming of font family ([6cf56a8](https://github.com/measuredco/puck/commit/6cf56a8a7cd7211490d2549cc7ae2af76becef1d))


### Bug Fixes

* add missing tiny-invariant dependency in remix recipe ([d405985](https://github.com/measuredco/puck/commit/d405985b80527ae633f7f472af73cfca4acb1cef))
* address error when using disallow on a slot in root ([93d525c](https://github.com/measuredco/puck/commit/93d525c57f513260f0a60cbb710308e820becd1d))
* don't revert custom Drawer.Items during drag ([0578004](https://github.com/measuredco/puck/commit/057800431be6530bfef8e2c8ea3d79245f2bdb14))
* ensure nested name is propagated to custom fields ([f09540d](https://github.com/measuredco/puck/commit/f09540db9e5ad9ff0bd0987a38c0e586f7fa8965))
* prevent field zoom on mobile devices ([660fd08](https://github.com/measuredco/puck/commit/660fd08af21841d52804e37a3a4503bbbc019ea0))
* prevent iframe hanging when stylesheets empty ([ea0610a](https://github.com/measuredco/puck/commit/ea0610acbaa47f5a20627afabebaf6b98630d9a3))
* reattach inline ref if element changes ([ba585f9](https://github.com/measuredco/puck/commit/ba585f93711b55bd100a2ebb7560d5d6b20fa28d))
* remove erroneous get() API from usePuck ([c119ed0](https://github.com/measuredco/puck/commit/c119ed0d0d707aefa1003efb9448ef736f7ce60c))
* respect user generic in usePuck hook ([6760121](https://github.com/measuredco/puck/commit/6760121f9f2a37ac990477e5b67c8d9f17cb9601))
* respect user types in getItemBySelector and getItemById ([f2d031f](https://github.com/measuredco/puck/commit/f2d031fb1285bb31989943e3090461ebc150180f))
* retain DropZone content in interactive mode ([d2e09bd](https://github.com/measuredco/puck/commit/d2e09bdc1ddd8d1973c08dbe9e75cdf232e9c259))
* retain metadata in interactive preview mode ([68dd73b](https://github.com/measuredco/puck/commit/68dd73b8a1209923e1c2b2efca0c36fd935a207c))
* support user-defined fields in overrides ([5cb4cc6](https://github.com/measuredco/puck/commit/5cb4cc652e5db3a54580eb0215932ddc6a648fc9))
* type object, array, and external field types correctly ([f768aab](https://github.com/measuredco/puck/commit/f768aab935ed9c5955dd558f249f29e347bc52f7))
* type user fields in overrides ([54d71e3](https://github.com/measuredco/puck/commit/54d71e34017c3319b6db2352fd4551277501d0ee))




### Performance Improvements

* don't render array fields unless open ([14d9681](https://github.com/measuredco/puck/commit/14d968176a62b68af7fab764138a9d7e0b1f74ec))




## [0.19.3](https://github.com/measuredco/puck/compare/v0.19.2...v0.19.3) (2025-07-15)


### Bug Fixes

* don't duplicate content in Render when using multiple root DropZones ([412cc57](https://github.com/measuredco/puck/commit/412cc57d9f800e7f862bb4dd59ea4fc8056daea3))




## [0.19.2](https://github.com/measuredco/puck/compare/v0.19.1...v0.19.2) (2025-07-11)


### Bug Fixes

* ensure setHistories resets the appState ([7cccfdd](https://github.com/measuredco/puck/commit/7cccfddf2c3c74ea8b17b1e6dda7dbdc2e231022))
* prevent icon buttons from submitting parent form ([5f6f6d8](https://github.com/measuredco/puck/commit/5f6f6d8e8e2e33281ff235a51786d1af9a6e5622))
* release ctrl/cmd when tab changes ([37d387b](https://github.com/measuredco/puck/commit/37d387bddec49f03dc10b1df6f72768bf39b24dd))
* respect slot label in outline panel ([cccf912](https://github.com/measuredco/puck/commit/cccf9125587f14ee1336447a4e63e044af787ca6))




## [0.19.1](https://github.com/measuredco/puck/compare/v0.19.0...v0.19.1) (2025-06-09)


### Bug Fixes

* address flat package import errors ([61f2e46](https://github.com/measuredco/puck/commit/61f2e46822471fcdbc52476eaae813a3fb2dd27b))
* handle multiple slots in migrate function ([8597105](https://github.com/measuredco/puck/commit/859710536bc17102f73db6b9cd411c55e1ed6517))
* prevent type erasure in object props ([00fbbb8](https://github.com/measuredco/puck/commit/00fbbb8ae2217e38a304a4114069c4e124a1a28f))
* tidy internal index when array slots removed ([f9d3f0e](https://github.com/measuredco/puck/commit/f9d3f0e93f21735b9a3fb605b4eed4fa8c7ded3e))




## [0.19.0](https://github.com/measuredco/puck/compare/v0.18.2...v0.19.0) (2025-06-04)


### Features

* add convenience metadata API to fields ([5fe936e](https://github.com/measuredco/puck/commit/5fe936e08d2f27f663e8849fc59f20973a289332))
* add getItem helpers to usePuck ([ad947d8](https://github.com/measuredco/puck/commit/ad947d8c2f9f25bb71585f7158900292237a46d4))
* add labelIcon param to all fields for custom label icons ([24030a9](https://github.com/measuredco/puck/commit/24030a9caa4091382561019c9adc123839a90569))
* add mapSlots helper function for manipulating slot data ([a27944f](https://github.com/measuredco/puck/commit/a27944ff7c1135c9ee582ff41173b060dd0d79bf))
* add metadata API for passing data to every component ([b9add22](https://github.com/measuredco/puck/commit/b9add22951755737e272dbf6e475e24198c401ec))
* add placeholder param for text, textarea and number fields ([32a6f78](https://github.com/measuredco/puck/commit/32a6f7844b7bd3962a16fd2c6989b412aa91685f))
* add react-router v7 recipe ([706ea0c](https://github.com/measuredco/puck/commit/706ea0c1f0d9237046675674903a0ba7f61fd785))
* add replaceRoot action to dispatcher ([586eccd](https://github.com/measuredco/puck/commit/586eccd6f3d80af6a4f43001f5d51feb29eeb887))
* add selector to usePuck for improved performance ([8976e5f](https://github.com/measuredco/puck/commit/8976e5f28736d97d61a99f6e219e88797d67e309))
* add slots API ([40bc2ee](https://github.com/measuredco/puck/commit/40bc2eec7e5b409cb2479dc10a989b7b5824ae60))
* add step parameter to number fields ([0ea6ce4](https://github.com/measuredco/puck/commit/0ea6ce41281710ceecdc5dee8a632c06004244f8))
* add useGetPuck hook for getting latest internal PuckApi ([1d9a47d](https://github.com/measuredco/puck/commit/1d9a47d78ff0e239ef343f851ef0e5e5de8e1d0d))
* add visible param to show/hide fields ([e5911f3](https://github.com/measuredco/puck/commit/e5911f3d075bcc560672f27e7b74849ab8c6df50))
* deprecate DropZone component ([d54145d](https://github.com/measuredco/puck/commit/d54145d8bedf6df319620fde82d867edb9d034e3))
* export package.json for module federation ([b918900](https://github.com/measuredco/puck/commit/b918900b1ffbd4de46c405a73b6a5c74f8db76f5))
* expose CustomFieldRender type for custom field render functions ([8d459e4](https://github.com/measuredco/puck/commit/8d459e4e848f70e0256c736b1b6cd58081ff7cb7))
* expose RootConfig type ([638e066](https://github.com/measuredco/puck/commit/638e066fb655bc3e258093bf2428189f3afd88f9))
* expose WithSlotProps type ([6dc5101](https://github.com/measuredco/puck/commit/6dc5101e26093960a528c9c908acebfe2c917b4e))
* provide `trigger` event to resolveData parameters ([55b42ae](https://github.com/measuredco/puck/commit/55b42aeeddbc1ada53646bf93c29592523c27e54))
* rename mapSlots to walkTree ([427e686](https://github.com/measuredco/puck/commit/427e686fdd2a54f35b2de5370bad289a4d409873))
* support slots in transformProps via optional config arg ([7d59b94](https://github.com/measuredco/puck/commit/7d59b94046e121b4e6afa7e502a66f43a2b236c7))


### Performance Improvements

* eliminate most re-renders ([9fcd968](https://github.com/measuredco/puck/commit/9fcd96851fd1472890c5846183f64d62a3a2643f))
* eliminate re-renders during drag operations ([3ba3ac5](https://github.com/measuredco/puck/commit/3ba3ac51b0733be0c2ce822d9dd82524873a31d3))


### Bug Fixes

* account for transforms in overlays ([22f5e3a](https://github.com/measuredco/puck/commit/22f5e3a37611e4d86c43ace936b0ffbbfaf9dd90))
* add missing `id` to changed type for resolvers ([eb4f9d8](https://github.com/measuredco/puck/commit/eb4f9d857952ee3323447c355edb9fd3d6770716))
* avoid query selector collision with multiple iframes ([2c1db86](https://github.com/measuredco/puck/commit/2c1db862bfddfee06c78bcf211ece0b9400bec58))
* bind array item to correct field when using multiple arrays ([7e231b7](https://github.com/measuredco/puck/commit/7e231b782e49162f2b5050ba17fa4178af6ec7c8))
* deeply check items before populating resolveData changed ([db75e42](https://github.com/measuredco/puck/commit/db75e42b85cfd2cff38bc633d0cd0335213db1fa))
* don't artificially constrain array items to container ([36b5713](https://github.com/measuredco/puck/commit/36b5713d04e6ad1d116faa25e41fc9683dddb09e))
* don't collide with parent if component contains drop zone ([e7d2371](https://github.com/measuredco/puck/commit/e7d237137f3381b517eebf39bedf29997e76d4fa))
* don't render array item until dropped ([1dfc1b3](https://github.com/measuredco/puck/commit/1dfc1b334678ad5b63de0919c92e810bbea19311))
* don't reset old values when modifying fields in other array items ([ad78e98](https://github.com/measuredco/puck/commit/ad78e98fc7f711da476fa0678a702fd4aa0310d2))
* don't track dragged headings in heading-outline-analyzer ([2e1a24e](https://github.com/measuredco/puck/commit/2e1a24ed77aa5157647ad93a9dfe2e0723f38cd1))
* ensure array items can be opened on mobile ([a60c81e](https://github.com/measuredco/puck/commit/a60c81eb4836c368c90cd1d000c77cecc33610cb))
* ensure file inputs work inside array fields ([83f8f2d](https://github.com/measuredco/puck/commit/83f8f2d7a1eab1bd7a9c182c5435b3782d3dc720))
* ensure nested array fields are draggable ([af4f756](https://github.com/measuredco/puck/commit/af4f756348db1a13c6e3139890e2d8b6750a1dc2))
* export migrate util in RSC bundle ([2568ac3](https://github.com/measuredco/puck/commit/2568ac34b4e6f5f00b3c0840b409d6b4f9655e03))
* expose transformProps in server bundle ([020071e](https://github.com/measuredco/puck/commit/020071e4a8820880b5c5e3389a71b97ce7d9ad4e))
* fix undo/redo hotkeys for Windows ([a994207](https://github.com/measuredco/puck/commit/a994207e11e6f04cfd23cf827f5e7176a87bab1e))
* prevent ActionBar clipping if it exceeds top bounds ([56f23e8](https://github.com/measuredco/puck/commit/56f23e8166e9ddf96f929d9f52faa072af2e98da))
* prevent horizontal scroll on touch  devices ([cb4b6ee](https://github.com/measuredco/puck/commit/cb4b6ee597f6e603bc084de3458195e3dfb6b84f))
* prevent input-type fields from exceeding container boundaries ([b22833e](https://github.com/measuredco/puck/commit/b22833ee9d3365789fe38d4350c79ee43b8441a1))
* prevent item from sometimes sticking to window during drag ([e62832e](https://github.com/measuredco/puck/commit/e62832e171de88e2710581d3a3096d5d759d2d63))
* reflect resolveData value changes in fields ([69dd799](https://github.com/measuredco/puck/commit/69dd799d0bb20ca2baa0bd206f84a575b68dbd70))
* remove erroneous React 17 from supported peer dependencies ([46212f0](https://github.com/measuredco/puck/commit/46212f0fdb11c2327d92317551a1503646f10e03))
* remove unexpected license from recipes ([7010bdc](https://github.com/measuredco/puck/commit/7010bdc2f971cb4ee535524e40b3d5c01a5e48f3))
* reorder array items more predictably ([64c65c3](https://github.com/measuredco/puck/commit/64c65c32ef6f8130832d11c1b532563890b9dcfe))
* reset stacking context in Puck entry ([6bf9c99](https://github.com/measuredco/puck/commit/6bf9c995ce8e3445e350fa864978fc2dabec52be))
* restore ability to drop between sibling zones ([2807cba](https://github.com/measuredco/puck/commit/2807cbaa83a161974802886ec8d12d555cf8c65d))
* restore field values during undo/redo ([6917928](https://github.com/measuredco/puck/commit/6917928d3ce053eee214c438268dbd115520c1f6))
* retain minimum height when ActionBar is empty ([a52ccb9](https://github.com/measuredco/puck/commit/a52ccb96abdd37ade8a76e12f902b56d5f4f4efd))
* set ready status more reliably when using strict mode ([5a526d0](https://github.com/measuredco/puck/commit/5a526d0a2fffdd243c8eb191961bd136639f75f2))
* show correct styles when insert permission is disabled ([f19cdca](https://github.com/measuredco/puck/commit/f19cdcab2c3579f38ad79c55f168bdfba5699ed2))
* show top border on array button when array empty ([add5a17](https://github.com/measuredco/puck/commit/add5a175286036bd029113b2746bc0c94fa0a2ff))
* still select item from outline if element not in document ([8e1d722](https://github.com/measuredco/puck/commit/8e1d722355409e0985195415a4b05e56a62af470))
* support strings in readOnly type for arrays and object ([9358a3b](https://github.com/measuredco/puck/commit/9358a3b53f245a1caf245ee984da8017edac3fc6))


## [0.18.3](https://github.com/measuredco/puck/compare/v0.18.2...v0.18.3) (2025-04-05)


### Bug Fixes

* bind array item to correct field when using multiple arrays ([934cfae](https://github.com/measuredco/puck/commit/934cfaeed36b9737cd51c0d400b4e7ec8686ae35))
* don't artificially constrain array items to container ([648a235](https://github.com/measuredco/puck/commit/648a235f5bb20b276f7fc307e81842b1215838f9))
* don't render array item until dropped ([94f5e23](https://github.com/measuredco/puck/commit/94f5e238e2a8dd2ec5b3eba211d1160a2faa739a))
* don't reset old values when modifying fields in other array items ([73c17b3](https://github.com/measuredco/puck/commit/73c17b30d1c13a8971731942f690c44ddc1794cc))
* don't track dragged headings in heading-outline-analyzer ([3c16391](https://github.com/measuredco/puck/commit/3c16391bc8085cbddc910f70657e440471216995))
* ensure file inputs work inside array fields ([746033f](https://github.com/measuredco/puck/commit/746033f53623b1824f31e987339737fd92ce38dc))
* ensure nested array fields are draggable ([0bdd243](https://github.com/measuredco/puck/commit/0bdd2434a254151cfbe636840ed1294fef5c0c26))
* expose transformProps in server bundle ([d234345](https://github.com/measuredco/puck/commit/d234345c73d530803f3effb1c8a458353ac006e2))
* prevent ActionBar clipping if it exceeds top bounds ([e8355f0](https://github.com/measuredco/puck/commit/e8355f09c668baa044629d923076c59817d43072))
* remove erroneous React 17 from supported peer dependencies ([98ad734](https://github.com/measuredco/puck/commit/98ad73412c1addb9214a3d953d962f401f044a3f))
* reorder array items more predictably ([659f2d8](https://github.com/measuredco/puck/commit/659f2d8fc0c3c4511211a4933e0337ab771b29dd))
* show top border on array button when array empty ([7442118](https://github.com/measuredco/puck/commit/7442118598793d808c80535428dd21de9315daa1))




## [0.18.2](https://github.com/measuredco/puck/compare/v0.18.0...v0.18.2) (2025-01-31)


### Bug Fixes

* add missing types for root render method ([0f52caf](https://github.com/measuredco/puck/commit/0f52caf0a3d77978d913b0915bbb23725fc94a3d))
* address ownerDocument permission error in Firefox ([c22b3a9](https://github.com/measuredco/puck/commit/c22b3a9838fad6c65c71091eb89bb9104b6aabaf))
* address prop name collision regression ([3a69ad4](https://github.com/measuredco/puck/commit/3a69ad4ac3e982340b3fcae6b5773240d88e7f92))
* correctly infer types when using Render with RSC ([ad7fbf4](https://github.com/measuredco/puck/commit/ad7fbf4bc7534cfb348dd7fdbac56b84b03552e3))
* don't jump to end of textarea fields during change ([36c27a9](https://github.com/measuredco/puck/commit/36c27a9c166affc83ecfd36f79974cb9990917c6))
* don't trigger clicks when dropping array items ([29a7f1d](https://github.com/measuredco/puck/commit/29a7f1df55f1eff6bee55ee7984ec7974a4feaec))
* don't trigger drag when interacting with array fields ([c7cd341](https://github.com/measuredco/puck/commit/c7cd34165cbde90ae0297ab79a1ea6852f9d9726))
* ensure ctrl+i interactive toggle hotkey works on Windows ([5db6f4d](https://github.com/measuredco/puck/commit/5db6f4d5f90b222423df363e9964ec344b9a0a7e))
* ensure renderDropZone provided correctly to root render ([b9ce5b7](https://github.com/measuredco/puck/commit/b9ce5b700056f985362d1f4a9125996badfcbdd7))
* fix RTL drag-and-drop behaviour ([28f518a](https://github.com/measuredco/puck/commit/28f518aad9da211042e3b51e52369b6c126c75d8))
* improve behaviour of array drag-and-drop ([565fabd](https://github.com/measuredco/puck/commit/565fabdaa78f92fdbb327d878d7142e0455f5e8a))
* provide empty readOnly object instead of undefined to root resolveFields ([8992a94](https://github.com/measuredco/puck/commit/8992a9476ab2bc3837bb986bbd3e1042babd81a8))
* provide updated props to resolveFields ([b7ff689](https://github.com/measuredco/puck/commit/b7ff6898618a1a30b07a85669f16e891db975ffd))
* reinstate padding for external field filters ([28ccfda](https://github.com/measuredco/puck/commit/28ccfdaf8b6c546464df18f1a3ebb2b8b6363dc7))
* tidy up stale items on drag cancellation ([de48691](https://github.com/measuredco/puck/commit/de48691b017a66c251616ba31861bd0b8816ef68))
* update styles for RTL ([23c8dda](https://github.com/measuredco/puck/commit/23c8dda031b0f50e30eacdb15d3a774bd8045879))
* use correct type for onChange args when overriding fieldTypes ([daff71e](https://github.com/measuredco/puck/commit/daff71ef726ad74d2b5628c466b2ddbaa1850160))




## [0.18.1](https://github.com/measuredco/puck/compare/v0.18.0...v0.18.1) (2025-01-24)


### Bug Fixes

* address React 19 peer dependency issues ([7649086](https://github.com/measuredco/puck/commit/7649086009deb9b9ceb5c4790e9c356b107a20b6))
* address ResizeObserver loop error ([d3e6b57](https://github.com/measuredco/puck/commit/d3e6b57190e3f6e8a4f857a45a51cbb060daf050))
* don't access selectedItem if undefined right after drop ([0573b18](https://github.com/measuredco/puck/commit/0573b182452f1c614a15f4125fefa81a880e37a2))
* ensure nested drag-and-drop works in Firefox ([f077a37](https://github.com/measuredco/puck/commit/f077a37158194867a10c1406252fe4a8f4f6974c))




## [0.18.0](https://github.com/measuredco/puck/compare/v0.17.1...v0.18.0) (2025-01-21)


### Features

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


### Bug Fixes

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



## [0.17.4](https://github.com/measuredco/puck/compare/v0.17.3...v0.17.4) (2025-01-19)


### Bug Fixes

* handle null when provided to text/textarea/number fields ([e778246](https://github.com/measuredco/puck/commit/e778246e4ae8925f3d04962369a33a9c1a4b6589))
* improve stability of resolveFields API ([5c60d6a](https://github.com/measuredco/puck/commit/5c60d6a11512086f395ace352eec868fcd748f44))
* respect allow prop for existing items ([e414e34](https://github.com/measuredco/puck/commit/e414e34680acb7259dcee1da081060f5be923c02))




## [0.17.3](https://github.com/measuredco/puck/compare/v0.17.2...v0.17.3) (2025-01-13)


### Bug Fixes

* ensure items in root DropZone can be selected ([f61dd4a](https://github.com/measuredco/puck/commit/f61dd4a955e6c09d49f4fc1967e1cac5445697f7))




## [0.17.2](https://github.com/measuredco/puck/compare/v0.17.1...v0.17.2) (2025-01-10)


### Bug Fixes

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




## [0.17.1](https://github.com/measuredco/puck/compare/v0.17.0...v0.17.1) (2024-12-18)


### Bug Fixes

* respect falsey booleans types in select/radio fields ([3406b01](https://github.com/measuredco/puck/commit/3406b01d5ce00e8f2b885a1f951b5c96aa7a7989))




## [0.17.0](https://github.com/measuredco/puck/compare/v0.16.2...v0.17.0) (2024-12-18)

### Features

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


### Bug Fixes

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




## [0.16.2](https://github.com/measuredco/puck/compare/v0.16.1...v0.16.2) (2024-11-07)


### Bug Fixes

* always treat data as immutable, fixing Redux issues ([51154e9](https://github.com/measuredco/puck/commit/51154e92b9022311afa79d086f69b70b6b8beb77))
* don't crash if component definition missing ([525b506](https://github.com/measuredco/puck/commit/525b5065563675d03d89cf090ce1f7fdf8ff0486))
* don't crash when selecting component with no config ([cb90f5d](https://github.com/measuredco/puck/commit/cb90f5d9109b340407bc9828fcd9761183d83e68)), closes [#671](https://github.com/measuredco/puck/issues/671)
* export missing resolveAllData lib in RSC bundle ([2f5fb7b](https://github.com/measuredco/puck/commit/2f5fb7ba69b61b857ad14720b93ceab026571aa7))
* fix RTL styles in action bar overlay ([bf5c5a3](https://github.com/measuredco/puck/commit/bf5c5a33081599331049063c79c7859aea96d0da))
* remove internal AutoField and FieldLabel components from bundle ([5df1597](https://github.com/measuredco/puck/commit/5df1597feede2f0ff922ad13297fd3acaf942da2))
* remove unused label from AutoField type ([18b6f1a](https://github.com/measuredco/puck/commit/18b6f1acae0186245817f35d4a27e6fdf4153ea1))




## [0.16.1](https://github.com/measuredco/puck/compare/v0.16.0...v0.16.1) (2024-10-07)


### Bug Fixes

* don't delete array field on click in FieldLabel ([ed282b9](https://github.com/measuredco/puck/commit/ed282b98ebe8574258444ba91716d8da7e8117d1))
* don't overwrite user input when field recently changed ([6126040](https://github.com/measuredco/puck/commit/61260407c5c87cc8c5c4fe925835f2d0d2a6f9ff))
* don't show field loader if no resolver defined ([8c706cd](https://github.com/measuredco/puck/commit/8c706cda92474114faffc7ed77f4b4024f75bf68))
* hide ActionBar.Group border when empty ([4345165](https://github.com/measuredco/puck/commit/4345165ee71b9762e6bca9baaa53d0c53144d0c4))
* prevent item click before iframe load ([61e1653](https://github.com/measuredco/puck/commit/61e1653020b9e272133c70fa9494f1a81782531e))
* prevent flash of field loader when no data changed ([20d7309](https://github.com/measuredco/puck/commit/20d730924d2f235871bfec4f0467a6652a518704))
* respect readOnly styles in AutoField ([9ffe817](https://github.com/measuredco/puck/commit/9ffe8176c1c437524fd9f7b2912f1a5846fc5e55))




## [0.16.0](https://github.com/measuredco/puck/compare/v0.15.0...v0.16.0) (2024-09-16)


### Features

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


### Bug Fixes

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




## [0.15.0](https://github.com/measuredco/puck/compare/v0.14.2...v0.15.0) (2024-05-30)


### Bug Fixes

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


### Features

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




## [0.14.2](https://github.com/measuredco/puck/compare/v0.14.0...v0.14.2) (2024-04-17)


### Bug Fixes

* add DropZone iframe compatablity mode for bug in Safari 17.2, 17.3 and 17.4 ([47496c2](https://github.com/measuredco/puck/commit/47496c25407b1a5fdb88333e1fbf5416efc51c50))
* check for optionality to handle race condition when dragging ([4dbd487](https://github.com/measuredco/puck/commit/4dbd487f6055ea3d38ab7de54e29bd6e4ffe84ce))
* defer iframe event binding until contentWindow is ready ([268ea53](https://github.com/measuredco/puck/commit/268ea53f969a892843c026e5ba9ced15edb9f801))
* don't crash if component is missing after referenced in category ([dc93789](https://github.com/measuredco/puck/commit/dc93789c4311e386b022b5c3d7c8595c00a8a212))
* don't force height of DropZones in custom interfaces ([046c255](https://github.com/measuredco/puck/commit/046c2557b6baa62994380c547ad006759b02cc92))
* don't query iframe document if not ready ([2b2ef32](https://github.com/measuredco/puck/commit/2b2ef32555387d4656872674289740b73dcd406b))
* don't throw undefined error if rapidly zooming browser in some environments ([282a8b0](https://github.com/measuredco/puck/commit/282a8b0d9f170ea95f5717c8b2ad08ec487d7d8f))
* fix drag-and-drop when entire Puck component used inside an iframe ([23db292](https://github.com/measuredco/puck/commit/23db292b9a2caa8e65117c08706843d3ed343454))
* fix support for boolean values in select fields ([c4a66ad](https://github.com/measuredco/puck/commit/c4a66addacd9acdc1f042ac54831b7dac38f2757))
* make draggable outlines consistent ([9008b70](https://github.com/measuredco/puck/commit/9008b70ed63155140a5241914c86456a2d4c9388))
* prevent grid layout issues in generated apps ([5c05f94](https://github.com/measuredco/puck/commit/5c05f945679f7f2c0edd5d99c652989c00920ac6))
* reflect value changes made via resolveData in radio fields ([9a7066f](https://github.com/measuredco/puck/commit/9a7066f4e837575aecbde0de4dd2bc96328a2a15))
* remove peer dependencies causing warnings ([041ca64](https://github.com/measuredco/puck/commit/041ca64a6fe96539681d88e9cd0e66a6ac27a6ce))
* resolve security warning when additional iframes present ([03ab0bd](https://github.com/measuredco/puck/commit/03ab0bd3314a4d6dfc863bdcf5f23246331b959b))
* use 100% width for Puck preview when iframe disabled ([#414](https://github.com/measuredco/puck/issues/414)) ([64303c8](https://github.com/measuredco/puck/commit/64303c8510df15b6ca94bc7be0294d9746193b35))
* use more custom interface friendly styles for iframes ([e6e01c6](https://github.com/measuredco/puck/commit/e6e01c6ec5b2bee9ab3a4a9425276ad4f1840c20))


### Performance Improvements

* add API for disabling auto-scroll due to performance issues ([3e5599e](https://github.com/measuredco/puck/commit/3e5599e687643094f7c80d0ce99a7c6a0c947e28))
* batch load initial iframe styles ([e585f20](https://github.com/measuredco/puck/commit/e585f2090c0457d124006bd6349a69c9883d3c03))
* don't lock main thread when iframe styles changed ([e529e85](https://github.com/measuredco/puck/commit/e529e8525eb758025261577c424d8601c1ed8daf))
* reuse host window styles in iframes ([e7fe7e0](https://github.com/measuredco/puck/commit/e7fe7e0d7577bae1ab90650e5d7986d6745fbaf9))




## [0.14.1](https://github.com/measuredco/puck/compare/v0.14.0...v0.14.1) (2024-04-01)


### Bug Fixes

* don't throw undefined error if rapidly zooming browser in some environments ([282a8b0](https://github.com/measuredco/puck/commit/282a8b0d9f170ea95f5717c8b2ad08ec487d7d8f))
* prevent grid layout issues in generated apps ([5c05f94](https://github.com/measuredco/puck/commit/5c05f945679f7f2c0edd5d99c652989c00920ac6))
* remove peer dependencies causing warnings ([041ca64](https://github.com/measuredco/puck/commit/041ca64a6fe96539681d88e9cd0e66a6ac27a6ce))




## [0.14.0](https://github.com/measuredco/puck/compare/v0.13.0...v0.14.0) (2024-03-28)


### Features

* add "name" prop to componentItem override ([45bbceb](https://github.com/measuredco/puck/commit/45bbceb1d2805455fa38f5bce91d892f6acacfbf))
* add `min` and `max` APIs to array fields ([53b7937](https://github.com/measuredco/puck/commit/53b7937675303bc3cf282bbd005309c8c276d1b2))
* add API to opt-out of iframes ([03dd90b](https://github.com/measuredco/puck/commit/03dd90b98c8a72e2af3baa8fc436ff7d4f4c7449))
* add Contentful field package ([d944288](https://github.com/measuredco/puck/commit/d94428819a958b4f566e5d0e8cd29b3bf1107881))
* add filter fields to ExternalFields ([7a55053](https://github.com/measuredco/puck/commit/7a5505374953ab8004720a9c91d8975ad3df94e5))
* add iframe support ([1d0bf57](https://github.com/measuredco/puck/commit/1d0bf57894200edc6b9a883a41937f7a3141074f))
* add `min` and `max` APIs to number fields ([4932a6e](https://github.com/measuredco/puck/commit/4932a6ef1b640410b3291cc67fb1f3153c04eac4))
* add `selectedItem` convenience param to usePuck ([c1224d0](https://github.com/measuredco/puck/commit/c1224d026d37bbbcf1366804947771902e29d9bb))
* add viewport switching ([ccf9149](https://github.com/measuredco/puck/commit/ccf91495f3a9f20a37051ba407abd992095a7b4d))
* enable mapping of table rows in external fields ([d50c56e](https://github.com/measuredco/puck/commit/d50c56e829b482f13c5ec08acc76eed70494d3cf))
* expose history via usePuck hook ([1b907cb](https://github.com/measuredco/puck/commit/1b907cba506dda7a2b1fe201a426e1c4bcfffecc))
* hide array Add button when array is readOnly ([4e27c3f](https://github.com/measuredco/puck/commit/4e27c3f18a0fa9a97dcd5fd240b01a133d7cb153))
* improve touch, contrast & keyboard a11y ([f975d87](https://github.com/measuredco/puck/commit/f975d87c5c2823e1f27161e6b6aa76a0d3fafad2))
* refine UI for external field modal ([6a2afa1](https://github.com/measuredco/puck/commit/6a2afa1abbd33a062bca6962b547b5534ed93036))
* support custom component labels via the new label param ([712fb8e](https://github.com/measuredco/puck/commit/712fb8eeac0502b2baea4c86a4494eb8f924ed82))
* update to 12-tint color palette ([d43da58](https://github.com/measuredco/puck/commit/d43da581da3bd79324ed846ca5c5cd0c86469b23))
* use InterVariable font ([88532fb](https://github.com/measuredco/puck/commit/88532fbc248a3a171dc2e26906dcd68ba5979570))


### Bug Fixes

* avoid FOUC of side bars on mobile ([83be956](https://github.com/measuredco/puck/commit/83be95643e4dcb96e30d0e6a9dbfe03c60f83002))
* correctly infer objectFields type from props ([e8991cc](https://github.com/measuredco/puck/commit/e8991cc90d5fd899a3357f6d1f50b382d90aad23))
* don't attempt to resolve data if component missing from config ([cc7d391](https://github.com/measuredco/puck/commit/cc7d391503cce3cbdbad9b769b5fb0fca6610cb0))
* don't flash nested DropZones on first drag ([38c3dc4](https://github.com/measuredco/puck/commit/38c3dc418e047b7f1218c8c50cf3ba3f2e6b74d8))
* don't unexpectedly show DropZone background ([2001fa2](https://github.com/measuredco/puck/commit/2001fa2bb6e69451f68cd94a3f872a0f83ff2b4b))
* ensure font loads for ExternalFields ([e9bca75](https://github.com/measuredco/puck/commit/e9bca751926db8a88f4f6ad2bc135a10705987d9))
* ensure heading-analyzer updates when content changes ([d75df7a](https://github.com/measuredco/puck/commit/d75df7a5c8ab365a4ef0de6c81c707e706433383))
* ensure select and radio fields support read only arrays ([cbdf66d](https://github.com/measuredco/puck/commit/cbdf66d348acc3461f321956c80dbc87a896069e))
* fix array field when used on root ([95280e6](https://github.com/measuredco/puck/commit/95280e686409342d3be3d68ec2acb90f7cfc570e))
* fix renderDropZone method in editor ([2c738dd](https://github.com/measuredco/puck/commit/2c738dd3761596925caecfee2bfdcb2960a10b83))
* lower opacity of DropZone background to support dark backgrounds ([9a5c0b8](https://github.com/measuredco/puck/commit/9a5c0b8ec57e41eeda3592d9a45ab00907a7a313))
* make getItemSummary optional on ExternalFields, as expected ([26bc4ff](https://github.com/measuredco/puck/commit/26bc4ff320cc93bf4376edd190b3779774f2f87c))
* only import Puck CSS on editor pages ([22a4182](https://github.com/measuredco/puck/commit/22a41823559d36fd06842496d59788004b316797))
* prevent unexpected field behaviour when pressing "Enter" key ([bf4f527](https://github.com/measuredco/puck/commit/bf4f5277f5d5cbf7a7ccf473130055575a5e983a))
* use strict return type for resolveData ([777cd3c](https://github.com/measuredco/puck/commit/777cd3c02a0b0ec8df1b81e19654b1179b56cb53))
* vertically align field icons ([fa92436](https://github.com/measuredco/puck/commit/fa924363c8f2e5ad3d866793ba34a1b488250ce5))



## [0.13.1](https://github.com/measuredco/puck/compare/v0.13.0...v0.13.1) (2023-12-23)


### Bug Fixes

* don't render plugins twice when using React strict mode ([f70c722](https://github.com/measuredco/puck/commit/f70c7222dd844257fab791fb4d5f8cf90e3361df))
* replace crypto with uuid lib ([a84e06f](https://github.com/measuredco/puck/commit/a84e06feec977bca1ac7e08b6e55ba8afe0141dc))




## [0.13.0](https://github.com/measuredco/puck/compare/v0.12.0...v0.13.0) (2023-12-19)


### Features

* add "ui" prop to Puck to set the initial state ([71f8b2f](https://github.com/measuredco/puck/commit/71f8b2f1143b9774fd763a8f5a3685957474237b))
* add APIs to restrict components dropped in DropZones ([28f24f9](https://github.com/measuredco/puck/commit/28f24f927a2d1c378834f124e85abfcc2267a0d7))
* add data migration API ([f987324](https://github.com/measuredco/puck/commit/f987324804d59e55a3a5e6770389305d88f39194))
* add generic Config type to Puck and Render components ([1c4b97f](https://github.com/measuredco/puck/commit/1c4b97f0a8487785b5a677a2a1ba168b292e5ca4))
* add object field type ([243278b](https://github.com/measuredco/puck/commit/243278bb01e34de6123a47d902fcc58ea7678642))
* add Puck class to outer div ([0698a12](https://github.com/measuredco/puck/commit/0698a127e093cb2cf66fa35dafca80ebd4c73f89))
* add search to external fields ([fe3b439](https://github.com/measuredco/puck/commit/fe3b4394c7464eeab69e1af5a96bd525bd15872a))
* add transformProps lib to migrate component props ([1ec2a78](https://github.com/measuredco/puck/commit/1ec2a78968e10efc5666aaf994b6feea6c820449))
* add usePuck hook ([13f3ccb](https://github.com/measuredco/puck/commit/13f3ccbd314e5a82f5a509c713ad34d3d0614b34))
* introduce UI overrides API ([8a7c325](https://github.com/measuredco/puck/commit/8a7c3252d8aed2c160e390c1ba7c411d8b884b6f))
* make onPublish prop optional ([60f317f](https://github.com/measuredco/puck/commit/60f317f75bb1a18bd59819d1323c45266334138c))
* remove renderComponentList in favour of overrides API ([97f65e3](https://github.com/measuredco/puck/commit/97f65e3f0411abab66a72ea3c9ecd485cd941b4e))
* replace existing plugin API with plugin overrides ([46cca26](https://github.com/measuredco/puck/commit/46cca26c879a2ae53cf3e668f1dad37bb480bd84))
* support compositional Puck ([22f053f](https://github.com/measuredco/puck/commit/22f053fa6209735c27b172eb625ea25d9df4bb3d))
* track isDragging in app state ([841ae12](https://github.com/measuredco/puck/commit/841ae126d3f5e8a9e40c064b69d5ee675169e4cd))


### Bug Fixes

* don't crash when loading external data into array field items ([d13d00b](https://github.com/measuredco/puck/commit/d13d00b67a7106889a0fc3beae94fa9c2e5bfcc3))
* enable user to pass in config without casting ([ee211e2](https://github.com/measuredco/puck/commit/ee211e2a3ae6fbcb3d2b12316172e49f11fecd1e)), closes [#185](https://github.com/measuredco/puck/issues/185)
* fix broken nested array fields ([7a3949f](https://github.com/measuredco/puck/commit/7a3949f7f10b2323504b31bcae9a9aa5d46f4074))
* fix initial UI state on mobile ([3aa0057](https://github.com/measuredco/puck/commit/3aa005740b650879d95318a01ac9e2949ec5e9d8))
* prevent pollution of global styles into component overlay ([3fcf8e3](https://github.com/measuredco/puck/commit/3fcf8e3f9975a14d8bc355e025585c9f55f233b1))
* record history when a user selects an item ([3a649c9](https://github.com/measuredco/puck/commit/3a649c9922cc0a6c8c6c2b96f5fbe44bd3a6176a))
* remove packages triggering superficial security warning ([0f52b61](https://github.com/measuredco/puck/commit/0f52b610769550b3365ab91f856b264d02d005c2))
* respect label in radio fields ([fe550d7](https://github.com/measuredco/puck/commit/fe550d795eed20ce3a3004a2e7c8dfdbaca0b67d))
* set aria-label on all loaders ([9adca27](https://github.com/measuredco/puck/commit/9adca2774dae5e532134be76de9c79e0b4af751c))
* stop color pollution in external field modals ([2e1b5ef](https://github.com/measuredco/puck/commit/2e1b5ef330ebbddee8c44b5002be65c2361fda4f))
* use correct title path in recipes ([60244ba](https://github.com/measuredco/puck/commit/60244ba5637d889530ae646986b1890c6b89efea))
* watch puck.config.tsx in Remix recipe ([ecb276c](https://github.com/measuredco/puck/commit/ecb276c39fd3cf03d524b221b3f34b3a8df99823))




## [0.12.0](https://github.com/measuredco/puck/compare/v0.11.0...v0.12.0) (2023-11-23)


### Features

* support React server components via @measured/puck/rsc bundle ([90ac161](https://github.com/measuredco/puck/commit/90ac161513d0c8c84f6b2bb968f7e5400c732a0a))
* add remix recipe ([f882878](https://github.com/measuredco/puck/commit/f882878e081b44a2b0bd1f773114f3c35b8398b1))
* add explicit rsc and css exports ([0b6a527](https://github.com/measuredco/puck/commit/0b6a52792628225d392775ba6b3d549aab5be59b))
* improve responsive behaviour ([889b4c7](https://github.com/measuredco/puck/commit/889b4c7a91f1a9b95c9fd7d4b3cdb20b2ee4946b))
* add visibility toggle for right-hand sidebar ([3d6c5d4](https://github.com/measuredco/puck/commit/3d6c5d479f2237400e0dc7cab6d5ed5773058d3b))
* allow custom fields to set UI state during onChange ([388793c](https://github.com/measuredco/puck/commit/388793c9b0ac27b14a538b70357abd0dc4f26779))
* expose field "id" to custom fields ([849161e](https://github.com/measuredco/puck/commit/849161ef0e2e2e01f6a1b9f517ba4bcc66cf6bd1))
* improve IconButton accessibility ([4c71d39](https://github.com/measuredco/puck/commit/4c71d39d1138f0fc823ada04710d0057433475b7))
* add new monospaced font stack ([c484ea6](https://github.com/measuredco/puck/commit/c484ea6bae5e6283bf82860e9a84413e60720163))
* tweak Field input focus state ([8012afd](https://github.com/measuredco/puck/commit/8012afdd9be2e3bc96185b4f0208b3ebdef0ed21))


### Bug Fixes

* don't enable style pollution of input background color ([bb1a76b](https://github.com/measuredco/puck/commit/bb1a76b314f744b76197cb670c448abc7896a45e))
* don't reset array item labels when changing order ([57563e1](https://github.com/measuredco/puck/commit/57563e1da1826dbfa08a32fabb27153e4618ab40))
* ensure field icon and label are vertically aligned ([caa40e0](https://github.com/measuredco/puck/commit/caa40e0499570831e5779f9a6a031e38f054c3f8))
* ensure root render receives props from latest data API ([abb6ff1](https://github.com/measuredco/puck/commit/abb6ff1bd53d7f93ef0ac287290712943ca2c1ce))
* export missing PuckAction type ([f22f32d](https://github.com/measuredco/puck/commit/f22f32dc5569eaa9cea90f896cf4cdafc59940fe))
* fix rootResolver behaviour when using recommended root data API ([5c13de5](https://github.com/measuredco/puck/commit/5c13de58a335f2b4c81f2b424fee8b4a356fb563))
* migrate to @hello-pangea/dnd to fix defaultProps warning ([2c97362](https://github.com/measuredco/puck/commit/2c97362e15f5d2046dc216c6e5fc25f5199d0a37))
* prevent inconsistent default input font-size ([99f90b3](https://github.com/measuredco/puck/commit/99f90b3ba81bf286758685f7c2a457abaffeb2e1))
* show a default value when no placeholder set on external fields ([e30b5b6](https://github.com/measuredco/puck/commit/e30b5b69b6a9f6467db4b05c55ffdc5f1ecebcfb))
* stop `zones` getting wiped out if data prop updated ([0c4514f](https://github.com/measuredco/puck/commit/0c4514fcde24d0ba585fea0981d73e7a8188840f))
* stop style pollution into array field items ([03b89d5](https://github.com/measuredco/puck/commit/03b89d568ded7cae6eb34e0dcf45e60eb758b552))
* stretch external field table to width of modal ([f6d89f6](https://github.com/measuredco/puck/commit/f6d89f69f1a24f94479365b9d955a3ea60b17b8d))
* use correct root data API in next recipe example database ([b598144](https://github.com/measuredco/puck/commit/b5981446ee64a3b5451eb17b8d42263f42df179f))
* use Inter font in button type Buttons ([1973847](https://github.com/measuredco/puck/commit/19738473723c49ddb0d764864283bf597280c7c5))




## [0.11.3](https://github.com/measuredco/puck/compare/v0.11.2...v0.11.3) (2023-11-12)


### Bug Fixes

* ensure field debounce doesn't sporadically lock preview update ([487ab83](https://github.com/measuredco/puck/commit/487ab83e2ffa42ad93ab90c2eadea9486008de9b))
* stop generator crashing on Windows due to commits with single quotes ([ab9d43f](https://github.com/measuredco/puck/commit/ab9d43f08113ef1c3f6fa30f7f87ba881b74a1e1))




## [0.11.2](https://github.com/measuredco/puck/compare/v0.11.1...v0.11.2) (2023-11-11)


### Bug Fixes

* add missing database.json back to generated next recipe ([3c15255](https://github.com/measuredco/puck/commit/3c15255a8f7f5e77c047ce853382f92715045c8d))




## [0.11.1](https://github.com/measuredco/puck/compare/v0.11.0...v0.11.1) (2023-11-11)


### Bug Fixes

* include next recipe in generator ([5b833ef](https://github.com/measuredco/puck/commit/5b833efd0f87b21e57303256e89f1456254b82bf))




## [0.11.0](https://github.com/measuredco/puck/compare/v0.10.0...v0.11.0) (2023-11-03)


### Bug Fixes

* don't flicker root DropZone when dragging ([358435c](https://github.com/measuredco/puck/commit/358435c36a216e6749be73599ab631ffdd8069c8))
* ensure array fields can render if value is undefined ([47ab3c9](https://github.com/measuredco/puck/commit/47ab3c971e4aafec443e8b4d73e7c921dec38ac6))
* isolate external field modal from high z-indexes ([fdf97c7](https://github.com/measuredco/puck/commit/fdf97c7f6da6035447e9b7deec9019217875c4ef))
* make Field types required based on type ([daf36ac](https://github.com/measuredco/puck/commit/daf36ac8864dc1b0f324c3e08294f9d62568acf2))
* prevent global style pollution in external fields ([429731d](https://github.com/measuredco/puck/commit/429731dbb77de2d8ca1c4a88832c73294a9b141c))
* prevent long header titles from rendering over actions ([4613df4](https://github.com/measuredco/puck/commit/4613df47fdde9ac796419f02a2d9f649892b3d35))
* use correct heading component for external inputs ([462266d](https://github.com/measuredco/puck/commit/462266d069b04a3de09684af4b816e1d1dac46dc))


### Features

* add categories API for grouping components in side bar ([594cc76](https://github.com/measuredco/puck/commit/594cc76c763a7d2ce06cd78f34a4683c0fa89f8e))
* add read-only states to all field types ([746d896](https://github.com/measuredco/puck/commit/746d896996f01d086d557f2a2918f4e76e3f5b35))
* add icon to external fields ([a3a018b](https://github.com/measuredco/puck/commit/a3a018bb1876fd4b831676e8ff848052ec7ba527))
* add loading state to external field modal ([5b4fc92](https://github.com/measuredco/puck/commit/5b4fc92f96caf83148fa335321dad3a5f1a65789))
* add lock icon when field is read-only ([a051000](https://github.com/measuredco/puck/commit/a05100016fed1e368be333f2707087b152fb4c0e))
* add mapProp API to external fields ([86c4979](https://github.com/measuredco/puck/commit/86c49795ac1d198836242772ec01bd755ee699c8))
* add renderComponentList API ([ec985e3](https://github.com/measuredco/puck/commit/ec985e3d28a4915f8fb2816b9599060d20bbf621))
* add resolveData API for modifying props dynamically ([c1181ad](https://github.com/measuredco/puck/commit/c1181ad9b1de6cc036cfedebcc3e57334ef62196))
* deprecate adaptors in favour of new external field APIs ([7f13efc](https://github.com/measuredco/puck/commit/7f13efc769ddc77fc7931a8191796f017354e89a))
* deprecate magic adaptor _data behaviour in favour of resolveData API ([4ee31e7](https://github.com/measuredco/puck/commit/4ee31e7c0d93578976b2b655e0c56477571f8341))
* deprecate props under root in favour of `root.props` ([7593584](https://github.com/measuredco/puck/commit/759358446e01b4320e55156dbe849d264e4e7edf))
* make external field more consistent with other fields ([5bfbc5b](https://github.com/measuredco/puck/commit/5bfbc5bf71b0af72e97e24b5828ad7009836e51e))
* update next recipe to render to static ([a333857](https://github.com/measuredco/puck/commit/a33385783022179e12ef3f732cb4e2e387985030))


### Performance Improvements

* cache data between fetchList calls in external fields ([04b7322](https://github.com/measuredco/puck/commit/04b7322d5fa5a5506b853c3dcde7a0b47d5b21bc))
* improve render performance of fields ([d92de7f](https://github.com/measuredco/puck/commit/d92de7fe6eaf081deff139b010e4741d07ba6114))




## [0.10.0](https://github.com/measuredco/puck/compare/v0.9.0...v0.10.0) (2023-10-18)


### Bug Fixes

* ensure layer tree consistently shows selected item ([6a9145c](https://github.com/measuredco/puck/commit/6a9145c23b1461e46f3568e9a107d3c429aa87d2))
* only render strings or numbers in external adaptors ([3c337be](https://github.com/measuredco/puck/commit/3c337be171c5fa6ad464f5a16fcb7f17e9b1a4f9))
* prevent style pollution for select fields ([fa7af7d](https://github.com/measuredco/puck/commit/fa7af7da9d770d5e790944d421dc0a30f0da84b1))


### Features

* align component list UI with refreshed array fields ([74cd3a7](https://github.com/measuredco/puck/commit/74cd3a7ba9100e5e7e1a5e626511906fbdf75b98))
* enable drag-and-drop of array items ([12800f8](https://github.com/measuredco/puck/commit/12800f816b872d614ed50c9fcf3179f41dbbbfb2))
* expose state dispatcher to plugins ([e94accb](https://github.com/measuredco/puck/commit/e94accb22bae2afbb30728e0d58f8c6a558b3e39))
* expose state to plugins, removing data ([89f9f2e](https://github.com/measuredco/puck/commit/89f9f2e3a526a1459d14bdd7301f2c761f7c340d))
* expose state to renderHeader, removing data ([29ddaaf](https://github.com/measuredco/puck/commit/29ddaaf376b57134be46a489e7686978d0465669))
* record application state in undo/redo history ([0f2d7c5](https://github.com/measuredco/puck/commit/0f2d7c55aebe898925084ff27d5af97e9a7b9090))
* refresh UI for array fields ([5ef8a96](https://github.com/measuredco/puck/commit/5ef8a96b6952d450927a499f1ec0f93610450864))




## [0.9.0](https://github.com/measuredco/puck/compare/v0.8.0...v0.9.0) (2023-10-06)


### Bug Fixes

* fill empty space under puck-root ([d42cfb6](https://github.com/measuredco/puck/commit/d42cfb69aa7c7e0b70321b4b509efd3c6fdbe393))
* prevent global pollution of Heading color ([327721c](https://github.com/measuredco/puck/commit/327721c705546a538fedd0a3b794926605cd58fc))
* render `icon` if provided to FieldLabel ([ae01891](https://github.com/measuredco/puck/commit/ae01891ce55b844c5a76a20faa33e5df16c2d593))
* reset stacking context for each item ([a826492](https://github.com/measuredco/puck/commit/a826492ee7bab57710edad6b7df498f294398606))


### Features

* add undo/redo history ([222697e](https://github.com/measuredco/puck/commit/222697e5b9e95e3b28d0dfd9ac0b85f46c56068e))
* make actions sticky to component scroll ([f3e5b50](https://github.com/measuredco/puck/commit/f3e5b50d921f0c75978f805a7d44b88511fbaf69))




## [0.8.0](https://github.com/measuredco/puck/compare/v0.7.0...v0.8.0) (2023-10-03)


 ### Features

 * introduce DropZone API for nesting components and advanced layouts ([5053a84](https://github.com/measuredco/puck/commit/5053a8430de1f4bfb6fb7a4b1f194a1474ed3ae3))
 * introduce new outline UI ([e32c4ff](https://github.com/measuredco/puck/commit/e32c4ff784a2fcc5f2e2879807c045bd2742f4ac))
 * redesign action overlay and move outside of component ([5145cba](https://github.com/measuredco/puck/commit/5145cba6595e2051d14a7bfd37d9b180d9553330))
 * cast number field types to Number ([d5df959](https://github.com/measuredco/puck/commit/d5df95946dd9abf1502cb21bfc8682dd98efb1e1))


 ### Bug Fixes

 * add missing id type to render props ([18753cf](https://github.com/measuredco/puck/commit/18753cf1142d70f7100bc6fd5aa913813491042e))
 * add missing optional chaining operator to next recipe ([a368319](https://github.com/measuredco/puck/commit/a368319ec73adfc5bce8fb6bd31ac8e46e669400))
 * don't show margin underneath placeholder when dragging in ([2620455](https://github.com/measuredco/puck/commit/26204557b6fc92b208ee1051921965b793a78b1e))
 * don't switch between controlled/uncontrolled inputs ([b20e298](https://github.com/measuredco/puck/commit/b20e2980be6df6d57f9dfb6987b512686ccc5a7a))
 * ensure form styles override global styles ([104091a](https://github.com/measuredco/puck/commit/104091ac87c95d1395687d1785e621f5580efd87))
 * ensure hooks can always be used within render functions ([cbf8e8e](https://github.com/measuredco/puck/commit/cbf8e8e49fc5d43a8818cf41010cfba6034bbf28))
 * ensure types allow for nested arrays ([06b145b](https://github.com/measuredco/puck/commit/06b145b9089548725166fec3dd54f757b6e932cc))
 * fix unpredictable rendering of drop placeholder ([bf5f16b](https://github.com/measuredco/puck/commit/bf5f16b394ef950318949e9a440dd1bf2407636e))
 * only show sidebar scroll bars if necessary ([87c8736](https://github.com/measuredco/puck/commit/87c87369003f417600ca0a7bb38041de5c675afb))
 * prevent global styles from overwriting fieldset styles ([550bd0e](https://github.com/measuredco/puck/commit/550bd0ef9263766817709cea2c0365e9bd3e95cf))
 * respect labels for array item fields ([f2e7843](https://github.com/measuredco/puck/commit/f2e7843de0b12df4b15b1c1dd953e8b4d82ce366))
 * prevent global styles from overwriting outline styles ([1dc222c](https://github.com/measuredco/puck/commit/1dc222cfa5924aca2e5eb5ea535f77cfe2fe1281))
 * prevent styles from clashing with dark mode root element ([8506e8e](https://github.com/measuredco/puck/commit/8506e8e7f72aa8df7e69a1e7349eae273ebdee0e))
 * upgrade next version in recipe to ensure vercel builds pass ([c2d7fae](https://github.com/measuredco/puck/commit/c2d7faeed59fea5c7c795f76915cf354151d644d))


 ### Performance Improvements

 * reduce bundle size by 61% by removing unused react-feather icons ([f4b0563](https://github.com/measuredco/puck/commit/f4b0563e38a93a5f582b0210b0d75a846e3bada4))


## [0.7.0](https://github.com/measuredco/puck/compare/v0.6.2...v0.7.0) (2023-09-14)


### Features

* add support for custom fields ([b46b721](https://github.com/measuredco/puck/commit/b46b721aea70698e249cd3dfff34f88717952da7))




## [0.6.2](https://github.com/measuredco/puck/compare/v0.6.1...v0.6.2) (2023-09-07)


### Bug Fixes

* bust cache in generated app on publish ([6e1c8ed](https://github.com/measuredco/puck/commit/6e1c8ed9df1be9634e49d18edc8c42c7ebf6e864))
* don't 404 on homepage in generated app ([8fd7b3b](https://github.com/measuredco/puck/commit/8fd7b3b38a046776f69105e25f86a622b5e41c40))
* don't call API when building generated app ([8041fc1](https://github.com/measuredco/puck/commit/8041fc1da598f61b4c30c711d8233466c8643099))
* fix type issues in generated app ([b16e98e](https://github.com/measuredco/puck/commit/b16e98e15407678524d904211ecc74230b205018))




## [0.6.1](https://github.com/measuredco/puck/compare/v0.6.0...v0.6.1) (2023-09-06)


### Bug Fixes

* add missing glob dependency for create-puck-app ([7dbe190](https://github.com/measuredco/puck/commit/7dbe1902bf1c31a674b35c1269ee44ac09aac763))
* return component to original position when drag cancelled ([cae760f](https://github.com/measuredco/puck/commit/cae760fbfb8497de09311bb81e3059c07efe75ac))
* use correct peer dependencies for react ([39f4e7f](https://github.com/measuredco/puck/commit/39f4e7fab5818266aa75046d2c2ca6e858803a13))




## [0.6.0](https://github.com/measuredco/puck/compare/v0.5.0...v0.6.0) (2023-08-15)


### Bug Fixes

* ensure component label doesn't inherit user styles ([5c0d65b](https://github.com/measuredco/puck/commit/5c0d65b8519897c454b2f321330dd24dd30f831f))
* make default props on root optional ([dc5b1ae](https://github.com/measuredco/puck/commit/dc5b1aec6518f1c3ed1ad8f798bcfe359077865f))


### Features

* export Button and IconButton to make extending header seamless ([d98eb29](https://github.com/measuredco/puck/commit/d98eb298f14ef0ae8888a710cadf85fac13e084d))




## [0.5.0](https://github.com/measuredco/puck/compare/v0.4.1...v0.5.0) (2023-08-14)


### Features

* add headerTitle and headerPath APIs ([ae5c7c2](https://github.com/measuredco/puck/commit/ae5c7c2083b16e8f69e9995d74f8be7fffbe6ea5))
* gracefully fallback if component definition doesn't exist ([d7e3190](https://github.com/measuredco/puck/commit/d7e31901626734ce43cd9161971d9811b6d5c483))
* refine editor styles ([9e57649](https://github.com/measuredco/puck/commit/9e57649e7bd9444b290122ecbc1c40bc6d88c3d1))
* support booleans in radios and selects ([acb7a96](https://github.com/measuredco/puck/commit/acb7a96b727c9bc6d4599dcd06e2448c10e82d0f))




## [0.4.1](https://github.com/measuredco/puck/compare/v0.4.0...v0.4.1) (2023-08-09)


### Bug Fixes

* move incorrect dependency to devDependencies ([6ffd86c](https://github.com/measuredco/puck/commit/6ffd86c9d668449991a0642d79fa85c1a364deae))




## [0.4.0](https://github.com/measuredco/puck/compare/v0.3.2...v0.4.0) (2023-07-07)


### Bug Fixes

* avoid hardcoding localhost in strapi adaptor ([f8d920c](https://github.com/measuredco/puck/commit/f8d920c6d188e9b8c9ea1bc7cb58d63e6f25d823))
* stretch ExternalInput button to fill container ([69ee221](https://github.com/measuredco/puck/commit/69ee221e41ab09aae3d4d4d89c92d799d9b387f9))


### Features

* add adaptor-fetch package ([eaf7875](https://github.com/measuredco/puck/commit/eaf787527c0f76f3d43cbb8fd6fd1542aebdf5b0))
* rename page to root in API ([8519675](https://github.com/measuredco/puck/commit/8519675ab450438ae459bee54a8ae00bdc7553b4))




## [0.3.2](https://github.com/measuredco/puck/compare/v0.3.1...v0.3.2) (2023-07-06)


### Bug Fixes

* export correct files for Strapi adaptor ([577a849](https://github.com/measuredco/puck/commit/577a84928cd3c8e4f7a57d1f2746abd69db23eeb))
* set correct font family for empty outlines ([3d45841](https://github.com/measuredco/puck/commit/3d4584190e13f9b07077d6012d1ce4197de0a436))




## [0.3.1](https://github.com/measuredco/puck/compare/v0.3.0...v0.3.1) (2023-07-05)


### Bug Fixes

* include .gitignore in recipes ([e18bf67](https://github.com/measuredco/puck/commit/e18bf67e366c431a6bea08a9965b7d40866119e2))




## [0.3.0](https://github.com/measuredco/puck/compare/v0.2.2...v0.3.0) (2023-07-05)


### Features

* release create-puck-app ([0722a65](https://github.com/measuredco/puck/commit/0722a656c7da4b4caa9212385affd62323a56c92))




## [0.2.2](https://github.com/measuredco/puck/compare/v0.2.1...v0.2.2) (2023-07-05)


### Bug Fixes

* ensure margin collapse fix works with coloured backgrounds ([fdec4fa](https://github.com/measuredco/puck/commit/fdec4faac197e541a04785ab7c16919223b3ec9d))




## [0.2.1](https://github.com/measuredco/puck/compare/v0.2.0...v0.2.1) (2023-07-05)


### Bug Fixes

* remove border on draggable components ([726a27c](https://github.com/measuredco/puck/commit/726a27cc0df6b8c439d0aa8e0dd05cac32774b3e))




## [0.2.0](https://github.com/measuredco/puck/compare/v0.1.3...v0.2.0) (2023-07-04)


### Bug Fixes

* inject react into libraries ([7e10d91](https://github.com/measuredco/puck/commit/7e10d9141901aaf79ae4ebfa3a7b60b589c6c715))
* render drag and drop correctly when using margins ([f88025b](https://github.com/measuredco/puck/commit/f88025bf27479036426305a1004acfe8f0ab6644))


### Features

* add icons to inputs ([f47482e](https://github.com/measuredco/puck/commit/f47482e8cabd334360666ea90d2e6a12b3648cf9))
* improve UI for fields ([aa0d2fe](https://github.com/measuredco/puck/commit/aa0d2fe56ff633b9c2cff2023ae00c8b9ec04df3))
* rename "group" field type to "array" ([4f99c7d](https://github.com/measuredco/puck/commit/4f99c7d761b8e1cfa280fb5e74f6f369be84d7a2))




## [0.1.6](https://github.com/measuredco/puck/compare/v0.1.3...v0.1.6) (2023-07-04)


### Bug Fixes

* inject react into libraries ([7e10d91](https://github.com/measuredco/puck/commit/7e10d9141901aaf79ae4ebfa3a7b60b589c6c715))




## 0.1.5 (2023-07-03)

- Publish all packages


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
  community

Examples of unacceptable behavior include:

- The use of sexualized language or imagery, and sexual attention or advances of
  any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
  without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement via Discord.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series of
actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within the
community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).

Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://opensource.creativecommons.org/community/code-of-conduct/enforcement/).

For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at
[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations).


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Puck

Puck is still under heavy development, having gained significant interest at an early stage. The contribution guidelines are designed to help us balance community engagement with our vision and direction.

## Reporting bugs or requesting features

Bugs and feature requests are best reported via GitHub issues. Always check if the issue already exists before opening a new one.

If you're unsure whether or not you've encountered a bug, feel free to ask first 👇

## Asking questions

There are several ways to ask questions or ask for help:

- Open a [discussion](https://github.com/puckeditor/puck/discussions) via GitHub
- Use the #chat or #help channels in our [Discord server](https://discord.gg/D9e4E3MQVZ)

_Please only use GitHub issues for bugs and feature requests, and not for questions._

## Labels

We manage our backlog using labels. Labels can help you understand the status of each ticket.

### Status labels

- **ready** - this ticket has a description and is ready to be worked on.
- **in triage** - this ticket has been seen by the Puck team and we are identifying next steps. Tickets may stay in this state until we're ready to process them.
- **blocked** - this ticket is blocked by another ticket. The relationship should be made apparent in the comments.

### Type labels

Denoted by the `type:` prefix.

- **type: bug**
- **type: feature**
- **type: docs**
- **type: performance**
- **type: test**

### Other labels

- **good first issue** - if you're new to contributing on Puck, this is a good place to start.
- **opinions wanted** - we're looking for opinions on this ticket. Feel free to chime in with comments or suggestions.

## Contributing code

### When to contribute

#### Existing issues

If picking up an existing GitHub issue, please respect the **ready** status label.

Any PRs made to close issues without the **ready** label are at risk of being premature and likely to be rejected.

#### New issues

If you've reported a bug via an issue and have a fix, you don't need to wait for the **ready** label before proposing a fix.

It's also okay to propose solutions to your own feature requests, but without proper discussion the solution may be rejected.

#### No issue

PRs without issues may be accepted for small fixes, but larger changes may be rejected or require further discussion.

### Setting up the environment

Puck uses:

- TypeScript
- CSS Modules
- Turborepo for monorepo tooling
- Yarn for package management and release automation
- Next.js for demo applications

To get setup, first clone the repo and then install the dependencies:

```sh
yarn
```

Rather than running the entire monorepo, it's quicker to run the project you need.

Generally, it's easiest to work in the context of the demo application:

```sh
cd apps/demo
yarn dev
```

### Style

#### TypeScript

- Avoid the use of `any`.
- Tests appreciated, but not required. They may be requested for complicated code.

#### CSS

- Class names must follow the [SUIT CSS](https://suitcss.github.io) methodology. This is a tooling-angostic convention used at [@puckeditor](https://github.com/puckeditor) for all CSS work.
- Don't rely on global styles. Puck is deployed into hostile third-party environments and we have no control over what CSS may be running on the page.

#### Commits

**Keep your PRs focused to a single issue**. This makes it easier to review and is necessary for our release process.

We rely on [angular-style conventional commits](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) for automating our releases, determining the version bump and generating our changelog.

You generally don't need to write perfect commit messages yourselves - we squash most PRs and rewrite the messages on merge.

If you need to solve multiple issues, it's best to split it into multiple PRs. Or, if you're comfortable writing conventional commits, you can also split each change into a separate commit. The team is more likely to have opinions about this and you may be asked to reword your commits.

### Additional guidance

#### Public APIs

If your PR introduces or changes public APIs, it will come under additional scrutiny to avoid introducing breaking changes.

## Releases

### Canary

A canary release is automatically deployed after each merge to `main`. These are suffixed with the hash of the commit, for example `0.10.0-canary.42c24f1`.

### Latest

Releases are triggered manually when the team feels the `main` branch is sufficiently stable.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) The Puck Contributors.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<br /><br /><br />

<div align="center">

<a href="https://puckeditor.com?utm_source=readme&utm_medium=code&utm_campaign=repo&utm_contents=logo">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://res.cloudinary.com/die3nptcg/image/upload/Puck_Logo_White_RGB_j2rwgg.svg" height="100px" aria-label="Puck logo">
    <img src="https://res.cloudinary.com/die3nptcg/image/upload/Puck_Logo_Black_RGB_dqsjag.svg" height="100px" aria-label="Puck logo">
  </picture>
</a>

_Create your own AI page builder_

[Documentation](https://puckeditor.com/docs?utm_source=readme&utm_medium=code&utm_campaign=repo&utm_contents=docs_link) • [Demo](https://demo.puckeditor.com/edit?utm_source=readme&utm_medium=code&utm_campaign=repo&utm_contents=demo_link) • [Discord](https://discord.gg/V9mDAhuxyZ) • [Contributing](https://github.com/puckeditor/puck/blob/main/CONTRIBUTING.md)

⭐️ Enjoying Puck? Please [leave a star](https://github.com/puckeditor/puck)!

<br />

[![GIF showing a page being created in the Puck Editor, with components being added, arranged, and customized in real time](https://github.com/user-attachments/assets/25e1ae25-ca5e-450f-afa0-01816830b731)](https://demo.puckeditor.com/edit)

</div>

## What is Puck?

Puck is a modular, open-source visual editor for React.js. You can use Puck to build custom drag-and-drop experiences with your own application and React components.

Because Puck is just a React component, it plays well with all React.js environments, including Next.js. You own your data and there’s no vendor lock-in.

Puck is also [licensed under MIT](https://github.com/puckeditor/puck?tab=MIT-1-ov-file#readme), making it suitable for both internal systems and commercial applications.

## Quick start

Install the package:

```sh
npm i @puckeditor/core --save # or npx create-puck-app my-app
```

Render the editor:

```jsx
// Editor.jsx
import { Puck } from "@puckeditor/core";
import "@puckeditor/core/puck.css";

// Create Puck component config
const config = {
  components: {
    HeadingBlock: {
      fields: {
        children: {
          type: "text",
        },
      },
      render: ({ children }) => {
        return <h1>{children}</h1>;
      },
    },
  },
};

// Describe the initial data
const initialData = {};

// Save the data to your database
const save = (data) => {};

// Render Puck editor
export function Editor() {
  return <Puck config={config} data={initialData} onPublish={save} />;
}
```

Render the page:

```jsx
// Page.jsx
import { Render } from "@puckeditor/core";
import "@puckeditor/core/puck.css";

export function Page() {
  return <Render config={config} data={data} />;
}
```

## Recipes

Use `create-puck-app` to quickly spin up a a pre-configured app based on our provided [recipes](https://github.com/puckeditor/puck/tree/main/recipes):

```sh
npx create-puck-app my-app
```

Available recipes include:

- [**next**](https://github.com/puckeditor/puck/tree/main/recipes/next): Next.js example, using App Router and static page generation
- [**remix**](https://github.com/puckeditor/puck/tree/main/recipes/remix): Remix Run v2 example, using dynamic routes at root-level
- [**react-router**](https://github.com/puckeditor/puck/tree/main/recipes/react-router): React Router v7 app example, using dynamic routes to create pages at any level

## Community

- [Discord server](https://discord.gg/D9e4E3MQVZ) for discussions
- [awesome-puck](https://github.com/puckeditor/awesome-puck) community repo for plugins, custom fields & more

## Get support

If you have any questions about Puck, please open a [GitHub issue](https://github.com/puckeditor/puck/issues) or join us on [Discord](https://discord.gg/D9e4E3MQVZ).

Or [book a discovery call](https://app.cal.com/chrisvxd/puck-enquiry/) for hands-on support and consultancy.

## License

MIT © [The Puck Contributors](https://github.com/puckeditor/puck/graphs/contributors)


================================================
FILE: apps/demo/.eslintrc.js
================================================
module.exports = {
  root: true,
  extends: ["custom"],
};


================================================
FILE: apps/demo/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel

database.json

================================================
FILE: apps/demo/README.md
================================================
# `next` recipe

The `next` recipe showcases one of the most powerful ways to implement Puck using to provide an authoring tool for any route in your Next app.

## Demonstrates

- Next.js 13 App Router implementation
- JSON database implementation with HTTP API
- Catch-all routes to use puck for any route on the platform

## Usage

Run the generator and enter `next` when prompted

```
npx create-puck-app my-app
```

Start the server

```
yarn dev
```

Navigate to the homepage at https://localhost:3000. To edit the homepage, access the Puck editor at https://localhost:3000/edit.

You can do this for any route on the application, **even if the page doesn't exist**. For example, visit https://localhost:3000/hello/world and you'll receive a 404. You can author and publish a page by visiting https://localhost:3000/hello/world/edit. After publishing, go back to the original URL to see your page.

## Using this recipe

To adopt this recipe you will need to:

- **IMPORTANT** Add authentication to `/edit` routes. This can be done by modifying the example API routes in `/app/api/puck/route.ts` and server component in `/app/[...puckPath]/page.tsx`. **If you don't do this, Puck will be completely public.**
- Integrate your database into the API calls in `/app/api/puck/route.ts`
- Implement a custom puck configuration in `puck.config.tsx`

## License

MIT © [The Puck Contributors](https://github.com/puckeditor/puck/graphs/contributors).


================================================
FILE: apps/demo/app/[...puckPath]/client.tsx
================================================
"use client";

import { AutoField, Button, FieldLabel, Puck, Render } from "@/core";
import headingAnalyzer from "@/plugin-heading-analyzer/src/HeadingAnalyzer";
import config from "../../config";
import { useDemoData } from "../../lib/use-demo-data";
import { useEffect, useState } from "react";
import { Type } from "lucide-react";

export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
  const metadata = {
    example: "Hello, world",
  };

  const { data, resolvedData, key } = useDemoData({
    path,
    isEdit,
    metadata,
  });

  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  if (!isClient) return null;

  const params = new URL(window.location.href).searchParams;

  if (isEdit) {
    return (
      <div>
        <Puck
          config={config}
          data={data}
          onPublish={async (data) => {
            localStorage.setItem(key, JSON.stringify(data));
          }}
          plugins={[headingAnalyzer]}
          headerPath={path}
          iframe={{
            enabled: params.get("disableIframe") === "true" ? false : true,
          }}
          fieldTransforms={{
            userField: ({ value }) => value, // Included to check types
          }}
          _experimentalFullScreenCanvas={false}
          overrides={{
            fieldTypes: {
              // Example of user field provided via overrides
              userField: ({ readOnly, field, name, value, onChange }) => (
                <FieldLabel
                  label={field.label || name}
                  readOnly={readOnly}
                  icon={<Type size={16} />}
                >
                  <AutoField
                    field={{ type: "text" }}
                    onChange={onChange}
                    value={value}
                  />
                </FieldLabel>
              ),
            },
            headerActions: ({ children }) => (
              <>
                <div>
                  <Button href={path} newTab variant="secondary">
                    View page
                  </Button>
                </div>

                {children}
              </>
            ),
          }}
          metadata={metadata}
        />
      </div>
    );
  }

  if (data.content) {
    return <Render config={config} data={resolvedData} metadata={metadata} />;
  }

  return (
    <div
      style={{
        display: "flex",
        height: "100vh",
        textAlign: "center",
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <div>
        <h1>404</h1>
        <p>Page does not exist in session storage</p>
      </div>
    </div>
  );
}

export default Client;


================================================
FILE: apps/demo/app/[...puckPath]/page.tsx
================================================
import resolvePuckPath from "../../lib/resolve-puck-path";
import { Metadata } from "next";
import Client from "./client";
export async function generateMetadata({
  params,
}: {
  params: Promise<{ framework: string; uuid: string; puckPath: string[] }>;
}): Promise<Metadata> {
  const { puckPath } = await params;
  const { isEdit, path } = resolvePuckPath(puckPath);

  if (isEdit) {
    return {
      title: "Editing: " + path,
    };
  }

  return {
    title: "",
  };
}

export default async function Page({
  params,
}: {
  params: Promise<{ framework: string; uuid: string; puckPath: string[] }>;
}) {
  const { puckPath } = await params;
  const { isEdit, path } = resolvePuckPath(puckPath);

  return <Client isEdit={isEdit} path={path} />;
}

export const dynamic = "force-dynamic";


================================================
FILE: apps/demo/app/custom-ui/[...puckPath]/client.tsx
================================================
// Disable rules of hooks as they are regularly used inside render functions
/* eslint-disable react-hooks/rules-of-hooks */

"use client";

import {
  ActionBar,
  AutoField,
  Button,
  Data,
  FieldLabel,
  Puck,
  Render,
  useGetPuck,
} from "@/core";
import { HeadingAnalyzer } from "@/plugin-heading-analyzer/src/HeadingAnalyzer";
import config from "../../../config";
import { UserConfig } from "../../../config/types";
import { useDemoData } from "../../../lib/use-demo-data";
import { IconButton, createUsePuck } from "@/core";
import { ReactNode, useEffect, useRef, useState } from "react";
import { Drawer } from "@/core/components/Drawer";
import {
  ChevronUp,
  ChevronDown,
  Globe,
  Lock,
  Unlock,
  Type,
} from "lucide-react";

const usePuck = createUsePuck<UserConfig>();

const CustomHeader = ({ onPublish }: { onPublish: (data: Data) => void }) => {
  const getPuck = useGetPuck();
  const dispatch = usePuck((s) => s.dispatch);
  const previewMode = usePuck((s) => s.appState.ui.previewMode);

  const toggleMode = () => {
    dispatch({
      type: "setUi",
      ui: {
        previewMode: previewMode === "edit" ? "interactive" : "edit",
      },
    });
  };

  return (
    <header
      style={{
        display: "flex",
        flexWrap: "wrap",
        gap: 16,
        padding: "16px 24px",
        background: "white",
        color: "black",
        alignItems: "center",
        borderBottom: "1px solid #ddd",
      }}
      onClick={() => dispatch({ type: "setUi", ui: { itemSelector: null } })}
    >
      <span style={{ fontWeight: 600 }}>Custom UI example </span>
      <div style={{ marginLeft: "auto", display: "flex", gap: 8 }}>
        <div style={{ gap: 8, display: "flex" }}>
          <Button onClick={toggleMode} variant="secondary">
            Switch to {previewMode === "edit" ? "interactive" : "edit"}
          </Button>
          <Button
            onClick={() => onPublish(getPuck().appState.data)}
            icon={<Globe size="14" />}
          >
            Publish
          </Button>
        </div>
      </div>
    </header>
  );
};

const Tabs = ({
  tabs,
  onTabCollapse,
  scrollTop,
}: {
  tabs: { label: string; body: ReactNode }[];
  onTabCollapse: () => void;
  scrollTop: number;
}) => {
  const [currentTab, setCurrentTab] = useState(-1);
  const itemSelector = usePuck((s) => s.appState.ui.itemSelector);
  const isDragging = usePuck((s) => s.appState.ui.isDragging);

  const currentTabRef = useRef(currentTab);

  useEffect(() => {
    if (currentTabRef.current !== -1 && itemSelector) {
      setCurrentTab(1);
    }
  }, [itemSelector]);

  useEffect(() => {
    currentTabRef.current = currentTab;
  }, [currentTab]);

  useEffect(() => {
    if (isDragging && currentTab === 1) {
      setCurrentTab(-1);
    }
  }, [currentTab, isDragging]);

  useEffect(() => {
    if (scrollTop === 0) {
      setCurrentTab(-1);
      onTabCollapse();
    }
  }, [scrollTop]);

  return (
    <div
      onClick={(e) => e.stopPropagation()}
      style={{
        background: "#ffffff",
        pointerEvents: "all",
        borderTop: "1px solid #ddd",
        boxShadow: "rgba(140, 152, 164, 0.25) 0px 0px 6px 0px",
      }}
    >
      <div
        style={{
          display: "flex",
          paddingLeft: 16,
          paddingRight: 16,
          borderBottom: "1px solid #ddd",
          overflowX: "auto",
        }}
      >
        {tabs.map((tab, idx) => {
          const isCurrentTab = currentTab === idx;
          return (
            <button
              key={idx}
              type="button"
              onClick={() => {
                if (currentTab === idx) {
                  setCurrentTab(-1);
                } else {
                  setCurrentTab(idx);
                  if (scrollTop < 20) {
                    setTimeout(() => {
                      document
                        .querySelector("#action-bar")
                        ?.scroll({ top: 128, behavior: "smooth" });
                    }, 25);
                  }
                }
              }}
              style={{
                fontFamily: "inherit",
                fontSize: 16,
                padding: "16px 16px",
                paddingTop: 19,
                color: isCurrentTab ? "var(--puck-color-azure-04)" : "black",
                border: "none",
                borderBottom: isCurrentTab
                  ? "3px solid var(--puck-color-azure-04)"
                  : "3px solid transparent",
                background: "white",
                cursor: "pointer",
              }}
            >
              {tab.label}
            </button>
          );
        })}
        <div
          style={{
            marginLeft: "auto",
            display: "flex",
            alignItems: "center",
            gap: 8,
          }}
        >
          <div>
            <IconButton
              onClick={() => {
                setCurrentTab(currentTab === -1 ? 0 : -1);

                if (currentTab !== -1) {
                  onTabCollapse();
                } else {
                  setTimeout(() => {
                    document
                      .querySelector("#action-bar")
                      ?.scroll({ top: 128, behavior: "smooth" });
                  }, 25);
                }
              }}
              title={currentTab !== -1 ? "Collapse Tabs" : "Expand Tabs"}
            >
              {currentTab === -1 ? <ChevronUp /> : <ChevronDown />}
            </IconButton>
          </div>
        </div>
      </div>
      <div style={{ overflowX: "auto" }}>
        {tabs.map((tab, idx) => {
          const isCurrentTab = currentTab === idx;
          return (
            <div
              key={idx}
              style={{
                display: isCurrentTab ? "block" : "none",
              }}
            >
              {tab.body}
            </div>
          );
        })}
      </div>
    </div>
  );
};

const CustomPuck = ({ dataKey }: { dataKey: string }) => {
  const [hoveringTabs, setHoveringTabs] = useState(false);

  const [actionBarScroll, setActionBarScroll] = useState(0);

  return (
    <div
      style={{
        position: "relative",
      }}
    >
      <div style={{ position: "sticky", top: 0, zIndex: 2 }}>
        <CustomHeader
          onPublish={async (data: Data) => {
            localStorage.setItem(dataKey, JSON.stringify(data));
          }}
        />
      </div>
      <div
        style={{
          position: "relative",
          overflowY: hoveringTabs ? "hidden" : "auto",
          zIndex: 0,
        }}
      >
        <Puck.Preview />
      </div>
      <div
        id="action-bar"
        style={{
          position: "fixed",
          bottom: 0,
          overflowY: "auto",
          overflowX: "hidden",
          maxHeight: "100vh",
          width: "100%",
          boxSizing: "border-box",
          paddingTop: "calc(100vh - 58px)",
          pointerEvents: hoveringTabs ? undefined : "none",
          zIndex: 1,
          overscrollBehavior: "none",
        }}
        onTouchStart={() => setHoveringTabs(false)}
        onScrollCapture={(e) => {
          setActionBarScroll(e.currentTarget.scrollTop);
        }}
      >
        <div
          style={{
            background: "white",
            position: "relative",
            pointerEvents: "none",
            zIndex: 0,
          }}
          onMouseOver={(e) => {
            e.stopPropagation();
            setHoveringTabs(true);
          }}
          onTouchStart={(e) => {
            e.stopPropagation();
            setHoveringTabs(true);
          }}
          onMouseOut={() => {
            setHoveringTabs(false);
          }}
        >
          {/* Force react to render when hoveringTabs changes, otherwise scroll gets trapped */}
          {hoveringTabs && <span />}
          <Tabs
            onTabCollapse={() => {
              setTimeout(() => setHoveringTabs(false), 50);
            }}
            scrollTop={actionBarScroll}
            tabs={[
              { label: "Components", body: <Puck.Components /> },
              { label: "Fields", body: <Puck.Fields /> },
              { label: "Outline", body: <Puck.Outline /> },
              {
                label: "Headings",
                body: (
                  <div style={{ padding: 24 }}>
                    <HeadingAnalyzer />
                  </div>
                ),
              },
            ]}
          />
        </div>
      </div>
    </div>
  );
};

const CustomDrawer = () => {
  const getPermissions = usePuck((s) => s.getPermissions);

  return (
    <Drawer>
      <div
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(auto-fill, minmax(256px, 1fr))",
          pointerEvents: "all",
          padding: "16px",
          background: "var(--puck-color-grey-12)",
          gap: 8,
        }}
      >
        {Object.keys(config.components).map((componentKey, componentIndex) => {
          const canInsert = getPermissions({
            type: componentKey as keyof UserConfig["components"],
          }).insert;

          return (
            <Drawer.Item
              key={componentKey}
              name={componentKey}
              isDragDisabled={!canInsert}
            />
          );
        })}
      </div>
    </Drawer>
  );
};

export function Client({ path, isEdit }: { path: string; isEdit: boolean }) {
  const { data, resolvedData, key } = useDemoData({
    path,
    isEdit,
  });

  const [lockedComponents, setLockedComponents] = useState<
    Record<string, boolean>
  >({});

  const configOverride: UserConfig = {
    ...config,
    components: {
      ...Object.keys(config.components).reduce((acc, componentKey) => {
        return {
          ...acc,
          [componentKey]: {
            ...acc[componentKey as keyof UserConfig["components"]],
            resolvePermissions: (data: any, { permissions }: any) => {
              if (lockedComponents[data.props.id]) {
                return {
                  drag: false,
                  edit: false,
                  duplicate: false,
                  delete: false,
                };
              }

              return permissions;
            },
          },
        };
      }, config.components),
    },
  };

  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  if (!isClient) return null;

  if (isEdit) {
    return (
      <Puck<UserConfig>
        config={configOverride}
        data={data}
        iframe={{ enabled: false }}
        headerPath={path}
        permissions={{
          lockable: true,
        }}
        overrides={{
          fieldTypes: {
            userField: ({ readOnly, field, name, value, onChange }) => (
              <FieldLabel
                label={field.label || name}
                readOnly={readOnly}
                icon={<Type size={16} />}
              >
                <AutoField
                  readOnly={readOnly}
                  field={{ type: "text" }}
                  onChange={onChange}
                  value={value}
                />
              </FieldLabel>
            ),
          },
          outline: ({ children }) => (
            <div style={{ padding: 16 }}>{children}</div>
          ),
          componentOverlay: ({ hover, isSelected }) => {
            return (
              <div
                style={{
                  width: "100%",
                  height: "100%",
                  background: hover ? "red" : "transparent",
                  outline: isSelected ? "2px solid blue" : "",
                  opacity: 0.4,
                }}
              />
            );
          },
          actionBar: ({ children, label, parentAction }) => {
            const selectedItem = usePuck((s) => s.selectedItem);
            const getPermissions = usePuck((s) => s.getPermissions);
            const refreshPermissions = usePuck((s) => s.refreshPermissions);

            const globalPermissions = getPermissions();

            // eslint-disable-next-line react-hooks/rules-of-hooks
            useEffect(() => {
              if (selectedItem) {
                // We have to force refresh the permission resolver to refresh, since it relies on lockedComponents state
                // Without this, the resolver won't trigger as no props will have changed
                refreshPermissions({ item: selectedItem });
              }
              // eslint-disable-next-line react-hooks/exhaustive-deps
            }, [lockedComponents, selectedItem?.props.id, refreshPermissions]);

            if (!selectedItem)
              return (
                <ActionBar>
                  <ActionBar.Group>
                    {parentAction}
                    {label && <ActionBar.Label label={label} />}
                  </ActionBar.Group>
                  <ActionBar.Group>{children}</ActionBar.Group>
                </ActionBar>
              );

            const isLocked = !!lockedComponents[selectedItem.props.id];

            return (
              <ActionBar>
                <ActionBar.Group>
                  {parentAction}
                  {label && <ActionBar.Label label={label} />}
                </ActionBar.Group>
                <ActionBar.Group>
                  {children}
                  {globalPermissions.lockable && (
                    <ActionBar.Action
                      onClick={() => {
                        setLockedComponents({
                          ...lockedComponents,
                          [selectedItem.props.id as string]: !isLocked,
                        });

                        refreshPermissions({ item: selectedItem });
                      }}
                      label={isLocked ? "Unlock component" : "Lock component"}
                    >
                      {isLocked ? <Unlock size={16} /> : <Lock size={16} />}
                    </ActionBar.Action>
                  )}
                </ActionBar.Group>
              </ActionBar>
            );
          },
          drawer: () => <CustomDrawer />,
          puck: () => <CustomPuck dataKey={key} />,
        }}
      />
    );
  }

  if (data) {
    return <Render<UserConfig> config={config} data={resolvedData} />;
  }

  return (
    <div
      style={{
        display: "flex",
        height: "100vh",
        textAlign: "center",
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <div>
        <h1>404</h1>
        <p>Page does not exist in session storage</p>
      </div>
    </div>
  );
}

export default Client;


================================================
FILE: apps/demo/app/custom-ui/[...puckPath]/page.tsx
================================================
import resolvePuckPath from "../../../lib/resolve-puck-path";
import { Metadata } from "next";
import Client from "./client";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ framework: string; uuid: string; puckPath: string[] }>;
}): Promise<Metadata> {
  const { puckPath } = await params;
  const { isEdit, path } = resolvePuckPath(puckPath);

  if (isEdit) {
    return {
      title: "Editing: " + path,
    };
  }

  return {
    title: "",
  };
}

export default async function Page({
  params,
}: {
  params: Promise<{ framework: string; uuid: string; puckPath: string[] }>;
}) {
  const { puckPath } = await params;
  const { isEdit, path } = resolvePuckPath(puckPath);

  return <Client isEdit={isEdit} path={path} />;
}


================================================
FILE: apps/demo/app/layout.tsx
================================================
import "@/core/styles.css";
import "./styles.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        {process.env.NEXT_PUBLIC_PLAUSIBLE_DATA_DOMAIN && (
          <script
            defer
            data-domain={process.env.NEXT_PUBLIC_PLAUSIBLE_DATA_DOMAIN}
            src="https://plausible.io/js/plausible.js"
          ></script>
        )}
      </head>
      <body>
        <div>{children}</div>
      </body>
    </html>
  );
}


================================================
FILE: apps/demo/app/page.tsx
================================================
export { default } from "./[...puckPath]/page";
export * from "./[...puckPath]/page";


================================================
FILE: apps/demo/app/rsc/page.tsx
================================================
import { Metadata } from "next";
import config from "../../config/server";
import { initialData } from "../../config/initial-data";
import { Components, RootProps } from "../../config/types";

import { Config } from "@/core";
import { Render, resolveAllData } from "@/core/bundle/rsc";

// NB This is only necessary for this demo app, as the `@/core/bundle/rsc` path does not resolve to dist but the type for Config does
// This will be resolved once the RSC package is merged with the regular package after DropZone support is dropped
const conf = config as unknown as Config;

export async function generateMetadata(): Promise<Metadata> {
  return {
    title: initialData["/"].root.title,
  };
}

export default async function Page() {
  const data = initialData["/"];
  const metadata = {
    example: "Hello, world",
  };

  const resolvedData = await resolveAllData<Components, RootProps>(
    data,
    conf,
    metadata
  );

  return <Render config={conf} data={resolvedData} metadata={metadata} />;
}


================================================
FILE: apps/demo/app/styles.css
================================================
@import url("https://rsms.me/inter/inter.css");

body {
  font-family: Inter, -apple-system, BlinkMacSystemFont, Segoe UI,
    Helvetica Neue, sans-serif, Apple Color Emoji, Segoe UI Emoji,
    Segoe UI Symbol;
  margin: 0;
}

@supports (font-variation-settings: normal) {
  body {
    font-family: InterVariable, -apple-system, BlinkMacSystemFont, Segoe UI,
      Helvetica Neue, sans-serif, Apple Color Emoji, Segoe UI Emoji,
      Segoe UI Symbol;
  }
}


================================================
FILE: apps/demo/config/blocks/Blank/index.tsx
================================================
import React from "react";
import { ComponentConfig } from "@/core";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";

const getClassName = getClassNameFactory("Blank", styles);

export type BlankProps = {};

export const Blank: ComponentConfig<BlankProps> = {
  fields: {},
  defaultProps: {},
  render: () => {
    return <div className={getClassName()}></div>;
  },
};


================================================
FILE: apps/demo/config/blocks/Blank/styles.module.css
================================================
.Blank {
  background: hotpink;
  padding: 16px;
}


================================================
FILE: apps/demo/config/blocks/Button/index.tsx
================================================
import React from "react";
import { ComponentConfig } from "@/core/types";
import { Button as _Button } from "@/core/components/Button";

export type ButtonProps = {
  label: string;
  href: string;
  variant: "primary" | "secondary";
};

export const Button: ComponentConfig<ButtonProps> = {
  label: "Button",
  fields: {
    label: {
      type: "text",
      placeholder: "Lorem ipsum...",
      contentEditable: true,
    },
    href: { type: "text" },
    variant: {
      type: "radio",
      options: [
        { label: "primary", value: "primary" },
        { label: "secondary", value: "secondary" },
      ],
    },
  },
  defaultProps: {
    label: "Button",
    href: "#",
    variant: "primary",
  },
  render: ({ href, variant, label, puck }) => {
    return (
      <div>
        <_Button
          href={puck.isEditing ? "#" : href}
          variant={variant}
          size="large"
          tabIndex={puck.isEditing ? -1 : undefined}
        >
          {label}
        </_Button>
      </div>
    );
  },
};


================================================
FILE: apps/demo/config/blocks/Card/index.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import React, { ReactElement } from "react";
import { ComponentConfig } from "@/core/types";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import dynamic from "next/dynamic";
import dynamicIconImports from "lucide-react/dynamicIconImports";
import { withLayout, WithLayout } from "../../components/Layout";

const getClassName = getClassNameFactory("Card", styles);

const icons = Object.keys(dynamicIconImports).reduce<
  Record<string, ReactElement>
>((acc, iconName) => {
  const El = dynamic((dynamicIconImports as any)[iconName]);

  return {
    ...acc,
    [iconName]: <El />,
  };
}, {});

const iconOptions = Object.keys(dynamicIconImports).map((iconName) => ({
  label: iconName,
  value: iconName,
}));

export type CardProps = WithLayout<{
  title: string;
  description: string;
  icon?: string;
  mode: "flat" | "card";
}>;

const CardInner: ComponentConfig<CardProps> = {
  fields: {
    title: {
      type: "text",
      contentEditable: true,
    },
    description: {
      type: "textarea",
      contentEditable: true,
    },
    icon: {
      type: "select",
      options: iconOptions,
    },
    mode: {
      type: "radio",
      options: [
        { label: "card", value: "card" },
        { label: "flat", value: "flat" },
      ],
    },
  },
  defaultProps: {
    title: "Title",
    description: "Description",
    icon: "Feather",
    mode: "flat",
  },
  render: ({ title, icon, description, mode }) => {
    return (
      <div className={getClassName({ [mode]: mode })}>
        <div className={getClassName("inner")}>
          <div className={getClassName("icon")}>{icon && icons[icon]}</div>

          <div className={getClassName("title")}>{title}</div>
          <div className={getClassName("description")}>{description}</div>
        </div>
      </div>
    );
  },
};

export const Card = withLayout(CardInner);


================================================
FILE: apps/demo/config/blocks/Card/styles.module.css
================================================
.Card {
  height: 100%;
}

.Card--card {
  background: white;
  box-shadow: rgba(140, 152, 164, 0.25) 0px 3px 6px 0px;
  border-radius: 8px;
  max-width: 100%;
}

.Card-inner {
  align-items: center;
  display: flex;
  gap: 16px;
  flex-direction: column;
}

.Card--card .Card-inner {
  align-items: flex-start;
  padding: 24px;
}

.Card-icon {
  border-radius: 256px;
  background: var(--puck-color-azure-09);
  color: var(--puck-color-azure-06);
  display: flex;
  justify-content: center;
  align-items: center;
  width: 64px;
  height: 64px;
}

.Card-title {
  font-size: 22px;
  text-align: center;
}

.Card--card .Card-title {
  text-align: left;
}

.Card-description {
  font-size: 16px;
  line-height: 1.5;
  color: var(--puck-color-grey-05);
  text-align: center;
  font-weight: 300;
}

.Card--card .Card-description {
  text-align: left;
}


================================================
FILE: apps/demo/config/blocks/Flex/index.tsx
================================================
import React from "react";
import { ComponentConfig, Slot } from "@/core/types";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Section } from "../../components/Section";
import { WithLayout, withLayout } from "../../components/Layout";

const getClassName = getClassNameFactory("Flex", styles);

export type FlexProps = WithLayout<{
  justifyContent: "start" | "center" | "end";
  direction: "row" | "column";
  gap: number;
  wrap: "wrap" | "nowrap";
  items: Slot;
}>;

const FlexInternal: ComponentConfig<FlexProps> = {
  fields: {
    direction: {
      label: "Direction",
      type: "radio",
      options: [
        { label: "Row", value: "row" },
        { label: "Column", value: "column" },
      ],
    },
    justifyContent: {
      label: "Justify Content",
      type: "radio",
      options: [
        { label: "Start", value: "start" },
        { label: "Center", value: "center" },
        { label: "End", value: "end" },
      ],
    },
    gap: {
      label: "Gap",
      type: "number",
      min: 0,
    },
    wrap: {
      label: "Wrap",
      type: "radio",
      options: [
        { label: "true", value: "wrap" },
        { label: "false", value: "nowrap" },
      ],
    },
    items: {
      type: "slot",
    },
  },
  defaultProps: {
    justifyContent: "start",
    direction: "row",
    gap: 24,
    wrap: "wrap",
    layout: {
      grow: true,
    },
    items: [],
  },
  render: ({ justifyContent, direction, gap, wrap, items: Items }) => {
    return (
      <Section style={{ height: "100%" }}>
        <Items
          className={getClassName()}
          style={{
            justifyContent,
            flexDirection: direction,
            gap,
            flexWrap: wrap,
          }}
          disallow={["Hero", "Stats"]}
        />
      </Section>
    );
  },
};

export const Flex = withLayout(FlexInternal);


================================================
FILE: apps/demo/config/blocks/Flex/styles.module.css
================================================
.Flex {
  display: flex;
  flex-wrap: wrap;
  height: 100%;
}

.Flex-item {
  flex: 1;
}


================================================
FILE: apps/demo/config/blocks/Grid/index.tsx
================================================
import React from "react";
import { ComponentConfig, Slot } from "@/core/types";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Section } from "../../components/Section";
import { withLayout } from "../../components/Layout";

const getClassName = getClassNameFactory("Grid", styles);

export type GridProps = {
  numColumns: number;
  gap: number;
  items: Slot;
};

const CustomSlot = (props: any) => {
  return <span {...props} />;
};

export const GridInternal: ComponentConfig<GridProps> = {
  fields: {
    numColumns: {
      type: "number",
      label: "Number of columns",
      min: 1,
      max: 12,
    },
    gap: {
      label: "Gap",
      type: "number",
      min: 0,
    },
    items: {
      type: "slot",
    },
  },
  defaultProps: {
    numColumns: 4,
    gap: 24,
    items: [],
  },
  render: ({ gap, numColumns, items: Items }) => {
    return (
      <Section>
        <Items
          as={CustomSlot}
          disallow={["Hero", "Stats"]}
          className={getClassName()}
          style={{
            gap,
            gridTemplateColumns: `repeat(${numColumns}, 1fr)`,
          }}
        />
      </Section>
    );
  },
};

export const Grid = withLayout(GridInternal);


================================================
FILE: apps/demo/config/blocks/Grid/styles.module.css
================================================
.Grid {
  display: flex;
  flex-direction: column;
  width: auto;
}

@media (min-width: 768px) {
  .Grid {
    display: grid;
  }
}


================================================
FILE: apps/demo/config/blocks/Heading/index.tsx
================================================
import React from "react";

import { ComponentConfig } from "@/core/types";
import { Heading as _Heading } from "@/core/components/Heading";
import type { HeadingProps as _HeadingProps } from "@/core/components/Heading";
import { Section } from "../../components/Section";
import { WithLayout, withLayout } from "../../components/Layout";

export type HeadingProps = WithLayout<{
  align: "left" | "center" | "right";
  text?: string;
  level?: _HeadingProps["rank"];
  size: _HeadingProps["size"];
}>;

const sizeOptions = [
  { value: "xxxl", label: "XXXL" },
  { value: "xxl", label: "XXL" },
  { value: "xl", label: "XL" },
  { value: "l", label: "L" },
  { value: "m", label: "M" },
  { value: "s", label: "S" },
  { value: "xs", label: "XS" },
];

const levelOptions = [
  { label: "", value: "" },
  { label: "1", value: "1" },
  { label: "2", value: "2" },
  { label: "3", value: "3" },
  { label: "4", value: "4" },
  { label: "5", value: "5" },
  { label: "6", value: "6" },
];

const HeadingInternal: ComponentConfig<HeadingProps> = {
  fields: {
    text: {
      type: "textarea",
      contentEditable: true,
    },
    size: {
      type: "select",
      options: sizeOptions,
    },
    level: {
      type: "select",
      options: levelOptions,
    },
    align: {
      type: "radio",
      options: [
        { label: "Left", value: "left" },
        { label: "Center", value: "center" },
        { label: "Right", value: "right" },
      ],
    },
  },
  defaultProps: {
    align: "left",
    text: "Heading",
    size: "m",
    layout: {
      padding: "8px",
    },
  },
  render: ({ align, text, size, level }) => {
    return (
      <Section>
        <_Heading size={size} rank={level as any}>
          <span style={{ display: "block", textAlign: align, width: "100%" }}>
            {text}
          </span>
        </_Heading>
      </Section>
    );
  },
};

export const Heading = withLayout(HeadingInternal);


================================================
FILE: apps/demo/config/blocks/Heading/styles.module.css
================================================
.Heading {
  margin: 0;
}


================================================
FILE: apps/demo/config/blocks/Hero/Hero.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import React, { ReactNode } from "react";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Button } from "@/core/components/Button";
import { Section } from "../../components/Section";
import { PuckComponent, RichText, Slot } from "@/core/types";

const getClassName = getClassNameFactory("Hero", styles);

export type HeroProps = {
  quote?: { index: number; label: string };
  title: string | ReactNode;
  description: RichText;
  align?: string;
  padding: string;
  image?: {
    content?: Slot;
    mode?: "inline" | "background" | "custom";
    url?: string;
  };
  buttons: {
    label: string;
    href: string;
    variant?: "primary" | "secondary";
  }[];
};

export const Hero: PuckComponent<HeroProps> = ({
  align,
  title,
  description,
  buttons,
  padding,
  image,
  puck,
}) => {
  return (
    <Section
      className={getClassName({
        left: align === "left",
        center: align === "center",
        hasImageBackground: image?.mode === "background",
      })}
      style={{ paddingTop: padding, paddingBottom: padding }}
    >
      {image?.mode === "background" && (
        <>
          <div
            className={getClassName("image")}
            style={{
              backgroundImage: `url("${image?.url}")`,
            }}
          ></div>

          <div className={getClassName("imageOverlay")}></div>
        </>
      )}

      <div className={getClassName("inner")}>
        <div className={getClassName("content")}>
          <h1>{title}</h1>
          <div className={getClassName("subtitle")}>{description}</div>
          <div className={getClassName("actions")}>
            {buttons.map((button, i) => (
              <Button
                key={i}
                href={button.href}
                variant={button.variant}
                size="large"
                tabIndex={puck.isEditing ? -1 : undefined}
              >
                {button.label}
              </Button>
            ))}
          </div>
        </div>

        {align !== "center" && image?.mode === "inline" && image?.url && (
          <div
            style={{
              backgroundImage: `url('${image?.url}')`,
              backgroundSize: "cover",
              backgroundRepeat: "no-repeat",
              backgroundPosition: "center",
              borderRadius: 24,
              height: 356,
              marginLeft: "auto",
              width: "100%",
            }}
          />
        )}

        {align !== "center" && image?.mode === "custom" && image.content && (
          <image.content
            style={{
              height: 356,
              marginLeft: "auto",
              width: "100%",
            }}
          />
        )}
      </div>
    </Section>
  );
};

export default Hero;


================================================
FILE: apps/demo/config/blocks/Hero/client.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import React from "react";
import { ComponentConfig } from "@/core/types";
import { quotes } from "./quotes";
import { AutoField, FieldLabel, RichTextMenu } from "@/core";
import { Link2, Quote } from "lucide-react";
import HeroComponent, { HeroProps } from "./Hero";

export const Hero: ComponentConfig<{
  props: HeroProps;
  fields: {
    userField: {
      type: "userField";
      option: boolean;
    };
  };
}> = {
  fields: {
    quote: {
      type: "external",
      placeholder: "Select a quote",
      showSearch: false,
      renderFooter: ({ items }) => {
        return (
          <div>
            {items.length} result{items.length === 1 ? "" : "s"}
          </div>
        );
      },
      filterFields: {
        author: {
          type: "select",
          options: [
            { value: "", label: "Select an author" },
            { value: "Mark Twain", label: "Mark Twain" },
            { value: "Henry Ford", label: "Henry Ford" },
            { value: "Kurt Vonnegut", label: "Kurt Vonnegut" },
            { value: "Andrew Carnegie", label: "Andrew Carnegie" },
            { value: "C. S. Lewis", label: "C. S. Lewis" },
            { value: "Confucius", label: "Confucius" },
            { value: "Eleanor Roosevelt", label: "Eleanor Roosevelt" },
            { value: "Samuel Ullman", label: "Samuel Ullman" },
          ],
        },
      },
      fetchList: async ({ query, filters }) => {
        // Simulate delay
        await new Promise((res) => setTimeout(res, 500));

        return quotes
          .map((quote, idx) => ({
            index: idx,
            title: quote.author,
            description: quote.content,
          }))
          .filter((item) => {
            if (filters?.author && item.title !== filters?.author) {
              return false;
            }

            if (!query) return true;

            const queryLowercase = query.toLowerCase();

            if (item.title.toLowerCase().indexOf(queryLowercase) > -1) {
              return true;
            }

            if (item.description.toLowerCase().indexOf(queryLowercase) > -1) {
              return true;
            }
          });
      },
      mapRow: (item) => ({
        title: item.title,
        description: <span>{item.description}</span>,
      }),
      mapProp: (result) => {
        return { index: result.index, label: result.description };
      },
      getItemSummary: (item) => item.label,
    },
    title: { type: "text", contentEditable: true },
    description: {
      type: "richtext",
      contentEditable: true,
      options: {
        heading: false,
        textAlign: false,
      },
      renderMenu: ({ editor, editorState }) => {
        return (
          <RichTextMenu>
            <RichTextMenu.Group>
              <RichTextMenu.Bold />
              <RichTextMenu.Italic />
              <RichTextMenu.Underline />
            </RichTextMenu.Group>
            <RichTextMenu.Group>
              <RichTextMenu.ListSelect />
              <RichTextMenu.Control
                icon={<Quote />}
                title="Quote"
                active={editorState?.isBlockquote}
                onClick={() => {
                  editor?.chain().focus().toggleBlockquote().run();
                }}
              />
            </RichTextMenu.Group>
          </RichTextMenu>
        );
      },
    },
    buttons: {
      type: "array",
      min: 1,
      max: 4,
      getItemSummary: (item) => item.label || "Button",
      arrayFields: {
        label: { type: "text", contentEditable: true },
        href: { type: "text" },
        variant: {
          type: "select",
          options: [
            { label: "primary", value: "primary" },
            { label: "secondary", value: "secondary" },
          ],
        },
      },
      defaultItemProps: {
        label: "Button",
        href: "#",
      },
    },
    align: {
      type: "radio",
      options: [
        { label: "left", value: "left" },
        { label: "center", value: "center" },
      ],
    },
    image: {
      type: "object",
      objectFields: {
        content: { type: "slot" },
        url: {
          type: "custom",
          render: ({ value, field, name, onChange, readOnly }) => (
            <FieldLabel
              label={field.label || name}
              readOnly={readOnly}
              icon={<Link2 size="16" />}
            >
              <AutoField
                field={{ type: "text" }}
                value={value}
                onChange={onChange}
                readOnly={readOnly}
              />
            </FieldLabel>
          ),
        },
        mode: {
          type: "radio",
          options: [
            { label: "inline", value: "inline" },
            { label: "bg", value: "background" },
            { label: "custom", value: "custom" },
          ],
        },
      },
    },
    padding: { type: "userField", option: true },
  },
  defaultProps: {
    title: "Hero",
    align: "left",
    description: "<p>Description</p>",
    buttons: [{ label: "Learn more", href: "#" }],
    padding: "64px",
  },
  /**
   * The resolveData method allows us to modify component data after being
   * set by the user.
   *
   * It is called after the page data is changed, but before a component
   * is rendered. This allows us to make dynamic changes to the props
   * without storing the data in Puck.
   *
   * For example, requesting a third-party API for the latest content.
   */
  resolveData: async ({ props }, { changed }) => {
    if (!props.quote)
      return { props, readOnly: { title: false, description: false } };

    if (!changed.quote) {
      return { props };
    }

    // Simulate a delay
    await new Promise((resolve) => setTimeout(resolve, 500));

    return {
      props: {
        title: quotes[props.quote.index].author,
        description: `<p>${quotes[props.quote.index].content}</p>`,
      },
      readOnly: { title: true, description: true },
    };
  },
  resolveFields: async (data, { fields }) => {
    if (data.props.align === "center") {
      return {
        ...fields,
        image: undefined,
      };
    }

    return fields;
  },
  resolvePermissions: async (data, params) => {
    if (!params.changed.quote) return params.lastPermissions;

    // Simulate delay
    await new Promise((resolve) => setTimeout(resolve, 500));

    return {
      ...params.permissions,
      // Disable delete if quote 7 is selected
      delete: data.props.quote?.index !== 7,
    };
  },
  render: HeroComponent,
};


================================================
FILE: apps/demo/config/blocks/Hero/index.tsx
================================================
export * from "./client";
export { type HeroProps } from "./Hero";


================================================
FILE: apps/demo/config/blocks/Hero/quotes.ts
================================================
export const quotes = [
  {
    content:
      "Age is an issue of mind over matter. If you don't mind, it doesn't matter.",
    author: "Mark Twain",
  },
  {
    content:
      "Anyone who stops learning is old, whether at twenty or eighty. Anyone who keeps learning stays young. The greatest thing in life is to keep your mind young.",
    author: "Henry Ford",
  },
  {
    content: "Wrinkles should merely indicate where smiles have been.",
    author: "Mark Twain",
  },
  {
    content:
      "True terror is to wake up one morning and discover that your high school class is running the country.",
    author: "Kurt Vonnegut",
  },
  {
    content:
      "As I grow older, I pay less attention to what men say. I just watch what they do.",
    author: "Andrew Carnegie",
  },
  {
    content:
      "How incessant and great are the ills with which a prolonged old age is replete.",
    author: "C. S. Lewis",
  },
  {
    content:
      "Old age, believe me, is a good and pleasant thing. It is true you are gently shouldered off the stage, but then you are given such a comfortable front stall as spectator.",
    author: "Confucius",
  },
  {
    content:
      "Old age has deformities enough of its own. It should never add to them the deformity of vice.",
    author: "Eleanor Roosevelt",
  },
  {
    content:
      "Nobody grows old merely by living a number of years. We grow old by deserting our ideals. Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul.",
    author: "Samuel Ullman",
  },
];


================================================
FILE: apps/demo/config/blocks/Hero/server.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import { ComponentConfig } from "@/core/types";
import HeroComponent, { HeroProps } from "./Hero";

export const Hero: ComponentConfig<HeroProps> = {
  render: HeroComponent,
};


================================================
FILE: apps/demo/config/blocks/Hero/styles.module.css
================================================
.Hero {
  background-image: linear-gradient(
    rgba(255, 255, 255, 0),
    rgb(247, 250, 255) 100%
  );
  display: flex;
  align-items: center;
  position: relative;
}

.Hero-inner {
  display: flex;
  align-items: center;
  position: relative;
  gap: 48px;
  flex-wrap: wrap;
  z-index: 1;
}

@media (min-width: 1024px) {
  .Hero-inner {
    flex-wrap: nowrap;
  }
}

.Hero h1 {
  line-height: 1.1;
  font-size: 48px;
  margin: 0;
}

@media (min-width: 768px) {
  .Hero h1 {
    font-size: 64px;
  }
}

.Hero-subtitle {
  color: var(--puck-color-grey-05);
  font-size: var(--puck-font-size-m);
  line-height: 1.5;
  margin: 0;
  margin-bottom: 8px;
  font-weight: 300;
}

.Hero-subtitle strong {
  font-weight: 500;
}

.Hero--hasImageBackground .Hero-subtitle {
  color: var(--puck-color-grey-03);
}

.Hero-image {
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  left: 0;
}

.Hero-imageOverlay {
  background-image: linear-gradient(
    -90deg,
    rgb(247, 250, 255, 0.7) 0%,
    rgb(247, 250, 255, 0.7) 80%
  );
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  left: 0;
}

@media (min-width: 768px) {
  .Hero--left .Hero-imageOverlay {
    background-image: linear-gradient(
      -90deg,
      rgba(255, 255, 255, 0) 0%,
      rgb(247, 250, 255) 70%
    );
  }
}

.Hero-bg img {
  height: 100%;
}

.Hero-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
}

@media (min-width: 768px) {
  .Hero--hasImageBackground .Hero-content {
    max-width: 50%;
  }
}

.Hero--center .Hero-inner {
  justify-content: center;
  text-align: center;
}

.Hero--center .Hero-content {
  align-items: center;
  justify-content: center;
  max-width: 100%;
}

.Hero-actions {
  display: flex;
  gap: 16px;
}


================================================
FILE: apps/demo/config/blocks/Logos/index.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import React from "react";
import { ComponentConfig } from "@/core";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Section } from "../../components/Section";

const getClassName = getClassNameFactory("Logos", styles);

export type LogosProps = {
  logos: {
    alt: string;
    imageUrl: string;
  }[];
};

export const Logos: ComponentConfig<LogosProps> = {
  fields: {
    logos: {
      type: "array",
      getItemSummary: (item, i) => item.alt || `Feature #${i}`,
      defaultItemProps: {
        alt: "",
        imageUrl: "",
      },
      arrayFields: {
        alt: { type: "text" },
        imageUrl: { type: "text" },
      },
    },
  },
  defaultProps: {
    logos: [
      {
        alt: "google",
        imageUrl:
          "https://logolook.net/wp-content/uploads/2021/06/Google-Logo.png",
      },
      {
        alt: "google",
        imageUrl:
          "https://logolook.net/wp-content/uploads/2021/06/Google-Logo.png",
      },
      {
        alt: "google",
        imageUrl:
          "https://logolook.net/wp-content/uploads/2021/06/Google-Logo.png",
      },
      {
        alt: "google",
        imageUrl:
          "https://logolook.net/wp-content/uploads/2021/06/Google-Logo.png",
      },
      {
        alt: "google",
        imageUrl:
          "https://logolook.net/wp-content/uploads/2021/06/Google-Logo.png",
      },
    ],
  },
  render: ({ logos }) => {
    return (
      <Section className={getClassName()}>
        <div className={getClassName("items")}>
          {logos.map((item, i) => (
            <div key={i} className={getClassName("item")}>
              <img
                className={getClassName("image")}
                alt={item.alt}
                src={item.imageUrl}
                height={64}
              ></img>
            </div>
          ))}
        </div>
      </Section>
    );
  },
};


================================================
FILE: apps/demo/config/blocks/Logos/styles.module.css
================================================
.Logos {
  background-color: var(--puck-color-grey-02);
}

.Logos-items {
  display: flex;
  justify-content: space-between;
  padding-bottom: 64px;
  padding-top: 64px;
  gap: 24px;
  filter: grayscale(1) brightness(100);
  opacity: 0.8;
}


================================================
FILE: apps/demo/config/blocks/RichText/index.tsx
================================================
import React from "react";
import { ComponentConfig } from "@/core/types";
import { WithLayout, withLayout } from "../../components/Layout";
import { Section } from "../../components/Section";

export type RichTextProps = WithLayout<{
  richtext?: string;
}>;

const RichTextInner: ComponentConfig<RichTextProps> = {
  fields: {
    richtext: {
      type: "richtext",
    },
  },
  render: ({ richtext }) => {
    return <Section>{richtext}</Section>;
  },
  defaultProps: {
    richtext: "<h2>Heading</h2><p>Body</p>",
  },
};

export const RichText = withLayout(RichTextInner);


================================================
FILE: apps/demo/config/blocks/Space/index.tsx
================================================
import React from "react";

import { ComponentConfig } from "@/core";
import { spacingOptions } from "../../options";
import { getClassNameFactory } from "@/core/lib";

import styles from "./styles.module.css";

const getClassName = getClassNameFactory("Space", styles);

export type SpaceProps = {
  direction?: "" | "vertical" | "horizontal";
  size: string;
};

export const Space: ComponentConfig<SpaceProps> = {
  label: "Space",
  fields: {
    size: {
      type: "select",
      options: spacingOptions,
    },
    direction: {
      type: "radio",
      options: [
        { value: "vertical", label: "Vertical" },
        { value: "horizontal", label: "Horizontal" },
        { value: "", label: "Both" },
      ],
    },
  },
  defaultProps: {
    direction: "",
    size: "24px",
  },
  inline: true,
  render: ({ direction, size, puck }) => {
    return (
      <div
        ref={puck.dragRef}
        className={getClassName(direction ? { [direction]: direction } : {})}
        style={{ "--size": size } as any}
      />
    );
  },
};


================================================
FILE: apps/demo/config/blocks/Space/styles.module.css
================================================
.Space {
  display: block;
  height: var(--size);
  width: var(--size);
}

.Space--vertical {
  width: 100%;
}

.Space--horizontal {
  width: var(--size);
  height: 100%;
}


================================================
FILE: apps/demo/config/blocks/Stats/index.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import React from "react";
import { ComponentConfig } from "@/core";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Section } from "../../components/Section";

const getClassName = getClassNameFactory("Stats", styles);

export type StatsProps = {
  items: {
    title: string;
    description: string;
  }[];
};

export const Stats: ComponentConfig<StatsProps> = {
  fields: {
    items: {
      type: "array",
      getItemSummary: (item, i) =>
        item.title && item.description ? (
          <>
            {item.title} ({item.description})
          </>
        ) : (
          `Feature #${i}`
        ),
      defaultItemProps: {
        title: "Stat",
        description: "1,000",
      },
      arrayFields: {
        title: {
          type: "text",
          contentEditable: true,
        },
        description: {
          type: "text",
          contentEditable: true,
        },
      },
    },
  },
  defaultProps: {
    items: [
      {
        title: "Stat",
        description: "1,000",
      },
    ],
  },
  render: ({ items }) => {
    return (
      <Section className={getClassName()} maxWidth={"916px"}>
        <div className={getClassName("items")}>
          {items.map((item, i) => (
            <div key={i} className={getClassName("item")}>
              <div className={getClassName("label")}>{item.title}</div>
              <div className={getClassName("value")}>{item.description}</div>
            </div>
          ))}
        </div>
      </Section>
    );
  },
};


================================================
FILE: apps/demo/config/blocks/Stats/styles.module.css
================================================
.Stats-items {
  background-image: linear-gradient(
    120deg,
    var(--puck-color-azure-03) 0%,
    var(--puck-color-azure-05) 100%
  );
  border-radius: 24px;
  display: grid;
  grid-template-columns: 1fr;
  grid-gap: 72px;
  align-items: center;
  justify-content: space-between;
  margin: 0 auto;
  max-width: 768px;
  padding: 64px 16px;
}

@media (min-width: 768px) {
  .Stats-items {
    padding: 64px 24px;
  }
}

@media (min-width: 1024px) {
  .Stats-items {
    grid-template-columns: 1fr 1fr;
    padding: 128px 24px;
    max-width: 100%;
  }
}

.Stats-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: white;
  gap: 8px;
  width: 100%;
  text-align: center;
}

.Stats-icon {
  border-radius: 256px;
  background: var(--puck-color-azure-09);
  color: var(--puck-color-azure-06);
  display: flex;
  justify-content: center;
  align-items: center;
  width: 64px;
  height: 64px;
}

.Stats-label {
  font-size: 22px;
  text-align: center;
  font-weight: 600;
  opacity: 0.8;
}

.Stats-value {
  font-size: 72px;
  line-height: 1;
  font-weight: 700;
}


================================================
FILE: apps/demo/config/blocks/Template/Template.tsx
================================================
import React from "react";
import { Slot } from "@/core/types";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";
import { Section } from "../../components/Section";
import { PuckComponent } from "@/core/types";

const getClassName = getClassNameFactory("Template", styles);

export type TemplateProps = {
  template: string;
  children: Slot;
};

export const Template: PuckComponent<TemplateProps> = ({
  children: Children,
}) => {
  return (
    <Section>
      <Children className={getClassName()} />
    </Section>
  );
};

export default Template;


================================================
FILE: apps/demo/config/blocks/Template/client.tsx
================================================
/* eslint-disable react-hooks/rules-of-hooks */
import React, { useState } from "react";
import { AutoField, Button, createUsePuck, FieldLabel, walkTree } from "@/core";
import { ComponentConfig, ComponentDataOptionalId, Slot } from "@/core/types";
import { withLayout } from "../../components/Layout";
import { generateId } from "@/core/lib/generate-id";
import { componentKey } from "../../index";
import { type Components } from "../../types";
import TemplateComponent, { TemplateProps } from "./Template";

const usePuck = createUsePuck();

async function createComponent<T extends keyof Components>(
  component: T,
  props?: Partial<Components[T]>
): Promise<ComponentDataOptionalId<Components[T]>> {
  const { conf: config } = await import("../../index");

  return {
    type: component,
    props: {
      ...config.components[component].defaultProps,
      ...props,
    },
  } as ComponentDataOptionalId<Components[T]>;
}

type TemplateData = Record<string, { label: string; data: Slot }>;

export const TemplateInternal: ComponentConfig<TemplateProps> = {
  fields: {
    template: {
      type: "custom",
      render: ({ name, value, onChange }) => {
        const templateKey = `puck-demo-templates:${componentKey}`;

        const props = usePuck((s) => s.selectedItem?.props) as
          | TemplateProps
          | undefined;

        const [templates, setTemplates] = useState<TemplateData>(
          JSON.parse(localStorage.getItem(templateKey) ?? "{}")
        );

        return (
          <FieldLabel label={name}>
            <AutoField
              value={value}
              onChange={onChange}
              field={{
                type: "select",
                options: [
                  { label: "Blank", value: "blank" },
                  { label: "Example 1", value: "example_1" },
                  { label: "Example 2", value: "example_2" },
                  ...Object.entries(templates).map(([key, template]) => ({
                    value: key,
                    label: template.label,
                  })),
                ],
              }}
            />
            <div style={{ marginLeft: "auto", marginTop: 16 }}>
              <Button
                variant="secondary"
                onClick={async () => {
                  if (!props?.children) {
                    return;
                  }

                  const templateId = generateId();

                  const { conf: config } = await import("../../index");

                  const data = props.children.map((child) =>
                    walkTree(
                      {
                        type: child.type,
                        props: { ...child.props, id: generateId(child.type) },
                      },
                      config,
                      (content) =>
                        content.map((item) => ({
                          ...item,
                          props: { ...item.props, id: generateId(item.type) },
                        }))
                    )
                  );

                  const templateData = {
                    ...templates,
                    [templateId]: {
                      label: new Date().toLocaleString(),
                      data,
                    },
                  };

                  localStorage.setItem(
                    templateKey,
                    JSON.stringify(templateData)
                  );

                  setTemplates(templateData);

                  onChange(templateId);
                }}
              >
                Save new template
              </Button>
            </div>
          </FieldLabel>
        );
      },
    },
    children: {
      type: "slot",
    },
  },
  defaultProps: {
    template: "example_1",
    children: [],
  },
  resolveData: async (data, { changed, trigger }) => {
    if (!changed.template || trigger === "load") return data;

    const templateKey = `puck-demo-templates:${componentKey}`;

    const templates: TemplateData = {
      ...JSON.parse(localStorage.getItem(templateKey) ?? "{}"),
      blank: {
        label: "Blank",
        data: [],
      },
      example_1: {
        label: "Example 1",
        data: [
          await createComponent("Heading", {
            text: "Template example.",
            size: "xl",
          }),
          await createComponent("Text", {
            text: "This component uses the slots API. Try changing template, or saving a new one via the template field.",
          }),
        ],
      },
      example_2: {
        label: "Example 2",
        data: [
          await createComponent("Grid", {
            numColumns: 2,
            items: [
              await createComponent("Card", { title: "A card", mode: "card" }),
              await createComponent("Flex", {
                direction: "column",
                gap: 0,
                items: [
                  await createComponent("Space", {
                    size: "32px",
                  }),
                  await createComponent("Heading", {
                    text: "Template example",
                    size: "xl",
                  }),
                  await createComponent("Text", {
                    text: "Dynamically create components using the new slots API.",
                  }),
                  await createComponent("Space", {
                    size: "16px",
                  }),
                  await createComponent("Button", {
                    variant: "secondary",
                    label: "Learn more",
                  }),
                  await createComponent("Space", {
                    size: "32px",
                  }),
                ],
              }),
            ],
          }),
        ],
      },
    };

    const children =
      templates[data.props.template]?.data || templates["example_1"].data;

    return {
      ...data,
      props: {
        ...data.props,
        children,
      },
    };
  },
  render: TemplateComponent,
};

export const Template = withLayout(TemplateInternal);


================================================
FILE: apps/demo/config/blocks/Template/index.tsx
================================================
export * from "./client";
export { type TemplateProps } from "./Template";


================================================
FILE: apps/demo/config/blocks/Template/server.tsx
================================================
import { ComponentConfig } from "@/core/types";
import { withLayout } from "../../components/Layout";
import TemplateComponent, { TemplateProps } from "./Template";

export const TemplateInternal: ComponentConfig<TemplateProps> = {
  render: TemplateComponent,
};

export const Template = withLayout(TemplateInternal);


================================================
FILE: apps/demo/config/blocks/Template/styles.module.css
================================================
.Template {
  display: flex;
  flex-direction: column;
  width: auto;
}

@media (min-width: 768px) {
  .Template {
    display: grid;
  }
}


================================================
FILE: apps/demo/config/blocks/Text/index.tsx
================================================
import React from "react";
import { ALargeSmall, AlignLeft } from "lucide-react";

import { ComponentConfig } from "@/core/types";
import { Section } from "../../components/Section";
import { WithLayout, withLayout } from "../../components/Layout";

export type TextProps = WithLayout<{
  align: "left" | "center" | "right";
  text?: string;
  padding?: string;
  size?: "s" | "m";
  color: "default" | "muted";
  maxWidth?: string;
}>;

const TextInner: ComponentConfig<TextProps> = {
  fields: {
    text: {
      type: "textarea",
      contentEditable: true,
    },
    size: {
      type: "select",
      labelIcon: <ALargeSmall size={16} />,
      options: [
        { label: "S", value: "s" },
        { label: "M", value: "m" },
      ],
    },
    align: {
      type: "radio",
      labelIcon: <AlignLeft size={16} />,
      options: [
        { label: "Left", value: "left" },
        { label: "Center", value: "center" },
        { label: "Right", value: "right" },
      ],
    },
    color: {
      type: "radio",
      options: [
        { label: "Default", value: "default" },
        { label: "Muted", value: "muted" },
      ],
    },
    maxWidth: { type: "text" },
  },
  defaultProps: {
    align: "left",
    text: "Text",
    size: "m",
    color: "default",
  },
  render: ({ align, color, text, size, maxWidth }) => {
    return (
      <Section maxWidth={maxWidth}>
        <span
          style={{
            color:
              color === "default" ? "inherit" : "var(--puck-color-grey-05)",
            display: "flex",
            textAlign: align,
            width: "100%",
            fontSize: size === "m" ? "20px" : "16px",
            fontWeight: 300,
            maxWidth,
            justifyContent:
              align === "center"
                ? "center"
                : align === "right"
                ? "flex-end"
                : "flex-start",
          }}
        >
          {text}
        </span>
      </Section>
    );
  },
};

export const Text = withLayout(TextInner);


================================================
FILE: apps/demo/config/blocks/Text/styles.module.css
================================================
.Text {
  line-height: 1.5;
  padding: 0px;
}


================================================
FILE: apps/demo/config/components/Footer/index.tsx
================================================
import { ReactNode } from "react";
import { Section } from "../Section";

const FooterLink = ({ children, href }: { children: string; href: string }) => {
  const El = href ? "a" : "span";

  return (
    <li style={{ paddingBottom: 8 }}>
      <El
        href={href}
        style={{
          textDecoration: "none",
          fontSize: "14px",
          color: "var(--puck-color-grey-05)",
        }}
      >
        {children}
      </El>
    </li>
  );
};

const FooterList = ({
  children,
  title,
}: {
  children: ReactNode;
  title: string;
}) => {
  return (
    <div>
      <h3
        style={{
          margin: 0,
          padding: 0,
          fontSize: "inherit",
          fontWeight: "600",
          color: "var(--puck-color-grey-03)",
        }}
      >
        {title}
      </h3>
      <ul
        style={{
          listStyle: "none",
          margin: 0,
          padding: 0,
          paddingTop: 12,
        }}
      >
        {children}
      </ul>
    </div>
  );
};

const Footer = ({ children }: { children: ReactNode }) => {
  return (
    <footer style={{ background: "var(--puck-color-grey-12)" }}>
      <h2 style={{ visibility: "hidden", height: 0, margin: 0 }}>Footer</h2>
      <div style={{ padding: 32 }}>
        <Section>
          <div
            style={{
              display: "grid",
              gridGap: 24,
              gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
              paddingTop: 24,
              paddingBottom: 24,
            }}
          >
            {children}
          </div>
        </Section>
      </div>
      <div
        style={{
          padding: 64,
          textAlign: "center",
          color: "var(--puck-color-grey-03)",
          background: "var(--puck-color-grey-11)",
        }}
      >
        Made by{" "}
        <a
          href="https://github.com/chrisvxd"
          target="_blank"
          style={{ color: "inherit", textDecoration: "none", fontWeight: 600 }}
        >
          Chris Villa
        </a>
      </div>
    </footer>
  );
};

Footer.List = FooterList;
Footer.Link = FooterLink;

export { Footer };


================================================
FILE: apps/demo/config/components/Header/index.tsx
================================================
import { getClassNameFactory } from "@/core/lib";

import styles from "./styles.module.css";

const getClassName = getClassNameFactory("Header", styles);

const NavItem = ({ label, href }: { label: string; href: string }) => {
  const navPath =
    typeof window !== "undefined"
      ? window.location.pathname.replace("/edit", "") || "/"
      : "/";

  const isActive = navPath === (href.replace("/edit", "") || "/");

  const El = href ? "a" : "span";

  return (
    <El
      href={href || "/"}
      style={{
        textDecoration: "none",
        color: isActive
          ? "var(--puck-color-grey-02)"
          : "var(--puck-color-grey-06)",
        fontWeight: isActive ? "600" : "400",
      }}
    >
      {label}
    </El>
  );
};

const Header = ({ editMode }: { editMode: boolean }) => (
  <div className={getClassName()}>
    <header className={getClassName("inner")}>
      <div className={getClassName("logo")}>LOGO</div>
      <nav className={getClassName("items")}>
        <NavItem label="Home" href={`${editMode ? "" : "/"}`} />
        <NavItem label="Pricing" href={editMode ? "" : "/pricing"} />
        <NavItem label="About" href={editMode ? "" : "/about"} />
      </nav>
    </header>
  </div>
);

export { Header };


================================================
FILE: apps/demo/config/components/Header/styles.module.css
================================================
.Header {
  background-color: white;
  position: sticky;
  top: 0;
  z-index: 2;
}

.Header-inner {
  align-items: center;
  display: flex;
  margin-inline-start: auto;
  margin-inline-end: auto;
  max-width: 1280px;
  padding: 24px 16px;
}

@media (min-width: 768px) {
  .Header-inner {
    padding: 24px;
  }
}

.Header-logo {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: 1.4;
  opacity: 0.8;
}

.Header-items {
  display: flex;
  gap: 24px;
  margin-inline-start: auto;
}

@media (min-width: 1024px) {
  .Header-items {
    gap: 32px;
  }
}


================================================
FILE: apps/demo/config/components/Layout/index.tsx
================================================
import { CSSProperties, forwardRef, ReactNode } from "react";
import {
  ComponentConfig,
  DefaultComponentProps,
  ObjectField,
} from "@/core/types";
import { spacingOptions } from "../../options";
import { getClassNameFactory } from "@/core/lib";
import styles from "./styles.module.css";

const getClassName = getClassNameFactory("Layout", styles);

type LayoutFieldProps = {
  padding?: string;
  spanCol?: number;
  spanRow?: number;
  grow?: boolean;
};

export type WithLayout<Props extends DefaultComponentProps> = Props & {
  layout?: LayoutFieldProps;
};

type LayoutProps = WithLayout<{
  children: ReactNode;
  className?: string;
  style?: CSSProperties;
}>;

export const layoutField: ObjectField<LayoutFieldProps> = {
  type: "object",
  objectFields: {
    spanCol: {
      label: "Grid Columns",
      type: "number",
      min: 1,
      max: 12,
    },
    spanRow: {
      label: "Grid Rows",
      type: "number",
      min: 1,
      max: 12,
    },
    grow: {
      label: "Flex Grow",
      type: "radio",
      options: [
        { label: "true", value: true },
        { label: "false", value: false },
      ],
    },
    padding: {
      type: "select",
      label: "Vertical Padding",
      options: [{ label: "0px", value: "0px" }, ...spacingOptions],
    },
  },
};

const Layout = forwardRef<HTMLDivElement, LayoutProps>(
  ({ children, className, layout, style }, ref) => {
    return (
      <div
        className={className}
        style={{
          gridColumn: layout?.spanCol
            ? `span ${Math.max(Math.min(layout.spanCol, 12), 1)}`
            : undefined,
          gridRow: layout?.spanRow
            ? `span ${Math.max(Math.min(layout.spanRow, 12), 1)}`
            : undefined,
          paddingTop: layout?.padding,
          paddingBottom: layout?.padding,
          flex: layout?.grow ? "1 1 0" : undefined,
          ...style,
        }}
        ref={ref}
      >
        {children}
      </div>
    );
  }
);

Layout.displayName = "Layout";

export { Layout };

export function withLayout<
  ThisComponentConfig extends ComponentConfig<any> = ComponentConfig
>(componentConfig: ThisComponentConfig): ThisComponentConfig {
  return {
    ...componentConfig,
    fields: {
      ...componentConfig.fields,
      layout: layoutField,
    },
    defaultProps: {
      ...componentConfig.defaultProps,
      layout: {
        spanCol: 1,
        spanRow: 1,
        padding: "0px",
        grow: false,
        ...componentConfig.defaultProps?.layout,
      },
    },
    resolveFields: (_, params) => {
      if (params.parent?.type === "Grid") {
        return {
          ...componentConfig.fields,
          layout: {
            ...layoutField,
            objectFields: {
              spanCol: layoutField.objectFields.spanCol,
              spanRow: layoutField.objectFields.spanRow,
              padding: layoutField.objectFields.padding,
            },
          },
        };
      }
      if (params.parent?.type === "Flex") {
        return {
          ...componentConfig.fields,
          layout: {
            ...layoutField,
            objectFields: {
              grow: layoutField.objectFields.grow,
              padding: layoutField.objectFields.padding,
            },
          },
        };
      }

      return {
        ...componentConfig.fields,
        layout: {
          ...layoutField,
          objectFields: {
            padding: layoutField.objectFields.padding,
          },
        },
      };
    },
    inline: true,
    render: (props) => (
      <Layout
        className={getClassName()}
        layout={props.layout as LayoutFieldProps}
        ref={props.puck.dragRef}
      >
        {componentConfig.render(props)}
      </Layout>
    ),
  };
}


================================================
FILE: apps/demo/config/components/Layout/styles.module.css
================================================
.Layout {
  display: block;
}


================================================
FILE: apps/demo/config/components/Section/index.tsx
================================================
import { CSSProperties, forwardRef, ReactNode } from "react";
import styles from "./styles.module.css";
import { getClassNameFactory } from "@/core/lib";

const getClassName = getClassNameFactory("Section", styles);

export type SectionProps = {
  className?: string;
  children: ReactNode;
  maxWidth?: string;
  style?: CSSProperties;
};

export const Section = forwardRef<HTMLDivElement, SectionProps>(
  ({ children, className, maxWidth = "1280px", style = {} }, ref) => {
    return (
      <div
        className={`${getClassName()}${className ? ` ${className}` : ""}`}
        style={{
          ...style,
        }}
        ref={ref}
      >
        <div className={getClassName("inner")} style={{ maxWidth }}>
          {children}
        </div>
      </div>
    );
  }
);


================================================
FILE: apps/demo/config/components/Section/styles.module.css
================================================
.Section:not(.Section .Section) {
  padding-inline-start: 16px;
  padding-inline-end: 16px;
}

@media (min-width: 768px) {
  .Section:not(.Section .Section) {
    padding-inline-start: 24px;
    padding-inline-end: 24px;
  }
}

.Section-inner {
  margin-inline-start: auto;
  margin-inline-end: auto;
  height: 100%;
  width: 100%;
}

.Section .Section .Section-inner {
  margin-inline-start: 0;
  margin-inline-end: 0;
}


================================================
FILE: apps/demo/config/index.tsx
================================================
import { Button } from "./blocks/Button";
import { Card } from "./blocks/Card";
import { Grid } from "./blocks/Grid";
import { Hero } from "./blocks/Hero";
import { Heading } from "./blocks/Heading";
import { Flex } from "./blocks/Flex";
import { Logos } from "./blocks/Logos";
import { Stats } from "./blocks/Stats";
import { Template } from "./blocks/Template";
import { Text } from "./blocks/Text";
import { Space } from "./blocks/Space";
import { RichText } from "./blocks/RichText";

import Root from "./root";
import { UserConfig } from "./types";
import { initialData } from "./initial-data";

// We avoid the name config as next gets confused
export const conf: UserConfig = {
  root: Root,
  categories: {
    layout: {
      components: ["Grid", "Flex", "Space"],
    },
    typography: {
      components: ["Heading", "Text", "RichText"],
    },
    interactive: {
      title: "Actions",
      components: ["Button"],
    },
    other: {
      title: "Other",
      components: ["Card", "Hero", "Logos", "Stats", "Template"],
    },
  },
  components: {
    Button,
    Card,
    Grid,
    Hero,
    Heading,
    Flex,
    Logos,
    Stats,
    Template,
    Text,
    Space,
    RichText,
  },
};

export const componentKey = Buffer.from(
  `${Object.keys(conf.components).join("-")}-${JSON.stringify(initialData)}`
).toString("base64");

export default conf;


================================================
FILE: apps/demo/config/initial-data.ts
================================================
import { UserData } from "./types";

export const initialData: Record<string, UserData> = {
  "/": {
    content: [
      {
        type: "Hero",
        props: {
          title: "This page was built with Puck",
          description:
            "<p>Puck is the self-hosted visual editor for React. Bring your own components and make site changes instantly, without a deploy.</p>",
          buttons: [
            {
              label: "Visit GitHub",
              href: "https://github.com/puckeditor/puck",
            },
            { label: "Edit this page", href: "/edit", variant: "secondary" },
          ],
          id: "Hero-1687283596554",
          image: {
            url: "https://images.unsplash.com/photo-1687204209659-3bded6aecd79?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2670&q=80",
            mode: "inline",
            content: [],
          },
          padding: "128px",
          align: "left",
        },
        readOnly: { title: false, description: false },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687298109536",
          direction: "vertical",
        },
      },
      {
        type: "Heading",
        props: {
          align: "center",
          level: "2",
          text: "Drag-and-drop your own React components",
          layout: { padding: "0px" },
          size: "xxl",
          id: "Heading-1687297593514",
        },
      },
      {
        type: "Space",
        props: {
          size: "8px",
          id: "Space-1687284122744",
          direction: "vertical",
        },
      },
      {
        type: "Text",
        props: {
          align: "center",
          text: "Configure Puck with your own components to make change for your marketing pages without a developer.",
          layout: { padding: "0px" },
          size: "m",
          id: "Text-1687297621556",
          color: "muted",
        },
      },
      {
        type: "Space",
        props: {
          size: "40px",
          id: "Space-1687296179388",
          direction: "vertical",
        },
      },
      {
        type: "Grid",
        props: {
          id: "Grid-c4cd99ae-8c5e-4cdb-87d2-35a639f5163e",
          gap: 24,
          numColumns: 3,
          items: [
            {
              type: "Card",
              props: {
                title: "Built for content teams",
                description:
                  "Puck enables content teams to make changes to their content without a developer or breaking the UI.",
                icon: "pen-tool",
                mode: "flat",
                layout: { grow: true, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-66ab42c9-d1da-4c44-9dba-5d7d72f2178d",
              },
            },
            {
              type: "Card",
              props: {
                title: "Easy to integrate",
                description:
                  "Front-end developers can easily integrate their own components using a familiar React API.",
                icon: "git-merge",
                mode: "flat",
                layout: { grow: true, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-0012a293-8ef3-4e7c-9d7c-7da0a03d97ae",
              },
            },
            {
              type: "Card",
              props: {
                title: "No vendor lock-in",
                description:
                  "Completely open-source, Puck is designed to be integrated into your existing React application.",
                icon: "github",
                mode: "flat",
                layout: { grow: true, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-09efb3f3-f58d-4e07-a481-7238d7e57ad6",
              },
            },
          ],
        },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687287070296",
          direction: "vertical",
        },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687298110602",
          direction: "vertical",
        },
      },
      {
        type: "Heading",
        props: {
          align: "center",
          level: "2",
          text: "The numbers",
          layout: { padding: "0px" },
          size: "xxl",
          id: "Heading-1687296574110",
        },
      },
      {
        type: "Space",
        props: {
          size: "16px",
          id: "Space-1687284283005",
          direction: "vertical",
        },
      },
      {
        type: "Text",
        props: {
          align: "center",
          text: 'This page demonstrates Puck configured with a custom component library. This component is called "Stats", and contains some made-up numbers. You can configure any page by adding "/edit" onto the URL.',
          layout: { padding: "0px" },
          size: "m",
          id: "Text-1687284565722",
          color: "muted",
          maxWidth: "916px",
        },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687297618253",
          direction: "vertical",
        },
      },
      {
        type: "Stats",
        props: {
          items: [
            { title: "Users reached", description: "20M+" },
            { title: "Cost savings", description: "$1.5M" },
            { title: "Another stat", description: "5M kg" },
            { title: "Final fake stat", description: "15K" },
          ],
          id: "Stats-1687297239724",
        },
      },
      {
        type: "Space",
        props: {
          size: "120px",
          id: "Space-1687297589663",
          direction: "vertical",
        },
      },
      {
        type: "Heading",
        props: {
          align: "center",
          level: "2",
          text: "Extending Puck",
          layout: { padding: "0px" },
          size: "xxl",
          id: "Heading-1687296184321",
        },
      },
      {
        type: "Space",
        props: {
          size: "8px",
          id: "Space-1687296602860",
          direction: "vertical",
        },
      },
      {
        type: "Text",
        props: {
          align: "center",
          text: "Puck can also be extended with plugins and headless CMS content fields, transforming Puck into the perfect tool for your Content Ops.",
          layout: { padding: "0px" },
          size: "m",
          id: "Text-1687296579834",
          color: "muted",
          maxWidth: "916px",
        },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687299311382",
          direction: "vertical",
        },
      },
      {
        type: "Grid",
        props: {
          gap: 24,
          numColumns: 3,
          id: "Grid-2da28e88-7b7b-4152-9da0-9f93f41213b6",
          items: [
            {
              type: "Card",
              props: {
                title: "plugin-heading-analyzer",
                description:
                  "Analyze the document structure and identify WCAG 2.1 issues with your heading hierarchy.",
                icon: "align-left",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-b0e8407d-9fbb-4e76-aa32-d32f655c11d3",
              },
            },
            {
              type: "Card",
              props: {
                title: "External data",
                description:
                  "Connect your components with an existing data source, like Strapi.js.",
                icon: "feather",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-f8ebd568-3a30-4099-a068-22cabae4691b",
              },
            },
            {
              type: "Card",
              props: {
                title: "Custom plugins",
                description:
                  "Create your own plugin to extend Puck for your use case using React.",
                icon: "plug",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-9c3b0acc-ee42-4a4a-8cc7-1b22d98493f1",
              },
            },
            {
              type: "Card",
              props: {
                title: "Title",
                description: "Description",
                icon: "Feather",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-dbec4ae9-8208-49bf-8910-3347ff13d957",
              },
            },
            {
              type: "Card",
              props: {
                title: "Title",
                description: "Description",
                icon: "Feather",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-e807464c-4974-4dbb-b1c9-989deabce58d",
              },
            },
            {
              type: "Card",
              props: {
                title: "Title",
                description: "Description",
                icon: "Feather",
                mode: "card",
                layout: { grow: false, spanCol: 1, spanRow: 1, padding: "0px" },
                id: "Card-3b4b7d53-2124-4d7a-a67e-36b24fd765b4",
              },
            },
          ],
        },
      },
      {
        type: "Space",
        props: {
          size: "96px",
          id: "Space-1687299315421",
          direction: "vertical",
        },
      },
      {
        type: "Heading",
        props: {
          align: "center",
          level: "2",
          text: "Get started",
          layout: { padding: "0px" },
          size: "xxl",
          id: "Heading-1687299303766",
        },
      },
      {
        type: "Space",
        props: {
          size: "16px",
          id: "Space-1687299318902",
          direction: "vertical",
        },
      },
      {
        type: "Text",
        props: {
          align: "center",
          text: "Browse the Puck GitHub to get started, or try editing this page",
          layout: { padding: "0px" },
          size: "m",
          id: "Text-1687299305686",
          color: "muted",
        },
      },
      {
        type: "Space",
        props: {
          size: "24px",
          id: "Space-1687299335149",
          direction: "vertical",
        },
      },
      {
        type: "Flex",
        props: {
          justifyContent: "center",
          direction: "row",
          gap: 24,
          wrap: "wrap",
          layout: { spanCol: 1, spanRow: 1, padding: "0px" },
          id: "Flex-7d63d5ff-bd42-4354-b05d-681b16436fd6",
          items: [
            {
              type: "Button",
              props: {
                label: "Visit GitHub",
                href: "https://github.com/puckeditor/puck",
                variant: "primary",
                id: "Button-bd41007c-6627-414d-839a-e261d470d8f9",
              },
            },
            {
              type: "Button",
              props: {
                label: "Edi
Download .txt
gitextract_c768lzuy/

├── .eslintrc.js
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── ci.yml
│       ├── publish-canary.yml
│       └── publish.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── .yarnrc
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps/
│   ├── demo/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── custom-ui/
│   │   │   │   └── [...puckPath]/
│   │   │   │       ├── client.tsx
│   │   │   │       └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── rsc/
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── config/
│   │   │   ├── blocks/
│   │   │   │   ├── Blank/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Button/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Card/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Flex/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Grid/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Heading/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Hero/
│   │   │   │   │   ├── Hero.tsx
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── quotes.ts
│   │   │   │   │   ├── server.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Logos/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── RichText/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Space/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Stats/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Template/
│   │   │   │   │   ├── Template.tsx
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── server.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   └── Text/
│   │   │   │       ├── index.tsx
│   │   │   │       └── styles.module.css
│   │   │   ├── components/
│   │   │   │   ├── Footer/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Header/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   ├── Layout/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── styles.module.css
│   │   │   │   └── Section/
│   │   │   │       ├── index.tsx
│   │   │   │       └── styles.module.css
│   │   │   ├── index.tsx
│   │   │   ├── initial-data.ts
│   │   │   ├── options.ts
│   │   │   ├── root.tsx
│   │   │   ├── server.tsx
│   │   │   └── types.ts
│   │   ├── lib/
│   │   │   ├── resolve-puck-path.ts
│   │   │   └── use-demo-data.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   └── docs/
│       ├── .eslintrc.js
│       ├── .gitignore
│       ├── components/
│       │   ├── CtaCard/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── DiscoveryButton/
│       │   │   └── index.tsx
│       │   ├── FooterActions/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── Home/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── Preview/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   ├── ReleaseSwitcher/
│       │   │   ├── index.tsx
│       │   │   └── styles.module.css
│       │   └── Viewport/
│       │       ├── index.tsx
│       │       └── styles.module.css
│       ├── middleware.ts
│       ├── next-env.d.ts
│       ├── next-sitemap.config.js
│       ├── next.config.mjs
│       ├── package.json
│       ├── pages/
│       │   ├── _app.tsx
│       │   ├── _document.tsx
│       │   ├── _meta.js
│       │   ├── api/
│       │   │   └── releases.ts
│       │   ├── docs/
│       │   │   ├── _meta.js
│       │   │   ├── api-reference/
│       │   │   │   ├── _meta.js
│       │   │   │   ├── actions.mdx
│       │   │   │   ├── components/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── action-bar-action.mdx
│       │   │   │   │   ├── action-bar-group.mdx
│       │   │   │   │   ├── action-bar-label.mdx
│       │   │   │   │   ├── action-bar-separator.mdx
│       │   │   │   │   ├── action-bar.mdx
│       │   │   │   │   ├── auto-field.mdx
│       │   │   │   │   ├── drawer-item.mdx
│       │   │   │   │   ├── drawer.mdx
│       │   │   │   │   ├── drop-zone.mdx
│       │   │   │   │   ├── field-label.mdx
│       │   │   │   │   ├── puck-components.mdx
│       │   │   │   │   ├── puck-fields.mdx
│       │   │   │   │   ├── puck-layout.mdx
│       │   │   │   │   ├── puck-outline.mdx
│       │   │   │   │   ├── puck-preview.mdx
│       │   │   │   │   ├── puck.mdx
│       │   │   │   │   ├── render.mdx
│       │   │   │   │   ├── rich-text-menu-control.mdx
│       │   │   │   │   ├── rich-text-menu-group.mdx
│       │   │   │   │   └── rich-text-menu.mdx
│       │   │   │   ├── components.mdx
│       │   │   │   ├── configuration/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── component-config.mdx
│       │   │   │   │   └── config.mdx
│       │   │   │   ├── configuration.mdx
│       │   │   │   ├── data-model/
│       │   │   │   │   ├── app-state.mdx
│       │   │   │   │   ├── component-data.mdx
│       │   │   │   │   ├── data.mdx
│       │   │   │   │   ├── item-selector.mdx
│       │   │   │   │   └── root-data.mdx
│       │   │   │   ├── data-model.mdx
│       │   │   │   ├── field-transforms.mdx
│       │   │   │   ├── fields/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── array.mdx
│       │   │   │   │   ├── base.mdx
│       │   │   │   │   ├── custom.mdx
│       │   │   │   │   ├── external.mdx
│       │   │   │   │   ├── number.mdx
│       │   │   │   │   ├── object.mdx
│       │   │   │   │   ├── radio.mdx
│       │   │   │   │   ├── richtext.mdx
│       │   │   │   │   ├── select.mdx
│       │   │   │   │   ├── slot.mdx
│       │   │   │   │   ├── text.mdx
│       │   │   │   │   └── textarea.mdx
│       │   │   │   ├── fields.mdx
│       │   │   │   ├── functions/
│       │   │   │   │   ├── migrate.mdx
│       │   │   │   │   ├── register-overlay-portal.mdx
│       │   │   │   │   ├── resolve-all-data.mdx
│       │   │   │   │   ├── set-deep.mdx
│       │   │   │   │   ├── transform-props.mdx
│       │   │   │   │   ├── use-get-puck.mdx
│       │   │   │   │   ├── use-puck.mdx
│       │   │   │   │   └── walk-tree.mdx
│       │   │   │   ├── functions.mdx
│       │   │   │   ├── overrides/
│       │   │   │   │   ├── action-bar.mdx
│       │   │   │   │   ├── component-overlay.mdx
│       │   │   │   │   ├── drawer-item.mdx
│       │   │   │   │   ├── drawer.mdx
│       │   │   │   │   ├── field-label.mdx
│       │   │   │   │   ├── field-types.mdx
│       │   │   │   │   ├── fields.mdx
│       │   │   │   │   ├── header-actions.mdx
│       │   │   │   │   ├── header.mdx
│       │   │   │   │   ├── iframe.mdx
│       │   │   │   │   ├── outline.mdx
│       │   │   │   │   ├── preview.mdx
│       │   │   │   │   └── puck.mdx
│       │   │   │   ├── overrides.mdx
│       │   │   │   ├── permissions.mdx
│       │   │   │   ├── plugin.mdx
│       │   │   │   ├── plugins/
│       │   │   │   │   ├── blocks-plugin.mdx
│       │   │   │   │   ├── fields-plugin.mdx
│       │   │   │   │   ├── legacy-side-bar-plugin.mdx
│       │   │   │   │   └── outline-plugin.mdx
│       │   │   │   ├── puck-api.mdx
│       │   │   │   └── theming.mdx
│       │   │   ├── extending-puck/
│       │   │   │   ├── _meta.js
│       │   │   │   ├── composition.mdx
│       │   │   │   ├── custom-fields.mdx
│       │   │   │   ├── field-transforms.mdx
│       │   │   │   ├── internal-puck-api.mdx
│       │   │   │   ├── plugins.mdx
│       │   │   │   ├── theming/
│       │   │   │   │   ├── _meta.js
│       │   │   │   │   ├── fonts.mdx
│       │   │   │   │   └── overview.mdx
│       │   │   │   └── ui-overrides.mdx
│       │   │   ├── getting-started.mdx
│       │   │   ├── guides/
│       │   │   │   ├── _meta.js
│       │   │   │   └── migrations/
│       │   │   │       ├── _meta.js
│       │   │   │       └── dropzones-to-slots.mdx
│       │   │   ├── index.mdx
│       │   │   └── integrating-puck/
│       │   │       ├── _meta.js
│       │   │       ├── categories.mdx
│       │   │       ├── component-configuration.mdx
│       │   │       ├── data-migration.mdx
│       │   │       ├── dynamic-fields.mdx
│       │   │       ├── dynamic-props.mdx
│       │   │       ├── external-data-sources.mdx
│       │   │       ├── feature-toggling.mdx
│       │   │       ├── multi-column-layouts.mdx
│       │   │       ├── overlay-portals.mdx
│       │   │       ├── rich-text-editing.mdx
│       │   │       ├── root-configuration.mdx
│       │   │       ├── server-components.mdx
│       │   │       └── viewports.mdx
│       │   └── index.mdx
│       ├── public/
│       │   ├── manifest.webmanifest
│       │   └── robots.txt
│       ├── releases.json
│       ├── styles.css
│       ├── theme.config.tsx
│       ├── tsconfig/
│       │   ├── base.json
│       │   └── nextjs.json
│       └── tsconfig.json
├── lerna.json
├── package.json
├── packages/
│   ├── core/
│   │   ├── .gitignore
│   │   ├── bundle/
│   │   │   ├── core.css
│   │   │   ├── core.ts
│   │   │   ├── index.css
│   │   │   ├── index.ts
│   │   │   ├── internal.ts
│   │   │   ├── no-external.css
│   │   │   ├── no-external.ts
│   │   │   └── rsc.tsx
│   │   ├── components/
│   │   │   ├── ActionBar/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── AutoField/
│   │   │   │   ├── FieldLabel.tsx
│   │   │   │   ├── context.tsx
│   │   │   │   ├── fields/
│   │   │   │   │   ├── ArrayField/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── DefaultField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ExternalField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── ObjectField/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── RadioField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── RichtextField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── SelectField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── TextareaField/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   ├── use-deep-field.ts
│   │   │   │   │   ├── use-is-focused.ts
│   │   │   │   │   └── use-local-value.ts
│   │   │   │   ├── store.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── subfield.tsx
│   │   │   ├── AutoFrame/
│   │   │   │   └── index.tsx
│   │   │   ├── Breadcrumbs/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Button/
│   │   │   │   ├── Button.module.css
│   │   │   │   ├── Button.tsx
│   │   │   │   └── index.ts
│   │   │   ├── ComponentList/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DefaultOverride/
│   │   │   │   └── index.tsx
│   │   │   ├── DragDropContext/
│   │   │   │   └── index.tsx
│   │   │   ├── DragIcon/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DraggableComponent/
│   │   │   │   ├── index.tsx
│   │   │   │   ├── styles.css
│   │   │   │   └── styles.module.css
│   │   │   ├── Drawer/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── DropZone/
│   │   │   │   ├── context.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   ├── use-content-with-preview.ts
│   │   │   │   │   ├── use-drag-axis.ts
│   │   │   │   │   └── use-min-empty-height.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── types.ts
│   │   │   ├── ExternalInput/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Heading/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── IconButton/
│   │   │   │   ├── IconButton.module.css
│   │   │   │   ├── IconButton.tsx
│   │   │   │   └── index.ts
│   │   │   ├── InlineTextField/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── LayerTree/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Loader/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── MemoizeComponent/
│   │   │   │   └── index.tsx
│   │   │   ├── MenuBar/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Modal/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── OutlineList/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── Puck/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── __snapshots__/
│   │   │   │   │   │   └── index.tsx.snap
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── Canvas/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Components/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Fields/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Header/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Layout/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Nav/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── Outline/
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── Preview/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   ├── ResizeHandle/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── styles.css
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   └── Sidebar/
│   │   │   │   │       ├── index.tsx
│   │   │   │   │       └── styles.module.css
│   │   │   │   └── index.tsx
│   │   │   ├── Render/
│   │   │   │   └── index.tsx
│   │   │   ├── RichTextEditor/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Editor.tsx
│   │   │   │   │   ├── EditorFallback.tsx
│   │   │   │   │   ├── EditorInner.tsx
│   │   │   │   │   ├── Render.tsx
│   │   │   │   │   └── RenderFallback.tsx
│   │   │   │   ├── extension.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── lib/
│   │   │   │   │   ├── mapDeep.ts
│   │   │   │   │   ├── use-richtext-props.tsx
│   │   │   │   │   └── use-synced-editor.ts
│   │   │   │   ├── selector.ts
│   │   │   │   ├── styles.module.css
│   │   │   │   └── types.ts
│   │   │   ├── RichTextMenu/
│   │   │   │   ├── components/
│   │   │   │   │   ├── Control/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── styles.module.css
│   │   │   │   │   └── SelectControl/
│   │   │   │   │       └── index.tsx
│   │   │   │   ├── controls/
│   │   │   │   │   ├── AlignCenter.tsx
│   │   │   │   │   ├── AlignJustify.tsx
│   │   │   │   │   ├── AlignLeft.tsx
│   │   │   │   │   ├── AlignRight.tsx
│   │   │   │   │   ├── AlignSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── Blockquote.tsx
│   │   │   │   │   ├── Bold.tsx
│   │   │   │   │   ├── BulletList.tsx
│   │   │   │   │   ├── CodeBlock.tsx
│   │   │   │   │   ├── HeadingSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── HorizontalRule.tsx
│   │   │   │   │   ├── InlineCode.tsx
│   │   │   │   │   ├── Italic.tsx
│   │   │   │   │   ├── ListSelect/
│   │   │   │   │   │   ├── fallback.tsx
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── loaded.tsx
│   │   │   │   │   │   └── use-options.ts
│   │   │   │   │   ├── OrderedList.tsx
│   │   │   │   │   ├── Strikethrough.tsx
│   │   │   │   │   ├── Underline.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── full.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── inner.tsx
│   │   │   │   ├── lib/
│   │   │   │   │   └── use-control-context.ts
│   │   │   │   └── styles.module.css
│   │   │   ├── Select/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── ServerRender/
│   │   │   │   └── index.tsx
│   │   │   ├── SidebarSection/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── SlotRender/
│   │   │   │   ├── index.tsx
│   │   │   │   └── server.tsx
│   │   │   ├── Sortable/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.css
│   │   │   └── ViewportControls/
│   │   │       ├── default-viewports.ts
│   │   │       ├── index.tsx
│   │   │       └── styles.module.css
│   │   ├── globals.d.ts
│   │   ├── index.ts
│   │   ├── jest.config.ts
│   │   ├── lib/
│   │   │   ├── __tests__/
│   │   │   │   ├── insert-component.spec.tsx
│   │   │   │   ├── load-overrides.spec.tsx
│   │   │   │   ├── migrate.spec.tsx
│   │   │   │   ├── move-component.spec.tsx
│   │   │   │   ├── resolve-all-data.spec.tsx
│   │   │   │   ├── resolve-component-data.spec.tsx
│   │   │   │   ├── transform-props.spec.tsx
│   │   │   │   └── use-breadcrumbs.spec.tsx
│   │   │   ├── accumulate-transform.ts
│   │   │   ├── assign-refs.ts
│   │   │   ├── bubble-pointer-event.ts
│   │   │   ├── data/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── flatten-data.spec.tsx
│   │   │   │   │   ├── resolve-and-replace-data.spec.tsx
│   │   │   │   │   ├── resolve-data-by-id.spec.tsx
│   │   │   │   │   ├── resolve-data-by-selector.spec.tsx
│   │   │   │   │   ├── walk-app-state.spec.tsx
│   │   │   │   │   └── walk-tree.spec.tsx
│   │   │   │   ├── default-data.ts
│   │   │   │   ├── default-slots.ts
│   │   │   │   ├── find-zones-for-area.ts
│   │   │   │   ├── flatten-data.ts
│   │   │   │   ├── flatten-node.ts
│   │   │   │   ├── for-related-zones.ts
│   │   │   │   ├── get-deep.ts
│   │   │   │   ├── get-ids-for-parent.ts
│   │   │   │   ├── get-item.ts
│   │   │   │   ├── insert.ts
│   │   │   │   ├── make-state-public.ts
│   │   │   │   ├── map-fields.ts
│   │   │   │   ├── populate-ids.ts
│   │   │   │   ├── remove.ts
│   │   │   │   ├── reorder.ts
│   │   │   │   ├── replace.ts
│   │   │   │   ├── resolve-and-replace-data.ts
│   │   │   │   ├── resolve-data-by-id.ts
│   │   │   │   ├── resolve-data-by-selector.ts
│   │   │   │   ├── set-deep.ts
│   │   │   │   ├── setup-zone.ts
│   │   │   │   ├── strip-slots.ts
│   │   │   │   ├── to-component.ts
│   │   │   │   ├── to-root.ts
│   │   │   │   ├── walk-app-state.ts
│   │   │   │   └── walk-tree.ts
│   │   │   ├── dnd/
│   │   │   │   ├── NestedDroppablePlugin.ts
│   │   │   │   ├── collision/
│   │   │   │   │   ├── collision-debug.ts
│   │   │   │   │   ├── directional/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── dynamic/
│   │   │   │   │       ├── get-direction.ts
│   │   │   │   │       ├── get-midpoint-impact.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── store.ts
│   │   │   │   │       └── track-movement-interval.ts
│   │   │   │   ├── use-on-drag-finished.ts
│   │   │   │   ├── use-rendered-callback.ts
│   │   │   │   └── use-sensors.ts
│   │   │   ├── field-transforms/
│   │   │   │   ├── build-mappers.ts
│   │   │   │   ├── default-transforms/
│   │   │   │   │   ├── inline-text-transform.tsx
│   │   │   │   │   ├── rich-text-transform.tsx
│   │   │   │   │   └── slot-transform.tsx
│   │   │   │   ├── use-field-transforms-tracked.tsx
│   │   │   │   └── use-field-transforms.tsx
│   │   │   ├── filter-data-attrs.ts
│   │   │   ├── filter.ts
│   │   │   ├── frame-context.tsx
│   │   │   ├── generate-id.ts
│   │   │   ├── get-changed.ts
│   │   │   ├── get-class-name-factory.ts
│   │   │   ├── get-deep-dir.ts
│   │   │   ├── get-deep-scroll-position.ts
│   │   │   ├── get-frame.ts
│   │   │   ├── get-selector-for-id.ts
│   │   │   ├── get-zone-id.ts
│   │   │   ├── get-zoom-config.ts
│   │   │   ├── global-position.ts
│   │   │   ├── group-zones-by-component.ts
│   │   │   ├── index.ts
│   │   │   ├── insert-component.ts
│   │   │   ├── is-ios.ts
│   │   │   ├── load-overrides.ts
│   │   │   ├── migrate.ts
│   │   │   ├── move-component.ts
│   │   │   ├── on-scroll-end.ts
│   │   │   ├── overlay-portal/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.css
│   │   │   ├── plugin-debug.tsx
│   │   │   ├── resolve-all-data.ts
│   │   │   ├── resolve-component-data.ts
│   │   │   ├── root-droppable-id.ts
│   │   │   ├── scroll-into-view.ts
│   │   │   ├── shallow-equal.ts
│   │   │   ├── throttle.ts
│   │   │   ├── transform-props.ts
│   │   │   ├── use-breadcrumbs.ts
│   │   │   ├── use-component-list.tsx
│   │   │   ├── use-context-store.tsx
│   │   │   ├── use-delete-hotkeys.ts
│   │   │   ├── use-frame.ts
│   │   │   ├── use-hotkey.ts
│   │   │   ├── use-inject-css.ts
│   │   │   ├── use-loaded-overrides.ts
│   │   │   ├── use-on-value-change.ts
│   │   │   ├── use-parent.ts
│   │   │   ├── use-preview-mode-hotkeys.ts
│   │   │   ├── use-puck.ts
│   │   │   ├── use-reset-auto-zoom.ts
│   │   │   ├── use-safe-id.ts
│   │   │   ├── use-sidebar-resize.ts
│   │   │   ├── use-slots.tsx
│   │   │   └── use-why-render.ts
│   │   ├── package.json
│   │   ├── plugins/
│   │   │   ├── blocks/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── fields/
│   │   │   │   ├── index.tsx
│   │   │   │   └── styles.module.css
│   │   │   ├── legacy-side-bar/
│   │   │   │   └── index.tsx
│   │   │   └── outline/
│   │   │       ├── index.tsx
│   │   │       └── styles.module.css
│   │   ├── reducer/
│   │   │   ├── actions/
│   │   │   │   ├── __helpers__/
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── duplicate.spec.ts
│   │   │   │   │   ├── insert.spec.ts
│   │   │   │   │   ├── move.spec.ts
│   │   │   │   │   ├── register-zone.spec.ts
│   │   │   │   │   ├── remove.spec.ts
│   │   │   │   │   ├── reorder.spec.ts
│   │   │   │   │   ├── replace.spec.ts
│   │   │   │   │   ├── set-ui.spec.ts
│   │   │   │   │   └── set.spec.ts
│   │   │   │   ├── duplicate.ts
│   │   │   │   ├── insert.ts
│   │   │   │   ├── move.ts
│   │   │   │   ├── register-zone.ts
│   │   │   │   ├── remove.ts
│   │   │   │   ├── reorder.ts
│   │   │   │   ├── replace-root.ts
│   │   │   │   ├── replace.ts
│   │   │   │   ├── set-data.ts
│   │   │   │   ├── set-ui.ts
│   │   │   │   └── set.ts
│   │   │   ├── actions.tsx
│   │   │   └── index.ts
│   │   ├── store/
│   │   │   ├── default-app-state.ts
│   │   │   ├── index.ts
│   │   │   └── slices/
│   │   │       ├── __tests__/
│   │   │       │   ├── fields.spec.tsx
│   │   │       │   ├── history.spec.tsx
│   │   │       │   ├── nodes.spec.tsx
│   │   │       │   └── permissions.spec.tsx
│   │   │       ├── fields.ts
│   │   │       ├── history.ts
│   │   │       ├── nodes.ts
│   │   │       └── permissions.ts
│   │   ├── styles/
│   │   │   ├── color.css
│   │   │   └── typography.css
│   │   ├── styles.css
│   │   ├── tsconfig.json
│   │   ├── tsup.config.ts
│   │   └── types/
│   │       ├── API/
│   │       │   ├── DropZone.ts
│   │       │   ├── FieldTransforms.ts
│   │       │   ├── Overrides.ts
│   │       │   ├── Viewports.ts
│   │       │   └── index.ts
│   │       ├── AppState.tsx
│   │       ├── Config.tsx
│   │       ├── Data.tsx
│   │       ├── Fields.ts
│   │       ├── Internal.tsx
│   │       ├── Props.tsx
│   │       ├── Utils.tsx
│   │       ├── __tests__/
│   │       │   └── internal.spec.ts
│   │       └── index.ts
│   ├── create-puck-app/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── generate.js
│   │   └── templates/
│   │       ├── next/
│   │       │   └── package.json.hbs
│   │       ├── next-ai/
│   │       │   └── package.json.hbs
│   │       ├── react-router/
│   │       │   ├── package.json.hbs
│   │       │   └── tsconfig.json.hbs
│   │       ├── react-router-ai/
│   │       │   ├── package.json.hbs
│   │       │   └── tsconfig.json.hbs
│   │       ├── remix/
│   │       │   └── package.json.hbs
│   │       └── remix-ai/
│   │           └── package.json.hbs
│   ├── eslint-config-custom/
│   │   ├── index.js
│   │   └── package.json
│   ├── field-contentful/
│   │   ├── README.md
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── plugin-emotion-cache/
│   │   ├── README.md
│   │   ├── index.tsx
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── plugin-heading-analyzer/
│   │   ├── README.md
│   │   ├── globals.d.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── HeadingAnalyzer.module.css
│   │   │   └── HeadingAnalyzer.tsx
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── tsconfig/
│   │   ├── base.json
│   │   ├── nextjs.json
│   │   ├── package.json
│   │   └── react-library.json
│   └── tsup-config/
│       ├── index.ts
│       ├── package.json
│       └── react-import.js
├── recipes/
│   ├── next/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── puck/
│   │   │   │   ├── [...puckPath]/
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   └── page.tsx
│   │   │   │   ├── api/
│   │   │   │   │   └── route.ts
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── database.json
│   │   ├── lib/
│   │   │   └── get-page.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── proxy.ts
│   │   ├── puck.config.tsx
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   ├── next-ai/
│   │   ├── .eslintrc.js
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── [...puckPath]/
│   │   │   │   ├── client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── api/
│   │   │   │   ├── pages/
│   │   │   │   │   └── route.ts
│   │   │   │   └── puck/
│   │   │   │       └── [...all]/
│   │   │   │           └── route.ts
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx
│   │   │   ├── puck/
│   │   │   │   ├── [...puckPath]/
│   │   │   │   │   ├── client.tsx
│   │   │   │   │   └── page.tsx
│   │   │   │   └── page.tsx
│   │   │   └── styles.css
│   │   ├── database.json
│   │   ├── lib/
│   │   │   └── get-page.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── package.json
│   │   ├── proxy.ts
│   │   ├── puck.config.tsx
│   │   ├── tsconfig/
│   │   │   ├── base.json
│   │   │   └── nextjs.json
│   │   └── tsconfig.json
│   ├── react-router/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── components/
│   │   │   │   └── puck-render.tsx
│   │   │   ├── lib/
│   │   │   │   ├── pages.server.ts
│   │   │   │   └── resolve-puck-path.server.ts
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── _index.tsx
│   │   │   │   └── puck-splat.tsx
│   │   │   └── routes.ts
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── puck.config.tsx
│   │   ├── react-router.config.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── react-router-ai/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── components/
│   │   │   │   └── puck-render.tsx
│   │   │   ├── lib/
│   │   │   │   ├── pages.server.ts
│   │   │   │   └── resolve-puck-path.server.ts
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── _index.tsx
│   │   │   │   ├── api.puck.ts
│   │   │   │   └── puck-splat.tsx
│   │   │   └── routes.ts
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── puck.config.tsx
│   │   ├── react-router.config.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── remix/
│   │   ├── .eslintrc.cjs
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app/
│   │   │   ├── entry.client.tsx
│   │   │   ├── entry.server.tsx
│   │   │   ├── models/
│   │   │   │   └── page.server.ts
│   │   │   ├── puck.config.tsx
│   │   │   ├── root.tsx
│   │   │   ├── routes/
│   │   │   │   ├── $puckPath.tsx
│   │   │   │   ├── $puckPath_.edit.tsx
│   │   │   │   ├── _index.tsx
│   │   │   │   └── edit.tsx
│   │   │   └── styles/
│   │   │       └── shared.css
│   │   ├── database.json
│   │   ├── package.json
│   │   ├── remix.config.js
│   │   ├── remix.env.d.ts
│   │   └── tsconfig.json
│   └── remix-ai/
│       ├── .eslintrc.cjs
│       ├── .gitignore
│       ├── README.md
│       ├── app/
│       │   ├── entry.client.tsx
│       │   ├── entry.server.tsx
│       │   ├── models/
│       │   │   └── page.server.ts
│       │   ├── puck.config.tsx
│       │   ├── root.tsx
│       │   ├── routes/
│       │   │   ├── $puckPath.tsx
│       │   │   ├── $puckPath_.edit.tsx
│       │   │   ├── _index.tsx
│       │   │   ├── api.puck.$.tsx
│       │   │   └── edit.tsx
│       │   └── styles/
│       │       └── shared.css
│       ├── database.json
│       ├── package.json
│       ├── remix.config.js
│       ├── remix.env.d.ts
│       └── tsconfig.json
├── scripts/
│   ├── create-changelog.js
│   ├── e2e/
│   │   ├── smoke-framework.mjs
│   │   ├── smoke.mjs
│   │   └── utils/
│   │       ├── drag-and-drop.mjs
│   │       ├── get-box.mjs
│   │       ├── pause.mjs
│   │       └── setup.mjs
│   ├── get-unstable-version.js
│   └── publish.sh
└── turbo.json
Download .txt
SYMBOL INDEX (492 symbols across 214 files)

FILE: apps/demo/app/[...puckPath]/client.tsx
  function Client (line 10) | function Client({ path, isEdit }: { path: string; isEdit: boolean }) {

FILE: apps/demo/app/[...puckPath]/page.tsx
  function generateMetadata (line 4) | async function generateMetadata({
  function Page (line 23) | async function Page({

FILE: apps/demo/app/custom-ui/[...puckPath]/client.tsx
  function Client (line 350) | function Client({ path, isEdit }: { path: string; isEdit: boolean }) {

FILE: apps/demo/app/custom-ui/[...puckPath]/page.tsx
  function generateMetadata (line 5) | async function generateMetadata({
  function Page (line 24) | async function Page({

FILE: apps/demo/app/layout.tsx
  function RootLayout (line 4) | function RootLayout({

FILE: apps/demo/app/rsc/page.tsx
  function generateMetadata (line 13) | async function generateMetadata(): Promise<Metadata> {
  function Page (line 19) | async function Page() {

FILE: apps/demo/config/blocks/Blank/index.tsx
  type BlankProps (line 8) | type BlankProps = {};

FILE: apps/demo/config/blocks/Button/index.tsx
  type ButtonProps (line 5) | type ButtonProps = {

FILE: apps/demo/config/blocks/Card/index.tsx
  type CardProps (line 28) | type CardProps = WithLayout<{

FILE: apps/demo/config/blocks/Flex/index.tsx
  type FlexProps (line 10) | type FlexProps = WithLayout<{

FILE: apps/demo/config/blocks/Grid/index.tsx
  type GridProps (line 10) | type GridProps = {

FILE: apps/demo/config/blocks/Heading/index.tsx
  type HeadingProps (line 9) | type HeadingProps = WithLayout<{

FILE: apps/demo/config/blocks/Hero/Hero.tsx
  type HeroProps (line 11) | type HeroProps = {

FILE: apps/demo/config/blocks/Logos/index.tsx
  type LogosProps (line 10) | type LogosProps = {

FILE: apps/demo/config/blocks/RichText/index.tsx
  type RichTextProps (line 6) | type RichTextProps = WithLayout<{

FILE: apps/demo/config/blocks/Space/index.tsx
  type SpaceProps (line 11) | type SpaceProps = {

FILE: apps/demo/config/blocks/Stats/index.tsx
  type StatsProps (line 10) | type StatsProps = {

FILE: apps/demo/config/blocks/Template/Template.tsx
  type TemplateProps (line 10) | type TemplateProps = {

FILE: apps/demo/config/blocks/Template/client.tsx
  function createComponent (line 13) | async function createComponent<T extends keyof Components>(
  type TemplateData (line 28) | type TemplateData = Record<string, { label: string; data: Slot }>;

FILE: apps/demo/config/blocks/Text/index.tsx
  type TextProps (line 8) | type TextProps = WithLayout<{

FILE: apps/demo/config/components/Layout/index.tsx
  type LayoutFieldProps (line 13) | type LayoutFieldProps = {
  type WithLayout (line 20) | type WithLayout<Props extends DefaultComponentProps> = Props & {
  type LayoutProps (line 24) | type LayoutProps = WithLayout<{
  function withLayout (line 90) | function withLayout<

FILE: apps/demo/config/components/Section/index.tsx
  type SectionProps (line 7) | type SectionProps = {

FILE: apps/demo/config/root.tsx
  type RootProps (line 5) | type RootProps = DefaultRootProps;

FILE: apps/demo/config/types.ts
  type Components (line 19) | type Components = {
  type UserConfig (line 34) | type UserConfig = Config<{
  type UserData (line 46) | type UserData = Data<Components, RootProps>;

FILE: apps/docs/components/DiscoveryButton/index.tsx
  function DiscoveryButton (line 3) | function DiscoveryButton() {

FILE: apps/docs/components/ReleaseSwitcher/index.tsx
  constant BASE_URL (line 8) | const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "https://puckeditor...

FILE: apps/docs/middleware.ts
  function middleware (line 8) | function middleware(request: NextRequest) {

FILE: apps/docs/next.config.mjs
  constant BRANCH_NAME (line 9) | const BRANCH_NAME = process.env.VERCEL_GIT_COMMIT_REF || "";
  constant IS_RELEASE_BRANCH (line 10) | const IS_RELEASE_BRANCH = BRANCH_NAME.startsWith("releases/");
  method redirects (line 13) | async redirects() {

FILE: apps/docs/pages/_app.tsx
  function DocsApp (line 4) | function DocsApp({ Component, pageProps }: AppProps) {

FILE: apps/docs/pages/_document.tsx
  function Document (line 3) | function Document() {

FILE: apps/docs/pages/api/releases.ts
  function handler (line 8) | async function handler(

FILE: packages/core/components/AutoField/FieldLabel.tsx
  type FieldLabelPropsInternal (line 44) | type FieldLabelPropsInternal = {
  type FieldPropsInternalOptional (line 83) | type FieldPropsInternalOptional<ValueType = any, F = Field<any>> = Omit<
  type FieldPropsInternal (line 93) | type FieldPropsInternal<ValueType = any, F = Field<any>> = FieldProps<

FILE: packages/core/components/AutoField/context.tsx
  type NestedFieldContext (line 3) | type NestedFieldContext = {

FILE: packages/core/components/AutoField/index.tsx
  type FieldPropsInternal (line 38) | type FieldPropsInternal<ValueType = any, F = Field<any>> = FieldProps<
  function AutoFieldInternal (line 63) | function AutoFieldInternal<
  type FieldNoLabel (line 214) | type FieldNoLabel<Props extends any = any> = Omit<Field<Props>, "label">;
  function AutoFieldPrivate (line 216) | function AutoFieldPrivate<
  function AutoFieldPublicInternal (line 228) | function AutoFieldPublicInternal<
  function AutoField (line 271) | function AutoField<

FILE: packages/core/components/AutoField/store.ts
  type FieldStore (line 6) | type FieldStore = Record<string, any>;
  function useFieldStore (line 12) | function useFieldStore<U>(

FILE: packages/core/components/AutoFrame/index.tsx
  type AutoFrameProps (line 321) | type AutoFrameProps = {
  type AutoFrameContext (line 331) | type AutoFrameContext = {
  function AutoFrame (line 340) | function AutoFrame({

FILE: packages/core/components/DragDropContext/index.tsx
  constant DEBUG (line 41) | const DEBUG = false;
  type Events (line 43) | type Events = DragDropEvents<Draggable, Droppable, DragDropManager>;
  type DragCbs (line 44) | type DragCbs = Partial<{ [eventName in keyof Events]: Events[eventName][...
  type EventKeys (line 53) | type EventKeys = keyof Events;
  function useDragListener (line 55) | function useDragListener(
  type DeepestParams (line 72) | type DeepestParams = {
  constant AREA_CHANGE_DEBOUNCE_MS (line 77) | const AREA_CHANGE_DEBOUNCE_MS = 100;
  type DragDropContextProps (line 79) | type DragDropContextProps = {

FILE: packages/core/components/DraggableComponent/index.tsx
  constant DEBUG (line 40) | const DEBUG = false;
  type ComponentDndData (line 76) | type ComponentDndData = {

FILE: packages/core/components/DropZone/context.tsx
  type PathData (line 14) | type PathData = Record<string, { path: string[]; label: string }>;
  type DropZoneContext (line 16) | type DropZoneContext = {
  type Preview (line 30) | type Preview = {
  type ZoneStore (line 39) | type ZoneStore = {

FILE: packages/core/components/DropZone/index.tsx
  constant RENDER_DEBUG (line 64) | const RENDER_DEBUG = false;
  type DropZoneDndData (line 66) | type DropZoneDndData = {

FILE: packages/core/components/DropZone/lib/use-drag-axis.ts
  constant GRID_DRAG_AXIS (line 5) | const GRID_DRAG_AXIS: DragAxis = "dynamic";
  constant FLEX_ROW_DRAG_AXIS (line 6) | const FLEX_ROW_DRAG_AXIS: DragAxis = "x";
  constant DEFAULT_DRAG_AXIS (line 7) | const DEFAULT_DRAG_AXIS: DragAxis = "y";

FILE: packages/core/components/DropZone/types.ts
  type DropZoneProps (line 4) | type DropZoneProps = {

FILE: packages/core/components/Heading/index.tsx
  type HeadingProps (line 7) | type HeadingProps = {

FILE: packages/core/components/MenuBar/index.tsx
  function MenuBar (line 14) | function MenuBar<UserData extends Data>({

FILE: packages/core/components/Puck/__tests__/index.tsx
  class ResizeObserver (line 46) | class ResizeObserver {
    method observe (line 47) | observe() {}
    method unobserve (line 48) | unobserve() {}
    method disconnect (line 49) | disconnect() {}
  type PuckInternal (line 53) | type PuckInternal = {

FILE: packages/core/components/Puck/components/Canvas/index.tsx
  constant ZOOM_ON_CHANGE (line 24) | const ZOOM_ON_CHANGE = true;
  constant TRANSITION_DURATION (line 25) | const TRANSITION_DURATION = 150;

FILE: packages/core/components/Puck/components/Nav/index.tsx
  type MenuItem (line 8) | type MenuItem = {

FILE: packages/core/components/Puck/components/Preview/index.tsx
  type PageProps (line 16) | type PageProps = DefaultRootRenderProps;

FILE: packages/core/components/Puck/components/ResizeHandle/index.tsx
  type ResizeHandleProps (line 10) | interface ResizeHandleProps {

FILE: packages/core/components/Puck/components/Sidebar/index.tsx
  type SidebarProps (line 8) | interface SidebarProps {

FILE: packages/core/components/Puck/index.tsx
  type PuckProps (line 57) | type PuckProps<
  function PropsProvider (line 96) | function PropsProvider<UserConfig extends Config = Config>(
  function PuckProvider (line 109) | function PuckProvider<
  function Puck (line 344) | function Puck<

FILE: packages/core/components/Render/index.tsx
  function Render (line 26) | function Render<

FILE: packages/core/components/RichTextEditor/components/Render.tsx
  function RichTextRender (line 11) | function RichTextRender({

FILE: packages/core/components/RichTextEditor/components/RenderFallback.tsx
  function RichTextRenderFallback (line 8) | function RichTextRenderFallback({ content }: { content: string }) {

FILE: packages/core/components/RichTextEditor/extension.ts
  type PuckRichTextOptions (line 42) | interface PuckRichTextOptions {
  method addExtensions (line 166) | addExtensions() {

FILE: packages/core/components/RichTextEditor/lib/use-richtext-props.tsx
  type RichtextPath (line 12) | type RichtextPath = {
  function useRichtextProps (line 17) | function useRichtextProps(

FILE: packages/core/components/RichTextEditor/lib/use-synced-editor.ts
  function useSyncedEditor (line 8) | function useSyncedEditor({

FILE: packages/core/components/RichTextEditor/types.ts
  type RichTextSelector (line 6) | type RichTextSelector = (
  type DefaultEditorState (line 11) | type DefaultEditorState = ReturnType<typeof defaultEditorState>;
  type EditorState (line 13) | type EditorState<Selector extends RichTextSelector = RichTextSelector> =
  type EditorProps (line 18) | type EditorProps = {
  type RichTextEditor (line 29) | type RichTextEditor = NonNullable<ReturnType<typeof useSyncedEditor>>;

FILE: packages/core/components/RichTextMenu/components/Control/index.tsx
  function Control (line 10) | function Control({

FILE: packages/core/components/RichTextMenu/components/SelectControl/index.tsx
  type Option (line 5) | type Option<T = string> = { label: string; value: T; icon?: React.FC };
  type Options (line 6) | type Options<T = string> = Option<T>[];
  function SelectControl (line 8) | function SelectControl<ValueType extends string = string>({

FILE: packages/core/components/RichTextMenu/controls/AlignCenter.tsx
  function AlignCenter (line 5) | function AlignCenter() {

FILE: packages/core/components/RichTextMenu/controls/AlignJustify.tsx
  function AlignJustify (line 5) | function AlignJustify() {

FILE: packages/core/components/RichTextMenu/controls/AlignLeft.tsx
  function AlignLeft (line 5) | function AlignLeft() {

FILE: packages/core/components/RichTextMenu/controls/AlignRight.tsx
  function AlignRight (line 5) | function AlignRight() {

FILE: packages/core/components/RichTextMenu/controls/AlignSelect/fallback.tsx
  function AlignSelectFallback (line 6) | function AlignSelectFallback() {

FILE: packages/core/components/RichTextMenu/controls/AlignSelect/loaded.tsx
  type AlignDirection (line 7) | type AlignDirection = "left" | "center" | "right" | "justify";
  function AlignSelectLoaded (line 9) | function AlignSelectLoaded() {

FILE: packages/core/components/RichTextMenu/controls/AlignSelect/use-options.ts
  type AlignDirection (line 12) | type AlignDirection = "left" | "center" | "right" | "justify";

FILE: packages/core/components/RichTextMenu/controls/Blockquote.tsx
  function Blockquote (line 5) | function Blockquote() {

FILE: packages/core/components/RichTextMenu/controls/Bold.tsx
  function Bold (line 5) | function Bold() {

FILE: packages/core/components/RichTextMenu/controls/BulletList.tsx
  function BulletList (line 5) | function BulletList() {

FILE: packages/core/components/RichTextMenu/controls/CodeBlock.tsx
  function CodeBlock (line 5) | function CodeBlock() {

FILE: packages/core/components/RichTextMenu/controls/HeadingSelect/fallback.tsx
  function HeadingSelectFallback (line 6) | function HeadingSelectFallback() {

FILE: packages/core/components/RichTextMenu/controls/HeadingSelect/loaded.tsx
  function HeadingSelectLoaded (line 7) | function HeadingSelectLoaded() {

FILE: packages/core/components/RichTextMenu/controls/HeadingSelect/use-options.ts
  type HeadingElement (line 21) | type HeadingElement = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";

FILE: packages/core/components/RichTextMenu/controls/HorizontalRule.tsx
  function HorizontalRule (line 5) | function HorizontalRule() {

FILE: packages/core/components/RichTextMenu/controls/InlineCode.tsx
  function InlineCode (line 5) | function InlineCode() {

FILE: packages/core/components/RichTextMenu/controls/Italic.tsx
  function Italic (line 5) | function Italic() {

FILE: packages/core/components/RichTextMenu/controls/ListSelect/fallback.tsx
  function ListSelectFallback (line 6) | function ListSelectFallback() {

FILE: packages/core/components/RichTextMenu/controls/ListSelect/loaded.tsx
  function ListSelectLoaded (line 7) | function ListSelectLoaded() {

FILE: packages/core/components/RichTextMenu/controls/ListSelect/use-options.ts
  type ListElement (line 10) | type ListElement = "ol" | "ul";

FILE: packages/core/components/RichTextMenu/controls/OrderedList.tsx
  function OrderedList (line 5) | function OrderedList() {

FILE: packages/core/components/RichTextMenu/controls/Strikethrough.tsx
  function Strikethrough (line 5) | function Strikethrough() {

FILE: packages/core/components/RichTextMenu/controls/Underline.tsx
  function Underline (line 5) | function Underline() {

FILE: packages/core/components/RichTextMenu/index.tsx
  type LoadedRichTextMenuProps (line 12) | type LoadedRichTextMenuProps = {

FILE: packages/core/components/RichTextMenu/lib/use-control-context.ts
  type ControlContextType (line 6) | type ControlContextType = {

FILE: packages/core/components/ServerRender/index.tsx
  type DropZoneRenderProps (line 13) | type DropZoneRenderProps = {
  function DropZoneRender (line 22) | function DropZoneRender({
  function Render (line 83) | function Render<

FILE: packages/core/components/SlotRender/server.tsx
  type SlotRenderProps (line 13) | type SlotRenderProps = DropZoneProps & {

FILE: packages/core/lib/__tests__/insert-component.spec.tsx
  type ComponentOrRootData (line 48) | type ComponentOrRootData = ComponentData | RootDataWithProps;

FILE: packages/core/lib/__tests__/move-component.spec.tsx
  function resetStores (line 55) | function resetStores() {

FILE: packages/core/lib/__tests__/resolve-component-data.spec.tsx
  type ComponentProps (line 10) | interface ComponentProps {

FILE: packages/core/lib/__tests__/use-breadcrumbs.spec.tsx
  function resetStores (line 18) | function resetStores() {

FILE: packages/core/lib/accumulate-transform.ts
  function accumulateTransform (line 1) | function accumulateTransform(el: HTMLElement) {

FILE: packages/core/lib/assign-refs.ts
  type Ref (line 1) | type Ref<ElementType = HTMLElement> =
  function assignRef (line 6) | function assignRef<ElementType = HTMLElement>(
  function assignRefs (line 17) | function assignRefs<ElementType = HTMLElement>(

FILE: packages/core/lib/bubble-pointer-event.ts
  type BubbledPointerEventType (line 1) | interface BubbledPointerEventType extends PointerEvent {
  class BubbledPointerEvent (line 8) | class BubbledPointerEvent extends BaseEvent {
    method constructor (line 11) | constructor(
    method originalTarget (line 20) | set originalTarget(target: EventTarget | null) {
    method originalTarget (line 25) | get originalTarget() {

FILE: packages/core/lib/data/__tests__/flatten-data.spec.tsx
  type Props (line 9) | type Props = {
  type RootProps (line 18) | type RootProps = {
  type UserConfig (line 23) | type UserConfig = Config<Props, RootProps>;
  type UserData (line 24) | type UserData = Data<Props, RootProps>;

FILE: packages/core/lib/data/__tests__/resolve-and-replace-data.spec.tsx
  function resetStores (line 40) | function resetStores() {

FILE: packages/core/lib/data/__tests__/resolve-data-by-id.spec.tsx
  function resetStores (line 33) | function resetStores() {

FILE: packages/core/lib/data/__tests__/resolve-data-by-selector.spec.tsx
  function resetStores (line 36) | function resetStores() {

FILE: packages/core/lib/data/__tests__/walk-app-state.spec.tsx
  type Props (line 12) | type Props = {
  type RootProps (line 22) | type RootProps = {
  type UserConfig (line 27) | type UserConfig = Config<Props, RootProps>;
  type UserData (line 28) | type UserData = Data<Props, RootProps>;

FILE: packages/core/lib/data/__tests__/walk-tree.spec.tsx
  type Props (line 7) | type Props = {
  type RootProps (line 15) | type RootProps = {
  type UserConfig (line 20) | type UserConfig = Config<Props, RootProps>;
  type UserData (line 21) | type UserData = Data<Props, RootProps>;

FILE: packages/core/lib/data/flatten-node.ts
  function encodeEmptyObjects (line 14) | function encodeEmptyObjects(props: Record<string, any> = {}) {
  function decodeEmptyObjects (line 34) | function decodeEmptyObjects(props: Record<string, any> = {}) {

FILE: packages/core/lib/data/for-related-zones.ts
  function forRelatedZones (line 4) | function forRelatedZones<UserData extends Data>(

FILE: packages/core/lib/data/get-item.ts
  type ItemSelector (line 5) | type ItemSelector = {
  function getItem (line 10) | function getItem<UserData extends Data>(

FILE: packages/core/lib/data/map-fields.ts
  type MapFnParams (line 11) | type MapFnParams<ThisField = Field> = {
  type MapFn (line 19) | type MapFn<T = any> = (params: MapFnParams) => T;
  type Mappers (line 21) | type Mappers<T = EitherMapFn> = Partial<Record<Field["type"], T>>;
  type PromiseMapFn (line 23) | type PromiseMapFn = MapFn<Promise<any>>;
  type EitherMapFn (line 25) | type EitherMapFn = MapFn<any | Promise<any>>;
  type WalkFieldOpts (line 27) | type WalkFieldOpts = {
  type WalkObjectOpts (line 38) | type WalkObjectOpts = {
  function mapFields (line 219) | function mapFields(

FILE: packages/core/lib/data/resolve-and-replace-data.ts
  function resolveAndReplaceData (line 6) | async function resolveAndReplaceData(

FILE: packages/core/lib/data/resolve-data-by-id.ts
  function resolveDataById (line 6) | async function resolveDataById(

FILE: packages/core/lib/data/resolve-data-by-selector.ts
  function resolveDataBySelector (line 7) | async function resolveDataBySelector(

FILE: packages/core/lib/data/set-deep.ts
  function setDeep (line 4) | function setDeep<T extends Record<string, any>>(

FILE: packages/core/lib/data/setup-zone.ts
  type WithZones (line 5) | type WithZones<T extends Data> = T & { zones: NonNullable<T["zones"]> };

FILE: packages/core/lib/data/walk-app-state.ts
  function walkAppState (line 29) | function walkAppState<UserData extends Data = Data>(

FILE: packages/core/lib/data/walk-tree.ts
  type WalkTreeOptions (line 10) | type WalkTreeOptions = {
  function walkTree (line 15) | function walkTree<

FILE: packages/core/lib/dnd/NestedDroppablePlugin.ts
  type NestedDroppablePluginOptions (line 18) | type NestedDroppablePluginOptions = {
  constant BUFFER (line 66) | const BUFFER = 6;
  method constructor (line 242) | constructor(manager: DragDropManager, options?: {}) {

FILE: packages/core/lib/dnd/collision/collision-debug.ts
  constant DEBUG (line 3) | const DEBUG = false;

FILE: packages/core/lib/dnd/collision/dynamic/track-movement-interval.ts
  type Interval (line 5) | type Interval = {
  constant INTERVAL_SENSITIVITY (line 12) | const INTERVAL_SENSITIVITY = 10;

FILE: packages/core/lib/dnd/use-rendered-callback.ts
  function useRenderedCallback (line 16) | function useRenderedCallback<T extends Function>(

FILE: packages/core/lib/dnd/use-sensors.ts
  type DelayConstraint (line 6) | interface DelayConstraint {
  type DistanceConstraint (line 11) | interface DistanceConstraint {
  type ActivationConstraints (line 16) | interface ActivationConstraints {
  method activationConstraints (line 43) | activationConstraints(event, source) {

FILE: packages/core/lib/field-transforms/build-mappers.ts
  function buildMappers (line 20) | function buildMappers<

FILE: packages/core/lib/field-transforms/use-field-transforms-tracked.tsx
  function useFieldTransformsTracked (line 9) | function useFieldTransformsTracked<

FILE: packages/core/lib/field-transforms/use-field-transforms.tsx
  function useFieldTransforms (line 7) | function useFieldTransforms<

FILE: packages/core/lib/frame-context.tsx
  type FrameContextType (line 11) | interface FrameContextType {

FILE: packages/core/lib/get-class-name-factory.ts
  type OptionsObj (line 3) | type OptionsObj = Record<string, any>;
  type Options (line 4) | type Options = string | OptionsObj;

FILE: packages/core/lib/get-deep-dir.ts
  type Dir (line 1) | type Dir = "ltr" | "rtl";
  function getDeepDir (line 3) | function getDeepDir(el: Element | null | undefined) {

FILE: packages/core/lib/get-deep-scroll-position.ts
  function getDeepScrollPosition (line 1) | function getDeepScrollPosition(element: HTMLElement) {

FILE: packages/core/lib/get-zoom-config.ts
  constant RESET_ZOOM_SMALLER_THAN_FRAME (line 4) | const RESET_ZOOM_SMALLER_THAN_FRAME = true;

FILE: packages/core/lib/global-position.ts
  type Position (line 1) | interface Position {
  class GlobalPosition (line 6) | class GlobalPosition {
    method constructor (line 13) | constructor(target: Element, original: Position) {
    method x (line 27) | get x() {
    method y (line 31) | get y() {
    method global (line 35) | get global() {
    method frame (line 46) | get frame() {

FILE: packages/core/lib/migrate.ts
  type MigrationOptions (line 13) | type MigrationOptions<UserConfig extends Config> = {
  type Migration (line 22) | type Migration = (
  function migrate (line 180) | function migrate<UserConfig extends Config = Config>(

FILE: packages/core/lib/resolve-all-data.ts
  function resolveAllData (line 17) | async function resolveAllData<

FILE: packages/core/lib/shallow-equal.ts
  function shallowEqual (line 5) | function shallowEqual(

FILE: packages/core/lib/throttle.ts
  function timeout (line 1) | function timeout(callback: () => void, duration: number): () => void {
  function throttle (line 7) | function throttle<T extends (...args: any[]) => any>(

FILE: packages/core/lib/transform-props.ts
  type PropTransform (line 11) | type PropTransform<
  function transformProps (line 22) | function transformProps<

FILE: packages/core/lib/use-breadcrumbs.ts
  type Breadcrumb (line 5) | type Breadcrumb = {

FILE: packages/core/lib/use-context-store.tsx
  type ExtractState (line 6) | type ExtractState<S> = S extends {
  function useContextStore (line 15) | function useContextStore<T, U>(
  function createStoreProvider (line 28) | function createStoreProvider<ValueType>(
  function createContextStore (line 50) | function createContextStore<ValueType>(defaultValue: ValueType) {

FILE: packages/core/lib/use-hotkey.ts
  type KeyStrict (line 40) | type KeyStrict = (typeof keys)[number];
  type KeyMapStrict (line 41) | type KeyMapStrict = Partial<Record<KeyStrict, boolean>>;
  type KeyMap (line 42) | type KeyMap = Partial<Record<string, boolean>>;
  type KeyCodeMap (line 43) | type KeyCodeMap = Record<string, KeyStrict>;

FILE: packages/core/lib/use-on-value-change.ts
  function useOnValueChange (line 3) | function useOnValueChange<T>(

FILE: packages/core/lib/use-puck.ts
  type UsePuckData (line 21) | type UsePuckData<
  type PuckApi (line 54) | type PuckApi<UserConfig extends Config = Config> =
  type UsePuckStore (line 57) | type UsePuckStore<UserConfig extends Config = Config> = PuckApi<UserConf...
  type PickedStore (line 59) | type PickedStore = Pick<
  function createUsePuck (line 162) | function createUsePuck<UserConfig extends Config = Config>() {
  function usePuck (line 181) | function usePuck<UserConfig extends Config = Config>() {
  function useGetPuck (line 196) | function useGetPuck() {

FILE: packages/core/lib/use-reset-auto-zoom.ts
  type ResetAutoZoomOptions (line 6) | type ResetAutoZoomOptions = {

FILE: packages/core/lib/use-sidebar-resize.ts
  function useSidebarResize (line 11) | function useSidebarResize(

FILE: packages/core/lib/use-slots.tsx
  function useSlots (line 7) | function useSlots<

FILE: packages/core/reducer/actions.tsx
  type InsertAction (line 4) | type InsertAction = {
  type DuplicateAction (line 12) | type DuplicateAction = {
  type ReplaceAction (line 18) | type ReplaceAction<UserData extends Data = Data> = {
  type ReplaceRootAction (line 26) | type ReplaceRootAction<UserData extends Data = Data> = {
  type ReorderAction (line 32) | type ReorderAction = {
  type MoveAction (line 39) | type MoveAction = {
  type RemoveAction (line 47) | type RemoveAction = {
  type SetUiAction (line 53) | type SetUiAction = {
  type SetDataAction (line 58) | type SetDataAction = {
  type SetAction (line 63) | type SetAction<UserData extends Data = Data> = {
  type RegisterZoneAction (line 72) | type RegisterZoneAction = {
  type UnregisterZoneAction (line 77) | type UnregisterZoneAction = {
  type PuckAction (line 82) | type PuckAction = { recordHistory?: boolean } & (

FILE: packages/core/reducer/actions/__helpers__/index.tsx
  type Props (line 17) | type Props = {
  type RootProps (line 30) | type RootProps = {
  type UserConfig (line 35) | type UserConfig = Config<Props, RootProps>;
  type UserData (line 36) | type UserData = Data<Props, RootProps>;

FILE: packages/core/reducer/actions/duplicate.ts
  function duplicateAction (line 11) | function duplicateAction<UserData extends Data>(

FILE: packages/core/reducer/actions/insert.ts
  function insertAction (line 11) | function insertAction<UserData extends Data>(

FILE: packages/core/reducer/actions/register-zone.ts
  function registerZoneAction (line 13) | function registerZoneAction<UserData extends Data>(
  function unregisterZoneAction (line 44) | function unregisterZoneAction<UserData extends Data>(

FILE: packages/core/reducer/index.ts
  type ActionType (line 25) | type ActionType = "insert" | "reorder";
  type StateReducer (line 27) | type StateReducer<UserData extends Data = Data> = Reducer<
  function storeInterceptor (line 32) | function storeInterceptor<UserData extends Data = Data>(
  function createReducer (line 65) | function createReducer<UserData extends Data>({

FILE: packages/core/store/index.ts
  type Status (line 43) | type Status = "LOADING" | "MOUNTED" | "READY";
  type ZoomConfig (line 45) | type ZoomConfig = {
  type ComponentState (line 51) | type ComponentState = Record<string, { loadingCount: number }>;
  type AppStore (line 53) | type AppStore<
  type AppStoreApi (line 103) | type AppStoreApi = StoreApi<AppStore>;
  function useAppStore (line 347) | function useAppStore<T>(selector: (state: AppStore) => T) {
  function useAppStoreApi (line 353) | function useAppStoreApi() {

FILE: packages/core/store/slices/__tests__/fields.spec.tsx
  function resetStores (line 25) | function resetStores() {

FILE: packages/core/store/slices/__tests__/history.spec.tsx
  function resetStores (line 7) | function resetStores() {

FILE: packages/core/store/slices/__tests__/nodes.spec.tsx
  function resetStores (line 6) | function resetStores() {

FILE: packages/core/store/slices/__tests__/permissions.spec.tsx
  function resetStores (line 11) | function resetStores() {

FILE: packages/core/store/slices/fields.ts
  type ComponentOrRootData (line 8) | type ComponentOrRootData = Omit<ComponentData<any>, "type">;
  type FieldsSlice (line 10) | type FieldsSlice = {

FILE: packages/core/store/slices/history.ts
  type HistorySlice (line 7) | type HistorySlice<D = any> = {
  constant EMPTY_HISTORY_INDEX (line 23) | const EMPTY_HISTORY_INDEX = 0;
  function debounce (line 25) | function debounce(func: Function, timeout = 300) {
  type PuckHistory (line 36) | type PuckHistory = {
  function useRegisterHistorySlice (line 151) | function useRegisterHistorySlice(

FILE: packages/core/store/slices/nodes.ts
  type NodeMethods (line 3) | type NodeMethods = {
  type PuckNodeInstance (line 9) | type PuckNodeInstance = {
  type NodesSlice (line 15) | type NodesSlice = {

FILE: packages/core/store/slices/permissions.ts
  type PermissionsArgs (line 8) | type PermissionsArgs<
  type GetPermissions (line 17) | type GetPermissions<UserConfig extends Config = Config> = (
  type ResolvePermissions (line 21) | type ResolvePermissions<UserConfig extends Config = Config> = (
  type RefreshPermissions (line 26) | type RefreshPermissions<UserConfig extends Config = Config> = (
  type Cache (line 31) | type Cache = Record<
  type PermissionsSlice (line 40) | type PermissionsSlice = {

FILE: packages/core/types/API/DropZone.ts
  type Direction (line 1) | type Direction = "left" | "right" | "up" | "down" | null;
  type DragAxis (line 3) | type DragAxis = "dynamic" | "y" | "x";

FILE: packages/core/types/API/FieldTransforms.ts
  type FieldTransformFnParams (line 4) | type FieldTransformFnParams<T> = Omit<MapFnParams<T>, "parentId"> & {
  type FieldTransformFn (line 9) | type FieldTransformFn<T> = (params: FieldTransformFnParams<T>) => any;
  type FieldTransforms (line 11) | type FieldTransforms<

FILE: packages/core/types/API/Overrides.ts
  type OverrideKey (line 22) | type OverrideKey = (typeof overrideKeys)[number];
  type OverridesGeneric (line 24) | type OverridesGeneric<Shape extends { [key in OverrideKey]: any }> = Shape;
  type Overrides (line 26) | type Overrides<UserConfig extends Config = Config> = OverridesGeneric<{
  type FieldRenderFunctions (line 65) | type FieldRenderFunctions<

FILE: packages/core/types/API/Viewports.ts
  type iconTypes (line 3) | type iconTypes = "Smartphone" | "Monitor" | "Tablet";
  type Viewport (line 5) | type Viewport = {
  type Viewports (line 12) | type Viewports = Viewport[];

FILE: packages/core/types/API/index.ts
  type Permissions (line 11) | type Permissions = {
  type IframeConfig (line 19) | type IframeConfig = {
  type OnAction (line 24) | type OnAction<UserData extends Data = Data> = (
  type Plugin (line 30) | type Plugin<UserConfig extends Config = Config> = {
  type History (line 40) | type History<D = any> = {
  type InitialHistoryAppend (line 45) | type InitialHistoryAppend<AS = Partial<AppState>> = {
  type InitialHistoryNoAppend (line 51) | type InitialHistoryNoAppend<AS = Partial<AppState>> = {
  type InitialHistory (line 57) | type InitialHistory<AS = Partial<AppState>> =
  type Slot (line 61) | type Slot<
  type WithSlotProps (line 72) | type WithSlotProps<
  type RichText (line 78) | type RichText = string | ReactNode;

FILE: packages/core/types/AppState.tsx
  type ItemWithId (line 5) | type ItemWithId = {
  type ArrayState (line 11) | type ArrayState = { items: ItemWithId[]; openId: string };
  type UiState (line 13) | type UiState = {
  type AppState (line 46) | type AppState<UserData extends Data = Data> = {

FILE: packages/core/types/Config.tsx
  type SlotComponent (line 17) | type SlotComponent = (props?: Omit<DropZoneProps, "zone">) => ReactNode;
  type PuckComponent (line 19) | type PuckComponent<Props> = (
  type ResolveDataTrigger (line 27) | type ResolveDataTrigger =
  type WithPartialProps (line 34) | type WithPartialProps<T, Props extends DefaultComponentProps> = Omit<
  type ComponentConfigExtensions (line 41) | interface ComponentConfigExtensions {}
  type ComponentConfigInternal (line 43) | type ComponentConfigInternal<
  type ComponentConfig (line 94) | type ComponentConfig<
  type RootConfigInternal (line 123) | type RootConfigInternal<
  type RootConfig (line 136) | type RootConfig<
  type Category (line 156) | type Category<ComponentName> = {
  type ConfigInternal (line 163) | type ConfigInternal<
  type DefaultComponents (line 187) | type DefaultComponents = Record<string, any>;
  type Config (line 190) | type Config<
  type ExtractConfigParams (line 226) | type ExtractConfigParams<UserConfig extends ConfigInternal> =
  type ConfigParams (line 241) | type ConfigParams<
  type ComponentConfigParams (line 253) | type ComponentConfigParams<

FILE: packages/core/types/Data.tsx
  type BaseData (line 6) | type BaseData<
  type RootDataWithProps (line 12) | type RootDataWithProps<
  type RootDataWithoutProps (line 19) | type RootDataWithoutProps<
  type RootData (line 23) | type RootData<
  type ComponentData (line 28) | type ComponentData<
  type ComponentDataOptionalId (line 40) | type ComponentDataOptionalId<
  type MappedItem (line 51) | type MappedItem = ComponentData;
  type ComponentDataMap (line 53) | type ComponentDataMap<
  type Content (line 63) | type Content<
  type Data (line 69) | type Data<
  type Metadata (line 78) | type Metadata = { [key: string]: any };
  type PuckMetadata (line 80) | interface PuckMetadata extends Metadata {}
  type ComponentMetadata (line 82) | interface ComponentMetadata extends PuckMetadata {}
  type FieldMetadata (line 84) | interface FieldMetadata extends Metadata {}

FILE: packages/core/types/Fields.ts
  type FieldOption (line 10) | type FieldOption = {
  type FieldOptions (line 15) | type FieldOptions = Array<FieldOption> | ReadonlyArray<FieldOption>;
  type BaseField (line 17) | interface BaseField {
  type TextField (line 24) | interface TextField extends BaseField {
  type NumberField (line 30) | interface NumberField extends BaseField {
  type TextareaField (line 38) | interface TextareaField extends BaseField {
  type SelectField (line 44) | interface SelectField extends BaseField {
  type RadioField (line 49) | interface RadioField extends BaseField {
  type RichtextField (line 54) | interface RichtextField<
  type ArrayField (line 79) | interface ArrayField<
  type ObjectField (line 95) | interface ObjectField<
  type Adaptor (line 108) | type Adaptor<
  type NotUndefined (line 118) | type NotUndefined<T> = T extends undefined ? never : T;
  type ExternalFieldWithAdaptor (line 121) | type ExternalFieldWithAdaptor<
  type CacheOpts (line 131) | type CacheOpts = {
  type ExternalField (line 135) | interface ExternalField<Props extends any = { [key: string]: any }>
  type CustomFieldRender (line 154) | type CustomFieldRender<Value extends any> = (props: {
  type CustomField (line 163) | interface CustomField<Value extends any> extends BaseField {
  type SlotField (line 170) | interface SlotField extends BaseField {
  type Field (line 176) | type Field<ValueType = any, UserField extends {} = {}> =
  type Fields (line 193) | type Fields<
  type FieldProps (line 204) | type FieldProps<F = Field<any>, ValueType = any> = {

FILE: packages/core/types/Internal.tsx
  type ZoneType (line 8) | type ZoneType = "root" | "dropzone" | "slot";
  type PuckNodeData (line 10) | type PuckNodeData = {
  type PuckZoneData (line 18) | type PuckZoneData = {
  type NodeIndex (line 23) | type NodeIndex = Record<string, PuckNodeData>;
  type ZoneIndex (line 24) | type ZoneIndex = Record<string, PuckZoneData>;
  type PrivateAppState (line 26) | type PrivateAppState<UserData extends Data = Data> =
  type BuiltinTypes (line 34) | type BuiltinTypes =
  type WithDeepSlots (line 46) | type WithDeepSlots<T, SlotType = T> =
  type ConfigParams (line 63) | type ConfigParams<
  type FieldsExtension (line 75) | type FieldsExtension = { [Type in string]: { type: Type } };
  type ComponentConfigParams (line 77) | type ComponentConfigParams<
  type Exact (line 86) | type Exact<T, Target> = Record<Exclude<keyof T, keyof Target>, never>;
  type LeftOrExactRight (line 90) | type LeftOrExactRight<Union, Left, Right> =
  type AssertHasValue (line 94) | type AssertHasValue<T, True = T, False = never> = [keyof T] extends [
  type RenderFunc (line 101) | type RenderFunc<
  type PluginInternal (line 105) | type PluginInternal = Plugin & {

FILE: packages/core/types/Props.tsx
  type PuckContext (line 5) | type PuckContext = {
  type DefaultRootFieldProps (line 12) | type DefaultRootFieldProps = {
  type DefaultRootRenderProps (line 16) | type DefaultRootRenderProps<
  type DefaultRootProps (line 20) | type DefaultRootProps = DefaultRootRenderProps;
  type DefaultComponentProps (line 22) | type DefaultComponentProps = { [key: string]: any };

FILE: packages/core/types/Utils.tsx
  type WithId (line 8) | type WithId<Props> = Props & {
  type WithPuckProps (line 12) | type WithPuckProps<Props> = Props & {
  type AsFieldProps (line 16) | type AsFieldProps<Props> = Omit<Props, "children" | "puck" | "editMode">;
  type WithChildren (line 18) | type WithChildren<Props> = Props & {
  type UserGenerics (line 22) | type UserGenerics<
  type ExtractField (line 43) | type ExtractField<

FILE: packages/create-puck-app/index.js
  function getPkgManager (line 26) | function getPkgManager() {

FILE: packages/field-contentful/index.ts
  type Entry (line 7) | type Entry<Fields extends Record<string, any> = {}> = BaseEntry & {
  function createFieldContentful (line 11) | function createFieldContentful<T extends Entry = Entry>(

FILE: packages/plugin-heading-analyzer/src/HeadingAnalyzer.tsx
  type Block (line 50) | type Block = {
  function buildHierarchy (line 59) | function buildHierarchy(frame: Element | Document): Block[] {

FILE: packages/tsup-config/index.ts
  method setup (line 25) | setup(build): void {

FILE: recipes/next-ai/app/[...puckPath]/client.tsx
  function Client (line 7) | function Client({ data }: { data: Data }) {

FILE: recipes/next-ai/app/[...puckPath]/page.tsx
  function generateMetadata (line 18) | async function generateMetadata({
  function Page (line 31) | async function Page({

FILE: recipes/next-ai/app/api/pages/route.ts
  function POST (line 6) | async function POST(request: Request) {

FILE: recipes/next-ai/app/layout.tsx
  function RootLayout (line 3) | function RootLayout({

FILE: recipes/next-ai/app/puck/[...puckPath]/client.tsx
  function Client (line 11) | function Client({ path, data }: { path: string; data: Partial<Data> }) {

FILE: recipes/next-ai/app/puck/[...puckPath]/page.tsx
  function generateMetadata (line 20) | async function generateMetadata({
  function Page (line 33) | async function Page({

FILE: recipes/next-ai/proxy.ts
  function proxy (line 5) | async function proxy(req: NextRequest) {

FILE: recipes/next-ai/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/next/app/[...puckPath]/client.tsx
  function Client (line 7) | function Client({ data }: { data: Data }) {

FILE: recipes/next/app/[...puckPath]/page.tsx
  function generateMetadata (line 18) | async function generateMetadata({
  function Page (line 31) | async function Page({

FILE: recipes/next/app/layout.tsx
  function RootLayout (line 3) | function RootLayout({

FILE: recipes/next/app/puck/[...puckPath]/client.tsx
  function Client (line 7) | function Client({ path, data }: { path: string; data: Partial<Data> }) {

FILE: recipes/next/app/puck/[...puckPath]/page.tsx
  function generateMetadata (line 19) | async function generateMetadata({
  function Page (line 32) | async function Page({

FILE: recipes/next/app/puck/api/route.ts
  function POST (line 5) | async function POST(request: Request) {

FILE: recipes/next/proxy.ts
  function proxy (line 5) | async function proxy(req: NextRequest) {

FILE: recipes/next/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/react-router-ai/app/components/puck-render.tsx
  function PuckRender (line 6) | function PuckRender({ data }: { data: Data }) {

FILE: recipes/react-router-ai/app/lib/pages.server.ts
  function getPage (line 10) | async function getPage(path: string) {
  function savePage (line 15) | async function savePage(path: string, data: Data) {
  function readDatabase (line 21) | async function readDatabase() {

FILE: recipes/react-router-ai/app/lib/resolve-puck-path.server.ts
  function resolvePuckPath (line 1) | function resolvePuckPath(

FILE: recipes/react-router-ai/app/root.tsx
  function Layout (line 12) | function Layout({ children }: { children: React.ReactNode }) {
  function App (line 30) | function App() {
  function ErrorBoundary (line 34) | function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {

FILE: recipes/react-router-ai/app/routes/_index.tsx
  function loader (line 6) | async function loader() {
  function meta (line 21) | function meta({ data: loaderData }: Route.MetaArgs) {
  function PuckSplatRoute (line 29) | function PuckSplatRoute({ loaderData }: Route.ComponentProps) {

FILE: recipes/react-router-ai/app/routes/api.puck.ts
  function action (line 6) | async function action(args: ActionFunctionArgs) {

FILE: recipes/react-router-ai/app/routes/puck-splat.tsx
  function loader (line 13) | async function loader({ params }: Route.LoaderArgs) {
  function meta (line 42) | function meta({ data: loaderData }: Route.MetaArgs) {
  function action (line 52) | async function action({ params, request }: Route.ActionArgs) {
  function Editor (line 62) | function Editor() {
  function PuckSplatRoute (line 91) | function PuckSplatRoute({ loaderData }: Route.ComponentProps) {

FILE: recipes/react-router-ai/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/react-router/app/components/puck-render.tsx
  function PuckRender (line 6) | function PuckRender({ data }: { data: Data }) {

FILE: recipes/react-router/app/lib/pages.server.ts
  function getPage (line 10) | async function getPage(path: string) {
  function savePage (line 15) | async function savePage(path: string, data: Data) {
  function readDatabase (line 21) | async function readDatabase() {

FILE: recipes/react-router/app/lib/resolve-puck-path.server.ts
  function resolvePuckPath (line 1) | function resolvePuckPath(

FILE: recipes/react-router/app/root.tsx
  function Layout (line 12) | function Layout({ children }: { children: React.ReactNode }) {
  function App (line 30) | function App() {
  function ErrorBoundary (line 34) | function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {

FILE: recipes/react-router/app/routes/_index.tsx
  function loader (line 6) | async function loader() {
  function meta (line 21) | function meta({ data: loaderData }: Route.MetaArgs) {
  function PuckSplatRoute (line 29) | function PuckSplatRoute({ loaderData }: Route.ComponentProps) {

FILE: recipes/react-router/app/routes/puck-splat.tsx
  function loader (line 11) | async function loader({ params }: Route.LoaderArgs) {
  function meta (line 40) | function meta({ data: loaderData }: Route.MetaArgs) {
  function action (line 50) | async function action({ params, request }: Route.ActionArgs) {
  function Editor (line 58) | function Editor() {
  function PuckSplatRoute (line 85) | function PuckSplatRoute({ loaderData }: Route.ComponentProps) {

FILE: recipes/react-router/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/remix-ai/app/entry.server.tsx
  constant ABORT_DELAY (line 15) | const ABORT_DELAY = 5_000;
  function handleRequest (line 17) | function handleRequest(
  function handleBotRequest (line 39) | function handleBotRequest(
  function handleBrowserRequest (line 89) | function handleBrowserRequest(

FILE: recipes/remix-ai/app/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/remix-ai/app/root.tsx
  function App (line 19) | function App() {

FILE: recipes/remix-ai/app/routes/_index.tsx
  function Page (line 30) | function Page() {

FILE: recipes/remix-ai/app/routes/api.puck.$.tsx
  function action (line 6) | async function action(args: ActionFunctionArgs) {

FILE: recipes/remix-ai/app/routes/edit.tsx
  function Edit (line 53) | function Edit() {

FILE: recipes/remix/app/entry.server.tsx
  constant ABORT_DELAY (line 15) | const ABORT_DELAY = 5_000;
  function handleRequest (line 17) | function handleRequest(
  function handleBotRequest (line 39) | function handleBotRequest(
  function handleBrowserRequest (line 89) | function handleBrowserRequest(

FILE: recipes/remix/app/puck.config.tsx
  type Props (line 3) | type Props = {

FILE: recipes/remix/app/root.tsx
  function App (line 19) | function App() {

FILE: recipes/remix/app/routes/_index.tsx
  function Page (line 30) | function Page() {

FILE: recipes/remix/app/routes/edit.tsx
  function Edit (line 48) | function Edit() {

FILE: scripts/e2e/smoke-framework.mjs
  constant CHART (line 5) | const CHART = false;
  constant CHART_HEIGHT (line 6) | const CHART_HEIGHT = 15;
  constant DURATION (line 7) | const DURATION = 60;
  constant THRESHOLD (line 8) | const THRESHOLD = 300;

FILE: scripts/e2e/utils/drag-and-drop.mjs
  constant TIME_PREFIX (line 4) | const TIME_PREFIX = 0;
  function dragAndDrop (line 6) | async function dragAndDrop(

FILE: scripts/e2e/utils/get-box.mjs
  function getFrameElement (line 10) | function getFrameElement(el) {
  function getFrameTransform (line 20) | function getFrameTransform(frameEl, boundary = window.frameElement) {
  function getScale (line 47) | function getScale(
Condensed preview — 719 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,569K chars).
[
  {
    "path": ".eslintrc.js",
    "chars": 392,
    "preview": "module.exports = {\n  root: true,\n  // This tells ESLint to load the config from the package `eslint-config-custom`\n  ext"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 1993,
    "preview": "---\nname: \"Bug Report 🐛\"\nabout:\n  Report a problem with Puck. Please provide enough information to reproduce\n  the probl"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 449,
    "preview": "blank_issues_enabled: false\ncontact_links:\n    - name: Guidance - Discord 👾\n      url: https://discord.gg/V9mDAhuxyZ\n   "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 1266,
    "preview": "---\nname: \"Feature Request ✨\"\nabout: \"Share ideas for new features.\"\ntitle: \"\"\nlabels: [\"type: feature\"]\nassignees: \"\"\n-"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 519,
    "preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 1101,
    "preview": "Closes #XXXX\n\n<!--\n  Replace XXXX with the actual issue number this PR closes.\n  Every PR should be linked to an issue.\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 1099,
    "preview": "# This workflow will run all checks required for a PR to be merged.\n\nname: Build and Test ci\n\non:\n  push:\n    branches: "
  },
  {
    "path": ".github/workflows/publish-canary.yml",
    "chars": 793,
    "preview": "name: Publish canary release\non:\n  push:\n    branches:\n      - \"main\"\n      - \"releases/**\"\n\njobs:\n  tag-and-publish-to-"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 1338,
    "preview": "name: Publish release\non:\n  push:\n    branches:\n      - \"releases/**\"\npermissions:\n  contents: write\njobs:\n  tag-and-pub"
  },
  {
    "path": ".gitignore",
    "chars": 410,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n.pnp\n"
  },
  {
    "path": ".npmrc",
    "chars": 26,
    "preview": "auto-install-peers = true\n"
  },
  {
    "path": ".nvmrc",
    "chars": 2,
    "preview": "20"
  },
  {
    "path": ".prettierignore",
    "chars": 34,
    "preview": "CHANGELOG.md\n\n/.nx/workspace-data\n"
  },
  {
    "path": ".prettierrc.json",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": ".yarnrc",
    "chars": 34,
    "preview": "version-git-message \"release: v%s\""
  },
  {
    "path": "CHANGELOG.md",
    "chars": 82436,
    "preview": "# CHANGELOG\n\n<!--__CHANGELOG_ENTRY__-->\n\n## [0.21.1](https://github.com/measuredco/puck/compare/v0.21.0...v0.21.1) (2026"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5412,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4536,
    "preview": "# Contributing to Puck\n\nPuck is still under heavy development, having gained significant interest at an early stage. The"
  },
  {
    "path": "LICENSE",
    "chars": 1074,
    "preview": "MIT License\n\nCopyright (c) The Puck Contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 3910,
    "preview": "<br /><br /><br />\n\n<div align=\"center\">\n\n<a href=\"https://puckeditor.com?utm_source=readme&utm_medium=code&utm_campaign"
  },
  {
    "path": "apps/demo/.eslintrc.js",
    "chars": 59,
    "preview": "module.exports = {\n  root: true,\n  extends: [\"custom\"],\n};\n"
  },
  {
    "path": "apps/demo/.gitignore",
    "chars": 400,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": "apps/demo/README.md",
    "chars": 1448,
    "preview": "# `next` recipe\n\nThe `next` recipe showcases one of the most powerful ways to implement Puck using to provide an authori"
  },
  {
    "path": "apps/demo/app/[...puckPath]/client.tsx",
    "chars": 2721,
    "preview": "\"use client\";\n\nimport { AutoField, Button, FieldLabel, Puck, Render } from \"@/core\";\nimport headingAnalyzer from \"@/plug"
  },
  {
    "path": "apps/demo/app/[...puckPath]/page.tsx",
    "chars": 796,
    "preview": "import resolvePuckPath from \"../../lib/resolve-puck-path\";\nimport { Metadata } from \"next\";\nimport Client from \"./client"
  },
  {
    "path": "apps/demo/app/custom-ui/[...puckPath]/client.tsx",
    "chars": 14620,
    "preview": "// Disable rules of hooks as they are regularly used inside render functions\n/* eslint-disable react-hooks/rules-of-hook"
  },
  {
    "path": "apps/demo/app/custom-ui/[...puckPath]/page.tsx",
    "chars": 759,
    "preview": "import resolvePuckPath from \"../../../lib/resolve-puck-path\";\nimport { Metadata } from \"next\";\nimport Client from \"./cli"
  },
  {
    "path": "apps/demo/app/layout.tsx",
    "chars": 530,
    "preview": "import \"@/core/styles.css\";\nimport \"./styles.css\";\n\nexport default function RootLayout({\n  children,\n}: {\n  children: Re"
  },
  {
    "path": "apps/demo/app/page.tsx",
    "chars": 86,
    "preview": "export { default } from \"./[...puckPath]/page\";\nexport * from \"./[...puckPath]/page\";\n"
  },
  {
    "path": "apps/demo/app/rsc/page.tsx",
    "chars": 1012,
    "preview": "import { Metadata } from \"next\";\nimport config from \"../../config/server\";\nimport { initialData } from \"../../config/ini"
  },
  {
    "path": "apps/demo/app/styles.css",
    "chars": 457,
    "preview": "@import url(\"https://rsms.me/inter/inter.css\");\n\nbody {\n  font-family: Inter, -apple-system, BlinkMacSystemFont, Segoe U"
  },
  {
    "path": "apps/demo/config/blocks/Blank/index.tsx",
    "chars": 415,
    "preview": "import React from \"react\";\nimport { ComponentConfig } from \"@/core\";\nimport styles from \"./styles.module.css\";\nimport { "
  },
  {
    "path": "apps/demo/config/blocks/Blank/styles.module.css",
    "chars": 51,
    "preview": ".Blank {\n  background: hotpink;\n  padding: 16px;\n}\n"
  },
  {
    "path": "apps/demo/config/blocks/Button/index.tsx",
    "chars": 1029,
    "preview": "import React from \"react\";\nimport { ComponentConfig } from \"@/core/types\";\nimport { Button as _Button } from \"@/core/com"
  },
  {
    "path": "apps/demo/config/blocks/Card/index.tsx",
    "chars": 1948,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport React, { ReactElement } from \"react\";\nimport { ComponentConfig } f"
  },
  {
    "path": "apps/demo/config/blocks/Card/styles.module.css",
    "chars": 850,
    "preview": ".Card {\n  height: 100%;\n}\n\n.Card--card {\n  background: white;\n  box-shadow: rgba(140, 152, 164, 0.25) 0px 3px 6px 0px;\n "
  },
  {
    "path": "apps/demo/config/blocks/Flex/index.tsx",
    "chars": 1915,
    "preview": "import React from \"react\";\nimport { ComponentConfig, Slot } from \"@/core/types\";\nimport styles from \"./styles.module.css"
  },
  {
    "path": "apps/demo/config/blocks/Flex/styles.module.css",
    "chars": 89,
    "preview": ".Flex {\n  display: flex;\n  flex-wrap: wrap;\n  height: 100%;\n}\n\n.Flex-item {\n  flex: 1;\n}\n"
  },
  {
    "path": "apps/demo/config/blocks/Grid/index.tsx",
    "chars": 1260,
    "preview": "import React from \"react\";\nimport { ComponentConfig, Slot } from \"@/core/types\";\nimport styles from \"./styles.module.css"
  },
  {
    "path": "apps/demo/config/blocks/Grid/styles.module.css",
    "chars": 132,
    "preview": ".Grid {\n  display: flex;\n  flex-direction: column;\n  width: auto;\n}\n\n@media (min-width: 768px) {\n  .Grid {\n    display: "
  },
  {
    "path": "apps/demo/config/blocks/Heading/index.tsx",
    "chars": 1942,
    "preview": "import React from \"react\";\n\nimport { ComponentConfig } from \"@/core/types\";\nimport { Heading as _Heading } from \"@/core/"
  },
  {
    "path": "apps/demo/config/blocks/Heading/styles.module.css",
    "chars": 26,
    "preview": ".Heading {\n  margin: 0;\n}\n"
  },
  {
    "path": "apps/demo/config/blocks/Hero/Hero.tsx",
    "chars": 2852,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport React, { ReactNode } from \"react\";\nimport styles from \"./styles.mo"
  },
  {
    "path": "apps/demo/config/blocks/Hero/client.tsx",
    "chars": 6603,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport React from \"react\";\nimport { ComponentConfig } from \"@/core/types\""
  },
  {
    "path": "apps/demo/config/blocks/Hero/index.tsx",
    "chars": 67,
    "preview": "export * from \"./client\";\nexport { type HeroProps } from \"./Hero\";\n"
  },
  {
    "path": "apps/demo/config/blocks/Hero/quotes.ts",
    "chars": 1533,
    "preview": "export const quotes = [\n  {\n    content:\n      \"Age is an issue of mind over matter. If you don't mind, it doesn't matte"
  },
  {
    "path": "apps/demo/config/blocks/Hero/server.tsx",
    "chars": 225,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport { ComponentConfig } from \"@/core/types\";\nimport HeroComponent, { H"
  },
  {
    "path": "apps/demo/config/blocks/Hero/styles.module.css",
    "chars": 1833,
    "preview": ".Hero {\n  background-image: linear-gradient(\n    rgba(255, 255, 255, 0),\n    rgb(247, 250, 255) 100%\n  );\n  display: fle"
  },
  {
    "path": "apps/demo/config/blocks/Logos/index.tsx",
    "chars": 1964,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport React from \"react\";\nimport { ComponentConfig } from \"@/core\";\nimpo"
  },
  {
    "path": "apps/demo/config/blocks/Logos/styles.module.css",
    "chars": 241,
    "preview": ".Logos {\n  background-color: var(--puck-color-grey-02);\n}\n\n.Logos-items {\n  display: flex;\n  justify-content: space-betw"
  },
  {
    "path": "apps/demo/config/blocks/RichText/index.tsx",
    "chars": 581,
    "preview": "import React from \"react\";\nimport { ComponentConfig } from \"@/core/types\";\nimport { WithLayout, withLayout } from \"../.."
  },
  {
    "path": "apps/demo/config/blocks/Space/index.tsx",
    "chars": 1051,
    "preview": "import React from \"react\";\n\nimport { ComponentConfig } from \"@/core\";\nimport { spacingOptions } from \"../../options\";\nim"
  },
  {
    "path": "apps/demo/config/blocks/Space/styles.module.css",
    "chars": 173,
    "preview": ".Space {\n  display: block;\n  height: var(--size);\n  width: var(--size);\n}\n\n.Space--vertical {\n  width: 100%;\n}\n\n.Space--"
  },
  {
    "path": "apps/demo/config/blocks/Stats/index.tsx",
    "chars": 1608,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport React from \"react\";\nimport { ComponentConfig } from \"@/core\";\nimpo"
  },
  {
    "path": "apps/demo/config/blocks/Stats/styles.module.css",
    "chars": 1094,
    "preview": ".Stats-items {\n  background-image: linear-gradient(\n    120deg,\n    var(--puck-color-azure-03) 0%,\n    var(--puck-color-"
  },
  {
    "path": "apps/demo/config/blocks/Template/Template.tsx",
    "chars": 597,
    "preview": "import React from \"react\";\nimport { Slot } from \"@/core/types\";\nimport styles from \"./styles.module.css\";\nimport { getCl"
  },
  {
    "path": "apps/demo/config/blocks/Template/client.tsx",
    "chars": 6069,
    "preview": "/* eslint-disable react-hooks/rules-of-hooks */\nimport React, { useState } from \"react\";\nimport { AutoField, Button, cre"
  },
  {
    "path": "apps/demo/config/blocks/Template/index.tsx",
    "chars": 75,
    "preview": "export * from \"./client\";\nexport { type TemplateProps } from \"./Template\";\n"
  },
  {
    "path": "apps/demo/config/blocks/Template/server.tsx",
    "chars": 319,
    "preview": "import { ComponentConfig } from \"@/core/types\";\nimport { withLayout } from \"../../components/Layout\";\nimport TemplateCom"
  },
  {
    "path": "apps/demo/config/blocks/Template/styles.module.css",
    "chars": 140,
    "preview": ".Template {\n  display: flex;\n  flex-direction: column;\n  width: auto;\n}\n\n@media (min-width: 768px) {\n  .Template {\n    d"
  },
  {
    "path": "apps/demo/config/blocks/Text/index.tsx",
    "chars": 2029,
    "preview": "import React from \"react\";\nimport { ALargeSmall, AlignLeft } from \"lucide-react\";\n\nimport { ComponentConfig } from \"@/co"
  },
  {
    "path": "apps/demo/config/blocks/Text/styles.module.css",
    "chars": 46,
    "preview": ".Text {\n  line-height: 1.5;\n  padding: 0px;\n}\n"
  },
  {
    "path": "apps/demo/config/components/Footer/index.tsx",
    "chars": 2130,
    "preview": "import { ReactNode } from \"react\";\nimport { Section } from \"../Section\";\n\nconst FooterLink = ({ children, href }: { chil"
  },
  {
    "path": "apps/demo/config/components/Header/index.tsx",
    "chars": 1248,
    "preview": "import { getClassNameFactory } from \"@/core/lib\";\n\nimport styles from \"./styles.module.css\";\n\nconst getClassName = getCl"
  },
  {
    "path": "apps/demo/config/components/Header/styles.module.css",
    "chars": 556,
    "preview": ".Header {\n  background-color: white;\n  position: sticky;\n  top: 0;\n  z-index: 2;\n}\n\n.Header-inner {\n  align-items: cente"
  },
  {
    "path": "apps/demo/config/components/Layout/index.tsx",
    "chars": 3751,
    "preview": "import { CSSProperties, forwardRef, ReactNode } from \"react\";\nimport {\n  ComponentConfig,\n  DefaultComponentProps,\n  Obj"
  },
  {
    "path": "apps/demo/config/components/Layout/styles.module.css",
    "chars": 30,
    "preview": ".Layout {\n  display: block;\n}\n"
  },
  {
    "path": "apps/demo/config/components/Section/index.tsx",
    "chars": 782,
    "preview": "import { CSSProperties, forwardRef, ReactNode } from \"react\";\nimport styles from \"./styles.module.css\";\nimport { getClas"
  },
  {
    "path": "apps/demo/config/components/Section/styles.module.css",
    "chars": 422,
    "preview": ".Section:not(.Section .Section) {\n  padding-inline-start: 16px;\n  padding-inline-end: 16px;\n}\n\n@media (min-width: 768px)"
  },
  {
    "path": "apps/demo/config/index.tsx",
    "chars": 1373,
    "preview": "import { Button } from \"./blocks/Button\";\nimport { Card } from \"./blocks/Card\";\nimport { Grid } from \"./blocks/Grid\";\nim"
  },
  {
    "path": "apps/demo/config/initial-data.ts",
    "chars": 11842,
    "preview": "import { UserData } from \"./types\";\n\nexport const initialData: Record<string, UserData> = {\n  \"/\": {\n    content: [\n    "
  },
  {
    "path": "apps/demo/config/options.ts",
    "chars": 769,
    "preview": "export const spacingOptions = [\n  { label: \"8px\", value: \"8px\" },\n  { label: \"16px\", value: \"16px\" },\n  { label: \"24px\","
  },
  {
    "path": "apps/demo/config/root.tsx",
    "chars": 1862,
    "preview": "import { DefaultRootProps, RootConfig } from \"@/core\";\nimport { Header } from \"./components/Header\";\nimport { Footer } f"
  },
  {
    "path": "apps/demo/config/server.tsx",
    "chars": 1180,
    "preview": "import { Button } from \"./blocks/Button\";\nimport { Card } from \"./blocks/Card\";\nimport { Grid } from \"./blocks/Grid\";\nim"
  },
  {
    "path": "apps/demo/config/types.ts",
    "chars": 1238,
    "preview": "import { Config, Data } from \"@/core\";\nimport { ButtonProps } from \"./blocks/Button\";\nimport { CardProps } from \"./block"
  },
  {
    "path": "apps/demo/lib/resolve-puck-path.ts",
    "chars": 352,
    "preview": "const resolvePuckPath = (puckPath: string[] = []) => {\n  const hasPath = puckPath.length > 0;\n\n  const isEdit = hasPath "
  },
  {
    "path": "apps/demo/lib/use-demo-data.ts",
    "chars": 1445,
    "preview": "import { useEffect, useState } from \"react\";\nimport config, { componentKey } from \"../config\";\nimport { initialData } fr"
  },
  {
    "path": "apps/demo/next-env.d.ts",
    "chars": 251,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\nimport \"./.next/dev/types/routes.d.ts\";"
  },
  {
    "path": "apps/demo/next.config.js",
    "chars": 106,
    "preview": "module.exports = {\n  reactStrictMode: true,\n  transpilePackages: [\"@puckeditor/core\", \"lucide-react\"],\n};\n"
  },
  {
    "path": "apps/demo/package.json",
    "chars": 551,
    "preview": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next bu"
  },
  {
    "path": "apps/demo/tsconfig/base.json",
    "chars": 521,
    "preview": "{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"display\": \"Default\",\n  \"compilerOptions\": {\n    \"composite\": "
  },
  {
    "path": "apps/demo/tsconfig/nextjs.json",
    "chars": 530,
    "preview": "{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"display\": \"Next.js\",\n  \"extends\": \"./base.json\",\n  \"compilerO"
  },
  {
    "path": "apps/demo/tsconfig.json",
    "chars": 571,
    "preview": "{\n  \"extends\": \"./tsconfig/nextjs.json\",\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"plugins\": [{ \"name\": \"next\" }],"
  },
  {
    "path": "apps/docs/.eslintrc.js",
    "chars": 59,
    "preview": "module.exports = {\n  root: true,\n  extends: [\"custom\"],\n};\n"
  },
  {
    "path": "apps/docs/.gitignore",
    "chars": 20,
    "preview": "/public/sitemap.xml\n"
  },
  {
    "path": "apps/docs/components/CtaCard/index.tsx",
    "chars": 729,
    "preview": "import styles from \"./styles.module.css\";\nimport getClassNameFactory from \"@/core/lib/get-class-name-factory\";\nimport { "
  },
  {
    "path": "apps/docs/components/CtaCard/styles.module.css",
    "chars": 893,
    "preview": ".CtaCard {\n  background-color: var(--puck-color-azure-01);\n  background-image: url(https://res.cloudinary.com/measuredco"
  },
  {
    "path": "apps/docs/components/DiscoveryButton/index.tsx",
    "chars": 1262,
    "preview": "import { Button } from \"@/core/components/Button\";\n\nexport function DiscoveryButton() {\n  return (\n    <>\n      <script\n"
  },
  {
    "path": "apps/docs/components/FooterActions/index.tsx",
    "chars": 571,
    "preview": "import { getClassNameFactory } from \"@/core/lib\";\n\nimport styles from \"./styles.module.css\";\nimport { ThemeSwitch } from"
  },
  {
    "path": "apps/docs/components/FooterActions/styles.module.css",
    "chars": 278,
    "preview": ".FooterActions {\n  align-items: center;\n  display: flex;\n  flex-wrap: wrap;\n  gap: 16px;\n  width: 100%;\n}\n\n.FooterAction"
  },
  {
    "path": "apps/docs/components/Home/index.tsx",
    "chars": 1989,
    "preview": "import React from \"react\";\n\nimport styles from \"./styles.module.css\";\nimport getClassNameFactory from \"@/core/lib/get-cl"
  },
  {
    "path": "apps/docs/components/Home/styles.module.css",
    "chars": 1175,
    "preview": ".Home {\n  display: flex;\n  padding-bottom: 48px;\n  padding-top: 48px;\n  flex-direction: column;\n  align-items: center;\n "
  },
  {
    "path": "apps/docs/components/Preview/index.tsx",
    "chars": 7959,
    "preview": "import React, {\n  createContext,\n  CSSProperties,\n  useContext,\n  useEffect,\n  useRef,\n  useState,\n} from \"react\";\n\nexpo"
  },
  {
    "path": "apps/docs/components/Preview/styles.module.css",
    "chars": 3008,
    "preview": ".PreviewFrame {\n  background: white;\n  border: 1px solid var(--puck-color-grey-09);\n  color: black;\n  border-radius: 16p"
  },
  {
    "path": "apps/docs/components/ReleaseSwitcher/index.tsx",
    "chars": 2193,
    "preview": "import { useEffect, useState } from \"react\";\n\nimport packageJson from \"../../package.json\";\nimport { getClassNameFactory"
  },
  {
    "path": "apps/docs/components/ReleaseSwitcher/styles.module.css",
    "chars": 680,
    "preview": ".ReleaseSwitcher {\n  appearance: none; /* Safari */\n  background: url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3"
  },
  {
    "path": "apps/docs/components/Viewport/index.tsx",
    "chars": 410,
    "preview": "import { getClassNameFactory } from \"@/core/lib\";\n\nimport styles from \"./styles.module.css\";\nimport { ReactNode } from \""
  },
  {
    "path": "apps/docs/components/Viewport/styles.module.css",
    "chars": 220,
    "preview": ".Viewport {\n  display: none;\n}\n\n.Viewport--mobile {\n  display: block;\n}\n\n@media (min-width: 768px) {\n  .Viewport--deskto"
  },
  {
    "path": "apps/docs/middleware.ts",
    "chars": 618,
    "preview": "import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\n\nimport releases from \"./rel"
  },
  {
    "path": "apps/docs/next-env.d.ts",
    "chars": 230,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edite"
  },
  {
    "path": "apps/docs/next-sitemap.config.js",
    "chars": 136,
    "preview": "/** @type {import('next-sitemap').IConfig} */\nmodule.exports = {\n  siteUrl: \"https://puckeditor.com\",\n  generateIndexSit"
  },
  {
    "path": "apps/docs/next.config.mjs",
    "chars": 1512,
    "preview": "import packageJson from \"./package.json\" assert { type: \"json\" };\nimport nextra from \"nextra\";\n\nconst withNextra = nextr"
  },
  {
    "path": "apps/docs/package.json",
    "chars": 591,
    "preview": "{\n  \"name\": \"docs\",\n  \"version\": \"0.21.1\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next b"
  },
  {
    "path": "apps/docs/pages/_app.tsx",
    "chars": 178,
    "preview": "import type { AppProps } from \"next/app\";\nimport \"../styles.css\";\n\nexport default function DocsApp({ Component, pageProp"
  },
  {
    "path": "apps/docs/pages/_document.tsx",
    "chars": 500,
    "preview": "import { Html, Head, Main, NextScript } from \"next/document\";\n\nexport default function Document() {\n  return (\n    <Html"
  },
  {
    "path": "apps/docs/pages/_meta.js",
    "chars": 314,
    "preview": "const menu = {\n  index: {\n    type: \"page\",\n    title: \"Puck\",\n    display: \"hidden\",\n    theme: {\n      layout: \"full\","
  },
  {
    "path": "apps/docs/pages/api/releases.ts",
    "chars": 665,
    "preview": "import type { NextApiRequest, NextApiResponse } from \"next\";\n\nimport releases from \"../../releases.json\";\n\n/**\n * Proxy "
  },
  {
    "path": "apps/docs/pages/docs/_meta.js",
    "chars": 349,
    "preview": "const menu = {\n  index: {\n    title: \"Introduction\",\n  },\n  \"getting-started\": {\n    title: \"Getting Started\",\n  },\n  \"i"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/_meta.js",
    "chars": 180,
    "preview": "const menu = {\n  components: {},\n  configuration: {},\n  \"data-model\": {},\n  fields: {},\n  functions: {},\n  overrides: {}"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/actions.mdx",
    "chars": 2161,
    "preview": "# Actions\n\nActions enable you to make changes to the internal [AppState](/docs/api-reference/data-model/app-state) via t"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/_meta.js",
    "chars": 487,
    "preview": "const menu = {\n  \"action-bar\": {},\n  \"action-bar-action\": {},\n  \"action-bar-group\": {},\n  \"action-bar-label\": {},\n  \"act"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/action-bar-action.mdx",
    "chars": 1469,
    "preview": "---\ntitle: <ActionBar.Action>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { ActionBar } from \"@"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/action-bar-group.mdx",
    "chars": 1092,
    "preview": "---\ntitle: <ActionBar.Group>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { ActionBar } from \"@/"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/action-bar-label.mdx",
    "chars": 986,
    "preview": "---\ntitle: <ActionBar.Label>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { ActionBar } from \"@/"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/action-bar-separator.mdx",
    "chars": 827,
    "preview": "---\ntitle: <ActionBar.Separator>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { ActionBar } from"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/action-bar.mdx",
    "chars": 1221,
    "preview": "---\ntitle: <ActionBar>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { ActionBar } from \"@/puck\";"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/auto-field.mdx",
    "chars": 2543,
    "preview": "---\ntitle: <AutoField>\n---\n\nimport { ConfigPreview } from \"@/docs/components/Preview\";\nimport { AutoField } from \"@/puck"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/drawer-item.mdx",
    "chars": 2240,
    "preview": "---\ntitle: <Drawer.Item>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Drawer } from \"@/puck\";\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/drawer.mdx",
    "chars": 1084,
    "preview": "---\ntitle: <Drawer>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck, Drawer } from \"@/puck\";"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/drop-zone.mdx",
    "chars": 5512,
    "preview": "---\ntitle: <DropZone>\n---\n\nimport { Callout } from \"nextra/components\";\n\n# \\<DropZone\\>\n\n<Callout>\nThe [`<DropZone>` com"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/field-label.mdx",
    "chars": 4449,
    "preview": "---\ntitle: <FieldLabel>\n---\n\nimport { ConfigPreview } from \"../../../../components/Preview\";\nimport { FieldLabel } from "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck-components.mdx",
    "chars": 810,
    "preview": "---\ntitle: <Puck.Components>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\""
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck-fields.mdx",
    "chars": 1186,
    "preview": "---\ntitle: <Puck.Fields>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\";\n\n#"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck-layout.mdx",
    "chars": 691,
    "preview": "---\ntitle: <Puck.Layout>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\";\n\n#"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck-outline.mdx",
    "chars": 897,
    "preview": "---\ntitle: <Puck.Outline>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\";\n\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck-preview.mdx",
    "chars": 1212,
    "preview": "---\ntitle: <Puck.Preview>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\";\n\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/puck.mdx",
    "chars": 15892,
    "preview": "---\ntitle: <Puck>\n---\n\n# \\<Puck\\>\n\nRender the Puck editor.\n\n```tsx copy\nimport { Puck } from \"@puckeditor/core\";\n\nconst "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/render.mdx",
    "chars": 2523,
    "preview": "---\ntitle: <Render>\n---\n\n# \\<Render\\>\n\nRender a [`Data`](/docs/api-reference/data-model/data) object for a given [`Confi"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/rich-text-menu-control.mdx",
    "chars": 2347,
    "preview": "---\ntitle: <RichTextMenu.Control>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { RichTextMenu } "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/rich-text-menu-group.mdx",
    "chars": 911,
    "preview": "---\ntitle: <RichTextMenu.Group>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { RichTextMenu } fr"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components/rich-text-menu.mdx",
    "chars": 4328,
    "preview": "---\ntitle: <RichTextMenu>\n---\n\nimport { PuckPreview } from \"@/docs/components/Preview\";\nimport { RichTextMenu } from \"@/"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/components.mdx",
    "chars": 2402,
    "preview": "# Components\n\nPuck provides several components to support different integration approaches.\n\n## Core\n\n- [\\<DropZone\\>](c"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/configuration/_meta.js",
    "chars": 54,
    "preview": "const menu = {\n  config: {},\n};\n\nexport default menu;\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/configuration/component-config.mdx",
    "chars": 19428,
    "preview": "---\ntitle: ComponentConfig\n---\n\nimport { ConfigPreview, PuckPreview } from \"@/docs/components/Preview\";\nimport { Drawer "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/configuration/config.mdx",
    "chars": 3164,
    "preview": "# Config\n\nThe main configuration object describing what Puck can render.\n\n```tsx copy\nconst config = {\n  components: {\n "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/configuration.mdx",
    "chars": 233,
    "preview": "# Configuration\n\n- [Config](configuration/config) - The main configuration object describing what Puck can render.\n- [Co"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model/app-state.mdx",
    "chars": 6530,
    "preview": "---\ntitle: AppState\n---\n\nimport { Callout } from \"nextra/components\";\n\n# `AppState`\n\n<Callout>\n  The application state i"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model/component-data.mdx",
    "chars": 1758,
    "preview": "---\ntitle: ComponentData\n---\n\n# `ComponentData`\n\nAn object representing an instance of a component.\n\n```json\n{\n  \"type\":"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model/data.mdx",
    "chars": 2705,
    "preview": "import { Callout } from \"nextra/components\";\n\n# `Data`\n\nAn object produced by Puck describing the shape of content.\n\n```"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model/item-selector.mdx",
    "chars": 1401,
    "preview": "---\ntitle: ItemSelector\n---\n\nimport { Callout } from \"nextra/components\";\n\n# `ItemSelector`\n\nAn object describing the lo"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model/root-data.mdx",
    "chars": 1697,
    "preview": "---\ntitle: RootData\n---\n\n# `RootData`\n\nAn object representing the root data. Similar to [`ComponentData`](/docs/api-refe"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/data-model.mdx",
    "chars": 329,
    "preview": "# Data Model\n\nThe Puck data model\n\n- [AppState](data-model/app-state) - Puck's internal state.\n- [ComponentData](data-mo"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/field-transforms.mdx",
    "chars": 1815,
    "preview": "---\ntitle: FieldTransforms\n---\n\n# FieldTransforms\n\nTransform the data for each [field type](/docs/api-reference/fields) "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/_meta.js",
    "chars": 74,
    "preview": "const menu = {\n  base: {\n    title: \"Base\",\n  },\n};\n\nexport default menu;\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/array.mdx",
    "chars": 7956,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\nimport { Callout } from \"nextra/components\";\n\n# Array\n\nRender"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/base.mdx",
    "chars": 1632,
    "preview": "# Base\n\nThe base type shared by all fields.\n\n## Params\n\n| Param                     | Example               | Type      "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/custom.mdx",
    "chars": 8954,
    "preview": "import { Puck, FieldLabel, AutoField } from \"@/puck\";\nimport { ConfigPreview, PuckPreview } from \"@/docs/components/Prev"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/external.mdx",
    "chars": 17825,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\nimport { Callout } from \"nextra/components\";\n\n# External\n\nSel"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/number.mdx",
    "chars": 3544,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\n\n# Number\n\nRender a `number` input. Extends [Base](base).\n\n<C"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/object.mdx",
    "chars": 1960,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\n\n# Object\n\nRender an object with a subset of fields. Extends "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/radio.mdx",
    "chars": 2243,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\n\n# Radio\n\nRender a `radio` input with a list of options. Exte"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/richtext.mdx",
    "chars": 14694,
    "preview": "import { Puck, RichTextMenu } from \"@/puck\";\nimport { ConfigPreview, PuckPreview } from \"@/docs/components/Preview\";\nimp"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/select.mdx",
    "chars": 2141,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\n\n# Select\n\nRender a `select` input with a list of options. Ex"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/slot.mdx",
    "chars": 7746,
    "preview": "import {\n  ConfigPreview,\n  PuckPreview,\n  CodeBlockDrawer,\n} from \"@/docs/components/Preview\";\nimport { usePuck } from "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/text.mdx",
    "chars": 3126,
    "preview": "import { Puck } from \"@/puck\";\nimport { ConfigPreview, PuckPreview } from \"@/docs/components/Preview\";\nimport { Callout "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields/textarea.mdx",
    "chars": 3336,
    "preview": "import { Puck } from \"@/puck\";\nimport { ConfigPreview, PuckPreview } from \"@/docs/components/Preview\";\nimport { Callout "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/fields.mdx",
    "chars": 861,
    "preview": "# Fields\n\nA field represents a user input shown in the Puck interface.\n\n- [Base](fields/base) - The base type shared by "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/migrate.mdx",
    "chars": 4687,
    "preview": "---\ntitle: migrate\n---\n\n# migrate\n\nMigrate the [Data payload](/docs/api-reference/data-model/data) to the latest shape, "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/register-overlay-portal.mdx",
    "chars": 1635,
    "preview": "---\ntitle: registerOverlayPortal\n---\n\n# registerOverlayPortal\n\nRegister a node as an [Overlay Portal](/docs/integrating-"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/resolve-all-data.mdx",
    "chars": 997,
    "preview": "---\ntitle: resolveAllData\n---\n\n# resolveAllData\n\nUtility function to execute all [`resolveData` methods](/docs/api-refer"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/set-deep.mdx",
    "chars": 1537,
    "preview": "---\ntitle: setDeep\n---\n\n# setDeep\n\nA convenience utility for setting the value of a key deep within an object.\n\nUseful w"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/transform-props.mdx",
    "chars": 2306,
    "preview": "---\ntitle: transformProps\n---\n\n# transformProps\n\nTransform component props stored in a [Data payload](/docs/api-referenc"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/use-get-puck.mdx",
    "chars": 767,
    "preview": "---\ntitle: useGetPuck\n---\n\n# useGetPuck\n\nA hook that returns a function that retrieves the latest [`PuckApi`](/docs/api-"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/use-puck.mdx",
    "chars": 1532,
    "preview": "---\ntitle: usePuck\n---\n\n# usePuck\n\nA hook for accessing the [`PuckApi`](/docs/api-reference/puck-api) as part of your Re"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions/walk-tree.mdx",
    "chars": 3914,
    "preview": "---\ntitle: walkTree\n---\n\n# walkTree\n\nRecursively walk the entire tree for the [`Data`](/docs/api-reference/data-model/da"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/functions.mdx",
    "chars": 885,
    "preview": "# Functions\n\n- [migrate](functions/migrate) - Migrate a legacy [data payload](/docs/api-reference/data-model/data) to th"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/action-bar.mdx",
    "chars": 1178,
    "preview": "---\ntitle: actionBar\n---\n\n# actionBar\n\nOverride the action bar. Use the [`<ActionBar>` component](/docs/api-reference/co"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/component-overlay.mdx",
    "chars": 1110,
    "preview": "---\ntitle: componentOverlay\n---\n\n# componentOverlay\n\nOverride the overlay shown on hover or selection of a component.\n\n`"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/drawer-item.mdx",
    "chars": 494,
    "preview": "---\ntitle: drawerItem\n---\n\n# drawerItem\n\nOverride an item within the component drawer.\n\n```tsx copy\nconst overrides = {\n"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/drawer.mdx",
    "chars": 380,
    "preview": "---\ntitle: drawer\n---\n\n# drawer\n\nOverride the component drawer.\n\n```tsx copy\nconst overrides = {\n  drawer: ({ children }"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/field-label.mdx",
    "chars": 321,
    "preview": "---\ntitle: fieldLabel\n---\n\n# fieldLabel\n\nOverride the label for all internal fields.\n\n```tsx copy\nconst overrides = {\n  "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/field-types.mdx",
    "chars": 1282,
    "preview": "---\ntitle: fieldTypes\n---\n\n# fieldTypes\n\nOverride each [field type](/docs/api-reference/fields).\n\n```tsx copy\nconst over"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/fields.mdx",
    "chars": 370,
    "preview": "---\ntitle: fields\n---\n\n# fields\n\nOverride the fields wrapper.\n\n```tsx copy\nconst overrides = {\n  fields: ({ children }) "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/header-actions.mdx",
    "chars": 537,
    "preview": "---\ntitle: headerActions\n---\n\n# headerActions\n\nOverride the header actions. Return a fragment so your items appear inlin"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/header.mdx",
    "chars": 553,
    "preview": "---\ntitle: header\n---\n\n# header\n\nOverride the header.\n\n```tsx copy\nconst overrides = {\n  header: ({ actions }) => (\n    "
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/iframe.mdx",
    "chars": 642,
    "preview": "---\ntitle: iframe\n---\n\n# iframe\n\nOverride the root of the iframe.\n\n```tsx copy\nconst overrides = {\n  iframe: ({ children"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/outline.mdx",
    "chars": 367,
    "preview": "---\ntitle: outline\n---\n\n# outline\n\nOverride the outline.\n\n```tsx copy\nconst overrides = {\n  outline: ({ children }) => <"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/preview.mdx",
    "chars": 381,
    "preview": "---\ntitle: preview\n---\n\n# preview\n\nOverride the drag-and-drop preview.\n\n```tsx copy\nconst overrides = {\n  preview: ({ ch"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides/puck.mdx",
    "chars": 575,
    "preview": "---\ntitle: puck\n---\n\n# puck\n\nOverride the Puck children. This is the equivalent of passing in [`children`](/docs/api-ref"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/overrides.mdx",
    "chars": 1580,
    "preview": "import { Callout } from \"nextra/components\";\n\n# Overrides\n\n<Callout>\n  The overrides API is highly experimental and is l"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/permissions.mdx",
    "chars": 2316,
    "preview": "# Permissions\n\nPermissions enable the [toggling of Puck features](/docs/integrating-puck/feature-toggling). There are th"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/plugin.mdx",
    "chars": 3864,
    "preview": "# Plugin\n\nA plugin is an extension that enhances the capabilities of Puck.\n\n```tsx showLineNumbers copy {3-8, 14}\nimport"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/plugins/blocks-plugin.mdx",
    "chars": 455,
    "preview": "---\ntitle: blocksPlugin\n---\n\n# blocksPlugin\n\nShow the component drawer for dragging new components onto the canvas.\n\n```"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/plugins/fields-plugin.mdx",
    "chars": 979,
    "preview": "---\ntitle: fieldsPlugin\n---\n\n# fieldsPlugin\n\nShow the fields for the currently selected component. On desktop, the field"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/plugins/legacy-side-bar-plugin.mdx",
    "chars": 446,
    "preview": "---\ntitle: legacySideBarPlugin\n---\n\n# legacySideBarPlugin\n\nHide the plugin rail and show a single sidebar with stacked \""
  },
  {
    "path": "apps/docs/pages/docs/api-reference/plugins/outline-plugin.mdx",
    "chars": 450,
    "preview": "---\ntitle: outlinePlugin\n---\n\n# outlinePlugin\n\nShow an outline of the components currently on the canvas.\n\n```tsx copy\ni"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/puck-api.mdx",
    "chars": 10869,
    "preview": "---\ntitle: PuckApi\n---\n\nimport { Callout } from \"nextra/components\";\n\n# PuckApi\n\n`PuckApi` exposes Puck's internals to e"
  },
  {
    "path": "apps/docs/pages/docs/api-reference/theming.mdx",
    "chars": 1217,
    "preview": "import { Callout } from \"nextra/components\";\n\n# Theming\n\n<Callout type=\"info\">\n  Theming in Puck is currently limited in"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/_meta.js",
    "chars": 205,
    "preview": "const menu = {\n  composition: {},\n  \"custom-fields\": {},\n  \"field-transforms\": {},\n  \"internal-puck-api\": {},\n  theming:"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/composition.mdx",
    "chars": 2641,
    "preview": "import { PuckPreview } from \"@/docs/components/Preview\";\nimport { Puck } from \"@/puck\";\n\n# Composition\n\nPuck uses compos"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/custom-fields.mdx",
    "chars": 5750,
    "preview": "import { ConfigPreview } from \"@/docs/components/Preview\";\nimport { AutoField, FieldLabel } from \"@/puck\";\n\n# Custom Fie"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/field-transforms.mdx",
    "chars": 2349,
    "preview": "import { Callout } from \"nextra/components\";\n\n# Field Transforms\n\nPuck lets you modify props before rendering in the edi"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/internal-puck-api.mdx",
    "chars": 3132,
    "preview": "---\ntitle: Internal Puck API\n---\n\n# Internal Puck API\n\nPuck exposes its internal API as [`PuckApi`](/docs/api-reference/"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/plugins.mdx",
    "chars": 5723,
    "preview": "# Plugin API\n\nimport { Callout } from \"nextra/components\";\n\nThe [plugin API](/docs/api-reference/plugins) enables develo"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/theming/_meta.js",
    "chars": 69,
    "preview": "const menu = {\n  overview: {},\n  fonts: {},\n};\n\nexport default menu;\n"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/theming/fonts.mdx",
    "chars": 724,
    "preview": "# Fonts\n\nPuck uses the [Inter typeface family](https://rsms.me/inter/) by default, loaded via a CDN.\n\nIt's possible to c"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/theming/overview.mdx",
    "chars": 639,
    "preview": "import { Callout } from \"nextra/components\";\n\n# Theming\n\n<Callout type=\"info\">\n  Theming in Puck is currently limited in"
  },
  {
    "path": "apps/docs/pages/docs/extending-puck/ui-overrides.mdx",
    "chars": 3699,
    "preview": "import { Callout } from \"nextra/components\";\n\n# UI overrides\n\n<Callout>\n  The overrides API is highly experimental and i"
  },
  {
    "path": "apps/docs/pages/docs/getting-started.mdx",
    "chars": 1061,
    "preview": "# Getting Started\n\n## Installation\n\nInstall the package\n\n```sh npm2yarn copy\nnpm i @puckeditor/core --save\n```\n\nOr gener"
  },
  {
    "path": "apps/docs/pages/docs/guides/_meta.js",
    "chars": 86,
    "preview": "const menu = {\n  migrations: {\n    title: \"Migrations\",\n  },\n};\n\nexport default menu;\n"
  }
]

// ... and 519 more files (download for full content)

About this extraction

This page contains the full source code of the puckeditor/puck GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 719 files (1.4 MB), approximately 385.0k tokens, and a symbol index with 492 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!