camox 0.26.0 → 0.28.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.
Files changed (30) hide show
  1. package/dist/core/components/lexical/InlineLexicalEditor.js +14 -11
  2. package/dist/core/components/lexical/SidebarLexicalEditor.js +10 -7
  3. package/dist/features/preview/CamoxPreview.d.ts +1 -0
  4. package/dist/features/preview/CamoxPreview.js +507 -147
  5. package/dist/features/preview/components/AssetLightbox.js +1 -1
  6. package/dist/features/preview/components/BlockActionsPopover.js +1 -1
  7. package/dist/features/preview/components/CreatePageModal.js +23 -8
  8. package/dist/features/preview/components/FieldToolbar.js +1 -1
  9. package/dist/features/preview/components/LinkFieldEditor.js +192 -204
  10. package/dist/features/preview/components/PageContentSheet.js +1 -1
  11. package/dist/features/preview/components/PageLocationFieldset.js +3 -4
  12. package/dist/features/preview/components/{EditPageModal.js → PageMetadataModal.js} +413 -229
  13. package/dist/features/preview/components/PageNicknameField.js +69 -0
  14. package/dist/features/preview/components/PagePicker.js +21 -84
  15. package/dist/features/preview/components/PageStatusBadge.js +97 -0
  16. package/dist/features/preview/components/PreviewPanel.js +111 -117
  17. package/dist/features/preview/components/PreviewToolbar.js +4 -4
  18. package/dist/features/preview/components/PublishDialog.js +1 -1
  19. package/dist/features/preview/components/UnlinkAssetButton.js +1 -1
  20. package/dist/features/routes/pageRoute.d.ts +3 -1
  21. package/dist/features/routes/pageRoute.js +34 -11
  22. package/dist/features/studio/components/EnvironmentMenu.js +1 -1
  23. package/dist/features/studio/components/ProjectMenu.js +1 -1
  24. package/dist/features/studio/components/UserButton.js +1 -1
  25. package/dist/lib/auth.js +43 -15
  26. package/dist/lib/queries.js +1 -0
  27. package/dist/lib/utils.js +1 -11
  28. package/dist/studio.css +1 -1
  29. package/package.json +4 -4
  30. package/skills/camox-cli/SKILL.md +79 -12
@@ -2,9 +2,9 @@ import { trackClientEvent } from "../../../lib/telemetry-client.js";
2
2
  import { previewStore } from "../previewStore.js";
3
3
  import { useProjectSlug } from "../../../lib/auth.js";
