@commercetools-demo/puck-page-manager 0.5.2 → 0.6.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 CHANGED
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
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
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/index.ts
@@ -65,42 +55,30 @@ var EnsureIntlProvider = ({ children }) => {
65
55
  );
66
56
  };
67
57
 
68
- // src/PageManager.tsx
69
- var import_data_table = __toESM(require("@commercetools-uikit/data-table"));
70
- var import_primary_button = __toESM(require("@commercetools-uikit/primary-button"));
71
- var import_secondary_button = __toESM(require("@commercetools-uikit/secondary-button"));
72
- var import_flat_button = __toESM(require("@commercetools-uikit/flat-button"));
73
- var import_card = __toESM(require("@commercetools-uikit/card"));
74
- var import_spacings = __toESM(require("@commercetools-uikit/spacings"));
75
- var import_text = __toESM(require("@commercetools-uikit/text"));
76
- var import_loading_spinner = __toESM(require("@commercetools-uikit/loading-spinner"));
77
- var import_text_input = __toESM(require("@commercetools-uikit/text-input"));
78
- var import_label = __toESM(require("@commercetools-uikit/label"));
79
- var import_icons = require("@commercetools-uikit/icons");
58
+ // src/EnsureNimbusProvider.tsx
59
+ var import_nimbus = require("@commercetools/nimbus");
80
60
  var import_jsx_runtime2 = require("react/jsx-runtime");
61
+ var EnsureNimbusProvider = ({
62
+ locale = "en",
63
+ children
64
+ }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_nimbus.NimbusProvider, { locale, children });
65
+
66
+ // src/PageManager.tsx
67
+ var import_nimbus2 = require("@commercetools/nimbus");
68
+ var import_nimbus_icons = require("@commercetools/nimbus-icons");
69
+ var import_jsx_runtime3 = require("react/jsx-runtime");
81
70
  var DEFAULT_CONFIG = {
82
71
  ...import_puck_editor.defaultPuckConfig,
83
72
  components: { ...import_puck_editor.defaultPuckConfig.components }
84
73
  };
74
+ var STATUS_BADGE = {
75
+ draft: { colorPalette: "warning", label: "Draft" },
76
+ published: { colorPalette: "positive", label: "Published" },
77
+ none: { colorPalette: "neutral", label: "No state" }
78
+ };
85
79
  var StatusBadge = ({ variant }) => {
86
- 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)" };
87
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
88
- "span",
89
- {
90
- style: {
91
- ...styles,
92
- display: "inline-flex",
93
- alignItems: "center",
94
- padding: "2px 8px",
95
- borderRadius: "var(--border-radius-20)",
96
- fontSize: "var(--font-size-10)",
97
- fontWeight: "var(--font-weight-600)",
98
- marginRight: "4px",
99
- whiteSpace: "nowrap"
100
- },
101
- children: variant === "published" ? "Published" : variant === "draft" ? "Draft" : "No state"
102
- }
103
- );
80
+ const meta = STATUS_BADGE[variant];
81
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Badge, { colorPalette: meta.colorPalette, size: "xs", children: meta.label });
104
82
  };
