camox 0.40.0 → 0.41.1

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 (108) hide show
  1. package/dist/components/PlatformLabel.js +62 -0
  2. package/dist/core/components/lexical/GradientNode.js +126 -0
  3. package/dist/core/components/lexical/InlineLexicalEditor.js +37 -56
  4. package/dist/core/components/lexical/InlineStylesPlugin.js +183 -0
  5. package/dist/core/components/lexical/SelectionBroadcaster.js +49 -46
  6. package/dist/core/components/lexical/SidebarLexicalEditor.js +197 -151
  7. package/dist/core/components/lexical/editorConfig.js +25 -7
  8. package/dist/core/components/lexical/selectTextLink.js +21 -0
  9. package/dist/core/createApp.d.ts +30 -17
  10. package/dist/core/createApp.js +14 -3
  11. package/dist/core/createBlock.d.ts +2 -2
  12. package/dist/core/createBlock.js +17 -28
  13. package/dist/core/createLayout.d.ts +48 -4
  14. package/dist/core/createLayout.js +51 -23
  15. package/dist/core/derivedRoutes.js +36 -0
  16. package/dist/core/editing/BlockEditingRuntime.js +4 -4
  17. package/dist/core/editing/CompleteBlockEditingRuntime.js +5 -5
  18. package/dist/core/editing/createEditableBlock.d.ts +9 -8
  19. package/dist/core/editing/createEditableBlock.js +265 -403
  20. package/dist/core/hooks/useIsEditable.js +4 -7
  21. package/dist/core/hooks/useRequireDraftSource.js +7 -11
  22. package/dist/core/lib/lexicalReact.d.ts +1 -26
  23. package/dist/core/lib/lexicalReact.js +46 -60
  24. package/dist/core/lib/lexicalState.js +164 -81
  25. package/dist/core/lib/modifierFormats.js +4 -15
  26. package/dist/core/lib/textStyles.d.ts +27 -0
  27. package/dist/core/lib/textStyles.js +47 -0
  28. package/dist/features/navigation/navigation.d.ts +2 -0
  29. package/dist/features/navigation/navigation.js +51 -46
  30. package/dist/features/page/DerivedPageContent.js +61 -0
  31. package/dist/features/page/PublishedPageContent.js +52 -83
  32. package/dist/features/page/SharedLayoutContent.js +66 -0
  33. package/dist/features/preview/CamoxPreview.d.ts +16 -1
  34. package/dist/features/preview/CamoxPreview.js +246 -290
  35. package/dist/features/preview/DerivedPreview.js +134 -0
  36. package/dist/features/preview/EditablePageExperience.js +25 -8
  37. package/dist/features/preview/components/AddBlockSidebar.js +43 -33
  38. package/dist/features/preview/components/AssetLightbox.js +1 -1
  39. package/dist/features/preview/components/BlockActionsPopover.js +8 -8
  40. package/dist/features/preview/components/BlockThumbnail.js +192 -0
  41. package/dist/features/preview/components/CreatePageModal.js +123 -115
  42. package/dist/features/preview/components/DerivedLayoutDialog.js +100 -0
  43. package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +5 -0
  44. package/dist/features/preview/components/DerivedLayoutSidebar.js +160 -0
  45. package/dist/features/preview/components/DerivedPageInfoSidebar.js +57 -0
  46. package/dist/features/preview/components/FieldToolbar.js +42 -20
  47. package/dist/features/preview/components/Frame.js +133 -140
  48. package/dist/features/preview/components/LeftSidebar.js +42 -38
  49. package/dist/features/preview/components/LinkFieldEditor.js +3 -4
  50. package/dist/features/preview/components/MobilePreviewDrawer.js +4 -4
  51. package/dist/features/preview/components/Overlays.js +59 -47
  52. package/dist/features/preview/components/PageEditorSidebar.js +194 -203
  53. package/dist/features/preview/components/PageInfoSidebar.js +63 -55
  54. package/dist/features/preview/components/PageNavigatorSidebar.js +34 -483
  55. package/dist/features/preview/components/PagePicker.js +205 -153
  56. package/dist/features/preview/components/PageTree.js +366 -340
  57. package/dist/features/preview/components/PreviewActivation.js +78 -0
  58. package/dist/features/preview/components/PreviewPanel.js +98 -68
  59. package/dist/features/preview/components/PreviewToolbar.js +224 -241
  60. package/dist/features/preview/components/PreviewToolbarSpacer.js +43 -0
  61. package/dist/features/preview/components/PublicationRow.js +425 -0
  62. package/dist/features/preview/components/PublishDialog.js +180 -97
  63. package/dist/features/preview/components/RightSidebar.js +19 -34
  64. package/dist/features/preview/components/previewStyles.js +8 -0
  65. package/dist/features/preview/components/useUpdateBlockPosition.js +7 -13
  66. package/dist/features/preview/previewConstants.js +8 -0
  67. package/dist/features/preview/previewStore.js +18 -39
  68. package/dist/features/preview/publication.js +71 -0
  69. package/dist/features/provider/AuthenticatedCamoxProvider.js +2 -1
  70. package/dist/features/provider/CoreCamoxProvider.js +11 -2
  71. package/dist/features/provider/LocalhostPreviewProvider.js +6 -7
  72. package/dist/features/provider/useAdminShortcuts.js +5 -4
  73. package/dist/features/routes/pageRuntime.d.ts +10 -0
  74. package/dist/features/routes/pageRuntime.js +7 -9
  75. package/dist/features/runtime/PreviewDocumentContext.js +7 -0
  76. package/dist/features/runtime/RuntimeChrome.js +149 -0
  77. package/dist/features/runtime/SharedChromeContext.js +7 -0
  78. package/dist/features/runtime/navigationRequest.js +21 -0
  79. package/dist/features/runtime/navigationTarget.js +23 -0
  80. package/dist/features/runtime/pageApp.js +196 -121
  81. package/dist/features/runtime/pageNavigation.js +79 -130
  82. package/dist/features/runtime/runtime.d.ts +11 -0
  83. package/dist/features/runtime/runtime.js +183 -47
  84. package/dist/features/runtime/studioApp.d.ts +2 -11
  85. package/dist/features/runtime/studioApp.js +14 -177
  86. package/dist/features/studio/CamoxStudio.js +27 -13
  87. package/dist/features/studio/components/Navbar.js +80 -74
  88. package/dist/features/studio/components/UserButton.js +4 -4
  89. package/dist/features/studio/studioTheme.js +25 -0
  90. package/dist/features/studio/useTheme.js +94 -109
  91. package/dist/features/vite/appGeneration.js +12 -3
  92. package/dist/features/vite/definitionsSync.js +4 -2
  93. package/dist/features/vite/layoutGeneration.js +38 -0
  94. package/dist/features/vite/runtimeDev.js +3 -1
  95. package/dist/lib/auth.js +15 -13
  96. package/dist/lib/normalized-data.js +4 -4
  97. package/dist/lib/platform.js +13 -0
  98. package/dist/lib/utils.js +90 -38
  99. package/dist/studio-overlays.css +5 -40
  100. package/dist/studio.css +1 -1
  101. package/package.json +8 -4
  102. package/skills/camox/SKILL.md +2 -0
  103. package/skills/camox/references/block-definitions.md +31 -12
  104. package/skills/camox/references/layout-definitions.md +2 -0
  105. package/dist/core/lib/modifiers.js +0 -24
  106. package/dist/features/preview/components/DraftSwitchDialog.js +0 -66
  107. package/dist/features/preview/previewQueryFns.js +0 -23
  108. package/dist/features/runtime/studioNavigation.js +0 -120