4
4
  import { blockQueries, layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
5
- import { formatPathSegment } from "../../../lib/utils.js";
6
5
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
7
6
  import { PageLocationFieldset } from "./PageLocationFieldset.js";
7
+ import { PageNicknameField } from "./PageNicknameField.js";
8
8
  import { UploadDropZone } from "../../content/components/UploadDropZone.js";
9
9
  import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
10
10
  import { ShikiMarkdown } from "./ShikiMarkdown.js";
@@ -26,55 +26,154 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
26
26
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@camox/ui/select";
27
27
  import { useForm } from "@tanstack/react-form";
28
28
 
29
- //#region src/features/preview/components/EditPageModal.tsx
30
- const EditPageModal = () => {
29
+ //#region src/features/preview/components/PageMetadataModal.tsx
30
+ const PageMetadataModal = () => {
31
31
  const $ = c(3);
32
- if ($[0] !== "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89") {
32
+ if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
33
33
  for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
34
- $[0] = "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89";
34
+ $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
35
35
  }
36
36
  const editingPageId = useSelector(previewStore, _temp);
37
37
  let t0;
38
38
  if ($[1] !== editingPageId) {
39
- t0 = /* @__PURE__ */ jsx(EditPageModalContent, { pageId: editingPageId });
39
+ t0 = /* @__PURE__ */ jsx(PageMetadataModalContent, { pageId: editingPageId });
40
40
  $[1] = editingPageId;
41
41
  $[2] = t0;
42
42
  } else t0 = $[2];
43
43
  return t0;
44
44
  };
45
- const EditPageModalContent = ({ pageId }) => {
45
+ const PageMetadataModalContent = (t0) => {
46
+ const $ = c(61);
47
+ if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
48
+ for (let $i = 0; $i < 61; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
49
+ $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
50
+ }
51
+ const { pageId } = t0;
46
52
  const projectSlug = useProjectSlug();
47
- const updatePage = useMutation(pageMutations.update());
48
- const setLayout = useMutation(pageMutations.setLayout());
49
- const setAiSeo = useMutation(pageMutations.setAiSeo());
50
- const setMetaTitle = useMutation(pageMutations.setMetaTitle());
51
- const setMetaDescription = useMutation(pageMutations.setMetaDescription());
52
- const { data: page } = useQuery({
53
- ...pageQueries.getById(pageId),
54
- enabled: pageId != null
55
- });
56
- const { data: project } = useQuery(projectQueries.getBySlug(projectSlug));
57
- const { data: pages } = useQuery({
58
- ...pageQueries.list(project?.id ?? 0),
59
- enabled: !!project
60
- });
61
- const { data: layouts } = useQuery({
62
- ...layoutQueries.list(project?.id ?? 0),
63
- enabled: !!project
64
- });
53
+ let t1;
54
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
55
+ t1 = pageMutations.update();
56
+ $[1] = t1;
57
+ } else t1 = $[1];
58
+ const updatePage = useMutation(t1);
59
+ let t2;
60
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
61
+ t2 = pageMutations.setLayout();
62
+ $[2] = t2;
63
+ } else t2 = $[2];
64
+ const setLayout = useMutation(t2);
65
+ let t3;
66
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
67
+ t3 = pageMutations.setAiSeo();
68
+ $[3] = t3;
69
+ } else t3 = $[3];
70
+ const setAiSeo = useMutation(t3);
71
+ let t4;
72
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
73
+ t4 = pageMutations.setMetaTitle();
74
+ $[4] = t4;
75
+ } else t4 = $[4];
76
+ const setMetaTitle = useMutation(t4);
77
+ let t5;
78
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
79
+ t5 = pageMutations.setMetaDescription();
80
+ $[5] = t5;
81
+ } else t5 = $[5];
82
+ const setMetaDescription = useMutation(t5);
83
+ let t6;
84
+ if ($[6] !== pageId) {
85
+ t6 = pageQueries.getById(pageId);
86
+ $[6] = pageId;
87
+ $[7] = t6;
88
+ } else t6 = $[7];
89
+ const t7 = pageId != null;
90
+ let t8;
91
+ if ($[8] !== t6 || $[9] !== t7) {
92
+ t8 = {
93
+ ...t6,
94
+ enabled: t7
95
+ };
96
+ $[8] = t6;
97
+ $[9] = t7;
98
+ $[10] = t8;
99
+ } else t8 = $[10];
100
+ const { data: page } = useQuery(t8);
101
+ let t9;
102
+ if ($[11] !== projectSlug) {
103
+ t9 = projectQueries.getBySlug(projectSlug);
104
+ $[11] = projectSlug;
105
+ $[12] = t9;
106
+ } else t9 = $[12];
107
+ const { data: project } = useQuery(t9);
108
+ let t10;
109
+ if ($[13] !== project?.id) {
110
+ t10 = pageQueries.list(project?.id ?? 0);
111
+ $[13] = project?.id;
112
+ $[14] = t10;
113
+ } else t10 = $[14];
114
+ const t11 = !!project;
115
+ let t12;
116
+ if ($[15] !== t10 || $[16] !== t11) {
117
+ t12 = {
118
+ ...t10,
119
+ enabled: t11
120
+ };
121
+ $[15] = t10;
122
+ $[16] = t11;
123
+ $[17] = t12;
124
+ } else t12 = $[17];
125
+ const { data: pages } = useQuery(t12);
126
+ let t13;
127
+ if ($[18] !== project?.id) {
128
+ t13 = layoutQueries.list(project?.id ?? 0);
129
+ $[18] = project?.id;
130
+ $[19] = t13;
131
+ } else t13 = $[19];
132
+ const t14 = !!project;
133
+ let t15;
134
+ if ($[20] !== t13 || $[21] !== t14) {
135
+ t15 = {
136
+ ...t13,
137
+ enabled: t14
138
+ };
139
+ $[20] = t13;
140
+ $[21] = t14;
141
+ $[22] = t15;
142
+ } else t15 = $[22];
143
+ const { data: layouts } = useQuery(t15);
65
144
  const camoxApp = useCamoxApp();
66
145
  const navigate = useNavigate();