105
83
  var NAV_BAR_STYLE = {
106
84
  position: "sticky",
@@ -110,26 +88,23 @@ var NAV_BAR_STYLE = {
110
88
  gap: "12px",
111
89
  padding: "8px 16px",
112
90
  background: "var(--color-surface, #fff)",
113
- borderBottom: "1px solid var(--color-neutral-90)",
91
+ borderBottom: "1px solid var(--color-neutral-90, #e0e0e0)",
114
92
  zIndex: 200,
115
93
  flexShrink: 0
116
94
  };
117
- var COLUMNS = [
118
- { key: "name", label: "Name" },
119
- { key: "slug", label: "Slug" },
120
- { key: "status", label: "Status" },
121
- { key: "updatedAt", label: "Updated" },
122
- { key: "actions", label: "Actions", shouldIgnoreRowClick: true }
123
- ];
124
95
  var PageList = ({ backButton }) => {
125
96
  const history = (0, import_react_router_dom.useHistory)();
126
97
  const { pages, loading, error, createPage, deletePage, refresh } = (0, import_puck_api.usePuckPages)();
98
+ const { templates } = (0, import_puck_api.usePuckTemplates)("page");
127
99
  const [creating, setCreating] = (0, import_react2.useState)(false);
128
100
  const [newName, setNewName] = (0, import_react2.useState)("");
129
101
  const [newSlug, setNewSlug] = (0, import_react2.useState)("");
102
+ const [templateKey, setTemplateKey] = (0, import_react2.useState)("");
130
103
  const [formError, setFormError] = (0, import_react2.useState)("");
131
104
  const [submitting, setSubmitting] = (0, import_react2.useState)(false);
132
105
  const [deleting, setDeleting] = (0, import_react2.useState)(null);
106
+ const [pendingDelete, setPendingDelete] = (0, import_react2.useState)(null);
107
+ const [search, setSearch] = (0, import_react2.useState)("");
133
108
  const handleCreate = async () => {
134
109
  if (!newName.trim()) {
135
110
  setFormError("Name is required");
@@ -146,10 +121,15 @@ var PageList = ({ backButton }) => {
146
121
  name: newName.trim(),
147
122
  slug: newSlug.trim().startsWith("/") ? newSlug.trim() : `/${newSlug.trim()}`
148
123
  };
124
+ if (templateKey) {
125
+ const template = templates.find((t) => t.key === templateKey);
126
+ if (template) input.puckData = template.value.puckData;
127
+ }
149
128
  const created = await createPage(input);
150
129
  setCreating(false);
151
130
  setNewName("");
152
131
  setNewSlug("");
132
+ setTemplateKey("");
153
133
  history.push(`/${created.key}/edit`, { pageName: created.value.name });
154
134
  } catch (err) {
155
135
  setFormError(err.message);
@@ -158,206 +138,323 @@ var PageList = ({ backButton }) => {
158
138
  }
159
139
  };
160
140
  const handleDelete = async (page) => {
161
- if (!confirm(`Delete "${page.value.name}"? This cannot be undone.`)) return;
162
141
  setDeleting(page.key);
163
142
  try {
164
143
  await deletePage(page.key);
165
144
  await refresh();
145
+ setPendingDelete(null);
166
146
  } finally {
167
147
  setDeleting(null);
168
148
  }
169
149
  };
170
150
  if (loading) {
171
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "64px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_loading_spinner.default, {}) });
151
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: "64px", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.LoadingSpinner, {}) });
172
152
  }
173
153
  if (error) {
174
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "32px" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_text.default.Body, { tone: "negative", children: [
154
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: "32px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Text, { color: "critical.11", children: [
175
155
  "Error: ",
176
156
  error
177
157
  ] }) });
178
158
  }
179
- const rows = pages.map((p) => ({ ...p, id: p.key }));
180
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { maxWidth: "1200px", margin: "0 auto", padding: "32px 24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "l", children: [
181
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Inline, { justifyContent: "space-between", alignItems: "center", children: [
182
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Inline, { scale: "m", alignItems: "center", children: [
183
- backButton,
184
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Headline, { as: "h1", children: "Puck Pages" })
185
- ] }),
186
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
187
- import_primary_button.default,
159
+ const term = search.trim().toLowerCase();
160
+ const filteredPages = term ? pages.filter(
161
+ (p) => p.value.name.toLowerCase().includes(term) || p.value.slug.toLowerCase().includes(term)
162
+ ) : pages;
163
+ const rows = filteredPages.map((p) => ({ ...p, id: p.key }));
164
+ const columns = [
165
+ {
166
+ id: "name",
167
+ header: "Name",
168
+ accessor: (row) => row.value.name,
169
+ render: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { fontWeight: "bold", children: row.value.name })
170
+ },
171
+ {
172
+ id: "slug",
173
+ header: "Slug",
174
+ accessor: (row) => row.value.slug,
175
+ render: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
176
+ "code",
188
177
  {
189
- label: "New Page",
190
- iconLeft: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.PlusThinIcon, {}),
191
- onClick: () => setCreating(true)
178
+ style: {
179
+ background: "#f4f4f4",
180
+ padding: "2px 6px",
181
+ borderRadius: "4px",
182
+ fontSize: "11px",
183
+ fontFamily: "monospace"
184
+ },
185
+ children: row.value.slug
192
186
  }
193
187
  )