@@ -26,10 +26,10 @@ const slugifyPathSegment = (nickname) => {
26
26
  return trimmedNickname.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
27
27
  };
28
28
  const CreatePageModal = () => {
29
- const $ = c(56);
30
- if ($[0] !== "1b629d2817a68910dcd0da1c3da2fc0aac9482f6f60a2348db493c3af333db39") {
31
- for (let $i = 0; $i < 56; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
32
- $[0] = "1b629d2817a68910dcd0da1c3da2fc0aac9482f6f60a2348db493c3af333db39";
29
+ const $ = c(59);
30
+ if ($[0] !== "a489bee2c2bcec31c62ddabbd93e62c3a08c94905cfefce5cfe8476f2f60182f") {
31
+ for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
32
+ $[0] = "a489bee2c2bcec31c62ddabbd93e62c3a08c94905cfefce5cfe8476f2f60182f";
33
33
  }
34
34
  const projectSlug = useProjectSlug();
35
35
  const open = useSelector(previewStore, _temp);
@@ -81,21 +81,29 @@ const CreatePageModal = () => {
81
81
  $[12] = t6;
82
82
  $[13] = t7;
83
83
  } else t7 = $[13];
84
- const { data: layouts } = useQuery(t7);
84
+ const { data: allLayouts } = useQuery(t7);
85
85
  const camoxApp = useCamoxApp();
86
- const navigate = useNavigate();
87
86
  let t8;
88
- if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
89
- t8 = {
87
+ if ($[14] !== allLayouts || $[15] !== camoxApp) {
88
+ t8 = allLayouts?.filter((layout) => camoxApp.getLayoutById(layout.layoutId)?._internal.kind !== "derived");
89
+ $[14] = allLayouts;
90
+ $[15] = camoxApp;
91
+ $[16] = t8;
92
+ } else t8 = $[16];
93
+ const layouts = t8;
94
+ const navigate = useNavigate();
95
+ let t9;
96
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
97
+ t9 = {
90
98
  nickname: "",
91
99
  parentPageId: void 0,
92
100
  pathSegment: "",
93
101
  layoutId: ""
94
102
  };
95
- $[14] = t8;
96
- } else t8 = $[14];
103
+ $[17] = t9;
104
+ } else t9 = $[17];
97
105
  const form = useForm({
98
- defaultValues: t8,
106
+ defaultValues: t9,
99
107
  onSubmit: async (values) => {
100
108
  try {
101
109
  if (!project) {
@@ -129,47 +137,47 @@ const CreatePageModal = () => {
129
137
  form.reset();
130
138
  await new Promise(_temp2);
131
139
  await navigate({ to: fullPath });
132
- } catch (t9) {
133
- console.error("Failed to create page:", t9);
140
+ } catch (t10) {
141
+ console.error("Failed to create page:", t10);
134
142
  toast.error("Could not create page");
135
143
  }
136
144
  }
137
145
  });
138
- let t10;
139
- if ($[15] !== form || $[16] !== layouts) {
140
- t10 = () => {
141
- if (layouts && layouts.length > 0 && !form.getFieldValue("layoutId")) form.setFieldValue("layoutId", String(layouts[0].id));
142
- };
143
- $[15] = form;
144
- $[16] = layouts;
145
- $[17] = t10;
146
- } else t10 = $[17];
147
146
  let t11;
148
147
  if ($[18] !== form || $[19] !== layouts) {
149
- t11 = [layouts, form];
148
+ t11 = () => {
149
+ if (layouts && layouts.length > 0 && !form.getFieldValue("layoutId")) form.setFieldValue("layoutId", String(layouts[0].id));
150
+ };
150
151
  $[18] = form;
151
152
  $[19] = layouts;
152
153
  $[20] = t11;
153
154
  } else t11 = $[20];
154
- useEffect(t10, t11);
155
155
  let t12;
156
- if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
157
- t12 = /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Create page" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Fill in the details to create a new page. It will be created as a draft." })] });
158
- $[21] = t12;
159
- } else t12 = $[21];
156
+ if ($[21] !== form || $[22] !== layouts) {
157
+ t12 = [layouts, form];
158
+ $[21] = form;
159
+ $[22] = layouts;
160
+ $[23] = t12;
161
+ } else t12 = $[23];
162
+ useEffect(t11, t12);
160
163
  let t13;
