camox 0.43.0 → 0.44.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 (63) hide show
  1. package/bin/camox.mjs +9 -1
  2. package/dist/core/components/lexical/InlineStylesPlugin.js +22 -6
  3. package/dist/core/components/lexical/SelectionBroadcaster.js +4 -4
  4. package/dist/core/components/lexical/SidebarLexicalEditor.js +15 -15
  5. package/dist/core/createApp.d.ts +28 -2
  6. package/dist/core/createBlock.js +24 -10
  7. package/dist/core/editing/createEditableBlock.d.ts +135 -1
  8. package/dist/core/editing/createEditableBlock.js +209 -74
  9. package/dist/core/lib/contentType.d.ts +5 -0
  10. package/dist/core/lib/contentType.js +11 -0
  11. package/dist/core/lib/fieldTypes.js +1 -0
  12. package/dist/core/lib/iconTypes.d.ts +13 -0
  13. package/dist/core/lib/icons.d.ts +6 -0
  14. package/dist/core/lib/icons.js +130 -0
  15. package/dist/core/lib/lexicalState.js +6 -6
  16. package/dist/core/lib/modifierFormats.js +1 -1
  17. package/dist/core/lib/textStyles.d.ts +1 -1
  18. package/dist/core/lib/textStyles.js +3 -3
  19. package/dist/features/content/components/AssetCard.js +104 -68
  20. package/dist/features/preview/CamoxPreview.js +120 -95
  21. package/dist/features/preview/commentsEnabled.js +2 -2
  22. package/dist/features/preview/components/AssetLightbox.js +17 -6
  23. package/dist/features/preview/components/AttachedComments.js +224 -87
  24. package/dist/features/preview/components/CommentTargetQuote.js +22 -21
  25. package/dist/features/preview/components/DerivedLayoutDialog.js +36 -21
  26. package/dist/features/preview/components/FieldOverlayStyles.js +29 -9
  27. package/dist/features/preview/components/FieldToolbar.js +8 -8
  28. package/dist/features/preview/components/IconFieldEditor.js +231 -0
  29. package/dist/features/preview/components/ItemFieldsEditor.js +21 -14
  30. package/dist/features/preview/components/OverlayTracker.js +1 -1
  31. package/dist/features/preview/components/PagePicker.js +44 -44
  32. package/dist/features/preview/components/PreviewPanel.js +1 -1
  33. package/dist/features/preview/components/PreviewToolbar.js +224 -225
  34. package/dist/features/preview/components/SendFeedbackDialog.js +83 -0
  35. package/dist/features/preview/overlayHighlights.js +54 -0
  36. package/dist/features/preview/previewCommentsStore.js +54 -34
  37. package/dist/features/preview/previewSelection.js +28 -23
  38. package/dist/features/preview/usePageComments.js +39 -0
  39. package/dist/features/provider/CoreCamoxProvider.js +37 -5
  40. package/dist/features/provider/LocalhostPreviewProvider.js +81 -45
  41. package/dist/features/provider/components/CommandPalette.js +35 -84
  42. package/dist/features/runtime/pageApp.js +32 -28
  43. package/dist/features/runtime/pageServer.js +4 -1
  44. package/dist/features/runtime/runtime.d.ts +2 -0
  45. package/dist/features/runtime/runtime.js +25 -0
  46. package/dist/features/studio/components/EnvironmentMenu.js +75 -63
  47. package/dist/features/vite/auth.js +1 -50
  48. package/dist/features/vite/iconGeneration.js +16 -0
  49. package/dist/features/vite/vite.d.ts +4 -2
  50. package/dist/features/vite/vite.js +19 -2
  51. package/dist/lib/auth.js +39 -16
  52. package/dist/lib/preview-handoff.js +13 -0
  53. package/dist/lib/queries.js +12 -1
  54. package/dist/lib/use-project-room.js +5 -2
  55. package/dist/studio-overlays.css +19 -15
  56. package/dist/studio.css +1 -1
  57. package/package.json +5 -4
  58. package/skills/camox/SKILL.md +6 -0
  59. package/skills/camox/references/block-definitions.md +27 -0
  60. package/skills/camox/references/cli-common.md +14 -0
  61. package/skills/camox/references/cli-content.md +11 -0
  62. package/skills/camox/references/field-styling.md +4 -4
  63. package/skills/camoxify/SKILL.md +14 -0