194
- ] }),
195
- creating && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_card.default, { insetScale: "l", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "m", children: [
196
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Subheadline, { as: "h4", isBold: true, children: "Create New Page" }),
197
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Inline, { scale: "m", children: [
198
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
199
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_label.default, { htmlFor: "new-page-name", children: "Name *" }),
200
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
201
- import_text_input.default,
202
- {
203
- id: "new-page-name",
204
- value: newName,
205
- onChange: (e) => setNewName(e.target.value),
206
- placeholder: "Home Page"
207
- }
208
- )
209
- ] }) }),
210
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
211
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_label.default, { htmlFor: "new-page-slug", children: "Slug *" }),
212
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
213
- import_text_input.default,
214
- {
215
- id: "new-page-slug",
216
- value: newSlug,
217
- onChange: (e) => setNewSlug(e.target.value),
218
- placeholder: "/home"
219
- }
220
- )
221
- ] }) })
222
- ] }),
223
- formError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "negative", children: formError }),
224
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Inline, { scale: "s", children: [
225
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
226
- import_primary_button.default,
188
+ },
189
+ {
190
+ id: "status",
191
+ header: "Status",
192
+ accessor: () => "",
193
+ isSortable: false,
194
+ render: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", gap: "100", wrap: "wrap", children: [
195
+ row.states.draft && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { variant: "draft" }),
196
+ row.states.published && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { variant: "published" }),
197
+ !row.states.draft && !row.states.published && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { variant: "none" })
198
+ ] })
199
+ },
200
+ {
201
+ id: "updatedAt",
202
+ header: "Updated",
203
+ accessor: (row) => row.value.updatedAt,
204
+ render: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { fontSize: "xs", color: "neutral.11", children: new Date(row.value.updatedAt).toLocaleString() })
205
+ },
206
+ {
207
+ id: "actions",
208
+ header: "Actions",
209
+ accessor: () => "",
210
+ isSortable: false,
211
+ render: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", gap: "100", alignItems: "center", children: [
212
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
213
+ import_nimbus2.IconButton,
227
214
  {
228
- label: submitting ? "Creating\u2026" : "Create",
229
- onClick: () => void handleCreate(),
230
- isDisabled: submitting
215
+ "aria-label": `Edit ${row.value.name}`,
216
+ variant: "ghost",
217
+ size: "xs",
218
+ onPress: () => history.push(`/${row.key}/edit`, { pageName: row.value.name }),
219
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus_icons.Edit, {})
231
220
  }
232
221
  ),
233
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
234
- import_secondary_button.default,
222
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
223
+ import_nimbus2.IconButton,
235
224
  {
236
- label: "Cancel",
237
- onClick: () => {
238
- setCreating(false);
239
- setFormError("");
240
- }
225
+ "aria-label": `Preview ${row.value.name}`,
226
+ variant: "ghost",
227
+ size: "xs",
228
+ onPress: () => history.push(`/${row.key}/preview`, { pageName: row.value.name }),
229
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus_icons.Visibility, {})
230
+ }
231
+ ),
232
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
233
+ import_nimbus2.IconButton,
234
+ {
235
+ "aria-label": `Delete ${row.value.name}`,
236
+ variant: "ghost",
237
+ colorPalette: "critical",
238
+ size: "xs",
239
+ isDisabled: deleting === row.key,
240
+ onPress: () => setPendingDelete(row),
241
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus_icons.Delete, {})
241
242
  }
