camox 0.32.0 → 0.33.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 (58) hide show
  1. package/dist/core/createBlock.d.ts +1 -1
  2. package/dist/core/createBlock.js +88 -108
  3. package/dist/core/hooks/useIsEditable.js +6 -10
  4. package/dist/core/lib/fieldTypes.js +10 -219
  5. package/dist/features/agent-chat/components/AgentChatSidebar.js +172 -0
  6. package/dist/features/agent-chat/components/AgentChatThread.js +9 -9
  7. package/dist/features/preview/CamoxPreview.js +137 -729
  8. package/dist/features/preview/components/{AddBlockSheet.js → AddBlockSidebar.js} +121 -131
  9. package/dist/features/preview/components/AssetFieldEditor.js +107 -82
  10. package/dist/features/preview/components/AssetLightbox.js +4 -4
  11. package/dist/features/preview/components/AssetPickerModal.js +277 -0
  12. package/dist/features/preview/components/BlockActionsPopover.js +18 -24
  13. package/dist/features/preview/components/CreatePageModal.js +6 -6
  14. package/dist/features/preview/components/FieldToolbar.js +64 -127
  15. package/dist/features/preview/components/ItemFieldsEditor.js +98 -125
  16. package/dist/features/preview/components/LeftSidebar.js +64 -0
  17. package/dist/features/preview/components/LinkFieldEditor.js +1 -1
  18. package/dist/features/preview/components/MultipleAssetFieldEditor.js +94 -56
  19. package/dist/features/preview/components/OverlayTracker.js +15 -15
  20. package/dist/features/preview/components/Overlays.js +12 -12
  21. package/dist/features/preview/components/PageEditorSidebar.js +563 -0
  22. package/dist/features/preview/components/PageInfoSidebar.js +1453 -0
  23. package/dist/features/preview/components/PageNavigatorSidebar.js +590 -0
  24. package/dist/features/preview/components/PagePicker.js +3 -3
  25. package/dist/features/preview/components/PageStatusBadge.js +1 -1
  26. package/dist/features/preview/components/PageTree.js +204 -564
  27. package/dist/features/preview/components/PreviewPanel.js +123 -158
  28. package/dist/features/preview/components/PreviewToolbar.js +260 -256
  29. package/dist/features/preview/components/PublishDialog.js +2 -2
  30. package/dist/features/preview/components/RepeatableItemsList.js +2 -2
  31. package/dist/features/preview/components/RightSidebar.js +109 -0
  32. package/dist/features/preview/components/UnlinkAssetButton.js +2 -2
  33. package/dist/features/preview/components/useRepeatableItemActions.js +3 -138
  34. package/dist/features/preview/components/useUpdateBlockPosition.js +1 -1
  35. package/dist/features/preview/previewQueryFns.js +23 -0
  36. package/dist/features/preview/previewStore.js +46 -63
  37. package/dist/features/provider/CamoxProvider.js +255 -70
  38. package/dist/features/provider/useAdminShortcuts.js +5 -48
  39. package/dist/features/routes/pageRoute.js +1 -1
  40. package/dist/features/studio/CamoxStudio.js +6 -5
  41. package/dist/features/studio/components/EnvironmentMenu.js +2 -2
  42. package/dist/features/studio/components/Navbar.js +53 -71
  43. package/dist/features/studio/components/ProjectMenu.js +1 -1
  44. package/dist/features/studio/components/UserButton.js +1 -1
  45. package/dist/features/studio/routes.js +7 -0
  46. package/dist/features/studio/useTheme.js +67 -33
  47. package/dist/features/vite/routeGeneration.js +68 -66
  48. package/dist/hooks/use-file-upload.js +1 -1
  49. package/dist/lib/auth.js +23 -22
  50. package/dist/lib/utils.js +1 -1
  51. package/dist/studio-overlays.css +1 -1
  52. package/dist/studio.css +1 -1
  53. package/package.json +4 -4
  54. package/dist/features/agent-chat/components/AgentChatSheet.js +0 -207
  55. package/dist/features/preview/components/AssetPickerGrid.js +0 -236
  56. package/dist/features/preview/components/PageContentSheet.js +0 -608
  57. package/dist/features/preview/components/PageMetadataModal.js +0 -908
  58. package/dist/features/preview/components/PreviewSideSheet.js +0 -76
