camox 0.47.0 → 0.51.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 (117) hide show
  1. package/dist/core/createApp.d.ts +19 -6
  2. package/dist/core/createApp.js +7 -2
  3. package/dist/core/createBlock.js +54 -43
  4. package/dist/core/createCollection.d.ts +25 -7
  5. package/dist/core/createCollection.js +28 -9
  6. package/dist/core/createLayout.d.ts +98 -71
  7. package/dist/core/createLayout.js +10 -16
  8. package/dist/core/derivedRoutes.js +1 -1
  9. package/dist/core/editing/BlockEditingRuntime.d.ts +3 -2
  10. package/dist/core/editing/CompleteBlockEditingRuntime.js +2 -1
  11. package/dist/core/editing/createEditableBlock.d.ts +59 -19
  12. package/dist/core/editing/createEditableBlock.js +162 -151
  13. package/dist/core/editing/useLatestRecord.js +7 -7
  14. package/dist/core/layoutContext.d.ts +55 -0
  15. package/dist/core/layoutContext.js +66 -0
  16. package/dist/core/lib/contentType.d.ts +91 -4
  17. package/dist/core/lib/contentType.js +84 -7
  18. package/dist/core/lib/recordScope.js +19 -17
  19. package/dist/core/lib/reference.d.ts +6 -2
  20. package/dist/core/recordItem.js +55 -2
  21. package/dist/core/requestContext.d.ts +18 -0
  22. package/dist/core/structuredData.d.ts +126 -0
  23. package/dist/core/structuredData.js +40 -0
  24. package/dist/features/canvas/canvasCamera.js +1 -1
  25. package/dist/features/canvas/sidebar/CanvasInspector.js +1 -1
  26. package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +1 -1
  27. package/dist/features/content/ContentAssets.js +84 -88
  28. package/dist/features/content/ContentCollection.js +13 -7
  29. package/dist/features/content/collection-form.js +6 -2
  30. package/dist/features/content/components/MissingFromLocale.js +1 -1
  31. package/dist/features/og/pageImage.js +89 -0
  32. package/dist/features/page/CuratedPageContent.js +45 -32
  33. package/dist/features/page/DerivedPageContent.js +49 -22
  34. package/dist/features/page/SharedLayoutContent.js +26 -22
  35. package/dist/features/preview/CamoxPreview.js +41 -27
  36. package/dist/features/preview/EditablePageExperience.js +17 -9
  37. package/dist/features/preview/components/AddBlockSheet.js +1 -0
  38. package/dist/features/preview/components/BlockActionsPopover.js +19 -41
  39. package/dist/features/preview/components/FieldToolbar.js +1 -1
  40. package/dist/features/preview/components/MobilePreviewDrawer.js +6 -9
  41. package/dist/features/preview/components/PageInfo.js +244 -264
  42. package/dist/features/preview/components/PageTree.js +63 -53
  43. package/dist/features/preview/components/PreviewPanel.js +10 -64
  44. package/dist/features/preview/components/PreviewToolbar.js +1 -1
  45. package/dist/features/preview/components/RecordCard.js +50 -34
  46. package/dist/features/preview/components/RecordCombobox.js +12 -5
  47. package/dist/features/preview/components/ReferenceFieldEditor.js +4 -2
  48. package/dist/features/preview/components/ReferenceListFieldEditor.js +24 -19
  49. package/dist/features/preview/components/RepeatableItemsList.js +62 -46
  50. package/dist/features/preview/components/SelectionEditor.js +3 -2
  51. package/dist/features/preview/components/useFieldWriter.js +2 -4
  52. package/dist/features/preview/components/useRecordView.js +2 -2
  53. package/dist/features/preview/entityName.js +11 -0
  54. package/dist/features/preview/pageRecord.js +17 -18
  55. package/dist/features/preview/previewConstants.js +2 -8
  56. package/dist/features/preview/usePreviewViewportActions.js +1 -1
  57. package/dist/features/provider/AuthenticatedCamoxProvider.js +1 -1
  58. package/dist/features/provider/components/CommandPalette.js +2 -5
  59. package/dist/features/provider/signInShortcut.js +1 -2
  60. package/dist/features/provider/useAdminShortcuts.js +47 -53
  61. package/dist/features/routes/pageRuntime.d.ts +17 -2
  62. package/dist/features/routes/pageRuntime.js +61 -57
  63. package/dist/features/runtime/RuntimeChrome.js +1 -1
  64. package/dist/features/runtime/breadcrumbs.js +68 -0
  65. package/dist/features/runtime/livePages.js +3 -2
  66. package/dist/features/runtime/pageGraph.js +92 -0
  67. package/dist/features/runtime/projectLogo.js +110 -0
  68. package/dist/features/runtime/publicCache.js +83 -0
  69. package/dist/features/runtime/runtime.d.ts +24 -9
  70. package/dist/features/runtime/runtime.js +447 -130
  71. package/dist/features/runtime/runtimeRoutes.d.ts +1 -0
  72. package/dist/features/runtime/runtimeRoutes.js +1 -0
  73. package/dist/features/runtime/structuredData.js +213 -0
  74. package/dist/features/runtime/worker.d.ts +5 -1
  75. package/dist/features/runtime/worker.js +20 -3
  76. package/dist/features/settings/AnalyticsSettings.js +622 -0
  77. package/dist/features/settings/CamoxSettings.js +95 -0
  78. package/dist/features/settings/FaviconSettings.js +254 -0
  79. package/dist/features/settings/ProjectNameSettings.js +145 -0
  80. package/dist/features/settings/SettingsPart.js +73 -0
  81. package/dist/features/settings/SocialProfilesSettings.js +245 -0
  82. package/dist/features/settings/useProjectMutation.js +61 -0
  83. package/dist/features/studio/components/ChatSidebar.js +5 -5
  84. package/dist/features/studio/components/DraftsControl.js +136 -131
  85. package/dist/features/studio/components/LocalePicker.js +178 -174
  86. package/dist/features/studio/components/Navbar.js +107 -66
  87. package/dist/features/studio/components/ProjectMenu.js +85 -110
  88. package/dist/features/studio/components/ReviewDraftSheet.js +1046 -990
  89. package/dist/features/studio/components/ThreadMessages.js +2 -2
  90. package/dist/features/studio/components/UserButton.js +1 -1
  91. package/dist/features/studio/routes.js +3 -1
  92. package/dist/features/studio/showInCanvas.js +129 -0
  93. package/dist/features/vite/blockBoilerplate.js +3 -2
  94. package/dist/features/vite/definitionsSync.js +4 -5
  95. package/dist/features/vite/layoutGeneration.js +3 -2
  96. package/dist/features/vite/runtimeDev.js +32 -17
  97. package/dist/features/vite/staticAssetHeaders.js +52 -0
  98. package/dist/features/vite/vite.d.ts +1 -1
  99. package/dist/features/vite/vite.js +17 -4
  100. package/dist/lib/api-client-server.d.ts +1 -1
  101. package/dist/lib/api-client.d.ts +2 -1
  102. package/dist/lib/draft-scope.d.ts +1 -0
  103. package/dist/lib/locale-path.d.ts +3 -11
  104. package/dist/lib/locale-path.js +3 -27
  105. package/dist/lib/queries.d.ts +4 -0
  106. package/dist/lib/queries.js +8 -1
  107. package/dist/lib/shortcuts.js +29 -0
  108. package/dist/lib/studio-reads.d.ts +1 -0
  109. package/dist/lib/studio-reads.js +3 -1
  110. package/dist/lib/utils.js +1 -104
  111. package/dist/package.js +1 -1
  112. package/dist/studio.css +1 -1
  113. package/package.json +6 -4
  114. package/skills/camox/references/block-definitions.md +105 -25
  115. package/skills/camox/references/layout-definitions.md +53 -17
  116. package/skills/camox/references/routed-layouts.md +17 -14
  117. package/dist/features/studio/components/FaviconDialog.js +0 -318