242
243
  )
243
244
  ] })
244
- ] }) }),
245
- pages.length === 0 && !creating ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "m", alignItems: "center", children: [
246
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: "No pages yet." }),
247
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
248
- import_primary_button.default,
249
- {
250
- label: "Create first page",
251
- iconLeft: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.PlusThinIcon, {}),
252
- onClick: () => setCreating(true)
253
- }
254
- )
255
- ] }) : pages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
256
- import_data_table.default,
257
- {
258
- columns: COLUMNS,
259
- rows,
260
- itemRenderer: (row, column) => {
261
- switch (column.key) {
262
- case "name":
263
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_spacings.default.Stack, { scale: "xs", children: [
264
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { isBold: true, children: row.value.name }),
265
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Detail, { tone: "secondary", children: row.key })
266
- ] });
267
- case "slug":
268
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
269
- "code",
270
- {
271
- style: {
272
- background: "var(--color-neutral-95)",
273
- padding: "2px 6px",
274
- borderRadius: "var(--border-radius-4)",
275
- fontSize: "var(--font-size-10)",
276
- fontFamily: "monospace"
277
- },
278
- children: row.value.slug
279
- }
280
- );
281
- case "status":
282
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
283
- row.states.draft && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge, { variant: "draft" }),
284
- row.states.published && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge, { variant: "published" }),
285
- !row.states.draft && !row.states.published && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusBadge, { variant: "none" })
286
- ] });
287
- case "updatedAt":
288
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: new Date(row.value.updatedAt).toLocaleString() });
289
- case "actions":
290
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
291
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
292
- import_primary_button.default,
293
- {
294
- label: "Edit",
295
- size: "20",
296
- onClick: () => history.push(`/${row.key}/edit`, { pageName: row.value.name })
297
- }
298
- ),
299
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
300
- import_secondary_button.default,
301
- {
302
- label: "Preview",
303
- size: "20",
304
- onClick: () => history.push(`/${row.key}/preview`, { pageName: row.value.name })
305
- }
306
- ),
307
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
308
- import_flat_button.default,
309
- {
310
- tone: "critical",
311
- label: deleting === row.key ? "\u2026" : "Delete",
312
- isDisabled: deleting === row.key,
313
- onClick: () => void handleDelete(row)
314
- }
315
- )
316
- ] });
317
- default:
318
- return null;
245
+ }
246
+ ];
247
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { maxWidth: "1200px", margin: "0 auto", padding: "32px 24px" }, children: [
248
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "column", gap: "600", children: [
249
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [
250
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", gap: "400", alignItems: "center", children: [
251
+ backButton,
252
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { as: "h1", fontSize: "2xl", fontWeight: "700", children: "Pages" })
253
+ ] }),
254
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Button, { variant: "solid", onPress: () => setCreating(true), children: [
255
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Icon, { as: import_nimbus_icons.Add }),
256
+ " New Page"
257
+ ] })
258
+ ] }),
259
+ creating && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Card.Root, { variant: "outlined", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Card.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "column", gap: "400", children: [
260
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { as: "h4", fontSize: "xl", fontWeight: "700", children: "Create New Page" }),
261
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", gap: "400", children: [
262
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.FormField.Root, { isRequired: true, children: [
263
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Label, { children: "Name" }),
264
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Input, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
265
+ import_nimbus2.TextInput,
266
+ {
267
+ value: newName,
268
+ onChange: (v) => setNewName(v),
269
+ placeholder: "Home Page"
270
+ }
271
+ ) })
272
+ ] }) }),
273
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.FormField.Root, { isRequired: true, children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Label, { children: "Slug" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Input, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
276
+ import_nimbus2.TextInput,
277
+ {
278
+ value: newSlug,
279
+ onChange: (v) => setNewSlug(v),
280
+ placeholder: "/home"
281
+ }
282
+ ) })
283
+ ] }) })
284
+ ] }),
285
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.FormField.Root, { children: [
286
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Label, { children: "Template" }),
287
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.FormField.Input, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
288
+ import_nimbus2.Select.Root,
289
+ {
290
+ "aria-label": "Template",
291
+ selectedKey: templateKey || "empty",
292
+ onSelectionChange: (key) => setTemplateKey(key == null || key === "empty" ? "" : String(key)),
293
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Select.Options, { children: [
294
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Select.Option, { id: "empty", children: "Empty" }),
295
+ templates.map((t) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Select.Option, { id: t.key, children: t.value.name }, t.key))
296
+ ] })
297
+ }
298
+ ) })
299
+ ] }),
300
+ formError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "critical.11", children: formError }),
301
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "row", gap: "200", children: [
302
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Button, { variant: "solid", onPress: () => void handleCreate(), isDisabled: submitting, children: submitting ? "Creating\u2026" : "Create" }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
304
+ import_nimbus2.Button,
305
+ {
306
+ variant: "outline",
307
+ onPress: () => {
308
+ setCreating(false);
309
+ setFormError("");
310
+ },
311
+ children: "Cancel"
312
+ }
313
+ )
314
+ ] })
315
+ ] }) }) }),
316
+ pages.length === 0 && !creating ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "column", gap: "400", alignItems: "center", children: [
317
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "neutral.11", children: "No pages yet." }),
318
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Button, { variant: "solid", onPress: () => setCreating(true), children: [
319
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Icon, { as: import_nimbus_icons.Add }),
320
+ " Create first page"
321
+ ] })
322
+ ] }) : pages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Stack, { direction: "column", gap: "400", children: [
323
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { maxWidth: 360 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
324
+ import_nimbus2.TextInput,
325
+ {
326
+ "aria-label": "Search pages",
327
+ placeholder: "Search by name or path\u2026",
328
+ value: search,
329
+ onChange: (v) => setSearch(v),
330
+ width: "100%",
331
+ trailingElement: search !== "" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
332
+ import_nimbus2.IconButton,
333
+ {
334
+ "aria-label": "Clear search",
335
+ variant: "ghost",
336
+ colorPalette: "neutral",
337
+ size: "2xs",
338
+ onPress: () => setSearch(""),
339
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus_icons.Close, {})
340
+ }
341
+ ) : void 0
319
342
  }
320
- }
343
+ ) }),
344
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "puck-page-list", children: [
345
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: `
346
+ .puck-page-list .pin-rows-column-header,
347
+ .puck-page-list [data-slot="pin-row-cell"] { display: none !important; }
348
+ ` }),
349
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.DataTable, { columns, rows, "aria-label": "Pages" })
350
+ ] })
351
+ ] }) : null
352
+ ] }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
354
+ import_nimbus2.Dialog.Root,
355
+ {
356
+ isOpen: pendingDelete !== null,
357
+ onOpenChange: (open) => {
358
+ if (!open) setPendingDelete(null);
359
+ },
360
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Dialog.Content, { children: [
361
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Dialog.Header, { children: [
362
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Dialog.Title, { children: "Delete page?" }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Dialog.CloseTrigger, {})
364
+ ] }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Text, { children: [
366
+ "Are you sure you want to delete",
367
+ " ",
368
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { as: "span", fontWeight: "700", children: pendingDelete?.value.name }),
369
+ "? This cannot be undone."
370
+ ] }) }),
371
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Dialog.Footer, { children: [
372
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Button, { slot: "close", variant: "outline", isDisabled: deleting !== null, children: "Cancel" }),
373
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
374
+ import_nimbus2.Button,
375
+ {
376
+ colorPalette: "critical",
377
+ isDisabled: deleting !== null,
378
+ onPress: () => {
379
+ if (pendingDelete) void handleDelete(pendingDelete);
380
+ },
381
+ children: deleting !== null ? "Deleting\u2026" : "Delete"
382
+ }
383
+ )
384
+ ] })
385
+ ] })
321
386
  }
