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
@@ -10,9 +10,9 @@ import { queryKeys } from "@camox/api-contract/query-keys";
10
10
  //#region src/features/preview/components/useUpdateBlockPosition.ts
11
11
  function useUpdateBlockPosition() {
12
12
  const $ = c(5);
13
- if ($[0] !== "5a96eb36dc11e719c3b59bd9e9b0341b45aea01f26dbb80c97c8a13ec4179126") {
13
+ if ($[0] !== "13182e6fc3bf905233106f71f311ee66fbdf35afd4c8eee1eed03bd0725a9e4a") {
14
14
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
15
- $[0] = "5a96eb36dc11e719c3b59bd9e9b0341b45aea01f26dbb80c97c8a13ec4179126";
15
+ $[0] = "13182e6fc3bf905233106f71f311ee66fbdf35afd4c8eee1eed03bd0725a9e4a";
16
16
  }
17
17
  const queryClient = useQueryClient();
18
18
  const { pathname } = useLocation();
@@ -27,12 +27,13 @@ function useUpdateBlockPosition() {
27
27
  t1 = {
28
28
  ...t0,
29
29
  onMutate: (variables) => {
30
- const pageQueryKey = queryKeys.pages.getByPath(pagePathname);
30
+ const pageQueryKey = queryKeys.pages.getByPath(pagePathname, "draft");
31
31
  const previousPage = queryClient.getQueryData(pageQueryKey);
32
32
  if (!previousPage) return {};
33
33
  const newPosition = generateKeyBetween(variables.afterPosition ?? null, variables.beforePosition ?? null);
34
- const prevBundle = queryClient.getQueryData(queryKeys.blocks.get(variables.id));
35
- if (prevBundle) queryClient.setQueryData(queryKeys.blocks.get(variables.id), {
34
+ const blockKey = queryKeys.blocks.get(variables.id, "draft");
35
+ const prevBundle = queryClient.getQueryData(blockKey);
36
+ if (prevBundle) queryClient.setQueryData(blockKey, {
36
37
  ...prevBundle,
37
38
  block: {
38
39
  ...prevBundle.block,
@@ -43,7 +44,7 @@ function useUpdateBlockPosition() {
43
44
  const positions = /* @__PURE__ */ new Map();
44
45
  for (const id of blockIds) if (id === variables.id) positions.set(id, newPosition);
45
46
  else {
46
- const bundle = queryClient.getQueryData(queryKeys.blocks.get(id));
47
+ const bundle = queryClient.getQueryData(queryKeys.blocks.get(id, "draft"));
47
48
  if (bundle) positions.set(id, bundle.block.position);
48
49
  }
49
50
  const sortedIds = [...blockIds].sort((a, b) => {
@@ -65,11 +66,11 @@ function useUpdateBlockPosition() {
65
66
  };
66
67
  },
67
68
  onError: (_error, variables_0, context) => {
68
- if (context?.previousPage) queryClient.setQueryData(queryKeys.pages.getByPath(pagePathname), context.previousPage);
69
- if (context?.prevBundle) queryClient.setQueryData(queryKeys.blocks.get(variables_0.id), context.prevBundle);
69
+ if (context?.previousPage) queryClient.setQueryData(queryKeys.pages.getByPath(pagePathname, "draft"), context.previousPage);
70
+ if (context?.prevBundle) queryClient.setQueryData(queryKeys.blocks.get(variables_0.id, "draft"), context.prevBundle);
70
71
  },
71
72
  onSettled: () => {
72
- queryClient.invalidateQueries({ queryKey: queryKeys.pages.getByPath(pagePathname) });
73
+ queryClient.invalidateQueries({ queryKey: queryKeys.pages.getByPath(pagePathname, "draft") });
73
74
  }
74
75
  };
75
76
  $[2] = pagePathname;
@@ -33,13 +33,16 @@ const previewStore = createStore({
33
33
  isCreatePageModalOpen: false,
34
34
  editingPageId: null,
35
35
  isContentLocked: false,
36
+ prePreviewLockState: null,
37
+ isDraftSwitchDialogOpen: false,
36
38
  isMobileMode: false,
37
39
  peekedBlock: null,
38
40
  peekedBlockPosition: null,
39
41
  peekedPagePathname: null,
40
42
  skipPeekedBlockExitAnimation: false,
41
43
  selection: null,
42
- iframeElement: null
44
+ iframeElement: null,
45
+ previewSource: "draft"
43
46
  },
44
47
  on: {
45
48
  enterPresentationMode: (context, _, enqueue) => {
@@ -71,6 +74,7 @@ const previewStore = createStore({
71
74
  };
72
75
  },
73
76
  toggleLockContent: (context, _, enqueue) => {
77
+ if (context.previewSource !== "draft") return context;
74
78
  enqueue.effect(() => {
75
79
  toast(context.isContentLocked ? "Enabling edits" : "Preventing edits");
76
80
  });
@@ -271,6 +275,39 @@ const previewStore = createStore({
271
275
  setIframeElement: (context, event) => ({
272
276
  ...context,
273
277
  iframeElement: event.element
278
+ }),
279
+ setPreviewSource: (context, event, enqueue) => {
280
+ if (event.source === context.previewSource) return context;
281
+ enqueue.effect(() => {
282
+ toast(event.source === "draft" ? "Previewing draft content" : "Previewing live content", { duration: 2500 });
283
+ });
284
+ if (event.source !== "draft" && context.previewSource === "draft") return {
285
+ ...context,
286
+ previewSource: event.source,
287
+ prePreviewLockState: context.isContentLocked,
288
+ isContentLocked: true
289
+ };
290
+ if (event.source === "draft" && context.previewSource !== "draft") return {
291
+ ...context,
292
+ previewSource: "draft",
293
+ isContentLocked: context.prePreviewLockState ?? false,
294
+ prePreviewLockState: null
295
+ };
296
+ return {
297
+ ...context,
298
+ previewSource: event.source
299
+ };
300
+ },
301
+ requestDraftSwitch: (context) => {
302
+ if (context.previewSource === "draft") return context;
303
+ return {
304
+ ...context,
305
+ isDraftSwitchDialogOpen: true
306
+ };
307
+ },
308
+ dismissDraftSwitch: (context) => ({
309
+ ...context,
310
+ isDraftSwitchDialogOpen: false
274
311
  })
275
312
  }
276
313
  });
@@ -11,9 +11,9 @@ import * as React from "react";
11
11
  */
12
12
  function useAdminShortcuts() {
13
13
  const $ = c(4);
14
- if ($[0] !== "8aa9f7b5d024a727491a97f8449b1e7300ebf32446cf1094a0f4557cc8d754f4") {
14
+ if ($[0] !== "ff9772b422e4fa94d361aac01db06ff7648c4018d1a51f451cd805e9e0430ce4") {
15
15
  for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
16
- $[0] = "8aa9f7b5d024a727491a97f8449b1e7300ebf32446cf1094a0f4557cc8d754f4";
16
+ $[0] = "ff9772b422e4fa94d361aac01db06ff7648c4018d1a51f451cd805e9e0430ce4";
17
17
  }
18
18
  const actions = useSelector(actionsStore, _temp);
19
19
  const previousLockState = React.useRef(null);
@@ -26,6 +26,10 @@ function useAdminShortcuts() {
26
26
  if (event.key.toLowerCase() === "l" && !event.metaKey && !event.altKey && !event.shiftKey) {
27
27
  if (event.repeat) return;
28
28
  if (checkIfInputFocused()) return;
29
+ if (previewStore.getSnapshot().context.previewSource !== "draft") {
30
+ event.preventDefault();
31
+ return;
32
+ }
29
33
  event.preventDefault();
30
34
  if (previousLockState.current === null) {
31
35
  lockKeyDownTime.current = Date.now();
@@ -61,6 +65,7 @@ function useAdminShortcuts() {
61
65
  };
62
66
  const handleMessage = (event_1) => {
63
67
  if (event_1.data?.type === "holdLockContent") {
68
+ if (previewStore.getSnapshot().context.previewSource !== "draft") return;
64
69
  if (previousLockState.current === null) {
65
70
  lockKeyDownTime.current = Date.now();
66
71
  previousLockState.current = previewStore.getSnapshot().context.isContentLocked;
@@ -22,21 +22,25 @@ declare function createPageLoader(apiUrl: string, projectSlug: string, environme
22
22
  }) => Promise<{
23
23
  page: {
24
24
  page: {
25
+ status: undefined;
26
+ modifiedReason: undefined | null;
25
27
  blockIds: number[];
26
28
  id: number;
29
+ createdAt: number;
30
+ updatedAt: number;
27
31
  projectId: number;
28
32
  environmentId: number;
29
33
  pathSegment: string;
30
34
  fullPath: string;
31
35
  parentPageId: number | null;
32
36
  layoutId: number;
37
+ livePublishedCheckpointId: number | null;
38
+ contentUpdatedAt: number;
33
39
  metaTitle: string | null;
34
40
  metaDescription: string | null;
35
41
  aiSeoEnabled: boolean | null;
36
42
  customOgImageBlobId: string | null;
37
43
  customOgImageUrl: string | null;
38
- createdAt: number;
39
- updatedAt: number;
40
44
  };
41
45
  layout: {
42
46
  id: number;
@@ -45,7 +45,8 @@ function createMarkdownMiddleware(apiUrl, projectSlug, environmentName) {
45
45
  try {
46
46
  const page = await api.pages.getByPath({
47
47
  path: url.pathname,
48
- projectSlug
48
+ projectSlug,
49
+ source: "live"
49
50
  });
50
51
  const { markdown } = await api.blocks.getPageMarkdown({ pageId: page.page.id });
51
52
  if (markdown) {
@@ -68,13 +69,16 @@ function createPageLoader(apiUrl, projectSlug, environmentName) {
68
69
  return async ({ location, context }) => {
69
70
  try {
70
71
  const [page, origin] = await Promise.all([context.queryClient.ensureQueryData({
71
- queryKey: queryKeys.pages.getByPath(location.pathname),
72
+ queryKey: queryKeys.pages.getByPath(location.pathname, "live"),
72
73
  queryFn: async () => {
73
74
  const [data, pagesList] = await Promise.all([serverApi.pages.getByPath({
74
75
  path: location.pathname,
75
- projectSlug
76
+ projectSlug,
77
+ source: "live"
76
78
  }), serverApi.pages.listBySlug({ projectSlug }).catch(() => null)]);
77
- seedBlockCaches(context.queryClient, data);
79
+ seedBlockCaches(context.queryClient, data, "live");
80
+ seedBlockCaches(context.queryClient, data, "draft");
81
+ context.queryClient.setQueryData(queryKeys.pages.getByPath(location.pathname, "draft"), data);
78
82
  if (pagesList) context.queryClient.setQueryData(queryKeys.pages.list, pagesList);
79
83
  return {
80
84
  page: data.page,
@@ -152,9 +156,9 @@ function createPageHead(camoxApp) {
152
156
  }
153
157
  const PageRouteComponent = () => {
154
158
  const $ = c(2);
155
- if ($[0] !== "858ec55c5e5a82d2aa9c37c6b5b7f1c0a2d1cff69ec415b2b53199f5bf1faa69") {
159
+ if ($[0] !== "70af43df8dd9dfc07ba240c4b5ef667ad871db6e9cbe22eb8e3647d7a89af86f") {
156
160
  for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
157
- $[0] = "858ec55c5e5a82d2aa9c37c6b5b7f1c0a2d1cff69ec415b2b53199f5bf1faa69";
161
+ $[0] = "70af43df8dd9dfc07ba240c4b5ef667ad871db6e9cbe22eb8e3647d7a89af86f";
158
162
  }
159
163
  let t0;
160
164
  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
@@ -37,10 +37,12 @@ function readAuthEmail(authenticationUrl) {
37
37
  }
38
38
  /**
39
39
  * Drop a sidecar at `<root>/node_modules/.camox/runtime.json` so the `camox`
40
- * CLI can pick up the same projectSlug / apiUrl / authenticationUrl /
41
- * environmentName the plugin actually used. The CLI treats the vite config
42
- * as the source of truth — there is no other reliable way to recover these
43
- * values from outside vite.
40
+ * CLI can pick up the same projectSlug / apiUrl / authenticationUrl the
41
+ * plugin actually used. The CLI treats the vite config as the source of
42
+ * truth for those values — there is no other reliable way to recover them
43
+ * from outside vite. The environment is *not* written here: the CLI derives
44
+ * `dev:<email>` from auth at call time and requires `--production` for prod,
45
+ * so a stale build sidecar can't silently route writes to production.
44
46
  */
45
47
  function writeRuntimeSidecar(root, data) {
46
48
  const dir = join(root, "node_modules", ".camox");
@@ -168,7 +170,6 @@ function camox(options) {
168
170
  projectSlug: options.projectSlug,
169
171
  apiUrl,
170
172
  authenticationUrl,
171
- environmentName,
172
173
  disableTelemetry: !!options.disableTelemetry
173
174
  });
174
175
  if (!disableCodeGen) {
@@ -11,9 +11,9 @@ const NormalizedDataContext = React.createContext({
11
11
  });
12
12
  const NormalizedDataProvider = (t0) => {
13
13
  const $ = c(13);
14
- if ($[0] !== "c508cbfbcda1ea1312463b6cbebcd66332f3346f51c02c09c35687c430a19469") {
14
+ if ($[0] !== "08bed558b0a428c072e8a0761d5efbb6bd49b29518144153bf64ed61004f9dda") {
15
15
  for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
16
- $[0] = "c508cbfbcda1ea1312463b6cbebcd66332f3346f51c02c09c35687c430a19469";
16
+ $[0] = "08bed558b0a428c072e8a0761d5efbb6bd49b29518144153bf64ed61004f9dda";
17
17
  }
18
18
  const { files, repeatableItems, children } = t0;
19
19
  let t1;
@@ -72,18 +72,19 @@ function useStableArray(next) {
72
72
  if (prev !== next && (prev.length !== next.length || prev.some((v, i) => v !== next[i]))) ref.current = next;
73
73
  return ref.current;
74
74
  }
75
- function usePageBlocks(pageStructure) {
76
- const $ = c(36);
77
- if ($[0] !== "c508cbfbcda1ea1312463b6cbebcd66332f3346f51c02c09c35687c430a19469") {
78
- for (let $i = 0; $i < 36; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
79
- $[0] = "c508cbfbcda1ea1312463b6cbebcd66332f3346f51c02c09c35687c430a19469";
75
+ function usePageBlocks(pageStructure, t0) {
76
+ const $ = c(37);
77
+ if ($[0] !== "08bed558b0a428c072e8a0761d5efbb6bd49b29518144153bf64ed61004f9dda") {
78
+ for (let $i = 0; $i < 37; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
79
+ $[0] = "08bed558b0a428c072e8a0761d5efbb6bd49b29518144153bf64ed61004f9dda";
80
80
  }
81
+ const source = t0 === void 0 ? "draft" : t0;
81
82
  const blockIds = pageStructure.page.blockIds;
82
83
  const beforeIds = pageStructure.layout?.beforeBlockIds ?? EMPTY_IDS;
83
84
  const afterIds = pageStructure.layout?.afterBlockIds ?? EMPTY_IDS;
84
- let t0;
85
+ let t1;
85
86
  if ($[1] !== afterIds || $[2] !== beforeIds || $[3] !== blockIds) {
86
- t0 = [
87
+ t1 = [
87
88
  ...blockIds,
88
89
  ...beforeIds,
89
90
  ...afterIds
@@ -91,108 +92,106 @@ function usePageBlocks(pageStructure) {
91
92
  $[1] = afterIds;
92
93
  $[2] = beforeIds;
93
94
  $[3] = blockIds;
94
- $[4] = t0;
95
- } else t0 = $[4];
96
- const allIds = t0;
97
- let t1;
98
- if ($[5] !== allIds) {
99
- t1 = { queries: allIds.map(_temp3) };
95
+ $[4] = t1;
96
+ } else t1 = $[4];
97
+ const allIds = t1;
98
+ let t2;
99
+ if ($[5] !== allIds || $[6] !== source) {
100
+ t2 = { queries: allIds.map((id) => blockQueries.get(id, source)) };
100
101
  $[5] = allIds;
101
- $[6] = t1;
102
- } else t1 = $[6];
103
- const results = useQueries(t1);
102
+ $[6] = source;
103
+ $[7] = t2;
104
+ } else t2 = $[7];
105
+ const results = useQueries(t2);
104
106
  let map;
105
- if ($[7] !== allIds || $[8] !== results) {
107
+ if ($[8] !== allIds || $[9] !== results) {
106
108
  map = /* @__PURE__ */ new Map();
107
109
  for (let i = 0; i < allIds.length; i++) {
108
110
  const data = results[i]?.data;
109
111
  if (data) map.set(allIds[i], data);
110
112
  }
111
- $[7] = allIds;
112
- $[8] = results;
113
- $[9] = map;
114
- } else map = $[9];
113
+ $[8] = allIds;
114
+ $[9] = results;
115
+ $[10] = map;
116
+ } else map = $[10];
115
117
  const bundleMap = map;
116
- let t2;
117
- if ($[10] !== afterIds || $[11] !== beforeIds) {
118
- t2 = [...beforeIds, ...afterIds];
119
- $[10] = afterIds;
120
- $[11] = beforeIds;
121
- $[12] = t2;
122
- } else t2 = $[12];
123
- const layoutIds = t2;
124
118
  let t3;
125
- if ($[13] !== bundleMap) {
126
- t3 = (ids) => ids.map((id_0) => bundleMap.get(id_0)?.block).filter(_temp4);
127
- $[13] = bundleMap;
128
- $[14] = t3;
129
- } else t3 = $[14];
130
- const resolveBlocks = t3;
119
+ if ($[11] !== afterIds || $[12] !== beforeIds) {
120
+ t3 = [...beforeIds, ...afterIds];
121
+ $[11] = afterIds;
122
+ $[12] = beforeIds;
123
+ $[13] = t3;
124
+ } else t3 = $[13];
125
+ const layoutIds = t3;
131
126
  let t4;
132
- if ($[15] !== blockIds || $[16] !== resolveBlocks) {
133
- t4 = resolveBlocks(blockIds);
134
- $[15] = blockIds;
135
- $[16] = resolveBlocks;
136
- $[17] = t4;
137
- } else t4 = $[17];
138
- const pageBlocks = useStableArray(t4);
127
+ if ($[14] !== bundleMap) {
128
+ t4 = (ids) => ids.map((id_0) => bundleMap.get(id_0)?.block).filter(_temp3);
129
+ $[14] = bundleMap;
130
+ $[15] = t4;
131
+ } else t4 = $[15];
132
+ const resolveBlocks = t4;
139
133
  let t5;
140
- if ($[18] !== beforeIds || $[19] !== resolveBlocks) {
141
- t5 = resolveBlocks(beforeIds);
142
- $[18] = beforeIds;
143
- $[19] = resolveBlocks;
144
- $[20] = t5;
145
- } else t5 = $[20];
146
- const beforeBlocks = useStableArray(t5);
134
+ if ($[16] !== blockIds || $[17] !== resolveBlocks) {
135
+ t5 = resolveBlocks(blockIds);
136
+ $[16] = blockIds;
137
+ $[17] = resolveBlocks;
138
+ $[18] = t5;
139
+ } else t5 = $[18];
140
+ const pageBlocks = useStableArray(t5);
147
141
  let t6;
148
- if ($[21] !== afterIds || $[22] !== resolveBlocks) {
149
- t6 = resolveBlocks(afterIds);
150
- $[21] = afterIds;
151
- $[22] = resolveBlocks;
152
- $[23] = t6;
153
- } else t6 = $[23];
154
- const afterBlocks = useStableArray(t6);
142
+ if ($[19] !== beforeIds || $[20] !== resolveBlocks) {
143
+ t6 = resolveBlocks(beforeIds);
144
+ $[19] = beforeIds;
145
+ $[20] = resolveBlocks;
146
+ $[21] = t6;
147
+ } else t6 = $[21];
148
+ const beforeBlocks = useStableArray(t6);
155
149
  let t7;
156
- if ($[24] !== bundleMap || $[25] !== layoutIds) {
157
- t7 = layoutIds.flatMap((id_1) => bundleMap.get(id_1)?.files ?? []);
158
- $[24] = bundleMap;
159
- $[25] = layoutIds;
160
- $[26] = t7;
161
- } else t7 = $[26];
162
- const layoutFiles = useStableArray(t7);
150
+ if ($[22] !== afterIds || $[23] !== resolveBlocks) {
151
+ t7 = resolveBlocks(afterIds);
152
+ $[22] = afterIds;
153
+ $[23] = resolveBlocks;
154
+ $[24] = t7;
155
+ } else t7 = $[24];
156
+ const afterBlocks = useStableArray(t7);
163
157
  let t8;
164
- if ($[27] !== bundleMap || $[28] !== layoutIds) {
165
- t8 = layoutIds.flatMap((id_2) => bundleMap.get(id_2)?.repeatableItems ?? []);
166
- $[27] = bundleMap;
167
- $[28] = layoutIds;
168
- $[29] = t8;
169
- } else t8 = $[29];
170
- const layoutItems = useStableArray(t8);
158
+ if ($[25] !== bundleMap || $[26] !== layoutIds) {
159
+ t8 = layoutIds.flatMap((id_1) => bundleMap.get(id_1)?.files ?? []);
160
+ $[25] = bundleMap;
161
+ $[26] = layoutIds;
162
+ $[27] = t8;
163
+ } else t8 = $[27];
164
+ const layoutFiles = useStableArray(t8);
171
165
  let t9;
172
- if ($[30] !== afterBlocks || $[31] !== beforeBlocks || $[32] !== layoutFiles || $[33] !== layoutItems || $[34] !== pageBlocks) {
173
- t9 = {
166
+ if ($[28] !== bundleMap || $[29] !== layoutIds) {
167
+ t9 = layoutIds.flatMap((id_2) => bundleMap.get(id_2)?.repeatableItems ?? []);
168
+ $[28] = bundleMap;
169
+ $[29] = layoutIds;
170
+ $[30] = t9;
171
+ } else t9 = $[30];
172
+ const layoutItems = useStableArray(t9);
173
+ let t10;
174
+ if ($[31] !== afterBlocks || $[32] !== beforeBlocks || $[33] !== layoutFiles || $[34] !== layoutItems || $[35] !== pageBlocks) {
175
+ t10 = {
174
176
  pageBlocks,
175
177
  beforeBlocks,
176
178
  afterBlocks,
177
179
  layoutFiles,
178
180
  layoutItems
179
181
  };
180
- $[30] = afterBlocks;
181
- $[31] = beforeBlocks;
182
- $[32] = layoutFiles;
183
- $[33] = layoutItems;
184
- $[34] = pageBlocks;
185
- $[35] = t9;
186
- } else t9 = $[35];
187
- return t9;
182
+ $[31] = afterBlocks;
183
+ $[32] = beforeBlocks;
184
+ $[33] = layoutFiles;
185
+ $[34] = layoutItems;
186
+ $[35] = pageBlocks;
187
+ $[36] = t10;
188
+ } else t10 = $[36];
189
+ return t10;
188
190
  }
189
191
  /** Check if a value is a { _fileId } marker */
190
- function _temp4(b) {
192
+ function _temp3(b) {
191
193
  return b != null;
192
194
  }
193
- function _temp3(id) {
194
- return blockQueries.get(id);
195
- }
196
195
  function isFileMarker(value) {
197
196
  return value != null && typeof value === "object" && "_fileId" in value && value._fileId != null;
198
197
  }
@@ -215,7 +214,7 @@ function visitForFileIds(value, ids) {
215
214
  function collectFileIdsFromContent(content, ids) {
216
215
  for (const value of Object.values(content)) visitForFileIds(value, ids);
217
216
  }
218
- function seedBlockCaches(queryClient, pageData) {
217
+ function seedBlockCaches(queryClient, pageData, source = "draft") {
219
218
  const filesById = new Map(pageData.files.map((f) => [f.id, f]));
220
219
  for (const block of pageData.blocks) {
221
220
  const blockItems = pageData.repeatableItems.filter((i) => i.blockId === block.id);
@@ -223,7 +222,7 @@ function seedBlockCaches(queryClient, pageData) {
223
222
  collectFileIdsFromContent(block.content, fileIds);
224
223
  for (const item of blockItems) collectFileIdsFromContent(item.content, fileIds);
225
224
  const blockFiles = [...fileIds].map((id) => filesById.get(id)).filter((f) => f != null);
226
- queryClient.setQueryData(queryKeys.blocks.get(block.id), {
225
+ queryClient.setQueryData(queryKeys.blocks.get(block.id, source), {
227
226
  block,
228
227
  repeatableItems: blockItems,
229
228
  files: blockFiles
@@ -11,15 +11,16 @@ const pageQueries = {
11
11
  }),
12
12
  queryKey: queryKeys.pages.list
13
13
  }),
14
- getByPath: (fullPath, projectSlug) => ({
14
+ getByPath: (fullPath, projectSlug, source = "draft") => ({
15
15
  ...getOrpc().pages.getByPath.queryOptions({
16
16
  input: {
17
17
  path: fullPath,
18
- projectSlug
18
+ projectSlug,
19
+ source
19
20
  },
20
21
  staleTime: Infinity
21
22
  }),
22
- queryKey: queryKeys.pages.getByPath(fullPath)
23
+ queryKey: queryKeys.pages.getByPath(fullPath, source)
23
24
  }),
24
25
  getById: (id) => ({
25
26
  ...getOrpc().pages.get.queryOptions({
@@ -64,12 +65,15 @@ const layoutQueries = { list: (projectId) => ({
64
65
  queryKey: queryKeys.layouts.all
65
66
  }) };
66
67
  const blockQueries = {
67
- get: (id) => ({
68
+ get: (id, source = "draft") => ({
68
69
  ...getOrpc().blocks.get.queryOptions({
69
- input: { id },
70
+ input: {
71
+ id,
72
+ source
73
+ },
70
74
  staleTime: Infinity
71
75
  }),
72
- queryKey: queryKeys.blocks.get(id)
76
+ queryKey: queryKeys.blocks.get(id, source)
73
77
  }),
74
78
  getUsageCounts: (projectId) => ({
75
79
  ...getOrpc().blocks.getUsageCounts.queryOptions({
@@ -139,6 +143,8 @@ const pageMutations = {
139
143
  setAiSeo: () => getOrpc().pages.setAiSeo.mutationOptions(),
140
144
  setMetaTitle: () => getOrpc().pages.setMetaTitle.mutationOptions(),
141
145
  setMetaDescription: () => getOrpc().pages.setMetaDescription.mutationOptions(),
146
+ publish: () => getOrpc().pages.publish.mutationOptions(),
147
+ unpublish: () => getOrpc().pages.unpublish.mutationOptions(),
142
148
  uploadCustomOgImage: () => ({ mutationFn: async ({ pageId, file }) => {
143
149
  const formData = new FormData();
144
150
  formData.append("file", file);