@delmaredigital/payload-puck 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. package/README.md +389 -1261
  2. package/dist/admin/EditWithPuckButton.d.ts +74 -0
  3. package/dist/admin/EditWithPuckButton.d.ts.map +1 -0
  4. package/dist/admin/EditWithPuckButton.js +114 -0
  5. package/dist/admin/EditWithPuckButton.js.map +1 -0
  6. package/dist/admin/EditWithPuckCell.d.ts +43 -0
  7. package/dist/admin/EditWithPuckCell.d.ts.map +1 -0
  8. package/dist/admin/EditWithPuckCell.js +66 -0
  9. package/dist/admin/EditWithPuckCell.js.map +1 -0
  10. package/dist/admin/PuckEditorView.d.ts +85 -0
  11. package/dist/admin/PuckEditorView.d.ts.map +1 -0
  12. package/dist/admin/PuckEditorView.js +135 -0
  13. package/dist/admin/PuckEditorView.js.map +1 -0
  14. package/dist/admin/client.d.ts +8 -104
  15. package/dist/admin/client.d.ts.map +1 -0
  16. package/dist/admin/client.js +14 -176
  17. package/dist/admin/client.js.map +1 -0
  18. package/dist/admin/generateAdminComponents.d.ts +51 -0
  19. package/dist/admin/generateAdminComponents.d.ts.map +1 -0
  20. package/dist/admin/generateAdminComponents.js +42 -0
  21. package/dist/admin/generateAdminComponents.js.map +1 -0
  22. package/dist/admin/index.d.ts +14 -150
  23. package/dist/admin/index.d.ts.map +1 -0
  24. package/dist/admin/index.js +17 -30
  25. package/dist/admin/index.js.map +1 -0
  26. package/dist/api/createPuckApiRoutes.d.ts +31 -0
  27. package/dist/api/createPuckApiRoutes.d.ts.map +1 -0
  28. package/dist/api/createPuckApiRoutes.js +193 -0
  29. package/dist/api/createPuckApiRoutes.js.map +1 -0
  30. package/dist/api/createPuckApiRoutesVersions.d.ts +28 -0
  31. package/dist/api/createPuckApiRoutesVersions.d.ts.map +1 -0
  32. package/dist/api/createPuckApiRoutesVersions.js +144 -0
  33. package/dist/api/createPuckApiRoutesVersions.js.map +1 -0
  34. package/dist/api/createPuckApiRoutesWithId.d.ts +34 -0
  35. package/dist/api/createPuckApiRoutesWithId.d.ts.map +1 -0
  36. package/dist/api/createPuckApiRoutesWithId.js +251 -0
  37. package/dist/api/createPuckApiRoutesWithId.js.map +1 -0
  38. package/dist/api/index.d.ts +11 -431
  39. package/dist/api/index.d.ts.map +1 -0
  40. package/dist/api/index.js +40 -587
  41. package/dist/api/index.js.map +1 -0
  42. package/dist/api/types.d.ts +302 -0
  43. package/dist/api/types.d.ts.map +1 -0
  44. package/dist/api/types.js +2 -0
  45. package/dist/api/types.js.map +1 -0
  46. package/dist/api/utils/mapRootProps.d.ts +76 -0
  47. package/dist/api/utils/mapRootProps.d.ts.map +1 -0
  48. package/dist/api/utils/mapRootProps.js +169 -0
  49. package/dist/api/utils/mapRootProps.js.map +1 -0
  50. package/dist/collections/Templates.d.ts +9 -0
  51. package/dist/collections/Templates.d.ts.map +1 -0
  52. package/dist/collections/Templates.js +62 -0
  53. package/dist/collections/Templates.js.map +1 -0
  54. package/dist/components/AccordionClient.d.ts +20 -0
  55. package/dist/components/AccordionClient.d.ts.map +1 -0
  56. package/dist/components/AccordionClient.js +67 -0
  57. package/dist/components/AccordionClient.js.map +1 -0
  58. package/dist/components/AnimatedWrapper.d.ts +33 -0
  59. package/dist/components/AnimatedWrapper.d.ts.map +1 -0
  60. package/dist/components/AnimatedWrapper.js +61 -0
  61. package/dist/components/AnimatedWrapper.js.map +1 -0
  62. package/dist/components/exports.d.ts +54 -0
  63. package/dist/components/exports.d.ts.map +1 -0
  64. package/dist/components/exports.js +71 -0
  65. package/dist/components/exports.js.map +1 -0
  66. package/dist/components/index.d.ts +8 -216
  67. package/dist/components/index.d.ts.map +1 -0
  68. package/dist/components/index.js +15 -9262
  69. package/dist/components/index.js.map +1 -0
  70. package/dist/components/interactive/Accordion.d.ts +28 -0
  71. package/dist/components/interactive/Accordion.d.ts.map +1 -0
  72. package/dist/components/interactive/Accordion.js +159 -0
  73. package/dist/components/interactive/Accordion.js.map +1 -0
  74. package/dist/components/interactive/Accordion.server.d.ts +29 -0
  75. package/dist/components/interactive/Accordion.server.d.ts.map +1 -0
  76. package/dist/components/interactive/Accordion.server.js +30 -0
  77. package/dist/components/interactive/Accordion.server.js.map +1 -0
  78. package/dist/components/interactive/Button.d.ts +26 -0
  79. package/dist/components/interactive/Button.d.ts.map +1 -0
  80. package/dist/components/interactive/Button.js +133 -0
  81. package/dist/components/interactive/Button.js.map +1 -0
  82. package/dist/components/interactive/Button.server.d.ts +28 -0
  83. package/dist/components/interactive/Button.server.d.ts.map +1 -0
  84. package/dist/components/interactive/Button.server.js +96 -0
  85. package/dist/components/interactive/Button.server.js.map +1 -0
  86. package/dist/components/interactive/Card.d.ts +27 -0
  87. package/dist/components/interactive/Card.d.ts.map +1 -0
  88. package/dist/components/interactive/Card.js +128 -0
  89. package/dist/components/interactive/Card.js.map +1 -0
  90. package/dist/components/interactive/Card.server.d.ts +29 -0
  91. package/dist/components/interactive/Card.server.d.ts.map +1 -0
  92. package/dist/components/interactive/Card.server.js +77 -0
  93. package/dist/components/interactive/Card.server.js.map +1 -0
  94. package/dist/components/interactive/Divider.d.ts +18 -0
  95. package/dist/components/interactive/Divider.d.ts.map +1 -0
  96. package/dist/components/interactive/Divider.js +68 -0
  97. package/dist/components/interactive/Divider.js.map +1 -0
  98. package/dist/components/interactive/Divider.server.d.ts +20 -0
  99. package/dist/components/interactive/Divider.server.d.ts.map +1 -0
  100. package/dist/components/interactive/Divider.server.js +50 -0
  101. package/dist/components/interactive/Divider.server.js.map +1 -0
  102. package/dist/components/interactive/index.d.ts +10 -0
  103. package/dist/components/interactive/index.d.ts.map +1 -0
  104. package/dist/components/interactive/index.js +10 -0
  105. package/dist/components/interactive/index.js.map +1 -0
  106. package/dist/components/layout/Container.d.ts +29 -0
  107. package/dist/components/layout/Container.d.ts.map +1 -0
  108. package/dist/components/layout/Container.js +166 -0
  109. package/dist/components/layout/Container.js.map +1 -0
  110. package/dist/components/layout/Container.server.d.ts +32 -0
  111. package/dist/components/layout/Container.server.d.ts.map +1 -0
  112. package/dist/components/layout/Container.server.js +105 -0
  113. package/dist/components/layout/Container.server.js.map +1 -0
  114. package/dist/components/layout/Flex.d.ts +36 -0
  115. package/dist/components/layout/Flex.d.ts.map +1 -0
  116. package/dist/components/layout/Flex.js +183 -0
  117. package/dist/components/layout/Flex.js.map +1 -0
  118. package/dist/components/layout/Flex.server.d.ts +36 -0
  119. package/dist/components/layout/Flex.server.d.ts.map +1 -0
  120. package/dist/components/layout/Flex.server.js +97 -0
  121. package/dist/components/layout/Flex.server.js.map +1 -0
  122. package/dist/components/layout/Grid.d.ts +31 -0
  123. package/dist/components/layout/Grid.d.ts.map +1 -0
  124. package/dist/components/layout/Grid.js +164 -0
  125. package/dist/components/layout/Grid.js.map +1 -0
  126. package/dist/components/layout/Grid.server.d.ts +32 -0
  127. package/dist/components/layout/Grid.server.d.ts.map +1 -0
  128. package/dist/components/layout/Grid.server.js +92 -0
  129. package/dist/components/layout/Grid.server.js.map +1 -0
  130. package/dist/components/layout/Section.d.ts +35 -0
  131. package/dist/components/layout/Section.d.ts.map +1 -0
  132. package/dist/components/layout/Section.js +212 -0
  133. package/dist/components/layout/Section.js.map +1 -0
  134. package/dist/components/layout/Section.server.d.ts +35 -0
  135. package/dist/components/layout/Section.server.d.ts.map +1 -0
  136. package/dist/components/layout/Section.server.js +144 -0
  137. package/dist/components/layout/Section.server.js.map +1 -0
  138. package/dist/components/layout/Spacer.d.ts +18 -0
  139. package/dist/components/layout/Spacer.d.ts.map +1 -0
  140. package/dist/components/layout/Spacer.js +99 -0
  141. package/dist/components/layout/Spacer.js.map +1 -0
  142. package/dist/components/layout/Spacer.server.d.ts +21 -0
  143. package/dist/components/layout/Spacer.server.d.ts.map +1 -0
  144. package/dist/components/layout/Spacer.server.js +61 -0
  145. package/dist/components/layout/Spacer.server.js.map +1 -0
  146. package/dist/components/layout/Template.d.ts +35 -0
  147. package/dist/components/layout/Template.d.ts.map +1 -0
  148. package/dist/components/layout/Template.js +124 -0
  149. package/dist/components/layout/Template.js.map +1 -0
  150. package/dist/components/layout/Template.server.d.ts +32 -0
  151. package/dist/components/layout/Template.server.d.ts.map +1 -0
  152. package/dist/components/layout/Template.server.js +75 -0
  153. package/dist/components/layout/Template.server.js.map +1 -0
  154. package/dist/components/layout/index.d.ts +14 -0
  155. package/dist/components/layout/index.d.ts.map +1 -0
  156. package/dist/components/layout/index.js +13 -0
  157. package/dist/components/layout/index.js.map +1 -0
  158. package/dist/components/media/Image.d.ts +30 -0
  159. package/dist/components/media/Image.d.ts.map +1 -0
  160. package/dist/components/media/Image.js +123 -0
  161. package/dist/components/media/Image.js.map +1 -0
  162. package/dist/components/media/Image.server.d.ts +28 -0
  163. package/dist/components/media/Image.server.d.ts.map +1 -0
  164. package/dist/components/media/Image.server.js +76 -0
  165. package/dist/components/media/Image.server.js.map +1 -0
  166. package/dist/components/media/index.d.ts +7 -0
  167. package/dist/components/media/index.d.ts.map +1 -0
  168. package/dist/components/media/index.js +7 -0
  169. package/dist/components/media/index.js.map +1 -0
  170. package/dist/components/typography/Heading.d.ts +21 -0
  171. package/dist/components/typography/Heading.d.ts.map +1 -0
  172. package/dist/components/typography/Heading.js +71 -0
  173. package/dist/components/typography/Heading.js.map +1 -0
  174. package/dist/components/typography/Heading.server.d.ts +21 -0
  175. package/dist/components/typography/Heading.server.d.ts.map +1 -0
  176. package/dist/components/typography/Heading.server.js +49 -0
  177. package/dist/components/typography/Heading.server.js.map +1 -0
  178. package/dist/components/typography/RichText.d.ts +20 -0
  179. package/dist/components/typography/RichText.d.ts.map +1 -0
  180. package/dist/components/typography/RichText.editor.d.ts +11 -0
  181. package/dist/components/typography/RichText.editor.d.ts.map +1 -0
  182. package/dist/components/typography/RichText.editor.js +67 -0
  183. package/dist/components/typography/RichText.editor.js.map +1 -0
  184. package/dist/components/typography/RichText.js +73 -0
  185. package/dist/components/typography/RichText.js.map +1 -0
  186. package/dist/components/typography/RichText.server.d.ts +22 -0
  187. package/dist/components/typography/RichText.server.d.ts.map +1 -0
  188. package/dist/components/typography/RichText.server.js +52 -0
  189. package/dist/components/typography/RichText.server.js.map +1 -0
  190. package/dist/components/typography/Text.d.ts +20 -0
  191. package/dist/components/typography/Text.d.ts.map +1 -0
  192. package/dist/components/typography/Text.js +61 -0
  193. package/dist/components/typography/Text.js.map +1 -0
  194. package/dist/components/typography/Text.server.d.ts +21 -0
  195. package/dist/components/typography/Text.server.d.ts.map +1 -0
  196. package/dist/components/typography/Text.server.js +39 -0
  197. package/dist/components/typography/Text.server.js.map +1 -0
  198. package/dist/components/typography/index.d.ts +10 -0
  199. package/dist/components/typography/index.d.ts.map +1 -0
  200. package/dist/components/typography/index.js +10 -0
  201. package/dist/components/typography/index.js.map +1 -0
  202. package/dist/config/config.editor.d.ts +15 -56
  203. package/dist/config/config.editor.d.ts.map +1 -0
  204. package/dist/config/config.editor.js +125 -9462
  205. package/dist/config/config.editor.js.map +1 -0
  206. package/dist/config/index.d.ts +7 -33
  207. package/dist/config/index.d.ts.map +1 -0
  208. package/dist/config/index.js +110 -2119
  209. package/dist/config/index.js.map +1 -0
  210. package/dist/config/merge.d.ts +23 -0
  211. package/dist/config/merge.d.ts.map +1 -0
  212. package/dist/config/merge.js +80 -0
  213. package/dist/config/merge.js.map +1 -0
  214. package/dist/config/presets.d.ts +342 -0
  215. package/dist/config/presets.d.ts.map +1 -0
  216. package/dist/config/presets.js +247 -0
  217. package/dist/config/presets.js.map +1 -0
  218. package/dist/editor/PuckEditor.client.d.ts +131 -0
  219. package/dist/editor/PuckEditor.client.d.ts.map +1 -0
  220. package/dist/editor/PuckEditor.client.js +42 -0
  221. package/dist/editor/PuckEditor.client.js.map +1 -0
  222. package/dist/editor/PuckEditorCore.client.d.ts +141 -0
  223. package/dist/editor/PuckEditorCore.client.d.ts.map +1 -0
  224. package/dist/editor/PuckEditorCore.client.js +306 -0
  225. package/dist/editor/PuckEditorCore.client.js.map +1 -0
  226. package/dist/editor/components/HeaderActions.d.ts +109 -0
  227. package/dist/editor/components/HeaderActions.d.ts.map +1 -0
  228. package/dist/editor/components/HeaderActions.js +254 -0
  229. package/dist/editor/components/HeaderActions.js.map +1 -0
  230. package/dist/editor/components/IframeWrapper.d.ts +77 -0
  231. package/dist/editor/components/IframeWrapper.d.ts.map +1 -0
  232. package/dist/editor/components/IframeWrapper.js +257 -0
  233. package/dist/editor/components/IframeWrapper.js.map +1 -0
  234. package/dist/editor/components/LoadingState.d.ts +14 -0
  235. package/dist/editor/components/LoadingState.d.ts.map +1 -0
  236. package/dist/editor/components/LoadingState.js +12 -0
  237. package/dist/editor/components/LoadingState.js.map +1 -0
  238. package/dist/editor/components/PreviewModal.d.ts +54 -0
  239. package/dist/editor/components/PreviewModal.d.ts.map +1 -0
  240. package/dist/editor/components/PreviewModal.js +298 -0
  241. package/dist/editor/components/PreviewModal.js.map +1 -0
  242. package/dist/editor/components/VersionHistory.d.ts +44 -0
  243. package/dist/editor/components/VersionHistory.d.ts.map +1 -0
  244. package/dist/editor/components/VersionHistory.js +308 -0
  245. package/dist/editor/components/VersionHistory.js.map +1 -0
  246. package/dist/editor/hooks/useUnsavedChanges.d.ts +27 -0
  247. package/dist/editor/hooks/useUnsavedChanges.d.ts.map +1 -0
  248. package/dist/editor/hooks/useUnsavedChanges.js +55 -0
  249. package/dist/editor/hooks/useUnsavedChanges.js.map +1 -0
  250. package/dist/editor/index.d.ts +16 -756
  251. package/dist/editor/index.d.ts.map +1 -0
  252. package/dist/editor/index.js +49 -4625
  253. package/dist/editor/index.js.map +1 -0
  254. package/dist/editor/plugins/index.d.ts +12 -0
  255. package/dist/editor/plugins/index.d.ts.map +1 -0
  256. package/dist/editor/plugins/index.js +12 -0
  257. package/dist/editor/plugins/index.js.map +1 -0
  258. package/dist/endpoints/index.d.ts +46 -0
  259. package/dist/endpoints/index.d.ts.map +1 -0
  260. package/dist/endpoints/index.js +204 -0
  261. package/dist/endpoints/index.js.map +1 -0
  262. package/dist/exports/client.d.ts +19 -0
  263. package/dist/exports/client.d.ts.map +1 -0
  264. package/dist/exports/client.js +21 -0
  265. package/dist/exports/client.js.map +1 -0
  266. package/dist/exports/rsc.d.ts +19 -0
  267. package/dist/exports/rsc.d.ts.map +1 -0
  268. package/dist/exports/rsc.js +19 -0
  269. package/dist/exports/rsc.js.map +1 -0
  270. package/dist/fields/AlignmentField.d.ts +36 -0
  271. package/dist/fields/AlignmentField.d.ts.map +1 -0
  272. package/dist/fields/AlignmentField.js +120 -0
  273. package/dist/fields/AlignmentField.js.map +1 -0
  274. package/dist/fields/AnimationField.d.ts +44 -0
  275. package/dist/fields/AnimationField.d.ts.map +1 -0
  276. package/dist/fields/AnimationField.js +329 -0
  277. package/dist/fields/AnimationField.js.map +1 -0
  278. package/dist/fields/BackgroundField.d.ts +40 -0
  279. package/dist/fields/BackgroundField.d.ts.map +1 -0
  280. package/dist/fields/BackgroundField.js +413 -0
  281. package/dist/fields/BackgroundField.js.map +1 -0
  282. package/dist/fields/BorderField.d.ts +29 -0
  283. package/dist/fields/BorderField.d.ts.map +1 -0
  284. package/dist/fields/BorderField.js +264 -0
  285. package/dist/fields/BorderField.js.map +1 -0
  286. package/dist/fields/ColorPickerField.d.ts +43 -0
  287. package/dist/fields/ColorPickerField.d.ts.map +1 -0
  288. package/dist/fields/ColorPickerField.js +285 -0
  289. package/dist/fields/ColorPickerField.js.map +1 -0
  290. package/dist/fields/DimensionsField.d.ts +43 -0
  291. package/dist/fields/DimensionsField.d.ts.map +1 -0
  292. package/dist/fields/DimensionsField.js +532 -0
  293. package/dist/fields/DimensionsField.js.map +1 -0
  294. package/dist/fields/FlexAlignmentField.d.ts +61 -0
  295. package/dist/fields/FlexAlignmentField.d.ts.map +1 -0
  296. package/dist/fields/FlexAlignmentField.js +166 -0
  297. package/dist/fields/FlexAlignmentField.js.map +1 -0
  298. package/dist/fields/FolderPickerField.d.ts +17 -0
  299. package/dist/fields/FolderPickerField.d.ts.map +1 -0
  300. package/dist/fields/FolderPickerField.js +282 -0
  301. package/dist/fields/FolderPickerField.js.map +1 -0
  302. package/dist/fields/GradientEditor.d.ts +22 -0
  303. package/dist/fields/GradientEditor.d.ts.map +1 -0
  304. package/dist/fields/GradientEditor.js +322 -0
  305. package/dist/fields/GradientEditor.js.map +1 -0
  306. package/dist/fields/LockedField.d.ts +67 -0
  307. package/dist/fields/LockedField.d.ts.map +1 -0
  308. package/dist/fields/LockedField.js +170 -0
  309. package/dist/fields/LockedField.js.map +1 -0
  310. package/dist/fields/MarginField.d.ts +31 -0
  311. package/dist/fields/MarginField.d.ts.map +1 -0
  312. package/dist/fields/MarginField.js +233 -0
  313. package/dist/fields/MarginField.js.map +1 -0
  314. package/dist/fields/MediaField.d.ts +33 -0
  315. package/dist/fields/MediaField.d.ts.map +1 -0
  316. package/dist/fields/MediaField.js +677 -0
  317. package/dist/fields/MediaField.js.map +1 -0
  318. package/dist/fields/PaddingField.d.ts +29 -0
  319. package/dist/fields/PaddingField.d.ts.map +1 -0
  320. package/dist/fields/PaddingField.js +232 -0
  321. package/dist/fields/PaddingField.js.map +1 -0
  322. package/dist/fields/PageSegmentField.d.ts +17 -0
  323. package/dist/fields/PageSegmentField.d.ts.map +1 -0
  324. package/dist/fields/PageSegmentField.js +92 -0
  325. package/dist/fields/PageSegmentField.js.map +1 -0
  326. package/dist/fields/ResetField.d.ts +27 -0
  327. package/dist/fields/ResetField.d.ts.map +1 -0
  328. package/dist/fields/ResetField.js +122 -0
  329. package/dist/fields/ResetField.js.map +1 -0
  330. package/dist/fields/ResponsiveField.d.ts +38 -0
  331. package/dist/fields/ResponsiveField.d.ts.map +1 -0
  332. package/dist/fields/ResponsiveField.js +275 -0
  333. package/dist/fields/ResponsiveField.js.map +1 -0
  334. package/dist/fields/ResponsiveVisibilityField.d.ts +34 -0
  335. package/dist/fields/ResponsiveVisibilityField.d.ts.map +1 -0
  336. package/dist/fields/ResponsiveVisibilityField.js +145 -0
  337. package/dist/fields/ResponsiveVisibilityField.js.map +1 -0
  338. package/dist/fields/SizeField.d.ts +54 -0
  339. package/dist/fields/SizeField.d.ts.map +1 -0
  340. package/dist/fields/SizeField.js +255 -0
  341. package/dist/fields/SizeField.js.map +1 -0
  342. package/dist/fields/SlugPreviewField.d.ts +16 -0
  343. package/dist/fields/SlugPreviewField.d.ts.map +1 -0
  344. package/dist/fields/SlugPreviewField.js +49 -0
  345. package/dist/fields/SlugPreviewField.js.map +1 -0
  346. package/dist/fields/TemplateField.d.ts +31 -0
  347. package/dist/fields/TemplateField.d.ts.map +1 -0
  348. package/dist/fields/TemplateField.js +428 -0
  349. package/dist/fields/TemplateField.js.map +1 -0
  350. package/dist/fields/TiptapField.d.ts +40 -0
  351. package/dist/fields/TiptapField.d.ts.map +1 -0
  352. package/dist/fields/TiptapField.js +857 -0
  353. package/dist/fields/TiptapField.js.map +1 -0
  354. package/dist/fields/TiptapModal.d.ts +10 -0
  355. package/dist/fields/TiptapModal.d.ts.map +1 -0
  356. package/dist/fields/TiptapModal.js +114 -0
  357. package/dist/fields/TiptapModal.js.map +1 -0
  358. package/dist/fields/TiptapModalField.d.ts +23 -0
  359. package/dist/fields/TiptapModalField.d.ts.map +1 -0
  360. package/dist/fields/TiptapModalField.js +55 -0
  361. package/dist/fields/TiptapModalField.js.map +1 -0
  362. package/dist/fields/TransformField.d.ts +31 -0
  363. package/dist/fields/TransformField.d.ts.map +1 -0
  364. package/dist/fields/TransformField.js +384 -0
  365. package/dist/fields/TransformField.js.map +1 -0
  366. package/dist/fields/VerticalAlignmentField.d.ts +35 -0
  367. package/dist/fields/VerticalAlignmentField.d.ts.map +1 -0
  368. package/dist/fields/VerticalAlignmentField.js +120 -0
  369. package/dist/fields/VerticalAlignmentField.js.map +1 -0
  370. package/dist/fields/WidthField.d.ts +28 -0
  371. package/dist/fields/WidthField.d.ts.map +1 -0
  372. package/dist/fields/WidthField.js +339 -0
  373. package/dist/fields/WidthField.js.map +1 -0
  374. package/dist/fields/index.d.ts +44 -559
  375. package/dist/fields/index.d.ts.map +1 -0
  376. package/dist/fields/index.js +91 -7704
  377. package/dist/fields/index.js.map +1 -0
  378. package/dist/fields/richtext-output.css +219 -0
  379. package/dist/{shared-X9UpCJKW.d.mts → fields/shared.d.ts} +111 -132
  380. package/dist/fields/shared.d.ts.map +1 -0
  381. package/dist/fields/shared.js +1542 -0
  382. package/dist/fields/shared.js.map +1 -0
  383. package/dist/fields/{index.css → tiptap-styles.css} +75 -166
  384. package/dist/hooks/index.d.ts +8 -0
  385. package/dist/hooks/index.d.ts.map +1 -0
  386. package/dist/hooks/index.js +8 -0
  387. package/dist/hooks/index.js.map +1 -0
  388. package/dist/hooks/useResponsiveStyles.d.ts +51 -0
  389. package/dist/hooks/useResponsiveStyles.d.ts.map +1 -0
  390. package/dist/hooks/useResponsiveStyles.js +149 -0
  391. package/dist/hooks/useResponsiveStyles.js.map +1 -0
  392. package/dist/hooks/useScrollAnimation.d.ts +56 -0
  393. package/dist/hooks/useScrollAnimation.d.ts.map +1 -0
  394. package/dist/hooks/useScrollAnimation.js +116 -0
  395. package/dist/hooks/useScrollAnimation.js.map +1 -0
  396. package/dist/index.d.ts +66 -6
  397. package/dist/index.d.ts.map +1 -0
  398. package/dist/index.js +67 -568
  399. package/dist/index.js.map +1 -0
  400. package/dist/layouts/LayoutWrapper.d.ts +33 -0
  401. package/dist/layouts/LayoutWrapper.d.ts.map +1 -0
  402. package/dist/layouts/LayoutWrapper.js +112 -0
  403. package/dist/layouts/LayoutWrapper.js.map +1 -0
  404. package/dist/layouts/defaults.d.ts +40 -0
  405. package/dist/layouts/defaults.d.ts.map +1 -0
  406. package/dist/layouts/defaults.js +106 -0
  407. package/dist/layouts/defaults.js.map +1 -0
  408. package/dist/layouts/index.d.ts +27 -94
  409. package/dist/layouts/index.d.ts.map +1 -0
  410. package/dist/layouts/index.js +30 -393
  411. package/dist/layouts/index.js.map +1 -0
  412. package/dist/{types-D7D3rZ1J.d.ts → layouts/types.d.ts} +8 -11
  413. package/dist/layouts/types.d.ts.map +1 -0
  414. package/dist/layouts/types.js +7 -0
  415. package/dist/layouts/types.js.map +1 -0
  416. package/dist/layouts/utils.d.ts +42 -0
  417. package/dist/layouts/utils.d.ts.map +1 -0
  418. package/dist/layouts/utils.js +83 -0
  419. package/dist/layouts/utils.js.map +1 -0
  420. package/dist/plugin/collections/Pages.d.ts +8 -0
  421. package/dist/plugin/collections/Pages.d.ts.map +1 -0
  422. package/dist/plugin/collections/Pages.js +117 -0
  423. package/dist/plugin/collections/Pages.js.map +1 -0
  424. package/dist/plugin/fields/index.d.ts +153 -0
  425. package/dist/plugin/fields/index.d.ts.map +1 -0
  426. package/dist/plugin/fields/index.js +364 -0
  427. package/dist/plugin/fields/index.js.map +1 -0
  428. package/dist/plugin/fields/types.d.ts +108 -0
  429. package/dist/plugin/fields/types.d.ts.map +1 -0
  430. package/dist/plugin/fields/types.js +7 -0
  431. package/dist/plugin/fields/types.js.map +1 -0
  432. package/dist/plugin/index.d.ts +13 -255
  433. package/dist/plugin/index.d.ts.map +1 -0
  434. package/dist/plugin/index.js +276 -553
  435. package/dist/plugin/index.js.map +1 -0
  436. package/dist/render/HybridPageRenderer.d.ts +85 -0
  437. package/dist/render/HybridPageRenderer.d.ts.map +1 -0
  438. package/dist/render/HybridPageRenderer.js +29 -0
  439. package/dist/render/HybridPageRenderer.js.map +1 -0
  440. package/dist/render/PageRenderer.d.ts +51 -0
  441. package/dist/render/PageRenderer.d.ts.map +1 -0
  442. package/dist/render/PageRenderer.js +61 -0
  443. package/dist/render/PageRenderer.js.map +1 -0
  444. package/dist/render/PuckEditor.client.d.ts +66 -0
  445. package/dist/render/PuckEditor.client.d.ts.map +1 -0
  446. package/dist/render/PuckEditor.client.js +66 -0
  447. package/dist/render/PuckEditor.client.js.map +1 -0
  448. package/dist/render/index.d.ts +8 -106
  449. package/dist/render/index.d.ts.map +1 -0
  450. package/dist/render/index.js +10 -2253
  451. package/dist/render/index.js.map +1 -0
  452. package/dist/theme/context.d.ts +59 -0
  453. package/dist/theme/context.d.ts.map +1 -0
  454. package/dist/theme/context.js +73 -0
  455. package/dist/theme/context.js.map +1 -0
  456. package/dist/theme/defaults.d.ts +39 -0
  457. package/dist/theme/defaults.d.ts.map +1 -0
  458. package/dist/theme/defaults.js +72 -0
  459. package/dist/theme/defaults.js.map +1 -0
  460. package/dist/theme/example.d.ts +30 -0
  461. package/dist/theme/example.d.ts.map +1 -0
  462. package/dist/theme/example.js +89 -0
  463. package/dist/theme/example.js.map +1 -0
  464. package/dist/theme/index.d.ts +17 -140
  465. package/dist/theme/index.d.ts.map +1 -0
  466. package/dist/theme/index.js +34 -200
  467. package/dist/theme/index.js.map +1 -0
  468. package/dist/{types-_6MvjyKv.d.ts → theme/types.d.ts} +8 -9
  469. package/dist/theme/types.d.ts.map +1 -0
  470. package/dist/theme/types.js +9 -0
  471. package/dist/theme/types.js.map +1 -0
  472. package/dist/theme/utils.d.ts +30 -0
  473. package/dist/theme/utils.d.ts.map +1 -0
  474. package/dist/theme/utils.js +84 -0
  475. package/dist/theme/utils.js.map +1 -0
  476. package/dist/{index-CQu6SzDg.d.mts → types/index.d.ts} +120 -115
  477. package/dist/types/index.d.ts.map +1 -0
  478. package/dist/types/index.js +2 -0
  479. package/dist/types/index.js.map +1 -0
  480. package/dist/utils/index.d.ts +23 -257
  481. package/dist/utils/index.d.ts.map +1 -0
  482. package/dist/utils/index.js +56 -425
  483. package/dist/utils/index.js.map +1 -0
  484. package/dist/utils/{index.d.mts → migration.d.ts} +16 -112
  485. package/dist/utils/migration.d.ts.map +1 -0
  486. package/dist/utils/migration.js +309 -0
  487. package/dist/utils/migration.js.map +1 -0
  488. package/dist/utils/validation.d.ts +89 -0
  489. package/dist/utils/validation.d.ts.map +1 -0
  490. package/dist/utils/validation.js +247 -0
  491. package/dist/utils/validation.js.map +1 -0
  492. package/dist/views/PuckConfigContext.d.ts +71 -0
  493. package/dist/views/PuckConfigContext.d.ts.map +1 -0
  494. package/dist/views/PuckConfigContext.js +45 -0
  495. package/dist/views/PuckConfigContext.js.map +1 -0
  496. package/dist/views/PuckEditorClient.d.ts +73 -0
  497. package/dist/views/PuckEditorClient.d.ts.map +1 -0
  498. package/dist/views/PuckEditorClient.js +130 -0
  499. package/dist/views/PuckEditorClient.js.map +1 -0
  500. package/dist/views/PuckEditorView.d.ts +19 -0
  501. package/dist/views/PuckEditorView.d.ts.map +1 -0
  502. package/dist/views/PuckEditorView.js +106 -0
  503. package/dist/views/PuckEditorView.js.map +1 -0
  504. package/dist/views/index.d.ts +10 -0
  505. package/dist/views/index.d.ts.map +1 -0
  506. package/dist/views/index.js +10 -0
  507. package/dist/views/index.js.map +1 -0
  508. package/package.json +51 -74
  509. package/dist/AccordionClient.d.mts +0 -24
  510. package/dist/AccordionClient.d.ts +0 -24
  511. package/dist/AccordionClient.js +0 -786
  512. package/dist/AccordionClient.mjs +0 -784
  513. package/dist/AnimatedWrapper.d.mts +0 -30
  514. package/dist/AnimatedWrapper.d.ts +0 -30
  515. package/dist/AnimatedWrapper.js +0 -379
  516. package/dist/AnimatedWrapper.mjs +0 -377
  517. package/dist/admin/client.d.mts +0 -108
  518. package/dist/admin/client.mjs +0 -173
  519. package/dist/admin/index.d.mts +0 -157
  520. package/dist/admin/index.mjs +0 -29
  521. package/dist/api/index.d.mts +0 -460
  522. package/dist/api/index.mjs +0 -578
  523. package/dist/components/index.css +0 -339
  524. package/dist/components/index.d.mts +0 -219
  525. package/dist/components/index.mjs +0 -9216
  526. package/dist/config/config.editor.css +0 -339
  527. package/dist/config/config.editor.d.mts +0 -153
  528. package/dist/config/config.editor.mjs +0 -9445
  529. package/dist/config/index.d.mts +0 -68
  530. package/dist/config/index.mjs +0 -2099
  531. package/dist/editor/index.d.mts +0 -784
  532. package/dist/editor/index.mjs +0 -4592
  533. package/dist/fields/index.d.mts +0 -600
  534. package/dist/fields/index.mjs +0 -7588
  535. package/dist/index-CoUQnyC3.d.ts +0 -327
  536. package/dist/index.d.mts +0 -6
  537. package/dist/index.mjs +0 -555
  538. package/dist/layouts/index.d.mts +0 -96
  539. package/dist/layouts/index.mjs +0 -378
  540. package/dist/plugin/index.d.mts +0 -289
  541. package/dist/plugin/index.mjs +0 -555
  542. package/dist/render/index.d.mts +0 -109
  543. package/dist/render/index.mjs +0 -2231
  544. package/dist/shared-X9UpCJKW.d.ts +0 -548
  545. package/dist/theme/index.d.mts +0 -155
  546. package/dist/theme/index.mjs +0 -186
  547. package/dist/types-D7D3rZ1J.d.mts +0 -116
  548. package/dist/types-_6MvjyKv.d.mts +0 -104
  549. package/dist/utils/index.mjs +0 -412
  550. package/dist/utils-DaRs9t0J.d.mts +0 -85
  551. package/dist/utils-gAvt0Vhw.d.ts +0 -85
  552. package/examples/README.md +0 -247
  553. package/examples/api/puck/pages/[id]/route.ts +0 -64
  554. package/examples/api/puck/pages/[id]/versions/route.ts +0 -47
  555. package/examples/api/puck/pages/route.ts +0 -45
  556. package/examples/app/(frontend)/page.tsx +0 -94
  557. package/examples/app/(manage)/layout.tsx +0 -31
  558. package/examples/app/[...slug]/page.tsx +0 -101
  559. package/examples/app/pages/[id]/edit/page.tsx +0 -148
  560. package/examples/components/CustomBanner.tsx +0 -368
  561. package/examples/config/custom-config.ts +0 -223
  562. package/examples/config/payload.config.example.ts +0 -64
  563. package/examples/lib/puck-layouts.ts +0 -258
  564. package/examples/lib/puck-theme.ts +0 -94
  565. package/examples/styles/puck-theme.css +0 -171
