@delmaredigital/payload-puck 0.6.24 → 0.6.26
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.
- package/dist/admin/PuckEditorView.d.ts +10 -1
- package/dist/admin/PuckEditorView.js +2 -2
- package/dist/endpoints/index.d.ts +7 -0
- package/dist/endpoints/index.js +33 -9
- package/dist/plugin/index.js +7 -2
- package/dist/types/index.d.ts +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/views/PuckEditorView.js +5 -2
- package/package.json +8 -8
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Config as PuckConfig, Data, Plugin as PuckPlugin } from '@puckeditor/core';
|
|
2
|
+
import type { RootPropsMapping } from '../api/types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Props for the PuckEditorView component
|
|
4
5
|
*/
|
|
@@ -52,6 +53,14 @@ export interface PuckEditorViewProps {
|
|
|
52
53
|
* Callback on save error
|
|
53
54
|
*/
|
|
54
55
|
onSaveError?: (error: Error) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Custom root.props ↔ Payload field mappings, merged with the defaults.
|
|
58
|
+
*
|
|
59
|
+
* Must match the `rootPropsMapping` passed to the API routes / plugin so the
|
|
60
|
+
* editor hydrates the same fields it persists on save — otherwise
|
|
61
|
+
* custom-mapped fields appear to revert after publish.
|
|
62
|
+
*/
|
|
63
|
+
rootPropsMapping?: RootPropsMapping[];
|
|
55
64
|
}
|
|
56
65
|
/**
|
|
57
66
|
* Ready-to-use Puck editor page component
|
|
@@ -80,5 +89,5 @@ export interface PuckEditorViewProps {
|
|
|
80
89
|
* }
|
|
81
90
|
* ```
|
|
82
91
|
*/
|
|
83
|
-
export declare function PuckEditorView({ config, collectionSlug, apiBasePath, backUrl, previewUrl, layoutStyles, layoutKey, plugins, onSaveSuccess, onSaveError, }: PuckEditorViewProps): import("react").JSX.Element;
|
|
92
|
+
export declare function PuckEditorView({ config, collectionSlug, apiBasePath, backUrl, previewUrl, layoutStyles, layoutKey, plugins, onSaveSuccess, onSaveError, rootPropsMapping, }: PuckEditorViewProps): import("react").JSX.Element;
|
|
84
93
|
export default PuckEditorView;
|
|
@@ -29,7 +29,7 @@ import { mapPayloadFieldsToRootProps } from '../api/utils/mapRootProps.js';
|
|
|
29
29
|
* )
|
|
30
30
|
* }
|
|
31
31
|
* ```
|
|
32
|
-
*/ export function PuckEditorView({ config, collectionSlug = 'pages', apiBasePath = '/api/puck', backUrl, previewUrl, layoutStyles, layoutKey = 'pageLayout', plugins, onSaveSuccess, onSaveError }) {
|
|
32
|
+
*/ export function PuckEditorView({ config, collectionSlug = 'pages', apiBasePath = '/api/puck', backUrl, previewUrl, layoutStyles, layoutKey = 'pageLayout', plugins, onSaveSuccess, onSaveError, rootPropsMapping }) {
|
|
33
33
|
const params = useParams();
|
|
34
34
|
const searchParams = useSearchParams();
|
|
35
35
|
// Get page ID from route params or search params
|
|
@@ -203,7 +203,7 @@ import { mapPayloadFieldsToRootProps } from '../api/utils/mapRootProps.js';
|
|
|
203
203
|
// Hydrate root.props from Payload fields — ensures saved values like pageLayout,
|
|
204
204
|
// isHomepage, conversion settings etc. are reflected in the editor UI even if
|
|
205
205
|
// they weren't stored in puckData (Puck may strip props that match defaults)
|
|
206
|
-
const payloadRootProps = mapPayloadFieldsToRootProps(page);
|
|
206
|
+
const payloadRootProps = mapPayloadFieldsToRootProps(page, rootPropsMapping);
|
|
207
207
|
const initialData = {
|
|
208
208
|
...basePuckData,
|
|
209
209
|
root: {
|
|
@@ -8,8 +8,15 @@
|
|
|
8
8
|
* Payload's local API, so collection-level access rules are enforced.
|
|
9
9
|
*/
|
|
10
10
|
import type { PayloadHandler } from 'payload';
|
|
11
|
+
import type { RootPropsMapping } from '../api/types.js';
|
|
11
12
|
export interface PuckEndpointOptions {
|
|
12
13
|
collections: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Custom root.props → Payload field mappings, merged with the defaults.
|
|
16
|
+
* Lets fields edited via Puck root fields (e.g. conversionTracking) sync
|
|
17
|
+
* back to their Payload columns on save/publish.
|
|
18
|
+
*/
|
|
19
|
+
rootPropsMapping?: RootPropsMapping[];
|
|
13
20
|
}
|
|
14
21
|
/**
|
|
15
22
|
* GET /api/puck/:collection
|
package/dist/endpoints/index.js
CHANGED
|
@@ -9,6 +9,25 @@
|
|
|
9
9
|
*/ import { APIError } from 'payload';
|
|
10
10
|
import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepageUnique.js';
|
|
11
11
|
import { resolveLocale } from '../utils/locale.js';
|
|
12
|
+
import { mapRootPropsToPayloadFields, deepMerge } from '../api/utils/mapRootProps.js';
|
|
13
|
+
/**
|
|
14
|
+
* Merge a Puck save payload's `data` with the Payload fields derived from its
|
|
15
|
+
* `puckData.root.props`.
|
|
16
|
+
*
|
|
17
|
+
* Mapped fields form the base; the explicitly-sent fields (puckData, title,
|
|
18
|
+
* slug, isHomepage, folder, pageSegment) take precedence. Without this, fields
|
|
19
|
+
* exposed as Puck root fields (e.g. conversionTracking, meta, pageLayout) are
|
|
20
|
+
* persisted only inside the puckData blob and never reach their Payload
|
|
21
|
+
* columns — so they appear to "revert" on publish. Mirrors the sync performed
|
|
22
|
+
* by createPuckApiRoutesWithId's PATCH handler.
|
|
23
|
+
*/ function applyRootPropsMapping(data, rootPropsMapping) {
|
|
24
|
+
const rootProps = data?.puckData?.root?.props || {};
|
|
25
|
+
const mappedFields = mapRootPropsToPayloadFields(rootProps, rootPropsMapping);
|
|
26
|
+
const merged = {};
|
|
27
|
+
deepMerge(merged, mappedFields);
|
|
28
|
+
deepMerge(merged, data);
|
|
29
|
+
return merged;
|
|
30
|
+
}
|
|
12
31
|
/**
|
|
13
32
|
* GET /api/puck/:collection
|
|
14
33
|
* List all documents in a Puck-enabled collection
|
|
@@ -51,7 +70,7 @@ import { resolveLocale } from '../utils/locale.js';
|
|
|
51
70
|
* POST /api/puck/:collection
|
|
52
71
|
* Create a new document in a Puck-enabled collection
|
|
53
72
|
*/ export function createCreateHandler(options) {
|
|
54
|
-
const { collections } = options;
|
|
73
|
+
const { collections, rootPropsMapping } = options;
|
|
55
74
|
return async (req)=>{
|
|
56
75
|
try {
|
|
57
76
|
const collection = req.routeParams?.collection;
|
|
@@ -65,11 +84,12 @@ import { resolveLocale } from '../utils/locale.js';
|
|
|
65
84
|
const body = await req.json?.();
|
|
66
85
|
const { _locale, ...data } = body || {};
|
|
67
86
|
const locale = resolveLocale(req, _locale);
|
|
87
|
+
const createData = applyRootPropsMapping(data, rootPropsMapping);
|
|
68
88
|
const doc = await req.payload.create({
|
|
69
89
|
collection: collection,
|
|
70
90
|
req,
|
|
71
91
|
overrideAccess: false,
|
|
72
|
-
data,
|
|
92
|
+
data: createData,
|
|
73
93
|
draft: true,
|
|
74
94
|
...locale ? {
|
|
75
95
|
locale
|
|
@@ -133,7 +153,7 @@ import { resolveLocale } from '../utils/locale.js';
|
|
|
133
153
|
* PATCH /api/puck/:collection/:id
|
|
134
154
|
* Update a document (supports draft saving, publishing, and homepage swapping)
|
|
135
155
|
*/ export function createUpdateHandler(options) {
|
|
136
|
-
const { collections } = options;
|
|
156
|
+
const { collections, rootPropsMapping } = options;
|
|
137
157
|
return async (req)=>{
|
|
138
158
|
try {
|
|
139
159
|
const collection = req.routeParams?.collection;
|
|
@@ -150,10 +170,17 @@ import { resolveLocale } from '../utils/locale.js';
|
|
|
150
170
|
const locale = resolveLocale(req, _locale);
|
|
151
171
|
// Determine if this is a publish or draft save
|
|
152
172
|
const shouldPublish = _status === 'published';
|
|
173
|
+
// Sync Puck root.props → Payload fields (e.g. conversionTracking, meta,
|
|
174
|
+
// pageLayout) so values edited via Puck root fields persist to their
|
|
175
|
+
// columns on publish instead of living only inside the puckData blob.
|
|
176
|
+
const updateData = applyRootPropsMapping(data, rootPropsMapping);
|
|
177
|
+
updateData._status = shouldPublish ? 'published' : 'draft';
|
|
153
178
|
// Handle homepage swap if requested
|
|
154
179
|
// When swapHomepage is true and isHomepage is being set to true,
|
|
155
|
-
// we need to unset the current homepage first
|
|
156
|
-
|
|
180
|
+
// we need to unset the current homepage first. Read the resolved value
|
|
181
|
+
// from updateData so this works whether isHomepage arrived as a top-level
|
|
182
|
+
// field or was mapped in from root.props.
|
|
183
|
+
if (swapHomepage && updateData.isHomepage === true) {
|
|
157
184
|
// Find the current homepage
|
|
158
185
|
const existingHomepage = await req.payload.find({
|
|
159
186
|
collection: collection,
|
|
@@ -190,10 +217,7 @@ import { resolveLocale } from '../utils/locale.js';
|
|
|
190
217
|
req,
|
|
191
218
|
overrideAccess: false,
|
|
192
219
|
id,
|
|
193
|
-
data:
|
|
194
|
-
...data,
|
|
195
|
-
_status: shouldPublish ? 'published' : 'draft'
|
|
196
|
-
},
|
|
220
|
+
data: updateData,
|
|
197
221
|
draft: !shouldPublish,
|
|
198
222
|
context: {
|
|
199
223
|
// Skip the isHomepage hook if we've already handled the swap
|
package/dist/plugin/index.js
CHANGED
|
@@ -105,7 +105,7 @@ import { createContextListHandler, createContextCreateHandler, createContextUpda
|
|
|
105
105
|
* })
|
|
106
106
|
* ```
|
|
107
107
|
*/ export function createPuckPlugin(options = {}) {
|
|
108
|
-
const { pagesCollection = 'pages', autoGenerateCollection = true, admin: pluginAdminConfig = {}, enableAdminView = true, adminViewPath = '/puck-editor', enableEndpoints = true, pageTreeIntegration, editorStylesheet, editorStylesheetUrls = [], editorStylesheetCompiled, ai: aiConfig, previewUrl } = options;
|
|
108
|
+
const { pagesCollection = 'pages', autoGenerateCollection = true, admin: pluginAdminConfig = {}, enableAdminView = true, adminViewPath = '/puck-editor', enableEndpoints = true, pageTreeIntegration, editorStylesheet, editorStylesheetUrls = [], editorStylesheetCompiled, ai: aiConfig, previewUrl, rootPropsMapping } = options;
|
|
109
109
|
const { addEditButton = true } = pluginAdminConfig;
|
|
110
110
|
// Parse page-tree integration config
|
|
111
111
|
// - undefined: auto-detect at runtime (null stored, view will check for pageSegment field)
|
|
@@ -264,7 +264,8 @@ import { createContextListHandler, createContextCreateHandler, createContextUpda
|
|
|
264
264
|
pagesCollection
|
|
265
265
|
];
|
|
266
266
|
const endpointOptions = {
|
|
267
|
-
collections: puckCollections
|
|
267
|
+
collections: puckCollections,
|
|
268
|
+
rootPropsMapping
|
|
268
269
|
};
|
|
269
270
|
// Parameterized endpoint paths that should only exist once (with merged collections)
|
|
270
271
|
const parameterizedPuckPaths = new Set([
|
|
@@ -411,6 +412,10 @@ import { createContextListHandler, createContextCreateHandler, createContextUpda
|
|
|
411
412
|
pageTree: pageTreeConfig ?? incomingConfig.custom?.puck?.pageTree,
|
|
412
413
|
editorStylesheets: editorStylesheets.length > 0 ? editorStylesheets : incomingConfig.custom?.puck?.editorStylesheets,
|
|
413
414
|
previewUrl: previewUrl ?? incomingConfig.custom?.puck?.previewUrl,
|
|
415
|
+
// Custom root.props ↔ Payload field mappings. Stored so the editor
|
|
416
|
+
// load view can hydrate root.props from the same mappings the save
|
|
417
|
+
// endpoints use, keeping the round-trip symmetric for custom fields.
|
|
418
|
+
rootPropsMapping: rootPropsMapping ?? incomingConfig.custom?.puck?.rootPropsMapping,
|
|
414
419
|
ai: aiConfig?.enabled ? {
|
|
415
420
|
enabled: true,
|
|
416
421
|
context: aiConfig.context,
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Config as PuckConfig, Data as PuckData } from '@puckeditor/core';
|
|
|
3
3
|
import type { ThemeConfig } from '../theme/types.js';
|
|
4
4
|
import type { LayoutDefinition } from '../layouts/types.js';
|
|
5
5
|
import type { PuckPluginAiConfig } from '../ai/types.js';
|
|
6
|
+
import type { RootPropsMapping } from '../api/types.js';
|
|
6
7
|
/**
|
|
7
8
|
* Admin UI configuration for the Puck plugin
|
|
8
9
|
*/
|
|
@@ -96,6 +97,16 @@ export interface PuckPluginOptions {
|
|
|
96
97
|
* @default true
|
|
97
98
|
*/
|
|
98
99
|
enableEndpoints?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Custom mappings from Puck `root.props` to Payload collection fields.
|
|
102
|
+
*
|
|
103
|
+
* Merged with the built-in defaults (title, slug, meta.*, pageLayout,
|
|
104
|
+
* conversionTracking.*, etc.). Applied in both directions: Payload field →
|
|
105
|
+
* root.prop when loading the editor, and root.prop → Payload field when
|
|
106
|
+
* saving/publishing, so values edited via Puck root fields persist to their
|
|
107
|
+
* columns instead of living only inside the puckData blob.
|
|
108
|
+
*/
|
|
109
|
+
rootPropsMapping?: RootPropsMapping[];
|
|
99
110
|
/**
|
|
100
111
|
* Integration with @delmaredigital/payload-page-tree plugin
|
|
101
112
|
*
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.6.
|
|
1
|
+
export declare const VERSION = "0.6.26";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/generate-version.js - do not edit manually
|
|
2
|
-
export const VERSION = '0.6.
|
|
2
|
+
export const VERSION = '0.6.26';
|
|
@@ -63,6 +63,7 @@ import { mapPayloadFieldsToRootProps } from '../api/utils/mapRootProps.js';
|
|
|
63
63
|
const aiConfig = payload.config.custom?.puck?.ai;
|
|
64
64
|
const editorStylesheets = payload.config.custom?.puck?.editorStylesheets;
|
|
65
65
|
const previewUrlConfig = payload.config.custom?.puck?.previewUrl;
|
|
66
|
+
const rootPropsMapping = payload.config.custom?.puck?.rootPropsMapping;
|
|
66
67
|
// Fetch the page data
|
|
67
68
|
// Use depth: 1 if previewUrl is a function (may need relationship data like organization)
|
|
68
69
|
let page = null;
|
|
@@ -163,8 +164,10 @@ import { mapPayloadFieldsToRootProps } from '../api/utils/mapRootProps.js';
|
|
|
163
164
|
};
|
|
164
165
|
if (page) {
|
|
165
166
|
// Map Payload document fields to root.props format
|
|
166
|
-
// This ensures fields like title, slug, isHomepage, pageLayout are synced
|
|
167
|
-
|
|
167
|
+
// This ensures fields like title, slug, isHomepage, pageLayout are synced.
|
|
168
|
+
// Pass the configured custom mappings so the load direction mirrors the
|
|
169
|
+
// save endpoints (otherwise custom-mapped fields would appear to revert).
|
|
170
|
+
const syncedRootProps = mapPayloadFieldsToRootProps(page, rootPropsMapping);
|
|
168
171
|
// Handle folder ID specially (could be object or string)
|
|
169
172
|
if (pageTreeConfig && page.folder !== undefined) {
|
|
170
173
|
const folderId = typeof page.folder === 'object' ? page.folder?.id : page.folder;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delmaredigital/payload-puck",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.26",
|
|
4
4
|
"description": "Puck visual page builder plugin for Payload CMS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -152,9 +152,9 @@
|
|
|
152
152
|
}
|
|
153
153
|
},
|
|
154
154
|
"dependencies": {
|
|
155
|
-
"@puckeditor/cloud-client": "^0.
|
|
156
|
-
"@puckeditor/plugin-ai": "^0.
|
|
157
|
-
"@puckeditor/plugin-heading-analyzer": "^0.21.
|
|
155
|
+
"@puckeditor/cloud-client": "^0.7.0",
|
|
156
|
+
"@puckeditor/plugin-ai": "^0.7.0",
|
|
157
|
+
"@puckeditor/plugin-heading-analyzer": "^0.21.2",
|
|
158
158
|
"@radix-ui/react-popover": "^1.1.15",
|
|
159
159
|
"@tiptap/core": "^3.20.1",
|
|
160
160
|
"@tiptap/extension-color": "^3.20.1",
|
|
@@ -171,9 +171,9 @@
|
|
|
171
171
|
"lucide-react": "^0.469.0"
|
|
172
172
|
},
|
|
173
173
|
"devDependencies": {
|
|
174
|
-
"@payloadcms/next": "^3.
|
|
175
|
-
"@payloadcms/ui": "^3.
|
|
176
|
-
"@puckeditor/core": "^0.21.
|
|
174
|
+
"@payloadcms/next": "^3.84.1",
|
|
175
|
+
"@payloadcms/ui": "^3.84.1",
|
|
176
|
+
"@puckeditor/core": "^0.21.2",
|
|
177
177
|
"@swc/cli": "^0.6.0",
|
|
178
178
|
"@swc/core": "^1.15.18",
|
|
179
179
|
"@types/node": "^24.12.0",
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
"@types/react-dom": "^19.2.3",
|
|
182
182
|
"copyfiles": "^2.4.1",
|
|
183
183
|
"next": "^16.2.6",
|
|
184
|
-
"payload": "^3.
|
|
184
|
+
"payload": "^3.84.1",
|
|
185
185
|
"react": "^19.2.4",
|
|
186
186
|
"react-dom": "^19.2.4",
|
|
187
187
|
"typescript": "^5.9.3"
|