322
- ) : null
323
- ] }) });
387
+ )
388
+ ] });
324
389
  };
325
390
  var PageEditorRoute = ({ config, backButton }) => {
326
391
  const { pageKey } = (0, import_react_router_dom.useParams)();
327
392
  const history = (0, import_react_router_dom.useHistory)();
328
393
  const location = (0, import_react_router_dom.useLocation)();
329
- const { baseURL, projectKey, businessUnitKey, jwtToken } = (0, import_puck_api.usePuckApiContext)();
394
+ const { baseURL, projectKey, businessUnitKey, jwtToken, locale } = (0, import_puck_api.usePuckApiContext)();
330
395
  const pageName = location.state?.pageName ?? pageKey ?? "Page";
331
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
332
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: NAV_BAR_STYLE, children: [
396
+ const [isDirty, setIsDirty] = (0, import_react2.useState)(false);
397
+ const [pendingNav, setPendingNav] = (0, import_react2.useState)(null);
398
+ const guardedNavigate = (0, import_react2.useCallback)(
399
+ (navFn) => {
400
+ if (isDirty) {
401
+ setPendingNav(() => navFn);
402
+ } else {
403
+ navFn();
404
+ }
405
+ },
406
+ [isDirty]
407
+ );
408
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
409
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: NAV_BAR_STYLE, children: [
333
410
  backButton,
334
- backButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
335
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
336
- import_flat_button.default,
411
+ backButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "neutral.11", children: "/" }),
412
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
413
+ import_nimbus2.Button,
337
414
  {
338
- label: "Pages",
339
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.AngleLeftIcon, {}),
340
- iconPosition: "left",
341
- onClick: () => history.push("/")
415
+ variant: "ghost",
416
+ onPress: () => guardedNavigate(() => history.push("/")),
417
+ children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Icon, { as: import_nimbus_icons.ChevronLeft }),
419
+ " Pages"
420
+ ]
342
421
  }
