camox 0.24.1 → 0.26.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 (26) hide show
  1. package/dist/core/hooks/useRequireDraftSource.js +27 -0
  2. package/dist/features/preview/CamoxPreview.d.ts +4 -0
  3. package/dist/features/preview/CamoxPreview.js +454 -181
  4. package/dist/features/preview/components/AddBlockSheet.js +79 -75
  5. package/dist/features/preview/components/AssetLightbox.js +1 -1
  6. package/dist/features/preview/components/BlockActionsPopover.js +39 -22
  7. package/dist/features/preview/components/DraftSwitchDialog.js +66 -0
  8. package/dist/features/preview/components/EditPageModal.js +9 -9
  9. package/dist/features/preview/components/LinkFieldEditor.js +1 -1
  10. package/dist/features/preview/components/Overlays.js +6 -2
  11. package/dist/features/preview/components/PageContentSheet.js +222 -190
  12. package/dist/features/preview/components/PagePicker.js +81 -3
  13. package/dist/features/preview/components/PageTree.js +418 -327
  14. package/dist/features/preview/components/PreviewToolbar.js +172 -158
  15. package/dist/features/preview/components/PublishDialog.js +111 -0
  16. package/dist/features/preview/components/useRepeatableItemActions.js +26 -20
  17. package/dist/features/preview/components/useUpdateBlockPosition.js +10 -9
  18. package/dist/features/preview/previewStore.js +38 -1
  19. package/dist/features/provider/useAdminShortcuts.js +7 -2
  20. package/dist/features/routes/pageRoute.d.ts +6 -2
  21. package/dist/features/routes/pageRoute.js +10 -6
  22. package/dist/features/vite/vite.js +6 -5
  23. package/dist/lib/normalized-data.js +87 -88
  24. package/dist/lib/queries.js +12 -6
  25. package/dist/studio.css +1 -1
  26. package/package.json +4 -4
@@ -3,7 +3,7 @@ import { actionsStore } from "../provider/actionsStore.js";
3
3
  import { useIsAuthenticated, useProjectSlug } from "../../lib/auth.js";
4
4
  import { getApiClient } from "../../lib/api-client.js";
5
5
  import { blockQueries, pageQueries, projectQueries } from "../../lib/queries.js";
6
- import { formatPathSegment } from "../../lib/utils.js";
6
+ import { cn, formatPathSegment } from "../../lib/utils.js";
7
7
  import { NormalizedDataProvider, seedBlockCaches, usePageBlocks } from "../../lib/normalized-data.js";
8
8
  import { BlockErrorBoundary } from "./components/BlockErrorBoundary.js";
9
9
  import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
@@ -11,13 +11,16 @@ import { Navbar } from "../studio/components/Navbar.js";
11
11
  import { AddBlockSheet } from "./components/AddBlockSheet.js";
12
12
  import { AgentChatSheet } from "./components/AgentChatSheet.js";
13
13
  import { CreatePageModal } from "./components/CreatePageModal.js";
14
+ import { DraftSwitchDialog } from "./components/DraftSwitchDialog.js";
14
15
  import { EditPageModal } from "./components/EditPageModal.js";
15
16
  import { PageContentSheet } from "./components/PageContentSheet.js";
16
17
  import { PagePicker } from "./components/PagePicker.js";
17
18
  import { PageTree } from "./components/PageTree.js";
18
19
  import { PeekedBlock } from "./components/PeekedBlock.js";
19
20
  import { PreviewFrame, PreviewPanel } from "./components/PreviewPanel.js";
21
+ import { PublishDialog } from "./components/PublishDialog.js";
20
22
  import { c } from "react/compiler-runtime";
