@puckeditor/cli 0.24.0-canary.301a0304

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 (372) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/bin.mjs +7304 -0
  4. package/dist/docs/api-reference/actions.md +63 -0
  5. package/dist/docs/api-reference/components/action-bar-action.md +35 -0
  6. package/dist/docs/api-reference/components/action-bar-group.md +24 -0
  7. package/dist/docs/api-reference/components/action-bar-label.md +25 -0
  8. package/dist/docs/api-reference/components/action-bar-separator.md +16 -0
  9. package/dist/docs/api-reference/components/action-bar.md +32 -0
  10. package/dist/docs/api-reference/components/auto-field.md +63 -0
  11. package/dist/docs/api-reference/components/drawer-item.md +75 -0
  12. package/dist/docs/api-reference/components/drawer.md +29 -0
  13. package/dist/docs/api-reference/components/drop-zone.md +232 -0
  14. package/dist/docs/api-reference/components/field-label.md +138 -0
  15. package/dist/docs/api-reference/components/inline-text-field.md +77 -0
  16. package/dist/docs/api-reference/components/puck-components.md +19 -0
  17. package/dist/docs/api-reference/components/puck-fields.md +39 -0
  18. package/dist/docs/api-reference/components/puck-layout.md +27 -0
  19. package/dist/docs/api-reference/components/puck-outline.md +19 -0
  20. package/dist/docs/api-reference/components/puck-preview.md +39 -0
  21. package/dist/docs/api-reference/components/puck.md +561 -0
  22. package/dist/docs/api-reference/components/render.md +94 -0
  23. package/dist/docs/api-reference/components/rich-text-menu-control.md +87 -0
  24. package/dist/docs/api-reference/components/rich-text-menu-group.md +27 -0
  25. package/dist/docs/api-reference/components/rich-text-menu.md +99 -0
  26. package/dist/docs/api-reference/components.md +32 -0
  27. package/dist/docs/api-reference/configuration/component-config.md +569 -0
  28. package/dist/docs/api-reference/configuration/config.md +108 -0
  29. package/dist/docs/api-reference/configuration.md +4 -0
  30. package/dist/docs/api-reference/data-model/app-state.md +168 -0
  31. package/dist/docs/api-reference/data-model/component-data.md +62 -0
  32. package/dist/docs/api-reference/data-model/data.md +95 -0
  33. package/dist/docs/api-reference/data-model/item-selector.md +34 -0
  34. package/dist/docs/api-reference/data-model/root-data.md +59 -0
  35. package/dist/docs/api-reference/data-model.md +8 -0
  36. package/dist/docs/api-reference/dictionary.md +172 -0
  37. package/dist/docs/api-reference/field-transforms.md +51 -0
  38. package/dist/docs/api-reference/fields/array.md +211 -0
  39. package/dist/docs/api-reference/fields/base.md +96 -0
  40. package/dist/docs/api-reference/fields/custom.md +193 -0
  41. package/dist/docs/api-reference/fields/external.md +413 -0
  42. package/dist/docs/api-reference/fields/number.md +132 -0
  43. package/dist/docs/api-reference/fields/object.md +78 -0
  44. package/dist/docs/api-reference/fields/radio.md +82 -0
  45. package/dist/docs/api-reference/fields/richtext.md +422 -0
  46. package/dist/docs/api-reference/fields/select.md +79 -0
  47. package/dist/docs/api-reference/fields/slot.md +302 -0
  48. package/dist/docs/api-reference/fields/text.md +93 -0
  49. package/dist/docs/api-reference/fields/textarea.md +93 -0
  50. package/dist/docs/api-reference/fields.md +16 -0
  51. package/dist/docs/api-reference/functions/migrate.md +204 -0
  52. package/dist/docs/api-reference/functions/register-overlay-portal.md +45 -0
  53. package/dist/docs/api-reference/functions/resolve-all-data.md +27 -0
  54. package/dist/docs/api-reference/functions/set-deep.md +55 -0
  55. package/dist/docs/api-reference/functions/transform-props.md +51 -0
  56. package/dist/docs/api-reference/functions/use-get-puck.md +24 -0
  57. package/dist/docs/api-reference/functions/use-puck.md +43 -0
  58. package/dist/docs/api-reference/functions/walk-tree.md +88 -0
  59. package/dist/docs/api-reference/functions.md +8 -0
  60. package/dist/docs/api-reference/overrides/action-bar.md +35 -0
  61. package/dist/docs/api-reference/overrides/component-overlay.md +41 -0
  62. package/dist/docs/api-reference/overrides/drawer-item.md +24 -0
  63. package/dist/docs/api-reference/overrides/drawer.md +19 -0
  64. package/dist/docs/api-reference/overrides/field-label.md +18 -0
  65. package/dist/docs/api-reference/overrides/field-types.md +51 -0
  66. package/dist/docs/api-reference/overrides/fields.md +19 -0
  67. package/dist/docs/api-reference/overrides/header-actions.md +24 -0
  68. package/dist/docs/api-reference/overrides/header.md +29 -0
  69. package/dist/docs/api-reference/overrides/iframe.md +32 -0
  70. package/dist/docs/api-reference/overrides/outline.md +19 -0
  71. package/dist/docs/api-reference/overrides/preview.md +19 -0
  72. package/dist/docs/api-reference/overrides/puck.md +19 -0
  73. package/dist/docs/api-reference/overrides.md +28 -0
  74. package/dist/docs/api-reference/permissions.md +55 -0
  75. package/dist/docs/api-reference/plugin.md +112 -0
  76. package/dist/docs/api-reference/plugins/blocks-plugin.md +57 -0
  77. package/dist/docs/api-reference/plugins/fields-plugin.md +68 -0
  78. package/dist/docs/api-reference/plugins/legacy-side-bar-plugin.md +54 -0
  79. package/dist/docs/api-reference/plugins/outline-plugin.md +57 -0
  80. package/dist/docs/api-reference/puck-api.md +278 -0
  81. package/dist/docs/api-reference/theming/action-bar.md +32 -0
  82. package/dist/docs/api-reference/theming/button.md +65 -0
  83. package/dist/docs/api-reference/theming/canvas.md +20 -0
  84. package/dist/docs/api-reference/theming/computed-values.md +194 -0
  85. package/dist/docs/api-reference/theming/drawer.md +34 -0
  86. package/dist/docs/api-reference/theming/fields.md +70 -0
  87. package/dist/docs/api-reference/theming/global.md +127 -0
  88. package/dist/docs/api-reference/theming/header.md +19 -0
  89. package/dist/docs/api-reference/theming/icon-button.md +28 -0
  90. package/dist/docs/api-reference/theming/outline.md +35 -0
  91. package/dist/docs/api-reference/theming/plugin-bar.md +24 -0
  92. package/dist/docs/api-reference/theming/sidebar.md +19 -0
  93. package/dist/docs/api-reference/theming/slot.md +27 -0
  94. package/dist/docs/cli.md +201 -0
  95. package/dist/docs/extending-puck/composition.md +54 -0
  96. package/dist/docs/extending-puck/custom-fields.md +133 -0
  97. package/dist/docs/extending-puck/field-transforms.md +89 -0
  98. package/dist/docs/extending-puck/internal-puck-api.md +96 -0
  99. package/dist/docs/extending-puck/plugins.md +159 -0
  100. package/dist/docs/extending-puck/theming.md +88 -0
  101. package/dist/docs/extending-puck/ui-overrides.md +134 -0
  102. package/dist/docs/getting-started.md +68 -0
  103. package/dist/docs/guides/migrations/dropzones-to-slots.md +138 -0
  104. package/dist/docs/index.json +466 -0
  105. package/dist/docs/index.md +37 -0
  106. package/dist/docs/integrating-puck/categories.md +92 -0
  107. package/dist/docs/integrating-puck/component-configuration.md +159 -0
  108. package/dist/docs/integrating-puck/data-migration.md +86 -0
  109. package/dist/docs/integrating-puck/dynamic-fields.md +86 -0
  110. package/dist/docs/integrating-puck/dynamic-props.md +137 -0
  111. package/dist/docs/integrating-puck/external-data-sources.md +149 -0
  112. package/dist/docs/integrating-puck/feature-toggling.md +121 -0
  113. package/dist/docs/integrating-puck/localization.md +228 -0
  114. package/dist/docs/integrating-puck/multi-column-layouts.md +226 -0
  115. package/dist/docs/integrating-puck/overlay-portals.md +25 -0
  116. package/dist/docs/integrating-puck/rich-text-editing.md +230 -0
  117. package/dist/docs/integrating-puck/root-configuration.md +171 -0
  118. package/dist/docs/integrating-puck/server-components.md +199 -0
  119. package/dist/docs/integrating-puck/styling.md +117 -0
  120. package/dist/docs/integrating-puck/viewports.md +75 -0
  121. package/dist/templates/astro/README.md +52 -0
  122. package/dist/templates/astro/_gitignore +24 -0
  123. package/dist/templates/astro/astro.config.mjs +14 -0
  124. package/dist/templates/astro/database.json +1 -0
  125. package/dist/templates/astro/package.json +25 -0
  126. package/dist/templates/astro/public/favicon.svg +9 -0
  127. package/dist/templates/astro/src/lib/pages.ts +21 -0
  128. package/dist/templates/astro/src/lib/resolve-puck-path.ts +19 -0
  129. package/dist/templates/astro/src/pages/[...puckPath].astro +25 -0
  130. package/dist/templates/astro/src/pages/api/pages.ts +18 -0
  131. package/dist/templates/astro/src/puck/editor.tsx +32 -0
  132. package/dist/templates/astro/src/puck/pages.ts +15 -0
  133. package/dist/templates/astro/src/puck/render.tsx +9 -0
  134. package/dist/templates/astro/src/puck.config.tsx +23 -0
  135. package/dist/templates/astro/tsconfig.json +14 -0
  136. package/dist/templates/astro-ai/README.md +64 -0
  137. package/dist/templates/astro-ai/_gitignore +24 -0
  138. package/dist/templates/astro-ai/astro.config.mjs +21 -0
  139. package/dist/templates/astro-ai/database.json +1 -0
  140. package/dist/templates/astro-ai/package.json +27 -0
  141. package/dist/templates/astro-ai/public/favicon.svg +9 -0
  142. package/dist/templates/astro-ai/src/lib/pages.ts +21 -0
  143. package/dist/templates/astro-ai/src/lib/resolve-puck-path.ts +19 -0
  144. package/dist/templates/astro-ai/src/pages/[...puckPath].astro +25 -0
  145. package/dist/templates/astro-ai/src/pages/api/pages.ts +18 -0
  146. package/dist/templates/astro-ai/src/pages/api/puck/[...all].ts +36 -0
  147. package/dist/templates/astro-ai/src/puck/editor.tsx +53 -0
  148. package/dist/templates/astro-ai/src/puck/pages.ts +15 -0
  149. package/dist/templates/astro-ai/src/puck/render.tsx +10 -0
  150. package/dist/templates/astro-ai/src/puck.config.tsx +23 -0
  151. package/dist/templates/astro-ai/tsconfig.json +14 -0
  152. package/dist/templates/express/README.md +66 -0
  153. package/dist/templates/express/_gitignore +16 -0
  154. package/dist/templates/express/database.json +1 -0
  155. package/dist/templates/express/package.json +20 -0
  156. package/dist/templates/express/src/index.ts +15 -0
  157. package/dist/templates/express/src/puck/pages.ts +39 -0
  158. package/dist/templates/express/tsconfig.json +12 -0
  159. package/dist/templates/express-ai/README.md +81 -0
  160. package/dist/templates/express-ai/_gitignore +16 -0
  161. package/dist/templates/express-ai/database.json +1 -0
  162. package/dist/templates/express-ai/package.json +22 -0
  163. package/dist/templates/express-ai/src/index.ts +17 -0
  164. package/dist/templates/express-ai/src/puck/cloud.ts +71 -0
  165. package/dist/templates/express-ai/src/puck/pages.ts +39 -0
  166. package/dist/templates/express-ai/tsconfig.json +12 -0
  167. package/dist/templates/hono/README.md +66 -0
  168. package/dist/templates/hono/_gitignore +32 -0
  169. package/dist/templates/hono/database.json +1 -0
  170. package/dist/templates/hono/package.json +20 -0
  171. package/dist/templates/hono/src/index.ts +21 -0
  172. package/dist/templates/hono/src/puck/pages.ts +32 -0
  173. package/dist/templates/hono/tsconfig.json +13 -0
  174. package/dist/templates/hono-ai/README.md +81 -0
  175. package/dist/templates/hono-ai/_gitignore +32 -0
  176. package/dist/templates/hono-ai/database.json +1 -0
  177. package/dist/templates/hono-ai/package.json +22 -0
  178. package/dist/templates/hono-ai/src/index.ts +23 -0
  179. package/dist/templates/hono-ai/src/puck/cloud.ts +30 -0
  180. package/dist/templates/hono-ai/src/puck/pages.ts +32 -0
  181. package/dist/templates/hono-ai/tsconfig.json +13 -0
  182. package/dist/templates/manifest.json +4 -0
  183. package/dist/templates/next/README.md +112 -0
  184. package/dist/templates/next/_gitignore +35 -0
  185. package/dist/templates/next/app/[...puckPath]/client.tsx +9 -0
  186. package/dist/templates/next/app/[...puckPath]/page.tsx +49 -0
  187. package/dist/templates/next/app/favicon.ico +0 -0
  188. package/dist/templates/next/app/layout.tsx +13 -0
  189. package/dist/templates/next/app/page.tsx +1 -0
  190. package/dist/templates/next/app/puck/[...puckPath]/client.tsx +20 -0
  191. package/dist/templates/next/app/puck/[...puckPath]/page.tsx +55 -0
  192. package/dist/templates/next/app/puck/api/route.ts +25 -0
  193. package/dist/templates/next/app/puck/page.tsx +3 -0
  194. package/dist/templates/next/app/styles.css +3 -0
  195. package/dist/templates/next/database.json +1 -0
  196. package/dist/templates/next/lib/get-page.ts +11 -0
  197. package/dist/templates/next/next.config.js +3 -0
  198. package/dist/templates/next/package.json +25 -0
  199. package/dist/templates/next/proxy.ts +27 -0
  200. package/dist/templates/next/puck.config.tsx +25 -0
  201. package/dist/templates/next/tsconfig/base.json +20 -0
  202. package/dist/templates/next/tsconfig/nextjs.json +21 -0
  203. package/dist/templates/next/tsconfig.json +8 -0
  204. package/dist/templates/next-ai/README.md +169 -0
  205. package/dist/templates/next-ai/_gitignore +35 -0
  206. package/dist/templates/next-ai/app/[...puckPath]/client.tsx +12 -0
  207. package/dist/templates/next-ai/app/[...puckPath]/page.tsx +49 -0
  208. package/dist/templates/next-ai/app/api/pages/route.ts +26 -0
  209. package/dist/templates/next-ai/app/api/puck/[...all]/route.ts +31 -0
  210. package/dist/templates/next-ai/app/layout.tsx +13 -0
  211. package/dist/templates/next-ai/app/page.tsx +1 -0
  212. package/dist/templates/next-ai/app/puck/[...puckPath]/client.tsx +38 -0
  213. package/dist/templates/next-ai/app/puck/[...puckPath]/page.tsx +57 -0
  214. package/dist/templates/next-ai/app/puck/page.tsx +3 -0
  215. package/dist/templates/next-ai/app/styles.css +3 -0
  216. package/dist/templates/next-ai/database.json +1 -0
  217. package/dist/templates/next-ai/lib/get-page.ts +11 -0
  218. package/dist/templates/next-ai/next.config.js +3 -0
  219. package/dist/templates/next-ai/package.json +27 -0
  220. package/dist/templates/next-ai/proxy.ts +27 -0
  221. package/dist/templates/next-ai/public/favicon.ico +0 -0
  222. package/dist/templates/next-ai/puck.config.tsx +25 -0
  223. package/dist/templates/next-ai/tsconfig/base.json +20 -0
  224. package/dist/templates/next-ai/tsconfig/nextjs.json +21 -0
  225. package/dist/templates/next-ai/tsconfig.json +8 -0
  226. package/dist/templates/react-router/README.md +113 -0
  227. package/dist/templates/react-router/_gitignore +6 -0
  228. package/dist/templates/react-router/app/components/puck-render.tsx +8 -0
  229. package/dist/templates/react-router/app/lib/pages.server.ts +29 -0
  230. package/dist/templates/react-router/app/lib/resolve-puck-path.server.ts +19 -0
  231. package/dist/templates/react-router/app/root.tsx +65 -0
  232. package/dist/templates/react-router/app/routes/_index.tsx +31 -0
  233. package/dist/templates/react-router/app/routes/puck-splat.tsx +95 -0
  234. package/dist/templates/react-router/app/routes.ts +7 -0
  235. package/dist/templates/react-router/database.json +1 -0
  236. package/dist/templates/react-router/package.json +33 -0
  237. package/dist/templates/react-router/public/favicon.ico +0 -0
  238. package/dist/templates/react-router/puck.config.tsx +23 -0
  239. package/dist/templates/react-router/react-router.config.ts +7 -0
  240. package/dist/templates/react-router/tsconfig.json +29 -0
  241. package/dist/templates/react-router/vite.config.ts +10 -0
  242. package/dist/templates/react-router-ai/README.md +172 -0
  243. package/dist/templates/react-router-ai/_gitignore +6 -0
  244. package/dist/templates/react-router-ai/app/components/puck-render.tsx +11 -0
  245. package/dist/templates/react-router-ai/app/lib/pages.server.ts +29 -0
  246. package/dist/templates/react-router-ai/app/lib/resolve-puck-path.server.ts +19 -0
  247. package/dist/templates/react-router-ai/app/root.tsx +65 -0
  248. package/dist/templates/react-router-ai/app/routes/_index.tsx +31 -0
  249. package/dist/templates/react-router-ai/app/routes/api.puck.ts +34 -0
  250. package/dist/templates/react-router-ai/app/routes/puck-splat.tsx +119 -0
  251. package/dist/templates/react-router-ai/app/routes.ts +8 -0
  252. package/dist/templates/react-router-ai/database.json +1 -0
  253. package/dist/templates/react-router-ai/package.json +35 -0
  254. package/dist/templates/react-router-ai/public/favicon.ico +0 -0
  255. package/dist/templates/react-router-ai/puck.config.tsx +25 -0
  256. package/dist/templates/react-router-ai/react-router.config.ts +7 -0
  257. package/dist/templates/react-router-ai/tsconfig.json +29 -0
  258. package/dist/templates/react-router-ai/vite.config.ts +10 -0
  259. package/dist/templates/tanstack-start/README.md +113 -0
  260. package/dist/templates/tanstack-start/_gitignore +12 -0
  261. package/dist/templates/tanstack-start/database.json +1 -0
  262. package/dist/templates/tanstack-start/package.json +26 -0
  263. package/dist/templates/tanstack-start/puck.config.tsx +23 -0
  264. package/dist/templates/tanstack-start/src/components/puck-render.tsx +8 -0
  265. package/dist/templates/tanstack-start/src/lib/pages.server.ts +26 -0
  266. package/dist/templates/tanstack-start/src/lib/pages.ts +39 -0
  267. package/dist/templates/tanstack-start/src/lib/resolve-puck-path.ts +19 -0
  268. package/dist/templates/tanstack-start/src/routeTree.gen.ts +86 -0
  269. package/dist/templates/tanstack-start/src/router.tsx +19 -0
  270. package/dist/templates/tanstack-start/src/routes/$.tsx +41 -0
  271. package/dist/templates/tanstack-start/src/routes/__root.tsx +42 -0
  272. package/dist/templates/tanstack-start/src/routes/index.tsx +18 -0
  273. package/dist/templates/tanstack-start/src/styles.css +13 -0
  274. package/dist/templates/tanstack-start/tsconfig.json +24 -0
  275. package/dist/templates/tanstack-start/vite.config.ts +15 -0
  276. package/dist/templates/tanstack-start-ai/README.md +171 -0
  277. package/dist/templates/tanstack-start-ai/_gitignore +12 -0
  278. package/dist/templates/tanstack-start-ai/database.json +1 -0
  279. package/dist/templates/tanstack-start-ai/package.json +28 -0
  280. package/dist/templates/tanstack-start-ai/puck.config.tsx +23 -0
  281. package/dist/templates/tanstack-start-ai/src/components/puck-render.tsx +11 -0
  282. package/dist/templates/tanstack-start-ai/src/lib/pages.server.ts +26 -0
  283. package/dist/templates/tanstack-start-ai/src/lib/pages.ts +39 -0
  284. package/dist/templates/tanstack-start-ai/src/lib/resolve-puck-path.ts +19 -0
  285. package/dist/templates/tanstack-start-ai/src/routeTree.gen.ts +104 -0
  286. package/dist/templates/tanstack-start-ai/src/router.tsx +19 -0
  287. package/dist/templates/tanstack-start-ai/src/routes/$.tsx +73 -0
  288. package/dist/templates/tanstack-start-ai/src/routes/__root.tsx +42 -0
  289. package/dist/templates/tanstack-start-ai/src/routes/api/puck/$.ts +39 -0
  290. package/dist/templates/tanstack-start-ai/src/routes/index.tsx +18 -0
  291. package/dist/templates/tanstack-start-ai/src/styles.css +13 -0
  292. package/dist/templates/tanstack-start-ai/tsconfig.json +24 -0
  293. package/dist/templates/tanstack-start-ai/vite.config.ts +15 -0
  294. package/dist/templates/vinext/README.md +112 -0
  295. package/dist/templates/vinext/_gitignore +33 -0
  296. package/dist/templates/vinext/app/[...puckPath]/client.tsx +9 -0
  297. package/dist/templates/vinext/app/[...puckPath]/page.tsx +49 -0
  298. package/dist/templates/vinext/app/favicon.ico +0 -0
  299. package/dist/templates/vinext/app/layout.tsx +13 -0
  300. package/dist/templates/vinext/app/page.tsx +1 -0
  301. package/dist/templates/vinext/app/puck/[...puckPath]/client.tsx +20 -0
  302. package/dist/templates/vinext/app/puck/[...puckPath]/page.tsx +55 -0
  303. package/dist/templates/vinext/app/puck/api/route.ts +25 -0
  304. package/dist/templates/vinext/app/puck/page.tsx +3 -0
  305. package/dist/templates/vinext/app/styles.css +3 -0
  306. package/dist/templates/vinext/database.json +1 -0
  307. package/dist/templates/vinext/lib/get-page.ts +11 -0
  308. package/dist/templates/vinext/package.json +30 -0
  309. package/dist/templates/vinext/proxy.ts +27 -0
  310. package/dist/templates/vinext/puck.config.tsx +25 -0
  311. package/dist/templates/vinext/tsconfig.json +30 -0
  312. package/dist/templates/vinext/vite.config.ts +6 -0
  313. package/dist/templates/vinext-ai/README.md +169 -0
  314. package/dist/templates/vinext-ai/_gitignore +33 -0
  315. package/dist/templates/vinext-ai/app/[...puckPath]/client.tsx +12 -0
  316. package/dist/templates/vinext-ai/app/[...puckPath]/page.tsx +49 -0
  317. package/dist/templates/vinext-ai/app/api/pages/route.ts +26 -0
  318. package/dist/templates/vinext-ai/app/api/puck/[...all]/route.ts +31 -0
  319. package/dist/templates/vinext-ai/app/layout.tsx +13 -0
  320. package/dist/templates/vinext-ai/app/page.tsx +1 -0
  321. package/dist/templates/vinext-ai/app/puck/[...puckPath]/client.tsx +38 -0
  322. package/dist/templates/vinext-ai/app/puck/[...puckPath]/page.tsx +57 -0
  323. package/dist/templates/vinext-ai/app/puck/page.tsx +3 -0
  324. package/dist/templates/vinext-ai/app/styles.css +3 -0
  325. package/dist/templates/vinext-ai/database.json +1 -0
  326. package/dist/templates/vinext-ai/lib/get-page.ts +11 -0
  327. package/dist/templates/vinext-ai/package.json +32 -0
  328. package/dist/templates/vinext-ai/proxy.ts +27 -0
  329. package/dist/templates/vinext-ai/public/favicon.ico +0 -0
  330. package/dist/templates/vinext-ai/puck.config.tsx +25 -0
  331. package/dist/templates/vinext-ai/tsconfig.json +30 -0
  332. package/dist/templates/vinext-ai/vite.config.ts +9 -0
  333. package/dist/templates/vite/README.md +56 -0
  334. package/dist/templates/vite/_gitignore +24 -0
  335. package/dist/templates/vite/database.json +1 -0
  336. package/dist/templates/vite/index.html +12 -0
  337. package/dist/templates/vite/package.json +29 -0
  338. package/dist/templates/vite/server/index.ts +13 -0
  339. package/dist/templates/vite/server/prod.ts +18 -0
  340. package/dist/templates/vite/server/puck/pages.ts +32 -0
  341. package/dist/templates/vite/src/App.tsx +11 -0
  342. package/dist/templates/vite/src/main.tsx +12 -0
  343. package/dist/templates/vite/src/puck/editor.tsx +28 -0
  344. package/dist/templates/vite/src/puck/page.tsx +27 -0
  345. package/dist/templates/vite/src/puck/pages.ts +15 -0
  346. package/dist/templates/vite/src/puck/root.tsx +27 -0
  347. package/dist/templates/vite/src/puck.config.tsx +23 -0
  348. package/dist/templates/vite/tsconfig.app.json +26 -0
  349. package/dist/templates/vite/tsconfig.json +7 -0
  350. package/dist/templates/vite/tsconfig.node.json +23 -0
  351. package/dist/templates/vite/vite.config.ts +14 -0
  352. package/dist/templates/vite-ai/README.md +67 -0
  353. package/dist/templates/vite-ai/_gitignore +24 -0
  354. package/dist/templates/vite-ai/database.json +1 -0
  355. package/dist/templates/vite-ai/index.html +12 -0
  356. package/dist/templates/vite-ai/package.json +31 -0
  357. package/dist/templates/vite-ai/server/index.ts +15 -0
  358. package/dist/templates/vite-ai/server/prod.ts +18 -0
  359. package/dist/templates/vite-ai/server/puck/cloud.ts +30 -0
  360. package/dist/templates/vite-ai/server/puck/pages.ts +32 -0
  361. package/dist/templates/vite-ai/src/App.tsx +11 -0
  362. package/dist/templates/vite-ai/src/main.tsx +12 -0
  363. package/dist/templates/vite-ai/src/puck/editor.tsx +49 -0
  364. package/dist/templates/vite-ai/src/puck/page.tsx +28 -0
  365. package/dist/templates/vite-ai/src/puck/pages.ts +15 -0
  366. package/dist/templates/vite-ai/src/puck/root.tsx +27 -0
  367. package/dist/templates/vite-ai/src/puck.config.tsx +23 -0
  368. package/dist/templates/vite-ai/tsconfig.app.json +26 -0
  369. package/dist/templates/vite-ai/tsconfig.json +7 -0
  370. package/dist/templates/vite-ai/tsconfig.node.json +23 -0
  371. package/dist/templates/vite-ai/vite.config.ts +14 -0
  372. package/package.json +51 -0