343
422
  ),
344
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
345
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { isBold: true, children: pageName })
423
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "neutral.11", children: "/" }),
424
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { fontWeight: "bold", children: pageName })
346
425
  ] }),
347
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
348
- import_puck_editor.PuckEditor,
349
- {
350
- baseURL,
351
- projectKey,
352
- businessUnitKey,
353
- jwtToken: jwtToken ?? "",
354
- pageKey,
355
- config,
356
- onError: (err) => {
357
- console.error("[PageManager] editor error:", err);
426
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "puck-editor-fill", style: { flex: 1, overflow: "hidden" }, children: [
427
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
428
+ import_puck_editor.PuckEditor,
429
+ {
430
+ baseURL,
431
+ projectKey,
432
+ businessUnitKey,
433
+ jwtToken: jwtToken ?? "",
434
+ locale,
435
+ pageKey,
436
+ config,
437
+ onDirtyChange: setIsDirty,
438
+ onPreview: () => guardedNavigate(
439
+ () => history.push(`/${pageKey}/preview`, { pageName })
440
+ ),
441
+ onError: (err) => {
442
+ console.error("[PageManager] editor error:", err);
443
+ }
358
444
  }
445
+ ),
446
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck_editor.PropertiesResizer, {})
447
+ ] }),
448
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
449
+ import_puck_editor.UnsavedChangesDialog,
450
+ {
451
+ isOpen: pendingNav !== null,
452
+ onOpenChange: (open) => {
453
+ if (!open) setPendingNav(null);
454
+ },
455
+ onConfirm: () => pendingNav?.()
359
456
  }
360
- ) })
457
+ )
361
458
  ] });
362
459
  };