package/README.md CHANGED
@@ -9,17 +9,15 @@ A PayloadCMS plugin for integrating [Puck](https://puckeditor.com) visual page b
9
9
  - [Installation](#installation)
10
10
  - [Quick Start](#quick-start)
11
11
  - [Styling Setup](#styling-setup)
12
- - [Setup Checklist](#setup-checklist)
13
12
  - [Core Concepts](#core-concepts)
14
13
  - [Components](#components)
15
- - [Configuration](#configuration)
16
14
  - [Custom Fields](#custom-fields)
15
+ - [Building Custom Components](#building-custom-components)
17
16
  - [Theming](#theming)
18
17
  - [Layouts](#layouts)
19
- - [API Routes](#api-routes)
20
- - [SEO Fields](#seo-fields)
21
- - [Plugin Options](#plugin-options)
18
+ - [Page-Tree Integration](#page-tree-integration)
22
19
  - [Hybrid Integration](#hybrid-integration)
20
+ - [Advanced Configuration](#advanced-configuration)
23
21
  - [License](#license)
24
22
 
25
23
  ---
@@ -32,65 +30,24 @@ A PayloadCMS plugin for integrating [Puck](https://puckeditor.com) visual page b
32
30
  |------------|---------|---------|
33
31
  | `@measured/puck` | >= 0.20.0 | Visual editor core |
34
32
  | `payload` | >= 3.0.0 | CMS backend |
35
- | `next` | >= 15.4.8 | React framework |
33
+ | `@payloadcms/next` | >= 3.0.0 | Payload Next.js integration |
34
+ | `next` | >= 14.0.0 | React framework |
36
35
  | `react` | >= 18.0.0 | UI library |
37
36
  | `@tailwindcss/typography` | >= 0.5.0 | RichText component styling |
38
37
 
39
- > **⚠️ Don't skip the styling setup!** After Quick Start, you must configure Tailwind to scan this package. See [Styling Setup](#styling-setup).
40
-
41
38
  ### Install
42
39
 
43
40
  ```bash
44
41
  pnpm add @delmaredigital/payload-puck @measured/puck
45
42
  ```
46
43
 
47
- Or install from GitHub:
48
-
49
- ```bash
50
- pnpm add github:delmaredigital/payload-puck#main @measured/puck
51
- ```
52
-
53
44
  ---
54
45
 
55
46
  ## Quick Start
56
47
 
57
- > **📋 Important:** After completing these steps, continue to [Styling Setup](#styling-setup) and verify with the [Setup Checklist](#setup-checklist).
58
-
59
- <details>
60
- <summary><strong>Option A: Copy Boilerplate (Fastest)</strong></summary>
61
-
62
- The package includes ready-to-use example files:
63
-
64
- ```bash
65
- # Copy API routes
66
- cp -r node_modules/@delmaredigital/payload-puck/examples/api/puck src/app/api/
67
-
68
- # Copy editor layout (REQUIRED - imports Tailwind CSS) and page
69
- mkdir -p src/app/\(manage\)/pages/\[id\]/edit
70
- cp node_modules/@delmaredigital/payload-puck/examples/app/\(manage\)/layout.tsx src/app/\(manage\)/
71
- cp node_modules/@delmaredigital/payload-puck/examples/app/pages/\[id\]/edit/page.tsx src/app/\(manage\)/pages/\[id\]/edit/
72
-
73
- # Copy frontend routes (homepage + dynamic pages)
74
- mkdir -p src/app/\(frontend\)
75
- cp node_modules/@delmaredigital/payload-puck/examples/app/\(frontend\)/page.tsx src/app/\(frontend\)/
76
- mkdir -p src/app/\(frontend\)/\[...slug\]
77
- cp node_modules/@delmaredigital/payload-puck/examples/app/\[...slug\]/page.tsx src/app/\(frontend\)/\[...slug\]/
78
-
79
- # Copy theme config (optional)
80
- mkdir -p src/lib
81
- cp node_modules/@delmaredigital/payload-puck/examples/lib/puck-theme.ts src/lib/
82
- ```
83
-
84
- > **Important:** Update the CSS import path in `src/app/(manage)/layout.tsx` to match your project's globals.css location.
85
-
86
- See `examples/README.md` for detailed customization instructions.
87
-
88
- </details>
89
-
90
- <details>
91
- <summary><strong>Option B: Manual Setup</strong></summary>
48
+ The plugin integrates directly into Payload's admin UI with minimal configuration. API endpoints and admin views are registered automatically.
92
49
 
93
- #### Step 1: Add the Plugin
50
+ ### Step 1: Add the Plugin
94
51
 
95
52
  ```typescript
96
53
  // payload.config.ts
@@ -107,254 +64,150 @@ export default buildConfig({
107
64
  })
108
65
  ```
109
66
 
110
- #### Step 2: Create API Routes
111
-
112
- ```typescript
113
- // app/api/puck/pages/route.ts
114
- import { createPuckApiRoutes } from '@delmaredigital/payload-puck/api'
115
- import { getPayload } from 'payload'
116
- import config from '@payload-config'
117
- import { headers } from 'next/headers'
118
-
119
- export const { GET, POST } = createPuckApiRoutes({
120
- collection: 'pages',
121
- payloadConfig: config,
122
- auth: {
123
- authenticate: async (request) => {
124
- const payload = await getPayload({ config })
125
- const { user } = await payload.auth({ headers: await headers() })
126
- if (!user) return { authenticated: false }
127
- return { authenticated: true, user: { id: user.id } }
128
- },
129
- },
130
- })
131
- ```
132
-
133
- ```typescript
134
- // app/api/puck/pages/[id]/route.ts
135
- import { createPuckApiRoutesWithId } from '@delmaredigital/payload-puck/api'
136
- import config from '@payload-config'
67
+ This automatically:
68
+ - Creates a `pages` collection with Puck fields (or adds fields to your existing collection)
69
+ - Registers API endpoints at `/api/puck/:collection`
70
+ - Adds the Puck editor view at `/admin/puck-editor/:collection/:id`
71
+ - Adds "Edit with Puck" buttons to the admin UI
137
72
 
138
- export const { GET, PATCH, DELETE } = createPuckApiRoutesWithId({
139
- collection: 'pages',
140
- payloadConfig: config,
141
- auth: {
142
- authenticate: async (request) => {
143
- // Same auth logic as above
144
- },
145
- },
146
- })
147
- ```
73
+ ### Step 2: Provide Puck Configuration
148
74
 
149
- #### Step 3: Create the Editor Layout & Page
150
-
151
- First, create a layout that imports your Tailwind CSS:
152
-
153
- ```typescript
154
- // app/(manage)/layout.tsx
155
- import '@/app/(frontend)/globals.css' // Adjust path to your CSS
156
-
157
- export const metadata = {
158
- title: 'Puck Editor',
159
- description: 'Visual page editor',
160
- }
161
-
162
- export default function ManageLayout({ children }: { children: React.ReactNode }) {
163
- return (
164
- // data-theme may be required if your CSS hides content until theme is set
165
- <html lang="en" data-theme="light">
166
- <body>{children}</body>
167
- </html>
168
- )
169
- }
170
- ```
171
-
172
- Then create the editor page:
75
+ Wrap your app with `PuckConfigProvider` to supply the Puck configuration. This is required because Puck configs contain React components that cannot be serialized from server to client.
173
76
 
174
77
  ```typescript
175
- // app/(manage)/pages/[id]/edit/page.tsx
176
- 'use client'
177
-
178
- import { PuckEditorView } from '@delmaredigital/payload-puck/editor'
78
+ // app/(app)/layout.tsx (covers both admin and frontend)
79
+ import { PuckConfigProvider } from '@delmaredigital/payload-puck/client'
179
80
  import { editorConfig } from '@delmaredigital/payload-puck/config/editor'
180
81
 
181
- export default function EditorPage() {
82
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
182
83
  return (
183
- <PuckEditorView
184
- config={editorConfig}
185
- collectionSlug="pages"
186
- apiBasePath="/api/puck"
187
- backUrl="/admin/collections/pages"
188
- previewUrl={(slug) => `/${slug}`}
189
- />
84
+ <html lang="en">
85
+ <body>
86
+ <PuckConfigProvider config={editorConfig}>
87
+ {children}
88
+ </PuckConfigProvider>
89
+ </body>
90
+ </html>
190
91
  )
191
92
  }
192
93
  ```
193
94
 
194
- The editor includes:
195
- - **Save Draft** - Saves without publishing
196
- - **Publish** - Publishes the page
197
- - **Draft/Published badge** - Shows current document status
198
- - **Unsaved changes warning** - Prevents accidental navigation
199
- - **Heading Analyzer** - WCAG-compliant heading outline visualization (enabled by default)
200
-
201
- **Heading Analyzer Plugin**
95
+ ### Step 3: Create a Frontend Route
202
96
 
203
- The heading analyzer plugin is included by default and displays a heading outline in the editor sidebar. It helps identify accessibility issues like skipped heading levels (e.g., jumping from H1 to H3).
97
+ The plugin can't auto-create frontend routes (Next.js App Router is file-based), but here's copy-paste ready code:
204
98
 
205
- To add additional plugins or disable the default:
206
-
207
- ```typescript
208
- // Add additional plugins (headingAnalyzer is still included)
209
- <PuckEditorView
210
- plugins={[myCustomPlugin]}
211
- // ...
212
- />
213
-
214
- // Disable all default plugins
215
- <PuckEditorView
216
- plugins={false}
217
- // ...
218
- />
219
- ```
220
-
221
- #### Step 4: Create a Frontend Route
99
+ <details>
100
+ <summary><strong>📄 app/(frontend)/[[...slug]]/page.tsx</strong> (click to expand)</summary>
222
101
 
223
102
  ```typescript
224
- // app/(frontend)/[...slug]/page.tsx
225
103
  import { getPayload } from 'payload'
226
104
  import config from '@payload-config'
227
105
  import { PageRenderer } from '@delmaredigital/payload-puck/render'
228
106
  import { baseConfig } from '@delmaredigital/payload-puck/config'
229
107
  import { notFound } from 'next/navigation'
108
+ import type { Metadata } from 'next'
230
109
 
231
- export default async function Page({ params }: { params: Promise<{ slug: string[] }> }) {
232
- const { slug } = await params
110
+ // Fetch page by slug (or homepage if no slug)
111
+ async function getPage(slug?: string[]) {
233
112
  const payload = await getPayload({ config })
113
+ const slugPath = slug?.join('/') || ''
234
114
 
115
+ // Try to find by slug, or find homepage
235
116
  const { docs } = await payload.find({
236
117
  collection: 'pages',
237
- where: { slug: { equals: slug.join('/') } },
118
+ where: slugPath
119
+ ? { slug: { equals: slugPath } }
120
+ : { isHomepage: { equals: true } },
238
121
  limit: 1,
239
122
  })
240
123
 
241
- const page = docs[0]
124
+ return docs[0] || null
125
+ }
126
+
127
+ // Generate metadata from page SEO fields
128
+ export async function generateMetadata({
129
+ params
130
+ }: {
131
+ params: Promise<{ slug?: string[] }>
132
+ }): Promise<Metadata> {
133
+ const { slug } = await params
134
+ const page = await getPage(slug)
135
+
136
+ if (!page) return {}
137
+
138
+ return {
139
+ title: page.meta?.title || page.title,
140
+ description: page.meta?.description,
141
+ }
142
+ }
143
+
144
+ // Render the page
145
+ export default async function Page({
146
+ params
147
+ }: {
148
+ params: Promise<{ slug?: string[] }>
149
+ }) {
150
+ const { slug } = await params
151
+ const page = await getPage(slug)
152
+
242
153
  if (!page) notFound()
243
154
 
244
155
  return <PageRenderer config={baseConfig} data={page.puckData} />
245
156
  }
246
157
  ```
247
158
 
248
- #### Step 5: Enable Version History (Optional)
249
-
250
- ```typescript
251
- // app/api/puck/pages/[id]/versions/route.ts
252
- import { createPuckApiRoutesVersions } from '@delmaredigital/payload-puck/api'
253
- import config from '@payload-config'
159
+ </details>
254
160
 
255
- export const { GET, POST } = createPuckApiRoutesVersions({
256
- collection: 'pages',
257
- payloadConfig: config,
258
- auth: {
259
- authenticate: async (request) => {
260
- // Same auth logic as your main routes
261
- },
262
- },
263
- })
264
- ```
161
+ > **Note:** The `[[...slug]]` pattern with double brackets makes the slug optional, so this handles both `/` (homepage) and `/any/path`.
265
162
 
266
- The History button automatically appears when this route exists.
163
+ ### That's It!
267
164
 
268
- </details>
165
+ - The plugin registers the editor view at `/admin/puck-editor/:collection/:id`
166
+ - "Edit with Puck" buttons appear in the collection list view
167
+ - The editor runs inside Payload's admin UI with full navigation
168
+ - API endpoints are handled automatically via Payload's endpoint system
269
169
 
270
170
  ---
271
171
 
272
172
  ## Styling Setup
273
173
 
274
- > **⚠️ This section is critical.** Without proper styling setup, components will render with broken or missing styles.
174
+ ### Tailwind Typography (Required)
275
175
 
276
- <details>
277
- <summary><strong>⚠️ Tailwind Typography</strong> — Required for RichText component</summary>
176
+ > Required only if using the RichText component.
278
177
 
279
- The RichText component uses the `prose` class from `@tailwindcss/typography`. **Without this, rich text content will be unstyled** — no proper heading sizes, list styles, blockquote formatting, etc.
178
+ The RichText component uses `@tailwindcss/typography`:
280
179
 
281
180
  ```bash
282
181
  pnpm add @tailwindcss/typography
283
182
  ```
284
183
 
285
- **Tailwind v4** — Add the `@plugin` directive to your main CSS file:
286
-
184
+ **Tailwind v4:**
287
185
  ```css
288
186
  @import "tailwindcss";
289
187
  @plugin "@tailwindcss/typography";
290
188
  ```
291
189
 
292
- **Tailwind v3** — Add to your Tailwind config:
293
-
190
+ **Tailwind v3:**
294
191
  ```javascript
295
192
  // tailwind.config.js
296
193
  module.exports = {
297
- plugins: [
298
- require('@tailwindcss/typography'),
299
- ],
194
+ plugins: [require('@tailwindcss/typography')],
300
195
  }
301
196
  ```
302
197
 
303
- </details>
304
-
305
- <details>
306
- <summary><strong>⚠️ Tailwind Source Scanning</strong> — Required for component styles</summary>
307
-
308
- **Without this, Tailwind won't include the plugin's CSS classes in your build.** Components will have missing styles.
309
-
310
- The `@source` directive (v4) or `content` path (v3) tells Tailwind to scan the package for class names.
198
+ ### Package Scanning (Required)
311
199
 
312
- **Tailwind v4**
200
+ > Required if your project uses Tailwind CSS. Ensures component classes are included in your build.
313
201
 
314
- The path is relative to your CSS file's location and must resolve to your project's `node_modules`:
315
-
316
- | CSS file location | `@source` path |
317
- |-------------------|----------------|
318
- | `globals.css` (root) | `./node_modules/@delmaredigital/payload-puck` |
319
- | `src/globals.css` | `../node_modules/@delmaredigital/payload-puck` |
320
- | `src/styles/tailwind.css` | `../../node_modules/@delmaredigital/payload-puck` |
202
+ Tell Tailwind to scan the plugin's components:
321
203
 
204
+ **Tailwind v4:**
322
205
  ```css
323
- @import "tailwindcss";
324
- @plugin "@tailwindcss/typography";
325
-
326
- /* Adjust path based on your CSS file location */
206
+ /* Adjust path relative to your CSS file */
327
207
  @source "../node_modules/@delmaredigital/payload-puck";
328
-
329
- @theme inline {
330
- --color-background: var(--background);
331
- --color-foreground: var(--foreground);
332
- --color-primary: var(--primary);
333
- --color-primary-foreground: var(--primary-foreground);
334
- --color-secondary: var(--secondary);
335
- --color-secondary-foreground: var(--secondary-foreground);
336
- --color-muted: var(--muted);
337
- --color-muted-foreground: var(--muted-foreground);
338
- --color-accent: var(--accent);
339
- --color-accent-foreground: var(--accent-foreground);
340
- --color-destructive: var(--destructive);
341
- --color-destructive-foreground: var(--destructive-foreground);
342
- --color-border: var(--border);
343
- --color-input: var(--input);
344
- --color-ring: var(--ring);
345
- --color-popover: var(--popover);
346
- --color-popover-foreground: var(--popover-foreground);
347
- --color-card: var(--card);
348
- --color-card-foreground: var(--card-foreground);
349
- --radius-sm: calc(var(--radius) - 4px);
350
- --radius-md: calc(var(--radius) - 2px);
351
- --radius-lg: var(--radius);
352
- --radius-xl: calc(var(--radius) + 4px);
353
- }
354
208
  ```
355
209
 
356
- **Tailwind v3**
357
-
210
+ **Tailwind v3:**
358
211
  ```javascript
359
212
  // tailwind.config.js
360
213
  module.exports = {
@@ -365,118 +218,59 @@ module.exports = {
365
218
  }
366
219
  ```
367
220
 
368
- </details>
369
-
370
- <details>
371
- <summary><strong>⚠️ Theme CSS Variables</strong> — Required if not using shadcn/ui</summary>
372
-
373
- The field components use [shadcn/ui](https://ui.shadcn.com)-style CSS variables.
374
-
375
- **If you use shadcn/ui:** No action needed — components inherit your existing theme.
221
+ ### Theme CSS Variables (Optional)
376
222
 
377
- **If you don't use shadcn/ui:** Copy the theme boilerplate:
223
+ > Optional - the plugin includes sensible defaults. Define these only to customize colors in rendered content (links, borders, etc).
378
224
 
379
- ```bash
380
- cp node_modules/@delmaredigital/payload-puck/examples/styles/puck-theme.css src/styles/
381
- ```
382
-
383
- Then import it:
225
+ The plugin uses [shadcn/ui](https://ui.shadcn.com)-style CSS variables. If you don't use shadcn/ui and want to customize colors, define these in your CSS:
384
226
 
385
227
  ```css
386
- @import './puck-theme.css';
228
+ :root {
229
+ --background: 0 0% 100%;
230
+ --foreground: 222.2 84% 4.9%;
231
+ --primary: 222.2 47.4% 11.2%;
232
+ --primary-foreground: 210 40% 98%;
233
+ --secondary: 210 40% 96%;
234
+ --secondary-foreground: 222.2 47.4% 11.2%;
235
+ --muted: 210 40% 96%;
236
+ --muted-foreground: 215.4 16.3% 46.9%;
237
+ --accent: 210 40% 96%;
238
+ --accent-foreground: 222.2 47.4% 11.2%;
239
+ --destructive: 0 84.2% 60.2%;
240
+ --destructive-foreground: 210 40% 98%;
241
+ --border: 214.3 31.8% 91.4%;
242
+ --input: 214.3 31.8% 91.4%;
243
+ --ring: 222.2 84% 4.9%;
244
+ --radius: 0.5rem;
245
+ }
387
246
  ```
388
247
 
389
- <details>
390
- <summary>CSS Variable Reference</summary>
391
-
392
- | Variable | Purpose |
393
- |----------|---------|
394
- | `--background` | Page background color |
395
- | `--foreground` | Default text color |
396
- | `--primary` | Primary buttons, active states |
397
- | `--primary-foreground` | Text on primary backgrounds |
398
- | `--secondary` | Secondary buttons |
399
- | `--secondary-foreground` | Text on secondary backgrounds |
400
- | `--muted` | Subtle backgrounds, disabled states |
401
- | `--muted-foreground` | Muted text |
402
- | `--accent` | Hover states |
403
- | `--accent-foreground` | Text on accent backgrounds |
404
- | `--destructive` | Error messages, delete buttons |
405
- | `--destructive-foreground` | Text on destructive backgrounds |
406
- | `--border` | General borders |
407
- | `--input` | Form input borders |
408
- | `--ring` | Focus rings |
409
- | `--popover` | Dropdown/modal backgrounds |
410
- | `--popover-foreground` | Text in popovers |
411
- | `--card` | Card backgrounds |
412
- | `--card-foreground` | Text in cards |
413
- | `--radius` | Base border radius |
414
-
415
- </details>
416
-
417
- </details>
418
-
419
248
  ---
420
249
 
421
- ## Setup Checklist
422
-
423
- Use this checklist to verify your setup is complete.
424
-
425
- ### ✅ Core Setup
426
-
427
- - [ ] Install packages: `@delmaredigital/payload-puck` and `@measured/puck`
428
- - [ ] Add `createPuckPlugin()` to your Payload config
429
- - [ ] Create API routes (`/api/puck/pages` and `/api/puck/pages/[id]`)
430
- - [ ] Create editor route layout that imports Tailwind CSS (see examples)
431
- - [ ] Create the editor page component with `PuckEditorView`
432
- - [ ] Create a frontend route with `PageRenderer`
433
-
434
- ### ⚠️ Styling Setup
435
-
436
- - [ ] Install and configure `@tailwindcss/typography`
437
- - [ ] Add Tailwind `@source` directive (v4) or `content` path (v3)
438
- - [ ] Set up theme CSS variables (if not using shadcn/ui)
439
-
440
- ### ⚙️ Collection Config
441
-
442
- - [ ] Enable `versions: { drafts: true }` on your pages collection
443
-
444
- ### 📦 Optional
445
-
446
- - [ ] Version history API route (`/api/puck/pages/[id]/versions`)
447
- - [ ] Custom theme configuration via `ThemeProvider`
448
- - [ ] Custom layouts with headers/footers
449
- - [ ] Custom components
450
-
451
- ---
452
-
453
- <details>
454
- <summary><strong>Core Concepts</strong> — Server vs Client configs, Draft system</summary>
250
+ ## Core Concepts
455
251
 
456
252
  ### Server vs Client Configuration
457
253
 
458
- The plugin provides two configurations to handle React Server Components:
254
+ The plugin provides two configurations for React Server Components:
459
255
 
460
256
  | Config | Import | Use Case |
461
257
  |--------|--------|----------|
462
258
  | `baseConfig` | `@delmaredigital/payload-puck/config` | Server-safe rendering with `PageRenderer` |
463
- | `editorConfig` | `@delmaredigital/payload-puck/config/editor` | Client-side editing with full TipTap support |
259
+ | `editorConfig` | `@delmaredigital/payload-puck/config/editor` | Client-side editing with full interactivity |
464
260
 
465
261
  ```typescript
466
262
  // Server component - use baseConfig
467
263
  import { baseConfig } from '@delmaredigital/payload-puck/config'
468
264
  <PageRenderer config={baseConfig} data={page.puckData} />
469
265
 
470
- // Client component - use editorConfig
266
+ // PuckConfigProvider - use editorConfig
471
267
  import { editorConfig } from '@delmaredigital/payload-puck/config/editor'
472
- <PuckEditor config={editorConfig} ... />
268
+ <PuckConfigProvider config={editorConfig}>
473
269
  ```
474
270
 
475
271
  ### Draft System
476
272
 
477
- The editor uses Payload's native draft system.
478
-
479
- > **⚠️ Required:** Without `drafts: true`, the Save Draft and Publish buttons won't work correctly.
273
+ The editor uses Payload's native draft system. The plugin automatically enables drafts on the pages collection. You can also enable it manually:
480
274
 
481
275
  ```typescript
482
276
  {
@@ -487,293 +281,49 @@ The editor uses Payload's native draft system.
487
281
  }
488
282
  ```
489
283
 
490
- </details>
491
-
492
284
  ---
493
285
 
494
- <details>
495
- <summary><strong>Components</strong> — Layout, Typography, Media, Interactive</summary>
286
+ ## Components
496
287
 
497
288
  ### Layout
498
289
 
499
- | Component | Description | Responsive Controls |
500
- |-----------|-------------|---------------------|
501
- | **Container** | Content wrapper with max-width and background options | Dimensions, Padding, Margin, Visibility |
502
- | **Flex** | Flexible box layout with direction and alignment | Dimensions, Padding, Margin, Visibility |
503
- | **Grid** | CSS Grid layout with responsive columns | Dimensions, Padding, Margin, Visibility |
504
- | **Section** | Full-width section with slot for nested content | Dimensions, Padding, Margin, Visibility |
505
- | **Spacer** | Vertical/horizontal spacing element | Visibility |
506
- | **Template** | Reusable component arrangements - save and load templates | Dimensions, Padding, Margin, Visibility |
290
+ | Component | Description |
291
+ |-----------|-------------|
292
+ | **Container** | Content wrapper with max-width and background |
293
+ | **Flex** | Flexible box layout with direction and alignment |
294
+ | **Grid** | CSS Grid layout with responsive columns |
295
+ | **Section** | Two-layer: full-bleed section + constrained content area |
296
+ | **Spacer** | Vertical/horizontal spacing element |
297
+ | **Template** | Save/load reusable component arrangements |
507
298
 
508
299
  ### Typography
509
300
 
510
- | Component | Description | Responsive Controls |
511
- |-----------|-------------|---------------------|
512
- | **Heading** | H1-H6 headings with size and alignment options | — |
513
- | **Text** | Paragraph text with styling options | — |
514
- | **RichText** | TipTap-powered WYSIWYG editor | — |
301
+ | Component | Description |
302
+ |-----------|-------------|
303
+ | **Heading** | H1-H6 headings with size and alignment |
304
+ | **Text** | Paragraph text with styling options |
305
+ | **RichText** | TipTap-powered WYSIWYG editor |
515
306
 
516
- > **⚠️ RichText requires `@tailwindcss/typography`** — see [Styling Setup](#styling-setup). Without it, content renders without proper formatting.
307
+ ### Media & Interactive
517
308
 
518
- ### Media
519
-
520
- | Component | Description | Responsive Controls |
521
- |-----------|-------------|---------------------|
522
- | **Image** | Responsive image with alt text and sizing | Visibility |
523
-
524
- ### Interactive
525
-
526
- | Component | Description | Responsive Controls |
527
- |-----------|-------------|---------------------|
528
- | **Button** | Styled button/link with variants | — |
529
- | **Card** | Content card with optional image header | — |
530
- | **Divider** | Horizontal rule with style options | — |
531
- | **Accordion** | Expandable content sections | — |
309
+ | Component | Description |
310
+ |-----------|-------------|
311
+ | **Image** | Responsive image with alt text |
312
+ | **Button** | Styled button/link with variants |
313
+ | **Card** | Content card with optional image |
314
+ | **Divider** | Horizontal rule with styles |
315
+ | **Accordion** | Expandable content sections |
532
316
 
533
317
  ### Responsive Controls
534
318
 
535
- Components with responsive controls allow you to customize their behavior at different breakpoints (mobile, tablet, desktop). Available controls:
536
-
537
- - **Dimensions** - Width, max-width, height constraints per breakpoint
538
- - **Padding** - Inner spacing per breakpoint
539
- - **Margin** - Outer spacing per breakpoint
540
- - **Visibility** - Show/hide components at specific breakpoints
541
-
542
- Breakpoints follow Tailwind CSS conventions:
543
- | Breakpoint | Min Width | Description |
544
- |------------|-----------|-------------|
545
- | base | 0px | Mobile (default) |
546
- | sm | 640px | Small tablets |
547
- | md | 768px | Tablets |
548
- | lg | 1024px | Laptops |
549
- | xl | 1280px | Desktops |
550
-
551
- ### Template Component
552
-
553
- The Template component allows saving groups of components as reusable templates. The plugin automatically creates a `puck-templates` collection in Payload.
554
-
555
- **Saving a template:**
556
- 1. Add a Template component to your page
557
- 2. Add child components inside the Template slot
558
- 3. Click "Save as Template" and give it a name/category
559
-
560
- **Loading a template:**
561
- 1. Add a Template component to your page
562
- 2. Select a saved template from the dropdown
563
- 3. The template's components are loaded into the slot
564
-
565
- </details>
566
-
567
- ---
568
-
569
- <details>
570
- <summary><strong>Configuration</strong> — Merging configs, Custom components</summary>
571
-
572
- ### Merging Custom Components
573
-
574
- ```typescript
575
- import { mergeConfigs } from '@delmaredigital/payload-puck/config'
576
- import { baseConfig } from '@delmaredigital/payload-puck/config'
577
- import { MyCustomComponent } from './components/MyCustomComponent'
578
-
579
- const customConfig = mergeConfigs({
580
- base: baseConfig,
581
- components: {
582
- MyCustomComponent,
583
- },
584
- categories: {
585
- custom: { title: 'Custom', components: ['MyCustomComponent'] },
586
- },
587
- exclude: ['Spacer'], // Optionally remove components
588
- })
589
- ```
590
-
591
- ### Creating Custom Components
592
-
593
- Components need two variants to work across server rendering and the editor:
594
-
595
- | File | Purpose | Used By |
596
- |------|---------|---------|
597
- | `MyComponent.server.tsx` | Server-safe render (no hooks/interactivity) | `baseConfig` → `PageRenderer` |
598
- | `MyComponent.tsx` or `.editor.tsx` | Full interactivity + field definitions | `editorConfig` → `PuckEditor` |
599
-
600
- **Server variant** (`MyComponent.server.tsx`):
601
- - No `'use client'` directive
602
- - No React hooks (`useState`, `useEffect`, etc.)
603
- - No event handlers that require client JS
604
- - **If component has slots**: Must include `fields: { content: { type: 'slot' } }` (Puck needs this to transform slot data into a renderable component)
605
- - Other fields can be omitted (not used in rendering)
606
-
607
- **Editor variant** (`MyComponent.tsx`):
608
- - Can use `'use client'` if needed
609
- - Full interactivity with hooks
610
- - Includes all `fields` for the Puck sidebar
611
-
612
- <details>
613
- <summary><strong>Example: Interactive Component</strong></summary>
614
-
615
- ```tsx
616
- // components/Tabs.server.tsx - Server-safe version
617
- import type { ComponentConfig } from '@measured/puck'
618
-
619
- export interface TabsProps {
620
- items: { title: string; content: string }[]
621
- defaultTab: number
622
- }
623
-
624
- export const TabsConfig: ComponentConfig<TabsProps> = {
625
- label: 'Tabs',
626
- defaultProps: {
627
- items: [{ title: 'Tab 1', content: 'Content 1' }],
628
- defaultTab: 0,
629
- },
630
- // No fields - server version only renders
631
- render: ({ items, defaultTab }) => (
632
- <div>
633
- {/* Render only the default tab statically */}
634
- <div className="flex border-b">
635
- {items.map((item, i) => (
636
- <div key={i} className={i === defaultTab ? 'border-b-2 border-primary' : ''}>
637
- {item.title}
638
- </div>
639
- ))}
640
- </div>
641
- <div>{items[defaultTab]?.content}</div>
642
- </div>
643
- ),
644
- }
645
- ```
646
-
647
- ```tsx
648
- // components/Tabs.tsx - Editor version with interactivity
649
- 'use client'
650
-
651
- import type { ComponentConfig } from '@measured/puck'
652
- import { useState } from 'react'
653
-
654
- export interface TabsProps {
655
- items: { title: string; content: string }[]
656
- defaultTab: number
657
- }
658
-
659
- export const TabsConfig: ComponentConfig<TabsProps> = {
660
- label: 'Tabs',
661
- fields: {
662
- items: {
663
- type: 'array',
664
- label: 'Tabs',
665
- arrayFields: {
666
- title: { type: 'text', label: 'Title' },
667
- content: { type: 'textarea', label: 'Content' },
668
- },
669
- },
670
- defaultTab: { type: 'number', label: 'Default Tab' },
671
- },
672
- defaultProps: {
673
- items: [{ title: 'Tab 1', content: 'Content 1' }],
674
- defaultTab: 0,
675
- },
676
- render: ({ items, defaultTab }) => {
677
- const [activeTab, setActiveTab] = useState(defaultTab)
678
-
679
- return (
680
- <div>
681
- <div className="flex border-b">
682
- {items.map((item, i) => (
683
- <button
684
- key={i}
685
- onClick={() => setActiveTab(i)}
686
- className={i === activeTab ? 'border-b-2 border-primary' : ''}
687
- >
688
- {item.title}
689
- </button>
690
- ))}
691
- </div>
692
- <div>{items[activeTab]?.content}</div>
693
- </div>
694
- )
695
- },
696
- }
697
- ```
698
-
699
- Then register both:
700
- ```tsx
701
- // In your custom baseConfig
702
- import { TabsConfig } from './components/Tabs.server'
703
-
704
- // In your custom editorConfig
705
- import { TabsConfig } from './components/Tabs'
706
- ```
707
- </details>
708
-
709
- <details>
710
- <summary><strong>Example: Component with Slot (nested components)</strong></summary>
711
-
712
- ```tsx
713
- // components/Card.server.tsx - Server-safe version WITH slot field
714
- import type { ComponentConfig } from '@measured/puck'
715
-
716
- export interface CardProps {
717
- content: unknown // Slot for nested components
718
- title: string
719
- }
720
-
721
- export const CardConfig: ComponentConfig<CardProps> = {
722
- label: 'Card',
723
- // CRITICAL: Slot field MUST be defined for Puck to transform data into component
724
- fields: {
725
- content: { type: 'slot' },
726
- },
727
- defaultProps: {
728
- content: [],
729
- title: 'Card Title',
730
- },
731
- render: ({ content: Content, title }) => (
732
- <div className="border rounded-lg p-4">
733
- <h3 className="font-bold mb-2">{title}</h3>
734
- <Content /> {/* Renders nested components */}
735
- </div>
736
- ),
737
- }
738
- ```
739
-
740
- ```tsx
741
- // components/Card.tsx - Editor version with all fields
742
- import type { ComponentConfig } from '@measured/puck'
743
-
744
- export interface CardProps {
745
- content: unknown
746
- title: string
747
- }
748
-
749
- export const CardConfig: ComponentConfig<CardProps> = {
750
- label: 'Card',
751
- fields: {
752
- title: { type: 'text', label: 'Title' },
753
- content: { type: 'slot' },
754
- },
755
- defaultProps: {
756
- content: [],
757
- title: 'Card Title',
758
- },
759
- render: ({ content: Content, title }) => (
760
- <div className="border rounded-lg p-4">
761
- <h3 className="font-bold mb-2">{title}</h3>
762
- <Content />
763
- </div>
764
- ),
765
- }
766
- ```
767
-
768
- **Why slots need the field definition:** Puck stores slot content as an array of component data. The `fields: { content: { type: 'slot' } }` tells Puck to transform this array into a renderable `<Content />` component before passing it to `render()`. Without this, you'll get "Element type is invalid: got array" errors.
769
- </details>
770
-
771
- </details>
319
+ Layout components support per-breakpoint customization:
320
+ - **Dimensions** - Width, max-width, height constraints
321
+ - **Padding/Margin** - Spacing per breakpoint
322
+ - **Visibility** - Show/hide at specific breakpoints
772
323
 
773
324
  ---
774
325
 
775
- <details>
776
- <summary><strong>Custom Fields</strong> — 19 field types with usage examples</summary>
326
+ ## Custom Fields
777
327
 
778
328
  All fields are imported from `@delmaredigital/payload-puck/fields`.
779
329
 
@@ -781,276 +331,176 @@ All fields are imported from `@delmaredigital/payload-puck/fields`.
781
331
 
782
332
  | Field | Description |
783
333
  |-------|-------------|
784
- | **MediaField** | Payload media library integration with upload/browse |
785
- | **TiptapField** | Rich text editor with formatting toolbar |
786
- | **ColorPickerField** | Color picker with presets and transparency |
787
- | **BackgroundField** | Backgrounds with solid colors, gradients, and images |
788
- | **PaddingField** | Visual padding editor with per-side controls |
789
- | **MarginField** | Visual margin editor with per-side controls |
790
- | **BorderField** | Border editor with width, style, color, radius |
791
- | **DimensionsField** | Width/height with min/max constraints |
792
- | **SizeField** | Preset sizes (sm, md, lg) or custom values |
793
- | **AlignmentField** | Text alignment (left, center, right, justify) |
794
- | **JustifyContentField** | Flexbox justify-content options |
795
- | **AlignItemsField** | Flexbox align-items options |
796
- | **VerticalAlignmentField** | Vertical alignment (top, center, bottom) |
797
- | **LockedTextField** | Protected text field with edit confirmation |
798
- | **LockedRadioField** | Protected radio field with edit confirmation |
799
- | **ResponsiveField** | Per-breakpoint values for responsive design |
800
- | **ResponsiveVisibilityField** | Show/hide toggle per breakpoint (Divi/Elementor-style) |
801
- | **AnimationField** | Entrance animations with easing/duration |
802
- | **TransformField** | CSS transforms (rotate, scale, translate) |
803
- | **GradientEditor** | Visual gradient builder |
804
-
805
- ### Usage Examples
806
-
807
- <details>
808
- <summary><strong>MediaField</strong></summary>
809
-
810
- Integrates with Payload's media collection:
811
-
812
- ```typescript
813
- import { createMediaField } from '@delmaredigital/payload-puck/fields'
814
-
815
- const config = {
816
- components: {
817
- Hero: {
818
- fields: {
819
- backgroundImage: createMediaField({
820
- label: 'Background Image',
821
- collection: 'media', // Default: 'media'
822
- }),
823
- },
824
- },
825
- },
826
- }
827
- ```
828
- </details>
829
-
830
- <details>
831
- <summary><strong>TiptapField</strong></summary>
832
-
833
- Rich text editor with formatting toolbar:
834
-
835
- ```typescript
836
- import { createTiptapField } from '@delmaredigital/payload-puck/fields'
837
-
838
- const config = {
839
- components: {
840
- TextBlock: {
841
- fields: {
842
- content: createTiptapField({ label: 'Content' }),
843
- },
844
- },
334
+ | **MediaField** | Payload media library integration |
335
+ | **TiptapField** | Rich text editor with formatting |
336
+ | **ColorPickerField** | Color picker with opacity and presets |
337
+ | **BackgroundField** | Solid colors, gradients, images |
338
+ | **PaddingField / MarginField** | Visual spacing editors |
339
+ | **BorderField** | Border width, style, color, radius |
340
+ | **DimensionsField** | Width/height with constraints |
341
+ | **AlignmentField** | Text alignment options |
342
+ | **AnimationField** | Entrance animations |
343
+ | **ResponsiveVisibilityField** | Show/hide per breakpoint |
344
+ | **FolderPickerField** | Hierarchical folder selection (page-tree) |
345
+ | **PageSegmentField** | URL segment with slugification (page-tree) |
346
+ | **SlugPreviewField** | Read-only computed slug (page-tree) |
347
+
348
+ ### Usage Example
349
+
350
+ ```typescript
351
+ import { createMediaField, createBackgroundField, backgroundValueToCSS } from '@delmaredigital/payload-puck/fields'
352
+
353
+ const HeroConfig = {
354
+ fields: {
355
+ image: createMediaField({ label: 'Background Image' }),
356
+ background: createBackgroundField({ label: 'Overlay' }),
845
357
  },
358
+ render: ({ image, background }) => (
359
+ <section style={{ background: backgroundValueToCSS(background) }}>
360
+ {/* content */}
361
+ </section>
362
+ ),
846
363
  }
847
364
  ```
848
- </details>
849
365
 
850
- <details>
851
- <summary><strong>ColorPickerField</strong></summary>
852
-
853
- Color picker with presets and alpha channel:
366
+ ### CSS Helper Functions
854
367
 
855
368
  ```typescript
856
- import { createColorPickerField } from '@delmaredigital/payload-puck/fields'
857
-
858
- const config = {
859
- components: {
860
- Section: {
861
- fields: {
862
- backgroundColor: createColorPickerField({
863
- label: 'Background Color',
864
- }),
865
- },
866
- },
867
- },
868
- }
369
+ import {
370
+ backgroundValueToCSS,
371
+ dimensionsValueToCSS,
372
+ animationValueToCSS,
373
+ visibilityValueToCSS,
374
+ } from '@delmaredigital/payload-puck/fields'
869
375
  ```
870
- </details>
871
376
 
872
- <details>
873
- <summary><strong>BackgroundField</strong></summary>
874
-
875
- Full background editor with solid colors, gradients, and images:
377
+ ---
876
378
 
877
- ```typescript
878
- import { createBackgroundField, backgroundValueToCSS } from '@delmaredigital/payload-puck/fields'
379
+ ## Building Custom Components
879
380
 
880
- const config = {
881
- components: {
882
- Section: {
883
- fields: {
884
- background: createBackgroundField({ label: 'Background' }),
885
- },
886
- render: ({ background }) => (
887
- <section style={{ background: backgroundValueToCSS(background) }}>
888
- {/* content */}
889
- </section>
890
- ),
891
- },
892
- },
893
- }
894
- ```
895
- </details>
381
+ The plugin exports individual component configs and field factories for building custom Puck configurations.
896
382
 
897
- <details>
898
- <summary><strong>DimensionsField</strong></summary>
383
+ ### Cherry-Picking Components
899
384
 
900
- Width/height with min/max constraints and alignment:
385
+ Import only the components you need:
901
386
 
902
387
  ```typescript
903
- import { createDimensionsField, dimensionsValueToCSS } from '@delmaredigital/payload-puck/fields'
904
-
905
- const config = {
388
+ import {
389
+ SectionConfig,
390
+ HeadingConfig,
391
+ TextConfig,
392
+ ImageConfig,
393
+ ButtonConfig,
394
+ } from '@delmaredigital/payload-puck/components'
395
+
396
+ export const puckConfig: Config = {
906
397
  components: {
907
- Container: {
908
- fields: {
909
- dimensions: createDimensionsField({ label: 'Size' }),
910
- },
911
- render: ({ dimensions, children }) => (
912
- <div style={dimensionsValueToCSS(dimensions)}>
913
- {children}
914
- </div>
915
- ),
916
- },
398
+ Section: SectionConfig,
399
+ Heading: HeadingConfig,
400
+ Text: TextConfig,
401
+ Image: ImageConfig,
402
+ Button: ButtonConfig,
917
403
  },
918
- }
919
- ```
920
- </details>
921
-
922
- <details>
923
- <summary><strong>PaddingField & MarginField</strong></summary>
924
-
925
- Visual spacing editors:
926
-
927
- ```typescript
928
- import { createPaddingField, createMarginField } from '@delmaredigital/payload-puck/fields'
929
-
930
- const config = {
931
- components: {
932
- Box: {
933
- fields: {
934
- padding: createPaddingField({ label: 'Padding' }),
935
- margin: createMarginField({ label: 'Margin' }),
936
- },
937
- },
404
+ categories: {
405
+ layout: { components: ['Section'] },
406
+ content: { components: ['Heading', 'Text', 'Image', 'Button'] },
938
407
  },
939
408
  }
940
409
  ```
941
- </details>
942
410
 
943
- <details>
944
- <summary><strong>LockedTextField & LockedRadioField</strong></summary>
411
+ ### Using Field Factories
945
412
 
946
- Protected fields that require confirmation before editing:
413
+ Build custom components with pre-built fields:
947
414
 
948
415
  ```typescript
416
+ import type { ComponentConfig } from '@measured/puck'
949
417
  import {
950
- createLockedTextField,
951
- createLockedRadioField,
952
- lockedSlugField, // Pre-built slug field
953
- lockedHomepageField, // Pre-built homepage toggle
418
+ createMediaField,
419
+ createBackgroundField,
420
+ createPaddingField,
421
+ backgroundValueToCSS,
422
+ paddingValueToCSS,
954
423
  } from '@delmaredigital/payload-puck/fields'
955
424
 
956
- // Use pre-built fields
957
- const config = {
958
- root: {
959
- fields: {
960
- slug: lockedSlugField,
961
- isHomepage: lockedHomepageField,
962
- },
425
+ export const HeroConfig: ComponentConfig = {
426
+ label: 'Hero',
427
+ fields: {
428
+ image: createMediaField({ label: 'Background Image' }),
429
+ overlay: createBackgroundField({ label: 'Overlay' }),
430
+ padding: createPaddingField({ label: 'Padding' }),
431
+ },
432
+ defaultProps: {
433
+ image: null,
434
+ overlay: null,
435
+ padding: { top: 80, bottom: 80, left: 24, right: 24, unit: 'px', linked: false },
963
436
  },
437
+ render: ({ image, overlay, padding }) => (
438
+ <section
439
+ style={{
440
+ background: backgroundValueToCSS(overlay),
441
+ padding: paddingValueToCSS(padding),
442
+ }}
443
+ >
444
+ {/* Hero content */}
445
+ </section>
446
+ ),
964
447
  }
965
-
966
- // Or create custom locked fields
967
- const customLockedField = createLockedTextField({
968
- label: 'API Key',
969
- placeholder: 'Enter API key',
970
- warningMessage: 'Changing this will break integrations.',
971
- })
972
448
  ```
973
- </details>
974
449
 
975
- <details>
976
- <summary><strong>AnimationField</strong></summary>
450
+ ### Server vs Editor Variants
977
451
 
978
- Entrance animations with customizable timing:
452
+ For `PageRenderer` (frontend), components need server-safe configs without React hooks:
979
453
 
980
454
  ```typescript
981
- import { createAnimationField, getEntranceAnimationClasses } from '@delmaredigital/payload-puck/fields'
455
+ // Import server variants for PageRenderer
456
+ import {
457
+ SectionServerConfig,
458
+ HeadingServerConfig,
459
+ TextServerConfig,
460
+ } from '@delmaredigital/payload-puck/components'
982
461
 
983
- const config = {
984
- components: {
985
- AnimatedSection: {
986
- fields: {
987
- animation: createAnimationField({ label: 'Entrance Animation' }),
988
- },
989
- render: ({ animation, children }) => (
990
- <div className={getEntranceAnimationClasses(animation)}>
991
- {children}
992
- </div>
993
- ),
994
- },
995
- },
996
- }
462
+ <PageRenderer config={{ components: { Section: SectionServerConfig, ... } }} data={page.puckData} />
997
463
  ```
998
- </details>
999
464
 
1000
- <details>
1001
- <summary><strong>ResponsiveField</strong></summary>
465
+ For custom components, create two files:
466
+ - `MyComponent.tsx` - Full editor version with fields and interactivity
467
+ - `MyComponent.server.tsx` - Server-safe version (no hooks, no 'use client')
1002
468
 
1003
- Values that change per breakpoint:
469
+ ### Extending Built-in Configs
470
+
471
+ Use `extendConfig()` to add custom components:
1004
472
 
1005
473
  ```typescript
1006
- import { createResponsiveField, BREAKPOINTS } from '@delmaredigital/payload-puck/fields'
474
+ import { extendConfig, fullConfig } from '@delmaredigital/payload-puck/config/editor'
475
+ import { HeroConfig } from './components/Hero'
1007
476
 
1008
- const config = {
477
+ export const puckConfig = extendConfig({
478
+ base: fullConfig,
1009
479
  components: {
1010
- Grid: {
1011
- fields: {
1012
- columns: createResponsiveField({
1013
- label: 'Columns',
1014
- field: { type: 'number' },
1015
- defaultValue: { sm: 1, md: 2, lg: 3 },
1016
- }),
1017
- },
1018
- },
480
+ Hero: HeroConfig,
1019
481
  },
1020
- }
482
+ categories: {
483
+ custom: { title: 'Custom', components: ['Hero'] },
484
+ },
485
+ })
1021
486
  ```
1022
- </details>
1023
487
 
1024
- <details>
1025
- <summary><strong>ResponsiveVisibilityField</strong></summary>
1026
-
1027
- Show/hide components at different breakpoints (like Divi/Elementor):
1028
-
1029
- ```typescript
1030
- import { createResponsiveVisibilityField, visibilityValueToCSS } from '@delmaredigital/payload-puck/fields'
488
+ > **Note:** Use `fullConfig` from `/config/editor` for extending the editor. For server-side rendering, use `baseConfig` from `/config`.
1031
489
 
1032
- const config = {
1033
- components: {
1034
- MobileOnlyBanner: {
1035
- fields: {
1036
- visibility: createResponsiveVisibilityField({ label: 'Visibility' }),
1037
- },
1038
- render: ({ visibility, children }) => {
1039
- const visibilityCSS = visibilityValueToCSS(visibility, 'mobile-banner')
1040
- return (
1041
- <>
1042
- {visibilityCSS && <style>{visibilityCSS}</style>}
1043
- <div className="mobile-banner">{children}</div>
1044
- </>
1045
- )
1046
- },
1047
- },
1048
- },
1049
- }
1050
- ```
490
+ ### Available Field Factories
1051
491
 
1052
- The field displays device icons with visibility toggles. Green = visible, Red = hidden at that breakpoint.
1053
- </details>
492
+ | Factory | Description |
493
+ |---------|-------------|
494
+ | `createMediaField()` | Payload media library picker |
495
+ | `createBackgroundField()` | Solid, gradient, or image backgrounds |
496
+ | `createColorPickerField()` | Color picker with opacity |
497
+ | `createPaddingField()` | Visual padding editor |
498
+ | `createMarginField()` | Visual margin editor |
499
+ | `createBorderField()` | Border styling |
500
+ | `createDimensionsField()` | Width/height constraints |
501
+ | `createAnimationField()` | Entrance animations |
502
+ | `createAlignmentField()` | Text alignment |
503
+ | `createTiptapField()` | Inline rich text editor |
1054
504
 
1055
505
  ### CSS Helper Functions
1056
506
 
@@ -1059,56 +509,25 @@ Convert field values to CSS:
1059
509
  ```typescript
1060
510
  import {
1061
511
  backgroundValueToCSS,
512
+ paddingValueToCSS,
513
+ marginValueToCSS,
514
+ borderValueToCSS,
1062
515
  dimensionsValueToCSS,
1063
- animationValueToCSS,
1064
- transformValueToCSS,
1065
- gradientValueToCSS,
1066
- sizeValueToCSS,
1067
- // Responsive helpers
1068
- responsiveValueToCSS,
1069
- visibilityValueToCSS,
516
+ colorValueToCSS,
1070
517
  } from '@delmaredigital/payload-puck/fields'
1071
518
 
1072
- const styles = {
1073
- background: backgroundValueToCSS(background),
1074
- ...dimensionsValueToCSS(dimensions),
1075
- animation: animationValueToCSS(animation),
1076
- transform: transformValueToCSS(transform),
519
+ const style = {
520
+ background: backgroundValueToCSS(props.background),
521
+ padding: paddingValueToCSS(props.padding),
522
+ ...dimensionsValueToCSS(props.dimensions),
1077
523
  }
1078
-
1079
- // Responsive values generate CSS media queries
1080
- const uniqueId = 'my-component-123'
1081
- const { baseStyles, mediaQueryCSS } = responsiveValueToCSS(
1082
- dimensions, // ResponsiveValue<T> or T
1083
- dimensionsValueToCSS, // Converter function
1084
- uniqueId // CSS class selector
1085
- )
1086
-
1087
- // Visibility generates show/hide media queries
1088
- const visibilityCSS = visibilityValueToCSS(visibility, uniqueId)
1089
-
1090
- // Render with media queries
1091
- return (
1092
- <>
1093
- {mediaQueryCSS && <style>{mediaQueryCSS}</style>}
1094
- {visibilityCSS && <style>{visibilityCSS}</style>}
1095
- <div className={uniqueId} style={baseStyles}>{children}</div>
1096
- </>
1097
- )
1098
524
  ```
1099
525
 
1100
- </details>
1101
-
1102
526
  ---
1103
527
 
1104
- <details>
1105
- <summary><strong>Theming</strong> — Button variants, color presets, focus rings</summary>
1106
-
1107
- Customize button styles, color presets, and focus rings to match your design system.
1108
-
1109
- ### Basic Usage
528
+ ## Theming
1110
529
 
1111
- Wrap your `PageRenderer` with `ThemeProvider` to apply custom theming:
530
+ Customize button styles, color presets, and focus rings:
1112
531
 
1113
532
  ```typescript
1114
533
  import { PageRenderer } from '@delmaredigital/payload-puck/render'
@@ -1116,94 +535,36 @@ import { ThemeProvider } from '@delmaredigital/payload-puck/theme'
1116
535
 
1117
536
  <ThemeProvider theme={{
1118
537
  buttonVariants: {
1119
- default: { classes: 'bg-primary text-primary-foreground hover:bg-primary/90' },
1120
- secondary: { classes: 'bg-secondary text-secondary-foreground hover:bg-secondary/90' },
538
+ default: { classes: 'bg-primary text-white hover:bg-primary/90' },
539
+ secondary: { classes: 'bg-secondary text-foreground hover:bg-secondary/90' },
1121
540
  },
1122
541
  focusRingColor: 'focus:ring-primary',
1123
- }}>
1124
- <PageRenderer config={baseConfig} data={page.puckData} />
1125
- </ThemeProvider>
1126
- ```
1127
-
1128
- ### Using the Example Theme
1129
-
1130
- ```typescript
1131
- import { ThemeProvider, exampleTheme } from '@delmaredigital/payload-puck/theme'
1132
-
1133
- <ThemeProvider theme={exampleTheme}>
1134
- <PageRenderer data={page.puckData} />
1135
- </ThemeProvider>
1136
-
1137
- // Or customize specific values
1138
- <ThemeProvider theme={{
1139
- ...exampleTheme,
1140
- focusRingColor: 'focus:ring-brand',
1141
- }}>
1142
- <PageRenderer data={page.puckData} />
1143
- </ThemeProvider>
1144
- ```
1145
-
1146
- ### Theme Options
1147
-
1148
- | Option | Description |
1149
- |--------|-------------|
1150
- | `buttonVariants` | Button component variant styles (default, secondary, outline, ghost) |
1151
- | `ctaButtonVariants` | CallToAction button styles (primary, secondary, outline) |
1152
- | `ctaBackgroundStyles` | CallToAction background styles (default, dark, light) |
1153
- | `colorPresets` | Color picker preset swatches |
1154
- | `extendColorPresets` | If true, adds to defaults instead of replacing |
1155
- | `focusRingColor` | Focus ring class (e.g., `focus:ring-primary`) |
1156
-
1157
- ### Custom Color Presets
1158
-
1159
- ```typescript
1160
- <ThemeProvider theme={{
1161
542
  colorPresets: [
1162
543
  { hex: '#3b82f6', label: 'Brand Blue' },
1163
544
  { hex: '#10b981', label: 'Success' },
1164
- { hex: '#ef4444', label: 'Danger' },
1165
545
  ],
1166
- extendColorPresets: false, // Replace defaults
1167
546
  }}>
1168
- <PageRenderer data={page.puckData} />
547
+ <PageRenderer config={baseConfig} data={page.puckData} />
1169
548
  </ThemeProvider>
1170
549
  ```
1171
550
 
1172
- ### Direct Theme Imports
551
+ Access theme values in custom components with `useTheme()`:
1173
552
 
1174
553
  ```typescript
1175
- import {
1176
- ThemeProvider,
1177
- useTheme,
1178
- getVariantClasses,
1179
- DEFAULT_THEME,
1180
- } from '@delmaredigital/payload-puck/theme'
554
+ import { useTheme } from '@delmaredigital/payload-puck/theme'
1181
555
 
1182
- function MyButton({ variant }) {
556
+ function CustomButton({ variant }) {
1183
557
  const theme = useTheme()
1184
- const classes = getVariantClasses(theme.buttonVariants, variant)
1185
- return <button className={classes}>Click me</button>
558
+ const classes = theme.buttonVariants[variant]?.classes
559
+ return <button className={classes}>...</button>
1186
560
  }
1187
561
  ```
1188
562
 
1189
- </details>
1190
-
1191
563
  ---
1192
564
 
1193
- <details>
1194
- <summary><strong>Layouts</strong> — Page structure, headers/footers, responsive controls</summary>
1195
-
1196
- The layout system controls page structure, max-width constraints, and optional header/footer rendering. Layouts are selected per-page in the Puck editor's "Page Setup" panel.
565
+ ## Layouts
1197
566
 
1198
- ### Built-in Layouts
1199
-
1200
- | Layout | Description |
1201
- |--------|-------------|
1202
- | **Default** | Standard page with max-width container (1200px) |
1203
- | **Landing** | Full-width sections, no container constraints |
1204
- | **Full Width** | Edge-to-edge content |
1205
-
1206
- ### Defining Custom Layouts
567
+ Define page layouts with headers, footers, and styling:
1207
568
 
1208
569
  ```typescript
1209
570
  // lib/puck-layouts.ts
@@ -1219,280 +580,91 @@ export const siteLayouts: LayoutDefinition[] = [
1219
580
  maxWidth: '1200px',
1220
581
  header: SiteHeader,
1221
582
  footer: SiteFooter,
1222
- editorBackground: '#ffffff',
1223
- editorDarkMode: false,
1224
583
  stickyHeaderHeight: 80,
1225
- // Default background for frontend (overridden by pageBackground in Puck)
1226
- styles: {
1227
- wrapper: {
1228
- background: 'var(--site-bg)',
1229
- backgroundAttachment: 'fixed',
1230
- },
1231
- },
1232
584
  },
1233
585
  {
1234
586
  value: 'landing',
1235
587
  label: 'Landing',
1236
588
  description: 'Full-width landing page',
1237
589
  fullWidth: true,
1238
- editorBackground: '#f8fafc',
1239
- styles: {
1240
- wrapper: {
1241
- background: 'linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%)',
1242
- },
1243
- },
1244
- },
1245
- {
1246
- value: 'full-width',
1247
- label: 'Full Width',
1248
- description: 'Edge-to-edge content',
1249
- fullWidth: true,
1250
590
  },
1251
591
  ]
1252
592
  ```
1253
593
 
1254
- > **Background priority:** If a user sets `pageBackground` in the Puck editor, it overrides the layout's `styles.wrapper.background`. This allows layouts to define sensible defaults while letting individual pages customize their appearance.
1255
-
1256
- ### Using Layouts in the Editor
594
+ Pass layouts to the `PuckConfigProvider`:
1257
595
 
1258
596
  ```typescript
1259
- import { PuckEditor } from '@delmaredigital/payload-puck/editor'
1260
- import { siteLayouts } from '@/lib/puck-layouts'
1261
-
1262
- <PuckEditor
1263
- config={editorConfig}
1264
- pageId={page.id}
1265
- initialData={page.puckData}
1266
- layouts={siteLayouts}
1267
- />
1268
- ```
1269
-
1270
- ### Using Layouts on the Frontend
1271
-
1272
- ```typescript
1273
- import { PageRenderer } from '@delmaredigital/payload-puck/render'
1274
- import { LayoutWrapper, DEFAULT_LAYOUTS } from '@delmaredigital/payload-puck/layouts'
1275
-
1276
- export default async function Page({ params }) {
1277
- const page = await getPage(params.slug)
1278
- const layout = DEFAULT_LAYOUTS.find(l => l.value === page.puckData?.root?.props?.pageLayout)
1279
-
1280
- return (
1281
- <LayoutWrapper layout={layout}>
1282
- <PageRenderer config={baseConfig} data={page.puckData} />
1283
- </LayoutWrapper>
1284
- )
1285
- }
597
+ <PuckConfigProvider config={editorConfig} layouts={siteLayouts}>
598
+ {children}
599
+ </PuckConfigProvider>
1286
600
  ```
1287
601
 
1288
- ### Layout Definition Options
1289
-
1290
- | Option | Type | Default | Description |
1291
- |--------|------|---------|-------------|
1292
- | `value` | `string` | — | Unique identifier |
1293
- | `label` | `string` | — | Display name in editor |
1294
- | `description` | `string` | — | Optional description |
1295
- | `maxWidth` | `string` | — | Container max-width (e.g., `'1200px'`) |
1296
- | `fullWidth` | `boolean` | `false` | If true, no container constraints |
1297
- | `classes` | `object` | — | CSS classes for wrapper/container/content |
1298
- | `styles` | `object` | — | Inline styles for wrapper/container/content |
1299
- | `header` | `ComponentType` | — | Header component for editor preview and frontend |
1300
- | `footer` | `ComponentType` | — | Footer component for editor preview and frontend |
1301
- | `editorBackground` | `string` | `'#ffffff'` | Background color/gradient for editor preview |
1302
- | `editorDarkMode` | `boolean` | `false` | Whether to use dark mode styling in editor preview |
1303
- | `stickyHeaderHeight` | `number` | — | Height in px of sticky/fixed header for proper content offset |
1304
- | `stickyFooter` | `boolean` | `true` | Push footer to bottom of viewport even with minimal content. Set to `false` to let footer flow naturally after content |
1305
-
1306
- ### Page-Level Settings
1307
-
1308
- The editor automatically includes page-level controls that allow overriding layout defaults per-page:
1309
-
1310
- | Field | Options | Description |
1311
- |-------|---------|-------------|
1312
- | `showHeader` | `default`, `show`, `hide` | Override header visibility for this page |
1313
- | `showFooter` | `default`, `show`, `hide` | Override footer visibility for this page |
1314
- | `pageBackground` | Background field | Custom page background color/gradient/image |
1315
- | `pageMaxWidth` | Select | Override layout's max-width constraint |
1316
-
1317
- These settings appear in the editor's "Page Setup" panel and are applied in both the editor preview and frontend rendering.
1318
-
1319
- </details>
1320
-
1321
- ---
1322
-
1323
- <details>
1324
- <summary><strong>API Routes</strong> — Auth configuration, root props mapping</summary>
1325
-
1326
- ### Auth Configuration
1327
-
1328
- The API routes require an `auth` configuration with permission hooks:
602
+ And use them with `PageRenderer`:
1329
603
 
1330
604
  ```typescript
1331
- const auth = {
1332
- // Required: Authenticate the request
1333
- authenticate: async (request) => {
1334
- const session = await getSession(request)
1335
- if (!session?.user) return { authenticated: false }
1336
- return { authenticated: true, user: session.user }
1337
- },
1338
-
1339
- // Optional permission hooks
1340
- canList: async (user) => ({ allowed: true }),
1341
- canView: async (user, pageId) => ({ allowed: true }),
1342
- canEdit: async (user, pageId) => ({ allowed: user.role === 'editor' }),
1343
- canPublish: async (user, pageId) => ({ allowed: user.role === 'admin' }),
1344
- canDelete: async (user, pageId) => ({ allowed: user.role === 'admin' }),
1345
- }
1346
- ```
605
+ import { LayoutWrapper } from '@delmaredigital/payload-puck/layouts'
1347
606
 
1348
- ### Root Props Mapping
607
+ const layout = siteLayouts.find(l => l.value === page.puckData?.root?.props?.pageLayout)
1349
608
 
1350
- Sync Puck root.props to Payload fields automatically:
1351
-
1352
- ```typescript
1353
- createPuckApiRoutesWithId({
1354
- // ...
1355
- rootPropsMapping: [
1356
- { from: 'title', to: 'meta.title' },
1357
- { from: 'description', to: 'meta.description' },
1358
- { from: 'pageLayout', to: 'pageLayout' },
1359
- ],
1360
- })
609
+ <LayoutWrapper layout={layout}>
610
+ <PageRenderer config={baseConfig} data={page.puckData} />
611
+ </LayoutWrapper>
1361
612
  ```
1362
613
 
1363
- </details>
1364
-
1365
614
  ---
1366
615
 
1367
- <details>
1368
- <summary><strong>SEO Fields</strong> — Robots meta, sitemap integration</summary>
616
+ ## Page-Tree Integration
1369
617
 
1370
- The plugin adds SEO-related fields to each page in the `meta` group:
618
+ When `@delmaredigital/payload-page-tree` is detected, the plugin automatically adds folder management to the Puck sidebar.
1371
619
 
1372
- | Field | Type | Description |
1373
- |-------|------|-------------|
1374
- | `meta.title` | text | Page title for search engines |
1375
- | `meta.description` | textarea | Meta description |
1376
- | `meta.image` | upload | Social sharing image |
1377
- | `meta.noindex` | checkbox | Prevent search engine indexing |
1378
- | `meta.nofollow` | checkbox | Prevent search engines from following links |
1379
- | `meta.excludeFromSitemap` | checkbox | Exclude page from XML sitemap |
620
+ ### How It Works
1380
621
 
1381
- **These fields are not automatically wired to your frontend.** You need to implement them based on your setup.
622
+ The plugin checks if your collection has a `pageSegment` field (page-tree's signature). When detected:
1382
623
 
1383
- ### Robots Meta (Next.js App Router)
624
+ 1. **Folder Picker** - Select a folder from the hierarchy
625
+ 2. **Page Segment** - Edit the page's URL segment
626
+ 3. **Slug Preview** - See the computed slug (folder path + segment)
1384
627
 
1385
- In your page's `generateMetadata` function:
1386
-
1387
- ```typescript
1388
- // app/(frontend)/[...slug]/page.tsx
1389
- export async function generateMetadata({ params }): Promise<Metadata> {
1390
- const page = await getPage(params.slug)
1391
-
1392
- return {
1393
- title: page.meta?.title || page.title,
1394
- description: page.meta?.description,
1395
- robots: {
1396
- index: !page.meta?.noindex,
1397
- follow: !page.meta?.nofollow,
1398
- },
1399
- }
1400
- }
1401
- ```
1402
-
1403
- ### Dynamic Sitemap
1404
-
1405
- Filter out pages marked as excluded in your `sitemap.ts`:
1406
-
1407
- ```typescript
1408
- // app/sitemap.ts
1409
- import type { MetadataRoute } from 'next'
1410
- import { getPayload } from 'payload'
1411
- import config from '@payload-config'
1412
-
1413
- export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
1414
- const baseUrl = 'https://yoursite.com'
1415
- const payload = await getPayload({ config })
1416
-
1417
- const { docs: pages } = await payload.find({
1418
- collection: 'pages',
1419
- limit: 1000,
1420
- where: {
1421
- or: [
1422
- { 'meta.excludeFromSitemap': { equals: false } },
1423
- { 'meta.excludeFromSitemap': { exists: false } },
1424
- ],
1425
- },
1426
- select: {
1427
- slug: true,
1428
- updatedAt: true,
1429
- },
1430
- })
1431
-
1432
- return pages.map((page) => ({
1433
- url: `${baseUrl}/${page.slug}`,
1434
- lastModified: new Date(page.updatedAt),
1435
- }))
1436
- }
1437
- ```
1438
-
1439
- </details>
1440
-
1441
- ---
1442
-
1443
- <details>
1444
- <summary><strong>Plugin Options</strong> — Collection config, access control</summary>
628
+ ### Configuration
1445
629
 
1446
630
  ```typescript
1447
631
  createPuckPlugin({
1448
- // Collection slug for pages (default: 'pages')
1449
- pagesCollection: 'pages',
632
+ // Auto-detect (default)
633
+ pageTreeIntegration: undefined,
1450
634
 
1451
- // Auto-generate the Pages collection (default: true)
1452
- autoGenerateCollection: true,
1453
-
1454
- // Override collection config
1455
- collectionOverrides: {
1456
- admin: {
1457
- defaultColumns: ['title', 'slug', 'updatedAt'],
1458
- },
635
+ // Explicitly enable with custom config
636
+ pageTreeIntegration: {
637
+ folderSlug: 'payload-folders',
638
+ pageSegmentFieldName: 'pageSegment',
1459
639
  },
1460
640
 
1461
- // Custom access control
1462
- access: {
1463
- read: () => true,
1464
- create: ({ req }) => !!req.user,
1465
- update: ({ req }) => !!req.user,
1466
- delete: ({ req }) => !!req.user,
1467
- },
641
+ // Explicitly disable
642
+ pageTreeIntegration: false,
1468
643
  })
1469
644
  ```
1470
645
 
1471
- </details>
646
+ ### Performance
647
+
648
+ Detection is instant - it reads the in-memory collection config, no database queries.
1472
649
 
1473
650
  ---
1474
651
 
1475
- <details>
1476
- <summary><strong>Hybrid Integration</strong> — Add Puck to existing collections with legacy blocks</summary>
652
+ ## Hybrid Integration
1477
653
 
1478
- If you have an existing Pages collection with legacy Payload blocks, you can add Puck support without replacing your collection.
654
+ Add Puck to existing collections with legacy blocks.
1479
655
 
1480
656
  ### Automatic (Recommended)
1481
657
 
1482
- If you already have a `pages` collection defined, the plugin automatically adds only the Puck-specific fields that don't already exist:
658
+ If you already have a `pages` collection, the plugin adds only the Puck-specific fields:
1483
659
 
1484
660
  ```typescript
1485
661
  // payload.config.ts
1486
- import { buildConfig } from 'payload'
1487
- import { createPuckPlugin } from '@delmaredigital/payload-puck/plugin'
1488
-
1489
662
  export default buildConfig({
1490
663
  collections: [
1491
664
  {
1492
665
  slug: 'pages',
1493
666
  fields: [
1494
667
  { name: 'title', type: 'text', required: true },
1495
- { name: 'slug', type: 'text', required: true },
1496
668
  { name: 'layout', type: 'blocks', blocks: [HeroBlock, CTABlock] },
1497
669
  ],
1498
670
  },
@@ -1503,162 +675,118 @@ export default buildConfig({
1503
675
  })
1504
676
  ```
1505
677
 
1506
- The plugin adds: `puckData`, `editorVersion`, `pageLayout`, `meta` (SEO fields), and the "Edit with Puck" button.
1507
-
1508
- **Smart detection:** The `editorVersion` field automatically detects whether existing pages use legacy blocks or Puck data. Pages with legacy blocks are marked `'legacy'`, pages with Puck content are marked `'puck'`, and new empty pages use the configured default. This prevents migrations from incorrectly overwriting existing content.
678
+ The `editorVersion` field auto-detects whether pages use legacy blocks or Puck.
1509
679
 
1510
680
  ### Manual with `getPuckFields()`
1511
681
 
1512
- For full control, disable auto-generation and use `getPuckFields()`:
1513
-
1514
682
  ```typescript
1515
- // collections/Pages.ts
1516
- import type { CollectionConfig } from 'payload'
1517
683
  import { getPuckFields } from '@delmaredigital/payload-puck'
1518
684
 
1519
685
  export const Pages: CollectionConfig = {
1520
686
  slug: 'pages',
1521
- versions: { drafts: true },
1522
687
  fields: [
1523
- { name: 'title', type: 'text', required: true },
1524
- { name: 'slug', type: 'text', required: true },
1525
- { name: 'layout', type: 'blocks', blocks: [HeroBlock, CTABlock] },
1526
-
688
+ { name: 'title', type: 'text' },
689
+ { name: 'layout', type: 'blocks', blocks: [...] },
1527
690
  ...getPuckFields({
1528
- includeSEO: false,
1529
- includeConversion: true,
1530
- // Custom conversion types (optional - defaults to standard types)
1531
- conversionTypeOptions: [
1532
- { label: 'Registration', value: 'registration' },
1533
- { label: 'Donation', value: 'donation' },
1534
- { label: 'Course Start', value: 'course_start' },
1535
- { label: 'Custom', value: 'custom' },
1536
- ],
691
+ includeSEO: true,
1537
692
  includeEditorVersion: true,
1538
693
  includePageLayout: true,
1539
- includeIsHomepage: false,
1540
- // Custom layouts (only value/label needed for the field)
1541
- layouts: [
1542
- { value: 'default', label: 'Default' },
1543
- { value: 'landing', label: 'Landing' },
1544
- ],
1545
694
  }),
1546
695
  ],
1547
696
  }
1548
697
  ```
1549
698
 
1550
- ```typescript
1551
- // payload.config.ts
1552
- createPuckPlugin({
1553
- pagesCollection: 'pages',
1554
- autoGenerateCollection: false,
1555
- })
1556
- ```
1557
-
1558
- ### Individual Field Imports
699
+ ### Rendering Hybrid Pages
1559
700
 
1560
701
  ```typescript
1561
- import {
1562
- puckDataField,
1563
- editorVersionField,
1564
- createPageLayoutField,
1565
- seoFieldGroup,
1566
- conversionFieldGroup,
1567
- } from '@delmaredigital/payload-puck'
1568
-
1569
- const Pages: CollectionConfig = {
1570
- slug: 'pages',
1571
- fields: [
1572
- puckDataField,
1573
- editorVersionField,
1574
- createPageLayoutField(myCustomLayouts),
1575
- ],
1576
- }
702
+ import { HybridPageRenderer } from '@delmaredigital/payload-puck/render'
703
+ import { LegacyBlockRenderer } from '@/components/LegacyBlockRenderer'
704
+
705
+ <HybridPageRenderer
706
+ page={page}
707
+ config={puckConfig}
708
+ legacyRenderer={(blocks) => <LegacyBlockRenderer blocks={blocks} />}
709
+ />
1577
710
  ```
1578
711
 
1579
- ### Rendering Hybrid Pages
712
+ ---
1580
713
 
1581
- **Option A: Using `HybridPageRenderer` (Recommended)**
714
+ ## Advanced Configuration
1582
715
 
1583
- The `HybridPageRenderer` component handles the branching logic for you:
716
+ ### Plugin Options
717
+
718
+ | Option | Default | Description |
719
+ |--------|---------|-------------|
720
+ | `pagesCollection` | `'pages'` | Collection slug to use for pages |
721
+ | `autoGenerateCollection` | `true` | Create the collection if it doesn't exist, or add Puck fields to existing |
722
+ | `enableEndpoints` | `true` | Register API endpoints at `/api/puck/:collection` for the editor |
723
+ | `enableAdminView` | `true` | Register the Puck editor view in Payload admin |
724
+ | `adminViewPath` | `'/puck-editor'` | Path for the editor (full path: `/admin/puck-editor/:collection/:id`) |
725
+ | `pageTreeIntegration` | auto-detect | Integration with `@delmaredigital/payload-page-tree` |
726
+ | `layouts` | `undefined` | Layout definitions for page templates |
1584
727
 
1585
728
  ```typescript
1586
- // app/(frontend)/[...slug]/page.tsx
1587
- import { HybridPageRenderer } from '@delmaredigital/payload-puck/render'
1588
- import { puckConfig } from '@/puck/config'
1589
- import { siteLayouts } from '@/lib/puck-layouts'
1590
- import { LegacyBlockRenderer } from '@/components/LegacyBlockRenderer'
729
+ createPuckPlugin({
730
+ pagesCollection: 'pages',
731
+ autoGenerateCollection: true,
732
+ enableEndpoints: true,
733
+ enableAdminView: true,
734
+ adminViewPath: '/puck-editor',
735
+ pageTreeIntegration: undefined, // auto-detects
1591
736
 
1592
- export default async function Page({ params }) {
1593
- const page = await getPage(params.slug)
737
+ // Collection overrides (merged with generated collection)
738
+ collectionOverrides: {
739
+ admin: {
740
+ defaultColumns: ['title', 'slug', 'updatedAt'],
741
+ },
742
+ },
1594
743
 
1595
- return (
1596
- <HybridPageRenderer
1597
- page={page}
1598
- config={puckConfig}
1599
- layouts={siteLayouts}
1600
- legacyRenderer={(blocks) => <LegacyBlockRenderer blocks={blocks} />}
1601
- />
1602
- )
1603
- }
744
+ // Access control
745
+ access: {
746
+ read: () => true,
747
+ create: ({ req }) => !!req.user,
748
+ update: ({ req }) => !!req.user,
749
+ delete: ({ req }) => !!req.user,
750
+ },
751
+ })
1604
752
  ```
1605
753
 
1606
- **Option B: Manual Branching**
754
+ ### Custom API Routes (Advanced)
1607
755
 
1608
- For more control, handle the branching yourself:
756
+ The built-in endpoints handle most use cases. Only disable them if you need custom authentication or middleware.
1609
757
 
1610
- ```typescript
1611
- // app/(frontend)/[...slug]/page.tsx
1612
- import { PageRenderer } from '@delmaredigital/payload-puck/render'
1613
- import { puckConfig } from '@/puck/config'
1614
- import { siteLayouts } from '@/lib/puck-layouts'
1615
- import { LegacyBlockRenderer } from '@/components/LegacyBlockRenderer'
758
+ If needed, three route factories are available:
1616
759
 
1617
- export default async function Page({ params }) {
1618
- const page = await getPage(params.slug)
1619
-
1620
- if (page.editorVersion === 'puck' && page.puckData) {
1621
- return (
1622
- <PageRenderer
1623
- config={puckConfig}
1624
- data={page.puckData}
1625
- layouts={siteLayouts}
1626
- />
1627
- )
1628
- }
760
+ | Factory | Route Pattern | Methods |
761
+ |---------|---------------|---------|
762
+ | `createPuckApiRoutes` | `/api/puck/[collection]` | GET (list), POST (create) |
763
+ | `createPuckApiRoutesWithId` | `/api/puck/[collection]/[id]` | GET, PATCH, DELETE |
764
+ | `createPuckApiRoutesVersions` | `/api/puck/[collection]/[id]/versions` | GET, POST (restore) |
1629
765
 
1630
- return <LegacyBlockRenderer blocks={page.layout} />
1631
- }
1632
- ```
766
+ See the JSDoc in `@delmaredigital/payload-puck/api` for usage examples.
1633
767
 
1634
- ### Available Field Exports
1635
-
1636
- | Export | Description |
1637
- |--------|-------------|
1638
- | `getPuckFields(options)` | Returns array of Puck fields based on options |
1639
- | `puckDataField` | JSON field for Puck editor data (hidden) |
1640
- | `editorVersionField` | Select field: 'legacy' \| 'puck' (auto-detects based on content) |
1641
- | `createEditorVersionField(default, sidebar, legacyBlocksFieldName)` | Factory for custom editor version field |
1642
- | `pageLayoutField` | Layout selector with DEFAULT_LAYOUTS |
1643
- | `createPageLayoutField(layouts, sidebar)` | Factory for custom layout options |
1644
- | `isHomepageField` | Checkbox for homepage designation |
1645
- | `seoFieldGroup` | Group named `meta` with title, description, image, noindex, etc. |
1646
- | `conversionFieldGroup` | Group for conversion tracking analytics (default types) |
1647
- | `createConversionFieldGroup(types, sidebar)` | Factory for custom conversion types |
1648
- | `DEFAULT_CONVERSION_TYPES` | Default conversion types array |
1649
- | `generatePuckEditField(slug, config)` | Creates the "Edit with Puck" UI button |
1650
-
1651
- ### Available Render Exports
1652
-
1653
- | Export | Description |
1654
- |--------|-------------|
1655
- | `PageRenderer` | Renders Puck data with layout support |
1656
- | `HybridPageRenderer` | Renders either Puck or legacy pages based on `editorVersion` |
768
+ ---
1657
769
 
1658
- </details>
770
+ ## Export Reference
771
+
772
+ | Export Path | Description |
773
+ |-------------|-------------|
774
+ | `@delmaredigital/payload-puck` | Plugin creation, field utilities |
775
+ | `@delmaredigital/payload-puck/plugin` | `createPuckPlugin` |
776
+ | `@delmaredigital/payload-puck/config` | `baseConfig`, `createConfig()`, `extendConfig()` |
777
+ | `@delmaredigital/payload-puck/config/editor` | `editorConfig` for editing |
778
+ | `@delmaredigital/payload-puck/client` | `PuckConfigProvider`, `usePuckConfig`, client components |
779
+ | `@delmaredigital/payload-puck/rsc` | `PuckEditorView` for Payload admin views |
780
+ | `@delmaredigital/payload-puck/render` | `PageRenderer`, `HybridPageRenderer` |
781
+ | `@delmaredigital/payload-puck/fields` | Custom Puck fields and CSS helpers |
782
+ | `@delmaredigital/payload-puck/components` | Component configs for custom configurations |
783
+ | `@delmaredigital/payload-puck/theme` | `ThemeProvider`, theme utilities |
784
+ | `@delmaredigital/payload-puck/layouts` | Layout definitions, `LayoutWrapper` |
785
+ | `@delmaredigital/payload-puck/api` | API route factories (for custom implementations) |
786
+ | `@delmaredigital/payload-puck/admin/client` | `EditWithPuckButton`, `EditWithPuckCell` |
1659
787
 
1660
788
  ---
1661
789
 
1662
790
  ## License
1663
791
 
1664
- MIT
792
+ MIT