146
+ const t16 = page?.nickname ?? "";
147
+ const t17 = page?.pathSegment ?? "";
148
+ const t18 = page?.parentPageId ?? void 0;
149
+ const t19 = page?.layoutId ?? 0;
150
+ let t20;
151
+ if ($[23] !== t16 || $[24] !== t17 || $[25] !== t18 || $[26] !== t19) {
152
+ t20 = {
153
+ nickname: t16,
154
+ pathSegment: t17,
155
+ parentPageId: t18,
156
+ layoutId: t19
157
+ };
158
+ $[23] = t16;
159
+ $[24] = t17;
160
+ $[25] = t18;
161
+ $[26] = t19;
162
+ $[27] = t20;
163
+ } else t20 = $[27];
67
164
  const form = useForm({
68
- defaultValues: {
69
- pathSegment: page?.pathSegment ?? "",
70
- parentPageId: page?.parentPageId ?? void 0,
71
- layoutId: page?.layoutId ?? 0
72
- },
165
+ defaultValues: t20,
73
166
  onSubmit: async (values) => {
74
167
  if (!page) return;
75
168
  try {
169
+ const nickname = values.value.nickname.trim();
170
+ if (!nickname) {
171
+ toast.error("Page nickname is required");
172
+ return;
173
+ }
76
174
  const { fullPath } = await updatePage.mutateAsync({
77
175
  id: page.id,
176
+ nickname,
78
177
  pathSegment: values.value.pathSegment,
79
178
  parentPageId: values.value.parentPageId
80
179
  });
@@ -85,217 +184,275 @@ const EditPageModalContent = ({ pageId }) => {
85
184
  trackClientEvent("page_updated", {
86
185
  projectId: page.projectId,
87
186
  changes: {
187
+ nickname: nickname !== page.nickname,
88
188
  path: values.value.pathSegment !== page.pathSegment,
89
189
  layout: values.value.layoutId !== page.layoutId,
90
190
  parent: values.value.parentPageId !== page.parentPageId
91
191
  }
92
192
  });
93
- const displayName = page.metaTitle ?? formatPathSegment(values.value.pathSegment);
193
+ const displayName = nickname;
94
194
  toast.success(`Updated ${displayName} page`);
95
195
  previewStore.send({ type: "closeEditPageModal" });
96
196
  form.reset();
97
197
  await navigate({ to: fullPath });
98
- } catch (error) {
99
- console.error("Failed to update page:", error);
198
+ } catch (t21) {
199
+ console.error("Failed to update page:", t21);
100
200
  toast.error("Could not update page");
101
201
  }
102
202
  }
103
203
  });
104
- const prevPageId = React.useRef(pageId);
105
- React.useEffect(() => {
106
- if (prevPageId.current === pageId || !page) return;
107
- prevPageId.current = pageId;
108
- form.reset({
109
- pathSegment: page.pathSegment,
110
- parentPageId: page.parentPageId ?? void 0,
111
- layoutId: page.layoutId ?? 0
112
- });
113
- }, [
114
- pageId,
115
- page,
116
- form
117
- ]);
204
+ const prevPageId = React.useRef(null);
205
+ let t22;
206
+ if ($[28] !== form || $[29] !== page || $[30] !== pageId) {
207
+ t22 = () => {
208
+ if (prevPageId.current === pageId || !page) return;
209
+ prevPageId.current = pageId;
210
+ form.reset({
211
+ nickname: page.nickname,
212
+ pathSegment: page.pathSegment,
213
+ parentPageId: page.parentPageId ?? void 0,
214
+ layoutId: page.layoutId ?? 0
215
+ });
216
+ };
217
+ $[28] = form;
218
+ $[29] = page;
219
+ $[30] = pageId;
220
+ $[31] = t22;
221
+ } else t22 = $[31];
222
+ let t23;
223
+ if ($[32] !== form || $[33] !== page || $[34] !== pageId) {
224
+ t23 = [
225
+ pageId,
226
+ page,
227
+ form
228
+ ];
229
+ $[32] = form;
230
+ $[33] = page;
231
+ $[34] = pageId;
232
+ $[35] = t23;
233
+ } else t23 = $[35];
234
+ React.useEffect(t22, t23);
118
235
  const isOpen = pageId != null && !!page;
119
236
  const isRootPage = page?.fullPath === "/";
120
- const pageLayoutRecord = layouts?.find((l) => l.id === page?.layoutId);
121
- const layoutDef = pageLayoutRecord ? camoxApp.getLayoutById(pageLayoutRecord.layoutId) : void 0;
122
- const metaTitle = layoutDef && page ? layoutDef._internal.buildMetaTitle({
123
- pageMetaTitle: page.metaTitle ?? "",
124
- projectName: project?.name ?? "",
125
- pageFullPath: page.fullPath
126
- }) : page?.metaTitle ?? "";
127
- return /* @__PURE__ */ jsx(Dialog, {
128
- open: isOpen,
129
- onOpenChange: (value) => {
130
- if (!value) previewStore.send({ type: "closeEditPageModal" });
131
- },
132
- children: /* @__PURE__ */ jsxs(DialogContent, {
133
- className: "flex max-h-[90vh] flex-col gap-0 overflow-hidden p-0 sm:max-w-5xl",
134
- children: [/* @__PURE__ */ jsxs(DialogHeader, {
135
- className: "border-border border-b p-4",
136
- children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Edit page" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Update the page details." })]
137
- }), page && /* @__PURE__ */ jsxs("div", {
138
- className: "flex-1 overflow-y-auto",
139
- children: [
140
- /* @__PURE__ */ jsxs("div", {
141
- className: "border-border grid grid-cols-[200px_1fr] gap-x-16 border-b px-4 py-4",
142
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
143
- className: "text-sm font-medium",
144
- children: "Page structure"
145
- }), /* @__PURE__ */ jsx("p", {
146
- className: "text-muted-foreground mt-1 text-xs",
147
- children: "URL path and layout used to render the page"
148
- })] }), /* @__PURE__ */ jsx("div", {
149
- className: "space-y-4",
150
- children: /* @__PURE__ */ jsxs("form", {
151
- onSubmit: (e) => {
152
- e.preventDefault();
153
- e.stopPropagation();
154
- form.handleSubmit();
155
- },
156
- className: "-mx-1 space-y-4 px-1",
157
- children: [
158
- isRootPage ? /* @__PURE__ */ jsxs(Alert, { children: [
159
- /* @__PURE__ */ jsx(Info, { className: "size-4" }),
160
- /* @__PURE__ */ jsx(AlertTitle, { children: "Homepage" }),
161
- /* @__PURE__ */ jsx(AlertDescription, { children: "You can't change the path of the home page." })
162
- ] }) : /* @__PURE__ */ jsx(form.Field, {
163
- name: "parentPageId",
164
- children: (parentField) => /* @__PURE__ */ jsx(form.Field, {
165
- name: "pathSegment",
166
- children: (pathField) => /* @__PURE__ */ jsx(PageLocationFieldset, {
167
- parentPageId: parentField.state.value,
168
- onParentPageIdChange: parentField.handleChange,
169
- pathSegment: pathField.state.value,
170
- onPathSegmentChange: pathField.handleChange,
171
- pages,
172
- excludePageId: page.id
173
- })
174
- })
175
- }),
176
- layouts && layouts.length > 0 && /* @__PURE__ */ jsx(form.Field, {
177
- name: "layoutId",
178
- children: (field) => /* @__PURE__ */ jsxs("div", {
179
- className: "space-y-2",
180
- children: [/* @__PURE__ */ jsx(Label, { children: "Layout" }), /* @__PURE__ */ jsxs(Select, {
181
- value: field.state.value ? String(field.state.value) : "",
182
- onValueChange: (value_0) => field.handleChange(Number(value_0)),
183
- items: layouts.map((t) => ({
184
- value: String(t.id),
185
- label: camoxApp.getLayoutById(t.layoutId)?._internal.title ?? t.layoutId
186
- })),
187
- children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a layout" }) }), /* @__PURE__ */ jsx(SelectContent, { children: layouts.map((t_0) => /* @__PURE__ */ jsx(SelectItem, {
188
- value: String(t_0.id),
189
- children: camoxApp.getLayoutById(t_0.layoutId)?._internal.title ?? t_0.layoutId
190
- }, t_0.id)) })]
191
- })]
192
- })
193
- }),
194
- /* @__PURE__ */ jsx(form.Subscribe, {
195
- selector: (s) => ({
196
- isSubmitting: s.isSubmitting,
197
- isPristine: s.isPristine
198
- }),
199
- children: ({ isSubmitting, isPristine }) => /* @__PURE__ */ jsxs(Button, {
200
- type: "submit",
201
- disabled: isSubmitting || isPristine,
202
- children: [
203
- isSubmitting && /* @__PURE__ */ jsx(Spinner, {}),
204
- "Save changes",
205
- isSubmitting && "..."
206
- ]
207
- })
208
- })
209
- ]
210
- })
211
- })]
212
- }),
213
- /* @__PURE__ */ jsxs("div", {
214
- className: "grid grid-cols-[200px_1fr] gap-x-16 px-4 py-4",
215
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
216
- className: "text-sm font-medium",
217
- children: "SEO data"
218
- }), /* @__PURE__ */ jsx("p", {
219
- className: "text-muted-foreground mt-1 text-xs",
220
- children: "How the page appears when shared across the web"
221
- })] }), /* @__PURE__ */ jsxs("div", {
222
- className: "space-y-4",
237
+ let pageLayoutRecord;
238
+ let t24;
239
+ if ($[36] !== camoxApp || $[37] !== layouts || $[38] !== page || $[39] !== project?.name) {
240
+ pageLayoutRecord = layouts?.find((l) => l.id === page?.layoutId);
241
+ const layoutDef = pageLayoutRecord ? camoxApp.getLayoutById(pageLayoutRecord.layoutId) : void 0;
242
+ t24 = layoutDef && page ? layoutDef._internal.buildMetaTitle({
243
+ pageMetaTitle: page.metaTitle ?? "",
244
+ projectName: project?.name ?? "",
245
+ pageFullPath: page.fullPath
246
+ }) : page?.metaTitle ?? "";
247
+ $[36] = camoxApp;
248
+ $[37] = layouts;
249
+ $[38] = page;
250
+ $[39] = project?.name;
251
+ $[40] = pageLayoutRecord;
252
+ $[41] = t24;
253
+ } else {
254
+ pageLayoutRecord = $[40];
255
+ t24 = $[41];
256
+ }
257
+ const metaTitle = t24;
258
+ let t25;
259
+ if ($[42] === Symbol.for("react.memo_cache_sentinel")) {
260
+ t25 = /* @__PURE__ */ jsxs(DialogHeader, {
261
+ className: "border-border border-b p-4",
262
+ children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Page metadata" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Update the page structure, SEO and markdown content." })]
263
+ });
264
+ $[42] = t25;
265
+ } else t25 = $[42];
266
+ let t26;
267
+ if ($[43] !== camoxApp || $[44] !== form || $[45] !== isRootPage || $[46] !== layouts || $[47] !== metaTitle || $[48] !== page || $[49] !== pageLayoutRecord?.layoutId || $[50] !== pages || $[51] !== project?.name || $[52] !== setAiSeo || $[53] !== setMetaDescription || $[54] !== setMetaTitle) {
268
+ t26 = page && /* @__PURE__ */ jsxs("div", {
269
+ className: "flex-1 overflow-y-auto",
270
+ children: [
271
+ /* @__PURE__ */ jsxs("div", {
272
+ className: "border-border grid grid-cols-[200px_1fr] gap-x-16 border-b px-4 py-4",
273
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
274
+ className: "text-sm font-medium",
275
+ children: "Page structure"
276
+ }), /* @__PURE__ */ jsx("p", {
277
+ className: "text-muted-foreground mt-1 text-xs",
278
+ children: "URL path and layout used to render the page"
279
+ })] }), /* @__PURE__ */ jsx("div", {
280
+ className: "space-y-4",
281
+ children: /* @__PURE__ */ jsxs("form", {
282
+ onSubmit: (e) => {
283
+ e.preventDefault();
284
+ e.stopPropagation();
285
+ form.handleSubmit();
286
+ },
287
+ className: "-mx-1 space-y-4 px-1",
223
288
  children: [
224
- /* @__PURE__ */ jsxs("div", {
225
- className: "flex items-center gap-2",
226
- children: [/* @__PURE__ */ jsx(Switch, {
227
- id: "ai-seo",
228
- checked: page.aiSeoEnabled !== false,
229
- onCheckedChange: (checked) => {
230
- setAiSeo.mutate({
231
- id: page.id,
232
- enabled: checked
233
- });
234
- trackClientEvent("ai_metadata_toggled", {
235
- target: "page",
236
- enabled: checked,
237
- pageId: page.id
238
- });
239
- }
240
- }), /* @__PURE__ */ jsx(Label, {
241
- htmlFor: "ai-seo",
242
- children: "AI metadata"
243
- })]
289
+ /* @__PURE__ */ jsx(form.Field, {
290
+ name: "nickname",
291
+ children: _temp3
244
292
  }),
245
- /* @__PURE__ */ jsx(DebouncedFieldEditor, {
246
- label: "Page title",
247
- placeholder: "Page title...",
248
- initialValue: page.metaTitle ?? "",
249
- disabled: page.aiSeoEnabled !== false,
250
- onSave: (value_1) => setMetaTitle.mutate({
251
- id: page.id,
252
- metaTitle: value_1
293
+ isRootPage ? /* @__PURE__ */ jsxs(Alert, { children: [
294
+ /* @__PURE__ */ jsx(Info, { className: "size-4" }),
295
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Homepage" }),
296
+ /* @__PURE__ */ jsx(AlertDescription, { children: "You can't change the path of the home page." })
297
+ ] }) : /* @__PURE__ */ jsx(form.Field, {
298
+ name: "parentPageId",
299
+ children: (parentField) => /* @__PURE__ */ jsx(form.Field, {
300
+ name: "pathSegment",
301
+ children: (pathField) => /* @__PURE__ */ jsx(PageLocationFieldset, {
302
+ parentPageId: parentField.state.value,
303
+ onParentPageIdChange: parentField.handleChange,
304
+ pathSegment: pathField.state.value,
305
+ onPathSegmentChange: pathField.handleChange,
306
+ pages,
307
+ excludePageId: page.id
308
+ })
253
309
  })
254
310
  }),
255
- /* @__PURE__ */ jsx(DebouncedFieldEditor, {
256
- label: "Page description",
257
- placeholder: "Page description...",
258
- initialValue: page.metaDescription ?? "",
259
- disabled: page.aiSeoEnabled !== false,
260
- rows: 2,
261
- onSave: (value_2) => setMetaDescription.mutate({
262
- id: page.id,
263
- metaDescription: value_2
311
+ layouts && layouts.length > 0 && /* @__PURE__ */ jsx(form.Field, {
312
+ name: "layoutId",
313
+ children: (field_0) => /* @__PURE__ */ jsxs("div", {
314
+ className: "space-y-2",
315
+ children: [/* @__PURE__ */ jsx(Label, { children: "Layout" }), /* @__PURE__ */ jsxs(Select, {
316
+ value: field_0.state.value ? String(field_0.state.value) : "",
317
+ onValueChange: (value_0) => field_0.handleChange(Number(value_0)),
318
+ items: layouts.map((t) => ({
319
+ value: String(t.id),
320
+ label: camoxApp.getLayoutById(t.layoutId)?._internal.title ?? t.layoutId
321
+ })),
322
+ children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a layout" }) }), /* @__PURE__ */ jsx(SelectContent, { children: layouts.map((t_0) => /* @__PURE__ */ jsx(SelectItem, {
323
+ value: String(t_0.id),
324
+ children: camoxApp.getLayoutById(t_0.layoutId)?._internal.title ?? t_0.layoutId
325
+ }, t_0.id)) })]
326
+ })]
264
327
  })
265
328
  }),
266
- /* @__PURE__ */ jsx(SearchEnginePreview, {
267
- page,
268
- metaTitle,
269
- metaDescription: page.metaDescription ?? ""
270
- }),
271
- /* @__PURE__ */ jsx(SocialPreviewSection, {
272
- page,
273
- metaTitle,
274
- metaDescription: page.metaDescription ?? "",
275
- layoutId: pageLayoutRecord?.layoutId,
276
- projectName: project?.name
329
+ /* @__PURE__ */ jsx(form.Subscribe, {
330
+ selector: _temp4,
331
+ children: _temp5
277
332
  })
278
333
  ]
279
- })]
280
- }),
281
- /* @__PURE__ */ jsxs("div", {
282
- className: "border-border grid grid-cols-[200px_1fr] gap-x-16 border-t px-4 py-4",
283
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
284
- className: "text-sm font-medium",
285
- children: "Markdown content"
286
- }), /* @__PURE__ */ jsx("p", {
287
- className: "text-muted-foreground mt-1 text-xs",
288
- children: "How your content will be served to AI agents"
289
- })] }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(PageMarkdownPreview, {
290
- pageId: page.id,
291
- metaTitle,
292
- metaDescription: page.metaDescription ?? ""
293
- }) })]
294
- })
295
- ]
296
- })]
297
- })
298
- });
334
+ })
335
+ })]
336
+ }),
337
+ /* @__PURE__ */ jsxs("div", {
338
+ className: "grid grid-cols-[200px_1fr] gap-x-16 px-4 py-4",
339
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
340
+ className: "text-sm font-medium",
341
+ children: "SEO data"
342
+ }), /* @__PURE__ */ jsx("p", {
343
+ className: "text-muted-foreground mt-1 text-xs",
344
+ children: "How the page appears when shared across the web"
345
+ })] }), /* @__PURE__ */ jsxs("div", {
346
+ className: "space-y-4",
347
+ children: [
348
+ /* @__PURE__ */ jsxs("div", {
349
+ className: "flex items-center gap-2",
350
+ children: [/* @__PURE__ */ jsx(Switch, {
351
+ id: "ai-seo",
352
+ checked: page.aiSeoEnabled !== false,
353
+ onCheckedChange: (checked) => {
354
+ setAiSeo.mutate({
355
+ id: page.id,
356
+ enabled: checked
357
+ });
358
+ trackClientEvent("ai_metadata_toggled", {
359
+ target: "page",
360
+ enabled: checked,
361
+ pageId: page.id
362
+ });
363
+ }
364
+ }), /* @__PURE__ */ jsx(Label, {
365
+ htmlFor: "ai-seo",
366
+ children: "AI metadata"
367
+ })]
368
+ }),
369
+ /* @__PURE__ */ jsx(DebouncedFieldEditor, {
370
+ label: "Page title",
371
+ placeholder: "Page title...",
372
+ initialValue: page.metaTitle ?? "",
373
+ disabled: page.aiSeoEnabled !== false,
374
+ onSave: (value_1) => setMetaTitle.mutate({
375
+ id: page.id,
376
+ metaTitle: value_1
377
+ })
378
+ }),
379
+ /* @__PURE__ */ jsx(DebouncedFieldEditor, {
380
+ label: "Page description",
381
+ placeholder: "Page description...",
382
+ initialValue: page.metaDescription ?? "",
383
+ disabled: page.aiSeoEnabled !== false,
384
+ rows: 2,
385
+ onSave: (value_2) => setMetaDescription.mutate({
386
+ id: page.id,
387
+ metaDescription: value_2
388
+ })
389
+ }),
390
+ /* @__PURE__ */ jsx(SearchEnginePreview, {
391
+ page,
392
+ metaTitle,
393
+ metaDescription: page.metaDescription ?? ""
394
+ }),
395
+ /* @__PURE__ */ jsx(SocialPreviewSection, {
396
+ page,
397
+ metaTitle,
398
+ metaDescription: page.metaDescription ?? "",
399
+ layoutId: pageLayoutRecord?.layoutId,
400
+ projectName: project?.name
401
+ })
402
+ ]
403
+ })]
404
+ }),
405
+ /* @__PURE__ */ jsxs("div", {
406
+ className: "border-border grid grid-cols-[200px_1fr] gap-x-16 border-t px-4 py-4",
407
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
408
+ className: "text-sm font-medium",
409
+ children: "Markdown content"
410
+ }), /* @__PURE__ */ jsx("p", {
411
+ className: "text-muted-foreground mt-1 text-xs",
412
+ children: "How your content will be served to AI agents"
413
+ })] }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(PageMarkdownPreview, {
414
+ pageId: page.id,
415
+ metaTitle,
416
+ metaDescription: page.metaDescription ?? ""
417
+ }) })]
418
+ })
419
+ ]
420
+ });
421
+ $[43] = camoxApp;
422
+ $[44] = form;
423
+ $[45] = isRootPage;
424
+ $[46] = layouts;
425
+ $[47] = metaTitle;
426
+ $[48] = page;
427
+ $[49] = pageLayoutRecord?.layoutId;
428
+ $[50] = pages;
429
+ $[51] = project?.name;
430
+ $[52] = setAiSeo;
431
+ $[53] = setMetaDescription;
432
+ $[54] = setMetaTitle;
433
+ $[55] = t26;
434
+ } else t26 = $[55];
435
+ let t27;
436
+ if ($[56] !== t26) {
437
+ t27 = /* @__PURE__ */ jsxs(DialogContent, {
438
+ className: "flex max-h-[90vh] flex-col gap-0 overflow-hidden p-0 sm:max-w-5xl",
439
+ children: [t25, t26]
440
+ });
441
+ $[56] = t26;
442
+ $[57] = t27;
443
+ } else t27 = $[57];
444
+ let t28;
445
+ if ($[58] !== isOpen || $[59] !== t27) {
446
+ t28 = /* @__PURE__ */ jsx(Dialog, {
447
+ open: isOpen,
448
+ onOpenChange: _temp2,
449
+ children: t27
450
+ });
451
+ $[58] = isOpen;
452
+ $[59] = t27;
453
+ $[60] = t28;
454
+ } else t28 = $[60];
455
+ return t28;
299
456
  };