@@ -0,0 +1,92 @@
1
+ # Categories
2
+
3
+ Categories allow you to group components in the left side bar.
4
+
5
+ ## Creating categories
6
+
7
+ Use the [`categories` API](/docs/api-reference/configuration/config#categories) to define the component categories.
8
+
9
+ ```tsx
10
+ const config = {
11
+ categories: {
12
+ typography: {
13
+ components: ["HeadingBlock", "ParagraphBlock"],
14
+ },
15
+ },
16
+ // ...
17
+ };
18
+ ```
19
+
20
+ Components can appear in separate categories:
21
+
22
+ ```tsx
23
+ const config = {
24
+ categories: {
25
+ typography: {
26
+ components: ["HeadingBlock", "ParagraphBlock"],
27
+ },
28
+ foundational: {
29
+ components: ["HeadingBlock"],
30
+ },
31
+ },
32
+ // ...
33
+ };
34
+ ```
35
+
36
+ You can also change the title, collapse and hide categories:
37
+
38
+ ```tsx
39
+ const config = {
40
+ categories: {
41
+ typography: {
42
+ components: ["HeadingBlock", "ParagraphBlock"],
43
+ title: "Text",
44
+ defaultExpanded: false, // Collapse this category by default
45
+ },
46
+ foundational: {
47
+ components: ["HeadingBlock"],
48
+ visible: false, // Mark this category as hidden
49
+ },
50
+ },
51
+ // ...
52
+ };
53
+ ```
54
+
55
+ ## The "other" category
56
+
57
+ Any uncategorized components will be grouped in the `other` category. This will be visible by default. It respects the same API as other categories.
58
+
59
+ ```tsx
60
+ const config = {
61
+ categories: {
62
+ typography: {
63
+ components: ["HeadingBlock", "ParagraphBlock"],
64
+ },
65
+ other: {
66
+ title: "Other components",
67
+ },
68
+ },
69
+ // ...
70
+ };
71
+ ```
72
+
73
+ ## TypeScript
74
+
75
+ You can pass in available category names to the `Config` type if using TypeScript
76
+
77
+ ```tsx
78
+ import type { Config } from "@puckeditor/core";
79
+
80
+ const config: Config<{}, {}, "typography" | "interactive"> = {
81
+ categories: {
82
+ typography: {},
83
+ interactive: {},
84
+ },
85
+ // ...
86
+ };
87
+ ```
88
+
89
+ ## Further reading
90
+
91
+ - [`categories` API reference](/docs/api-reference/configuration/config#categories)
92
+ - [`renderComponentList` API reference](/docs/api-reference/components/puck#rendercomponentlistparams)
@@ -0,0 +1,159 @@
1
+ # Component Configuration
2
+
3
+ Puck's core behaviour is configured via the [Config](/docs/api-reference/configuration/config). This describes:
4
+
5
+ - which components are available to Puck
6
+ - how to render each component
7
+ - which fields to show when the user selects a component
8
+ - additional information, like [category grouping](/docs/integrating-puck/categories)
9
+
10
+ The [Config](/docs/api-reference/configuration/config) is provided via the `config` prop to the main Puck components:
11
+
12
+ - [`<Puck>`](/docs/api-reference/components/puck) reads the Config and renders an editor UI. The user interacts with the editor to produce a [data payload](/docs/api-reference/data-model/data).
13
+ - [`<Render>`](/docs/api-reference/components/render) takes a [data payload](/docs/api-reference/data-model/data) and renders it according to the provided Config.
14
+
15
+ ## The `render` function
16
+
17
+ Components can be defined via the `components` object in [Config](/docs/api-reference/configuration/config). Every definition must provide a [`render` function](/docs/api-reference/configuration/component-config#renderprops):
18
+
19
+ ```tsx
20
+ const config = {
21
+ components: {
22
+ HeadingBlock: {
23
+ render: () => {
24
+ return <h1>Hello, world</h1>;
25
+ },
26
+ },
27
+ },
28
+ };
29
+ ```
30
+
31
+ This tells Puck that **HeadingBlock** is a valid component, and describes how to render it.
32
+
33
+ When the user drags the component onto the preview and hits **Publish** in the editor UI via the `<Puck>` component, this Config will produce a [data payload](/docs/api-reference/data-model/data) like this:
34
+
35
+ ```json
36
+ {
37
+ "content": [
38
+ {
39
+ "type": "HeadingBlock",
40
+ "props": {
41
+ "id": "HeadingBlock-1234"
42
+ }
43
+ }
44
+ ],
45
+ "root": {}
46
+ }
47
+ ```
48
+
49
+ The data payload and Config together tell `<Render>` how to render the page. It can also be provided to `<Puck>` as an [initial `data` payload](/docs/api-reference/components/puck#data).
50
+
51
+ ### TypeScript
52
+
53
+ If you're using TypeScript, we recommend strictly typing your config:
54
+
55
+ ```tsx
56
+ import type { Config } from "@puckeditor/core";
57
+
58
+ type Components = {
59
+ HeadingBlock: {};
60
+ };
61
+
62
+ const config: Config<Components> = {
63
+ components: {
64
+ HeadingBlock: {
65
+ render: () => {
66
+ return <h1>Hello, world</h1>;
67
+ },
68
+ },
69
+ },
70
+ };
71
+ ```
72
+
73
+ ## Adding fields
74
+
75
+ [Fields](/docs/api-reference/fields) allow users to provide input to components. The value of each field is passed in as a prop to the `render` function.
76
+
77
+ You can define a field via the [`fields` parameter](/docs/api-reference/configuration/component-config#fields):
78
+
79
+ ```tsx
80
+ const config = {
81
+ components: {
82
+ HeadingBlock: {
83
+ fields: {
84
+ title: {
85
+ type: "text",
86
+ },
87
+ },
88
+ render: ({ title }) => {
89
+ return <h1>{title}</h1>;
90
+ },
91
+ },
92
+ },
93
+ };
94
+ ```
95
+
96
+ This will render a [Text field](/docs/api-reference/fields/text) when the user selects an instance of the **HeadingBlock** component in the editor UI.
97
+
98
+ When the user modifies the input, the editor will produce a data payload like this:
99
+
100
+ ```json
101
+ {
102
+ "content": [
103
+ {
104
+ "type": "HeadingBlock",
105
+ "props": {
106
+ "id": "HeadingBlock-1234",
107
+ "title": "Hello, world"
108
+ }
109
+ }
110
+ ],
111
+ "root": {}
112
+ }
113
+ ```
114
+
115
+ ### TypeScript
116
+
117
+ It's best to define the props for the component if using TypeScript. This enables strict type checking for your fields.
118
+
119
+ ```tsx
120
+ import type { Config } from "@puckeditor/core";
121
+
122
+ type Components = {
123
+ HeadingBlock: {
124
+ title: string;
125
+ };
126
+ };
127
+
128
+ const config: Config<Components> = {
129
+ // ...
130
+ };
131
+ ```
132
+
133
+ ## Setting default props
134
+
135
+ Default props allow you to set an initial value for a prop when a new component is added.
136
+
137
+ Provide an object to the [`defaultProps`](/docs/api-reference/configuration/component-config#fields) parameter to configure this:
138
+
139
+ ```tsx
140
+ const config = {
141
+ components: {
142
+ HeadingBlock: {
143
+ fields: {
144
+ title: {
145
+ type: "text",
146
+ },
147
+ },
148
+ defaultProps: {
149
+ title: "Hello, world",
150
+ },
151
+ render: ({ title }) => {
152
+ return <h1>{title}</h1>;
153
+ },
154
+ },
155
+ },
156
+ };
157
+ ```
158
+
159
+ Unlike [default parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters), `defaultProps` are stored in the data payload and will populate the Puck fields.
@@ -0,0 +1,86 @@
1
+ # Data Migration
2
+
3
+ ## Version migrating
4
+
5
+ Puck follows semantic versioning. Major releases may introduce breaking changes for your Data payload.
6
+
7
+ Puck provides the [`migrate`](/docs/api-reference/functions/migrate) helper method to help migrate legacy data payloads to the latest data model, transforming any deprecated properties to their latest counterparts as described by the [Data API reference](/docs/api-reference/data-model/data).
8
+
9
+ ```tsx
10
+ import { migrate } from "@puckeditor/core";
11
+
12
+ migrate(legacyData);
13
+ ```
14
+
15
+ ## Breaking changes to props
16
+
17
+ Renaming or removing the props passed to your components are considered breaking changes. Any existing [Data](/docs/api-reference/data-model/data) payloads that reference these props will be unable to render.
18
+
19
+ There are two strategies for dealing with this:
20
+
21
+ 1. Retaining backwards-compatible props
22
+ 2. Implementing a prop migration
23
+
24
+ ### Retaining backwards-compatibility
25
+
26
+ The easiest way to avoid breaking changes is to implement your prop changes in a backwards compatible manor:
27
+
28
+ ```tsx
29
+ const config = {
30
+ HeadingBlock: ({ title, heading }) => <h1>{heading || title}</h1>,
31
+ };
32
+ ```
33
+
34
+ ### Implementing a prop migration
35
+
36
+ It will often be preferrable to update the underlying [Data](/docs/api-reference/data-model/data) payload. Puck provides the [`transformProps`](/docs/api-reference/functions/transform-props) utility method to conveniently transform the props for a given component throughout the payload.
37
+
38
+ ```tsx
39
+ import { transformProps } from "@puckeditor/core";
40
+
41
+ const config = {
42
+ // Renamed `title` prop to `heading`
43
+ HeadingBlock: ({ heading }) => <h1>{heading}</h1>,
44
+ };
45
+
46
+ const data = {
47
+ content: [
48
+ // HeadingBlock references the legacy `title` prop
49
+ { type: "HeadingBlock", props: { title: "Hello, world" } },
50
+ ],
51
+ };
52
+
53
+ const updatedData = transformProps(data, {
54
+ // Map `heading` to the legacy `title` prop
55
+ HeadingBlock: ({ title, ...props }) => ({ heading: title, ...props }),
56
+ });
57
+
58
+ console.log(updatedData);
59
+ // { content: [{ type: "HeadingBlock", props: { heading: "Hello, world" } }] };
60
+ ```
61
+
62
+ You may choose to run this transform every time you render your content, or perform a batch operation against your database.
63
+
64
+ File: `Example showing data being updated before rendering`
65
+
66
+ ```tsx
67
+ import { Puck, Render, transformProps } from "@puckeditor/core";
68
+
69
+ const transforms = {
70
+ HeadingBlock: ({ title, ...props }) => ({ heading: title, ...props }),
71
+ };
72
+
73
+ export const MyEditor = ({ data, config }) => (
74
+ <Puck data={transformProps(data, transforms)} config={config} />
75
+ );
76
+
77
+ export const MyPage = ({ data, config }) => (
78
+ <Render data={transformProps(data, transforms)} config={config} />
79
+ );
80
+ ```
81
+
82
+ ## Further reading
83
+
84
+ - [`Data` API reference](/docs/api-reference/data-model/data)
85
+ - [`migrate` API reference](/docs/api-reference/functions/migrate)
86
+ - [`transformProps` API reference](/docs/api-reference/functions/transform-props)
@@ -0,0 +1,86 @@
1
+ # Dynamic Fields
2
+
3
+ Dynamic field resolution allows you to change the [field configuration](/docs/api-reference/configuration/component-config#fields) for a component based on the current component props.
4
+
5
+ ## Dynamic component fields
6
+
7
+ The [`resolveFields` function](/docs/api-reference/configuration/component-config#resolvefieldsdata-params) allows you to make synchronous and asynchronous changes to the field configuration.
8
+
9
+ For example, we can set the configuration of one field based on the prop value of another:
10
+
11
+ ```tsx
12
+ const config = {
13
+ components: {
14
+ MyComponent: {
15
+ resolveFields: (data) => {
16
+ const fields = {
17
+ drink: {
18
+ type: "radio",
19
+ options: [
20
+ { label: "Water", value: "water" },
21
+ { label: "Orange juice", value: "orange-juice" },
22
+ ],
23
+ },
24
+ };
25
+
26
+ if (data.props.drink === "water") {
27
+ return {
28
+ ...fields,
29
+ waterType: {
30
+ // ... Define field
31
+ },
32
+ };
33
+ }
34
+
35
+ return fields;
36
+ },
37
+ // ...
38
+ },
39
+ },
40
+ };
41
+ ```
42
+
43
+ ### Making asynchronous calls
44
+
45
+ The [`resolveFields` function](/docs/api-reference/configuration/component-config#resolvefieldsdata-params) also enables asynchronous calls.
46
+
47
+ Here's an example populating the options for a [`select` field](/docs/api-reference/fields/select) based on a [`radio` field](/docs/api-reference/fields/radio)
48
+
49
+ ```tsx
50
+ const config = {
51
+ components: {
52
+ MyComponent: {
53
+ resolveFields: async (data, { changed, lastFields }) => {
54
+ // Don't call the API unless `category` has changed
55
+ if (!changed.category) return lastFields;
56
+
57
+ // Make an asynchronous API call to get the options
58
+ const options = await getOptions(data.category);
59
+
60
+ return {
61
+ category: {
62
+ type: "radio",
63
+ options: [
64
+ { label: "Fruit", value: "fruit" },
65
+ { label: "Vegetables", value: "vegetables" },
66
+ ],
67
+ },
68
+ item: {
69
+ type: "select",
70
+ options,
71
+ },
72
+ };
73
+ },
74
+ render: ({ item }) => <h1>{item}</h1>,
75
+ },
76
+ },
77
+ };
78
+ ```
79
+
80
+ ## Limitations
81
+
82
+ The [`slot` field](/docs/api-reference/fields/slot) is not currently supported by Dynamic Fields, but most use-cases can be achieved using [Dynamic Props](/docs/integrating-puck/dynamic-props).
83
+
84
+ ## Further reading
85
+
86
+ - [`resolveFields` API reference](/docs/api-reference/configuration/component-config#resolvefieldsdata-params)
@@ -0,0 +1,137 @@
1
+ # Dynamic Props
2
+
3
+ Dynamic prop resolution allows you to change the props for a component after the props have been changed by the user. This is useful for making third-party API calls, such as requesting the latest content from a headless CMS.
4
+
5
+ ## Dynamic component props
6
+
7
+ The [`resolveData` function](/docs/api-reference/configuration/component-config#resolvedatadata-params) allows you to make changes to the props and set fields as read-only.
8
+
9
+ For example, we can set the value of one prop to another:
10
+
11
+ ```tsx
12
+ const config = {
13
+ components: {
14
+ HeadingBlock: {
15
+ fields: {
16
+ title: {
17
+ type: "text",
18
+ },
19
+ resolvedTitle: {
20
+ type: "text",
21
+ },
22
+ },
23
+ resolveData: async ({ props }) => {
24
+ return {
25
+ props: {
26
+ resolvedTitle: props.title,
27
+ },
28
+ };
29
+ },
30
+ render: ({ resolvedTitle }) => {
31
+ return <h1>{resolvedTitle}</h1>;
32
+ },
33
+ },
34
+ },
35
+ };
36
+ ```
37
+
38
+ > When inserting components with `resolveData`, the Puck state will update twice - once for the initial insert, and once more when the method resolves, if it changes the data. This will be reflected in the undo/redo history.
39
+
40
+ ### Setting fields as read-only
41
+
42
+ [`resolveData`](/docs/api-reference/configuration/component-config#resolvedatadata-params) also allows us to mark fields as read-only using the [`readOnly` parameter](/docs/api-reference/configuration/component-config#datareadonly-1).
43
+
44
+ ```tsx
45
+ const config = {
46
+ components: {
47
+ HeadingBlock: {
48
+ // ...
49
+ resolveData: async ({ props }) => {
50
+ return {
51
+ props: {
52
+ resolvedTitle: props.title,
53
+ },
54
+ readOnly: { resolvedTitle: true },
55
+ };
56
+ },
57
+ // ...
58
+ },
59
+ },
60
+ };
61
+ ```
62
+
63
+ ### Preventing duplicate calls
64
+
65
+ It's possible that `resolveData` may carry out an expensive operation (like an API call) that we want to avoid making unless a specific prop has changed.
66
+
67
+ This can be restricted by checking the [`changed` param](/docs/api-reference/configuration/component-config#paramschanged) before calling any expensive operations.
68
+
69
+ ```tsx
70
+ const config = {
71
+ components: {
72
+ HeadingBlock: {
73
+ // ...
74
+ resolveData: async ({ props }, { changed }) => {
75
+ if (!changed.text) return { props };
76
+
77
+ return {
78
+ props: {
79
+ resolvedTitle: await expensiveOperation(props.title),
80
+ },
81
+ };
82
+ },
83
+ // ...
84
+ },
85
+ },
86
+ };
87
+ ```
88
+
89
+ ## Dynamic Root props
90
+
91
+ The `resolveData` method is also available on the [root component](/docs/api-reference/configuration/config#root).
92
+
93
+ ```tsx
94
+ const config = {
95
+ components: {},
96
+ root: {
97
+ fields: {
98
+ title: {
99
+ type: "text",
100
+ },
101
+ resolvedTitle: {
102
+ type: "text",
103
+ },
104
+ },
105
+ resolveData: async ({ props }) => {
106
+ return {
107
+ props: {
108
+ resolvedTitle: props.title,
109
+ },
110
+ };
111
+ },
112
+ render: ({ children, resolvedTitle }) => {
113
+ return (
114
+ <>
115
+ <h1>{resolvedTitle}</h1>
116
+ {children}
117
+ </>
118
+ );
119
+ },
120
+ },
121
+ };
122
+ ```
123
+
124
+ ## Triggering `resolveData`
125
+
126
+ Resolve data is triggered whenever the props for a component change, or when the [`resolveAllData` utility](/docs/api-reference/functions/resolve-all-data) is used.
127
+
128
+ ```tsx
129
+ import { resolveAllData } from "@puckeditor/core";
130
+
131
+ const updatedData = await resolveAllData(data, config);
132
+ ```
133
+
134
+ ## Further reading
135
+
136
+ - [`resolveData` API reference](/docs/api-reference/configuration/component-config#resolvedatadata-params)
137
+ - [`resolveAllData` API reference](/docs/api-reference/functions/resolve-all-data)
@@ -0,0 +1,149 @@
1
+ # External Data Sources
2
+
3
+ There are several different approaches for loading external data into a Puck component.
4
+
5
+ It's possible for Puck components to load their own data internally on the client, or on the server using [React server components](/docs/integrating-puck/server-components). This doesn't require any Puck configuration.
6
+
7
+ If you want to provide the user a way to select the data, you can use the [`external` field type](/docs/api-reference/fields/external).
8
+
9
+ ## Selecting external data
10
+
11
+ The [`external` field type](/docs/api-reference/fields/external) allows users to select tabular data from a third-party data source, like a headless CMS. This will load the data once and save it into the [data payload](/docs/api-reference/data-model/data).
12
+
13
+ ```tsx
14
+ const config = {
15
+ components: {
16
+ Example: {
17
+ fields: {
18
+ data: {
19
+ type: "external",
20
+ fetchList: async () => {
21
+ // Query an API for a list of items
22
+ const items = await fetch(`/api/items`).then((res) => res.json());
23
+ // [
24
+ // { title: "Hello, world", description: "Lorem ipsum 1" },
25
+ // { title: "Goodbye, world", description: "Lorem ipsum 2" },
26
+ // ];
27
+
28
+ return items;
29
+ },
30
+ },
31
+ },
32
+ render: ({ data }) => {
33
+ if (!data) {
34
+ return "No data selected";
35
+ }
36
+
37
+ return (
38
+ <>
39
+ <b>{data.title}</b>
40
+ <p>{data.description}</p>
41
+ </>
42
+ );
43
+ },
44
+ },
45
+ },
46
+ };
47
+ ```
48
+
49
+ You can also use the [`showSearch` parameter](/docs/api-reference/fields/external#showsearch) to show a search input to the user.
50
+
51
+ ## Data syncing
52
+
53
+ To keep the data in sync with the external source, we can combine the `external` field with the [`resolveData`](/docs/api-reference/configuration/component-config#resolvedatadata-params) function.
54
+
55
+ This technique re-fetches the content every time the page is loaded, or the [`resolveAllData` utility](/docs/api-reference/functions/resolve-all-data) is called.
56
+
57
+ ```tsx
58
+ const config = {
59
+ components: {
60
+ Example: {
61
+ fields: {
62
+ data: {
63
+ type: "external",
64
+ fetchList: async () => {
65
+ // Query an API for a list of items
66
+ const items = await fetch(`/api/items`).then((res) => res.json());
67
+ // [
68
+ // { title: "Hello, world", id: 0 },
69
+ // { title: "Goodbye, world", id: 1 },
70
+ // ];
71
+
72
+ return items;
73
+ },
74
+ },
75
+ },
76
+ resolveData: async ({ props }, { changed }) => {
77
+ if (!props.data) return { props };
78
+
79
+ // Don't query unless `data` has changed since resolveData was last run
80
+ if (!changed.data) return { props };
81
+
82
+ // Re-query the API for a particular item
83
+ const latestData = await fetch(`/api/items/${props.data.id}`).then(
84
+ (res) => res.json()
85
+ );
86
+ // { title: "Hello, world", description: "Lorem ipsum 1", id: 0 }
87
+
88
+ return {
89
+ props: {
90
+ // Update the value for `data`
91
+ data: latestData,
92
+ },
93
+ };
94
+ },
95
+ // ...
96
+ },
97
+ },
98
+ };
99
+ ```
100
+
101
+ ## Hybrid authoring
102
+
103
+ Hybrid authoring enables users to edit fields inline, or populate those fields with data from an external source.
104
+
105
+ This can be achieved by mapping the data from `data.title` to `title` in [`resolveData`](/docs/api-reference/configuration/component-config#resolvedatadata-params), and marking the field as read-only.
106
+
107
+ ```tsx
108
+ const config = {
109
+ components: {
110
+ Example: {
111
+ fields: {
112
+ data: {
113
+ // ...
114
+ },
115
+ title: {
116
+ type: "text",
117
+ },
118
+ },
119
+ resolveData: async ({ props }, { changed }) => {
120
+ // Remove read-only from the title field if `data` is empty
121
+ if (!props.data) return { props, readOnly: { title: false } };
122
+
123
+ // Don't query unless `data` has changed since resolveData was last run
124
+ if (!changed.data) return { props };
125
+
126
+ return {
127
+ props: {
128
+ title: props.data.title,
129
+ readOnly: { title: true },
130
+ },
131
+ };
132
+ },
133
+ render: ({ title }) => <b>{title}</b>,
134
+ },
135
+ },
136
+ };
137
+ ```
138
+
139
+ ## External data packages
140
+
141
+ We provide helper packages to load data from common data sources.
142
+
143
+ - [`contentful`](https://github.com/puckeditor/puck/tree/main/packages/field-contentful): Select content entries from a [Contentful](https://www.contentful.com) space.
144
+
145
+ ## Further reading
146
+
147
+ - [`external` field API reference](/docs/api-reference/fields/external)
148
+ - [`resolveData` API reference](/docs/api-reference/configuration/component-config#resolvedatadata-params)
149
+ - [`resolveAllData` API reference](/docs/api-reference/functions/resolve-all-data)