@@ -6,7 +6,7 @@ function getTextStyleData(format) {
6
6
  highlight: false,
7
7
  bold: !!(format & FORMAT_FLAGS.bold),
8
8
  italic: !!(format & FORMAT_FLAGS.italic),
9
- underline: !!(format & FORMAT_FLAGS.underline)
9
+ strikethrough: !!(format & FORMAT_FLAGS.strikethrough)
10
10
  };
11
11
  }
12
12
  function getTextAppearance(format, styles) {
@@ -16,7 +16,7 @@ function getTextAppearance(format, styles) {
16
16
  className: custom?.className,
17
17
  style: {
18
18
  ...flags.bold && flags.italic ? { fontStyle: "italic" } : {},
19
- ...flags.underline ? { textDecorationLine: "underline" } : {},
19
+ ...flags.strikethrough ? { textDecorationLine: "line-through" } : {},
20
20
  ...custom?.style
21
21
  }
22
22
  };
@@ -27,7 +27,7 @@ function getHighlightStyle(styles) {
27
27
  highlight: true,
28
28
  bold: false,
29
29
  italic: false,
30
- underline: false
30
+ strikethrough: false
31
31
  });
32
32
  return {
33
33
  className: custom?.className,
@@ -2,20 +2,21 @@ import { transformImageUrl } from "../../../core/lib/imageTransform.js";
2
2
  import { cn } from "../../../lib/utils.js";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { FileIcon } from "lucide-react";
5
+ import { FileIcon, Play } from "lucide-react";
6
6
 
7
7
  //#region src/features/content/components/AssetCard.tsx
8
8
  const OPAQUE_IMAGE_MIME_TYPES = new Set(["image/jpeg", "image/jpg"]);
9
9
  const AssetCard = (t0) => {
10
- const $ = c(46);
11
- if ($[0] !== "1047e431261024f9506ec8f4989ecb00b2808af70364054688c5f3d5eb9e1f28") {
12
- for (let $i = 0; $i < 46; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
13
- $[0] = "1047e431261024f9506ec8f4989ecb00b2808af70364054688c5f3d5eb9e1f28";
10
+ const $ = c(50);
11
+ if ($[0] !== "9aebb85bb22fc4b24c35af733cd21a00df48ad736a0749a2028271c210f9e9e9") {
12
+ for (let $i = 0; $i < 50; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
13
+ $[0] = "9aebb85bb22fc4b24c35af733cd21a00df48ad736a0749a2028271c210f9e9e9";
14
14
  }
15
15
  const { file, selected, onSelect, onOpen } = t0;
16
16
  let extension;
17
17
  let isImage;
18
18
  let isOpaqueImage;
19
+ let isVideo;
19
20
  let t1;
20
21
  let t2;
21
22
  let t3;
@@ -24,38 +25,45 @@ const AssetCard = (t0) => {
24
25
  let t6;
25
26
  if ($[1] !== file.filename || $[2] !== file.id || $[3] !== file.mimeType || $[4] !== onOpen || $[5] !== onSelect || $[6] !== selected) {
26
27
  isImage = file.mimeType?.startsWith("image/");
27
- isOpaqueImage = isImage && OPAQUE_IMAGE_MIME_TYPES.has(file.mimeType ?? "");
28
28
  let t7;
29
- if ($[16] !== file.filename) {
30
- t7 = file.filename?.split(".").pop()?.toUpperCase() ?? "";
31
- $[16] = file.filename;
32
- $[17] = t7;
33
- } else t7 = $[17];
34
- extension = t7;
29
+ if ($[17] !== file.mimeType) {
30
+ t7 = file.mimeType?.startsWith("video/");
31
+ $[17] = file.mimeType;
32
+ $[18] = t7;
33
+ } else t7 = $[18];
34
+ isVideo = t7;
35
+ isOpaqueImage = isImage && OPAQUE_IMAGE_MIME_TYPES.has(file.mimeType ?? "");
36
+ let t8;
37
+ if ($[19] !== file.filename) {
38
+ t8 = file.filename?.split(".").pop()?.toUpperCase() ?? "";
39
+ $[19] = file.filename;
40
+ $[20] = t8;
41
+ } else t8 = $[20];
42
+ extension = t8;
35
43
  t2 = "button";
36
44
  t3 = file.id;
37
- const t8 = selected ? "bg-primary/20 border-2 border-primary" : "hover:bg-accent/75";
38
- if ($[18] !== t8) {
39
- t4 = cn("group flex flex-col gap-1.5 rounded-lg p-2 text-left border-2 border-transparent", t8);
40
- $[18] = t8;
41
- $[19] = t4;
42
- } else t4 = $[19];
43
- if ($[20] !== onSelect) {
45
+ const t9 = selected ? "bg-primary/20 border-2 border-primary" : "hover:bg-accent/75";
46
+ if ($[21] !== t9) {
47
+ t4 = cn("group flex flex-col gap-1.5 rounded-lg p-2 text-left border-2 border-transparent", t9);
48
+ $[21] = t9;
49
+ $[22] = t4;
50
+ } else t4 = $[22];
51
+ if ($[23] !== onSelect) {
44
52
  t5 = (e) => {
45
53
  e.stopPropagation();
46
54
  onSelect();
47
55
  };
48
- $[20] = onSelect;
49
- $[21] = t5;
50
- } else t5 = $[21];
51
- if ($[22] !== onOpen) {
56
+ $[23] = onSelect;
57
+ $[24] = t5;
58
+ } else t5 = $[24];
59
+ if ($[25] !== onOpen) {
52
60
  t6 = (e_0) => {
53
61
  e_0.stopPropagation();
54
62
  onOpen();
55
63
  };
56
- $[22] = onOpen;
57
- $[23] = t6;
58
- } else t6 = $[23];
64
+ $[25] = onOpen;
65
+ $[26] = t6;
66
+ } else t6 = $[26];
59
67
  t1 = cn("flex aspect-4/3 w-full items-center justify-center overflow-hidden rounded-sm", isOpaqueImage && "bg-muted", !isImage && "bg-muted", isImage && !isOpaqueImage && "checkered p-1.5");
60
68
  $[1] = file.filename;
61
69
  $[2] = file.id;
@@ -66,25 +74,27 @@ const AssetCard = (t0) => {
66
74
  $[7] = extension;
67
75
  $[8] = isImage;
68
76
  $[9] = isOpaqueImage;
69
- $[10] = t1;
70
- $[11] = t2;
71
- $[12] = t3;
72
- $[13] = t4;
73
- $[14] = t5;
74
- $[15] = t6;
77
+ $[10] = isVideo;
78
+ $[11] = t1;
79
+ $[12] = t2;
80
+ $[13] = t3;
81
+ $[14] = t4;
82
+ $[15] = t5;
83
+ $[16] = t6;
75
84
  } else {
76
85
  extension = $[7];
77
86
  isImage = $[8];
78
87
  isOpaqueImage = $[9];
79
- t1 = $[10];
80
- t2 = $[11];
81
- t3 = $[12];
82
- t4 = $[13];
83
- t5 = $[14];
84
- t6 = $[15];
88
+ isVideo = $[10];
89
+ t1 = $[11];
90
+ t2 = $[12];
91
+ t3 = $[13];
92
+ t4 = $[14];
93
+ t5 = $[15];
94
+ t6 = $[16];
85
95
  }
86
96
  let t7;
87
- if ($[24] !== extension || $[25] !== file.alt || $[26] !== file.filename || $[27] !== file.mimeType || $[28] !== file.size || $[29] !== file.url || $[30] !== isImage || $[31] !== isOpaqueImage) {
97
+ if ($[27] !== extension || $[28] !== file.alt || $[29] !== file.filename || $[30] !== file.mimeType || $[31] !== file.size || $[32] !== file.url || $[33] !== isImage || $[34] !== isOpaqueImage || $[35] !== isVideo) {
88
98
  t7 = isImage ? /* @__PURE__ */ jsx("img", {
89
99
  src: transformImageUrl(file.url, {
90
100
  width: 480,
@@ -94,6 +104,27 @@ const AssetCard = (t0) => {
94
104
  alt: file.alt || file.filename,
95
105
  draggable: false,
96
106
  className: cn("pointer-events-none h-full w-full", isOpaqueImage ? "object-cover" : "object-contain")
107
+ }) : isVideo ? /* @__PURE__ */ jsxs("div", {
108
+ className: "pointer-events-none relative h-full w-full",
109
+ children: [/* @__PURE__ */ jsx("video", {
110
+ src: file.url,
111
+ muted: true,
112
+ playsInline: true,
113
+ preload: "metadata",
114
+ "aria-hidden": "true",
115
+ className: "h-full w-full object-cover",
116
+ onLoadedMetadata: _temp
117
+ }, file.url), /* @__PURE__ */ jsx("span", {
118
+ className: "absolute inset-0 flex items-center justify-center",
119
+ children: /* @__PURE__ */ jsx("span", {
120
+ className: "rounded-full bg-black/50 p-2 text-white",
121
+ children: /* @__PURE__ */ jsx(Play, {
122
+ className: "h-5 w-5",
123
+ fill: "currentColor",
124
+ "aria-hidden": "true"
125
+ })
126
+ })
127
+ })]
97
128
  }) : /* @__PURE__ */ jsxs("div", {
98
129
  className: "text-muted-foreground flex flex-col items-center gap-1",
99
130
  children: [/* @__PURE__ */ jsx(FileIcon, { className: "h-8 w-8" }), extension && /* @__PURE__ */ jsx("span", {
@@ -101,37 +132,38 @@ const AssetCard = (t0) => {
101
132
  children: extension
102
133
  })]
103
134
  });
104
- $[24] = extension;
105
- $[25] = file.alt;
106
- $[26] = file.filename;
107
- $[27] = file.mimeType;
108
- $[28] = file.size;
109
- $[29] = file.url;
110
- $[30] = isImage;
111
- $[31] = isOpaqueImage;
112
- $[32] = t7;
113
- } else t7 = $[32];
135
+ $[27] = extension;
136
+ $[28] = file.alt;
137
+ $[29] = file.filename;
138
+ $[30] = file.mimeType;
139
+ $[31] = file.size;
140
+ $[32] = file.url;
141
+ $[33] = isImage;
142
+ $[34] = isOpaqueImage;
143
+ $[35] = isVideo;
144
+ $[36] = t7;
145
+ } else t7 = $[36];
114
146
  let t8;
115
- if ($[33] !== t1 || $[34] !== t7) {
147
+ if ($[37] !== t1 || $[38] !== t7) {
116
148
  t8 = /* @__PURE__ */ jsx("div", {
117
149
  className: t1,
118
150
  children: t7
119
151
  });
120
- $[33] = t1;
121
- $[34] = t7;
122
- $[35] = t8;
123
- } else t8 = $[35];
152
+ $[37] = t1;
153
+ $[38] = t7;
154
+ $[39] = t8;
155
+ } else t8 = $[39];
124
156
  let t9;
125
- if ($[36] !== file.filename) {
157
+ if ($[40] !== file.filename) {
126
158
  t9 = /* @__PURE__ */ jsx("p", {
127
159
  className: "line-clamp-2 px-0.5 text-xs break-all",
128
160
  children: file.filename
129
161
  });
130
- $[36] = file.filename;
131
- $[37] = t9;
132
- } else t9 = $[37];
162
+ $[40] = file.filename;
163
+ $[41] = t9;
164
+ } else t9 = $[41];
133
165
  let t10;
134
- if ($[38] !== t2 || $[39] !== t3 || $[40] !== t4 || $[41] !== t5 || $[42] !== t6 || $[43] !== t8 || $[44] !== t9) {
166
+ if ($[42] !== t2 || $[43] !== t3 || $[44] !== t4 || $[45] !== t5 || $[46] !== t6 || $[47] !== t8 || $[48] !== t9) {
135
167
  t10 = /* @__PURE__ */ jsxs("button", {
136
168
  type: t2,
137
169
  "data-asset-id": t3,
@@ -140,17 +172,21 @@ const AssetCard = (t0) => {
140
172
  onDoubleClick: t6,
141
173
  children: [t8, t9]
142
174
  });
143
- $[38] = t2;
144
- $[39] = t3;
145
- $[40] = t4;
146
- $[41] = t5;
147
- $[42] = t6;
148
- $[43] = t8;
149
- $[44] = t9;
150
- $[45] = t10;
151
- } else t10 = $[45];
175
+ $[42] = t2;
176
+ $[43] = t3;
177
+ $[44] = t4;
178
+ $[45] = t5;
179
+ $[46] = t6;
180
+ $[47] = t8;
181
+ $[48] = t9;
182
+ $[49] = t10;
183
+ } else t10 = $[49];
152
184
  return t10;
153
185
  };
186
+ function _temp(event) {
187
+ const video = event.currentTarget;
188
+ if (Number.isFinite(video.duration) && video.duration > 0) video.currentTime = Math.min(.1, video.duration / 2);
189
+ }
154
190
 
155
191
  //#endregion
156
192
  export { AssetCard };
@@ -9,7 +9,8 @@ import { blockQueries } from "../../lib/queries.js";
9
9
  import { usePageDestinations } from "../../hooks/use-page-destinations.js";
10
10
  import { cn } from "../../lib/utils.js";
11
11
  import { SharedChromeContext } from "../runtime/SharedChromeContext.js";
12
- import { previewStore, selectIsEditMode, selectPreviewSource } from "./previewStore.js";
12
+ import { areCommentsEnabled } from "./commentsEnabled.js";
13
+ import { previewStore, selectIsCommentMode, selectIsEditMode, selectPreviewSource } from "./previewStore.js";
13
14
  import { Navbar } from "../studio/components/Navbar.js";
14
15
  import { CreatePageModal } from "./components/CreatePageModal.js";
15
16
  import { EDIT_MODE_SHORTCUT } from "./previewConstants.js";
@@ -37,9 +38,9 @@ function getMobileStudioSnapshot() {
37
38
  }
38
39
  function useIsMobileStudio() {
39
40
  const $ = c(1);
40
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
41
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
41
42
  for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
42
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
43
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
43
44
  }
44
45
  return React.useSyncExternalStore(subscribeToMobileStudio, getMobileStudioSnapshot, _temp);
45
46
  }
@@ -72,9 +73,9 @@ function pageStructureQueryFn(path, projectSlug, source) {
72
73
  }
73
74
  function usePreviewedPage() {
74
75
  const $ = c(11);
75
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
76
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
76
77
  for (let $i = 0; $i < 11; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
77
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
78
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
78
79
  }
79
80
  const { pathname } = useLocation();
80
81
  const projectSlug = useProjectSlug();
@@ -110,9 +111,9 @@ function usePreviewedPage() {
110
111
  }
111
112
  const BlockRenderer = (t0) => {
112
113
  const $ = c(23);
113
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
114
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
114
115
  for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
115
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
116
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
116
117
  }
117
118
  const { blockId, mode, showAddBlockTop, showAddBlockBottom } = t0;
118
119
  const previewSource = useSelector(previewStore, selectPreviewSource);
@@ -255,9 +256,9 @@ const PageContent = () => {
255
256
  };
256
257
  function useHydrateDraftCache() {
257
258
  const $ = c(7);
258
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
259
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
259
260
  for (let $i = 0; $i < 7; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
260
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
261
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
261
262
  }
262
263
  const isAuthenticated = useIsAuthenticated();
263
264
  const queryClient = useQueryClient();
@@ -308,9 +309,9 @@ function useHydrateDraftCache() {
308
309
  function _temp2() {}
309
310
  const CamoxPreview = (t0) => {
310
311
  const $ = c(4);
311
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
312
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
312
313
  for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
313
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
314
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
314
315
  }
315
316
  const { children } = t0;
316
317
  const pageData = usePreviewedPage();
@@ -329,10 +330,10 @@ const CamoxPreview = (t0) => {
329
330
  };
330
331
  /** Studio chrome is shared; only curated previews require a Camox page record. */
331
332
  const PreviewShell = (t0) => {
332
- const $ = c(59);
333
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
334
- for (let $i = 0; $i < 59; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
335
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
333
+ const $ = c(61);
334
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
335
+ for (let $i = 0; $i < 61; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
336
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
336
337
  }
337
338
  const { children, pageData, hasLiveVersion: t1, derivedLayoutId, derivedLayout } = t0;
338
339
  const hasLiveVersion = t1 === void 0 ? false : t1;
@@ -340,6 +341,7 @@ const PreviewShell = (t0) => {
340
341
  const isMobileStudio = useIsMobileStudio();
341
342
  const sharedChrome = React.useContext(SharedChromeContext);
342
343
  const isEditMode = useSelector(previewStore, selectIsEditMode);
344
+ const isCommentMode = useSelector(previewStore, selectIsCommentMode);
343
345
  const isToolbarHidden = useSelector(previewStore, _temp3);
344
346
  const isAddBlockSidebarOpen = useSelector(previewStore, _temp4);
345
347
  const previewSource = useSelector(previewStore, selectPreviewSource);
@@ -363,7 +365,7 @@ const PreviewShell = (t0) => {
363
365
  React.useEffect(t2, t3);
364
366
  let t4;
365
367
  let t5;
366
- if ($[4] !== hasLiveCheckpoint || $[5] !== isAuthenticated || $[6] !== isEditMode || $[7] !== isMobileStudio || $[8] !== previewSource) {
368
+ if ($[4] !== hasLiveCheckpoint || $[5] !== isAuthenticated || $[6] !== isCommentMode || $[7] !== isEditMode || $[8] !== isMobileStudio || $[9] !== pageData || $[10] !== previewSource) {
367
369
  t4 = () => {
368
370
  const actions = [
369
371
  {
@@ -393,6 +395,25 @@ const PreviewShell = (t0) => {
393
395
  execute: _temp6,
394
396
  shortcut: EDIT_MODE_SHORTCUT
395
397
  },
398
+ {
399
+ id: "enter-comment-mode",
400
+ label: "Leave feedback",
401
+ aliases: [
402
+ "Comment",
403
+ "Comment mode",
404
+ "Show feedback"
405
+ ],
406
+ groupLabel: "Preview",
407
+ checkIfAvailable: () => isAuthenticated && !isMobileStudio && pageData != null && areCommentsEnabled() && !isCommentMode,
408
+ execute: () => {
409
+ if (!isEditMode) previewStore.send({ type: "enterEditMode" });
410
+ previewStore.send({
411
+ type: "setCommentMode",
412
+ enabled: true
413
+ });
414
+ },
415
+ shortcut: { key: "c" }
416
+ },
396
417
  {
397
418
  id: "preview-live-content",
398
419
  label: "Preview live content",
@@ -448,43 +469,47 @@ const PreviewShell = (t0) => {
448
469
  };
449
470
  t5 = [
450
471
  isEditMode,
472
+ isCommentMode,
451
473
  isAuthenticated,
452
474
  isMobileStudio,
475
+ pageData,
453
476
  previewSource,
454
477
  hasLiveCheckpoint
455
478
  ];
456
479
  $[4] = hasLiveCheckpoint;
457
480
  $[5] = isAuthenticated;
458
- $[6] = isEditMode;
459
- $[7] = isMobileStudio;
460
- $[8] = previewSource;
461
- $[9] = t4;
462
- $[10] = t5;
481
+ $[6] = isCommentMode;
482
+ $[7] = isEditMode;
483
+ $[8] = isMobileStudio;
484
+ $[9] = pageData;
485
+ $[10] = previewSource;
486
+ $[11] = t4;
487
+ $[12] = t5;
463
488
  } else {
464
- t4 = $[9];
465
- t5 = $[10];
489
+ t4 = $[11];
490
+ t5 = $[12];
466
491
  }
467
492
  React.useEffect(t4, t5);
468
493
  if (!isAuthenticated) {
469
494
  let t6;
470
- if ($[11] !== children) {
495
+ if ($[13] !== children) {
471
496
  t6 = /* @__PURE__ */ jsx(Fragment, { children });
472
- $[11] = children;
473
- $[12] = t6;
474
- } else t6 = $[12];
497
+ $[13] = children;
498
+ $[14] = t6;
499
+ } else t6 = $[14];
475
500
  return t6;
476
501
  }
477
502
  const t6 = sharedChrome ? "h-full" : "h-screen";
478
503
  const t7 = !isEditMode && "bg-black";
479
504
  let t8;
480
- if ($[13] !== t6 || $[14] !== t7) {
505
+ if ($[15] !== t6 || $[16] !== t7) {
481
506
  t8 = cn("bg-background flex flex-col overflow-hidden", t6, t7);
482
- $[13] = t6;
483
- $[14] = t7;
484
- $[15] = t8;
485
- } else t8 = $[15];
507
+ $[15] = t6;
508
+ $[16] = t7;
509
+ $[17] = t8;
510
+ } else t8 = $[17];
486
511
  let t9;
487
- if ($[16] !== isAddBlockSidebarOpen || $[17] !== isMobileStudio || $[18] !== isToolbarHidden || $[19] !== pageData || $[20] !== sharedChrome) {
512
+ if ($[18] !== isAddBlockSidebarOpen || $[19] !== isMobileStudio || $[20] !== isToolbarHidden || $[21] !== pageData || $[22] !== sharedChrome) {
488
513
  t9 = !sharedChrome && !isMobileStudio && !isToolbarHidden && /* @__PURE__ */ jsxs("div", {
489
514
  className: "relative",
490
515
  children: [/* @__PURE__ */ jsx(Navbar, { isPreview: true }), pageData && isAddBlockSidebarOpen && /* @__PURE__ */ jsx("div", {
@@ -493,15 +518,15 @@ const PreviewShell = (t0) => {
493
518
  onClick: _temp10
494
519
  })]
495
520
  });
496
- $[16] = isAddBlockSidebarOpen;
497
- $[17] = isMobileStudio;
498
- $[18] = isToolbarHidden;
499
- $[19] = pageData;
500
- $[20] = sharedChrome;
501
- $[21] = t9;
502
- } else t9 = $[21];
521
+ $[18] = isAddBlockSidebarOpen;
522
+ $[19] = isMobileStudio;
523
+ $[20] = isToolbarHidden;
524
+ $[21] = pageData;
525
+ $[22] = sharedChrome;
526
+ $[23] = t9;
527
+ } else t9 = $[23];
503
528
  let t10;
504
- if ($[22] !== derivedLayout || $[23] !== derivedLayoutId || $[24] !== isEditMode || $[25] !== isMobileStudio || $[26] !== pageData) {
529
+ if ($[24] !== derivedLayout || $[25] !== derivedLayoutId || $[26] !== isEditMode || $[27] !== isMobileStudio || $[28] !== pageData) {
505
530
  t10 = !isMobileStudio && (pageData || derivedLayoutId) && /* @__PURE__ */ jsx("div", {
506
531
  className: isEditMode ? "contents" : "hidden",
507
532
  children: /* @__PURE__ */ jsx(LeftSidebar, {
@@ -509,38 +534,38 @@ const PreviewShell = (t0) => {
509
534
  derivedLayout
510
535
  })
511
536
  });
512
- $[22] = derivedLayout;
513
- $[23] = derivedLayoutId;
514
- $[24] = isEditMode;
515
- $[25] = isMobileStudio;
516
- $[26] = pageData;
517
- $[27] = t10;
518
- } else t10 = $[27];
537
+ $[24] = derivedLayout;
538
+ $[25] = derivedLayoutId;
539
+ $[26] = isEditMode;
540
+ $[27] = isMobileStudio;
541
+ $[28] = pageData;
542
+ $[29] = t10;
543
+ } else t10 = $[29];
519
544
  const t11 = pageData?.page;
520
545
  const t12 = pageData?.projectName;
521
546
  const t13 = pageData?.page.id;
522
547
  const t14 = pageData?.page.status;
523
548
  let t15;
524
- if ($[28] !== hasLiveCheckpoint || $[29] !== t13 || $[30] !== t14) {
549
+ if ($[30] !== hasLiveCheckpoint || $[31] !== t13 || $[32] !== t14) {
525
550
  t15 = {
526
551
  pageId: t13,
527
552
  pageStatus: t14,
528
553
  hasLiveVersion: hasLiveCheckpoint
529
554
  };
530
- $[28] = hasLiveCheckpoint;
531
- $[29] = t13;
532
- $[30] = t14;
533
- $[31] = t15;
534
- } else t15 = $[31];
555
+ $[30] = hasLiveCheckpoint;
556
+ $[31] = t13;
557
+ $[32] = t14;
558
+ $[33] = t15;
559
+ } else t15 = $[33];
535
560
  let t16;
536
- if ($[32] !== isEditMode || $[33] !== isMobileStudio) {
561
+ if ($[34] !== isEditMode || $[35] !== isMobileStudio) {
537
562
  t16 = !isMobileStudio && isEditMode && /* @__PURE__ */ jsx(PreviewToolbarSpacer, {});
538
- $[32] = isEditMode;
539
- $[33] = isMobileStudio;
540
- $[34] = t16;
541
- } else t16 = $[34];
563
+ $[34] = isEditMode;
564
+ $[35] = isMobileStudio;
565
+ $[36] = t16;
566
+ } else t16 = $[36];
542
567
  let t17;
543
- if ($[35] !== children || $[36] !== isMobileStudio || $[37] !== t11 || $[38] !== t12 || $[39] !== t15 || $[40] !== t16) {
568
+ if ($[37] !== children || $[38] !== isMobileStudio || $[39] !== t11 || $[40] !== t12 || $[41] !== t15 || $[42] !== t16) {
544
569
  t17 = /* @__PURE__ */ jsxs(PreviewPanel, {
545
570
  isMobileExperience: isMobileStudio,
546
571
  page: t11,
@@ -548,28 +573,28 @@ const PreviewShell = (t0) => {
548
573
  toolbarProps: t15,
549
574
  children: [children, t16]
550
575
  });
551
- $[35] = children;
552
- $[36] = isMobileStudio;
553
- $[37] = t11;
554
- $[38] = t12;
555
- $[39] = t15;
556
- $[40] = t16;
557
- $[41] = t17;
558
- } else t17 = $[41];
576
+ $[37] = children;
577
+ $[38] = isMobileStudio;
578
+ $[39] = t11;
579
+ $[40] = t12;
580
+ $[41] = t15;
581
+ $[42] = t16;
582
+ $[43] = t17;
583
+ } else t17 = $[43];
559
584
  let t18;
560
- if ($[42] !== derivedLayoutId || $[43] !== isEditMode || $[44] !== isMobileStudio || $[45] !== pageData?.page) {
585
+ if ($[44] !== derivedLayoutId || $[45] !== isEditMode || $[46] !== isMobileStudio || $[47] !== pageData?.page) {
561
586
  t18 = !isMobileStudio && isEditMode && /* @__PURE__ */ jsx(RightSidebar, {
562
587
  pageId: pageData?.page.id,
563
588
  derivedLayoutId
564
589
  });
565
- $[42] = derivedLayoutId;
566
- $[43] = isEditMode;
567
- $[44] = isMobileStudio;
568
- $[45] = pageData?.page;
569
- $[46] = t18;
570
- } else t18 = $[46];
590
+ $[44] = derivedLayoutId;
591
+ $[45] = isEditMode;
592
+ $[46] = isMobileStudio;
593
+ $[47] = pageData?.page;
594
+ $[48] = t18;
595
+ } else t18 = $[48];
571
596
  let t19;
572
- if ($[47] !== t10 || $[48] !== t17 || $[49] !== t18) {
597
+ if ($[49] !== t10 || $[50] !== t17 || $[51] !== t18) {
573
598
  t19 = /* @__PURE__ */ jsxs("div", {
574
599
  className: "flex h-full flex-row items-stretch",
575
600
  children: [
@@ -578,20 +603,20 @@ const PreviewShell = (t0) => {
578
603
  t18
579
604
  ]
580
605
  });
581
- $[47] = t10;
582
- $[48] = t17;
583
- $[49] = t18;
584
- $[50] = t19;
585
- } else t19 = $[50];
606
+ $[49] = t10;
607
+ $[50] = t17;
608
+ $[51] = t18;
609
+ $[52] = t19;
610
+ } else t19 = $[52];
586
611
  let t20;
587
- if ($[51] !== isEditMode || $[52] !== isMobileStudio) {
612
+ if ($[53] !== isEditMode || $[54] !== isMobileStudio) {
588
613
  t20 = (isMobileStudio || isEditMode) && /* @__PURE__ */ jsx(CreatePageModal, {});
589
- $[51] = isEditMode;
590
- $[52] = isMobileStudio;
591
- $[53] = t20;
592
- } else t20 = $[53];
614
+ $[53] = isEditMode;
615
+ $[54] = isMobileStudio;
616
+ $[55] = t20;
617
+ } else t20 = $[55];
593
618
  let t21;
594
- if ($[54] !== t19 || $[55] !== t20 || $[56] !== t8 || $[57] !== t9) {
619
+ if ($[56] !== t19 || $[57] !== t20 || $[58] !== t8 || $[59] !== t9) {
595
620
  t21 = /* @__PURE__ */ jsxs("div", {
596
621
  className: t8,
597
622
  children: [
@@ -600,19 +625,19 @@ const PreviewShell = (t0) => {
600
625
  t20
601
626
  ]
602
627
  });
603
- $[54] = t19;
604
- $[55] = t20;
605
- $[56] = t8;
606
- $[57] = t9;
607
- $[58] = t21;
608
- } else t21 = $[58];
628
+ $[56] = t19;
629
+ $[57] = t20;
630
+ $[58] = t8;
631
+ $[59] = t9;
632
+ $[60] = t21;
633
+ } else t21 = $[60];
609
634
  return t21;
610
635
  };
611
636
  function usePreviewPagesActions() {
612
637
  const $ = c(6);
613
- if ($[0] !== "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082") {
638
+ if ($[0] !== "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c") {
614
639
  for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
615
- $[0] = "2d1a4df08feec350ec60cc84fec5c50c421655f0e335816baf3bbe36ccd11082";
640
+ $[0] = "1f7f5b8cfc80775a4d8d5a69dedeb5c289bf8de78288daf387d6edc5d5f0b09c";
616
641
  }
617
642
  const navigate = useNavigate();
618
643
  const { pathname } = useLocation();
@@ -1,7 +1,7 @@
1
1
  //#region src/features/preview/commentsEnabled.ts
2
- /** Opt-in prototype flag, replaced by the Camox Vite plugin in both client and SSR builds. */
2
+ /** Comments follow the experimental-features flag in both client and SSR builds. */
3
3
  function areCommentsEnabled() {
4
- return typeof __CAMOX_ENABLE_COMMENTS__ !== "undefined" && __CAMOX_ENABLE_COMMENTS__;
4
+ return typeof __CAMOX_ENABLE_EXPERIMENTAL_FEATURES__ !== "undefined" && __CAMOX_ENABLE_EXPERIMENTAL_FEATURES__;
5
5
  }
6
6
 
7
7
  //#endregion