camox 0.17.0 → 0.17.3

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.
@@ -1,9 +1,9 @@
1
+ import { trackClientEvent } from "../../../lib/telemetry-client.js";
1
2
  import { previewStore } from "../previewStore.js";
2
3
  import { useProjectSlug } from "../../../lib/auth.js";
3
4
  import { blockQueries, layoutQueries, pageMutations, pageQueries, projectQueries } from "../../../lib/queries.js";
4
5
  import { formatPathSegment } from "../../../lib/utils.js";
5
6
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
6
- import { trackClientEvent } from "../../../lib/analytics-client.js";
7
7
  import { PageLocationFieldset } from "./PageLocationFieldset.js";
8
8
  import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
9
9
  import { ShikiMarkdown } from "./ShikiMarkdown.js";
@@ -28,9 +28,9 @@ import { Switch } from "@camox/ui/switch";
28
28
  //#region src/features/preview/components/EditPageModal.tsx
29
29
  const EditPageModal = () => {
30
30
  const $ = c(3);
31
- if ($[0] !== "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59") {
31
+ if ($[0] !== "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2") {
32
32
  for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
33
- $[0] = "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59";
33
+ $[0] = "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2";
34
34
  }
35
35
  const editingPageId = useSelector(previewStore, _temp);
36
36
  let t0;
@@ -225,10 +225,17 @@ const EditPageModalContent = ({ pageId }) => {
225
225
  children: [/* @__PURE__ */ jsx(Switch, {
226
226
  id: "ai-seo",
227
227
  checked: page.aiSeoEnabled !== false,
228
- onCheckedChange: (checked) => setAiSeo.mutate({
229
- id: page.id,
230
- enabled: checked
231
- })
228
+ onCheckedChange: (checked) => {
229
+ setAiSeo.mutate({
230
+ id: page.id,
231
+ enabled: checked
232
+ });
233
+ trackClientEvent("ai_metadata_toggled", {
234
+ target: "page",
235
+ enabled: checked,
236
+ pageId: page.id
237
+ });
238
+ }
232
239
  }), /* @__PURE__ */ jsx(Label, {
233
240
  htmlFor: "ai-seo",
234
241
  children: "AI metadata"
@@ -295,9 +302,9 @@ function truncateText(text, maxLen) {
295
302
  }
296
303
  const SearchEnginePreview = (t0) => {
297
304
  const $ = c(17);
298
- if ($[0] !== "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59") {
305
+ if ($[0] !== "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2") {
299
306
  for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
300
- $[0] = "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59";
307
+ $[0] = "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2";
301
308
  }
302
309
  const { page, metaTitle, metaDescription } = t0;
303
310
  const url = `${typeof window !== "undefined" ? window.location.origin : ""}${page.fullPath}`;
@@ -380,9 +387,9 @@ const SearchEnginePreview = (t0) => {
380
387
  };
381
388
  const SocialPreviewSection = (t0) => {
382
389
  const $ = c(23);
383
- if ($[0] !== "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59") {
390
+ if ($[0] !== "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2") {
384
391
  for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
385
- $[0] = "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59";
392
+ $[0] = "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2";
386
393
  }
387
394
  const { page, metaTitle, metaDescription, layoutId, projectName } = t0;
388
395
  const pageMetaTitle = page.metaTitle ?? page.pathSegment;
@@ -493,9 +500,9 @@ const SocialPreviewSection = (t0) => {
493
500
  };
494
501
  const PageMarkdownPreview = (t0) => {
495
502
  const $ = c(9);
496
- if ($[0] !== "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59") {
503
+ if ($[0] !== "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2") {
497
504
  for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
498
- $[0] = "77e099cc2262abd4d5933b5ccdac9b8a465b2ec9734a24e689cb553e1f237c59";
505
+ $[0] = "1a44c3b62f2d464ddc4fb38012b10897c6c1b331adf4c50075c0f78c681dcec2";
499
506
  }
500
507
  const { pageId, metaTitle, metaDescription } = t0;
501
508
  let t1;
@@ -9,9 +9,9 @@ import * as React from "react";
9
9
  //#region src/features/preview/components/Overlays.tsx
10
10
  const Overlays = (t0) => {
11
11
  const $ = c(15);
12
- if ($[0] !== "c0f7c4c8a7e0ca42965ee74bb3077e5ef65c52138c6801bfc431adeaaaed697c") {
12
+ if ($[0] !== "1bd993485c8b6ef80e5869cbd59723cb7bd4d85cf57877fd5be25c69a7427872") {
13
13
  for (let $i = 0; $i < 15; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
14
- $[0] = "c0f7c4c8a7e0ca42965ee74bb3077e5ef65c52138c6801bfc431adeaaaed697c";
14
+ $[0] = "1bd993485c8b6ef80e5869cbd59723cb7bd4d85cf57877fd5be25c69a7427872";
15
15
  }
16
16
  const { iframeElement } = t0;
17
17
  const isPageContentSheetOpen = useSelector(previewStore, _temp);
@@ -37,7 +37,8 @@ const Overlays = (t0) => {
37
37
  }
38
38
  previewStore.send({
39
39
  type: "openAddBlockSheet",
40
- afterPosition
40
+ afterPosition,
41
+ via: "overlay"
41
42
  });
42
43
  }
43
44
  };
@@ -1,17 +1,16 @@
1
+ import { trackClientEvent } from "../../../lib/telemetry-client.js";
1
2
  import { previewStore, selectionBlockId, selectionField, selectionItemId } from "../previewStore.js";
2
3
  import { PreviewSideSheet, Sheet } from "./PreviewSideSheet.js";
3
4
  import { actionsStore } from "../../provider/actionsStore.js";
4
5
  import { blockMutations, blockQueries, fileQueries, repeatableItemMutations } from "../../../lib/queries.js";
5
6
  import { isFileMarker } from "../../../lib/normalized-data.js";
6
7
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
7
- import { trackClientEvent } from "../../../lib/analytics-client.js";
8
8
  import { fieldTypesDictionary } from "../../../core/lib/fieldTypes.js";
9
9
  import { SingleAssetFieldEditor } from "./AssetFieldEditor.js";
10
10
  import { useRepeatableItemActions } from "./useRepeatableItemActions.js";
11
11
  import { ItemFieldsEditor, formatFieldName } from "./ItemFieldsEditor.js";
12
12
  import { LinkFieldEditor } from "./LinkFieldEditor.js";
13
13
  import { MultipleAssetFieldEditor } from "./MultipleAssetFieldEditor.js";
14
- import { usePreviewedPage } from "../CamoxPreview.js";
15
14
  import { Label } from "@camox/ui/label";
16
15
  import { useMutation, useQueries, useQuery } from "@tanstack/react-query";
17
16
  import { useSelector } from "@xstate/store-react";
@@ -109,7 +108,6 @@ const PageContentSheet = () => {
109
108
  const blockId = selectionBlockId(selection);
110
109
  const currentItemId = selectionItemId(selection);
111
110
  const fieldInfo = selectionField(selection);
112
- const page = usePreviewedPage();
113
111
  const { data: blockBundle } = useQuery({
114
112
  ...blockQueries.get(blockId),
115
113
  enabled: blockId != null
@@ -219,16 +217,19 @@ const PageContentSheet = () => {
219
217
  assetFieldName,
220
218
  currentSchema
221
219
  ]);
220
+ const sessionDirtyRef = React.useRef(false);
221
+ const trackedOpenRef = React.useRef(false);
222
222
  React.useEffect(() => {
223
- if (isOpen && block) trackClientEvent("content_sheet_opened", {
224
- projectId: page?.page.projectId,
225
- blockType: block.type
226
- });
227
- }, [
228
- isOpen,
229
- block,
230
- page?.page.projectId
231
- ]);
223
+ if (!isOpen) {
224
+ trackedOpenRef.current = false;
225
+ return;
226
+ }
227
+ if (trackedOpenRef.current) return;
228
+ if (!block) return;
229
+ trackedOpenRef.current = true;
230
+ sessionDirtyRef.current = false;
231
+ trackClientEvent("content_sheet_opened", { blockType: block.type });
232
+ }, [isOpen, block]);
232
233
  const fieldIdPrefix = React.useId();
233
234
  const autoFocusFieldName = React.useMemo(() => {
234
235
  if ((selection?.type === "block-field" || selection?.type === "item-field") && (selection.fieldType === "String" || selection.fieldType === "Embed")) return selection.fieldName;
@@ -269,6 +270,7 @@ const PageContentSheet = () => {
269
270
  }, [blockId, isOpen]);
270
271
  const handleBlockFieldChange = React.useCallback((fieldName, value_1) => {
271
272
  if (!block) return;
273
+ sessionDirtyRef.current = true;
272
274
  updateContent.mutate({
273
275
  id: block.id,
274
276
  content: { [fieldName]: value_1 }
@@ -276,6 +278,7 @@ const PageContentSheet = () => {
276
278
  }, [block, updateContent]);
277
279
  const handleItemFieldChange = React.useCallback((fieldName_0, value_2) => {
278
280
  if (currentItemId == null) return;
281
+ sessionDirtyRef.current = true;
279
282
  updateRepeatableContent.mutate({
280
283
  id: currentItemId,
281
284
  content: { [fieldName_0]: value_2 }
@@ -284,6 +287,11 @@ const PageContentSheet = () => {
284
287
  const activeFieldChangeHandler = currentItemId != null ? handleItemFieldChange : handleBlockFieldChange;
285
288
  const handleOpenChange = (open) => {
286
289
  if (open) return;
290
+ if (block && sessionDirtyRef.current) trackClientEvent("block_edited", {
291
+ via: "content-sheet",
292
+ blockType: block.type
293
+ });
294
+ sessionDirtyRef.current = false;
287
295
  if (block && autoFocusFieldName) postToIframe({
288
296
  type: "CAMOX_FOCUS_FIELD_END",
289
297
  fieldId: currentItemId != null ? `${block.id}__${currentItemId}__${autoFocusFieldName}` : `${block.id}__${autoFocusFieldName}`
@@ -395,6 +403,7 @@ const PageContentSheet = () => {
395
403
  }), /* @__PURE__ */ jsxs(Select, {
396
404
  value: value_3,
397
405
  onValueChange: (newValue) => {
406
+ sessionDirtyRef.current = true;
398
407
  updateSettings.mutate({
399
408
  id: block.id,
400
409
  settings: { [field.name]: newValue }
@@ -421,6 +430,7 @@ const PageContentSheet = () => {
421
430
  id: `setting-${field.name}`,
422
431
  checked,
423
432
  onCheckedChange: (newValue_0) => {
433
+ sessionDirtyRef.current = true;
424
434
  updateSettings.mutate({
425
435
  id: block.id,
426
436
  settings: { [field.name]: newValue_0 }
@@ -451,6 +461,7 @@ const PageContentSheet = () => {
451
461
  }), /* @__PURE__ */ jsxs(Select, {
452
462
  value: value_4,
453
463
  onValueChange: (newValue_1) => {
464
+ sessionDirtyRef.current = true;
454
465
  updateRepeatableSettings.mutate({
455
466
  id: currentItemId,
456
467
  settings: { [field_0.name]: newValue_1 }
@@ -477,6 +488,7 @@ const PageContentSheet = () => {
477
488
  id: `item-setting-${field_0.name}`,
478
489
  checked: checked_0,
479
490
  onCheckedChange: (newValue_2) => {
491
+ sessionDirtyRef.current = true;
480
492
  updateRepeatableSettings.mutate({
481
493
  id: currentItemId,
482
494
  settings: { [field_0.name]: newValue_2 }
@@ -24,9 +24,9 @@ import { Accordion } from "@base-ui/react/accordion";
24
24
  //#region src/features/preview/components/PageTree.tsx
25
25
  function useEmbedTitle(url) {
26
26
  const $ = c(4);
27
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
27
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
28
28
  for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
29
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
29
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
30
30
  }
31
31
  const [title, setTitle] = React.useState(null);
32
32
  let t0;
@@ -59,9 +59,9 @@ function _temp(res) {
59
59
  }
60
60
  const FieldItem = (t0) => {
61
61
  const $ = c(30);
62
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
62
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
63
63
  for (let $i = 0; $i < 30; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
64
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
64
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
65
65
  }
66
66
  const { fieldName, value, fieldType, schemaTitle, arrayItemType, isSelected, onFieldClick, onFieldDoubleClick, onMouseEnter, onMouseLeave } = t0;
67
67
  const fetchedEmbedTitle = useEmbedTitle(fieldType === "Embed" ? value : null);
@@ -148,9 +148,9 @@ const FieldItem = (t0) => {
148
148
  };
149
149
  const BlockFields = (t0) => {
150
150
  const $ = c(5);
151
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
151
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
152
152
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
153
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
153
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
154
154
  }
155
155
  const { block } = t0;
156
156
  const schemaProperties = useCamoxApp().getBlockById(block.type)?._internal.contentSchema.properties;
@@ -252,9 +252,9 @@ const BlockFields = (t0) => {
252
252
  };
253
253
  function useBlockTreeItem(block, t0) {
254
254
  const $ = c(17);
255
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
255
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
256
256
  for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
257
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
257
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
258
258
  }
259
259
  const isDragging = t0 === void 0 ? false : t0;
260
260
  const [ellipsisPopoverOpen, setEllipsisPopoverOpen] = React.useState(false);
@@ -336,9 +336,9 @@ function _temp6(state) {
336
336
  }
337
337
  const BlockTreeItemHeader = (t0) => {
338
338
  const $ = c(17);
339
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
339
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
340
340
  for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
341
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
341
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
342
342
  }
343
343
  let children;
344
344
  let className;
@@ -391,9 +391,9 @@ const BlockTreeItemHeader = (t0) => {
391
391
  };
392
392
  const BlockTreeItemTrigger = (t0) => {
393
393
  const $ = c(5);
394
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
394
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
395
395
  for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
396
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
396
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
397
397
  }
398
398
  const { displayText, onClick } = t0;
399
399
  let t1;
@@ -420,9 +420,9 @@ const BlockTreeItemTrigger = (t0) => {
420
420
  };
421
421
  const BlockTreeItemEllipsis = (t0) => {
422
422
  const $ = c(12);
423
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
423
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
424
424
  for (let $i = 0; $i < 12; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
425
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
425
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
426
426
  }
427
427
  let className;
428
428
  let open;
@@ -468,9 +468,9 @@ const BlockTreeItemEllipsis = (t0) => {
468
468
  };
469
469
  const BlockTreeItemContent = (t0) => {
470
470
  const $ = c(3);
471
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
471
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
472
472
  for (let $i = 0; $i < 3; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
473
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
473
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
474
474
  }
475
475
  const { block } = t0;
476
476
  let t1;
@@ -491,9 +491,9 @@ const animateLayoutChanges = (args) => {
491
491
  };
492
492
  const SortableBlock = (t0) => {
493
493
  const $ = c(53);
494
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
494
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
495
495
  for (let $i = 0; $i < 53; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
496
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
496
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
497
497
  }
498
498
  const { block } = t0;
499
499
  const [gripPopoverOpen, setGripPopoverOpen] = React.useState(false);
@@ -682,9 +682,9 @@ const SortableBlock = (t0) => {
682
682
  };
683
683
  const LayoutBlockItem = (t0) => {
684
684
  const $ = c(44);
685
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
685
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
686
686
  for (let $i = 0; $i < 44; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
687
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
687
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
688
688
  }
689
689
  const { block, layoutName } = t0;
690
690
  const camoxApp = useCamoxApp();
@@ -843,9 +843,9 @@ const LayoutBlockItem = (t0) => {
843
843
  };
844
844
  const PageTree = () => {
845
845
  const $ = c(47);
846
- if ($[0] !== "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903") {
846
+ if ($[0] !== "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e") {
847
847
  for (let $i = 0; $i < 47; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
848
- $[0] = "79ab6b120b2bb787a1048ac6df2d27952726deab51bb8be3775e9053c83d0903";
848
+ $[0] = "3438c79b953b86993bcb0e3d161fc8842fabb36537be7c6172ce394e67f78c7e";
849
849
  }
850
850
  const page = usePreviewedPage();
851
851
  const { pageBlocks, beforeBlocks: layoutBeforeBlocks, afterBlocks: layoutAfterBlocks } = usePageBlocks(page);
@@ -1082,7 +1082,10 @@ function _temp9(block_3) {
1082
1082
  return /* @__PURE__ */ jsx(SortableBlock, { block: block_3 }, String(block_3.id));
1083
1083
  }
1084
1084
  function _temp0() {
1085
- return previewStore.send({ type: "openAddBlockSheet" });
1085
+ return previewStore.send({
1086
+ type: "openAddBlockSheet",
1087
+ via: "page-tree"
1088
+ });
1086
1089
  }
1087
1090
 
1088
1091
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { trackClientEvent } from "../../lib/telemetry-client.js";
1
2
  import { toast } from "@camox/ui/toaster";
2
3
  import { createStore } from "@xstate/store-react";
3
4
 
@@ -27,6 +28,7 @@ const previewStore = createStore({
27
28
  isSidebarOpen: true,
28
29
  isPageContentSheetOpen: false,
29
30
  isAddBlockSheetOpen: false,
31
+ addBlockSource: null,
30
32
  isAgentChatSheetOpen: false,
31
33
  isCreatePageModalOpen: false,
32
34
  editingPageId: null,
@@ -44,14 +46,18 @@ const previewStore = createStore({
44
46
  if (context.isPresentationMode) return context;
45
47
  enqueue.effect(() => {
46
48
  toast("Press ⌘ + Enter to restore Camox Studio", { duration: 2500 });
49
+ trackClientEvent("presentation_mode_toggled", { enabled: true });
47
50
  });
48
51
  return {
49
52
  ...context,
50
53
  isPresentationMode: true
51
54
  };
52
55
  },
53
- exitPresentationMode: (context) => {
56
+ exitPresentationMode: (context, _, enqueue) => {
54
57
  if (!context.isPresentationMode) return context;
58
+ enqueue.effect(() => {
59
+ trackClientEvent("presentation_mode_toggled", { enabled: false });
60
+ });
55
61
  return {
56
62
  ...context,
57
63
  isPresentationMode: false
@@ -185,12 +191,14 @@ const previewStore = createStore({
185
191
  openAddBlockSheet: (context, event) => ({
186
192
  ...context,
187
193
  isAddBlockSheetOpen: true,
194
+ addBlockSource: event.via ?? null,
188
195
  peekedBlock: null,
189
196
  peekedBlockPosition: event.afterPosition ?? null
190
197
  }),
191
198
  closeAddBlockSheet: (context) => ({
192
199
  ...context,
193
200
  isAddBlockSheetOpen: false,
201
+ addBlockSource: null,
194
202
  peekedBlock: null,
195
203
  peekedBlockPosition: null
196
204
  }),
@@ -228,10 +236,14 @@ const previewStore = createStore({
228
236
  ...context,
229
237
  isPageContentSheetOpen: false
230
238
  }),
231
- openAgentChatSheet: (context) => ({
232
- ...context,
233
- isAgentChatSheetOpen: true
234
- }),
239
+ openAgentChatSheet: (context, _, enqueue) => {
240
+ if (context.isAgentChatSheetOpen) return context;
241
+ enqueue.effect(() => trackClientEvent("agent_chat_opened"));
242
+ return {
243
+ ...context,
244
+ isAgentChatSheetOpen: true
245
+ };
246
+ },
235
247
  closeAgentChatSheet: (context) => ({
236
248
  ...context,
237
249
  isAgentChatSheetOpen: false
@@ -244,10 +256,14 @@ const previewStore = createStore({
244
256
  ...context,
245
257
  isCreatePageModalOpen: false
246
258
  }),
247
- openEditPageModal: (context, event) => ({
248
- ...context,
249
- editingPageId: event.pageId
250
- }),
259
+ openEditPageModal: (context, event, enqueue) => {
260
+ if (context.editingPageId === event.pageId) return context;
261
+ enqueue.effect(() => trackClientEvent("page_editor_opened", { pageId: event.pageId }));
262
+ return {
263
+ ...context,
264
+ editingPageId: event.pageId
265
+ };
266
+ },
251
267
  closeEditPageModal: (context) => ({
252
268
  ...context,
253
269
  editingPageId: null
@@ -1,3 +1,4 @@
1
+ import { identifyProject, identifyUser } from "../../lib/telemetry-client.js";
1
2
  import { AuthContext, createCamoxAuthClient, useAuthActions, useAuthContext, useProcessOtt, useSignInRedirect } from "../../lib/auth.js";
2
3
  import { initApiClient } from "../../lib/api-client.js";
3
4
  import { projectQueries } from "../../lib/queries.js";
@@ -18,58 +19,51 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools/production";
18
19
  import studioCssUrl from "virtual:camox-studio-css";
19
20
 
20
21
  //#region src/features/provider/CamoxProvider.tsx
21
- const AuthenticatedCamoxProvider = (t0) => {
22
- const $ = c(9);
23
- if ($[0] !== "4aa858f2d01b8522f136fc586f47d0bfc585b3ef0680197aead771149ae36446") {
24
- for (let $i = 0; $i < 9; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
25
- $[0] = "4aa858f2d01b8522f136fc586f47d0bfc585b3ef0680197aead771149ae36446";
26
- }
27
- const { children } = t0;
22
+ const AuthenticatedCamoxProvider = ({ children }) => {
28
23
  useAdminShortcuts();
29
24
  useCommandPaletteActions();
30
25
  useThemeActions();
31
26
  useAuthActions();
32
27
  useNavbarActions();
33
28
  usePreviewPagesActions();
34
- const { apiUrl, projectSlug } = React.useContext(AuthContext);
35
- let t1;
36
- if ($[1] !== projectSlug) {
37
- t1 = projectQueries.getBySlug(projectSlug);
38
- $[1] = projectSlug;
39
- $[2] = t1;
40
- } else t1 = $[2];
41
- const { data: project } = useQuery(t1);
29
+ const { authClient, apiUrl, projectSlug, environmentName } = React.useContext(AuthContext);
30
+ const { data: session } = authClient.useSession();
31
+ const user = session?.user;
32
+ const { data: project } = useQuery(projectQueries.getBySlug(projectSlug));
42
33
  useProjectRoom(apiUrl, project?.id);
34
+ React.useEffect(() => {
35
+ if (!user) return;
36
+ identifyUser({
37
+ userId: user.id,
38
+ email: user.email,
39
+ name: user.name
40
+ });
41
+ }, [user]);
42
+ React.useEffect(() => {
43
+ if (!project) return;
44
+ identifyProject({
45
+ projectId: project.id,
46
+ projectSlug,
47
+ projectName: project.name,
48
+ environmentName
49
+ });
50
+ }, [
51
+ project,
52
+ projectSlug,
53
+ environmentName
54
+ ]);
43
55
  const { theme } = useApplyTheme();
44
- let t2;
45
- if ($[3] !== theme) {
46
- t2 = /* @__PURE__ */ jsx(Toaster, { theme });
47
- $[3] = theme;
48
- $[4] = t2;
49
- } else t2 = $[4];
50
- let t3;
51
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
52
- t3 = /* @__PURE__ */ jsx(CommandPalette, {});
53
- $[5] = t3;
54
- } else t3 = $[5];
55
- let t4;
56
- if ($[6] !== children || $[7] !== t2) {
57
- t4 = /* @__PURE__ */ jsxs(Fragment, { children: [
58
- children,
59
- t2,
60
- t3
61
- ] });
62
- $[6] = children;
63
- $[7] = t2;
64
- $[8] = t4;
65
- } else t4 = $[8];
66
- return t4;
56
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
57
+ children,
58
+ /* @__PURE__ */ jsx(Toaster, { theme }),
59
+ /* @__PURE__ */ jsx(CommandPalette, {})
60
+ ] });
67
61
  };
68
62
  const UnauthenticatedCamoxProvider = (t0) => {
69
63
  const $ = c(17);
70
- if ($[0] !== "4aa858f2d01b8522f136fc586f47d0bfc585b3ef0680197aead771149ae36446") {
64
+ if ($[0] !== "b5981d9bd712f25eeda6cbcda49d6423a2b369fb23cae3edd8e4fd78a92731e5") {
71
65
  for (let $i = 0; $i < 17; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
72
- $[0] = "4aa858f2d01b8522f136fc586f47d0bfc585b3ef0680197aead771149ae36446";
66
+ $[0] = "b5981d9bd712f25eeda6cbcda49d6423a2b369fb23cae3edd8e4fd78a92731e5";
73
67
  }
74
68
  const { children } = t0;
75
69
  const signInRedirect = useSignInRedirect();
@@ -1,6 +1,6 @@
1
1
  import { seedBlockCaches } from "../../lib/normalized-data.js";
2
2
  import { CamoxPreview, PageContent } from "../preview/CamoxPreview.js";
3
- import { trackEvent } from "../../lib/analytics.js";
3
+ import { trackEvent } from "../../lib/telemetry.js";
4
4
  import { c } from "react/compiler-runtime";
5
5
  import { notFound } from "@tanstack/react-router";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -143,9 +143,9 @@ function createPageHead(camoxApp) {
143
143
  }
144
144
  const PageRouteComponent = () => {
145
145
  const $ = c(2);
146
- if ($[0] !== "868ae726f7b5958b542919849be1144cc4a493498385015b5825d8132609202a") {
146
+ if ($[0] !== "af05e19496b4a2096f4315eaed68c6a75307af2bf2159c4789e0b818ba1bd1c7") {
147
147
  for (let $i = 0; $i < 2; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
148
- $[0] = "868ae726f7b5958b542919849be1144cc4a493498385015b5825d8132609202a";
148
+ $[0] = "af05e19496b4a2096f4315eaed68c6a75307af2bf2159c4789e0b818ba1bd1c7";
149
149
  }
150
150
  let t0;
151
151
  if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
@@ -1,3 +1,4 @@
1
+ import { trackClientEvent } from "../../lib/telemetry-client.js";
1
2
  import { useAuthState, useSignInRedirect } from "../../lib/auth.js";
2
3
  import { Navbar } from "./components/Navbar.js";
3
4
  import { c } from "react/compiler-runtime";
@@ -7,10 +8,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
7
8
 
8
9
  //#region src/features/studio/CamoxStudio.tsx
9
10
  const CamoxStudio = (t0) => {
10
- const $ = c(10);
11
- if ($[0] !== "974cf0d1f779b675cbbe8c8d600e9d789e2718cb2b7aaea29f2828cbe4b25895") {
12
- for (let $i = 0; $i < 10; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
13
- $[0] = "974cf0d1f779b675cbbe8c8d600e9d789e2718cb2b7aaea29f2828cbe4b25895";
11
+ const $ = c(14);
12
+ if ($[0] !== "a3859231f360f8aeee5cc1cb82b7375ae6b37024c558809efb60b3f2fac33069") {
13
+ for (let $i = 0; $i < 14; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
14
+ $[0] = "a3859231f360f8aeee5cc1cb82b7375ae6b37024c558809efb60b3f2fac33069";
14
15
  }
15
16
  const { children } = t0;
16
17
  const { isAuthenticated, isLoading: isLoadingAuth } = useAuthState();
@@ -37,30 +38,49 @@ const CamoxStudio = (t0) => {
37
38
  t2 = $[5];
38
39
  }
39
40
  React.useEffect(t1, t2);
41
+ const hasTrackedOpenRef = React.useRef(false);
42
+ let t3;
43
+ let t4;
44
+ if ($[6] !== isAuthenticated || $[7] !== pathname) {
45
+ t3 = () => {
46
+ if (!isAuthenticated || hasTrackedOpenRef.current) return;
47
+ hasTrackedOpenRef.current = true;
48
+ trackClientEvent("studio_opened", { route: pathname });
49
+ };
50
+ t4 = [isAuthenticated, pathname];
51
+ $[6] = isAuthenticated;
52
+ $[7] = pathname;
53
+ $[8] = t3;
54
+ $[9] = t4;
55
+ } else {
56
+ t3 = $[8];
57
+ t4 = $[9];
58
+ }
59
+ React.useEffect(t3, t4);
40
60
  if (pathname === "cmx-studio") {
41
- let t3;
42
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
43
- t3 = /* @__PURE__ */ jsx(Navigate, { to: "/" });
44
- $[6] = t3;
45
- } else t3 = $[6];
46
- return t3;
61
+ let t5;
62
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
63
+ t5 = /* @__PURE__ */ jsx(Navigate, { to: "/" });
64
+ $[10] = t5;
65
+ } else t5 = $[10];
66
+ return t5;
47
67
  }
48
68
  if (!isAuthenticated) return null;
49
- let t3;
50
- if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
51
- t3 = /* @__PURE__ */ jsx(Navbar, {});
52
- $[7] = t3;
53
- } else t3 = $[7];
54
- let t4;
55
- if ($[8] !== children) {
56
- t4 = /* @__PURE__ */ jsxs("div", {
69
+ let t5;
70
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
71
+ t5 = /* @__PURE__ */ jsx(Navbar, {});
72
+ $[11] = t5;
73
+ } else t5 = $[11];
74
+ let t6;
75
+ if ($[12] !== children) {
76
+ t6 = /* @__PURE__ */ jsxs("div", {
57
77
  className: "bg-background flex h-screen flex-col overflow-hidden",
58
- children: [t3, children]
78
+ children: [t5, children]
59
79
  });
60
- $[8] = children;
61
- $[9] = t4;
62
- } else t4 = $[9];
63
- return t4;
80
+ $[12] = children;
81
+ $[13] = t6;
82
+ } else t6 = $[13];
83
+ return t6;
64
84
  };
65
85
 
66
86
  //#endregion
@@ -6,8 +6,8 @@ interface CamoxPluginOptions {
6
6
  projectSlug: string;
7
7
  /** Secret used to authenticate definition sync requests with the API */
8
8
  syncSecret: string;
9
- /** Disable PostHog analytics collection (default: false) */
10
- disableAnalytics?: boolean;
9
+ /** Disable PostHog telemetry collection (default: false) */
10
+ disableTelemetry?: boolean;
11
11
  /** Internal options (intended for Camox contributors in development, not for public use) */
12
12
  _internal?: {
13
13
  /** URL of the Camox API backend, used for data fetching */apiUrl?: string; /** URL of the Camox authentication backend (default: https://camox.ai) */