363
460
  var PagePreviewRoute = ({ config, backButton }) => {
@@ -365,56 +462,39 @@ var PagePreviewRoute = ({ config, backButton }) => {
365
462
  const history = (0, import_react_router_dom.useHistory)();
366
463
  const location = (0, import_react_router_dom.useLocation)();
367
464
  const pageName = location.state?.pageName ?? pageKey ?? "Page";
368
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
369
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: NAV_BAR_STYLE, children: [
465
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
466
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: NAV_BAR_STYLE, children: [
370
467
  backButton,
371
- backButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
372
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
373
- import_flat_button.default,
374
- {
375
- label: "Pages",
376
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.AngleLeftIcon, {}),
377
- iconPosition: "left",
378
- onClick: () => history.push("/")
379
- }
380
- ),
381
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { tone: "secondary", children: "/" }),
382
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_text.default.Body, { isBold: true, children: pageName }),
383
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
384
- "span",
385
- {
386
- style: {
387
- background: "var(--color-primary-95)",
388
- color: "var(--color-primary-25)",
389
- border: "1px solid var(--color-primary-85)",
390
- display: "inline-flex",
391
- alignItems: "center",
392
- padding: "2px 10px",
393
- borderRadius: "var(--border-radius-20)",
394
- fontSize: "var(--font-size-10)",
395
- fontWeight: "var(--font-weight-600)"
396
- },
397
- children: "Preview"
398
- }
399
- )
468
+ backButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "neutral.11", children: "/" }),
469
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Button, { variant: "ghost", onPress: () => history.push("/"), children: [
470
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Icon, { as: import_nimbus_icons.ChevronLeft }),
471
+ " Pages"
472
+ ] }),
473
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { color: "neutral.11", children: "/" }),
474
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Text, { fontWeight: "bold", children: pageName }),
475
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Badge, { colorPalette: "primary", size: "xs", children: "Preview" }),
476
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginLeft: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_nimbus2.Button, { variant: "outline", size: "xs", onPress: () => history.goBack(), children: [
477
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_nimbus2.Icon, { as: import_nimbus_icons.Close }),
478
+ " Close preview"
479
+ ] }) })
400
480
  ] }),
401
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_puck_renderer.PuckRenderer, { pageKey, mode: "preview", config })
481
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_puck_renderer.PuckRenderer, { pageKey, mode: "preview", config })
402
482
  ] });
403
483
  };
404
- var PageManagerInner = ({ config, backButton }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_router_dom.Switch, { children: [
405
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom.Route, { exact: true, path: "/", render: () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PageList, { backButton }) }),
406
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
484
+ var PageManagerInner = ({ config, backButton }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_router_dom.Switch, { children: [
485
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_router_dom.Route, { exact: true, path: "/", render: () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PageList, { backButton }) }),
486
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
407
487
  import_react_router_dom.Route,
408
488
  {
409
489
  path: "/:pageKey/edit",
410
- render: () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PageEditorRoute, { config, backButton })
490
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PageEditorRoute, { config, backButton })
411
491
  }
412
492
  ),
413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
493
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
414
494
  import_react_router_dom.Route,
415
495
  {
416
496
  path: "/:pageKey/preview",
417
- render: () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PagePreviewRoute, { config, backButton })
497
+ render: () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PagePreviewRoute, { config, backButton })
418
498
  }
419
499
  )
420
500
  ] });
@@ -424,18 +504,20 @@ var PageManager = ({
424
504
  projectKey,
425
505
  businessUnitKey,
426
506
  jwtToken,
507
+ locale,
427
508
  config = DEFAULT_CONFIG,
428
509
  backButton
429
- }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EnsureIntlProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
510
+ }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EnsureNimbusProvider, { locale, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EnsureIntlProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
430
511
  import_puck_api.PuckApiProvider,
431
512
  {
432
513
  baseURL,
433
514
  projectKey,
434
515
  businessUnitKey,
435
516
  jwtToken,
436
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_router_dom.BrowserRouter, { basename: parentUrl, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PageManagerInner, { config, backButton }) })
517
+ locale,
518
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_router_dom.BrowserRouter, { basename: parentUrl, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PageManagerInner, { config, backButton }) })
437
519
  }
438
- ) });
520
+ ) }) });
439
521
  // Annotate the CommonJS export names for ESM import in node:
440
522
  0 && (module.exports = {
441
523
  PageManager