161
- if ($[22] !== form) {
162
- t13 = (e) => {
164
+ if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
165
+ t13 = /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Create page" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Fill in the details to create a new page. It will be created as a draft." })] });
166
+ $[24] = t13;
167
+ } else t13 = $[24];
168
+ let t14;
169
+ if ($[25] !== form) {
170
+ t14 = (e) => {
163
171
  e.preventDefault();
164
172
  e.stopPropagation();
165
173
  form.handleSubmit();
166
174
  };
167
- $[22] = form;
168
- $[23] = t13;
169
- } else t13 = $[23];
170
- let t14;
171
- if ($[24] !== form) {
172
- t14 = (field) => /* @__PURE__ */ jsx(PageNicknameField, {
175
+ $[25] = form;
176
+ $[26] = t14;
177
+ } else t14 = $[26];
178
+ let t15;
179
+ if ($[27] !== form) {
180
+ t15 = (field) => /* @__PURE__ */ jsx(PageNicknameField, {
173
181
  value: field.state.value,
174
182
  onChange: (value_0) => {
175
183
  field.handleChange(value_0);
@@ -178,22 +186,22 @@ const CreatePageModal = () => {
178
186
  },
179
187
  autoFocus: true
180
188
  });
181
- $[24] = form;
182
- $[25] = t14;
183
- } else t14 = $[25];
184
- let t15;
185
- if ($[26] !== form.Field || $[27] !== t14) {
186
- t15 = /* @__PURE__ */ jsx(form.Field, {
187
- name: "nickname",
188
- children: t14
189
- });
190
- $[26] = form.Field;
191
- $[27] = t14;
189
+ $[27] = form;
192
190
  $[28] = t15;
193
191
  } else t15 = $[28];
194
192
  let t16;
195
- if ($[29] !== form.Field || $[30] !== pages) {
196
- t16 = (parentField) => /* @__PURE__ */ jsx(form.Field, {
193
+ if ($[29] !== form.Field || $[30] !== t15) {
194
+ t16 = /* @__PURE__ */ jsx(form.Field, {
195
+ name: "nickname",
196
+ children: t15
197
+ });
198
+ $[29] = form.Field;
199
+ $[30] = t15;
200
+ $[31] = t16;
201
+ } else t16 = $[31];
202
+ let t17;
203
+ if ($[32] !== form.Field || $[33] !== pages) {
204
+ t17 = (parentField) => /* @__PURE__ */ jsx(form.Field, {
197
205
  name: "pathSegment",
198
206
  children: (pathField) => /* @__PURE__ */ jsx(PageLocationFieldset, {
199
207
  parentPageId: parentField.state.value,
@@ -203,23 +211,23 @@ const CreatePageModal = () => {
203
211
  pages
204
212
  })
205
213
  });
206
- $[29] = form.Field;
207
- $[30] = pages;
208
- $[31] = t16;
209
- } else t16 = $[31];
210
- let t17;
211
- if ($[32] !== form.Field || $[33] !== t16) {
212
- t17 = /* @__PURE__ */ jsx(form.Field, {
213
- name: "parentPageId",
214
- children: t16
215
- });
216
214
  $[32] = form.Field;
217
- $[33] = t16;
215
+ $[33] = pages;
218
216
  $[34] = t17;
219
217
  } else t17 = $[34];
220
218
  let t18;
221
- if ($[35] !== camoxApp || $[36] !== layouts) {
222
- t18 = (field_0) => /* @__PURE__ */ jsxs("div", {
219
+ if ($[35] !== form.Field || $[36] !== t17) {
220
+ t18 = /* @__PURE__ */ jsx(form.Field, {
221
+ name: "parentPageId",
222
+ children: t17
223
+ });
224
+ $[35] = form.Field;
225
+ $[36] = t17;
226
+ $[37] = t18;
227
+ } else t18 = $[37];
228
+ let t19;
229
+ if ($[38] !== camoxApp || $[39] !== layouts) {
230
+ t19 = (field_0) => /* @__PURE__ */ jsxs("div", {
223
231
  className: "space-y-2",
224
232
  children: [/* @__PURE__ */ jsx(Label, {
225
233
  htmlFor: "layoutId",
@@ -240,77 +248,77 @@ const CreatePageModal = () => {
240
248
  }, t_0.id)) })]
241
249
  })]
242
250
  });
243
- $[35] = camoxApp;
244
- $[36] = layouts;
245
- $[37] = t18;
246
- } else t18 = $[37];
247
- let t19;
248
- if ($[38] !== form.Field || $[39] !== t18) {
249
- t19 = /* @__PURE__ */ jsx(form.Field, {
250
- name: "layoutId",
251
- children: t18
252
- });
253
- $[38] = form.Field;
254
- $[39] = t18;
251
+ $[38] = camoxApp;
252
+ $[39] = layouts;
255
253
  $[40] = t19;
256
254
  } else t19 = $[40];
257
255
  let t20;
258
- if ($[41] !== form.state.isSubmitting) {
259
- t20 = form.state.isSubmitting && /* @__PURE__ */ jsx(Spinner, {});
260
- $[41] = form.state.isSubmitting;
261
- $[42] = t20;
262
- } else t20 = $[42];
263
- const t21 = form.state.isSubmitting && "...";
264
- let t22;
265
- if ($[43] !== form.state.isSubmitting || $[44] !== t20 || $[45] !== t21) {
266
- t22 = /* @__PURE__ */ jsxs(Button, {
256
+ if ($[41] !== form.Field || $[42] !== t19) {
257
+ t20 = /* @__PURE__ */ jsx(form.Field, {
258
+ name: "layoutId",
259
+ children: t19
260
+ });
261
+ $[41] = form.Field;
262
+ $[42] = t19;
263
+ $[43] = t20;
264
+ } else t20 = $[43];
265
+ let t21;
266
+ if ($[44] !== form.state.isSubmitting) {
267
+ t21 = form.state.isSubmitting && /* @__PURE__ */ jsx(Spinner, {});
268
+ $[44] = form.state.isSubmitting;
269
+ $[45] = t21;
270
+ } else t21 = $[45];
271
+ const t22 = form.state.isSubmitting && "...";
272
+ let t23;
273
+ if ($[46] !== form.state.isSubmitting || $[47] !== t21 || $[48] !== t22) {
274
+ t23 = /* @__PURE__ */ jsxs(Button, {
267
275
  type: "submit",
268
276
  disabled: form.state.isSubmitting,
269
277
  children: [
270
- t20,
278
+ t21,
271
279
  "Create page",
272
- t21
280
+ t22
273
281
  ]
274
282
  });
275
- $[43] = form.state.isSubmitting;
276
- $[44] = t20;
277
- $[45] = t21;
278
- $[46] = t22;
279
- } else t22 = $[46];
280
- let t23;
281
- if ($[47] !== t13 || $[48] !== t15 || $[49] !== t17 || $[50] !== t19 || $[51] !== t22) {
282
- t23 = /* @__PURE__ */ jsxs(DialogContent, {
283
+ $[46] = form.state.isSubmitting;
284
+ $[47] = t21;
285
+ $[48] = t22;
286
+ $[49] = t23;
287
+ } else t23 = $[49];
288
+ let t24;
289
+ if ($[50] !== t14 || $[51] !== t16 || $[52] !== t18 || $[53] !== t20 || $[54] !== t23) {
290
+ t24 = /* @__PURE__ */ jsxs(DialogContent, {
283
291
  className: "flex max-h-[90vh] flex-col sm:max-w-lg",
284
- children: [t12, /* @__PURE__ */ jsxs("form", {
285
- onSubmit: t13,
292
+ children: [t13, /* @__PURE__ */ jsxs("form", {
293
+ onSubmit: t14,
286
294
  className: "-mx-1 space-y-4 overflow-y-auto px-1 py-2",
287
295
  children: [
288
- t15,
289
- t17,
290
- t19,
291
- t22
296
+ t16,
297
+ t18,
298
+ t20,
299
+ t23
292
300
  ]
293
301
  })]
294
302
  });
295
- $[47] = t13;
296
- $[48] = t15;
297
- $[49] = t17;
298
- $[50] = t19;
299
- $[51] = t22;
300
- $[52] = t23;
301
- } else t23 = $[52];
302
- let t24;
303
- if ($[53] !== open || $[54] !== t23) {
304
- t24 = /* @__PURE__ */ jsx(Dialog, {
305
- open,
306
- onOpenChange: _temp3,
307
- children: t23
308
- });
309
- $[53] = open;
303
+ $[50] = t14;
304
+ $[51] = t16;
305
+ $[52] = t18;
306
+ $[53] = t20;
310
307
  $[54] = t23;
311
308
  $[55] = t24;
312
309
  } else t24 = $[55];
313
- return t24;
310
+ let t25;
311
+ if ($[56] !== open || $[57] !== t24) {
312
+ t25 = /* @__PURE__ */ jsx(Dialog, {
313
+ open,
314
+ onOpenChange: _temp3,
315
+ children: t24
316
+ });
317
+ $[56] = open;
318
+ $[57] = t24;
319
+ $[58] = t25;
320
+ } else t25 = $[58];
321
+ return t25;
314
322
  };
315
323
  function _temp(state) {
316
324
  return state.context.isCreatePageModalOpen;
@@ -0,0 +1,100 @@
1
+ import { useNavigate } from "../../navigation/navigation.js";
2
+ import { routeSegments } from "../../../core/derivedRoutes.js";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Button } from "@camox/ui/button";
6
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@camox/ui/dialog";
7
+ import { Label } from "@camox/ui/label";
8
+ import { Input } from "@camox/ui/input";
9
+
10
+ //#region src/features/preview/components/DerivedLayoutDialog.tsx
11
+ function DerivedLayoutDialog({ layout, projectSlug, currentParams, onClose }) {
12
+ const navigate = useNavigate();
13
+ const id = React.useId();
14
+ const storageKey = `camox:derived-preview:${projectSlug}:${layout._internal.id}`;
15
+ const [values, setValues] = React.useState(() => {
16
+ if (currentParams) return currentParams;
17
+ try {
18
+ const saved = JSON.parse(sessionStorage.getItem(storageKey) ?? "{}");
19
+ if (saved && typeof saved === "object" && !Array.isArray(saved)) return Object.fromEntries(Object.entries(saved).filter((entry) => typeof entry[1] === "string"));
20
+ } catch {}
21
+ return {};
22
+ });
23
+ const [pending, setPending] = React.useState(false);
24
+ const [error, setError] = React.useState(null);
25
+ const segments = routeSegments(layout._internal.id);
26
+ const params = [...new Set(segments.filter((segment) => segment.startsWith("$")).map((segment_0) => segment_0.slice(1)))];
27
+ const valid = params.every((param) => {
28
+ const value = values[param]?.trim();
29
+ return value && !value.includes("/") && value !== "." && value !== "..";
30
+ });
31
+ const path = `/${segments.map((segment_1) => {
32
+ if (!segment_1.startsWith("$")) return encodeURIComponent(segment_1);
33
+ const value_0 = values[segment_1.slice(1)]?.trim();
34
+ return value_0 ? encodeURIComponent(value_0) : segment_1;
35
+ }).join("/")}`;
36
+ return /* @__PURE__ */ jsx(Dialog, {
37
+ open: true,
38
+ onOpenChange: (open) => !open && onClose(),
39
+ children: /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs("form", {
40
+ className: "space-y-4",
41
+ onSubmit: async (event) => {
42
+ event.preventDefault();
43
+ if (!valid || pending) return;
44
+ try {
45
+ sessionStorage.setItem(storageKey, JSON.stringify(values));
46
+ } catch {}
47
+ setPending(true);
48
+ setError(null);
49
+ try {
50
+ await navigate({ to: path });
51
+ onClose();
52
+ } catch {
53
+ setError("Could not open this preview. Check the parameters and try again.");
54
+ } finally {
55
+ setPending(false);
56
+ }
57
+ },
58
+ children: [
59
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsxs(DialogTitle, { children: ["Preview ", layout._internal.title] }), /* @__PURE__ */ jsx(DialogDescription, { children: "Enter the path parameters for the page you want to preview." })] }),
60
+ params.map((param_0) => /* @__PURE__ */ jsxs("div", {
61
+ className: "space-y-2",
62
+ children: [/* @__PURE__ */ jsx(Label, {
63
+ htmlFor: `${id}-${param_0}`,
64
+ children: param_0
65
+ }), /* @__PURE__ */ jsx(Input, {
66
+ id: `${id}-${param_0}`,
67
+ required: true,
68
+ value: values[param_0] ?? "",
69
+ onChange: (event_0) => setValues((previous) => ({
70
+ ...previous,
71
+ [param_0]: event_0.target.value
72
+ }))
73
+ })]
74
+ }, param_0)),
75
+ /* @__PURE__ */ jsx("p", {
76
+ className: "text-muted-foreground font-mono text-sm break-all",
77
+ children: path
78
+ }),
79
+ error && /* @__PURE__ */ jsx("p", {
80
+ role: "alert",
81
+ className: "text-destructive text-sm",
82
+ children: error
83
+ }),
84
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
85
+ type: "button",
86
+ variant: "outline",
87
+ onClick: onClose,
88
+ children: "Cancel"
89
+ }), /* @__PURE__ */ jsx(Button, {
90
+ type: "submit",
91
+ disabled: !valid || pending,
92
+ children: pending ? "Opening…" : "Open preview"
93
+ })] })
94
+ ]
95
+ }) })
96
+ });
97
+ }
98
+
99
+ //#endregion
100
+ export { DerivedLayoutDialog };
@@ -0,0 +1,5 @@
1
+ import { PageRenderInput } from "../../runtime/runtime.js";
2
+ //#region src/features/preview/components/DerivedLayoutSidebar.d.ts
3
+ type DerivedLayoutStructure = NonNullable<PageRenderInput["derived"]>["layout"];
4
+ //#endregion
5
+ export { DerivedLayoutStructure };
@@ -0,0 +1,160 @@
1
+ import { useProjectSlug } from "../../../lib/auth.js";
2
+ import { usePageBlocks } from "../../../lib/normalized-data.js";
3
+ import { layoutQueries, projectQueries } from "../../../lib/queries.js";
4
+ import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
5
+ import { previewStore, selectPreviewSource } from "../previewStore.js";
6
+ import { PagePicker } from "./PagePicker.js";
7
+ import { LayoutBlockItem } from "./PageTree.js";
8
+ import { PublicationRow } from "./PublicationRow.js";
9
+ import { c } from "react/compiler-runtime";
10
+ import { useQuery } from "@tanstack/react-query";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { useSelector } from "@xstate/store-react";
13
+ import { Alert, AlertDescription, AlertTitle } from "@camox/ui/alert";
14
+ import { PanelContent, PanelHeader } from "@camox/ui/panel";
15
+
16
+ //#region src/features/preview/components/DerivedLayoutSidebar.tsx
17
+ const EMPTY_PAGE = { blockIds: [] };
18
+ function DerivedLayoutSidebar(t0) {
19
+ const $ = c(32);
20
+ if ($[0] !== "2c7da8bd37fd1558e1c31149d4435d439cdd1425cb374116d681960617531266") {
21
+ for (let $i = 0; $i < 32; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
22
+ $[0] = "2c7da8bd37fd1558e1c31149d4435d439cdd1425cb374116d681960617531266";
23
+ }
24
+ const { layout } = t0;
25
+ const source = useSelector(previewStore, selectPreviewSource);
26
+ let t1;
27
+ if ($[1] !== layout) {
28
+ t1 = {
29
+ page: EMPTY_PAGE,
30
+ layout
31
+ };
32
+ $[1] = layout;
33
+ $[2] = t1;
34
+ } else t1 = $[2];
35
+ const { beforeBlocks, afterBlocks } = usePageBlocks(t1, source);
36
+ const app = useCamoxApp();
37
+ let t2;
38
+ if ($[3] !== app || $[4] !== layout.layoutId) {
39
+ t2 = app.getLayoutById(layout.layoutId)?._internal.title ?? layout.layoutId;
40
+ $[3] = app;
41
+ $[4] = layout.layoutId;
42
+ $[5] = t2;
43
+ } else t2 = $[5];
44
+ const layoutName = t2;
45
+ const projectSlug = useProjectSlug();
46
+ let t3;
47
+ if ($[6] !== projectSlug) {
48
+ t3 = projectQueries.getBySlug(projectSlug);
49
+ $[6] = projectSlug;
50
+ $[7] = t3;
51
+ } else t3 = $[7];
52
+ const { data: project } = useQuery(t3);
53
+ let t4;
54
+ if ($[8] !== project?.id) {
55
+ t4 = layoutQueries.list(project?.id ?? 0);
56
+ $[8] = project?.id;
57
+ $[9] = t4;
58
+ } else t4 = $[9];
59
+ const t5 = !!project;
60
+ let t6;
61
+ if ($[10] !== t4 || $[11] !== t5) {
62
+ t6 = {
63
+ ...t4,
64
+ enabled: t5
65
+ };
66
+ $[10] = t4;
67
+ $[11] = t5;
68
+ $[12] = t6;
69
+ } else t6 = $[12];
70
+ const { data: layouts } = useQuery(t6);
71
+ let t7;
72
+ if ($[13] !== layout.id || $[14] !== layouts) {
73
+ t7 = layouts?.find((item) => item.id === layout.id);
74
+ $[13] = layout.id;
75
+ $[14] = layouts;
76
+ $[15] = t7;
77
+ } else t7 = $[15];
78
+ const record = t7;
79
+ let t8;
80
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
81
+ t8 = /* @__PURE__ */ jsx("div", {
82
+ className: "flex w-full",
83
+ children: /* @__PURE__ */ jsx(PagePicker, {})
84
+ });
85
+ $[16] = t8;
86
+ } else t8 = $[16];
87
+ let t9;
88
+ if ($[17] !== layoutName || $[18] !== record) {
89
+ t9 = record ? {
90
+ kind: "layout",
91
+ layout: record,
92
+ name: layoutName
93
+ } : null;
94
+ $[17] = layoutName;
95
+ $[18] = record;
96
+ $[19] = t9;
97
+ } else t9 = $[19];
98
+ let t10;
99
+ if ($[20] !== t9) {
100
+ t10 = /* @__PURE__ */ jsxs(PanelHeader, {
101
+ className: "flex flex-col gap-2 p-2",
102
+ children: [t8, /* @__PURE__ */ jsx(PublicationRow, { target: t9 })]
103
+ });
104
+ $[20] = t9;
105
+ $[21] = t10;
106
+ } else t10 = $[21];
107
+ let t11;
108
+ if ($[22] !== afterBlocks || $[23] !== beforeBlocks || $[24] !== layoutName) {
109
+ t11 = [["Before", beforeBlocks], ["After", afterBlocks]].map((t12) => {
110
+ const [title, blocks] = t12;
111
+ return /* @__PURE__ */ jsxs("section", {
112
+ className: "space-y-1",
113
+ children: [/* @__PURE__ */ jsx("h2", {
114
+ className: "text-muted-foreground px-2 text-xs font-medium",
115
+ children: title
116
+ }), blocks.length === 0 ? /* @__PURE__ */ jsxs("p", {
117
+ className: "text-muted-foreground px-2 py-2 text-sm",
118
+ children: [
119
+ "No ",
120
+ title.toLowerCase(),
121
+ " blocks"
122
+ ]
123
+ }) : blocks.map((block) => /* @__PURE__ */ jsx(LayoutBlockItem, {
124
+ block,
125
+ layoutName,
126
+ derived: true
127
+ }, block.id))]
128
+ }, title);
129
+ });
130
+ $[22] = afterBlocks;
131
+ $[23] = beforeBlocks;
132
+ $[24] = layoutName;
133
+ $[25] = t11;
134
+ } else t11 = $[25];
135
+ let t12;
136
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
137
+ t12 = /* @__PURE__ */ jsxs(Alert, { children: [/* @__PURE__ */ jsx(AlertTitle, { children: "Shared layout blocks" }), /* @__PURE__ */ jsx(AlertDescription, { children: "Changes apply to every page using this layout. The generated page content is managed outside the studio." })] });
138
+ $[26] = t12;
139
+ } else t12 = $[26];
140
+ let t13;
141
+ if ($[27] !== t11) {
142
+ t13 = /* @__PURE__ */ jsxs(PanelContent, {
143
+ className: "flex grow basis-0 flex-col gap-4 overflow-auto p-2",
144
+ children: [t11, t12]
145
+ });
146
+ $[27] = t11;
147
+ $[28] = t13;
148
+ } else t13 = $[28];
149
+ let t14;
150
+ if ($[29] !== t10 || $[30] !== t13) {
151
+ t14 = /* @__PURE__ */ jsxs(Fragment, { children: [t10, t13] });
152
+ $[29] = t10;
153
+ $[30] = t13;
154
+ $[31] = t14;
155
+ } else t14 = $[31];
156
+ return t14;
157
+ }
158
+
159
+ //#endregion
160
+ export { DerivedLayoutSidebar };
@@ -0,0 +1,57 @@
1
+ import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
2
+ import { c } from "react/compiler-runtime";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Alert, AlertDescription, AlertTitle } from "@camox/ui/alert";
5
+
6
+ //#region src/features/preview/components/DerivedPageInfoSidebar.tsx
7
+ function DerivedPageInfoSidebar(t0) {
8
+ const $ = c(8);
9
+ if ($[0] !== "188f548de856db3a863c0d74a6e937ddbe5a25be65cd852330ec33162eb56ebf") {
10
+ for (let $i = 0; $i < 8; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
11
+ $[0] = "188f548de856db3a863c0d74a6e937ddbe5a25be65cd852330ec33162eb56ebf";
12
+ }
13
+ const { layoutId } = t0;
14
+ const camoxApp = useCamoxApp();
15
+ let t1;
16
+ if ($[1] !== camoxApp || $[2] !== layoutId) {
17
+ t1 = camoxApp.getLayoutById(layoutId);
18
+ $[1] = camoxApp;
19
+ $[2] = layoutId;
20
+ $[3] = t1;
21
+ } else t1 = $[3];
22
+ const layoutName = t1?._internal.title ?? layoutId;
23
+ let t2;
24
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
25
+ t2 = /* @__PURE__ */ jsx("p", {
26
+ className: "text-base font-semibold",
27
+ children: "About this page"
28
+ });
29
+ $[4] = t2;
30
+ } else t2 = $[4];
31
+ let t3;
32
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
33
+ t3 = /* @__PURE__ */ jsx(AlertTitle, { children: "Derived page" });
34
+ $[5] = t3;
35
+ } else t3 = $[5];
36
+ let t4;
37
+ if ($[6] !== layoutName) {
38
+ t4 = /* @__PURE__ */ jsxs("div", {
39
+ className: "flex-1 space-y-4 p-2 pt-4",
40
+ children: [t2, /* @__PURE__ */ jsxs(Alert, { children: [t3, /* @__PURE__ */ jsxs(AlertDescription, { children: [
41
+ "This page is generated using the",
42
+ " ",
43
+ /* @__PURE__ */ jsx("strong", {
44
+ className: "font-semibold italic",
45
+ children: layoutName
46
+ }),
47
+ " layout. Select a shared block in the preview to edit it."
48
+ ] })] })]
49
+ });
50
+ $[6] = layoutName;
51
+ $[7] = t4;
52
+ } else t4 = $[7];
53
+ return t4;
54
+ }
55
+
56
+ //#endregion
57
+ export { DerivedPageInfoSidebar };