@commercetools-demo/puck-page-manager 0.1.0
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/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +413 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +387 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Config } from '@measured/puck';
|
|
3
|
+
|
|
4
|
+
interface PageManagerProps {
|
|
5
|
+
/** URL path where this manager is mounted, e.g. "/pages" — used as router basename */
|
|
6
|
+
parentUrl: string;
|
|
7
|
+
baseURL: string;
|
|
8
|
+
projectKey: string;
|
|
9
|
+
businessUnitKey: string;
|
|
10
|
+
jwtToken: string;
|
|
11
|
+
/** Puck component config — passed to editor and preview */
|
|
12
|
+
config: Config;
|
|
13
|
+
/** Optional element rendered before the breadcrumb in editor/preview headers */
|
|
14
|
+
backButton?: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
declare const PageManager: React.FC<PageManagerProps>;
|
|
17
|
+
|
|
18
|
+
export { PageManager, type PageManagerProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Config } from '@measured/puck';
|
|
3
|
+
|
|
4
|
+
interface PageManagerProps {
|
|
5
|
+
/** URL path where this manager is mounted, e.g. "/pages" — used as router basename */
|
|
6
|
+
parentUrl: string;
|
|
7
|
+
baseURL: string;
|
|
8
|
+
projectKey: string;
|
|
9
|
+
businessUnitKey: string;
|
|
10
|
+
jwtToken: string;
|
|
11
|
+
/** Puck component config — passed to editor and preview */
|
|
12
|
+
config: Config;
|
|
13
|
+
/** Optional element rendered before the breadcrumb in editor/preview headers */
|
|
14
|
+
backButton?: ReactNode;
|
|
15
|
+
}
|
|
16
|
+
declare const PageManager: React.FC<PageManagerProps>;
|
|
17
|
+
|
|
18
|
+
export { PageManager, type PageManagerProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
PageManager: () => PageManager
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/PageManager.tsx
|
|
38
|
+
var import_react = require("react");
|
|
39
|
+
var import_react_router_dom = require("react-router-dom");
|
|
40
|
+
var import_puck_api = require("@commercetools-demo/puck-api");
|
|
41
|
+
var import_puck_editor = require("@commercetools-demo/puck-editor");
|
|
42
|
+
var import_puck_renderer = require("@commercetools-demo/puck-renderer");
|
|
43
|
+
var import_data_table = __toESM(require("@commercetools-uikit/data-table"));
|
|
44
|
+
var import_primary_button = __toESM(require("@commercetools-uikit/primary-button"));
|
|
45
|
+
var import_secondary_button = __toESM(require("@commercetools-uikit/secondary-button"));
|
|
46
|
+
var import_flat_button = __toESM(require("@commercetools-uikit/flat-button"));
|
|
47
|
+
var import_card = __toESM(require("@commercetools-uikit/card"));
|
|
48
|
+
var import_spacings = __toESM(require("@commercetools-uikit/spacings"));
|
|
49
|
+
var import_text = __toESM(require("@commercetools-uikit/text"));
|
|
50
|
+
var import_loading_spinner = __toESM(require("@commercetools-uikit/loading-spinner"));
|
|
51
|
+
var import_text_input = __toESM(require("@commercetools-uikit/text-input"));
|
|
52
|
+
var import_label = __toESM(require("@commercetools-uikit/label"));
|
|
53
|
+
var import_icons = require("@commercetools-uikit/icons");
|
|
54
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
55
|
+
var StatusBadge = ({ variant }) => {
|
|
56
|
+
const styles = variant === "published" ? { background: "var(--color-success-95)", color: "var(--color-success-40)", border: "1px solid var(--color-success-85)" } : variant === "draft" ? { background: "var(--color-warning-95)", color: "var(--color-warning-40)", border: "1px solid var(--color-warning-85)" } : { background: "var(--color-neutral-95)", color: "var(--color-neutral-50)", border: "1px solid var(--color-neutral-85)" };
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
58
|
+
"span",
|
|
59
|
+
{
|
|
60
|
+
style: {
|
|
61
|
+
...styles,
|
|
62
|
+
display: "inline-flex",
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
padding: "2px 8px",
|
|
65
|
+
borderRadius: "var(--border-radius-20)",
|
|
66
|
+
fontSize: "var(--font-size-10)",
|
|
67
|
+
fontWeight: "var(--font-weight-600)",
|
|
68
|
+
marginRight: "4px",
|
|
69
|
+
whiteSpace: "nowrap"
|
|
70
|
+
},
|
|
71
|
+
children: variant === "published" ? "Published" : variant === "draft" ? "Draft" : "No state"
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
var NAV_BAR_STYLE = {
|
|
76
|
+
position: "sticky",
|
|
77
|
+
top: 0,
|
|
78
|
+
display: "flex",
|
|
79
|
+
alignItems: "center",
|
|
80
|
+
gap: "12px",
|
|
81
|
+
padding: "8px 16px",
|
|
82
|
+
background: "var(--color-surface, #fff)",
|
|
83
|
+
borderBottom: "1px solid var(--color-neutral-90)",
|
|
84
|
+
zIndex: 200,
|
|
85
|
+
flexShrink: 0
|
|
86
|
+
};
|
|
87
|
+
var COLUMNS = [
|
|
88
|
+
{ key: "name", label: "Name" },
|
|
89
|
+
{ key: "slug", label: "Slug" },
|
|
90
|
+
{ key: "status", label: "Status" },
|
|
91
|
+
{ key: "updatedAt", label: "Updated" },
|
|
92
|
+
{ key: "actions", label: "Actions", shouldIgnoreRowClick: true }
|
|
93
|
+
];
|
|
94
|
+
var PageList = ({ backButton }) => {
|
|
95
|
+
const navigate = (0, import_react_router_dom.useNavigate)();
|
|
96
|
+
const { pages, loading, error, createPage, deletePage, refresh } = (0, import_puck_api.usePuckPages)();
|
|
97
|
+
const [creating, setCreating] = (0, import_react.useState)(false);
|
|
98
|
+
const [newName, setNewName] = (0, import_react.useState)("");
|
|
99
|
+
const [newSlug, setNewSlug] = (0, import_react.useState)("");
|
|
100
|
+
const [formError, setFormError] = (0, import_react.useState)("");
|
|
101
|
+
const [submitting, setSubmitting] = (0, import_react.useState)(false);
|
|
102
|
+
const [deleting, setDeleting] = (0, import_react.useState)(null);
|
|
103
|
+
const handleCreate = async () => {
|
|
104
|
+
if (!newName.trim()) {
|
|
105
|
+
setFormError("Name is required");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (!newSlug.trim()) {
|
|
109
|
+
setFormError("Slug is required");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setFormError("");
|
|
113
|
+
setSubmitting(true);
|
|
114
|
+
try {
|
|
115
|
+
const input = {
|
|
116
|
+
name: newName.trim(),
|
|
117
|
+
slug: newSlug.trim().startsWith("/") ? newSlug.trim() : `/${newSlug.trim()}`
|
|
118
|
+
};
|
|
119
|
+
const created = await createPage(input);
|
|
120
|
+
setCreating(false);
|
|
121
|
+
setNewName("");
|
|
122
|
+
setNewSlug("");
|
|
123
|
+
navigate(`/${created.key}/edit`, { state: { pageName: created.value.name } });
|
|
124
|
+
} catch (err) {
|
|
125
|
+
setFormError(err.message);
|
|
126
|
+
} finally {
|
|
127
|
+
setSubmitting(false);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const handleDelete = async (page) => {
|
|
131
|
+
if (!confirm(`Delete "${page.value.name}"? This cannot be undone.`)) return;
|
|
132
|
+
setDeleting(page.key);
|
|
133
|
+
try {
|
|
134
|
+
await deletePage(page.key);
|
|
135
|
+
await refresh();
|
|
136
|
+
} finally {
|
|
137
|
+
setDeleting(null);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
if (loading) {
|
|
141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "64px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_loading_spinner.default, {}) });
|
|
142
|
+
}
|
|
143
|
+
if (error) {
|
|
144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "32px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_text.default.Body, { tone: "negative", children: [
|
|
145
|
+
"Error: ",
|
|
146
|
+
error
|
|
147
|
+
] }) });
|
|
148
|
+
}
|
|
149
|
+
const rows = pages.map((p) => ({ ...p, id: p.key }));
|
|
150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { maxWidth: "1200px", margin: "0 auto", padding: "32px 24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "l", children: [
|
|
151
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { justifyContent: "space-between", alignItems: "center", children: [
|
|
152
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "m", alignItems: "center", children: [
|
|
153
|
+
backButton,
|
|
154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Headline, { as: "h1", children: "Puck Pages" })
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
157
|
+
import_primary_button.default,
|
|
158
|
+
{
|
|
159
|
+
label: "New Page",
|
|
160
|
+
iconLeft: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlusThinIcon, {}),
|
|
161
|
+
onClick: () => setCreating(true)
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
] }),
|
|
165
|
+
creating && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_card.default, { insetScale: "l", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "m", children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Subheadline, { as: "h4", isBold: true, children: "Create New Page" }),
|
|
167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "m", children: [
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
|
|
169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.default, { htmlFor: "new-page-name", children: "Name *" }),
|
|
170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
171
|
+
import_text_input.default,
|
|
172
|
+
{
|
|
173
|
+
id: "new-page-name",
|
|
174
|
+
value: newName,
|
|
175
|
+
onChange: (e) => setNewName(e.target.value),
|
|
176
|
+
placeholder: "Home Page"
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
] }) }),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.default, { htmlFor: "new-page-slug", children: "Slug *" }),
|
|
182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
183
|
+
import_text_input.default,
|
|
184
|
+
{
|
|
185
|
+
id: "new-page-slug",
|
|
186
|
+
value: newSlug,
|
|
187
|
+
onChange: (e) => setNewSlug(e.target.value),
|
|
188
|
+
placeholder: "/home"
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
] }) })
|
|
192
|
+
] }),
|
|
193
|
+
formError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "negative", children: formError }),
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "s", children: [
|
|
195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
196
|
+
import_primary_button.default,
|
|
197
|
+
{
|
|
198
|
+
label: submitting ? "Creating\u2026" : "Create",
|
|
199
|
+
onClick: () => void handleCreate(),
|
|
200
|
+
isDisabled: submitting
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
204
|
+
import_secondary_button.default,
|
|
205
|
+
{
|
|
206
|
+
label: "Cancel",
|
|
207
|
+
onClick: () => {
|
|
208
|
+
setCreating(false);
|
|
209
|
+
setFormError("");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
] })
|
|
214
|
+
] }) }),
|
|
215
|
+
pages.length === 0 && !creating ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "m", alignItems: "center", children: [
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "No pages yet." }),
|
|
217
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
218
|
+
import_primary_button.default,
|
|
219
|
+
{
|
|
220
|
+
label: "Create first page",
|
|
221
|
+
iconLeft: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlusThinIcon, {}),
|
|
222
|
+
onClick: () => setCreating(true)
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
] }) : pages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
226
|
+
import_data_table.default,
|
|
227
|
+
{
|
|
228
|
+
columns: COLUMNS,
|
|
229
|
+
rows,
|
|
230
|
+
itemRenderer: (row, column) => {
|
|
231
|
+
switch (column.key) {
|
|
232
|
+
case "name":
|
|
233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
|
|
234
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { isBold: true, children: row.value.name }),
|
|
235
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Detail, { tone: "secondary", children: row.key })
|
|
236
|
+
] });
|
|
237
|
+
case "slug":
|
|
238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
239
|
+
"code",
|
|
240
|
+
{
|
|
241
|
+
style: {
|
|
242
|
+
background: "var(--color-neutral-95)",
|
|
243
|
+
padding: "2px 6px",
|
|
244
|
+
borderRadius: "var(--border-radius-4)",
|
|
245
|
+
fontSize: "var(--font-size-10)",
|
|
246
|
+
fontFamily: "monospace"
|
|
247
|
+
},
|
|
248
|
+
children: row.value.slug
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
case "status":
|
|
252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
253
|
+
row.states.draft && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "draft" }),
|
|
254
|
+
row.states.published && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "published" }),
|
|
255
|
+
!row.states.draft && !row.states.published && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "none" })
|
|
256
|
+
] });
|
|
257
|
+
case "updatedAt":
|
|
258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: new Date(row.value.updatedAt).toLocaleString() });
|
|
259
|
+
case "actions":
|
|
260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
262
|
+
import_primary_button.default,
|
|
263
|
+
{
|
|
264
|
+
label: "Edit",
|
|
265
|
+
size: "20",
|
|
266
|
+
onClick: () => navigate(`/${row.key}/edit`, { state: { pageName: row.value.name } })
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
270
|
+
import_secondary_button.default,
|
|
271
|
+
{
|
|
272
|
+
label: "Preview",
|
|
273
|
+
size: "20",
|
|
274
|
+
onClick: () => navigate(`/${row.key}/preview`, { state: { pageName: row.value.name } })
|
|
275
|
+
}
|
|
276
|
+
),
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
278
|
+
import_flat_button.default,
|
|
279
|
+
{
|
|
280
|
+
tone: "critical",
|
|
281
|
+
label: deleting === row.key ? "\u2026" : "Delete",
|
|
282
|
+
isDisabled: deleting === row.key,
|
|
283
|
+
onClick: () => void handleDelete(row)
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
] });
|
|
287
|
+
default:
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
) : null
|
|
293
|
+
] }) });
|
|
294
|
+
};
|
|
295
|
+
var PageEditorRoute = ({ config, backButton }) => {
|
|
296
|
+
const { pageKey } = (0, import_react_router_dom.useParams)();
|
|
297
|
+
const navigate = (0, import_react_router_dom.useNavigate)();
|
|
298
|
+
const location = (0, import_react_router_dom.useLocation)();
|
|
299
|
+
const { baseURL, projectKey, businessUnitKey, jwtToken } = (0, import_puck_api.usePuckApiContext)();
|
|
300
|
+
const pageName = location.state?.pageName ?? pageKey ?? "Page";
|
|
301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
|
|
302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: NAV_BAR_STYLE, children: [
|
|
303
|
+
backButton,
|
|
304
|
+
backButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
|
|
305
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
306
|
+
import_flat_button.default,
|
|
307
|
+
{
|
|
308
|
+
label: "Pages",
|
|
309
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.AngleLeftIcon, {}),
|
|
310
|
+
iconPosition: "left",
|
|
311
|
+
onClick: () => navigate("/")
|
|
312
|
+
}
|
|
313
|
+
),
|
|
314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
|
|
315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { isBold: true, children: pageName })
|
|
316
|
+
] }),
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
318
|
+
import_puck_editor.PuckEditor,
|
|
319
|
+
{
|
|
320
|
+
baseURL,
|
|
321
|
+
projectKey,
|
|
322
|
+
businessUnitKey,
|
|
323
|
+
jwtToken: jwtToken ?? "",
|
|
324
|
+
pageKey,
|
|
325
|
+
config,
|
|
326
|
+
onError: (err) => {
|
|
327
|
+
console.error("[PageManager] editor error:", err);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
) })
|
|
331
|
+
] });
|
|
332
|
+
};
|
|
333
|
+
var PagePreviewRoute = ({ config, backButton }) => {
|
|
334
|
+
const { pageKey } = (0, import_react_router_dom.useParams)();
|
|
335
|
+
const navigate = (0, import_react_router_dom.useNavigate)();
|
|
336
|
+
const location = (0, import_react_router_dom.useLocation)();
|
|
337
|
+
const pageName = location.state?.pageName ?? pageKey ?? "Page";
|
|
338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
339
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: NAV_BAR_STYLE, children: [
|
|
340
|
+
backButton,
|
|
341
|
+
backButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
343
|
+
import_flat_button.default,
|
|
344
|
+
{
|
|
345
|
+
label: "Pages",
|
|
346
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.AngleLeftIcon, {}),
|
|
347
|
+
iconPosition: "left",
|
|
348
|
+
onClick: () => navigate("/")
|
|
349
|
+
}
|
|
350
|
+
),
|
|
351
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
|
|
352
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { isBold: true, children: pageName }),
|
|
353
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
354
|
+
"span",
|
|
355
|
+
{
|
|
356
|
+
style: {
|
|
357
|
+
background: "var(--color-primary-95)",
|
|
358
|
+
color: "var(--color-primary-25)",
|
|
359
|
+
border: "1px solid var(--color-primary-85)",
|
|
360
|
+
display: "inline-flex",
|
|
361
|
+
alignItems: "center",
|
|
362
|
+
padding: "2px 10px",
|
|
363
|
+
borderRadius: "var(--border-radius-20)",
|
|
364
|
+
fontSize: "var(--font-size-10)",
|
|
365
|
+
fontWeight: "var(--font-weight-600)"
|
|
366
|
+
},
|
|
367
|
+
children: "Preview"
|
|
368
|
+
}
|
|
369
|
+
)
|
|
370
|
+
] }),
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_puck_renderer.PuckRenderer, { pageKey, mode: "preview", config })
|
|
372
|
+
] });
|
|
373
|
+
};
|
|
374
|
+
var PageManagerInner = ({ config, backButton }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_router_dom.Routes, { children: [
|
|
375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageList, { backButton }) }),
|
|
376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
377
|
+
import_react_router_dom.Route,
|
|
378
|
+
{
|
|
379
|
+
path: "/:pageKey/edit",
|
|
380
|
+
element: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageEditorRoute, { config, backButton })
|
|
381
|
+
}
|
|
382
|
+
),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
384
|
+
import_react_router_dom.Route,
|
|
385
|
+
{
|
|
386
|
+
path: "/:pageKey/preview",
|
|
387
|
+
element: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PagePreviewRoute, { config, backButton })
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
] });
|
|
391
|
+
var PageManager = ({
|
|
392
|
+
parentUrl,
|
|
393
|
+
baseURL,
|
|
394
|
+
projectKey,
|
|
395
|
+
businessUnitKey,
|
|
396
|
+
jwtToken,
|
|
397
|
+
config,
|
|
398
|
+
backButton
|
|
399
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
400
|
+
import_puck_api.PuckApiProvider,
|
|
401
|
+
{
|
|
402
|
+
baseURL,
|
|
403
|
+
projectKey,
|
|
404
|
+
businessUnitKey,
|
|
405
|
+
jwtToken,
|
|
406
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_router_dom.BrowserRouter, { basename: parentUrl, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageManagerInner, { config, backButton }) })
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
410
|
+
0 && (module.exports = {
|
|
411
|
+
PageManager
|
|
412
|
+
});
|
|
413
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/PageManager.tsx"],"sourcesContent":["export { PageManager } from './PageManager';\nexport type { PageManagerProps } from './PageManager';\n","import React, { useState, type ReactNode } from 'react';\nimport {\n BrowserRouter,\n Routes,\n Route,\n useNavigate,\n useParams,\n useLocation,\n} from 'react-router-dom';\nimport {\n PuckApiProvider,\n usePuckPages,\n usePuckApiContext,\n} from '@commercetools-demo/puck-api';\nimport { PuckEditor } from '@commercetools-demo/puck-editor';\nimport { PuckRenderer } from '@commercetools-demo/puck-renderer';\nimport type { Config } from '@measured/puck';\nimport type { CreatePuckPageInput, PuckPageListItem } from '@commercetools-demo/puck-types';\nimport DataTable from '@commercetools-uikit/data-table';\nimport PrimaryButton from '@commercetools-uikit/primary-button';\nimport SecondaryButton from '@commercetools-uikit/secondary-button';\nimport FlatButton from '@commercetools-uikit/flat-button';\nimport Card from '@commercetools-uikit/card';\nimport Spacings from '@commercetools-uikit/spacings';\nimport Text from '@commercetools-uikit/text';\nimport LoadingSpinner from '@commercetools-uikit/loading-spinner';\nimport TextInput from '@commercetools-uikit/text-input';\nimport Label from '@commercetools-uikit/label';\nimport { PlusThinIcon, AngleLeftIcon } from '@commercetools-uikit/icons';\n\n// ---------------------------------------------------------------------------\n// Status badge\n// ---------------------------------------------------------------------------\n\nconst StatusBadge: React.FC<{ variant: 'draft' | 'published' | 'none' }> = ({ variant }) => {\n const styles: React.CSSProperties =\n variant === 'published'\n ? { background: 'var(--color-success-95)', color: 'var(--color-success-40)', border: '1px solid var(--color-success-85)' }\n : variant === 'draft'\n ? { background: 'var(--color-warning-95)', color: 'var(--color-warning-40)', border: '1px solid var(--color-warning-85)' }\n : { background: 'var(--color-neutral-95)', color: 'var(--color-neutral-50)', border: '1px solid var(--color-neutral-85)' };\n return (\n <span\n style={{\n ...styles,\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 8px',\n borderRadius: 'var(--border-radius-20)',\n fontSize: 'var(--font-size-10)',\n fontWeight: 'var(--font-weight-600)',\n marginRight: '4px',\n whiteSpace: 'nowrap',\n }}\n >\n {variant === 'published' ? 'Published' : variant === 'draft' ? 'Draft' : 'No state'}\n </span>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Shared nav bar style\n// ---------------------------------------------------------------------------\n\nconst NAV_BAR_STYLE: React.CSSProperties = {\n position: 'sticky',\n top: 0,\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '8px 16px',\n background: 'var(--color-surface, #fff)',\n borderBottom: '1px solid var(--color-neutral-90)',\n zIndex: 200,\n flexShrink: 0,\n};\n\n// ---------------------------------------------------------------------------\n// Table columns\n// ---------------------------------------------------------------------------\n\ntype PageRow = PuckPageListItem & { id: string };\n\nconst COLUMNS = [\n { key: 'name', label: 'Name' },\n { key: 'slug', label: 'Slug' },\n { key: 'status', label: 'Status' },\n { key: 'updatedAt', label: 'Updated' },\n { key: 'actions', label: 'Actions', shouldIgnoreRowClick: true },\n];\n\n// ---------------------------------------------------------------------------\n// PageList route\n// ---------------------------------------------------------------------------\n\ninterface PageListProps {\n backButton?: ReactNode;\n}\n\nconst PageList: React.FC<PageListProps> = ({ backButton }) => {\n const navigate = useNavigate();\n const { pages, loading, error, createPage, deletePage, refresh } = usePuckPages();\n\n const [creating, setCreating] = useState(false);\n const [newName, setNewName] = useState('');\n const [newSlug, setNewSlug] = useState('');\n const [formError, setFormError] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [deleting, setDeleting] = useState<string | null>(null);\n\n const handleCreate = async () => {\n if (!newName.trim()) { setFormError('Name is required'); return; }\n if (!newSlug.trim()) { setFormError('Slug is required'); return; }\n setFormError('');\n setSubmitting(true);\n try {\n const input: CreatePuckPageInput = {\n name: newName.trim(),\n slug: newSlug.trim().startsWith('/') ? newSlug.trim() : `/${newSlug.trim()}`,\n };\n const created = await createPage(input);\n setCreating(false);\n setNewName('');\n setNewSlug('');\n navigate(`/${created.key}/edit`, { state: { pageName: created.value.name } });\n } catch (err) {\n setFormError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n };\n\n const handleDelete = async (page: PuckPageListItem) => {\n if (!confirm(`Delete \"${page.value.name}\"? This cannot be undone.`)) return;\n setDeleting(page.key);\n try {\n await deletePage(page.key);\n await refresh();\n } finally {\n setDeleting(null);\n }\n };\n\n if (loading) {\n return (\n <div style={{ padding: '64px', display: 'flex', justifyContent: 'center' }}>\n <LoadingSpinner />\n </div>\n );\n }\n\n if (error) {\n return (\n <div style={{ padding: '32px' }}>\n <Text.Body tone=\"negative\">Error: {error}</Text.Body>\n </div>\n );\n }\n\n const rows: PageRow[] = pages.map((p) => ({ ...p, id: p.key }));\n\n return (\n <div style={{ maxWidth: '1200px', margin: '0 auto', padding: '32px 24px' }}>\n <Spacings.Stack scale=\"l\">\n <Spacings.Inline justifyContent=\"space-between\" alignItems=\"center\">\n <Spacings.Inline scale=\"m\" alignItems=\"center\">\n {backButton}\n <Text.Headline as=\"h1\">Puck Pages</Text.Headline>\n </Spacings.Inline>\n <PrimaryButton\n label=\"New Page\"\n iconLeft={<PlusThinIcon />}\n onClick={() => setCreating(true)}\n />\n </Spacings.Inline>\n\n {creating && (\n <Card insetScale=\"l\">\n <Spacings.Stack scale=\"m\">\n <Text.Subheadline as=\"h4\" isBold>Create New Page</Text.Subheadline>\n <Spacings.Inline scale=\"m\">\n <div style={{ flex: 1 }}>\n <Spacings.Stack scale=\"xs\">\n <Label htmlFor=\"new-page-name\">Name *</Label>\n <TextInput\n id=\"new-page-name\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Home Page\"\n />\n </Spacings.Stack>\n </div>\n <div style={{ flex: 1 }}>\n <Spacings.Stack scale=\"xs\">\n <Label htmlFor=\"new-page-slug\">Slug *</Label>\n <TextInput\n id=\"new-page-slug\"\n value={newSlug}\n onChange={(e) => setNewSlug(e.target.value)}\n placeholder=\"/home\"\n />\n </Spacings.Stack>\n </div>\n </Spacings.Inline>\n {formError && <Text.Body tone=\"negative\">{formError}</Text.Body>}\n <Spacings.Inline scale=\"s\">\n <PrimaryButton\n label={submitting ? 'Creating…' : 'Create'}\n onClick={() => void handleCreate()}\n isDisabled={submitting}\n />\n <SecondaryButton\n label=\"Cancel\"\n onClick={() => { setCreating(false); setFormError(''); }}\n />\n </Spacings.Inline>\n </Spacings.Stack>\n </Card>\n )}\n\n {pages.length === 0 && !creating ? (\n <Spacings.Stack scale=\"m\" alignItems=\"center\">\n <Text.Body tone=\"secondary\">No pages yet.</Text.Body>\n <PrimaryButton\n label=\"Create first page\"\n iconLeft={<PlusThinIcon />}\n onClick={() => setCreating(true)}\n />\n </Spacings.Stack>\n ) : pages.length > 0 ? (\n <DataTable\n columns={COLUMNS}\n rows={rows}\n itemRenderer={(row: PageRow, column) => {\n switch (column.key) {\n case 'name':\n return (\n <Spacings.Stack scale=\"xs\">\n <Text.Body isBold>{row.value.name}</Text.Body>\n <Text.Detail tone=\"secondary\">{row.key}</Text.Detail>\n </Spacings.Stack>\n );\n case 'slug':\n return (\n <code\n style={{\n background: 'var(--color-neutral-95)',\n padding: '2px 6px',\n borderRadius: 'var(--border-radius-4)',\n fontSize: 'var(--font-size-10)',\n fontFamily: 'monospace',\n }}\n >\n {row.value.slug}\n </code>\n );\n case 'status':\n return (\n <span>\n {row.states.draft && <StatusBadge variant=\"draft\" />}\n {row.states.published && <StatusBadge variant=\"published\" />}\n {!row.states.draft && !row.states.published && <StatusBadge variant=\"none\" />}\n </span>\n );\n case 'updatedAt':\n return (\n <Text.Body tone=\"secondary\">\n {new Date(row.value.updatedAt).toLocaleString()}\n </Text.Body>\n );\n case 'actions':\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <PrimaryButton\n label=\"Edit\"\n size=\"20\"\n onClick={() =>\n navigate(`/${row.key}/edit`, { state: { pageName: row.value.name } })\n }\n />\n <SecondaryButton\n label=\"Preview\"\n size=\"20\"\n onClick={() =>\n navigate(`/${row.key}/preview`, { state: { pageName: row.value.name } })\n }\n />\n <FlatButton\n tone=\"critical\"\n label={deleting === row.key ? '…' : 'Delete'}\n isDisabled={deleting === row.key}\n onClick={() => void handleDelete(row)}\n />\n </div>\n );\n default:\n return null;\n }\n }}\n />\n ) : null}\n </Spacings.Stack>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// PageEditorRoute\n// ---------------------------------------------------------------------------\n\ninterface RouteProps {\n config: Config;\n backButton?: ReactNode;\n}\n\nconst PageEditorRoute: React.FC<RouteProps> = ({ config, backButton }) => {\n const { pageKey } = useParams<{ pageKey: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const { baseURL, projectKey, businessUnitKey, jwtToken } = usePuckApiContext();\n const pageName =\n (location.state as { pageName?: string } | null)?.pageName ?? pageKey ?? 'Page';\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>\n <div style={NAV_BAR_STYLE}>\n {backButton}\n {backButton && <Text.Body tone=\"secondary\">/</Text.Body>}\n <FlatButton\n label=\"Pages\"\n icon={<AngleLeftIcon />}\n iconPosition=\"left\"\n onClick={() => navigate('/')}\n />\n <Text.Body tone=\"secondary\">/</Text.Body>\n <Text.Body isBold>{pageName}</Text.Body>\n </div>\n <div style={{ flex: 1, overflow: 'hidden' }}>\n <PuckEditor\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n jwtToken={jwtToken ?? ''}\n pageKey={pageKey!}\n config={config}\n onError={(err: Error) => { console.error('[PageManager] editor error:', err); }}\n />\n </div>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// PagePreviewRoute\n// ---------------------------------------------------------------------------\n\nconst PagePreviewRoute: React.FC<RouteProps> = ({ config, backButton }) => {\n const { pageKey } = useParams<{ pageKey: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const pageName =\n (location.state as { pageName?: string } | null)?.pageName ?? pageKey ?? 'Page';\n\n return (\n <div>\n <div style={NAV_BAR_STYLE}>\n {backButton}\n {backButton && <Text.Body tone=\"secondary\">/</Text.Body>}\n <FlatButton\n label=\"Pages\"\n icon={<AngleLeftIcon />}\n iconPosition=\"left\"\n onClick={() => navigate('/')}\n />\n <Text.Body tone=\"secondary\">/</Text.Body>\n <Text.Body isBold>{pageName}</Text.Body>\n <span\n style={{\n background: 'var(--color-primary-95)',\n color: 'var(--color-primary-25)',\n border: '1px solid var(--color-primary-85)',\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 10px',\n borderRadius: 'var(--border-radius-20)',\n fontSize: 'var(--font-size-10)',\n fontWeight: 'var(--font-weight-600)',\n }}\n >\n Preview\n </span>\n </div>\n <PuckRenderer pageKey={pageKey} mode=\"preview\" config={config} />\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Inner router component\n// ---------------------------------------------------------------------------\n\ninterface PageManagerInnerProps {\n config: Config;\n backButton?: ReactNode;\n}\n\nconst PageManagerInner: React.FC<PageManagerInnerProps> = ({ config, backButton }) => (\n <Routes>\n <Route path=\"/\" element={<PageList backButton={backButton} />} />\n <Route\n path=\"/:pageKey/edit\"\n element={<PageEditorRoute config={config} backButton={backButton} />}\n />\n <Route\n path=\"/:pageKey/preview\"\n element={<PagePreviewRoute config={config} backButton={backButton} />}\n />\n </Routes>\n);\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PageManagerProps {\n /** URL path where this manager is mounted, e.g. \"/pages\" — used as router basename */\n parentUrl: string;\n baseURL: string;\n projectKey: string;\n businessUnitKey: string;\n jwtToken: string;\n /** Puck component config — passed to editor and preview */\n config: Config;\n /** Optional element rendered before the breadcrumb in editor/preview headers */\n backButton?: ReactNode;\n}\n\nexport const PageManager: React.FC<PageManagerProps> = ({\n parentUrl,\n baseURL,\n projectKey,\n businessUnitKey,\n jwtToken,\n config,\n backButton,\n}) => (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n jwtToken={jwtToken}\n >\n <BrowserRouter basename={parentUrl}>\n <PageManagerInner config={config} backButton={backButton} />\n </BrowserRouter>\n </PuckApiProvider>\n);\n"],"mappings":"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","names":["LoadingSpinner","Text","Spacings","PrimaryButton","Card","Label","TextInput","SecondaryButton","DataTable","FlatButton"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// src/PageManager.tsx
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import {
|
|
4
|
+
BrowserRouter,
|
|
5
|
+
Routes,
|
|
6
|
+
Route,
|
|
7
|
+
useNavigate,
|
|
8
|
+
useParams,
|
|
9
|
+
useLocation
|
|
10
|
+
} from "react-router-dom";
|
|
11
|
+
import {
|
|
12
|
+
PuckApiProvider,
|
|
13
|
+
usePuckPages,
|
|
14
|
+
usePuckApiContext
|
|
15
|
+
} from "@commercetools-demo/puck-api";
|
|
16
|
+
import { PuckEditor } from "@commercetools-demo/puck-editor";
|
|
17
|
+
import { PuckRenderer } from "@commercetools-demo/puck-renderer";
|
|
18
|
+
import DataTable from "@commercetools-uikit/data-table";
|
|
19
|
+
import PrimaryButton from "@commercetools-uikit/primary-button";
|
|
20
|
+
import SecondaryButton from "@commercetools-uikit/secondary-button";
|
|
21
|
+
import FlatButton from "@commercetools-uikit/flat-button";
|
|
22
|
+
import Card from "@commercetools-uikit/card";
|
|
23
|
+
import Spacings from "@commercetools-uikit/spacings";
|
|
24
|
+
import Text from "@commercetools-uikit/text";
|
|
25
|
+
import LoadingSpinner from "@commercetools-uikit/loading-spinner";
|
|
26
|
+
import TextInput from "@commercetools-uikit/text-input";
|
|
27
|
+
import Label from "@commercetools-uikit/label";
|
|
28
|
+
import { PlusThinIcon, AngleLeftIcon } from "@commercetools-uikit/icons";
|
|
29
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
30
|
+
var StatusBadge = ({ variant }) => {
|
|
31
|
+
const styles = variant === "published" ? { background: "var(--color-success-95)", color: "var(--color-success-40)", border: "1px solid var(--color-success-85)" } : variant === "draft" ? { background: "var(--color-warning-95)", color: "var(--color-warning-40)", border: "1px solid var(--color-warning-85)" } : { background: "var(--color-neutral-95)", color: "var(--color-neutral-50)", border: "1px solid var(--color-neutral-85)" };
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
"span",
|
|
34
|
+
{
|
|
35
|
+
style: {
|
|
36
|
+
...styles,
|
|
37
|
+
display: "inline-flex",
|
|
38
|
+
alignItems: "center",
|
|
39
|
+
padding: "2px 8px",
|
|
40
|
+
borderRadius: "var(--border-radius-20)",
|
|
41
|
+
fontSize: "var(--font-size-10)",
|
|
42
|
+
fontWeight: "var(--font-weight-600)",
|
|
43
|
+
marginRight: "4px",
|
|
44
|
+
whiteSpace: "nowrap"
|
|
45
|
+
},
|
|
46
|
+
children: variant === "published" ? "Published" : variant === "draft" ? "Draft" : "No state"
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
var NAV_BAR_STYLE = {
|
|
51
|
+
position: "sticky",
|
|
52
|
+
top: 0,
|
|
53
|
+
display: "flex",
|
|
54
|
+
alignItems: "center",
|
|
55
|
+
gap: "12px",
|
|
56
|
+
padding: "8px 16px",
|
|
57
|
+
background: "var(--color-surface, #fff)",
|
|
58
|
+
borderBottom: "1px solid var(--color-neutral-90)",
|
|
59
|
+
zIndex: 200,
|
|
60
|
+
flexShrink: 0
|
|
61
|
+
};
|
|
62
|
+
var COLUMNS = [
|
|
63
|
+
{ key: "name", label: "Name" },
|
|
64
|
+
{ key: "slug", label: "Slug" },
|
|
65
|
+
{ key: "status", label: "Status" },
|
|
66
|
+
{ key: "updatedAt", label: "Updated" },
|
|
67
|
+
{ key: "actions", label: "Actions", shouldIgnoreRowClick: true }
|
|
68
|
+
];
|
|
69
|
+
var PageList = ({ backButton }) => {
|
|
70
|
+
const navigate = useNavigate();
|
|
71
|
+
const { pages, loading, error, createPage, deletePage, refresh } = usePuckPages();
|
|
72
|
+
const [creating, setCreating] = useState(false);
|
|
73
|
+
const [newName, setNewName] = useState("");
|
|
74
|
+
const [newSlug, setNewSlug] = useState("");
|
|
75
|
+
const [formError, setFormError] = useState("");
|
|
76
|
+
const [submitting, setSubmitting] = useState(false);
|
|
77
|
+
const [deleting, setDeleting] = useState(null);
|
|
78
|
+
const handleCreate = async () => {
|
|
79
|
+
if (!newName.trim()) {
|
|
80
|
+
setFormError("Name is required");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!newSlug.trim()) {
|
|
84
|
+
setFormError("Slug is required");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setFormError("");
|
|
88
|
+
setSubmitting(true);
|
|
89
|
+
try {
|
|
90
|
+
const input = {
|
|
91
|
+
name: newName.trim(),
|
|
92
|
+
slug: newSlug.trim().startsWith("/") ? newSlug.trim() : `/${newSlug.trim()}`
|
|
93
|
+
};
|
|
94
|
+
const created = await createPage(input);
|
|
95
|
+
setCreating(false);
|
|
96
|
+
setNewName("");
|
|
97
|
+
setNewSlug("");
|
|
98
|
+
navigate(`/${created.key}/edit`, { state: { pageName: created.value.name } });
|
|
99
|
+
} catch (err) {
|
|
100
|
+
setFormError(err.message);
|
|
101
|
+
} finally {
|
|
102
|
+
setSubmitting(false);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const handleDelete = async (page) => {
|
|
106
|
+
if (!confirm(`Delete "${page.value.name}"? This cannot be undone.`)) return;
|
|
107
|
+
setDeleting(page.key);
|
|
108
|
+
try {
|
|
109
|
+
await deletePage(page.key);
|
|
110
|
+
await refresh();
|
|
111
|
+
} finally {
|
|
112
|
+
setDeleting(null);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
if (loading) {
|
|
116
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "64px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx(LoadingSpinner, {}) });
|
|
117
|
+
}
|
|
118
|
+
if (error) {
|
|
119
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "32px" }, children: /* @__PURE__ */ jsxs(Text.Body, { tone: "negative", children: [
|
|
120
|
+
"Error: ",
|
|
121
|
+
error
|
|
122
|
+
] }) });
|
|
123
|
+
}
|
|
124
|
+
const rows = pages.map((p) => ({ ...p, id: p.key }));
|
|
125
|
+
return /* @__PURE__ */ jsx("div", { style: { maxWidth: "1200px", margin: "0 auto", padding: "32px 24px" }, children: /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "l", children: [
|
|
126
|
+
/* @__PURE__ */ jsxs(Spacings.Inline, { justifyContent: "space-between", alignItems: "center", children: [
|
|
127
|
+
/* @__PURE__ */ jsxs(Spacings.Inline, { scale: "m", alignItems: "center", children: [
|
|
128
|
+
backButton,
|
|
129
|
+
/* @__PURE__ */ jsx(Text.Headline, { as: "h1", children: "Puck Pages" })
|
|
130
|
+
] }),
|
|
131
|
+
/* @__PURE__ */ jsx(
|
|
132
|
+
PrimaryButton,
|
|
133
|
+
{
|
|
134
|
+
label: "New Page",
|
|
135
|
+
iconLeft: /* @__PURE__ */ jsx(PlusThinIcon, {}),
|
|
136
|
+
onClick: () => setCreating(true)
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
] }),
|
|
140
|
+
creating && /* @__PURE__ */ jsx(Card, { insetScale: "l", children: /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "m", children: [
|
|
141
|
+
/* @__PURE__ */ jsx(Text.Subheadline, { as: "h4", isBold: true, children: "Create New Page" }),
|
|
142
|
+
/* @__PURE__ */ jsxs(Spacings.Inline, { scale: "m", children: [
|
|
143
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "xs", children: [
|
|
144
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "new-page-name", children: "Name *" }),
|
|
145
|
+
/* @__PURE__ */ jsx(
|
|
146
|
+
TextInput,
|
|
147
|
+
{
|
|
148
|
+
id: "new-page-name",
|
|
149
|
+
value: newName,
|
|
150
|
+
onChange: (e) => setNewName(e.target.value),
|
|
151
|
+
placeholder: "Home Page"
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
] }) }),
|
|
155
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "xs", children: [
|
|
156
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "new-page-slug", children: "Slug *" }),
|
|
157
|
+
/* @__PURE__ */ jsx(
|
|
158
|
+
TextInput,
|
|
159
|
+
{
|
|
160
|
+
id: "new-page-slug",
|
|
161
|
+
value: newSlug,
|
|
162
|
+
onChange: (e) => setNewSlug(e.target.value),
|
|
163
|
+
placeholder: "/home"
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
] }) })
|
|
167
|
+
] }),
|
|
168
|
+
formError && /* @__PURE__ */ jsx(Text.Body, { tone: "negative", children: formError }),
|
|
169
|
+
/* @__PURE__ */ jsxs(Spacings.Inline, { scale: "s", children: [
|
|
170
|
+
/* @__PURE__ */ jsx(
|
|
171
|
+
PrimaryButton,
|
|
172
|
+
{
|
|
173
|
+
label: submitting ? "Creating\u2026" : "Create",
|
|
174
|
+
onClick: () => void handleCreate(),
|
|
175
|
+
isDisabled: submitting
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
SecondaryButton,
|
|
180
|
+
{
|
|
181
|
+
label: "Cancel",
|
|
182
|
+
onClick: () => {
|
|
183
|
+
setCreating(false);
|
|
184
|
+
setFormError("");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
] })
|
|
189
|
+
] }) }),
|
|
190
|
+
pages.length === 0 && !creating ? /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "m", alignItems: "center", children: [
|
|
191
|
+
/* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: "No pages yet." }),
|
|
192
|
+
/* @__PURE__ */ jsx(
|
|
193
|
+
PrimaryButton,
|
|
194
|
+
{
|
|
195
|
+
label: "Create first page",
|
|
196
|
+
iconLeft: /* @__PURE__ */ jsx(PlusThinIcon, {}),
|
|
197
|
+
onClick: () => setCreating(true)
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
] }) : pages.length > 0 ? /* @__PURE__ */ jsx(
|
|
201
|
+
DataTable,
|
|
202
|
+
{
|
|
203
|
+
columns: COLUMNS,
|
|
204
|
+
rows,
|
|
205
|
+
itemRenderer: (row, column) => {
|
|
206
|
+
switch (column.key) {
|
|
207
|
+
case "name":
|
|
208
|
+
return /* @__PURE__ */ jsxs(Spacings.Stack, { scale: "xs", children: [
|
|
209
|
+
/* @__PURE__ */ jsx(Text.Body, { isBold: true, children: row.value.name }),
|
|
210
|
+
/* @__PURE__ */ jsx(Text.Detail, { tone: "secondary", children: row.key })
|
|
211
|
+
] });
|
|
212
|
+
case "slug":
|
|
213
|
+
return /* @__PURE__ */ jsx(
|
|
214
|
+
"code",
|
|
215
|
+
{
|
|
216
|
+
style: {
|
|
217
|
+
background: "var(--color-neutral-95)",
|
|
218
|
+
padding: "2px 6px",
|
|
219
|
+
borderRadius: "var(--border-radius-4)",
|
|
220
|
+
fontSize: "var(--font-size-10)",
|
|
221
|
+
fontFamily: "monospace"
|
|
222
|
+
},
|
|
223
|
+
children: row.value.slug
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
case "status":
|
|
227
|
+
return /* @__PURE__ */ jsxs("span", { children: [
|
|
228
|
+
row.states.draft && /* @__PURE__ */ jsx(StatusBadge, { variant: "draft" }),
|
|
229
|
+
row.states.published && /* @__PURE__ */ jsx(StatusBadge, { variant: "published" }),
|
|
230
|
+
!row.states.draft && !row.states.published && /* @__PURE__ */ jsx(StatusBadge, { variant: "none" })
|
|
231
|
+
] });
|
|
232
|
+
case "updatedAt":
|
|
233
|
+
return /* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: new Date(row.value.updatedAt).toLocaleString() });
|
|
234
|
+
case "actions":
|
|
235
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
236
|
+
/* @__PURE__ */ jsx(
|
|
237
|
+
PrimaryButton,
|
|
238
|
+
{
|
|
239
|
+
label: "Edit",
|
|
240
|
+
size: "20",
|
|
241
|
+
onClick: () => navigate(`/${row.key}/edit`, { state: { pageName: row.value.name } })
|
|
242
|
+
}
|
|
243
|
+
),
|
|
244
|
+
/* @__PURE__ */ jsx(
|
|
245
|
+
SecondaryButton,
|
|
246
|
+
{
|
|
247
|
+
label: "Preview",
|
|
248
|
+
size: "20",
|
|
249
|
+
onClick: () => navigate(`/${row.key}/preview`, { state: { pageName: row.value.name } })
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ jsx(
|
|
253
|
+
FlatButton,
|
|
254
|
+
{
|
|
255
|
+
tone: "critical",
|
|
256
|
+
label: deleting === row.key ? "\u2026" : "Delete",
|
|
257
|
+
isDisabled: deleting === row.key,
|
|
258
|
+
onClick: () => void handleDelete(row)
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
] });
|
|
262
|
+
default:
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
) : null
|
|
268
|
+
] }) });
|
|
269
|
+
};
|
|
270
|
+
var PageEditorRoute = ({ config, backButton }) => {
|
|
271
|
+
const { pageKey } = useParams();
|
|
272
|
+
const navigate = useNavigate();
|
|
273
|
+
const location = useLocation();
|
|
274
|
+
const { baseURL, projectKey, businessUnitKey, jwtToken } = usePuckApiContext();
|
|
275
|
+
const pageName = location.state?.pageName ?? pageKey ?? "Page";
|
|
276
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
|
|
277
|
+
/* @__PURE__ */ jsxs("div", { style: NAV_BAR_STYLE, children: [
|
|
278
|
+
backButton,
|
|
279
|
+
backButton && /* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: "/" }),
|
|
280
|
+
/* @__PURE__ */ jsx(
|
|
281
|
+
FlatButton,
|
|
282
|
+
{
|
|
283
|
+
label: "Pages",
|
|
284
|
+
icon: /* @__PURE__ */ jsx(AngleLeftIcon, {}),
|
|
285
|
+
iconPosition: "left",
|
|
286
|
+
onClick: () => navigate("/")
|
|
287
|
+
}
|
|
288
|
+
),
|
|
289
|
+
/* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: "/" }),
|
|
290
|
+
/* @__PURE__ */ jsx(Text.Body, { isBold: true, children: pageName })
|
|
291
|
+
] }),
|
|
292
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ jsx(
|
|
293
|
+
PuckEditor,
|
|
294
|
+
{
|
|
295
|
+
baseURL,
|
|
296
|
+
projectKey,
|
|
297
|
+
businessUnitKey,
|
|
298
|
+
jwtToken: jwtToken ?? "",
|
|
299
|
+
pageKey,
|
|
300
|
+
config,
|
|
301
|
+
onError: (err) => {
|
|
302
|
+
console.error("[PageManager] editor error:", err);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
) })
|
|
306
|
+
] });
|
|
307
|
+
};
|
|
308
|
+
var PagePreviewRoute = ({ config, backButton }) => {
|
|
309
|
+
const { pageKey } = useParams();
|
|
310
|
+
const navigate = useNavigate();
|
|
311
|
+
const location = useLocation();
|
|
312
|
+
const pageName = location.state?.pageName ?? pageKey ?? "Page";
|
|
313
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
314
|
+
/* @__PURE__ */ jsxs("div", { style: NAV_BAR_STYLE, children: [
|
|
315
|
+
backButton,
|
|
316
|
+
backButton && /* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: "/" }),
|
|
317
|
+
/* @__PURE__ */ jsx(
|
|
318
|
+
FlatButton,
|
|
319
|
+
{
|
|
320
|
+
label: "Pages",
|
|
321
|
+
icon: /* @__PURE__ */ jsx(AngleLeftIcon, {}),
|
|
322
|
+
iconPosition: "left",
|
|
323
|
+
onClick: () => navigate("/")
|
|
324
|
+
}
|
|
325
|
+
),
|
|
326
|
+
/* @__PURE__ */ jsx(Text.Body, { tone: "secondary", children: "/" }),
|
|
327
|
+
/* @__PURE__ */ jsx(Text.Body, { isBold: true, children: pageName }),
|
|
328
|
+
/* @__PURE__ */ jsx(
|
|
329
|
+
"span",
|
|
330
|
+
{
|
|
331
|
+
style: {
|
|
332
|
+
background: "var(--color-primary-95)",
|
|
333
|
+
color: "var(--color-primary-25)",
|
|
334
|
+
border: "1px solid var(--color-primary-85)",
|
|
335
|
+
display: "inline-flex",
|
|
336
|
+
alignItems: "center",
|
|
337
|
+
padding: "2px 10px",
|
|
338
|
+
borderRadius: "var(--border-radius-20)",
|
|
339
|
+
fontSize: "var(--font-size-10)",
|
|
340
|
+
fontWeight: "var(--font-weight-600)"
|
|
341
|
+
},
|
|
342
|
+
children: "Preview"
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
] }),
|
|
346
|
+
/* @__PURE__ */ jsx(PuckRenderer, { pageKey, mode: "preview", config })
|
|
347
|
+
] });
|
|
348
|
+
};
|
|
349
|
+
var PageManagerInner = ({ config, backButton }) => /* @__PURE__ */ jsxs(Routes, { children: [
|
|
350
|
+
/* @__PURE__ */ jsx(Route, { path: "/", element: /* @__PURE__ */ jsx(PageList, { backButton }) }),
|
|
351
|
+
/* @__PURE__ */ jsx(
|
|
352
|
+
Route,
|
|
353
|
+
{
|
|
354
|
+
path: "/:pageKey/edit",
|
|
355
|
+
element: /* @__PURE__ */ jsx(PageEditorRoute, { config, backButton })
|
|
356
|
+
}
|
|
357
|
+
),
|
|
358
|
+
/* @__PURE__ */ jsx(
|
|
359
|
+
Route,
|
|
360
|
+
{
|
|
361
|
+
path: "/:pageKey/preview",
|
|
362
|
+
element: /* @__PURE__ */ jsx(PagePreviewRoute, { config, backButton })
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
] });
|
|
366
|
+
var PageManager = ({
|
|
367
|
+
parentUrl,
|
|
368
|
+
baseURL,
|
|
369
|
+
projectKey,
|
|
370
|
+
businessUnitKey,
|
|
371
|
+
jwtToken,
|
|
372
|
+
config,
|
|
373
|
+
backButton
|
|
374
|
+
}) => /* @__PURE__ */ jsx(
|
|
375
|
+
PuckApiProvider,
|
|
376
|
+
{
|
|
377
|
+
baseURL,
|
|
378
|
+
projectKey,
|
|
379
|
+
businessUnitKey,
|
|
380
|
+
jwtToken,
|
|
381
|
+
children: /* @__PURE__ */ jsx(BrowserRouter, { basename: parentUrl, children: /* @__PURE__ */ jsx(PageManagerInner, { config, backButton }) })
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
export {
|
|
385
|
+
PageManager
|
|
386
|
+
};
|
|
387
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/PageManager.tsx"],"sourcesContent":["import React, { useState, type ReactNode } from 'react';\nimport {\n BrowserRouter,\n Routes,\n Route,\n useNavigate,\n useParams,\n useLocation,\n} from 'react-router-dom';\nimport {\n PuckApiProvider,\n usePuckPages,\n usePuckApiContext,\n} from '@commercetools-demo/puck-api';\nimport { PuckEditor } from '@commercetools-demo/puck-editor';\nimport { PuckRenderer } from '@commercetools-demo/puck-renderer';\nimport type { Config } from '@measured/puck';\nimport type { CreatePuckPageInput, PuckPageListItem } from '@commercetools-demo/puck-types';\nimport DataTable from '@commercetools-uikit/data-table';\nimport PrimaryButton from '@commercetools-uikit/primary-button';\nimport SecondaryButton from '@commercetools-uikit/secondary-button';\nimport FlatButton from '@commercetools-uikit/flat-button';\nimport Card from '@commercetools-uikit/card';\nimport Spacings from '@commercetools-uikit/spacings';\nimport Text from '@commercetools-uikit/text';\nimport LoadingSpinner from '@commercetools-uikit/loading-spinner';\nimport TextInput from '@commercetools-uikit/text-input';\nimport Label from '@commercetools-uikit/label';\nimport { PlusThinIcon, AngleLeftIcon } from '@commercetools-uikit/icons';\n\n// ---------------------------------------------------------------------------\n// Status badge\n// ---------------------------------------------------------------------------\n\nconst StatusBadge: React.FC<{ variant: 'draft' | 'published' | 'none' }> = ({ variant }) => {\n const styles: React.CSSProperties =\n variant === 'published'\n ? { background: 'var(--color-success-95)', color: 'var(--color-success-40)', border: '1px solid var(--color-success-85)' }\n : variant === 'draft'\n ? { background: 'var(--color-warning-95)', color: 'var(--color-warning-40)', border: '1px solid var(--color-warning-85)' }\n : { background: 'var(--color-neutral-95)', color: 'var(--color-neutral-50)', border: '1px solid var(--color-neutral-85)' };\n return (\n <span\n style={{\n ...styles,\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 8px',\n borderRadius: 'var(--border-radius-20)',\n fontSize: 'var(--font-size-10)',\n fontWeight: 'var(--font-weight-600)',\n marginRight: '4px',\n whiteSpace: 'nowrap',\n }}\n >\n {variant === 'published' ? 'Published' : variant === 'draft' ? 'Draft' : 'No state'}\n </span>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Shared nav bar style\n// ---------------------------------------------------------------------------\n\nconst NAV_BAR_STYLE: React.CSSProperties = {\n position: 'sticky',\n top: 0,\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '8px 16px',\n background: 'var(--color-surface, #fff)',\n borderBottom: '1px solid var(--color-neutral-90)',\n zIndex: 200,\n flexShrink: 0,\n};\n\n// ---------------------------------------------------------------------------\n// Table columns\n// ---------------------------------------------------------------------------\n\ntype PageRow = PuckPageListItem & { id: string };\n\nconst COLUMNS = [\n { key: 'name', label: 'Name' },\n { key: 'slug', label: 'Slug' },\n { key: 'status', label: 'Status' },\n { key: 'updatedAt', label: 'Updated' },\n { key: 'actions', label: 'Actions', shouldIgnoreRowClick: true },\n];\n\n// ---------------------------------------------------------------------------\n// PageList route\n// ---------------------------------------------------------------------------\n\ninterface PageListProps {\n backButton?: ReactNode;\n}\n\nconst PageList: React.FC<PageListProps> = ({ backButton }) => {\n const navigate = useNavigate();\n const { pages, loading, error, createPage, deletePage, refresh } = usePuckPages();\n\n const [creating, setCreating] = useState(false);\n const [newName, setNewName] = useState('');\n const [newSlug, setNewSlug] = useState('');\n const [formError, setFormError] = useState('');\n const [submitting, setSubmitting] = useState(false);\n const [deleting, setDeleting] = useState<string | null>(null);\n\n const handleCreate = async () => {\n if (!newName.trim()) { setFormError('Name is required'); return; }\n if (!newSlug.trim()) { setFormError('Slug is required'); return; }\n setFormError('');\n setSubmitting(true);\n try {\n const input: CreatePuckPageInput = {\n name: newName.trim(),\n slug: newSlug.trim().startsWith('/') ? newSlug.trim() : `/${newSlug.trim()}`,\n };\n const created = await createPage(input);\n setCreating(false);\n setNewName('');\n setNewSlug('');\n navigate(`/${created.key}/edit`, { state: { pageName: created.value.name } });\n } catch (err) {\n setFormError((err as Error).message);\n } finally {\n setSubmitting(false);\n }\n };\n\n const handleDelete = async (page: PuckPageListItem) => {\n if (!confirm(`Delete \"${page.value.name}\"? This cannot be undone.`)) return;\n setDeleting(page.key);\n try {\n await deletePage(page.key);\n await refresh();\n } finally {\n setDeleting(null);\n }\n };\n\n if (loading) {\n return (\n <div style={{ padding: '64px', display: 'flex', justifyContent: 'center' }}>\n <LoadingSpinner />\n </div>\n );\n }\n\n if (error) {\n return (\n <div style={{ padding: '32px' }}>\n <Text.Body tone=\"negative\">Error: {error}</Text.Body>\n </div>\n );\n }\n\n const rows: PageRow[] = pages.map((p) => ({ ...p, id: p.key }));\n\n return (\n <div style={{ maxWidth: '1200px', margin: '0 auto', padding: '32px 24px' }}>\n <Spacings.Stack scale=\"l\">\n <Spacings.Inline justifyContent=\"space-between\" alignItems=\"center\">\n <Spacings.Inline scale=\"m\" alignItems=\"center\">\n {backButton}\n <Text.Headline as=\"h1\">Puck Pages</Text.Headline>\n </Spacings.Inline>\n <PrimaryButton\n label=\"New Page\"\n iconLeft={<PlusThinIcon />}\n onClick={() => setCreating(true)}\n />\n </Spacings.Inline>\n\n {creating && (\n <Card insetScale=\"l\">\n <Spacings.Stack scale=\"m\">\n <Text.Subheadline as=\"h4\" isBold>Create New Page</Text.Subheadline>\n <Spacings.Inline scale=\"m\">\n <div style={{ flex: 1 }}>\n <Spacings.Stack scale=\"xs\">\n <Label htmlFor=\"new-page-name\">Name *</Label>\n <TextInput\n id=\"new-page-name\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n placeholder=\"Home Page\"\n />\n </Spacings.Stack>\n </div>\n <div style={{ flex: 1 }}>\n <Spacings.Stack scale=\"xs\">\n <Label htmlFor=\"new-page-slug\">Slug *</Label>\n <TextInput\n id=\"new-page-slug\"\n value={newSlug}\n onChange={(e) => setNewSlug(e.target.value)}\n placeholder=\"/home\"\n />\n </Spacings.Stack>\n </div>\n </Spacings.Inline>\n {formError && <Text.Body tone=\"negative\">{formError}</Text.Body>}\n <Spacings.Inline scale=\"s\">\n <PrimaryButton\n label={submitting ? 'Creating…' : 'Create'}\n onClick={() => void handleCreate()}\n isDisabled={submitting}\n />\n <SecondaryButton\n label=\"Cancel\"\n onClick={() => { setCreating(false); setFormError(''); }}\n />\n </Spacings.Inline>\n </Spacings.Stack>\n </Card>\n )}\n\n {pages.length === 0 && !creating ? (\n <Spacings.Stack scale=\"m\" alignItems=\"center\">\n <Text.Body tone=\"secondary\">No pages yet.</Text.Body>\n <PrimaryButton\n label=\"Create first page\"\n iconLeft={<PlusThinIcon />}\n onClick={() => setCreating(true)}\n />\n </Spacings.Stack>\n ) : pages.length > 0 ? (\n <DataTable\n columns={COLUMNS}\n rows={rows}\n itemRenderer={(row: PageRow, column) => {\n switch (column.key) {\n case 'name':\n return (\n <Spacings.Stack scale=\"xs\">\n <Text.Body isBold>{row.value.name}</Text.Body>\n <Text.Detail tone=\"secondary\">{row.key}</Text.Detail>\n </Spacings.Stack>\n );\n case 'slug':\n return (\n <code\n style={{\n background: 'var(--color-neutral-95)',\n padding: '2px 6px',\n borderRadius: 'var(--border-radius-4)',\n fontSize: 'var(--font-size-10)',\n fontFamily: 'monospace',\n }}\n >\n {row.value.slug}\n </code>\n );\n case 'status':\n return (\n <span>\n {row.states.draft && <StatusBadge variant=\"draft\" />}\n {row.states.published && <StatusBadge variant=\"published\" />}\n {!row.states.draft && !row.states.published && <StatusBadge variant=\"none\" />}\n </span>\n );\n case 'updatedAt':\n return (\n <Text.Body tone=\"secondary\">\n {new Date(row.value.updatedAt).toLocaleString()}\n </Text.Body>\n );\n case 'actions':\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <PrimaryButton\n label=\"Edit\"\n size=\"20\"\n onClick={() =>\n navigate(`/${row.key}/edit`, { state: { pageName: row.value.name } })\n }\n />\n <SecondaryButton\n label=\"Preview\"\n size=\"20\"\n onClick={() =>\n navigate(`/${row.key}/preview`, { state: { pageName: row.value.name } })\n }\n />\n <FlatButton\n tone=\"critical\"\n label={deleting === row.key ? '…' : 'Delete'}\n isDisabled={deleting === row.key}\n onClick={() => void handleDelete(row)}\n />\n </div>\n );\n default:\n return null;\n }\n }}\n />\n ) : null}\n </Spacings.Stack>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// PageEditorRoute\n// ---------------------------------------------------------------------------\n\ninterface RouteProps {\n config: Config;\n backButton?: ReactNode;\n}\n\nconst PageEditorRoute: React.FC<RouteProps> = ({ config, backButton }) => {\n const { pageKey } = useParams<{ pageKey: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const { baseURL, projectKey, businessUnitKey, jwtToken } = usePuckApiContext();\n const pageName =\n (location.state as { pageName?: string } | null)?.pageName ?? pageKey ?? 'Page';\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>\n <div style={NAV_BAR_STYLE}>\n {backButton}\n {backButton && <Text.Body tone=\"secondary\">/</Text.Body>}\n <FlatButton\n label=\"Pages\"\n icon={<AngleLeftIcon />}\n iconPosition=\"left\"\n onClick={() => navigate('/')}\n />\n <Text.Body tone=\"secondary\">/</Text.Body>\n <Text.Body isBold>{pageName}</Text.Body>\n </div>\n <div style={{ flex: 1, overflow: 'hidden' }}>\n <PuckEditor\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n jwtToken={jwtToken ?? ''}\n pageKey={pageKey!}\n config={config}\n onError={(err: Error) => { console.error('[PageManager] editor error:', err); }}\n />\n </div>\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// PagePreviewRoute\n// ---------------------------------------------------------------------------\n\nconst PagePreviewRoute: React.FC<RouteProps> = ({ config, backButton }) => {\n const { pageKey } = useParams<{ pageKey: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const pageName =\n (location.state as { pageName?: string } | null)?.pageName ?? pageKey ?? 'Page';\n\n return (\n <div>\n <div style={NAV_BAR_STYLE}>\n {backButton}\n {backButton && <Text.Body tone=\"secondary\">/</Text.Body>}\n <FlatButton\n label=\"Pages\"\n icon={<AngleLeftIcon />}\n iconPosition=\"left\"\n onClick={() => navigate('/')}\n />\n <Text.Body tone=\"secondary\">/</Text.Body>\n <Text.Body isBold>{pageName}</Text.Body>\n <span\n style={{\n background: 'var(--color-primary-95)',\n color: 'var(--color-primary-25)',\n border: '1px solid var(--color-primary-85)',\n display: 'inline-flex',\n alignItems: 'center',\n padding: '2px 10px',\n borderRadius: 'var(--border-radius-20)',\n fontSize: 'var(--font-size-10)',\n fontWeight: 'var(--font-weight-600)',\n }}\n >\n Preview\n </span>\n </div>\n <PuckRenderer pageKey={pageKey} mode=\"preview\" config={config} />\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Inner router component\n// ---------------------------------------------------------------------------\n\ninterface PageManagerInnerProps {\n config: Config;\n backButton?: ReactNode;\n}\n\nconst PageManagerInner: React.FC<PageManagerInnerProps> = ({ config, backButton }) => (\n <Routes>\n <Route path=\"/\" element={<PageList backButton={backButton} />} />\n <Route\n path=\"/:pageKey/edit\"\n element={<PageEditorRoute config={config} backButton={backButton} />}\n />\n <Route\n path=\"/:pageKey/preview\"\n element={<PagePreviewRoute config={config} backButton={backButton} />}\n />\n </Routes>\n);\n\n// ---------------------------------------------------------------------------\n// Public component\n// ---------------------------------------------------------------------------\n\nexport interface PageManagerProps {\n /** URL path where this manager is mounted, e.g. \"/pages\" — used as router basename */\n parentUrl: string;\n baseURL: string;\n projectKey: string;\n businessUnitKey: string;\n jwtToken: string;\n /** Puck component config — passed to editor and preview */\n config: Config;\n /** Optional element rendered before the breadcrumb in editor/preview headers */\n backButton?: ReactNode;\n}\n\nexport const PageManager: React.FC<PageManagerProps> = ({\n parentUrl,\n baseURL,\n projectKey,\n businessUnitKey,\n jwtToken,\n config,\n backButton,\n}) => (\n <PuckApiProvider\n baseURL={baseURL}\n projectKey={projectKey}\n businessUnitKey={businessUnitKey}\n jwtToken={jwtToken}\n >\n <BrowserRouter basename={parentUrl}>\n <PageManagerInner config={config} backButton={backButton} />\n </BrowserRouter>\n </PuckApiProvider>\n);\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@commercetools-demo/puck-page-manager",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Router-aware page manager UI (list, editor, preview) for the Puck CMS integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"package.json"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"build:watch": "tsup --watch",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@commercetools-demo/puck-api": "^0.1.0",
|
|
29
|
+
"@commercetools-demo/puck-editor": "^0.1.0",
|
|
30
|
+
"@commercetools-demo/puck-renderer": "^0.1.0",
|
|
31
|
+
"@commercetools-demo/puck-types": "^0.1.0",
|
|
32
|
+
"@commercetools-uikit/card": "^20.5.0",
|
|
33
|
+
"@commercetools-uikit/data-table": "^20.5.0",
|
|
34
|
+
"@commercetools-uikit/flat-button": "^20.5.0",
|
|
35
|
+
"@commercetools-uikit/icons": "^20.5.0",
|
|
36
|
+
"@commercetools-uikit/label": "^20.5.0",
|
|
37
|
+
"@commercetools-uikit/loading-spinner": "^20.5.0",
|
|
38
|
+
"@commercetools-uikit/primary-button": "^20.5.0",
|
|
39
|
+
"@commercetools-uikit/secondary-button": "^20.5.0",
|
|
40
|
+
"@commercetools-uikit/spacings": "^20.5.0",
|
|
41
|
+
"@commercetools-uikit/text": "^20.5.0",
|
|
42
|
+
"@commercetools-uikit/text-input": "^20.5.0",
|
|
43
|
+
"@measured/puck": "^0.18.2"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"react": ">=19.0.0",
|
|
47
|
+
"react-dom": ">=19.0.0",
|
|
48
|
+
"react-intl": ">=6.0.0",
|
|
49
|
+
"react-router-dom": ">=5.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/react": "^18",
|
|
53
|
+
"@types/react-dom": "^18",
|
|
54
|
+
"tsup": "^8.3.0",
|
|
55
|
+
"typescript": "^5.7.2"
|
|
56
|
+
}
|
|
57
|
+
}
|