23
+ import { Label } from "@camox/ui/label";
21
24
  import { keepPreviousData, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
22
25
  import { useLocation, useNavigate } from "@tanstack/react-router";
23
26
  import { useSelector } from "@xstate/store-react";
@@ -26,6 +29,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
26
29
  import { queryKeys } from "@camox/api-contract/query-keys";
27
30
  import { Button } from "@camox/ui/button";
28
31
  import { PanelContent, PanelHeader } from "@camox/ui/panel";
32
+ import { Switch } from "@camox/ui/switch";
29
33
  import { Tooltip, TooltipContent, TooltipTrigger } from "@camox/ui/tooltip";
30
34
  import { Info } from "lucide-react";
31
35
 
@@ -41,24 +45,32 @@ import { Info } from "lucide-react";
41
45
  /**
42
46
  * Lightweight queryFn for client-side refetches — only fetches structural data.
43
47
  * Used after initial SSR load when block caches are already populated.
48
+ *
49
+ * Source is threaded from the studio's source select (previewStore). Each
50
+ * source has its own cache slot, so toggling Draft↔Live is instant once both
51
+ * have been seeded. Public visitors never invalidate (no project room) so
52
+ * this query function doesn't run for them — they stay on the SSR-seeded
53
+ * 'live' data.
44
54
  */
45
- function pageStructureQueryFn(path, projectSlug) {
55
+ function pageStructureQueryFn(path, projectSlug, source) {
46
56
  return () => getApiClient().pages.getStructure({
47
57
  path,
48
- projectSlug
58
+ projectSlug,
59
+ source
49
60
  });
50
61
  }
51
62
  /**
52
63
  * Full queryFn that fetches all page data and seeds block caches.
53
64
  * Used for peeked pages where block caches may not be populated yet.
54
65
  */
55
- function pageFullQueryFn(queryClient, path, projectSlug) {
66
+ function pageFullQueryFn(queryClient, path, projectSlug, source) {
56
67
  return async () => {
57
68
  const data = await getApiClient().pages.getByPath({
58
69
  path,
59
- projectSlug
70
+ projectSlug,
71
+ source
60
72
  });
61
- seedBlockCaches(queryClient, data);
73
+ seedBlockCaches(queryClient, data, source);
62
74
  return {
63
75
  page: data.page,
64
76
  layout: data.layout,
@@ -68,15 +80,16 @@ function pageFullQueryFn(queryClient, path, projectSlug) {
68
80
  };
69
81
  }
70
82
  function usePreviewedPage() {
71
- const $ = c(22);
72
- if ($[0] !== "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f") {
73
- for (let $i = 0; $i < 22; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
74
- $[0] = "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f";
83
+ const $ = c(26);
84
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
85
+ for (let $i = 0; $i < 26; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
86
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
75
87
  }
76
88
  const { pathname } = useLocation();
77
89
  const queryClient = useQueryClient();
78
90
  const projectSlug = useProjectSlug();
79
91
  const peekedPagePathname = useSelector(previewStore, _temp);
92
+ const previewSource = useSelector(previewStore, _temp2);
80
93
  const prevPathnameRef = React.useRef(pathname);
81
94
  let t0;
82
95
  let t1;
@@ -97,49 +110,53 @@ function usePreviewedPage() {
97
110
  }
98
111
  React.useEffect(t0, t1);
99
112
  let t2;
100
- if ($[4] !== pathname) {
101
- t2 = queryKeys.pages.getByPath(pathname);
113
+ if ($[4] !== pathname || $[5] !== previewSource) {
114
+ t2 = queryKeys.pages.getByPath(pathname, previewSource);
102
115
  $[4] = pathname;
103
- $[5] = t2;
104
- } else t2 = $[5];
116
+ $[5] = previewSource;
117
+ $[6] = t2;
118
+ } else t2 = $[6];
105
119
  let t3;
106
- if ($[6] !== pathname || $[7] !== projectSlug) {
107
- t3 = pageStructureQueryFn(pathname, projectSlug);
108
- $[6] = pathname;
109
- $[7] = projectSlug;
110
- $[8] = t3;
111
- } else t3 = $[8];
120
+ if ($[7] !== pathname || $[8] !== previewSource || $[9] !== projectSlug) {
121
+ t3 = pageStructureQueryFn(pathname, projectSlug, previewSource);
122
+ $[7] = pathname;
123
+ $[8] = previewSource;
124
+ $[9] = projectSlug;
125
+ $[10] = t3;
126
+ } else t3 = $[10];
112
127
  let t4;
113
- if ($[9] !== t2 || $[10] !== t3) {
128
+ if ($[11] !== t2 || $[12] !== t3) {
114
129
  t4 = {
115
130
  queryKey: t2,
116
131
  queryFn: t3,
117
132
  staleTime: Infinity
118
133
  };
119
- $[9] = t2;
120
- $[10] = t3;
121
- $[11] = t4;
122
- } else t4 = $[11];
134
+ $[11] = t2;
135
+ $[12] = t3;
136
+ $[13] = t4;
137
+ } else t4 = $[13];
123
138
  const { data: currentPage } = useSuspenseQuery(t4);
124
139
  const isAuthenticated = useIsAuthenticated();
125
140
  let t5;
126
- if ($[12] !== peekedPagePathname) {
127
- t5 = queryKeys.pages.getByPath(peekedPagePathname ?? "");
128
- $[12] = peekedPagePathname;
129
- $[13] = t5;
130
- } else t5 = $[13];
141
+ if ($[14] !== peekedPagePathname || $[15] !== previewSource) {
142
+ t5 = queryKeys.pages.getByPath(peekedPagePathname ?? "", previewSource);
143
+ $[14] = peekedPagePathname;
144
+ $[15] = previewSource;
145
+ $[16] = t5;
146
+ } else t5 = $[16];
131
147
  const t6 = peekedPagePathname ?? "";
132
148
  let t7;
133
- if ($[14] !== projectSlug || $[15] !== queryClient || $[16] !== t6) {
134
- t7 = pageFullQueryFn(queryClient, t6, projectSlug);
135
- $[14] = projectSlug;
136
- $[15] = queryClient;
137
- $[16] = t6;
138
- $[17] = t7;
139
- } else t7 = $[17];
149
+ if ($[17] !== previewSource || $[18] !== projectSlug || $[19] !== queryClient || $[20] !== t6) {
150
+ t7 = pageFullQueryFn(queryClient, t6, projectSlug, previewSource);
151
+ $[17] = previewSource;
152
+ $[18] = projectSlug;
153
+ $[19] = queryClient;
154
+ $[20] = t6;
155
+ $[21] = t7;
156
+ } else t7 = $[21];
140
157
  const t8 = isAuthenticated && !!peekedPagePathname;
141
158
  let t9;
142
- if ($[18] !== t5 || $[19] !== t7 || $[20] !== t8) {
159
+ if ($[22] !== t5 || $[23] !== t7 || $[24] !== t8) {
143
160
  t9 = {
144
161
  queryKey: t5,
145
162
  queryFn: t7,
@@ -147,39 +164,44 @@ function usePreviewedPage() {
147
164
  placeholderData: keepPreviousData,
148
165
  staleTime: Infinity
149
166
  };
150
- $[18] = t5;
151
- $[19] = t7;
152
- $[20] = t8;
153
- $[21] = t9;
154
- } else t9 = $[21];
167
+ $[22] = t5;
168
+ $[23] = t7;
169
+ $[24] = t8;
170
+ $[25] = t9;
171
+ } else t9 = $[25];
155
172
  const { data: peekedPage } = useQuery(t9);
156
173
  return peekedPagePathname ? peekedPage ?? currentPage : currentPage;
157
174
  }
175
+ function _temp2(state_0) {
176
+ return state_0.context.previewSource;
177
+ }
158
178
  function _temp(state) {
159
179
  return state.context.peekedPagePathname;
160
180
  }
161
181
  const BlockRenderer = (t0) => {
162
- const $ = c(22);
163
- if ($[0] !== "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f") {
164
- for (let $i = 0; $i < 22; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
165
- $[0] = "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f";
182
+ const $ = c(23);
183
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
184
+ for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
185
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
166
186
  }
167
187
  const { blockId, mode, showAddBlockTop, showAddBlockBottom } = t0;
188
+ const previewSource = useSelector(previewStore, _temp3);
168
189
  let t1;
169
- if ($[1] !== blockId) {
170
- t1 = blockQueries.get(blockId);
190
+ if ($[1] !== blockId || $[2] !== previewSource) {
191
+ t1 = blockQueries.get(blockId, previewSource);
171
192
  $[1] = blockId;
172
- $[2] = t1;
173
- } else t1 = $[2];
193
+ $[2] = previewSource;
194
+ $[3] = t1;
195
+ } else t1 = $[3];
174
196
  const { data } = useSuspenseQuery(t1);
175
197
  const camoxApp = useCamoxApp();
176
198
  let t2;
177
- if ($[3] !== camoxApp || $[4] !== data.block.type) {
199
+ if ($[4] !== camoxApp || $[5] !== data.block.type) {
178
200
  t2 = camoxApp.getBlockById(data.block.type);
179
- $[3] = camoxApp;
180
- $[4] = data.block.type;
181
- $[5] = t2;
182
- } else t2 = $[5];
201
+ $[4] = camoxApp;
202
+ $[5] = data.block.type;
203
+ $[6] = t2;
204
+ } else t2 = $[6];
183
205
  const blockDef = t2;
184
206
  if (!blockDef) return null;
185
207
  const t3 = data.files;
@@ -191,7 +213,7 @@ const BlockRenderer = (t0) => {
191
213
  const t8 = data.block.settings;
192
214
  const t9 = String(data.block.position);
193
215
  let t10;
194
- if ($[6] !== data.block.id || $[7] !== data.block.type || $[8] !== t7 || $[9] !== t8 || $[10] !== t9) {
216
+ if ($[7] !== data.block.id || $[8] !== data.block.type || $[9] !== t7 || $[10] !== t8 || $[11] !== t9) {
195
217
  t10 = {
196
218
  _id: t5,
197
219
  type: t6,
@@ -199,46 +221,46 @@ const BlockRenderer = (t0) => {
199
221
  settings: t8,
200
222
  position: t9
201
223
  };
202
- $[6] = data.block.id;
203
- $[7] = data.block.type;
204
- $[8] = t7;
205
- $[9] = t8;
206
- $[10] = t9;
207
- $[11] = t10;
208
- } else t10 = $[11];
224
+ $[7] = data.block.id;
225
+ $[8] = data.block.type;
226
+ $[9] = t7;
227
+ $[10] = t8;
228
+ $[11] = t9;
229
+ $[12] = t10;
230
+ } else t10 = $[12];
209
231
  let t11;
210
- if ($[12] !== blockDef._internal.Component || $[13] !== mode || $[14] !== showAddBlockBottom || $[15] !== showAddBlockTop || $[16] !== t10) {
232
+ if ($[13] !== blockDef._internal.Component || $[14] !== mode || $[15] !== showAddBlockBottom || $[16] !== showAddBlockTop || $[17] !== t10) {
211
233
  t11 = /* @__PURE__ */ jsx(T0, {
212
234
  blockData: t10,
213
235
  mode,
214
236
  showAddBlockTop,
215
237
  showAddBlockBottom
216
238
  });
217
- $[12] = blockDef._internal.Component;
218
- $[13] = mode;
219
- $[14] = showAddBlockBottom;
220
- $[15] = showAddBlockTop;
221
- $[16] = t10;
222
- $[17] = t11;
223
- } else t11 = $[17];
239
+ $[13] = blockDef._internal.Component;
240
+ $[14] = mode;
241
+ $[15] = showAddBlockBottom;
242
+ $[16] = showAddBlockTop;
243
+ $[17] = t10;
244
+ $[18] = t11;
245
+ } else t11 = $[18];
224
246
  let t12;
225
- if ($[18] !== data.files || $[19] !== data.repeatableItems || $[20] !== t11) {
247
+ if ($[19] !== data.files || $[20] !== data.repeatableItems || $[21] !== t11) {
226
248
  t12 = /* @__PURE__ */ jsx(NormalizedDataProvider, {
227
249
  files: t3,
228
250
  repeatableItems: t4,
229
251
  children: t11
230
252
  });
231
- $[18] = data.files;
232
- $[19] = data.repeatableItems;
233
- $[20] = t11;
234
- $[21] = t12;
235
- } else t12 = $[21];
253
+ $[19] = data.files;
254
+ $[20] = data.repeatableItems;
255
+ $[21] = t11;
256
+ $[22] = t12;
257
+ } else t12 = $[22];
236
258
  return t12;
237
259
  };
238
260
  const PageContent = () => {
239
261
  const pageData = usePreviewedPage();
240
- const { pageBlocks, beforeBlocks, afterBlocks, layoutFiles, layoutItems } = usePageBlocks(pageData);
241
- const peekedBlockPosition = useSelector(previewStore, (state) => state.context.peekedBlockPosition);
262
+ const { pageBlocks, beforeBlocks, afterBlocks, layoutFiles, layoutItems } = usePageBlocks(pageData, useSelector(previewStore, (state) => state.context.previewSource));
263
+ const peekedBlockPosition = useSelector(previewStore, (state_0) => state_0.context.peekedBlockPosition);
242
264
  const displayedPositionRef = React.useRef(null);
243
265
  if (peekedBlockPosition !== null) displayedPositionRef.current = peekedBlockPosition;
244
266
  const effectivePosition = peekedBlockPosition ?? displayedPositionRef.current;
@@ -301,20 +323,207 @@ const PageContent = () => {
301
323
  children: pageBlocksContent
302
324
  });
303
325
  };
326
+ const SidebarPublishRow = (t0) => {
327
+ const $ = c(30);
328
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
329
+ for (let $i = 0; $i < 30; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
330
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
331
+ }
332
+ const { page } = t0;
333
+ const previewSource = useSelector(previewStore, _temp4);
334
+ const queryClient = useQueryClient();
335
+ const projectSlug = useProjectSlug();
336
+ const { pathname } = useLocation();
337
+ const [isPublishDialogOpen, setIsPublishDialogOpen] = React.useState(false);
338
+ const hasLiveCheckpoint = page.livePublishedCheckpointId != null;
339
+ const otherSource = previewSource === "draft" ? "live" : "draft";
340
+ const canPrefetchOther = otherSource === "draft" || hasLiveCheckpoint;
341
+ let t1;
342
+ if ($[1] !== canPrefetchOther || $[2] !== otherSource || $[3] !== pathname || $[4] !== projectSlug || $[5] !== queryClient) {
343
+ t1 = () => {
344
+ if (!canPrefetchOther) return;
345
+ queryClient.prefetchQuery({
346
+ queryKey: queryKeys.pages.getByPath(pathname, otherSource),
347
+ queryFn: pageFullQueryFn(queryClient, pathname, projectSlug, otherSource),
348
+ staleTime: Infinity
349
+ });
350
+ };
351
+ $[1] = canPrefetchOther;
352
+ $[2] = otherSource;
353
+ $[3] = pathname;
354
+ $[4] = projectSlug;
355
+ $[5] = queryClient;
356
+ $[6] = t1;
357
+ } else t1 = $[6];
358
+ const prefetchOtherSource = t1;
359
+ const canPublish = (page.status === "draft" || page.status === "modified") && previewSource === "draft";
360
+ let t2;
361
+ if ($[7] !== page.modifiedReason) {
362
+ t2 = page.modifiedReason && (page.modifiedReason.reason === "layout" || page.modifiedReason.reason === "both") ? {
363
+ layoutHandle: page.modifiedReason.layoutHandle,
364
+ affectedPagesCount: page.modifiedReason.affectedPagesCount
365
+ } : null;
366
+ $[7] = page.modifiedReason;
367
+ $[8] = t2;
368
+ } else t2 = $[8];
369
+ const layoutCascade = t2;
370
+ const t3 = !hasLiveCheckpoint;
371
+ const t4 = previewSource === "draft";
372
+ let t5;
373
+ if ($[9] !== t3 || $[10] !== t4) {
374
+ t5 = /* @__PURE__ */ jsx(Switch, {
375
+ id: "draft-content",
376
+ disabled: t3,
377
+ checked: t4,
378
+ onCheckedChange: _temp5
379
+ });
380
+ $[9] = t3;
381
+ $[10] = t4;
382
+ $[11] = t5;
383
+ } else t5 = $[11];
384
+ let t6;
385
+ if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
386
+ t6 = /* @__PURE__ */ jsx(Label, {
387
+ htmlFor: "draft-content",
388
+ children: "Draft content"
389
+ });
390
+ $[12] = t6;
391
+ } else t6 = $[12];
392
+ let t7;
393
+ if ($[13] !== prefetchOtherSource || $[14] !== t5) {
394
+ t7 = /* @__PURE__ */ jsxs("div", {
395
+ className: "flex items-center gap-2",
396
+ onMouseEnter: prefetchOtherSource,
397
+ onFocus: prefetchOtherSource,
398
+ children: [t5, t6]
399
+ });
400
+ $[13] = prefetchOtherSource;
401
+ $[14] = t5;
402
+ $[15] = t7;
403
+ } else t7 = $[15];
404
+ const t8 = !canPublish;
405
+ let t9;
406
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
407
+ t9 = () => setIsPublishDialogOpen(true);
408
+ $[16] = t9;
409
+ } else t9 = $[16];
410
+ let t10;
411
+ if ($[17] !== t8) {
412
+ t10 = /* @__PURE__ */ jsx(Button, {
413
+ type: "button",
414
+ size: "sm",
415
+ disabled: t8,
416
+ onClick: t9,
417
+ children: "Publish"
418
+ });
419
+ $[17] = t8;
420
+ $[18] = t10;
421
+ } else t10 = $[18];
422
+ let t11;
423
+ if ($[19] !== t10 || $[20] !== t7) {
424
+ t11 = /* @__PURE__ */ jsxs("div", {
425
+ className: "flex items-center justify-between gap-2",
426
+ children: [t7, t10]
427
+ });
428
+ $[19] = t10;
429
+ $[20] = t7;
430
+ $[21] = t11;
431
+ } else t11 = $[21];
432
+ const t12 = isPublishDialogOpen ? page : null;
433
+ let t13;
434
+ if ($[22] !== isPublishDialogOpen || $[23] !== layoutCascade || $[24] !== page.status || $[25] !== t12) {
435
+ t13 = /* @__PURE__ */ jsx(PublishDialog, {
436
+ page: t12,
437
+ pageStatus: page.status,
438
+ alsoPublishLayout: layoutCascade,
439
+ open: isPublishDialogOpen,
440
+ onOpenChange: setIsPublishDialogOpen
441
+ });
442
+ $[22] = isPublishDialogOpen;
443
+ $[23] = layoutCascade;
444
+ $[24] = page.status;
445
+ $[25] = t12;
446
+ $[26] = t13;
447
+ } else t13 = $[26];
448
+ let t14;
449
+ if ($[27] !== t11 || $[28] !== t13) {
450
+ t14 = /* @__PURE__ */ jsxs(Fragment, { children: [t11, t13] });
451
+ $[27] = t11;
452
+ $[28] = t13;
453
+ $[29] = t14;
454
+ } else t14 = $[29];
455
+ return t14;
456
+ };
457
+ function useHydrateDraftCache() {
458
+ const $ = c(7);
459
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
460
+ for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
461
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
462
+ }
463
+ const isAuthenticated = useIsAuthenticated();
464
+ const queryClient = useQueryClient();
465
+ const projectSlug = useProjectSlug();
466
+ const { pathname } = useLocation();
467
+ let t0;
468
+ let t1;
469
+ if ($[1] !== isAuthenticated || $[2] !== pathname || $[3] !== projectSlug || $[4] !== queryClient) {
470
+ t0 = () => {
471
+ if (!isAuthenticated) return;
472
+ let cancelled = false;
473
+ getApiClient().pages.getByPath({
474
+ path: pathname,
475
+ projectSlug,
476
+ source: "draft"
477
+ }).then((data) => {
478
+ if (cancelled) return;
479
+ seedBlockCaches(queryClient, data, "draft");
480
+ queryClient.setQueryData(queryKeys.pages.getByPath(pathname, "draft"), {
481
+ page: data.page,
482
+ layout: data.layout,
483
+ projectName: data.projectName,
484
+ project: data.project
485
+ });
486
+ }).catch(_temp6);
487
+ return () => {
488
+ cancelled = true;
489
+ };
490
+ };
491
+ t1 = [
492
+ isAuthenticated,
493
+ pathname,
494
+ projectSlug,
495
+ queryClient
496
+ ];
497
+ $[1] = isAuthenticated;
498
+ $[2] = pathname;
499
+ $[3] = projectSlug;
500
+ $[4] = queryClient;
501
+ $[5] = t0;
502
+ $[6] = t1;
503
+ } else {
504
+ t0 = $[5];
505
+ t1 = $[6];
506
+ }
507
+ React.useEffect(t0, t1);
508
+ }
509
+ function _temp6() {}
304
510
  const CamoxPreview = (t0) => {
305
- const $ = c(29);
306
- if ($[0] !== "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f") {
307
- for (let $i = 0; $i < 29; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
308
- $[0] = "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f";
511
+ const $ = c(32);
512
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
513
+ for (let $i = 0; $i < 32; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
514
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
309
515
  }
310
516
  const { children } = t0;
311
517
  const isAuthenticated = useIsAuthenticated();
312
- const isPresentationMode = useSelector(previewStore, _temp2);
313
- const isSidebarOpen = useSelector(previewStore, _temp3);
518
+ const isPresentationMode = useSelector(previewStore, _temp7);
519
+ const isSidebarOpen = useSelector(previewStore, _temp8);
520
+ const previewSource = useSelector(previewStore, _temp9);
314
521
  const pageData = usePreviewedPage();
522
+ useHydrateDraftCache();
523
+ const hasLiveCheckpoint = pageData.page.livePublishedCheckpointId != null;
315
524
  let t1;
316
525
  let t2;
317
- if ($[1] !== isAuthenticated || $[2] !== isPresentationMode) {
526
+ if ($[1] !== hasLiveCheckpoint || $[2] !== isAuthenticated || $[3] !== isPresentationMode || $[4] !== previewSource) {
318
527
  t1 = () => {
319
528
  const actions = [
320
529
  {
@@ -322,7 +531,7 @@ const CamoxPreview = (t0) => {
322
531
  label: "Hide Camox Studio",
323
532
  groupLabel: "Preview",
324
533
  checkIfAvailable: () => isAuthenticated && !isPresentationMode,
325
- execute: _temp4,
534
+ execute: _temp0,
326
535
  shortcut: {
327
536
  key: "Enter",
328
537
  withMeta: true
@@ -333,18 +542,40 @@ const CamoxPreview = (t0) => {
333
542
  label: "Show Camox Studio",
334
543
  groupLabel: "Preview",
335
544
  checkIfAvailable: () => isAuthenticated && isPresentationMode,
336
- execute: _temp5,
545
+ execute: _temp1,
337
546
  shortcut: {
338
547
  key: "Enter",
339
548
  withMeta: true
340
549
  }
341
550
  },
551
+ {
552
+ id: "preview-live-content",
553
+ label: "Preview live content",
554
+ groupLabel: "Preview",
555
+ checkIfAvailable: () => isAuthenticated && previewSource === "draft" && hasLiveCheckpoint,
556
+ execute: _temp10,
557
+ shortcut: {
558
+ key: "d",
559
+ withAlt: true
560
+ }
561
+ },
562
+ {
563
+ id: "preview-draft-content",
564
+ label: "Preview draft content",
565
+ groupLabel: "Preview",
566
+ checkIfAvailable: () => isAuthenticated && previewSource === "live",
567
+ execute: _temp11,
568
+ shortcut: {
569
+ key: "d",
570
+ withAlt: true
571
+ }
572
+ },
342
573
  {
343
574
  id: "clear-selection",
344
575
  label: "Clear selection",
345
576
  groupLabel: "Preview",
346
- checkIfAvailable: _temp6,
347
- execute: _temp7,
577
+ checkIfAvailable: _temp12,
578
+ execute: _temp13,
348
579
  shortcut: { key: "Escape" }
349
580
  }
350
581
  ];
@@ -355,126 +586,140 @@ const CamoxPreview = (t0) => {
355
586
  return () => {
356
587
  actionsStore.send({
357
588
  type: "unregisterManyActions",
358
- ids: actions.map(_temp8)
589
+ ids: actions.map(_temp14)
359
590
  });
360
591
  };
361
592
  };
362
- t2 = [isPresentationMode, isAuthenticated];
363
- $[1] = isAuthenticated;
364
- $[2] = isPresentationMode;
365
- $[3] = t1;
366
- $[4] = t2;
593
+ t2 = [
594
+ isPresentationMode,
595
+ isAuthenticated,
596
+ previewSource,
597
+ hasLiveCheckpoint
598
+ ];
599
+ $[1] = hasLiveCheckpoint;
600
+ $[2] = isAuthenticated;
601
+ $[3] = isPresentationMode;
602
+ $[4] = previewSource;
603
+ $[5] = t1;
604
+ $[6] = t2;
367
605
  } else {
368
- t1 = $[3];
369
- t2 = $[4];
606
+ t1 = $[5];
607
+ t2 = $[6];
370
608
  }
371
609
  React.useEffect(t1, t2);
372
610
  if (isPresentationMode) {
373
611
  let t3;
374
- if ($[5] !== children) {
612
+ if ($[7] !== children) {
375
613
  t3 = /* @__PURE__ */ jsx(PreviewFrame, {
376
614
  className: "h-screen w-full",
377
615
  children
378
616
  });
379
- $[5] = children;
380
- $[6] = t3;
381
- } else t3 = $[6];
617
+ $[7] = children;
618
+ $[8] = t3;
619
+ } else t3 = $[8];
382
620
  return t3;
383
621
  }
384
622
  if (!isAuthenticated) {
385
623
  let t3;
386
- if ($[7] !== children) {
624
+ if ($[9] !== children) {
387
625
  t3 = /* @__PURE__ */ jsx(Fragment, { children });
388
- $[7] = children;
389
- $[8] = t3;
390
- } else t3 = $[8];
626
+ $[9] = children;
627
+ $[10] = t3;
628
+ } else t3 = $[10];
391
629
  return t3;
392
630
  }
393
631
  let t3;
394
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
632
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
395
633
  t3 = /* @__PURE__ */ jsx(Navbar, {});
396
- $[9] = t3;
397
- } else t3 = $[9];
634
+ $[11] = t3;
635
+ } else t3 = $[11];
398
636
  let t4;
399
- if ($[10] !== isSidebarOpen || $[11] !== pageData) {
637
+ if ($[12] !== isSidebarOpen || $[13] !== pageData.page) {
400
638
  t4 = isSidebarOpen && /* @__PURE__ */ jsxs("div", {
401
639
  className: "flex w-[300px] flex-col border-r-2",
402
640
  children: [/* @__PURE__ */ jsxs(PanelHeader, {
403
- className: "flew-row flex gap-2 px-2 py-2",
404
- children: [/* @__PURE__ */ jsx(PagePicker, {}), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
405
- render: /* @__PURE__ */ jsx(Button, {
406
- type: "button",
407
- variant: "outline",
408
- size: "icon",
409
- onClick: () => previewStore.send({
410
- type: "openEditPageModal",
411
- pageId: pageData.page.id
412
- })
413
- }),
414
- children: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-4" })
415
- }), /* @__PURE__ */ jsx(TooltipContent, { children: "Page metadata, SEO and markdown" })] })]
641
+ className: cn("flex flex-col gap-2 px-2 py-2"),
642
+ children: [/* @__PURE__ */ jsxs("div", {
643
+ className: "flex flex-row gap-2",
644
+ children: [/* @__PURE__ */ jsx(PagePicker, {}), /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
645
+ render: /* @__PURE__ */ jsx(Button, {
646
+ type: "button",
647
+ variant: "outline",
648
+ size: "icon",
649
+ onClick: () => previewStore.send({
650
+ type: "openEditPageModal",
651
+ pageId: pageData.page.id
652
+ })
653
+ }),
654
+ children: /* @__PURE__ */ jsx(Info, { className: "text-muted-foreground size-4" })
655
+ }), /* @__PURE__ */ jsx(TooltipContent, { children: "Page metadata, SEO and markdown" })] })]
656
+ }), /* @__PURE__ */ jsx(SidebarPublishRow, { page: pageData.page })]
416
657
  }), /* @__PURE__ */ jsx(PanelContent, {
417
658
  className: "flex grow basis-0 flex-col gap-2 overflow-auto p-2",
418
659
  children: /* @__PURE__ */ jsx(PageTree, {})
419
660
  })]
420
661
  });
421
- $[10] = isSidebarOpen;
422
- $[11] = pageData;
423
- $[12] = t4;
424
- } else t4 = $[12];
662
+ $[12] = isSidebarOpen;
663
+ $[13] = pageData.page;
664
+ $[14] = t4;
665
+ } else t4 = $[14];
425
666
  let t5;
426
- if ($[13] !== isAuthenticated || $[14] !== isPresentationMode) {
667
+ if ($[15] !== isAuthenticated || $[16] !== isPresentationMode) {
427
668
  t5 = !isPresentationMode && isAuthenticated && /* @__PURE__ */ jsx("div", { style: {
428
669
  height: "80px",
429
670
  background: "transparent"
430
671
  } });
431
- $[13] = isAuthenticated;
432
- $[14] = isPresentationMode;
433
- $[15] = t5;
434
- } else t5 = $[15];
672
+ $[15] = isAuthenticated;
673
+ $[16] = isPresentationMode;
674
+ $[17] = t5;
675
+ } else t5 = $[17];
435
676
  let t6;
436
- if ($[16] !== children || $[17] !== t5) {
677
+ if ($[18] !== children || $[19] !== t5) {
437
678
  t6 = /* @__PURE__ */ jsxs(PreviewPanel, { children: [children, t5] });
438
- $[16] = children;
439
- $[17] = t5;
440
- $[18] = t6;
441
- } else t6 = $[18];
679
+ $[18] = children;
680
+ $[19] = t5;
681
+ $[20] = t6;
682
+ } else t6 = $[20];
442
683
  let t7;
443
- if ($[19] !== t4 || $[20] !== t6) {
684
+ if ($[21] !== t4 || $[22] !== t6) {
444
685
  t7 = /* @__PURE__ */ jsxs("div", {
445
686
  className: "flex h-full flex-row items-stretch",
446
687
  children: [t4, t6]
447
688
  });
448
- $[19] = t4;
449
- $[20] = t6;
450
- $[21] = t7;
451
- } else t7 = $[21];
689
+ $[21] = t4;
690
+ $[22] = t6;
691
+ $[23] = t7;
692
+ } else t7 = $[23];
452
693
  let t10;
453
694
  let t11;
454
695
  let t12;
696
+ let t13;
455
697
  let t8;
456
698
  let t9;
457
- if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
699
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
458
700
  t8 = /* @__PURE__ */ jsx(PageContentSheet, {});
459
701
  t9 = /* @__PURE__ */ jsx(AddBlockSheet, {});
460
702
  t10 = /* @__PURE__ */ jsx(AgentChatSheet, {});
461
703
  t11 = /* @__PURE__ */ jsx(CreatePageModal, {});
462
704
  t12 = /* @__PURE__ */ jsx(EditPageModal, {});
463
- $[22] = t10;
464
- $[23] = t11;
465
- $[24] = t12;
466
- $[25] = t8;
467
- $[26] = t9;
705
+ t13 = /* @__PURE__ */ jsx(DraftSwitchDialog, {});
706
+ $[24] = t10;
707
+ $[25] = t11;
708
+ $[26] = t12;
709
+ $[27] = t13;
710
+ $[28] = t8;
711
+ $[29] = t9;
468
712
  } else {
469
- t10 = $[22];
470
- t11 = $[23];
471
- t12 = $[24];
472
- t8 = $[25];
473
- t9 = $[26];
713
+ t10 = $[24];
714
+ t11 = $[25];
715
+ t12 = $[26];
716
+ t13 = $[27];
717
+ t8 = $[28];
718
+ t9 = $[29];
474
719
  }
475
- let t13;
476
- if ($[27] !== t7) {
477
- t13 = /* @__PURE__ */ jsxs("div", {
720
+ let t14;
721
+ if ($[30] !== t7) {
722
+ t14 = /* @__PURE__ */ jsxs("div", {
478
723
  className: "bg-background flex h-screen flex-col overflow-hidden",
479
724
  children: [
480
725
  t3,
@@ -483,19 +728,20 @@ const CamoxPreview = (t0) => {
483
728
  t9,
484
729
  t10,
485
730
  t11,
486
- t12
731
+ t12,
732
+ t13
487
733
  ]
488
734
  });
489
- $[27] = t7;
490
- $[28] = t13;
491
- } else t13 = $[28];
492
- return t13;
735
+ $[30] = t7;
736
+ $[31] = t14;
737
+ } else t14 = $[31];
738
+ return t14;
493
739
  };
494
740
  function usePreviewPagesActions() {
495
741
  const $ = c(13);
496
- if ($[0] !== "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f") {
742
+ if ($[0] !== "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8") {
497
743
  for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
498
- $[0] = "069eff6982da6e4159df17e8edcf4b3a08c7294570ccd8f684892ed8c223d55f";
744
+ $[0] = "db8d810f3b089d82690f0e1b5661e44e1ec1bfed6c53c9605ab4126a4f1e25b8";
499
745
  }
500
746
  const navigate = useNavigate();
501
747
  const { pathname } = useLocation();
@@ -535,8 +781,8 @@ function usePreviewPagesActions() {
535
781
  id: "create-page",
536
782
  label: "Create page",
537
783
  groupLabel: "Preview",
538
- checkIfAvailable: _temp9,
539
- execute: _temp0
784
+ checkIfAvailable: _temp15,
785
+ execute: _temp16
540
786
  },
541
787
  {
542
788
  id: "edit-current-page",
@@ -557,14 +803,14 @@ function usePreviewPagesActions() {
557
803
  groupLabel: "Preview",
558
804
  checkIfAvailable: () => !!pages,
559
805
  hasChildren: true,
560
- execute: _temp1
806
+ execute: _temp17
561
807
  },
562
808
  ...pages ? pages.map((page) => ({
563
809
  id: `go-to-page-${page.id}`,
564
810
  parentActionId: "go-to-page",
565
811
  label: `Go to "${page.metaTitle ?? formatPathSegment(page.pathSegment)}"`,
566
812
  groupLabel: "Preview",
567
- checkIfAvailable: _temp10,
813
+ checkIfAvailable: _temp18,
568
814
  execute: () => navigate({ to: page.fullPath })
569
815
  })) : []
570
816
  ];
@@ -575,7 +821,7 @@ function usePreviewPagesActions() {
575
821
  return () => {
576
822
  actionsStore.send({
577
823
  type: "unregisterManyActions",
578
- ids: actions.map(_temp11)
824
+ ids: actions.map(_temp19)
579
825
  });
580
826
  };
581
827
  };
@@ -595,38 +841,65 @@ function usePreviewPagesActions() {
595
841
  }
596
842
  React.useEffect(t4, t5);
597
843
  }
598
- function _temp11(a) {
844
+ function _temp19(a) {
599
845
  return a.id;
600
846
  }
601
- function _temp10() {
847
+ function _temp18() {
602
848
  return true;
603
849
  }
604
- function _temp1() {}
605
- function _temp0() {
850
+ function _temp17() {}
851
+ function _temp16() {
606
852
  return previewStore.send({ type: "openCreatePageModal" });
607
853
  }
608
- function _temp9() {
854
+ function _temp15() {
609
855
  return true;
610
856
  }
611
- function _temp2(state) {
857
+ function _temp3(state) {
858
+ return state.context.previewSource;
859
+ }
860
+ function _temp4(state) {
861
+ return state.context.previewSource;
862
+ }
863
+ function _temp5(checked) {
864
+ previewStore.send({
865
+ type: "setPreviewSource",
866
+ source: checked ? "draft" : "live"
867
+ });
868
+ }
869
+ function _temp7(state) {
612
870
  return state.context.isPresentationMode;
613
871
  }
614
- function _temp3(state_0) {
872
+ function _temp8(state_0) {
615
873
  return state_0.context.isSidebarOpen;
616
874
  }
617
- function _temp4() {
875
+ function _temp9(state_1) {
876
+ return state_1.context.previewSource;
877
+ }
878
+ function _temp0() {
618
879
  return previewStore.send({ type: "enterPresentationMode" });
619
880
  }
620
- function _temp5() {
881
+ function _temp1() {
621
882
  return previewStore.send({ type: "exitPresentationMode" });
622
883
  }
623
- function _temp6() {
884
+ function _temp10() {
885
+ return previewStore.send({
886
+ type: "setPreviewSource",
887
+ source: "live"
888
+ });
889
+ }
890
+ function _temp11() {
891
+ return previewStore.send({
892
+ type: "setPreviewSource",
893
+ source: "draft"
894
+ });
895
+ }
896
+ function _temp12() {
624
897
  return true;
625
898
  }
626
- function _temp7() {
899
+ function _temp13() {
627
900
  console.log("clear selection");
628
901
  }
629
- function _temp8(a) {
902
+ function _temp14(a) {
630
903
  return a.id;
631
904
  }
632
905