@commercetools-demo/puck-content-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.js ADDED
@@ -0,0 +1,1125 @@
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
+ ContentEditor: () => ContentEditor,
34
+ ContentManager: () => ContentManager,
35
+ ContentManagerRouter: () => ContentManagerRouter
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/ContentManager.tsx
40
+ var import_react = require("react");
41
+ var import_puck_api = require("@commercetools-demo/puck-api");
42
+ var import_data_table = __toESM(require("@commercetools-uikit/data-table"));
43
+ var import_primary_button = __toESM(require("@commercetools-uikit/primary-button"));
44
+ var import_secondary_button = __toESM(require("@commercetools-uikit/secondary-button"));
45
+ var import_flat_button = __toESM(require("@commercetools-uikit/flat-button"));
46
+ var import_card = __toESM(require("@commercetools-uikit/card"));
47
+ var import_spacings = __toESM(require("@commercetools-uikit/spacings"));
48
+ var import_text = __toESM(require("@commercetools-uikit/text"));
49
+ var import_loading_spinner = __toESM(require("@commercetools-uikit/loading-spinner"));
50
+ var import_text_input = __toESM(require("@commercetools-uikit/text-input"));
51
+ var import_label = __toESM(require("@commercetools-uikit/label"));
52
+ var import_icons = require("@commercetools-uikit/icons");
53
+ var import_jsx_runtime = require("react/jsx-runtime");
54
+ var StatusBadge = ({ variant }) => {
55
+ 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)" };
56
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
57
+ "span",
58
+ {
59
+ style: {
60
+ ...styles,
61
+ display: "inline-flex",
62
+ alignItems: "center",
63
+ padding: "2px 8px",
64
+ borderRadius: "var(--border-radius-20)",
65
+ fontSize: "var(--font-size-10)",
66
+ fontWeight: "var(--font-weight-600)",
67
+ marginRight: "4px",
68
+ whiteSpace: "nowrap"
69
+ },
70
+ children: variant === "published" ? "Published" : variant === "draft" ? "Draft" : "No state"
71
+ }
72
+ );
73
+ };
74
+ var columns = [
75
+ { key: "name", label: "Name" },
76
+ { key: "contentType", label: "Content Type" },
77
+ { key: "status", label: "Status" },
78
+ { key: "updatedAt", label: "Updated" },
79
+ { key: "actions", label: "Actions", shouldIgnoreRowClick: true }
80
+ ];
81
+ var ContentList = ({ defaultContentType, onEdit }) => {
82
+ const { contents, loading, error, fetchContents, createContent, deleteContent, refresh } = (0, import_puck_api.usePuckContents)(defaultContentType);
83
+ const [filterType, setFilterType] = (0, import_react.useState)(defaultContentType ?? "");
84
+ const [showCreate, setShowCreate] = (0, import_react.useState)(false);
85
+ const [createName, setCreateName] = (0, import_react.useState)("");
86
+ const [createType, setCreateType] = (0, import_react.useState)(defaultContentType ?? "");
87
+ const [createError, setCreateError] = (0, import_react.useState)(null);
88
+ const [creating, setCreating] = (0, import_react.useState)(false);
89
+ const [deleting, setDeleting] = (0, import_react.useState)(null);
90
+ const handleFilter = () => void fetchContents(filterType || void 0);
91
+ const handleCreate = async () => {
92
+ setCreateError(null);
93
+ if (!createName.trim()) {
94
+ setCreateError("Name is required");
95
+ return;
96
+ }
97
+ if (!createType.trim()) {
98
+ setCreateError("Content type is required");
99
+ return;
100
+ }
101
+ setCreating(true);
102
+ try {
103
+ const input = {
104
+ name: createName.trim(),
105
+ contentType: createType.trim(),
106
+ data: { content: [], root: { props: {} } }
107
+ };
108
+ await createContent(input);
109
+ setShowCreate(false);
110
+ setCreateName("");
111
+ setCreateType(defaultContentType ?? "");
112
+ } catch (err) {
113
+ setCreateError(err.message);
114
+ } finally {
115
+ setCreating(false);
116
+ }
117
+ };
118
+ const handleDelete = async (key) => {
119
+ if (!confirm("Delete this content item and all its versions?")) return;
120
+ setDeleting(key);
121
+ try {
122
+ await deleteContent(key);
123
+ } finally {
124
+ setDeleting(null);
125
+ }
126
+ };
127
+ const rows = contents.map((c) => ({ ...c, id: c.key }));
128
+ 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: [
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { justifyContent: "space-between", alignItems: "center", children: [
130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Headline, { as: "h1", children: "Content Items" }),
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
132
+ import_primary_button.default,
133
+ {
134
+ label: "New Content",
135
+ iconLeft: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlusThinIcon, {}),
136
+ onClick: () => setShowCreate((v) => !v)
137
+ }
138
+ )
139
+ ] }),
140
+ showCreate && /* @__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: [
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Subheadline, { as: "h4", isBold: true, children: "Create Content Item" }),
142
+ createError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "negative", children: createError }),
143
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "m", children: [
144
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.default, { htmlFor: "create-name", children: "Name" }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ import_text_input.default,
148
+ {
149
+ id: "create-name",
150
+ value: createName,
151
+ onChange: (e) => setCreateName(e.target.value),
152
+ placeholder: "e.g. Homepage Hero"
153
+ }
154
+ )
155
+ ] }) }),
156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
157
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_label.default, { htmlFor: "create-type", children: "Content Type" }),
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
+ import_text_input.default,
160
+ {
161
+ id: "create-type",
162
+ value: createType,
163
+ onChange: (e) => setCreateType(e.target.value),
164
+ placeholder: "e.g. hero, banner"
165
+ }
166
+ )
167
+ ] }) })
168
+ ] }),
169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "s", children: [
170
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
171
+ import_primary_button.default,
172
+ {
173
+ label: creating ? "Creating\u2026" : "Create",
174
+ onClick: () => void handleCreate(),
175
+ isDisabled: creating
176
+ }
177
+ ),
178
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_secondary_button.default, { label: "Cancel", onClick: () => setShowCreate(false) })
179
+ ] })
180
+ ] }) }),
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_spacings.default.Inline, { scale: "s", alignItems: "center", children: [
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, maxWidth: "280px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
+ import_text_input.default,
184
+ {
185
+ value: filterType,
186
+ onChange: (e) => setFilterType(e.target.value),
187
+ placeholder: "Filter by content type\u2026"
188
+ }
189
+ ) }),
190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
191
+ import_secondary_button.default,
192
+ {
193
+ label: "Filter",
194
+ iconLeft: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.SearchIcon, {}),
195
+ onClick: handleFilter
196
+ }
197
+ ),
198
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
199
+ import_flat_button.default,
200
+ {
201
+ label: "Clear",
202
+ onClick: () => {
203
+ setFilterType("");
204
+ void fetchContents(void 0);
205
+ }
206
+ }
207
+ ),
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_flat_button.default, { label: "Refresh", onClick: () => void refresh() })
209
+ ] }),
210
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "negative", children: error }),
211
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", justifyContent: "center", padding: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_loading_spinner.default, {}) }) : contents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_spacings.default.Stack, { scale: "m", alignItems: "center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: "No content items found." }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
212
+ import_data_table.default,
213
+ {
214
+ columns,
215
+ rows,
216
+ itemRenderer: (row, column) => {
217
+ switch (column.key) {
218
+ case "name":
219
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { isBold: true, children: row.value.name });
220
+ case "contentType":
221
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
222
+ "code",
223
+ {
224
+ style: {
225
+ background: "var(--color-neutral-95)",
226
+ padding: "2px 6px",
227
+ borderRadius: "var(--border-radius-4)",
228
+ fontSize: "var(--font-size-10)",
229
+ fontFamily: "monospace"
230
+ },
231
+ children: row.value.contentType
232
+ }
233
+ );
234
+ case "status": {
235
+ const hasDraft = !!row.states.draft;
236
+ const hasPublished = !!row.states.published;
237
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
238
+ hasDraft && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "draft" }),
239
+ hasPublished && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "published" }),
240
+ !hasDraft && !hasPublished && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { variant: "none" })
241
+ ] });
242
+ }
243
+ case "updatedAt":
244
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.default.Body, { tone: "secondary", children: new Date(row.value.updatedAt).toLocaleDateString() });
245
+ case "actions":
246
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
247
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_primary_button.default, { label: "Edit", size: "20", onClick: () => onEdit(row) }),
248
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
249
+ import_flat_button.default,
250
+ {
251
+ tone: "critical",
252
+ label: deleting === row.key ? "\u2026" : "Delete",
253
+ isDisabled: deleting === row.key,
254
+ onClick: () => void handleDelete(row.key)
255
+ }
256
+ )
257
+ ] });
258
+ default:
259
+ return null;
260
+ }
261
+ }
262
+ }
263
+ )
264
+ ] }) });
265
+ };
266
+ var ContentManager = ({
267
+ baseURL,
268
+ projectKey,
269
+ businessUnitKey,
270
+ jwtToken,
271
+ defaultContentType,
272
+ onEdit
273
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
+ import_puck_api.PuckApiProvider,
275
+ {
276
+ baseURL,
277
+ projectKey,
278
+ businessUnitKey,
279
+ jwtToken,
280
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContentList, { defaultContentType, onEdit })
281
+ }
282
+ );
283
+
284
+ // src/ContentEditor.tsx
285
+ var import_react2 = require("react");
286
+ var import_puck = require("@measured/puck");
287
+ var import_puck2 = require("@measured/puck/puck.css");
288
+ var import_puck_api2 = require("@commercetools-demo/puck-api");
289
+ var import_puck_editor = require("@commercetools-demo/puck-editor");
290
+ var import_jsx_runtime2 = require("react/jsx-runtime");
291
+ var BADGE_STYLES = {
292
+ saving: { bg: "rgba(251, 191, 36, 0.12)", color: "var(--status-saving)", border: "rgba(251, 191, 36, 0.3)" },
293
+ unsaved: { bg: "rgba(100, 116, 139, 0.12)", color: "var(--text-muted)", border: "rgba(100, 116, 139, 0.3)" },
294
+ draft: { bg: "rgba(129, 140, 248, 0.12)", color: "var(--status-draft)", border: "rgba(129, 140, 248, 0.3)" },
295
+ published: { bg: "rgba(6, 214, 160, 0.12)", color: "var(--status-published)", border: "rgba(6, 214, 160, 0.3)" }
296
+ };
297
+ var StatusBadge2 = ({
298
+ label,
299
+ variant
300
+ }) => {
301
+ const bs = BADGE_STYLES[variant];
302
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
303
+ "span",
304
+ {
305
+ style: {
306
+ display: "inline-flex",
307
+ alignItems: "center",
308
+ padding: "2px 10px",
309
+ borderRadius: "12px",
310
+ fontSize: "12px",
311
+ fontWeight: 600,
312
+ background: bs.bg,
313
+ color: bs.color,
314
+ border: `1px solid ${bs.border}`
315
+ },
316
+ children: label
317
+ }
318
+ );
319
+ };
320
+ var ContentToolbar = ({
321
+ saving,
322
+ isDirty,
323
+ states,
324
+ onSave,
325
+ onPublish,
326
+ onRevert
327
+ }) => {
328
+ const hasDraft = Boolean(states.draft);
329
+ const hasPublished = Boolean(states.published);
330
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "12px", flexWrap: "wrap" }, children: [
331
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
332
+ saving && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge2, { label: "Saving\u2026", variant: "saving" }),
333
+ !saving && isDirty && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge2, { label: "Unsaved", variant: "unsaved" }),
334
+ !saving && !isDirty && hasDraft && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge2, { label: "Draft", variant: "draft" }),
335
+ hasPublished && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge2, { label: "Published", variant: "published" })
336
+ ] }),
337
+ hasDraft && hasPublished && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
338
+ "button",
339
+ {
340
+ onClick: onRevert,
341
+ disabled: saving,
342
+ style: {
343
+ padding: "6px 14px",
344
+ borderRadius: "4px",
345
+ border: "1px solid var(--border-glow)",
346
+ background: "transparent",
347
+ color: "var(--text-muted)",
348
+ fontWeight: 500,
349
+ fontSize: "13px",
350
+ cursor: saving ? "not-allowed" : "pointer",
351
+ opacity: saving ? 0.5 : 1
352
+ },
353
+ children: "Revert to Published"
354
+ }
355
+ ),
356
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
357
+ "button",
358
+ {
359
+ onClick: onSave,
360
+ disabled: !isDirty || saving,
361
+ style: {
362
+ padding: "6px 14px",
363
+ borderRadius: "4px",
364
+ border: "1px solid var(--border-glow)",
365
+ background: "transparent",
366
+ color: "var(--text-muted)",
367
+ fontWeight: 500,
368
+ fontSize: "13px",
369
+ cursor: !isDirty || saving ? "not-allowed" : "pointer",
370
+ opacity: !isDirty || saving ? 0.4 : 1
371
+ },
372
+ children: "Save"
373
+ }
374
+ ),
375
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
376
+ "button",
377
+ {
378
+ onClick: onPublish,
379
+ disabled: saving,
380
+ style: {
381
+ padding: "6px 16px",
382
+ borderRadius: "4px",
383
+ border: "1px solid var(--accent-cyan)",
384
+ background: "rgba(0, 212, 255, 0.1)",
385
+ color: "var(--accent-cyan)",
386
+ fontWeight: 600,
387
+ fontSize: "13px",
388
+ cursor: saving ? "not-allowed" : "pointer",
389
+ opacity: saving ? 0.5 : 1,
390
+ boxShadow: "0 0 12px rgba(0, 212, 255, 0.15)"
391
+ },
392
+ children: hasPublished ? "Re-publish" : "Publish"
393
+ }
394
+ )
395
+ ] });
396
+ };
397
+ var ContentEditorInner = ({
398
+ contentKey,
399
+ config,
400
+ onPublish,
401
+ onSave,
402
+ onError
403
+ }) => {
404
+ const {
405
+ content,
406
+ states,
407
+ saving,
408
+ loading,
409
+ error,
410
+ saveDraft,
411
+ publish,
412
+ revertToPublished
413
+ } = (0, import_puck_api2.usePuckContent)(contentKey);
414
+ const latestDataRef = (0, import_react2.useRef)(null);
415
+ const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react2.useState)(false);
416
+ const handleChange = (0, import_react2.useCallback)((data) => {
417
+ latestDataRef.current = data;
418
+ setHasUnsavedChanges(true);
419
+ }, []);
420
+ const handleSave = (0, import_react2.useCallback)(async () => {
421
+ const data = latestDataRef.current;
422
+ if (!data) return;
423
+ try {
424
+ await saveDraft(data);
425
+ setHasUnsavedChanges(false);
426
+ onSave?.(data);
427
+ } catch (err) {
428
+ onError?.(err);
429
+ }
430
+ }, [saveDraft, onSave, onError]);
431
+ const handlePublish = (0, import_react2.useCallback)(
432
+ async (data) => {
433
+ try {
434
+ await saveDraft(data);
435
+ setHasUnsavedChanges(false);
436
+ await publish(false);
437
+ onPublish?.(data);
438
+ } catch (err) {
439
+ onError?.(err);
440
+ }
441
+ },
442
+ [saveDraft, publish, onPublish, onError]
443
+ );
444
+ const handleRevert = (0, import_react2.useCallback)(async () => {
445
+ try {
446
+ await revertToPublished();
447
+ setHasUnsavedChanges(false);
448
+ } catch (err) {
449
+ onError?.(err);
450
+ }
451
+ }, [revertToPublished, onError]);
452
+ const contentConfig = (0, import_react2.useMemo)(() => {
453
+ const otherRootFields = Object.fromEntries(
454
+ Object.entries(config.root?.fields ?? {}).filter(([k]) => k !== "title")
455
+ );
456
+ return {
457
+ ...config,
458
+ root: {
459
+ ...config.root,
460
+ fields: {
461
+ title: { type: "text", label: "Content Title" },
462
+ slot: { type: "text", label: "Slot" },
463
+ ...otherRootFields
464
+ },
465
+ defaultProps: {
466
+ title: "New Content",
467
+ slot: "",
468
+ ...config.root?.defaultProps
469
+ }
470
+ }
471
+ };
472
+ }, [config]);
473
+ if (loading) {
474
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
475
+ "div",
476
+ {
477
+ style: {
478
+ display: "flex",
479
+ alignItems: "center",
480
+ justifyContent: "center",
481
+ height: "100vh",
482
+ fontSize: "16px",
483
+ color: "var(--text-muted)"
484
+ },
485
+ children: "Loading editor\u2026"
486
+ }
487
+ );
488
+ }
489
+ if (error) {
490
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
491
+ "div",
492
+ {
493
+ style: {
494
+ padding: "32px",
495
+ color: "var(--status-error)",
496
+ background: "rgba(248, 113, 113, 0.08)",
497
+ border: "1px solid rgba(248, 113, 113, 0.25)",
498
+ borderRadius: "8px",
499
+ margin: "16px"
500
+ },
501
+ children: [
502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "Error loading content:" }),
503
+ " ",
504
+ error
505
+ ]
506
+ }
507
+ );
508
+ }
509
+ const activeData = states.draft?.data ?? content?.data ?? {
510
+ content: [],
511
+ root: { props: {} }
512
+ };
513
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_puck_editor.ComponentSearchProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
514
+ import_puck.Puck,
515
+ {
516
+ config: contentConfig,
517
+ data: activeData,
518
+ onChange: handleChange,
519
+ onPublish: handlePublish,
520
+ overrides: {
521
+ headerActions: () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
522
+ ContentToolbar,
523
+ {
524
+ saving,
525
+ isDirty: hasUnsavedChanges,
526
+ states,
527
+ onSave: () => void handleSave(),
528
+ onPublish: () => void handlePublish(activeData),
529
+ onRevert: () => void handleRevert()
530
+ }
531
+ ),
532
+ components: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_puck_editor.ComponentsPanel, { children }),
533
+ componentItem: ({ children, name }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_puck_editor.ComponentItemFilter, { name, children })
534
+ }
535
+ }
536
+ ) });
537
+ };
538
+ var ContentEditor = ({
539
+ baseURL,
540
+ projectKey,
541
+ businessUnitKey,
542
+ jwtToken,
543
+ contentKey,
544
+ config,
545
+ onPublish,
546
+ onSave,
547
+ onError
548
+ }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
549
+ import_puck_api2.PuckApiProvider,
550
+ {
551
+ baseURL,
552
+ projectKey,
553
+ businessUnitKey,
554
+ jwtToken,
555
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
556
+ ContentEditorInner,
557
+ {
558
+ contentKey,
559
+ config,
560
+ onPublish,
561
+ onSave,
562
+ onError
563
+ }
564
+ )
565
+ }
566
+ );
567
+
568
+ // src/ContentManagerRouter.tsx
569
+ var import_react3 = require("react");
570
+ var import_react_router_dom = require("react-router-dom");
571
+ var import_puck3 = require("@measured/puck");
572
+ var import_puck4 = require("@measured/puck/puck.css");
573
+ var import_puck_editor2 = require("@commercetools-demo/puck-editor");
574
+ var import_puck_api3 = require("@commercetools-demo/puck-api");
575
+ var import_data_table2 = __toESM(require("@commercetools-uikit/data-table"));
576
+ var import_primary_button2 = __toESM(require("@commercetools-uikit/primary-button"));
577
+ var import_secondary_button2 = __toESM(require("@commercetools-uikit/secondary-button"));
578
+ var import_flat_button2 = __toESM(require("@commercetools-uikit/flat-button"));
579
+ var import_card2 = __toESM(require("@commercetools-uikit/card"));
580
+ var import_spacings2 = __toESM(require("@commercetools-uikit/spacings"));
581
+ var import_text2 = __toESM(require("@commercetools-uikit/text"));
582
+ var import_loading_spinner2 = __toESM(require("@commercetools-uikit/loading-spinner"));
583
+ var import_text_input2 = __toESM(require("@commercetools-uikit/text-input"));
584
+ var import_label2 = __toESM(require("@commercetools-uikit/label"));
585
+ var import_icons2 = require("@commercetools-uikit/icons");
586
+ var import_jsx_runtime3 = require("react/jsx-runtime");
587
+ var StatusBadge3 = ({ variant }) => {
588
+ 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)" };
589
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
590
+ "span",
591
+ {
592
+ style: {
593
+ ...styles,
594
+ display: "inline-flex",
595
+ alignItems: "center",
596
+ padding: "2px 8px",
597
+ borderRadius: "var(--border-radius-20)",
598
+ fontSize: "var(--font-size-10)",
599
+ fontWeight: "var(--font-weight-600)",
600
+ marginRight: "4px",
601
+ whiteSpace: "nowrap"
602
+ },
603
+ children: variant === "published" ? "Published" : variant === "draft" ? "Draft" : "No state"
604
+ }
605
+ );
606
+ };
607
+ var BADGE_STYLES2 = {
608
+ saving: { bg: "rgba(251, 191, 36, 0.12)", color: "var(--status-saving)", border: "rgba(251, 191, 36, 0.3)" },
609
+ unsaved: { bg: "rgba(100, 116, 139, 0.12)", color: "var(--text-muted)", border: "rgba(100, 116, 139, 0.3)" },
610
+ draft: { bg: "rgba(129, 140, 248, 0.12)", color: "var(--status-draft)", border: "rgba(129, 140, 248, 0.3)" },
611
+ published: { bg: "rgba(6, 214, 160, 0.12)", color: "var(--status-published)", border: "rgba(6, 214, 160, 0.3)" }
612
+ };
613
+ var EditorStatusBadge = ({ label, variant }) => {
614
+ const bs = BADGE_STYLES2[variant];
615
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
616
+ "span",
617
+ {
618
+ style: {
619
+ display: "inline-flex",
620
+ alignItems: "center",
621
+ padding: "2px 10px",
622
+ borderRadius: "12px",
623
+ fontSize: "12px",
624
+ fontWeight: 600,
625
+ background: bs.bg,
626
+ color: bs.color,
627
+ border: `1px solid ${bs.border}`
628
+ },
629
+ children: label
630
+ }
631
+ );
632
+ };
633
+ var ContentToolbar2 = ({ saving, isDirty, states, onSave, onPublish, onRevert }) => {
634
+ const hasDraft = Boolean(states.draft);
635
+ const hasPublished = Boolean(states.published);
636
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "12px", flexWrap: "wrap" }, children: [
637
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
638
+ saving && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EditorStatusBadge, { label: "Saving\u2026", variant: "saving" }),
639
+ !saving && isDirty && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EditorStatusBadge, { label: "Unsaved", variant: "unsaved" }),
640
+ !saving && !isDirty && hasDraft && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EditorStatusBadge, { label: "Draft", variant: "draft" }),
641
+ hasPublished && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EditorStatusBadge, { label: "Published", variant: "published" })
642
+ ] }),
643
+ hasDraft && hasPublished && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
644
+ "button",
645
+ {
646
+ onClick: onRevert,
647
+ disabled: saving,
648
+ style: {
649
+ padding: "6px 14px",
650
+ borderRadius: "4px",
651
+ border: "1px solid var(--border-glow)",
652
+ background: "transparent",
653
+ color: "var(--text-muted)",
654
+ fontWeight: 500,
655
+ fontSize: "13px",
656
+ cursor: saving ? "not-allowed" : "pointer",
657
+ opacity: saving ? 0.5 : 1
658
+ },
659
+ children: "Revert to Published"
660
+ }
661
+ ),
662
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
663
+ "button",
664
+ {
665
+ onClick: onSave,
666
+ disabled: !isDirty || saving,
667
+ style: {
668
+ padding: "6px 14px",
669
+ borderRadius: "4px",
670
+ border: "1px solid var(--border-glow)",
671
+ background: "transparent",
672
+ color: "var(--text-muted)",
673
+ fontWeight: 500,
674
+ fontSize: "13px",
675
+ cursor: !isDirty || saving ? "not-allowed" : "pointer",
676
+ opacity: !isDirty || saving ? 0.4 : 1
677
+ },
678
+ children: "Save"
679
+ }
680
+ ),
681
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
682
+ "button",
683
+ {
684
+ onClick: onPublish,
685
+ disabled: saving,
686
+ style: {
687
+ padding: "6px 16px",
688
+ borderRadius: "4px",
689
+ border: "1px solid var(--accent-cyan)",
690
+ background: "rgba(0, 212, 255, 0.1)",
691
+ color: "var(--accent-cyan)",
692
+ fontWeight: 600,
693
+ fontSize: "13px",
694
+ cursor: saving ? "not-allowed" : "pointer",
695
+ opacity: saving ? 0.5 : 1,
696
+ boxShadow: "0 0 12px rgba(0, 212, 255, 0.15)"
697
+ },
698
+ children: hasPublished ? "Re-publish" : "Publish"
699
+ }
700
+ )
701
+ ] });
702
+ };
703
+ var NAV_BAR_STYLE = {
704
+ position: "sticky",
705
+ top: 0,
706
+ display: "flex",
707
+ alignItems: "center",
708
+ gap: "12px",
709
+ padding: "8px 16px",
710
+ background: "var(--color-surface, #fff)",
711
+ borderBottom: "1px solid var(--color-neutral-90)",
712
+ zIndex: 200,
713
+ flexShrink: 0
714
+ };
715
+ var COLUMNS = [
716
+ { key: "name", label: "Name" },
717
+ { key: "contentType", label: "Content Type" },
718
+ { key: "status", label: "Status" },
719
+ { key: "updatedAt", label: "Updated" },
720
+ { key: "actions", label: "Actions", shouldIgnoreRowClick: true }
721
+ ];
722
+ var ContentListRoute = ({ defaultContentType, backButton }) => {
723
+ const navigate = (0, import_react_router_dom.useNavigate)();
724
+ const { contents, loading, error, fetchContents, createContent, deleteContent, refresh } = (0, import_puck_api3.usePuckContents)(defaultContentType);
725
+ const [filterType, setFilterType] = (0, import_react3.useState)(defaultContentType ?? "");
726
+ const [showCreate, setShowCreate] = (0, import_react3.useState)(false);
727
+ const [createName, setCreateName] = (0, import_react3.useState)("");
728
+ const [createType, setCreateType] = (0, import_react3.useState)(defaultContentType ?? "");
729
+ const [createError, setCreateError] = (0, import_react3.useState)(null);
730
+ const [creating, setCreating] = (0, import_react3.useState)(false);
731
+ const [deleting, setDeleting] = (0, import_react3.useState)(null);
732
+ const handleFilter = () => void fetchContents(filterType || void 0);
733
+ const handleCreate = async () => {
734
+ setCreateError(null);
735
+ if (!createName.trim()) {
736
+ setCreateError("Name is required");
737
+ return;
738
+ }
739
+ if (!createType.trim()) {
740
+ setCreateError("Content type is required");
741
+ return;
742
+ }
743
+ setCreating(true);
744
+ try {
745
+ const input = {
746
+ name: createName.trim(),
747
+ contentType: createType.trim(),
748
+ data: { content: [], root: { props: {} } }
749
+ };
750
+ const created = await createContent(input);
751
+ setShowCreate(false);
752
+ setCreateName("");
753
+ setCreateType(defaultContentType ?? "");
754
+ navigate(`/${created.key}`, { state: { contentName: created.value.name } });
755
+ } catch (err) {
756
+ setCreateError(err.message);
757
+ } finally {
758
+ setCreating(false);
759
+ }
760
+ };
761
+ const handleDelete = async (key) => {
762
+ if (!confirm("Delete this content item and all its versions?")) return;
763
+ setDeleting(key);
764
+ try {
765
+ await deleteContent(key);
766
+ } finally {
767
+ setDeleting(null);
768
+ }
769
+ };
770
+ const rows = contents.map((c) => ({ ...c, id: c.key }));
771
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { maxWidth: "1200px", margin: "0 auto", padding: "32px 24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Stack, { scale: "l", children: [
772
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Inline, { justifyContent: "space-between", alignItems: "center", children: [
773
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Inline, { scale: "m", alignItems: "center", children: [
774
+ backButton,
775
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Headline, { as: "h1", children: "Content Items" })
776
+ ] }),
777
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
778
+ import_primary_button2.default,
779
+ {
780
+ label: "New Content",
781
+ iconLeft: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.PlusThinIcon, {}),
782
+ onClick: () => setShowCreate((v) => !v)
783
+ }
784
+ )
785
+ ] }),
786
+ showCreate && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_card2.default, { insetScale: "l", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Stack, { scale: "m", children: [
787
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Subheadline, { as: "h4", isBold: true, children: "Create Content Item" }),
788
+ createError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "negative", children: createError }),
789
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Inline, { scale: "m", children: [
790
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Stack, { scale: "xs", children: [
791
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_label2.default, { htmlFor: "create-content-name", children: "Name" }),
792
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
793
+ import_text_input2.default,
794
+ {
795
+ id: "create-content-name",
796
+ value: createName,
797
+ onChange: (e) => setCreateName(e.target.value),
798
+ placeholder: "e.g. Homepage Hero"
799
+ }
800
+ )
801
+ ] }) }),
802
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Stack, { scale: "xs", children: [
803
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_label2.default, { htmlFor: "create-content-type", children: "Content Type" }),
804
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
805
+ import_text_input2.default,
806
+ {
807
+ id: "create-content-type",
808
+ value: createType,
809
+ onChange: (e) => setCreateType(e.target.value),
810
+ placeholder: "e.g. hero, banner"
811
+ }
812
+ )
813
+ ] }) })
814
+ ] }),
815
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Inline, { scale: "s", children: [
816
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
817
+ import_primary_button2.default,
818
+ {
819
+ label: creating ? "Creating\u2026" : "Create",
820
+ onClick: () => void handleCreate(),
821
+ isDisabled: creating
822
+ }
823
+ ),
824
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_secondary_button2.default, { label: "Cancel", onClick: () => setShowCreate(false) })
825
+ ] })
826
+ ] }) }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_spacings2.default.Inline, { scale: "s", alignItems: "center", children: [
828
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1, maxWidth: "280px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
829
+ import_text_input2.default,
830
+ {
831
+ value: filterType,
832
+ onChange: (e) => setFilterType(e.target.value),
833
+ placeholder: "Filter by content type\u2026"
834
+ }
835
+ ) }),
836
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
837
+ import_secondary_button2.default,
838
+ {
839
+ label: "Filter",
840
+ iconLeft: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.SearchIcon, {}),
841
+ onClick: handleFilter
842
+ }
843
+ ),
844
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
845
+ import_flat_button2.default,
846
+ {
847
+ label: "Clear",
848
+ onClick: () => {
849
+ setFilterType("");
850
+ void fetchContents(void 0);
851
+ }
852
+ }
853
+ ),
854
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_flat_button2.default, { label: "Refresh", onClick: () => void refresh() })
855
+ ] }),
856
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "negative", children: error }),
857
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", justifyContent: "center", padding: "48px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_loading_spinner2.default, {}) }) : contents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_spacings2.default.Stack, { scale: "m", alignItems: "center", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "secondary", children: "No content items found." }) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
858
+ import_data_table2.default,
859
+ {
860
+ columns: COLUMNS,
861
+ rows,
862
+ itemRenderer: (row, column) => {
863
+ switch (column.key) {
864
+ case "name":
865
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { isBold: true, children: row.value.name });
866
+ case "contentType":
867
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
868
+ "code",
869
+ {
870
+ style: {
871
+ background: "var(--color-neutral-95)",
872
+ padding: "2px 6px",
873
+ borderRadius: "var(--border-radius-4)",
874
+ fontSize: "var(--font-size-10)",
875
+ fontFamily: "monospace"
876
+ },
877
+ children: row.value.contentType
878
+ }
879
+ );
880
+ case "status": {
881
+ const hasDraft = !!row.states.draft;
882
+ const hasPublished = !!row.states.published;
883
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
884
+ hasDraft && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge3, { variant: "draft" }),
885
+ hasPublished && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge3, { variant: "published" }),
886
+ !hasDraft && !hasPublished && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge3, { variant: "none" })
887
+ ] });
888
+ }
889
+ case "updatedAt":
890
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "secondary", children: new Date(row.value.updatedAt).toLocaleDateString() });
891
+ case "actions":
892
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
893
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
894
+ import_primary_button2.default,
895
+ {
896
+ label: "Edit",
897
+ size: "20",
898
+ onClick: () => navigate(`/${row.key}`, { state: { contentName: row.value.name } })
899
+ }
900
+ ),
901
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
902
+ import_flat_button2.default,
903
+ {
904
+ tone: "critical",
905
+ label: deleting === row.key ? "\u2026" : "Delete",
906
+ isDisabled: deleting === row.key,
907
+ onClick: () => void handleDelete(row.key)
908
+ }
909
+ )
910
+ ] });
911
+ default:
912
+ return null;
913
+ }
914
+ }
915
+ }
916
+ )
917
+ ] }) });
918
+ };
919
+ var ContentEditorRoute = ({ config, backButton }) => {
920
+ const { contentKey } = (0, import_react_router_dom.useParams)();
921
+ const navigate = (0, import_react_router_dom.useNavigate)();
922
+ const location = (0, import_react_router_dom.useLocation)();
923
+ const contentName = location.state?.contentName ?? contentKey ?? "Content";
924
+ const {
925
+ content,
926
+ states,
927
+ saving,
928
+ loading,
929
+ error,
930
+ saveDraft,
931
+ publish,
932
+ revertToPublished
933
+ } = (0, import_puck_api3.usePuckContent)(contentKey);
934
+ const latestDataRef = (0, import_react3.useRef)(null);
935
+ const [hasUnsavedChanges, setHasUnsavedChanges] = (0, import_react3.useState)(false);
936
+ const handleChange = (0, import_react3.useCallback)((data) => {
937
+ latestDataRef.current = data;
938
+ setHasUnsavedChanges(true);
939
+ }, []);
940
+ const handleSave = (0, import_react3.useCallback)(async () => {
941
+ const data = latestDataRef.current;
942
+ if (!data) return;
943
+ try {
944
+ await saveDraft(data);
945
+ setHasUnsavedChanges(false);
946
+ } catch (err) {
947
+ console.error("[ContentManagerRouter] save error:", err);
948
+ }
949
+ }, [saveDraft]);
950
+ const handlePublish = (0, import_react3.useCallback)(
951
+ async (data) => {
952
+ try {
953
+ await saveDraft(data);
954
+ setHasUnsavedChanges(false);
955
+ await publish(false);
956
+ } catch (err) {
957
+ console.error("[ContentManagerRouter] publish error:", err);
958
+ }
959
+ },
960
+ [saveDraft, publish]
961
+ );
962
+ const handleRevert = (0, import_react3.useCallback)(async () => {
963
+ try {
964
+ await revertToPublished();
965
+ setHasUnsavedChanges(false);
966
+ } catch (err) {
967
+ console.error("[ContentManagerRouter] revert error:", err);
968
+ }
969
+ }, [revertToPublished]);
970
+ const contentConfig = (0, import_react3.useMemo)(() => {
971
+ const otherRootFields = Object.fromEntries(
972
+ Object.entries(config.root?.fields ?? {}).filter(([k]) => k !== "title")
973
+ );
974
+ return {
975
+ ...config,
976
+ root: {
977
+ ...config.root,
978
+ fields: {
979
+ title: { type: "text", label: "Content Title" },
980
+ slot: { type: "text", label: "Slot" },
981
+ ...otherRootFields
982
+ },
983
+ defaultProps: {
984
+ title: "New Content",
985
+ slot: "",
986
+ ...config.root?.defaultProps
987
+ }
988
+ }
989
+ };
990
+ }, [config]);
991
+ if (loading) {
992
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
993
+ "div",
994
+ {
995
+ style: {
996
+ display: "flex",
997
+ alignItems: "center",
998
+ justifyContent: "center",
999
+ height: "100vh",
1000
+ fontSize: "16px",
1001
+ color: "var(--text-muted)"
1002
+ },
1003
+ children: "Loading editor\u2026"
1004
+ }
1005
+ );
1006
+ }
1007
+ if (error) {
1008
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1009
+ "div",
1010
+ {
1011
+ style: {
1012
+ padding: "32px",
1013
+ color: "var(--status-error)",
1014
+ background: "rgba(248, 113, 113, 0.08)",
1015
+ border: "1px solid rgba(248, 113, 113, 0.25)",
1016
+ borderRadius: "8px",
1017
+ margin: "16px"
1018
+ },
1019
+ children: [
1020
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "Error loading content:" }),
1021
+ " ",
1022
+ error
1023
+ ]
1024
+ }
1025
+ );
1026
+ }
1027
+ const activeData = states.draft?.data ?? content?.data ?? {
1028
+ content: [],
1029
+ root: { props: {} }
1030
+ };
1031
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
1032
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: NAV_BAR_STYLE, children: [
1033
+ backButton,
1034
+ backButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "secondary", children: "/" }),
1035
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1036
+ import_flat_button2.default,
1037
+ {
1038
+ label: "Content Items",
1039
+ icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.AngleLeftIcon, {}),
1040
+ iconPosition: "left",
1041
+ onClick: () => navigate("/")
1042
+ }
1043
+ ),
1044
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { tone: "secondary", children: "/" }),
1045
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_text2.default.Body, { isBold: true, children: contentName })
1046
+ ] }),
1047
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck_editor2.ComponentSearchProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1048
+ import_puck3.Puck,
1049
+ {
1050
+ config: contentConfig,
1051
+ data: activeData,
1052
+ onChange: handleChange,
1053
+ onPublish: handlePublish,
1054
+ overrides: {
1055
+ headerActions: () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1056
+ ContentToolbar2,
1057
+ {
1058
+ saving,
1059
+ isDirty: hasUnsavedChanges,
1060
+ states,
1061
+ onSave: () => void handleSave(),
1062
+ onPublish: () => void handlePublish(activeData),
1063
+ onRevert: () => void handleRevert()
1064
+ }
1065
+ ),
1066
+ components: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck_editor2.ComponentsPanel, { children }),
1067
+ componentItem: ({ children, name }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck_editor2.ComponentItemFilter, { name, children })
1068
+ }
1069
+ }
1070
+ ) }) })
1071
+ ] });
1072
+ };
1073
+ var ContentManagerRouterInner = ({
1074
+ config,
1075
+ defaultContentType,
1076
+ backButton
1077
+ }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_router_dom.Routes, { children: [
1078
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1079
+ import_react_router_dom.Route,
1080
+ {
1081
+ path: "/",
1082
+ element: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ContentListRoute, { defaultContentType, backButton })
1083
+ }
1084
+ ),
1085
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1086
+ import_react_router_dom.Route,
1087
+ {
1088
+ path: "/:contentKey",
1089
+ element: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ContentEditorRoute, { config, backButton })
1090
+ }
1091
+ )
1092
+ ] });
1093
+ var ContentManagerRouter = ({
1094
+ parentUrl,
1095
+ baseURL,
1096
+ projectKey,
1097
+ businessUnitKey,
1098
+ jwtToken,
1099
+ config,
1100
+ defaultContentType,
1101
+ backButton
1102
+ }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1103
+ import_puck_api3.PuckApiProvider,
1104
+ {
1105
+ baseURL,
1106
+ projectKey,
1107
+ businessUnitKey,
1108
+ jwtToken,
1109
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_router_dom.BrowserRouter, { basename: parentUrl, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1110
+ ContentManagerRouterInner,
1111
+ {
1112
+ config,
1113
+ defaultContentType,
1114
+ backButton
1115
+ }
1116
+ ) })
1117
+ }
1118
+ );
1119
+ // Annotate the CommonJS export names for ESM import in node:
1120
+ 0 && (module.exports = {
1121
+ ContentEditor,
1122
+ ContentManager,
1123
+ ContentManagerRouter
1124
+ });
1125
+ //# sourceMappingURL=index.js.map