@@ -6,8 +6,8 @@ import { jsx } from "react/jsx-runtime";
6
6
  //#region src/features/page/SharedLayoutContent.tsx
7
7
  /** Shared before/after rendering for both curated and data-derived pages. */
8
8
  function SharedLayoutContent(t0) {
9
- const $ = c(15);
10
- const { layout, blocks, files, repeatableItems, result, children } = t0;
9
+ const $ = c(16);
10
+ const { layout, context, blocks, files, repeatableItems, result, children } = t0;
11
11
  let result_0;
12
12
  if ($[0] !== blocks) {
13
13
  result_0 = {};
@@ -22,41 +22,45 @@ function SharedLayoutContent(t0) {
22
22
  $[1] = result_0;
23
23
  } else result_0 = $[1];
24
24
  const layoutBlocks = result_0;
25
- const Component = layout._internal.component;
25
+ const ToReact = layout._internal.toReact;
26
26
  let t1;
27
- if ($[2] !== Component || $[3] !== children) {
28
- t1 = /* @__PURE__ */ jsx(Component, { children });
29
- $[2] = Component;
27
+ if ($[2] !== ToReact || $[3] !== children || $[4] !== context) {
28
+ t1 = /* @__PURE__ */ jsx(ToReact, {
29
+ ...context,
30
+ children
31
+ });
32
+ $[2] = ToReact;
30
33
  $[3] = children;
31
- $[4] = t1;
32
- } else t1 = $[4];
34
+ $[4] = context;
35
+ $[5] = t1;
36
+ } else t1 = $[5];
33
37
  let t2;
34
- if ($[5] !== layout._internal.Provider || $[6] !== layoutBlocks || $[7] !== result || $[8] !== t1) {
38
+ if ($[6] !== layout._internal.Provider || $[7] !== layoutBlocks || $[8] !== result || $[9] !== t1) {
35
39
  t2 = /* @__PURE__ */ jsx(layout._internal.Provider, {
36
40
  layoutBlocks,
37
41
  result,
38
42
  children: t1
39
43
  });
40
- $[5] = layout._internal.Provider;
41
- $[6] = layoutBlocks;
42
- $[7] = result;
43
- $[8] = t1;
44
- $[9] = t2;
45
- } else t2 = $[9];
44
+ $[6] = layout._internal.Provider;
45
+ $[7] = layoutBlocks;
46
+ $[8] = result;
47
+ $[9] = t1;
48
+ $[10] = t2;
49
+ } else t2 = $[10];
46
50
  let t3;
47
- if ($[10] !== blocks || $[11] !== files || $[12] !== repeatableItems || $[13] !== t2) {
51
+ if ($[11] !== blocks || $[12] !== files || $[13] !== repeatableItems || $[14] !== t2) {
48
52
  t3 = /* @__PURE__ */ jsx(NormalizedDataProvider, {
49
53
  files,
50
54
  repeatableItems,
51
55
  blocks,
52
56
  children: t2
53
57
  });
54
- $[10] = blocks;
55
- $[11] = files;
56
- $[12] = repeatableItems;
57
- $[13] = t2;
58
- $[14] = t3;
59
- } else t3 = $[14];
58
+ $[11] = blocks;
59
+ $[12] = files;
60
+ $[13] = repeatableItems;
61
+ $[14] = t2;
62
+ $[15] = t3;
63
+ } else t3 = $[15];
60
64
  return t3;
61
65
  }
62
66
 
@@ -8,6 +8,7 @@ import { useCamoxApp } from "../provider/components/CamoxAppContext.js";
8
8
  import { NormalizedDataProvider, usePageBlocks } from "../../lib/normalized-data.js";
9
9
  import { reads, useRead, useStudioCache } from "../../lib/studio-reads.js";
10
10
  import { BlockErrorBoundary } from "./components/BlockErrorBoundary.js";
11
+ import { curatedLayoutContext } from "../../core/layoutContext.js";
11
12
  import { CollectionItemSheetProvider } from "../content/CollectionItemSheetContext.js";
12
13
  import { cn } from "../../lib/utils.js";
13
14
  import { ContentCollectionItemSheet } from "../content/ContentCollection.js";
@@ -164,10 +165,11 @@ const BlockRenderer = (t0) => {
164
165
  return t13;
165
166
  };
166
167
  const PageContent = () => {
167
- const $ = c(30);
168
+ const $ = c(34);
168
169
  const pageData = usePreviewedPage();
169
170
  const { pageBlocks, beforeBlocks, afterBlocks, layoutFiles, layoutItems } = usePageBlocks(pageData);
170
171
  const camoxApp = useCamoxApp();
172
+ const { locale } = useViewLocale();
171
173
  let layout;
172
174
  let layoutBlocksMap;
173
175
  let t0;
@@ -228,7 +230,7 @@ const PageContent = () => {
228
230
  } else t1 = $[12];
229
231
  const pageBlocksContent = t1;
230
232
  if (layout && layoutBlocksMap) {
231
- const LayoutComponent = layout._internal.component;
233
+ const ToReact = layout._internal.toReact;
232
234
  let t2;
233
235
  if ($[13] !== afterBlocks || $[14] !== beforeBlocks) {
234
236
  t2 = [...beforeBlocks, ...afterBlocks];
@@ -236,49 +238,61 @@ const PageContent = () => {
236
238
  $[14] = beforeBlocks;
237
239
  $[15] = t2;
238
240
  } else t2 = $[15];
241
+ const T0 = layout._internal.Provider;
239
242
  let t3;
240
- if ($[16] !== LayoutComponent || $[17] !== pageBlocksContent) {
241
- t3 = /* @__PURE__ */ jsx(LayoutComponent, { children: pageBlocksContent });
242
- $[16] = LayoutComponent;
243
- $[17] = pageBlocksContent;
243
+ if ($[16] !== locale || $[17] !== pageData) {
244
+ t3 = curatedLayoutContext(pageData, locale);
245
+ $[16] = locale;
246
+ $[17] = pageData;
244
247
  $[18] = t3;
245
248
  } else t3 = $[18];
246
249
  let t4;
247
- if ($[19] !== layout._internal.Provider || $[20] !== layoutBlocksMap || $[21] !== t3) {
248
- t4 = /* @__PURE__ */ jsx(layout._internal.Provider, {
249
- layoutBlocks: layoutBlocksMap,
250
- children: t3
250
+ if ($[19] !== ToReact || $[20] !== pageBlocksContent || $[21] !== t3) {
251
+ t4 = /* @__PURE__ */ jsx(ToReact, {
252
+ ...t3,
253
+ children: pageBlocksContent
251
254
  });
252
- $[19] = layout._internal.Provider;
253
- $[20] = layoutBlocksMap;
255
+ $[19] = ToReact;
256
+ $[20] = pageBlocksContent;
254
257
  $[21] = t3;
255
258
  $[22] = t4;
256
259
  } else t4 = $[22];
257
260
  let t5;
258
- if ($[23] !== layoutFiles || $[24] !== layoutItems || $[25] !== t2 || $[26] !== t4) {
259
- t5 = /* @__PURE__ */ jsx(NormalizedDataProvider, {
261
+ if ($[23] !== layout._internal.Provider || $[24] !== layoutBlocksMap || $[25] !== t4) {
262
+ t5 = /* @__PURE__ */ jsx(T0, {
263
+ layoutBlocks: layoutBlocksMap,
264
+ children: t4
265
+ });
266
+ $[23] = layout._internal.Provider;
267
+ $[24] = layoutBlocksMap;
268
+ $[25] = t4;
269
+ $[26] = t5;
270
+ } else t5 = $[26];
271
+ let t6;
272
+ if ($[27] !== layoutFiles || $[28] !== layoutItems || $[29] !== t2 || $[30] !== t5) {
273
+ t6 = /* @__PURE__ */ jsx(NormalizedDataProvider, {
260
274
  files: layoutFiles,
261
275
  repeatableItems: layoutItems,
262
276
  blocks: t2,
263
- children: t4
277
+ children: t5
264
278
  });
265
- $[23] = layoutFiles;
266
- $[24] = layoutItems;
267
- $[25] = t2;
268
- $[26] = t4;
269
- $[27] = t5;
270
- } else t5 = $[27];
271
- return t5;
279
+ $[27] = layoutFiles;
280
+ $[28] = layoutItems;
281
+ $[29] = t2;
282
+ $[30] = t5;
283
+ $[31] = t6;
284
+ } else t6 = $[31];
285
+ return t6;
272
286
  }
273
287
  let t2;
274
- if ($[28] !== pageBlocksContent) {
288
+ if ($[32] !== pageBlocksContent) {
275
289
  t2 = /* @__PURE__ */ jsx("main", {
276
290
  className: "flex min-h-screen flex-col",
277
291
  children: pageBlocksContent
278
292
  });
279
- $[28] = pageBlocksContent;
280
- $[29] = t2;
281
- } else t2 = $[29];
293
+ $[32] = pageBlocksContent;
294
+ $[33] = t2;
295
+ } else t2 = $[33];
282
296
  return t2;
283
297
  };
284
298
  /**
@@ -735,7 +749,7 @@ const PreviewShell = (t0) => {
735
749
  groupLabel: "Website",
736
750
  checkIfAvailable: _temp6,
737
751
  execute: _temp7,
738
- shortcut: { key: "Escape" }
752
+ shortcut: "Escape"
739
753
  }
740
754
  ];
741
755
  actionsStore.send({
@@ -4,16 +4,23 @@ import { AuthenticatedCamoxProvider } from "../provider/AuthenticatedCamoxProvid
4
4
  import { CamoxStudio } from "../studio/CamoxStudio.js";
5
5
  import "./EditablePageContent.js";
6
6
  import { CompleteBlockEditingRuntimeProvider } from "../../core/editing/CompleteBlockEditingRuntime.js";
7
+ import { CamoxSettings } from "../settings/CamoxSettings.js";
7
8
  import { c } from "react/compiler-runtime";
8
9
  import { jsx } from "react/jsx-runtime";
9
10
 
10
11
  //#region src/features/preview/EditablePageExperience.tsx
12
+ /** The studio section each studio route shows. */
13
+ const STUDIO_SECTIONS = {
14
+ "studio-content": CamoxContent,
15
+ "studio-settings": CamoxSettings
16
+ };
11
17
  function EditablePageExperience(t0) {
12
- const $ = c(5);
18
+ const $ = c(6);
13
19
  const { input } = t0;
20
+ const StudioSection = input.routeKind && STUDIO_SECTIONS[input.routeKind];
14
21
  let t1;
15
- if ($[0] !== input.canvasOnly || $[1] !== input.derived || $[2] !== input.routeKind || $[3] !== input.runtimeBasePath) {
16
- t1 = /* @__PURE__ */ jsx(AuthenticatedCamoxProvider, { children: /* @__PURE__ */ jsx(CompleteBlockEditingRuntimeProvider, { children: input.routeKind ? /* @__PURE__ */ jsx(CamoxStudio, { children: input.routeKind === "studio-content" ? /* @__PURE__ */ jsx(CamoxContent, {}) : /* @__PURE__ */ jsx("div", {
22
+ if ($[0] !== StudioSection || $[1] !== input.canvasOnly || $[2] !== input.derived || $[3] !== input.routeKind || $[4] !== input.runtimeBasePath) {
23
+ t1 = /* @__PURE__ */ jsx(AuthenticatedCamoxProvider, { children: /* @__PURE__ */ jsx(CompleteBlockEditingRuntimeProvider, { children: input.routeKind ? /* @__PURE__ */ jsx(CamoxStudio, { children: StudioSection ? /* @__PURE__ */ jsx(StudioSection, {}) : /* @__PURE__ */ jsx("div", {
17
24
  className: "text-muted-foreground p-6 text-sm",
18
25
  children: "Studio page not found"
19
26
  }) }) : /* @__PURE__ */ jsx(CamoxPreview, {
@@ -22,12 +29,13 @@ function EditablePageExperience(t0) {
22
29
  runtimeBasePath: input.runtimeBasePath,
23
30
  children: /* @__PURE__ */ jsx(PageContent, {})
24
31
  }) }) });
25
- $[0] = input.canvasOnly;
26
- $[1] = input.derived;
27
- $[2] = input.routeKind;
28
- $[3] = input.runtimeBasePath;
29
- $[4] = t1;
30
- } else t1 = $[4];
32
+ $[0] = StudioSection;
33
+ $[1] = input.canvasOnly;
34
+ $[2] = input.derived;
35
+ $[3] = input.routeKind;
36
+ $[4] = input.runtimeBasePath;
37
+ $[5] = t1;
38
+ } else t1 = $[5];
31
39
  return t1;
32
40
  }
33
41
 
@@ -76,6 +76,7 @@ const AddBlockSheet = ({ focusCreatedBlock = true }) => {
76
76
  settings: variables.settings ?? null,
77
77
  slot: null,
78
78
  summary: "",
79
+ title: "",
79
80
  position,
80
81
  createdAt: now,
81
82
  updatedAt: now
@@ -1,9 +1,10 @@
1
1
  import { actionsStore } from "../../provider/actionsStore.js";
2
2
  import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
3
3
  import { usePageBlocks } from "../../../lib/normalized-data.js";
4
- import { formatShortcut } from "../../../lib/utils.js";
5
4
  import { blockMutations, repeatableItemMutations } from "../../../lib/queries.js";
5
+ import { formatShortcut } from "../../../lib/shortcuts.js";
6
6
  import { isBlockSelection, previewStore, selectionForPage, selectionItemId } from "../previewStore.js";
7
+ import { entityName } from "../entityName.js";
7
8
  import { useUpdateBlockPosition } from "./useUpdateBlockPosition.js";
8
9
  import { usePreviewedPage } from "../CamoxPreview.js";
9
10
  import { c } from "react/compiler-runtime";
@@ -28,7 +29,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
28
29
  const handleDeleteBlock = async (block) => {
29
30
  try {
30
31
  await deleteBlock.mutateAsync({ id: block.id });
31
- toast.success(`Deleted "${block.summary || block.type}" block`);
32
+ toast.success(`Deleted "${entityName(block, block.type)}" block`);
32
33
  } catch (error) {
33
34
  console.error("Failed to delete block:", error);
34
35
  toast.error("Could not delete block");
@@ -39,7 +40,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
39
40
  const handleDuplicateBlock = async (block) => {
40
41
  try {
41
42
  await duplicateBlock.mutateAsync({ id: block.id });
42
- toast.success(`Duplicated "${block.summary}" block`);
43
+ toast.success(`Duplicated "${entityName(block, block.type)}" block`);
43
44
  } catch (error) {
44
45
  console.error("Failed to duplicate block:", error);
45
46
  toast.error("Could not duplicate block");
@@ -138,7 +139,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
138
139
  children: [/* @__PURE__ */ jsxs("div", {
139
140
  className: "flex items-center gap-2",
140
141
  children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block below"]
141
- }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut({ key: "o" }) })]
142
+ }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut("O") })]
142
143
  }), /* @__PURE__ */ jsxs(CommandItem, {
143
144
  className: "justify-between",
144
145
  onSelect: () => {
@@ -148,10 +149,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
148
149
  children: [/* @__PURE__ */ jsxs("div", {
149
150
  className: "flex items-center gap-2",
150
151
  children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block above"]
151
- }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut({
152
- key: "o",
153
- withShift: true
154
- }) })]
152
+ }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut("Shift+O") })]
155
153
  })] }),
156
154
  /* @__PURE__ */ jsx(CommandSeparator, {}),
157
155
  /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsxs(CommandItem, {
@@ -163,10 +161,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
163
161
  children: [/* @__PURE__ */ jsxs("div", {
164
162
  className: "flex items-center gap-2",
165
163
  children: [/* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }), "Duplicate block"]
166
- }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut({
167
- key: "d",
168
- withMeta: true
169
- }) })]
164
+ }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut("Mod+D") })]
170
165
  }) }),
171
166
  /* @__PURE__ */ jsx(CommandSeparator, {}),
172
167
  /* @__PURE__ */ jsxs(CommandGroup, { children: [
@@ -195,10 +190,7 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
195
190
  children: [/* @__PURE__ */ jsxs("div", {
196
191
  className: "flex items-center gap-2",
197
192
  children: [/* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }), "Delete block"]
198
- }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut({
199
- key: "Backspace",
200
- withMeta: true
201
- }) })]
193
+ }), /* @__PURE__ */ jsx(CommandShortcut, { children: formatShortcut("Mod+Backspace") })]
202
194
  })
203
195
  ] })
204
196
  ] })
@@ -209,8 +201,9 @@ const BlockActionsPopover = ({ block, children, open, onOpenChange, align = "sta
209
201
  open: !!blockToDelete,
210
202
  onOpenChange: (open) => !open && setBlockToDelete(null),
211
203
  children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: "Delete block" }), /* @__PURE__ */ jsxs(AlertDialogDescription, { children: [
212
- "Are you sure you want to delete ",
213
- /* @__PURE__ */ jsx("strong", { children: blockToDelete?.summary }),
204
+ "Are you sure you want to delete",
205
+ " ",
206
+ /* @__PURE__ */ jsx("strong", { children: blockToDelete && entityName(blockToDelete, blockToDelete.type) }),
214
207
  "? This action cannot be undone."
215
208
  ] })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, {
216
209
  variant: "outline",
@@ -277,10 +270,7 @@ function useBlockActionsShortcuts() {
277
270
  id: "delete-selected",
278
271
  label: "Delete selected",
279
272
  groupLabel: "Website",
280
- shortcut: {
281
- key: "Backspace",
282
- withMeta: true
283
- },
273
+ shortcut: "Mod+Backspace",
284
274
  checkIfAvailable: () => {
285
275
  const ctx = previewStore.getSnapshot().context;
286
276
  if (ctx.view !== "canvas") return false;
@@ -310,7 +300,7 @@ function useBlockActionsShortcuts() {
310
300
  return;
311
301
  }
312
302
  const block_0 = pageBlocks.find((b_0) => b_0.id === sel_0.blockId);
313
- deleteBlock({ id: sel_0.blockId }).then(() => toast.success(`Deleted "${block_0?.summary || block_0?.type}" block`), _temp6);
303
+ deleteBlock({ id: sel_0.blockId }).then(() => toast.success(`Deleted "${block_0 ? entityName(block_0, block_0.type) : ""}" block`), _temp6);
314
304
  previewStore.send({ type: "clearSelection" });
315
305
  }
316
306
  },
@@ -318,10 +308,7 @@ function useBlockActionsShortcuts() {
318
308
  id: "duplicate-selected",
319
309
  label: "Duplicate selected",
320
310
  groupLabel: "Website",
321
- shortcut: {
322
- key: "d",
323
- withMeta: true
324
- },
311
+ shortcut: "Mod+D",
325
312
  checkIfAvailable: () => {
326
313
  const ctx_0 = previewStore.getSnapshot().context;
327
314
  if (ctx_0.view !== "canvas") return false;
@@ -339,17 +326,14 @@ function useBlockActionsShortcuts() {
339
326
  return;
340
327
  }
341
328
  const block_1 = pageBlocks.find((b_1) => b_1.id === sel_2.blockId);
342
- duplicateBlock({ id: sel_2.blockId }).then(() => toast.success(`Duplicated "${block_1?.summary}" block`), _temp9);
329
+ duplicateBlock({ id: sel_2.blockId }).then(() => toast.success(`Duplicated "${block_1 ? entityName(block_1, block_1.type) : ""}" block`), _temp9);
343
330
  }
344
331
  },
345
332
  {
346
333
  id: "move-block-up",
347
334
  label: "Move block up",
348
335
  groupLabel: "Website",
349
- shortcut: {
350
- key: "ArrowUp",
351
- withAlt: true
352
- },
336
+ shortcut: "Alt+ArrowUp",
353
337
  checkIfAvailable: () => {
354
338
  const ctx_1 = previewStore.getSnapshot().context;
355
339
  if (ctx_1.view !== "canvas") return false;
@@ -376,10 +360,7 @@ function useBlockActionsShortcuts() {
376
360
  id: "move-block-down",
377
361
  label: "Move block down",
378
362
  groupLabel: "Website",
379
- shortcut: {
380
- key: "ArrowDown",
381
- withAlt: true
382
- },
363
+ shortcut: "Alt+ArrowDown",
383
364
  checkIfAvailable: () => {
384
365
  const ctx_2 = previewStore.getSnapshot().context;
385
366
  if (ctx_2.view !== "canvas") return false;
@@ -407,7 +388,7 @@ function useBlockActionsShortcuts() {
407
388
  id: "add-block-below",
408
389
  label: "Add block below",
409
390
  groupLabel: "Website",
410
- shortcut: { key: "o" },
391
+ shortcut: "O",
411
392
  checkIfAvailable: () => {
412
393
  const ctx_3 = previewStore.getSnapshot().context;
413
394
  if (ctx_3.view !== "canvas") return false;
@@ -428,10 +409,7 @@ function useBlockActionsShortcuts() {
428
409
  id: "add-block-above",
429
410
  label: "Add block above",
430
411
  groupLabel: "Website",
431
- shortcut: {
432
- key: "o",
433
- withShift: true
434
- },
412
+ shortcut: "Shift+O",
435
413
  checkIfAvailable: () => {
436
414
  const ctx_4 = previewStore.getSnapshot().context;
437
415
  if (ctx_4.view !== "canvas") return false;
@@ -7,9 +7,9 @@ import * as React from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { Button } from "@camox/ui/button";
9
9
  import { Bold, Highlighter, Italic, Strikethrough } from "lucide-react";
10
- import { Kbd } from "@camox/ui/kbd";
11
10
  import { ButtonGroup } from "@camox/ui/button-group";
12
11
  import * as Tooltip$1 from "@camox/ui/tooltip";
12
+ import { Kbd } from "@camox/ui/kbd";
13
13
  import { FloatingToolbar } from "@camox/ui/floating-toolbar";
14
14
  import { Toggle } from "@camox/ui/toggle";
15
15
 
@@ -1,6 +1,7 @@
1
- import { useAuthContext } from "../../../lib/auth.js";
2
- import { reads, useReadQuery } from "../../../lib/studio-reads.js";
1
+ import { useNavigate } from "../../navigation/navigation.js";
3
2
  import { cn } from "../../../lib/utils.js";
3
+ import { useLocalizedPath } from "../../../lib/view-locale.js";
4
+ import { STUDIO_SETTINGS_PATH } from "../../studio/routes.js";
4
5
  import { previewStore, selectionBlockId, selectionForPage } from "../previewStore.js";
5
6
  import { UserButton } from "../../studio/components/UserButton.js";
6
7
  import { PageInfo, PageMarkdownContent, PageSeoContent } from "./PageInfo.js";
@@ -28,8 +29,8 @@ function MobilePreviewDrawer({ page, projectName }) {
28
29
  const [isExpanded, setIsExpanded] = React.useState(false);
29
30
  const [isDragging, setIsDragging] = React.useState(false);
30
31
  const [screen, setScreen] = React.useState("root");
31
- const authCtx = useAuthContext();
32
- const { data: project } = useReadQuery(reads.project({ projectUuid: authCtx.projectUuid }));
32
+ const navigate = useNavigate();
33
+ const localized = useLocalizedPath();
33
34
  const dragStartRef = React.useRef({
34
35
  y: 0,
35
36
  height: COLLAPSED_HEIGHT
@@ -200,11 +201,7 @@ function MobilePreviewDrawer({ page, projectName }) {
200
201
  /* @__PURE__ */ jsx(DrawerTile, {
201
202
  title: "Project settings",
202
203
  icon: Settings,
203
- onClick: () => {
204
- if (!project) return;
205
- window.open(`${authCtx.authenticationUrl}/${project.organizationSlug}/${project.slug}/overview`, "_blank", "noopener,noreferrer");
206
- },
207
- disabled: !project
204
+ onClick: () => void navigate({ to: localized("/camox/settings") })
208
205
  })
209
206
  ]
210
207
  })]