300
457
  function truncateText(text, maxLen) {
301
458
  if (text.length <= maxLen) return text;
@@ -303,9 +460,9 @@ function truncateText(text, maxLen) {
303
460
  }
304
461
  const SearchEnginePreview = (t0) => {
305
462
  const $ = c(17);
306
- if ($[0] !== "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89") {
463
+ if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
307
464
  for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
308
- $[0] = "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89";
465
+ $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
309
466
  }
310
467
  const { page, metaTitle, metaDescription } = t0;
311
468
  const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
@@ -388,9 +545,9 @@ const SearchEnginePreview = (t0) => {
388
545
  };
389
546
  const SocialPreviewSection = (t0) => {
390
547
  const $ = c(60);
391
- if ($[0] !== "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89") {
548
+ if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
392
549
  for (let $i = 0; $i < 60; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
393
- $[0] = "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89";
550
+ $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
394
551
  }
395
552
  const { page, metaTitle, metaDescription, layoutId, projectName } = t0;
396
553
  const pageMetaTitle = page.metaTitle ?? page.pathSegment;
@@ -426,7 +583,7 @@ const SocialPreviewSection = (t0) => {
426
583
  queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
427
584
  trackClientEvent("page_custom_og_image_uploaded", { pageId: page.id });
428
585
  },
429
- onError: _temp5
586
+ onError: _temp6
430
587
  };
431
588
  $[7] = page.id;
432
589
  $[8] = queryClient;
@@ -446,7 +603,7 @@ const SocialPreviewSection = (t0) => {
446
603
  queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
447
604
  trackClientEvent("page_custom_og_image_removed", { pageId: page.id });
448
605
  },
449
- onError: _temp6
606
+ onError: _temp7
450
607
  };
451
608
  $[11] = page.id;
452
609
  $[12] = queryClient;
@@ -664,9 +821,9 @@ const SocialPreviewSection = (t0) => {
664
821
  };
665
822
  const PageMarkdownPreview = (t0) => {
666
823
  const $ = c(9);
667
- if ($[0] !== "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89") {
824
+ if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
668
825
  for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
669
- $[0] = "dfed49772fc493ebb158f0892caae2776e9f3903bcc54115d8f549c2a9beee89";
826
+ $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
670
827
  }
671
828
  const { pageId, metaTitle, metaDescription } = t0;
672
829
  let t1;
@@ -713,12 +870,39 @@ const PageMarkdownPreview = (t0) => {
713
870
  function _temp(state) {
714
871
  return state.context.editingPageId;
715
872
  }
716
- function _temp5(error) {
873
+ function _temp2(value) {
874
+ if (!value) previewStore.send({ type: "closeEditPageModal" });
875
+ }
876
+ function _temp3(field) {
877
+ return /* @__PURE__ */ jsx(PageNicknameField, {
878
+ value: field.state.value,
879
+ onChange: field.handleChange
880
+ });
881
+ }
882
+ function _temp4(s) {
883
+ return {
884
+ isSubmitting: s.isSubmitting,
885
+ isPristine: s.isPristine
886
+ };
887
+ }
888
+ function _temp5(t0) {
889
+ const { isSubmitting, isPristine } = t0;
890
+ return /* @__PURE__ */ jsxs(Button, {
891
+ type: "submit",
892
+ disabled: isSubmitting || isPristine,
893
+ children: [
894
+ isSubmitting && /* @__PURE__ */ jsx(Spinner, {}),
895
+ "Save changes",
896
+ isSubmitting && "..."
897
+ ]
898
+ });
899
+ }
900
+ function _temp6(error) {
717
901
  toast.error(error.message || "Could not upload image");
718
902
  }
719
- function _temp6() {
903
+ function _temp7() {
720
904
  toast.error("Could not remove image");
721
905
  }
722
906
 
723
907
  //#endregion
724
- export { EditPageModal };
908
+ export { PageMetadataModal };