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
@@ -1,908 +0,0 @@
1
- import { trackClientEvent } from "../../../lib/telemetry-client.js";
2
- import { previewStore } from "../previewStore.js";
3
- import { useProjectSlug } from "../../../lib/auth.js";
4
- import { blockQueries, layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
5
- import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
6
- import { PageLocationFieldset } from "./PageLocationFieldset.js";
7
- import { PageNicknameField } from "./PageNicknameField.js";
8
- import { UploadDropZone } from "../../content/components/UploadDropZone.js";
9
- import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
10
- import { ShikiMarkdown } from "./ShikiMarkdown.js";
11
- import { c } from "react/compiler-runtime";
12
- import { Label } from "@camox/ui/label";
13
- import { toast } from "@camox/ui/toaster";
14
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
15
- import { useNavigate } from "@tanstack/react-router";
16
- import { useSelector } from "@xstate/store-react";
17
- import * as React from "react";
18
- import { jsx, jsxs } from "react/jsx-runtime";
19
- import { Button } from "@camox/ui/button";
20
- import { Switch } from "@camox/ui/switch";
21
- import { Tooltip, TooltipContent, TooltipTrigger } from "@camox/ui/tooltip";
22
- import { Globe, Info, Trash2, Upload } from "lucide-react";
23
- import { Alert, AlertDescription, AlertTitle } from "@camox/ui/alert";
24
- import { Spinner } from "@camox/ui/spinner";
25
- import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@camox/ui/dialog";
26
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@camox/ui/select";
27
- import { useForm } from "@tanstack/react-form";
28
-
29
- //#region src/features/preview/components/PageMetadataModal.tsx
30
- const PageMetadataModal = () => {
31
- const $ = c(3);
32
- if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
33
- for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
34
- $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
35
- }
36
- const editingPageId = useSelector(previewStore, _temp);
37
- let t0;
38
- if ($[1] !== editingPageId) {
39
- t0 = /* @__PURE__ */ jsx(PageMetadataModalContent, { pageId: editingPageId });
40
- $[1] = editingPageId;
41
- $[2] = t0;
42
- } else t0 = $[2];
43
- return t0;
44
- };
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;
52
- const projectSlug = useProjectSlug();
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);
144
- const camoxApp = useCamoxApp();
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];
164
- const form = useForm({
165
- defaultValues: t20,
166
- onSubmit: async (values) => {
167
- if (!page) return;
168
- try {
169
- const nickname = values.value.nickname.trim();
170
- if (!nickname) {
171
- toast.error("Page nickname is required");
172
- return;
173
- }
174
- const { fullPath } = await updatePage.mutateAsync({
175
- id: page.id,
176
- nickname,
177
- pathSegment: values.value.pathSegment,
178
- parentPageId: values.value.parentPageId
179
- });
180
- if (values.value.layoutId) await setLayout.mutateAsync({
181
- id: page.id,
182
- layoutId: values.value.layoutId
183
- });
184
- trackClientEvent("page_updated", {
185
- projectId: page.projectId,
186
- changes: {
187
- nickname: nickname !== page.nickname,
188
- path: values.value.pathSegment !== page.pathSegment,
189
- layout: values.value.layoutId !== page.layoutId,
190
- parent: values.value.parentPageId !== page.parentPageId
191
- }
192
- });
193
- const displayName = nickname;
194
- toast.success(`Updated ${displayName} page`);
195
- previewStore.send({ type: "closeEditPageModal" });
196
- form.reset();
197
- await navigate({ to: fullPath });
198
- } catch (t21) {
199
- console.error("Failed to update page:", t21);
200
- toast.error("Could not update page");
201
- }
202
- }
203
- });
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);
235
- const isOpen = pageId != null && !!page;
236
- const isRootPage = page?.fullPath === "/";
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",
288
- children: [
289
- /* @__PURE__ */ jsx(form.Field, {
290
- name: "nickname",
291
- children: _temp3
292
- }),
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
- })
309
- })
310
- }),
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
- })]
327
- })
328
- }),
329
- /* @__PURE__ */ jsx(form.Subscribe, {
330
- selector: _temp4,
331
- children: _temp5
332
- })
333
- ]
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;
456
- };
457
- function truncateText(text, maxLen) {
458
- if (text.length <= maxLen) return text;
459
- return text.slice(0, maxLen) + "...";
460
- }
461
- const SearchEnginePreview = (t0) => {
462
- const $ = c(17);
463
- if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
464
- for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
465
- $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
466
- }
467
- const { page, metaTitle, metaDescription } = t0;
468
- const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
469
- let t1;
470
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
471
- t1 = /* @__PURE__ */ jsx(Label, { children: "Search engine preview" });
472
- $[1] = t1;
473
- } else t1 = $[1];
474
- let t2;
475
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
476
- t2 = /* @__PURE__ */ jsxs("div", {
477
- className: "flex items-center gap-1.5",
478
- children: [t1, /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
479
- delay: 50,
480
- render: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-3.5" })
481
- }), /* @__PURE__ */ jsx(TooltipContent, { children: "Titles are cropped after 60 characters and descriptions after 155, like on Google Search results." })] })]
482
- });
483
- $[2] = t2;
484
- } else t2 = $[2];
485
- let t3;
486
- if ($[3] !== url) {
487
- t3 = /* @__PURE__ */ jsx("p", {
488
- className: "text-muted-foreground truncate text-xs",
489
- children: url
490
- });
491
- $[3] = url;
492
- $[4] = t3;
493
- } else t3 = $[4];
494
- const t4 = metaTitle || "Untitled";
495
- let t5;
496
- if ($[5] !== t4) {
497
- t5 = truncateText(t4, 60);
498
- $[5] = t4;
499
- $[6] = t5;
500
- } else t5 = $[6];
501
- let t6;
502
- if ($[7] !== t5) {
503
- t6 = /* @__PURE__ */ jsx("p", {
504
- className: "text-base font-medium text-blue-600 dark:text-blue-400",
505
- children: t5
506
- });
507
- $[7] = t5;
508
- $[8] = t6;
509
- } else t6 = $[8];
510
- const t7 = metaDescription || "No description";
511
- let t8;
512
- if ($[9] !== t7) {
513
- t8 = truncateText(t7, 155);
514
- $[9] = t7;
515
- $[10] = t8;
516
- } else t8 = $[10];
517
- let t9;
518
- if ($[11] !== t8) {
519
- t9 = /* @__PURE__ */ jsx("p", {
520
- className: "text-muted-foreground line-clamp-2 text-xs",
521
- children: t8
522
- });
523
- $[11] = t8;
524
- $[12] = t9;
525
- } else t9 = $[12];
526
- let t10;
527
- if ($[13] !== t3 || $[14] !== t6 || $[15] !== t9) {
528
- t10 = /* @__PURE__ */ jsxs("div", {
529
- className: "space-y-1 pt-2",
530
- children: [t2, /* @__PURE__ */ jsxs("div", {
531
- className: "border-border space-y-0.5 rounded-lg border p-3",
532
- children: [
533
- t3,
534
- t6,
535
- t9
536
- ]
537
- })]
538
- });
539
- $[13] = t3;
540
- $[14] = t6;
541
- $[15] = t9;
542
- $[16] = t10;
543
- } else t10 = $[16];
544
- return t10;
545
- };
546
- const SocialPreviewSection = (t0) => {
547
- const $ = c(60);
548
- if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
549
- for (let $i = 0; $i < 60; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
550
- $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
551
- }
552
- const { page, metaTitle, metaDescription, layoutId, projectName } = t0;
553
- const pageMetaTitle = page.metaTitle ?? page.pathSegment;
554
- let t1;
555
- if ($[1] !== layoutId || $[2] !== page.metaDescription || $[3] !== pageMetaTitle || $[4] !== projectName) {
556
- t1 = new URLSearchParams({
557
- ...layoutId && { layoutId },
558
- title: pageMetaTitle,
559
- ...page.metaDescription && { description: page.metaDescription },
560
- ...projectName && { projectName }
561
- }).toString();
562
- $[1] = layoutId;
563
- $[2] = page.metaDescription;
564
- $[3] = pageMetaTitle;
565
- $[4] = projectName;
566
- $[5] = t1;
567
- } else t1 = $[5];
568
- const generatedOgImage = `/og?${t1}`;
569
- const ogImage = page.customOgImageUrl ?? generatedOgImage;
570
- const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
571
- const fileInputRef = React.useRef(null);
572
- const queryClient = useQueryClient();
573
- let t2;
574
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
575
- t2 = pageMutations.uploadCustomOgImage();
576
- $[6] = t2;
577
- } else t2 = $[6];
578
- let t3;
579
- if ($[7] !== page.id || $[8] !== queryClient) {
580
- t3 = {
581
- ...t2,
582
- onSuccess: () => {
583
- queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
584
- trackClientEvent("page_custom_og_image_uploaded", { pageId: page.id });
585
- },
586
- onError: _temp6
587
- };
588
- $[7] = page.id;
589
- $[8] = queryClient;
590
- $[9] = t3;
591
- } else t3 = $[9];
592
- const uploadCustomOgImage = useMutation(t3);
593
- let t4;
594
- if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
595
- t4 = pageMutations.deleteCustomOgImage();
596
- $[10] = t4;
597
- } else t4 = $[10];
598
- let t5;
599
- if ($[11] !== page.id || $[12] !== queryClient) {
600
- t5 = {
601
- ...t4,
602
- onSuccess: () => {
603
- queryClient.invalidateQueries({ queryKey: pageQueries.getById(page.id).queryKey });
604
- trackClientEvent("page_custom_og_image_removed", { pageId: page.id });
605
- },
606
- onError: _temp7
607
- };
608
- $[11] = page.id;
609
- $[12] = queryClient;
610
- $[13] = t5;
611
- } else t5 = $[13];
612
- const deleteCustomOgImage = useMutation(t5);
613
- const hasCustomImage = !!page.customOgImageUrl;
614
- const isBusy = uploadCustomOgImage.isPending || deleteCustomOgImage.isPending;
615
- let t6;
616
- if ($[14] !== page.id || $[15] !== uploadCustomOgImage) {
617
- t6 = (files) => {
618
- const file = files[0];
619
- if (file) uploadCustomOgImage.mutate({
620
- pageId: page.id,
621
- file
622
- });
623
- };
624
- $[14] = page.id;
625
- $[15] = uploadCustomOgImage;
626
- $[16] = t6;
627
- } else t6 = $[16];
628
- const handleFiles = t6;
629
- let t7;
630
- if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
631
- t7 = /* @__PURE__ */ jsx(Label, { children: "Social preview" });
632
- $[17] = t7;
633
- } else t7 = $[17];
634
- let t8;
635
- if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
636
- t8 = () => fileInputRef.current?.click();
637
- $[18] = t8;
638
- } else t8 = $[18];
639
- let t9;
640
- if ($[19] !== uploadCustomOgImage.isPending) {
641
- t9 = uploadCustomOgImage.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Upload, { className: "size-3.5" });
642
- $[19] = uploadCustomOgImage.isPending;
643
- $[20] = t9;
644
- } else t9 = $[20];
645
- const t10 = hasCustomImage ? "Replace custom image" : "Upload custom image";
646
- let t11;
647
- if ($[21] !== isBusy || $[22] !== t10 || $[23] !== t9) {
648
- t11 = /* @__PURE__ */ jsxs(Button, {
649
- type: "button",
650
- variant: "secondary",
651
- size: "sm",
652
- disabled: isBusy,
653
- onClick: t8,
654
- children: [t9, t10]
655
- });
656
- $[21] = isBusy;
657
- $[22] = t10;
658
- $[23] = t9;
659
- $[24] = t11;
660
- } else t11 = $[24];
661
- let t12;
662
- if ($[25] !== deleteCustomOgImage || $[26] !== hasCustomImage || $[27] !== isBusy || $[28] !== page.id) {
663
- t12 = hasCustomImage && /* @__PURE__ */ jsxs(Button, {
664
- type: "button",
665
- variant: "ghost",
666
- disabled: isBusy,
667
- onClick: () => deleteCustomOgImage.mutate({ pageId: page.id }),
668
- "aria-label": "Remove custom image",
669
- children: [
670
- deleteCustomOgImage.isPending ? /* @__PURE__ */ jsx(Spinner, { className: "text-muted-foreground" }) : /* @__PURE__ */ jsx(Trash2, { className: "text-muted-foreground" }),
671
- " ",
672
- "Clear"
673
- ]
674
- });
675
- $[25] = deleteCustomOgImage;
676
- $[26] = hasCustomImage;
677
- $[27] = isBusy;
678
- $[28] = page.id;
679
- $[29] = t12;
680
- } else t12 = $[29];
681
- let t13;
682
- if ($[30] !== handleFiles) {
683
- t13 = /* @__PURE__ */ jsx("input", {
684
- type: "file",
685
- ref: fileInputRef,
686
- className: "hidden",
687
- accept: "image/jpeg,image/png,image/gif,image/webp",
688
- onChange: (e) => {
689
- if (e.target.files) handleFiles(e.target.files);
690
- e.target.value = "";
691
- }
692
- });
693
- $[30] = handleFiles;
694
- $[31] = t13;
695
- } else t13 = $[31];
696
- let t14;
697
- if ($[32] !== t11 || $[33] !== t12 || $[34] !== t13) {
698
- t14 = /* @__PURE__ */ jsxs("div", {
699
- className: "flex items-center gap-2",
700
- children: [
701
- t11,
702
- t12,
703
- t13
704
- ]
705
- });
706
- $[32] = t11;
707
- $[33] = t12;
708
- $[34] = t13;
709
- $[35] = t14;
710
- } else t14 = $[35];
711
- const t15 = hasCustomImage ? "Drop image to replace" : "Drop image to upload";
712
- let t16;
713
- if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
714
- t16 = { aspectRatio: "1200 / 630" };
715
- $[36] = t16;
716
- } else t16 = $[36];
717
- let t17;
718
- if ($[37] !== ogImage) {
719
- t17 = /* @__PURE__ */ jsx("img", {
720
- src: ogImage,
721
- alt: "",
722
- className: "w-full object-cover",
723
- style: t16
724
- });
725
- $[37] = ogImage;
726
- $[38] = t17;
727
- } else t17 = $[38];
728
- let t18;
729
- if ($[39] !== handleFiles || $[40] !== t15 || $[41] !== t17) {
730
- t18 = /* @__PURE__ */ jsx(UploadDropZone, {
731
- onDrop: handleFiles,
732
- label: t15,
733
- className: "block",
734
- children: t17
735
- });
736
- $[39] = handleFiles;
737
- $[40] = t15;
738
- $[41] = t17;
739
- $[42] = t18;
740
- } else t18 = $[42];
741
- const t19 = metaTitle || "Untitled";
742
- let t20;
743
- if ($[43] !== t19) {
744
- t20 = /* @__PURE__ */ jsx("p", {
745
- className: "text-foreground truncate text-sm font-semibold",
746
- children: t19
747
- });
748
- $[43] = t19;
749
- $[44] = t20;
750
- } else t20 = $[44];
751
- const t21 = metaDescription || "No description";
752
- let t22;
753
- if ($[45] !== t21) {
754
- t22 = /* @__PURE__ */ jsx("p", {
755
- className: "text-muted-foreground line-clamp-2 text-xs",
756
- children: t21
757
- });
758
- $[45] = t21;
759
- $[46] = t22;
760
- } else t22 = $[46];
761
- let t23;
762
- if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
763
- t23 = /* @__PURE__ */ jsx(Globe, { className: "size-3 shrink-0" });
764
- $[47] = t23;
765
- } else t23 = $[47];
766
- let t24;
767
- if ($[48] !== url) {
768
- t24 = /* @__PURE__ */ jsx("div", {
769
- className: "pt-1.5",
770
- children: /* @__PURE__ */ jsxs("p", {
771
- className: "text-muted-foreground flex items-center gap-1 text-xs",
772
- children: [t23, /* @__PURE__ */ jsx("span", {
773
- className: "truncate",
774
- children: url
775
- })]
776
- })
777
- });
778
- $[48] = url;
779
- $[49] = t24;
780
- } else t24 = $[49];
781
- let t25;
782
- if ($[50] !== t20 || $[51] !== t22 || $[52] !== t24) {
783
- t25 = /* @__PURE__ */ jsxs("div", {
784
- className: "space-y-1.5 border-t px-3 py-2.5",
785
- children: [
786
- t20,
787
- t22,
788
- t24
789
- ]
790
- });
791
- $[50] = t20;
792
- $[51] = t22;
793
- $[52] = t24;
794
- $[53] = t25;
795
- } else t25 = $[53];
796
- let t26;
797
- if ($[54] !== t18 || $[55] !== t25) {
798
- t26 = /* @__PURE__ */ jsxs("div", {
799
- className: "border-border max-w-xl overflow-hidden rounded-lg border",
800
- children: [t18, t25]
801
- });
802
- $[54] = t18;
803
- $[55] = t25;
804
- $[56] = t26;
805
- } else t26 = $[56];
806
- let t27;
807
- if ($[57] !== t14 || $[58] !== t26) {
808
- t27 = /* @__PURE__ */ jsxs("div", {
809
- className: "space-y-2 pt-2",
810
- children: [
811
- t7,
812
- t14,
813
- t26
814
- ]
815
- });
816
- $[57] = t14;
817
- $[58] = t26;
818
- $[59] = t27;
819
- } else t27 = $[59];
820
- return t27;
821
- };
822
- const PageMarkdownPreview = (t0) => {
823
- const $ = c(9);
824
- if ($[0] !== "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8") {
825
- for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
826
- $[0] = "5a8f7b6ce5fca8ad19dd3940040a627aa1141a2cb6ff61a0cb7eafe6485f2ad8";
827
- }
828
- const { pageId, metaTitle, metaDescription } = t0;
829
- let t1;
830
- if ($[1] !== pageId) {
831
- t1 = blockQueries.getPageMarkdown(pageId);
832
- $[1] = pageId;
833
- $[2] = t1;
834
- } else t1 = $[2];
835
- const { data: markdown } = useQuery(t1);
836
- if (markdown === void 0) {
837
- let t2;
838
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
839
- t2 = /* @__PURE__ */ jsxs("div", {
840
- className: "text-muted-foreground flex items-center gap-2 py-2 text-sm",
841
- children: [/* @__PURE__ */ jsx(Spinner, { className: "size-3.5" }), "Loading..."]
842
- });
843
- $[3] = t2;
844
- } else t2 = $[3];
845
- return t2;
846
- }
847
- const t2 = `title: "${metaTitle}"`;
848
- const t3 = `description: "${metaDescription}"`;
849
- let frontmatterLines;
850
- if ($[4] !== t2 || $[5] !== t3) {
851
- frontmatterLines = [
852
- "---",
853
- t2,
854
- t3
855
- ];
856
- frontmatterLines.push("---");
857
- $[4] = t2;
858
- $[5] = t3;
859
- $[6] = frontmatterLines;
860
- } else frontmatterLines = $[6];
861
- const fullMarkdown = frontmatterLines.join("\n") + "\n\n" + (markdown ?? "");
862
- let t4;
863
- if ($[7] !== fullMarkdown) {
864
- t4 = /* @__PURE__ */ jsx(ShikiMarkdown, { code: fullMarkdown });
865
- $[7] = fullMarkdown;
866
- $[8] = t4;
867
- } else t4 = $[8];
868
- return t4;
869
- };
870
- function _temp(state) {
871
- return state.context.editingPageId;
872
- }
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) {
901
- toast.error(error.message || "Could not upload image");
902
- }
903
- function _temp7() {
904
- toast.error("Could not remove image");
905
- }
906
-
907
- //#endregion
908
- export { PageMetadataModal };