@@ -0,0 +1,1453 @@
1
+ import { useProjectSlug } from "../../../lib/auth.js";
2
+ import { blockQueries, layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
3
+ import { trackClientEvent } from "../../../lib/telemetry-client.js";
4
+ import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
5
+ import { PageLocationFieldset } from "./PageLocationFieldset.js";
6
+ import { PageNicknameField } from "./PageNicknameField.js";
7
+ import { UploadDropZone } from "../../content/components/UploadDropZone.js";
8
+ import { useDebouncedField } from "../../../hooks/use-debounced-field.js";
9
+ import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
10
+ import { ShikiMarkdown } from "./ShikiMarkdown.js";
11
+ import { c } from "react/compiler-runtime";
12
+ import { Input } from "@camox/ui/input";
13
+ import { Label } from "@camox/ui/label";
14
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
15
+ import { useNavigate } from "@tanstack/react-router";
16
+ import * as React from "react";
17
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
18
+ import { toast } from "@camox/ui/toaster";
19
+ import { Button } from "@camox/ui/button";
20
+ import { Globe, Info, Pencil, Trash2, Upload } from "lucide-react";
21
+ import { Alert, AlertDescription, AlertTitle } from "@camox/ui/alert";
22
+ import { Spinner } from "@camox/ui/spinner";
23
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@camox/ui/dialog";
24
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@camox/ui/select";
25
+ import { useForm } from "@tanstack/react-form";
26
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText } from "@camox/ui/input-group";
27
+ import { Switch } from "@camox/ui/switch";
28
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@camox/ui/tooltip";
29
+
30
+ //#region src/features/preview/components/PageInfoSidebar.tsx
31
+ const usePageMetadataData = (pageId) => {
32
+ const $ = c(29);
33
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
34
+ for (let $i = 0; $i < 29; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
35
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
36
+ }
37
+ const projectSlug = useProjectSlug();
38
+ const camoxApp = useCamoxApp();
39
+ let t0;
40
+ if ($[1] !== pageId) {
41
+ t0 = pageQueries.getById(pageId);
42
+ $[1] = pageId;
43
+ $[2] = t0;
44
+ } else t0 = $[2];
45
+ const { data: page } = useQuery(t0);
46
+ let t1;
47
+ if ($[3] !== projectSlug) {
48
+ t1 = projectQueries.getBySlug(projectSlug);
49
+ $[3] = projectSlug;
50
+ $[4] = t1;
51
+ } else t1 = $[4];
52
+ const { data: project } = useQuery(t1);
53
+ let t2;
54
+ if ($[5] !== project?.id) {
55
+ t2 = pageQueries.list(project?.id ?? 0);
56
+ $[5] = project?.id;
57
+ $[6] = t2;
58
+ } else t2 = $[6];
59
+ const t3 = !!project;
60
+ let t4;
61
+ if ($[7] !== t2 || $[8] !== t3) {
62
+ t4 = {
63
+ ...t2,
64
+ enabled: t3
65
+ };
66
+ $[7] = t2;
67
+ $[8] = t3;
68
+ $[9] = t4;
69
+ } else t4 = $[9];
70
+ const { data: pages } = useQuery(t4);
71
+ let t5;
72
+ if ($[10] !== project?.id) {
73
+ t5 = layoutQueries.list(project?.id ?? 0);
74
+ $[10] = project?.id;
75
+ $[11] = t5;
76
+ } else t5 = $[11];
77
+ const t6 = !!project;
78
+ let t7;
79
+ if ($[12] !== t5 || $[13] !== t6) {
80
+ t7 = {
81
+ ...t5,
82
+ enabled: t6
83
+ };
84
+ $[12] = t5;
85
+ $[13] = t6;
86
+ $[14] = t7;
87
+ } else t7 = $[14];
88
+ const { data: layouts } = useQuery(t7);
89
+ let pageLayoutRecord;
90
+ let t8;
91
+ if ($[15] !== camoxApp || $[16] !== layouts || $[17] !== page || $[18] !== project?.name) {
92
+ pageLayoutRecord = layouts?.find((l) => l.id === page?.layoutId);
93
+ const layoutDef = pageLayoutRecord ? camoxApp.getLayoutById(pageLayoutRecord.layoutId) : void 0;
94
+ t8 = layoutDef && page ? layoutDef._internal.buildMetaTitle({
95
+ pageMetaTitle: page.metaTitle ?? "",
96
+ projectName: project?.name ?? "",
97
+ pageFullPath: page.fullPath
98
+ }) : page?.metaTitle ?? "";
99
+ $[15] = camoxApp;
100
+ $[16] = layouts;
101
+ $[17] = page;
102
+ $[18] = project?.name;
103
+ $[19] = pageLayoutRecord;
104
+ $[20] = t8;
105
+ } else {
106
+ pageLayoutRecord = $[19];
107
+ t8 = $[20];
108
+ }
109
+ const metaTitle = t8;
110
+ let t9;
111
+ if ($[21] !== camoxApp || $[22] !== layouts || $[23] !== metaTitle || $[24] !== page || $[25] !== pageLayoutRecord || $[26] !== pages || $[27] !== project) {
112
+ t9 = {
113
+ page,
114
+ project,
115
+ pages,
116
+ layouts,
117
+ pageLayoutRecord,
118
+ metaTitle,
119
+ camoxApp
120
+ };
121
+ $[21] = camoxApp;
122
+ $[22] = layouts;
123
+ $[23] = metaTitle;
124
+ $[24] = page;
125
+ $[25] = pageLayoutRecord;
126
+ $[26] = pages;
127
+ $[27] = project;
128
+ $[28] = t9;
129
+ } else t9 = $[28];
130
+ return t9;
131
+ };
132
+ const PageInfoSidebar = (t0) => {
133
+ const $ = c(40);
134
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
135
+ for (let $i = 0; $i < 40; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
136
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
137
+ }
138
+ const { pageId } = t0;
139
+ const data = usePageMetadataData(pageId);
140
+ const { page, metaTitle } = data;
141
+ const [isStructureModalOpen, setIsStructureModalOpen] = React.useState(false);
142
+ const [isSeoModalOpen, setIsSeoModalOpen] = React.useState(false);
143
+ const [isMarkdownModalOpen, setIsMarkdownModalOpen] = React.useState(false);
144
+ if (!page) {
145
+ let t1;
146
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
147
+ t1 = /* @__PURE__ */ jsxs("div", {
148
+ className: "text-muted-foreground flex flex-1 items-center justify-center px-2 text-sm",
149
+ children: [/* @__PURE__ */ jsx(Spinner, { className: "mr-2 size-3.5" }), " Loading page info..."]
150
+ });
151
+ $[1] = t1;
152
+ } else t1 = $[1];
153
+ return t1;
154
+ }
155
+ let t1;
156
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
157
+ t1 = /* @__PURE__ */ jsx("p", {
158
+ className: "text-base font-semibold",
159
+ children: "About this page"
160
+ });
161
+ $[2] = t1;
162
+ } else t1 = $[2];
163
+ let t2;
164
+ if ($[3] !== data) {
165
+ t2 = /* @__PURE__ */ jsx(PageNicknameSidebarEditor, { data });
166
+ $[3] = data;
167
+ $[4] = t2;
168
+ } else t2 = $[4];
169
+ let t3;
170
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
171
+ t3 = /* @__PURE__ */ jsx(Label, { children: "Page path" });
172
+ $[5] = t3;
173
+ } else t3 = $[5];
174
+ let t4;
175
+ if ($[6] !== page.fullPath) {
176
+ t4 = /* @__PURE__ */ jsx(InputGroupText, {
177
+ className: "min-w-0 flex-1 px-2 py-1.5 font-mono font-normal break-all",
178
+ children: page.fullPath
179
+ });
180
+ $[6] = page.fullPath;
181
+ $[7] = t4;
182
+ } else t4 = $[7];
183
+ let t5;
184
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
185
+ t5 = () => setIsStructureModalOpen(true);
186
+ $[8] = t5;
187
+ } else t5 = $[8];
188
+ let t6;
189
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
190
+ t6 = /* @__PURE__ */ jsx(InputGroupAddon, {
191
+ align: "inline-end",
192
+ children: /* @__PURE__ */ jsx(InputGroupButton, {
193
+ type: "button",
194
+ variant: "ghost",
195
+ size: "icon-xs",
196
+ onClick: t5,
197
+ "aria-label": "Edit page structure",
198
+ children: /* @__PURE__ */ jsx(Pencil, { className: "size-4" })
199
+ })
200
+ });
201
+ $[9] = t6;
202
+ } else t6 = $[9];
203
+ let t7;
204
+ if ($[10] !== t4) {
205
+ t7 = /* @__PURE__ */ jsxs("div", {
206
+ className: "space-y-2",
207
+ children: [t3, /* @__PURE__ */ jsxs(InputGroup, {
208
+ className: "h-auto min-h-9 px-1",
209
+ children: [t4, t6]
210
+ })]
211
+ });
212
+ $[10] = t4;
213
+ $[11] = t7;
214
+ } else t7 = $[11];
215
+ let t8;
216
+ if ($[12] !== data) {
217
+ t8 = /* @__PURE__ */ jsx(PageLayoutSidebarSelect, { data });
218
+ $[12] = data;
219
+ $[13] = t8;
220
+ } else t8 = $[13];
221
+ let t9;
222
+ if ($[14] !== t2 || $[15] !== t7 || $[16] !== t8) {
223
+ t9 = /* @__PURE__ */ jsxs("section", {
224
+ className: "space-y-4",
225
+ children: [
226
+ t1,
227
+ t2,
228
+ t7,
229
+ t8
230
+ ]
231
+ });
232
+ $[14] = t2;
233
+ $[15] = t7;
234
+ $[16] = t8;
235
+ $[17] = t9;
236
+ } else t9 = $[17];
237
+ let t10;
238
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
239
+ t10 = /* @__PURE__ */ jsx(Label, { children: "SEO" });
240
+ $[18] = t10;
241
+ } else t10 = $[18];
242
+ let t11;
243
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
244
+ t11 = /* @__PURE__ */ jsxs("div", {
245
+ className: "space-y-2",
246
+ children: [t10, /* @__PURE__ */ jsx(Button, {
247
+ type: "button",
248
+ variant: "outline",
249
+ className: "w-full",
250
+ onClick: () => setIsSeoModalOpen(true),
251
+ children: "Manage SEO metadata"
252
+ })]
253
+ });
254
+ $[19] = t11;
255
+ } else t11 = $[19];
256
+ let t12;
257
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
258
+ t12 = /* @__PURE__ */ jsx(Label, { children: "Markdown" });
259
+ $[20] = t12;
260
+ } else t12 = $[20];
261
+ let t13;
262
+ if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
263
+ t13 = /* @__PURE__ */ jsxs("div", {
264
+ className: "space-y-2",
265
+ children: [t12, /* @__PURE__ */ jsx(Button, {
266
+ type: "button",
267
+ variant: "outline",
268
+ className: "w-full",
269
+ onClick: () => setIsMarkdownModalOpen(true),
270
+ children: "View page markdown"
271
+ })]
272
+ });
273
+ $[21] = t13;
274
+ } else t13 = $[21];
275
+ let t14;
276
+ if ($[22] !== t9) {
277
+ t14 = /* @__PURE__ */ jsxs("div", {
278
+ className: "flex-1 space-y-4 overflow-auto p-2 pt-4",
279
+ children: [
280
+ t9,
281
+ t11,
282
+ t13
283
+ ]
284
+ });
285
+ $[22] = t9;
286
+ $[23] = t14;
287
+ } else t14 = $[23];
288
+ let t15;
289
+ if ($[24] !== isStructureModalOpen || $[25] !== page.id) {
290
+ t15 = /* @__PURE__ */ jsx(PageStructureModal, {
291
+ open: isStructureModalOpen,
292
+ onOpenChange: setIsStructureModalOpen,
293
+ pageId: page.id
294
+ });
295
+ $[24] = isStructureModalOpen;
296
+ $[25] = page.id;
297
+ $[26] = t15;
298
+ } else t15 = $[26];
299
+ let t16;
300
+ if ($[27] !== isSeoModalOpen || $[28] !== page.id) {
301
+ t16 = /* @__PURE__ */ jsx(PageSeoModal, {
302
+ open: isSeoModalOpen,
303
+ onOpenChange: setIsSeoModalOpen,
304
+ pageId: page.id
305
+ });
306
+ $[27] = isSeoModalOpen;
307
+ $[28] = page.id;
308
+ $[29] = t16;
309
+ } else t16 = $[29];
310
+ const t17 = page.metaDescription ?? "";
311
+ let t18;
312
+ if ($[30] !== isMarkdownModalOpen || $[31] !== metaTitle || $[32] !== page.id || $[33] !== t17) {
313
+ t18 = /* @__PURE__ */ jsx(PageMarkdownModal, {
314
+ open: isMarkdownModalOpen,
315
+ onOpenChange: setIsMarkdownModalOpen,
316
+ pageId: page.id,
317
+ metaTitle,
318
+ metaDescription: t17
319
+ });
320
+ $[30] = isMarkdownModalOpen;
321
+ $[31] = metaTitle;
322
+ $[32] = page.id;
323
+ $[33] = t17;
324
+ $[34] = t18;
325
+ } else t18 = $[34];
326
+ let t19;
327
+ if ($[35] !== t14 || $[36] !== t15 || $[37] !== t16 || $[38] !== t18) {
328
+ t19 = /* @__PURE__ */ jsxs(Fragment, { children: [
329
+ t14,
330
+ t15,
331
+ t16,
332
+ t18
333
+ ] });
334
+ $[35] = t14;
335
+ $[36] = t15;
336
+ $[37] = t16;
337
+ $[38] = t18;
338
+ $[39] = t19;
339
+ } else t19 = $[39];
340
+ return t19;
341
+ };
342
+ const PageNicknameSidebarEditor = (t0) => {
343
+ const $ = c(21);
344
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
345
+ for (let $i = 0; $i < 21; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
346
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
347
+ }
348
+ const { data } = t0;
349
+ const { page } = data;
350
+ let t1;
351
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
352
+ t1 = pageMutations.update();
353
+ $[1] = t1;
354
+ } else t1 = $[1];
355
+ const updatePage = useMutation(t1);
356
+ const inputId = React.useId();
357
+ let t2;
358
+ if ($[2] !== page || $[3] !== updatePage) {
359
+ t2 = (value) => {
360
+ if (!page) return;
361
+ const nickname = value.trim();
362
+ if (nickname === page.nickname) return;
363
+ if (!nickname) {
364
+ toast.error("Page nickname is required");
365
+ return;
366
+ }
367
+ updatePage.mutate({
368
+ id: page.id,
369
+ nickname,
370
+ pathSegment: page.pathSegment,
371
+ parentPageId: page.parentPageId
372
+ }, {
373
+ onSuccess: () => {
374
+ trackClientEvent("page_updated", {
375
+ projectId: page.projectId,
376
+ changes: {
377
+ nickname: true,
378
+ path: false,
379
+ layout: false,
380
+ parent: false
381
+ }
382
+ });
383
+ },
384
+ onError: _temp
385
+ });
386
+ };
387
+ $[2] = page;
388
+ $[3] = updatePage;
389
+ $[4] = t2;
390
+ } else t2 = $[4];
391
+ const saveNickname = t2;
392
+ const { value: value_0, setValue, onFocus, onBlur } = useDebouncedField(page?.nickname ?? "", saveNickname);
393
+ if (!page) return null;
394
+ let t3;
395
+ if ($[5] !== inputId) {
396
+ t3 = /* @__PURE__ */ jsx(Label, {
397
+ htmlFor: inputId,
398
+ children: "Page nickname"
399
+ });
400
+ $[5] = inputId;
401
+ $[6] = t3;
402
+ } else t3 = $[6];
403
+ let t4;
404
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
405
+ t4 = /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-3.5" }) }), /* @__PURE__ */ jsx(TooltipContent, { children: "A short internal name. Does not affect SEO." })] });
406
+ $[7] = t4;
407
+ } else t4 = $[7];
408
+ let t5;
409
+ if ($[8] !== t3) {
410
+ t5 = /* @__PURE__ */ jsxs("div", {
411
+ className: "flex items-center gap-1.5",
412
+ children: [t3, t4]
413
+ });
414
+ $[8] = t3;
415
+ $[9] = t5;
416
+ } else t5 = $[9];
417
+ let t6;
418
+ if ($[10] !== setValue) {
419
+ t6 = (e) => setValue(e.target.value);
420
+ $[10] = setValue;
421
+ $[11] = t6;
422
+ } else t6 = $[11];
423
+ let t7;
424
+ if ($[12] !== inputId || $[13] !== onBlur || $[14] !== onFocus || $[15] !== t6 || $[16] !== value_0) {
425
+ t7 = /* @__PURE__ */ jsx(Input, {
426
+ id: inputId,
427
+ value: value_0,
428
+ onChange: t6,
429
+ onFocus,
430
+ onBlur,
431
+ placeholder: "e.g. Home, Pricing, About",
432
+ maxLength: 80
433
+ });
434
+ $[12] = inputId;
435
+ $[13] = onBlur;
436
+ $[14] = onFocus;
437
+ $[15] = t6;
438
+ $[16] = value_0;
439
+ $[17] = t7;
440
+ } else t7 = $[17];
441
+ let t8;
442
+ if ($[18] !== t5 || $[19] !== t7) {
443
+ t8 = /* @__PURE__ */ jsxs("div", {
444
+ className: "space-y-2",
445
+ children: [t5, t7]
446
+ });
447
+ $[18] = t5;
448
+ $[19] = t7;
449
+ $[20] = t8;
450
+ } else t8 = $[20];
451
+ return t8;
452
+ };
453
+ const PageLayoutSidebarSelect = (t0) => {
454
+ const $ = c(30);
455
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
456
+ for (let $i = 0; $i < 30; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
457
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
458
+ }
459
+ const { data } = t0;
460
+ const { page, layouts, camoxApp } = data;
461
+ let t1;
462
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
463
+ t1 = pageMutations.setLayout();
464
+ $[1] = t1;
465
+ } else t1 = $[1];
466
+ const setLayout = useMutation(t1);
467
+ if (!page || !layouts || layouts.length === 0) return null;
468
+ let t2;
469
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
470
+ t2 = /* @__PURE__ */ jsx(Label, { children: "Layout" });
471
+ $[2] = t2;
472
+ } else t2 = $[2];
473
+ let t3;
474
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
475
+ t3 = /* @__PURE__ */ jsxs("div", {
476
+ className: "flex items-center gap-1.5",
477
+ children: [t2, /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { render: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-3.5" }) }), /* @__PURE__ */ jsx(TooltipContent, {
478
+ className: "max-w-xs",
479
+ children: "A layout wraps page content in shared structure, like navbars and footers, and controls how metadata is generated."
480
+ })] })]
481
+ });
482
+ $[3] = t3;
483
+ } else t3 = $[3];
484
+ const t4 = page.layoutId ? String(page.layoutId) : "";
485
+ let t5;
486
+ if ($[4] !== page.id || $[5] !== page.layoutId || $[6] !== page.projectId || $[7] !== setLayout) {
487
+ t5 = (value) => {
488
+ const layoutId = Number(value);
489
+ if (layoutId === page.layoutId) return;
490
+ setLayout.mutate({
491
+ id: page.id,
492
+ layoutId
493
+ }, {
494
+ onSuccess: () => {
495
+ trackClientEvent("page_updated", {
496
+ projectId: page.projectId,
497
+ changes: {
498
+ nickname: false,
499
+ path: false,
500
+ layout: true,
501
+ parent: false
502
+ }
503
+ });
504
+ },
505
+ onError: _temp2
506
+ });
507
+ };
508
+ $[4] = page.id;
509
+ $[5] = page.layoutId;
510
+ $[6] = page.projectId;
511
+ $[7] = setLayout;
512
+ $[8] = t5;
513
+ } else t5 = $[8];
514
+ let t6;
515
+ if ($[9] !== camoxApp || $[10] !== layouts) {
516
+ let t7;
517
+ if ($[12] !== camoxApp) {
518
+ t7 = (t) => ({
519
+ value: String(t.id),
520
+ label: camoxApp.getLayoutById(t.layoutId)?._internal.title ?? t.layoutId
521
+ });
522
+ $[12] = camoxApp;
523
+ $[13] = t7;
524
+ } else t7 = $[13];
525
+ t6 = layouts.map(t7);
526
+ $[9] = camoxApp;
527
+ $[10] = layouts;
528
+ $[11] = t6;
529
+ } else t6 = $[11];
530
+ let t7;
531
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
532
+ t7 = /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a layout" });
533
+ $[14] = t7;
534
+ } else t7 = $[14];
535
+ let t8;
536
+ if ($[15] !== setLayout.isPending) {
537
+ t8 = /* @__PURE__ */ jsx(SelectTrigger, {
538
+ disabled: setLayout.isPending,
539
+ className: "w-full",
540
+ children: t7
541
+ });
542
+ $[15] = setLayout.isPending;
543
+ $[16] = t8;
544
+ } else t8 = $[16];
545
+ let t9;
546
+ if ($[17] !== camoxApp || $[18] !== layouts) {
547
+ let t10;
548
+ if ($[20] !== camoxApp) {
549
+ t10 = (t_0) => /* @__PURE__ */ jsx(SelectItem, {
550
+ value: String(t_0.id),
551
+ children: camoxApp.getLayoutById(t_0.layoutId)?._internal.title ?? t_0.layoutId
552
+ }, t_0.id);
553
+ $[20] = camoxApp;
554
+ $[21] = t10;
555
+ } else t10 = $[21];
556
+ t9 = layouts.map(t10);
557
+ $[17] = camoxApp;
558
+ $[18] = layouts;
559
+ $[19] = t9;
560
+ } else t9 = $[19];
561
+ let t10;
562
+ if ($[22] !== t9) {
563
+ t10 = /* @__PURE__ */ jsx(SelectContent, { children: t9 });
564
+ $[22] = t9;
565
+ $[23] = t10;
566
+ } else t10 = $[23];
567
+ let t11;
568
+ if ($[24] !== t10 || $[25] !== t4 || $[26] !== t5 || $[27] !== t6 || $[28] !== t8) {
569
+ t11 = /* @__PURE__ */ jsxs("div", {
570
+ className: "space-y-2",
571
+ children: [t3, /* @__PURE__ */ jsxs(Select, {
572
+ value: t4,
573
+ onValueChange: t5,
574
+ items: t6,
575
+ children: [t8, t10]
576
+ })]
577
+ });
578
+ $[24] = t10;
579
+ $[25] = t4;
580
+ $[26] = t5;
581
+ $[27] = t6;
582
+ $[28] = t8;
583
+ $[29] = t11;
584
+ } else t11 = $[29];
585
+ return t11;
586
+ };
587
+ const PageStructureModal = (t0) => {
588
+ const $ = c(10);
589
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
590
+ for (let $i = 0; $i < 10; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
591
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
592
+ }
593
+ const { open, onOpenChange, pageId } = t0;
594
+ const data = usePageMetadataData(pageId);
595
+ const { page } = data;
596
+ let t1;
597
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
598
+ t1 = /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Page page" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Update the URL path for this page." })] });
599
+ $[1] = t1;
600
+ } else t1 = $[1];
601
+ let t2;
602
+ if ($[2] !== data || $[3] !== onOpenChange || $[4] !== page) {
603
+ t2 = /* @__PURE__ */ jsxs(DialogContent, {
604
+ className: "max-h-[90vh] overflow-y-auto sm:max-w-2xl",
605
+ children: [t1, page ? /* @__PURE__ */ jsx(PageStructureEditor, {
606
+ data,
607
+ includeNickname: false,
608
+ includeLayout: false,
609
+ onSaved: () => onOpenChange(false)
610
+ }) : /* @__PURE__ */ jsxs("div", {
611
+ className: "text-muted-foreground flex items-center gap-2 py-6 text-sm",
612
+ children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }), " Loading..."]
613
+ })]
614
+ });
615
+ $[2] = data;
616
+ $[3] = onOpenChange;
617
+ $[4] = page;
618
+ $[5] = t2;
619
+ } else t2 = $[5];
620
+ let t3;
621
+ if ($[6] !== onOpenChange || $[7] !== open || $[8] !== t2) {
622
+ t3 = /* @__PURE__ */ jsx(Dialog, {
623
+ open,
624
+ onOpenChange,
625
+ children: t2
626
+ });
627
+ $[6] = onOpenChange;
628
+ $[7] = open;
629
+ $[8] = t2;
630
+ $[9] = t3;
631
+ } else t3 = $[9];
632
+ return t3;
633
+ };
634
+ const PageStructureEditor = ({ data, includeNickname = true, includeLayout = true, onSaved }) => {
635
+ const { page, project, pages, layouts, camoxApp } = data;
636
+ const updatePage = useMutation(pageMutations.update());
637
+ const setLayout = useMutation(pageMutations.setLayout());
638
+ const navigate = useNavigate();
639
+ const form = useForm({
640
+ defaultValues: {
641
+ nickname: page?.nickname ?? "",
642
+ pathSegment: page?.pathSegment ?? "",
643
+ parentPageId: page?.parentPageId ?? void 0,
644
+ layoutId: page?.layoutId ?? 0
645
+ },
646
+ onSubmit: async (values) => {
647
+ if (!page) return;
648
+ try {
649
+ const nickname = values.value.nickname.trim();
650
+ if (!nickname) {
651
+ toast.error("Page nickname is required");
652
+ return;
653
+ }
654
+ const { fullPath } = await updatePage.mutateAsync({
655
+ id: page.id,
656
+ nickname,
657
+ pathSegment: values.value.pathSegment,
658
+ parentPageId: values.value.parentPageId
659
+ });
660
+ if (includeLayout && values.value.layoutId) await setLayout.mutateAsync({
661
+ id: page.id,
662
+ layoutId: values.value.layoutId
663
+ });
664
+ trackClientEvent("page_updated", {
665
+ projectId: page.projectId,
666
+ changes: {
667
+ nickname: nickname !== page.nickname,
668
+ path: values.value.pathSegment !== page.pathSegment,
669
+ layout: includeLayout && values.value.layoutId !== page.layoutId,
670
+ parent: values.value.parentPageId !== page.parentPageId
671
+ }
672
+ });
673
+ toast.success(`Updated ${nickname} page`);
674
+ form.reset();
675
+ onSaved?.();
676
+ await navigate({ to: fullPath });
677
+ } catch (error) {
678
+ console.error("Failed to update page:", error);
679
+ toast.error("Could not update page");
680
+ }
681
+ }
682
+ });
683
+ React.useEffect(() => {
684
+ if (!page) return;
685
+ form.reset({
686
+ nickname: page.nickname,
687
+ pathSegment: page.pathSegment,
688
+ parentPageId: page.parentPageId ?? void 0,
689
+ layoutId: page.layoutId ?? 0
690
+ });
691
+ }, [page?.id]);
692
+ if (!page || !project) return null;
693
+ const isRootPage = page.fullPath === "/";
694
+ return /* @__PURE__ */ jsxs("form", {
695
+ onSubmit: (e) => {
696
+ e.preventDefault();
697
+ e.stopPropagation();
698
+ form.handleSubmit();
699
+ },
700
+ className: "space-y-4",
701
+ children: [
702
+ includeNickname && /* @__PURE__ */ jsx(form.Field, {
703
+ name: "nickname",
704
+ children: (field) => /* @__PURE__ */ jsx(PageNicknameField, {
705
+ value: field.state.value,
706
+ onChange: field.handleChange
707
+ })
708
+ }),
709
+ isRootPage ? /* @__PURE__ */ jsxs(Alert, { children: [
710
+ /* @__PURE__ */ jsx(Info, { className: "size-4" }),
711
+ /* @__PURE__ */ jsx(AlertTitle, { children: "Homepage" }),
712
+ /* @__PURE__ */ jsx(AlertDescription, { children: "You can't change the path of the home page." })
713
+ ] }) : /* @__PURE__ */ jsx(form.Field, {
714
+ name: "parentPageId",
715
+ children: (parentField) => /* @__PURE__ */ jsx(form.Field, {
716
+ name: "pathSegment",
717
+ children: (pathField) => /* @__PURE__ */ jsx(PageLocationFieldset, {
718
+ parentPageId: parentField.state.value,
719
+ onParentPageIdChange: parentField.handleChange,
720
+ pathSegment: pathField.state.value,
721
+ onPathSegmentChange: pathField.handleChange,
722
+ pages,
723
+ excludePageId: page.id
724
+ })
725
+ })
726
+ }),
727
+ includeLayout && layouts && layouts.length > 0 && /* @__PURE__ */ jsx(form.Field, {
728
+ name: "layoutId",
729
+ children: (field_0) => /* @__PURE__ */ jsxs("div", {
730
+ className: "space-y-2",
731
+ children: [/* @__PURE__ */ jsx(Label, { children: "Layout" }), /* @__PURE__ */ jsxs(Select, {
732
+ value: field_0.state.value ? String(field_0.state.value) : "",
733
+ onValueChange: (value) => field_0.handleChange(Number(value)),
734
+ items: layouts.map((t) => ({
735
+ value: String(t.id),
736
+ label: camoxApp.getLayoutById(t.layoutId)?._internal.title ?? t.layoutId
737
+ })),
738
+ children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a layout" }) }), /* @__PURE__ */ jsx(SelectContent, { children: layouts.map((t_0) => /* @__PURE__ */ jsx(SelectItem, {
739
+ value: String(t_0.id),
740
+ children: camoxApp.getLayoutById(t_0.layoutId)?._internal.title ?? t_0.layoutId
741
+ }, t_0.id)) })]
742
+ })]
743
+ })
744
+ }),
745
+ /* @__PURE__ */ jsx(form.Subscribe, {
746
+ selector: (s) => ({
747
+ isSubmitting: s.isSubmitting,
748
+ isPristine: s.isPristine
749
+ }),
750
+ children: ({ isSubmitting, isPristine }) => /* @__PURE__ */ jsxs(Button, {
751
+ type: "submit",
752
+ disabled: isSubmitting || isPristine,
753
+ children: [
754
+ isSubmitting && /* @__PURE__ */ jsx(Spinner, {}),
755
+ "Save changes",
756
+ isSubmitting && "..."
757
+ ]
758
+ })
759
+ })
760
+ ]
761
+ });
762
+ };
763
+ const PageSeoModal = (t0) => {
764
+ const $ = c(11);
765
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
766
+ for (let $i = 0; $i < 11; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
767
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
768
+ }
769
+ const { open, onOpenChange, pageId } = t0;
770
+ const { page, metaTitle, pageLayoutRecord, project } = usePageMetadataData(pageId);
771
+ let t1;
772
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
773
+ t1 = /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "SEO metadata" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Control how this page appears in search and social previews." })] });
774
+ $[1] = t1;
775
+ } else t1 = $[1];
776
+ let t2;
777
+ if ($[2] !== metaTitle || $[3] !== page || $[4] !== pageLayoutRecord?.layoutId || $[5] !== project?.name) {
778
+ t2 = /* @__PURE__ */ jsxs(DialogContent, {
779
+ className: "max-h-[90vh] overflow-y-auto sm:max-w-3xl",
780
+ children: [t1, page ? /* @__PURE__ */ jsx(PageSeoEditor, {
781
+ page,
782
+ metaTitle,
783
+ layoutId: pageLayoutRecord?.layoutId,
784
+ projectName: project?.name
785
+ }) : /* @__PURE__ */ jsxs("div", {
786
+ className: "text-muted-foreground flex items-center gap-2 py-6 text-sm",
787
+ children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }), " Loading..."]
788
+ })]
789
+ });
790
+ $[2] = metaTitle;
791
+ $[3] = page;
792
+ $[4] = pageLayoutRecord?.layoutId;
793
+ $[5] = project?.name;
794
+ $[6] = t2;
795
+ } else t2 = $[6];
796
+ let t3;
797
+ if ($[7] !== onOpenChange || $[8] !== open || $[9] !== t2) {
798
+ t3 = /* @__PURE__ */ jsx(Dialog, {
799
+ open,
800
+ onOpenChange,
801
+ children: t2
802
+ });
803
+ $[7] = onOpenChange;
804
+ $[8] = open;
805
+ $[9] = t2;
806
+ $[10] = t3;
807
+ } else t3 = $[10];
808
+ return t3;
809
+ };
810
+ const PageSeoEditor = (t0) => {
811
+ const $ = c(43);
812
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
813
+ for (let $i = 0; $i < 43; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
814
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
815
+ }
816
+ const { page, metaTitle, layoutId, projectName } = t0;
817
+ let t1;
818
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
819
+ t1 = pageMutations.setAiSeo();
820
+ $[1] = t1;
821
+ } else t1 = $[1];
822
+ const setAiSeo = useMutation(t1);
823
+ let t2;
824
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
825
+ t2 = pageMutations.setMetaTitle();
826
+ $[2] = t2;
827
+ } else t2 = $[2];
828
+ const setMetaTitle = useMutation(t2);
829
+ let t3;
830
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
831
+ t3 = pageMutations.setMetaDescription();
832
+ $[3] = t3;
833
+ } else t3 = $[3];
834
+ const setMetaDescription = useMutation(t3);
835
+ const t4 = page.aiSeoEnabled !== false;
836
+ let t5;
837
+ if ($[4] !== page.id || $[5] !== setAiSeo) {
838
+ t5 = (checked) => {
839
+ setAiSeo.mutate({
840
+ id: page.id,
841
+ enabled: checked
842
+ });
843
+ trackClientEvent("ai_metadata_toggled", {
844
+ target: "page",
845
+ enabled: checked,
846
+ pageId: page.id
847
+ });
848
+ };
849
+ $[4] = page.id;
850
+ $[5] = setAiSeo;
851
+ $[6] = t5;
852
+ } else t5 = $[6];
853
+ let t6;
854
+ if ($[7] !== t4 || $[8] !== t5) {
855
+ t6 = /* @__PURE__ */ jsx(Switch, {
856
+ id: "ai-seo",
857
+ checked: t4,
858
+ onCheckedChange: t5
859
+ });
860
+ $[7] = t4;
861
+ $[8] = t5;
862
+ $[9] = t6;
863
+ } else t6 = $[9];
864
+ let t7;
865
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
866
+ t7 = /* @__PURE__ */ jsx(Label, {
867
+ htmlFor: "ai-seo",
868
+ children: "AI metadata"
869
+ });
870
+ $[10] = t7;
871
+ } else t7 = $[10];
872
+ let t8;
873
+ if ($[11] !== t6) {
874
+ t8 = /* @__PURE__ */ jsxs("div", {
875
+ className: "flex items-center gap-2",
876
+ children: [t6, t7]
877
+ });
878
+ $[11] = t6;
879
+ $[12] = t8;
880
+ } else t8 = $[12];
881
+ const t9 = page.metaTitle ?? "";
882
+ const t10 = page.aiSeoEnabled !== false;
883
+ let t11;
884
+ if ($[13] !== page.id || $[14] !== setMetaTitle) {
885
+ t11 = (value) => setMetaTitle.mutate({
886
+ id: page.id,
887
+ metaTitle: value
888
+ });
889
+ $[13] = page.id;
890
+ $[14] = setMetaTitle;
891
+ $[15] = t11;
892
+ } else t11 = $[15];
893
+ let t12;
894
+ if ($[16] !== t10 || $[17] !== t11 || $[18] !== t9) {
895
+ t12 = /* @__PURE__ */ jsx(DebouncedFieldEditor, {
896
+ label: "Page title",
897
+ placeholder: "Page title...",
898
+ initialValue: t9,
899
+ disabled: t10,
900
+ onSave: t11
901
+ });
902
+ $[16] = t10;
903
+ $[17] = t11;
904
+ $[18] = t9;
905
+ $[19] = t12;
906
+ } else t12 = $[19];
907
+ const t13 = page.metaDescription ?? "";
908
+ const t14 = page.aiSeoEnabled !== false;
909
+ let t15;
910
+ if ($[20] !== page.id || $[21] !== setMetaDescription) {
911
+ t15 = (value_0) => setMetaDescription.mutate({
912
+ id: page.id,
913
+ metaDescription: value_0
914
+ });
915
+ $[20] = page.id;
916
+ $[21] = setMetaDescription;
917
+ $[22] = t15;
918
+ } else t15 = $[22];
919
+ let t16;
920
+ if ($[23] !== t13 || $[24] !== t14 || $[25] !== t15) {
921
+ t16 = /* @__PURE__ */ jsx(DebouncedFieldEditor, {
922
+ label: "Page description",
923
+ placeholder: "Page description...",
924
+ initialValue: t13,
925
+ disabled: t14,
926
+ rows: 2,
927
+ onSave: t15
928
+ });
929
+ $[23] = t13;
930
+ $[24] = t14;
931
+ $[25] = t15;
932
+ $[26] = t16;
933
+ } else t16 = $[26];
934
+ const t17 = page.metaDescription ?? "";
935
+ let t18;
936
+ if ($[27] !== metaTitle || $[28] !== page || $[29] !== t17) {
937
+ t18 = /* @__PURE__ */ jsx(SearchEnginePreview, {
938
+ page,
939
+ metaTitle,
940
+ metaDescription: t17
941
+ });
942
+ $[27] = metaTitle;
943
+ $[28] = page;
944
+ $[29] = t17;
945
+ $[30] = t18;
946
+ } else t18 = $[30];
947
+ const t19 = page.metaDescription ?? "";
948
+ let t20;
949
+ if ($[31] !== layoutId || $[32] !== metaTitle || $[33] !== page || $[34] !== projectName || $[35] !== t19) {
950
+ t20 = /* @__PURE__ */ jsx(SocialPreviewSection, {
951
+ page,
952
+ metaTitle,
953
+ metaDescription: t19,
954
+ layoutId,
955
+ projectName
956
+ });
957
+ $[31] = layoutId;
958
+ $[32] = metaTitle;
959
+ $[33] = page;
960
+ $[34] = projectName;
961
+ $[35] = t19;
962
+ $[36] = t20;
963
+ } else t20 = $[36];
964
+ let t21;
965
+ if ($[37] !== t12 || $[38] !== t16 || $[39] !== t18 || $[40] !== t20 || $[41] !== t8) {
966
+ t21 = /* @__PURE__ */ jsxs("div", {
967
+ className: "space-y-4",
968
+ children: [
969
+ t8,
970
+ t12,
971
+ t16,
972
+ t18,
973
+ t20
974
+ ]
975
+ });
976
+ $[37] = t12;
977
+ $[38] = t16;
978
+ $[39] = t18;
979
+ $[40] = t20;
980
+ $[41] = t8;
981
+ $[42] = t21;
982
+ } else t21 = $[42];
983
+ return t21;
984
+ };
985
+ const PageMarkdownModal = (t0) => {
986
+ const $ = c(10);
987
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
988
+ for (let $i = 0; $i < 10; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
989
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
990
+ }
991
+ const { open, onOpenChange, pageId, metaTitle, metaDescription } = t0;
992
+ let t1;
993
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
994
+ t1 = /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Markdown content" }), /* @__PURE__ */ jsx(DialogDescription, { children: "How your content will be served to AI agents." })] });
995
+ $[1] = t1;
996
+ } else t1 = $[1];
997
+ let t2;
998
+ if ($[2] !== metaDescription || $[3] !== metaTitle || $[4] !== pageId) {
999
+ t2 = /* @__PURE__ */ jsxs(DialogContent, {
1000
+ className: "max-h-[90vh] overflow-y-auto sm:max-w-4xl",
1001
+ children: [t1, /* @__PURE__ */ jsx(PageMarkdownPreview, {
1002
+ pageId,
1003
+ metaTitle,
1004
+ metaDescription
1005
+ })]
1006
+ });
1007
+ $[2] = metaDescription;
1008
+ $[3] = metaTitle;
1009
+ $[4] = pageId;
1010
+ $[5] = t2;
1011
+ } else t2 = $[5];
1012
+ let t3;
1013
+ if ($[6] !== onOpenChange || $[7] !== open || $[8] !== t2) {
1014
+ t3 = /* @__PURE__ */ jsx(Dialog, {
1015
+ open,
1016
+ onOpenChange,
1017
+ children: t2
1018
+ });
1019
+ $[6] = onOpenChange;
1020
+ $[7] = open;
1021
+ $[8] = t2;
1022
+ $[9] = t3;
1023
+ } else t3 = $[9];
1024
+ return t3;
1025
+ };
1026
+ function truncateText(text, maxLen) {
1027
+ if (text.length <= maxLen) return text;
1028
+ return text.slice(0, maxLen) + "...";
1029
+ }
1030
+ const SearchEnginePreview = (t0) => {
1031
+ const $ = c(17);
1032
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
1033
+ for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1034
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
1035
+ }
1036
+ const { page, metaTitle, metaDescription } = t0;
1037
+ const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
1038
+ let t1;
1039
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
1040
+ t1 = /* @__PURE__ */ jsx(Label, { children: "Search engine preview" });
1041
+ $[1] = t1;
1042
+ } else t1 = $[1];
1043
+ let t2;
1044
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
1045
+ t2 = /* @__PURE__ */ jsxs("div", {
1046
+ className: "flex items-center gap-1.5",
1047
+ children: [t1, /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
1048
+ delay: 50,
1049
+ render: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-3.5" })
1050
+ }), /* @__PURE__ */ jsx(TooltipContent, { children: "Titles are cropped after 60 characters and descriptions after 155, like on Google Search results." })] })]
1051
+ });
1052
+ $[2] = t2;
1053
+ } else t2 = $[2];
1054
+ let t3;
1055
+ if ($[3] !== url) {
1056
+ t3 = /* @__PURE__ */ jsx("p", {
1057
+ className: "text-muted-foreground truncate text-xs",
1058
+ children: url
1059
+ });
1060
+ $[3] = url;
1061
+ $[4] = t3;
1062
+ } else t3 = $[4];
1063
+ const t4 = metaTitle || "Untitled";
1064
+ let t5;
1065
+ if ($[5] !== t4) {
1066
+ t5 = truncateText(t4, 60);
1067
+ $[5] = t4;
1068
+ $[6] = t5;
1069
+ } else t5 = $[6];
1070
+ let t6;
1071
+ if ($[7] !== t5) {
1072
+ t6 = /* @__PURE__ */ jsx("p", {
1073
+ className: "text-base font-medium text-blue-600 dark:text-blue-400",
1074
+ children: t5
1075
+ });
1076
+ $[7] = t5;
1077
+ $[8] = t6;
1078
+ } else t6 = $[8];
1079
+ const t7 = metaDescription || "No description";
1080
+ let t8;
1081
+ if ($[9] !== t7) {
1082
+ t8 = truncateText(t7, 155);
1083
+ $[9] = t7;
1084
+ $[10] = t8;
1085
+ } else t8 = $[10];
1086
+ let t9;
1087
+ if ($[11] !== t8) {
1088
+ t9 = /* @__PURE__ */ jsx("p", {
1089
+ className: "text-muted-foreground line-clamp-2 text-xs",
1090
+ children: t8
1091
+ });
1092
+ $[11] = t8;
1093
+ $[12] = t9;
1094
+ } else t9 = $[12];
1095
+ let t10;
1096
+ if ($[13] !== t3 || $[14] !== t6 || $[15] !== t9) {
1097
+ t10 = /* @__PURE__ */ jsxs("div", {
1098
+ className: "space-y-1 pt-2",
1099
+ children: [t2, /* @__PURE__ */ jsxs("div", {
1100
+ className: "border-border space-y-0.5 rounded-lg border p-3",
1101
+ children: [
1102
+ t3,
1103
+ t6,
1104
+ t9
1105
+ ]
1106
+ })]
1107
+ });
1108
+ $[13] = t3;
1109
+ $[14] = t6;
1110
+ $[15] = t9;
1111
+ $[16] = t10;
1112
+ } else t10 = $[16];
1113
+ return t10;
1114
+ };
1115
+ const SocialPreviewSection = (t0) => {
1116
+ const $ = c(60);
1117
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
1118
+ for (let $i = 0; $i < 60; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1119
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
1120
+ }
1121
+ const { page, metaTitle, metaDescription, layoutId, projectName } = t0;
1122
+ const pageMetaTitle = page.metaTitle ?? page.pathSegment;
1123
+ let t1;
1124
+ if ($[1] !== layoutId || $[2] !== page.metaDescription || $[3] !== pageMetaTitle || $[4] !== projectName) {
1125
+ t1 = new URLSearchParams({
1126
+ ...layoutId && { layoutId },
1127
+ title: pageMetaTitle,
1128
+ ...page.metaDescription && { description: page.metaDescription },
1129
+ ...projectName && { projectName }
1130
+ }).toString();
1131
+ $[1] = layoutId;
1132
+ $[2] = page.metaDescription;
1133
+ $[3] = pageMetaTitle;
1134
+ $[4] = projectName;
1135
+ $[5] = t1;
1136
+ } else t1 = $[5];
1137
+ const generatedOgImage = `/og?${t1}`;
1138
+ const ogImage = page.customOgImageUrl ?? generatedOgImage;
1139
+ const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
1140
+ const fileInputRef = React.useRef(null);
1141
+ const queryClient = useQueryClient();
1142
+ let t2;
1143
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
1144
+ t2 = pageMutations.uploadCustomOgImage();
1145
+ $[6] = t2;
1146
+ } else t2 = $[6];
1147
+ let t3;
1148
+ if ($[7] !== page.id || $[8] !== queryClient) {
1149
+ t3 = {
1150
+ ...t2,
1151
+ onSuccess: () => {
1152
+ queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
1153
+ trackClientEvent("page_custom_og_image_uploaded", { pageId: page.id });
1154
+ },
1155
+ onError: _temp6
1156
+ };
1157
+ $[7] = page.id;
1158
+ $[8] = queryClient;
1159
+ $[9] = t3;
1160
+ } else t3 = $[9];
1161
+ const uploadCustomOgImage = useMutation(t3);
1162
+ let t4;
1163
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
1164
+ t4 = pageMutations.deleteCustomOgImage();
1165
+ $[10] = t4;
1166
+ } else t4 = $[10];
1167
+ let t5;
1168
+ if ($[11] !== page.id || $[12] !== queryClient) {
1169
+ t5 = {
1170
+ ...t4,
1171
+ onSuccess: () => {
1172
+ queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
1173
+ trackClientEvent("page_custom_og_image_removed", { pageId: page.id });
1174
+ },
1175
+ onError: _temp7
1176
+ };
1177
+ $[11] = page.id;
1178
+ $[12] = queryClient;
1179
+ $[13] = t5;
1180
+ } else t5 = $[13];
1181
+ const deleteCustomOgImage = useMutation(t5);
1182
+ const hasCustomImage = !!page.customOgImageUrl;
1183
+ const isBusy = uploadCustomOgImage.isPending || deleteCustomOgImage.isPending;
1184
+ let t6;
1185
+ if ($[14] !== page.id || $[15] !== uploadCustomOgImage) {
1186
+ t6 = (files) => {
1187
+ const file = files[0];
1188
+ if (file) uploadCustomOgImage.mutate({
1189
+ pageId: page.id,
1190
+ file
1191
+ });
1192
+ };
1193
+ $[14] = page.id;
1194
+ $[15] = uploadCustomOgImage;
1195
+ $[16] = t6;
1196
+ } else t6 = $[16];
1197
+ const handleFiles = t6;
1198
+ let t7;
1199
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
1200
+ t7 = /* @__PURE__ */ jsx(Label, { children: "Social preview" });
1201
+ $[17] = t7;
1202
+ } else t7 = $[17];
1203
+ let t8;
1204
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
1205
+ t8 = () => fileInputRef.current?.click();
1206
+ $[18] = t8;
1207
+ } else t8 = $[18];
1208
+ let t9;
1209
+ if ($[19] !== uploadCustomOgImage.isPending) {
1210
+ t9 = uploadCustomOgImage.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Upload, { className: "size-3.5" });
1211
+ $[19] = uploadCustomOgImage.isPending;
1212
+ $[20] = t9;
1213
+ } else t9 = $[20];
1214
+ const t10 = hasCustomImage ? "Replace custom image" : "Upload custom image";
1215
+ let t11;
1216
+ if ($[21] !== isBusy || $[22] !== t10 || $[23] !== t9) {
1217
+ t11 = /* @__PURE__ */ jsxs(Button, {
1218
+ type: "button",
1219
+ variant: "secondary",
1220
+ size: "sm",
1221
+ disabled: isBusy,
1222
+ onClick: t8,
1223
+ children: [t9, t10]
1224
+ });
1225
+ $[21] = isBusy;
1226
+ $[22] = t10;
1227
+ $[23] = t9;
1228
+ $[24] = t11;
1229
+ } else t11 = $[24];
1230
+ let t12;
1231
+ if ($[25] !== deleteCustomOgImage || $[26] !== hasCustomImage || $[27] !== isBusy || $[28] !== page.id) {
1232
+ t12 = hasCustomImage && /* @__PURE__ */ jsxs(Button, {
1233
+ type: "button",
1234
+ variant: "ghost",
1235
+ disabled: isBusy,
1236
+ onClick: () => deleteCustomOgImage.mutate({ pageId: page.id }),
1237
+ "aria-label": "Remove custom image",
1238
+ children: [
1239
+ deleteCustomOgImage.isPending ? /* @__PURE__ */ jsx(Spinner, { className: "text-muted-foreground" }) : /* @__PURE__ */ jsx(Trash2, { className: "text-muted-foreground" }),
1240
+ " ",
1241
+ "Clear"
1242
+ ]
1243
+ });
1244
+ $[25] = deleteCustomOgImage;
1245
+ $[26] = hasCustomImage;
1246
+ $[27] = isBusy;
1247
+ $[28] = page.id;
1248
+ $[29] = t12;
1249
+ } else t12 = $[29];
1250
+ let t13;
1251
+ if ($[30] !== handleFiles) {
1252
+ t13 = /* @__PURE__ */ jsx("input", {
1253
+ type: "file",
1254
+ ref: fileInputRef,
1255
+ className: "hidden",
1256
+ accept: "image/jpeg,image/png,image/gif,image/webp",
1257
+ onChange: (e) => {
1258
+ if (e.target.files) handleFiles(e.target.files);
1259
+ e.target.value = "";
1260
+ }
1261
+ });
1262
+ $[30] = handleFiles;
1263
+ $[31] = t13;
1264
+ } else t13 = $[31];
1265
+ let t14;
1266
+ if ($[32] !== t11 || $[33] !== t12 || $[34] !== t13) {
1267
+ t14 = /* @__PURE__ */ jsxs("div", {
1268
+ className: "flex items-center gap-2",
1269
+ children: [
1270
+ t11,
1271
+ t12,
1272
+ t13
1273
+ ]
1274
+ });
1275
+ $[32] = t11;
1276
+ $[33] = t12;
1277
+ $[34] = t13;
1278
+ $[35] = t14;
1279
+ } else t14 = $[35];
1280
+ const t15 = hasCustomImage ? "Drop image to replace" : "Drop image to upload";
1281
+ let t16;
1282
+ if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
1283
+ t16 = { aspectRatio: "1200 / 630" };
1284
+ $[36] = t16;
1285
+ } else t16 = $[36];
1286
+ let t17;
1287
+ if ($[37] !== ogImage) {
1288
+ t17 = /* @__PURE__ */ jsx("img", {
1289
+ src: ogImage,
1290
+ alt: "",
1291
+ className: "w-full object-cover",
1292
+ style: t16
1293
+ });
1294
+ $[37] = ogImage;
1295
+ $[38] = t17;
1296
+ } else t17 = $[38];
1297
+ let t18;
1298
+ if ($[39] !== handleFiles || $[40] !== t15 || $[41] !== t17) {
1299
+ t18 = /* @__PURE__ */ jsx(UploadDropZone, {
1300
+ onDrop: handleFiles,
1301
+ label: t15,
1302
+ className: "block",
1303
+ children: t17
1304
+ });
1305
+ $[39] = handleFiles;
1306
+ $[40] = t15;
1307
+ $[41] = t17;
1308
+ $[42] = t18;
1309
+ } else t18 = $[42];
1310
+ const t19 = metaTitle || "Untitled";
1311
+ let t20;
1312
+ if ($[43] !== t19) {
1313
+ t20 = /* @__PURE__ */ jsx("p", {
1314
+ className: "text-foreground truncate text-sm font-semibold",
1315
+ children: t19
1316
+ });
1317
+ $[43] = t19;
1318
+ $[44] = t20;
1319
+ } else t20 = $[44];
1320
+ const t21 = metaDescription || "No description";
1321
+ let t22;
1322
+ if ($[45] !== t21) {
1323
+ t22 = /* @__PURE__ */ jsx("p", {
1324
+ className: "text-muted-foreground line-clamp-2 text-xs",
1325
+ children: t21
1326
+ });
1327
+ $[45] = t21;
1328
+ $[46] = t22;
1329
+ } else t22 = $[46];
1330
+ let t23;
1331
+ if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
1332
+ t23 = /* @__PURE__ */ jsx(Globe, { className: "size-3 shrink-0" });
1333
+ $[47] = t23;
1334
+ } else t23 = $[47];
1335
+ let t24;
1336
+ if ($[48] !== url) {
1337
+ t24 = /* @__PURE__ */ jsx("div", {
1338
+ className: "pt-1.5",
1339
+ children: /* @__PURE__ */ jsxs("p", {
1340
+ className: "text-muted-foreground flex items-center gap-1 text-xs",
1341
+ children: [t23, /* @__PURE__ */ jsx("span", {
1342
+ className: "truncate",
1343
+ children: url
1344
+ })]
1345
+ })
1346
+ });
1347
+ $[48] = url;
1348
+ $[49] = t24;
1349
+ } else t24 = $[49];
1350
+ let t25;
1351
+ if ($[50] !== t20 || $[51] !== t22 || $[52] !== t24) {
1352
+ t25 = /* @__PURE__ */ jsxs("div", {
1353
+ className: "space-y-1.5 border-t px-3 py-2.5",
1354
+ children: [
1355
+ t20,
1356
+ t22,
1357
+ t24
1358
+ ]
1359
+ });
1360
+ $[50] = t20;
1361
+ $[51] = t22;
1362
+ $[52] = t24;
1363
+ $[53] = t25;
1364
+ } else t25 = $[53];
1365
+ let t26;
1366
+ if ($[54] !== t18 || $[55] !== t25) {
1367
+ t26 = /* @__PURE__ */ jsxs("div", {
1368
+ className: "border-border max-w-xl overflow-hidden rounded-lg border",
1369
+ children: [t18, t25]
1370
+ });
1371
+ $[54] = t18;
1372
+ $[55] = t25;
1373
+ $[56] = t26;
1374
+ } else t26 = $[56];
1375
+ let t27;
1376
+ if ($[57] !== t14 || $[58] !== t26) {
1377
+ t27 = /* @__PURE__ */ jsxs("div", {
1378
+ className: "space-y-2 pt-2",
1379
+ children: [
1380
+ t7,
1381
+ t14,
1382
+ t26
1383
+ ]
1384
+ });
1385
+ $[57] = t14;
1386
+ $[58] = t26;
1387
+ $[59] = t27;
1388
+ } else t27 = $[59];
1389
+ return t27;
1390
+ };
1391
+ const PageMarkdownPreview = (t0) => {
1392
+ const $ = c(9);
1393
+ if ($[0] !== "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e") {
1394
+ for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
1395
+ $[0] = "7c7e91a25652fa060b67c4ffcd921b50c9111bae47d2051cc0eaca87fb060c3e";
1396
+ }
1397
+ const { pageId, metaTitle, metaDescription } = t0;
1398
+ let t1;
1399
+ if ($[1] !== pageId) {
1400
+ t1 = blockQueries.getPageMarkdown(pageId);
1401
+ $[1] = pageId;
1402
+ $[2] = t1;
1403
+ } else t1 = $[2];
1404
+ const { data: markdown } = useQuery(t1);
1405
+ if (markdown === void 0) {
1406
+ let t2;
1407
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
1408
+ t2 = /* @__PURE__ */ jsxs("div", {
1409
+ className: "text-muted-foreground flex items-center gap-2 py-2 text-sm",
1410
+ children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }), "Loading..."]
1411
+ });
1412
+ $[3] = t2;
1413
+ } else t2 = $[3];
1414
+ return t2;
1415
+ }
1416
+ const t2 = `title: "${metaTitle}"`;
1417
+ const t3 = `description: "${metaDescription}"`;
1418
+ let frontmatterLines;
1419
+ if ($[4] !== t2 || $[5] !== t3) {
1420
+ frontmatterLines = [
1421
+ "---",
1422
+ t2,
1423
+ t3
1424
+ ];
1425
+ frontmatterLines.push("---");
1426
+ $[4] = t2;
1427
+ $[5] = t3;
1428
+ $[6] = frontmatterLines;
1429
+ } else frontmatterLines = $[6];
1430
+ const fullMarkdown = frontmatterLines.join("\n") + "\n\n" + (markdown ?? "");
1431
+ let t4;
1432
+ if ($[7] !== fullMarkdown) {
1433
+ t4 = /* @__PURE__ */ jsx(ShikiMarkdown, { code: fullMarkdown });
1434
+ $[7] = fullMarkdown;
1435
+ $[8] = t4;
1436
+ } else t4 = $[8];
1437
+ return t4;
1438
+ };
1439
+ function _temp() {
1440
+ toast.error("Could not update page");
1441
+ }
1442
+ function _temp2() {
1443
+ toast.error("Could not update page layout");
1444
+ }
1445
+ function _temp6(error) {
1446
+ toast.error(error.message || "Could not upload image");
1447
+ }
1448
+ function _temp7() {
1449
+ toast.error("Could not remove image");
1450
+ }
1451
+
1452
+ //#endregion
1453
+ export { PageInfoSidebar };