camox 0.0.0 → 0.1.2-alpha.2

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 (255) hide show
  1. package/LICENSE.md +110 -0
  2. package/dist/components/AuthGate.d.ts +7 -0
  3. package/dist/components/AuthGate.d.ts.map +1 -0
  4. package/dist/core/components/AddBlockControlBar.d.ts +9 -0
  5. package/dist/core/components/AddBlockControlBar.d.ts.map +1 -0
  6. package/dist/core/components/AddBlockControlBar.js +65 -0
  7. package/dist/core/components/lexical/InlineContentEditable.d.ts +7 -0
  8. package/dist/core/components/lexical/InlineContentEditable.d.ts.map +1 -0
  9. package/dist/core/components/lexical/InlineContentEditable.js +40 -0
  10. package/dist/core/components/lexical/InlineLexicalEditor.d.ts +12 -0
  11. package/dist/core/components/lexical/InlineLexicalEditor.d.ts.map +1 -0
  12. package/dist/core/components/lexical/InlineLexicalEditor.js +133 -0
  13. package/dist/core/components/lexical/InlineParagraphNode.d.ts +10 -0
  14. package/dist/core/components/lexical/InlineParagraphNode.d.ts.map +1 -0
  15. package/dist/core/components/lexical/InlineParagraphNode.js +34 -0
  16. package/dist/core/components/lexical/SelectionBroadcaster.d.ts +6 -0
  17. package/dist/core/components/lexical/SelectionBroadcaster.d.ts.map +1 -0
  18. package/dist/core/components/lexical/SelectionBroadcaster.js +62 -0
  19. package/dist/core/components/lexical/SidebarLexicalEditor.d.ts +9 -0
  20. package/dist/core/components/lexical/SidebarLexicalEditor.d.ts.map +1 -0
  21. package/dist/core/components/lexical/editorConfig.d.ts +4 -0
  22. package/dist/core/components/lexical/editorConfig.d.ts.map +1 -0
  23. package/dist/core/components/lexical/editorConfig.js +24 -0
  24. package/dist/core/createApp.d.ts +373 -0
  25. package/dist/core/createApp.d.ts.map +1 -0
  26. package/dist/core/createApp.js +40 -0
  27. package/dist/core/createBlock.d.ts +947 -0
  28. package/dist/core/createBlock.d.ts.map +1 -0
  29. package/dist/core/createBlock.js +873 -0
  30. package/dist/core/createLayout.d.ts +78 -0
  31. package/dist/core/createLayout.d.ts.map +1 -0
  32. package/dist/core/createLayout.js +73 -0
  33. package/dist/core/hooks/useFieldSelection.d.ts +11 -0
  34. package/dist/core/hooks/useFieldSelection.d.ts.map +1 -0
  35. package/dist/core/hooks/useFieldSelection.js +25 -0
  36. package/dist/core/hooks/useIsEditable.d.ts +2 -0
  37. package/dist/core/hooks/useIsEditable.d.ts.map +1 -0
  38. package/dist/core/hooks/useIsEditable.js +12 -0
  39. package/dist/core/hooks/useOverlayMessage.d.ts +10 -0
  40. package/dist/core/hooks/useOverlayMessage.d.ts.map +1 -0
  41. package/dist/core/hooks/useOverlayMessage.js +37 -0
  42. package/dist/core/lib/contentType.d.ts +165 -0
  43. package/dist/core/lib/contentType.d.ts.map +1 -0
  44. package/dist/core/lib/contentType.js +148 -0
  45. package/dist/core/lib/fieldTypes.d.ts +85 -0
  46. package/dist/core/lib/fieldTypes.d.ts.map +1 -0
  47. package/dist/core/lib/lexicalReact.d.ts +3 -0
  48. package/dist/core/lib/lexicalReact.d.ts.map +1 -0
  49. package/dist/core/lib/lexicalReact.js +24 -0
  50. package/dist/core/lib/lexicalState.d.ts +10 -0
  51. package/dist/core/lib/lexicalState.d.ts.map +1 -0
  52. package/dist/core/lib/lexicalState.js +38 -0
  53. package/dist/core/lib/modifierFormats.d.ts +9 -0
  54. package/dist/core/lib/modifierFormats.d.ts.map +1 -0
  55. package/dist/core/lib/modifierFormats.js +8 -0
  56. package/dist/core/lib/modifiers.d.ts +12 -0
  57. package/dist/core/lib/modifiers.d.ts.map +1 -0
  58. package/dist/core/lib/modifiers.js +27 -0
  59. package/dist/features/content/CamoxContent.d.ts +2 -0
  60. package/dist/features/content/CamoxContent.d.ts.map +1 -0
  61. package/dist/features/content/CamoxContent.js +100 -0
  62. package/dist/features/content/components/AssetCard.d.ts +10 -0
  63. package/dist/features/content/components/AssetCard.d.ts.map +1 -0
  64. package/dist/features/content/components/AssetCard.js +41 -0
  65. package/dist/features/content/components/AssetCardSkeleton.d.ts +2 -0
  66. package/dist/features/content/components/AssetCardSkeleton.d.ts.map +1 -0
  67. package/dist/features/content/components/AssetCardSkeleton.js +11 -0
  68. package/dist/features/content/components/ContentSidebar.d.ts +2 -0
  69. package/dist/features/content/components/ContentSidebar.d.ts.map +1 -0
  70. package/dist/features/content/components/ContentSidebar.js +15 -0
  71. package/dist/features/content/components/UploadDropZone.d.ts +9 -0
  72. package/dist/features/content/components/UploadDropZone.d.ts.map +1 -0
  73. package/dist/features/content/components/UploadDropZone.js +51 -0
  74. package/dist/features/content/components/UploadProgressDrawer.d.ts +11 -0
  75. package/dist/features/content/components/UploadProgressDrawer.d.ts.map +1 -0
  76. package/dist/features/content/components/UploadProgressDrawer.js +72 -0
  77. package/dist/features/preview/CamoxPreview.d.ts +124 -0
  78. package/dist/features/preview/CamoxPreview.d.ts.map +1 -0
  79. package/dist/features/preview/CamoxPreview.js +253 -0
  80. package/dist/features/preview/components/AddBlockSheet.d.ts +3 -0
  81. package/dist/features/preview/components/AddBlockSheet.d.ts.map +1 -0
  82. package/dist/features/preview/components/AddBlockSheet.js +121 -0
  83. package/dist/features/preview/components/AgentChatSheet.d.ts +3 -0
  84. package/dist/features/preview/components/AgentChatSheet.d.ts.map +1 -0
  85. package/dist/features/preview/components/AgentChatSheet.js +24 -0
  86. package/dist/features/preview/components/AssetFieldEditor.d.ts +18 -0
  87. package/dist/features/preview/components/AssetFieldEditor.d.ts.map +1 -0
  88. package/dist/features/preview/components/AssetFieldEditor.js +139 -0
  89. package/dist/features/preview/components/AssetLightbox.d.ts +9 -0
  90. package/dist/features/preview/components/AssetLightbox.d.ts.map +1 -0
  91. package/dist/features/preview/components/AssetLightbox.js +421 -0
  92. package/dist/features/preview/components/AssetPickerGrid.d.ts +11 -0
  93. package/dist/features/preview/components/AssetPickerGrid.d.ts.map +1 -0
  94. package/dist/features/preview/components/AssetPickerGrid.js +92 -0
  95. package/dist/features/preview/components/BlockActionsPopover.d.ts +15 -0
  96. package/dist/features/preview/components/BlockActionsPopover.d.ts.map +1 -0
  97. package/dist/features/preview/components/BlockActionsPopover.js +506 -0
  98. package/dist/features/preview/components/CreatePageSheet.d.ts +3 -0
  99. package/dist/features/preview/components/CreatePageSheet.d.ts.map +1 -0
  100. package/dist/features/preview/components/CreatePageSheet.js +159 -0
  101. package/dist/features/preview/components/DebouncedFieldEditor.d.ts +10 -0
  102. package/dist/features/preview/components/DebouncedFieldEditor.d.ts.map +1 -0
  103. package/dist/features/preview/components/DebouncedFieldEditor.js +51 -0
  104. package/dist/features/preview/components/EditPageSheet.d.ts +3 -0
  105. package/dist/features/preview/components/EditPageSheet.d.ts.map +1 -0
  106. package/dist/features/preview/components/EditPageSheet.js +352 -0
  107. package/dist/features/preview/components/ItemFieldsEditor.d.ts +29 -0
  108. package/dist/features/preview/components/ItemFieldsEditor.d.ts.map +1 -0
  109. package/dist/features/preview/components/ItemFieldsEditor.js +308 -0
  110. package/dist/features/preview/components/LinkFieldEditor.d.ts +8 -0
  111. package/dist/features/preview/components/LinkFieldEditor.d.ts.map +1 -0
  112. package/dist/features/preview/components/LinkFieldEditor.js +190 -0
  113. package/dist/features/preview/components/MultipleAssetFieldEditor.d.ts +10 -0
  114. package/dist/features/preview/components/MultipleAssetFieldEditor.d.ts.map +1 -0
  115. package/dist/features/preview/components/MultipleAssetFieldEditor.js +232 -0
  116. package/dist/features/preview/components/OverlayTracker.d.ts +6 -0
  117. package/dist/features/preview/components/OverlayTracker.d.ts.map +1 -0
  118. package/dist/features/preview/components/OverlayTracker.js +41 -0
  119. package/dist/features/preview/components/Overlays.d.ts +6 -0
  120. package/dist/features/preview/components/Overlays.d.ts.map +1 -0
  121. package/dist/features/preview/components/Overlays.js +58 -0
  122. package/dist/features/preview/components/PageContentSheet.d.ts +3 -0
  123. package/dist/features/preview/components/PageContentSheet.d.ts.map +1 -0
  124. package/dist/features/preview/components/PageContentSheet.js +492 -0
  125. package/dist/features/preview/components/PageLocationFieldset.d.ts +14 -0
  126. package/dist/features/preview/components/PageLocationFieldset.d.ts.map +1 -0
  127. package/dist/features/preview/components/PageLocationFieldset.js +77 -0
  128. package/dist/features/preview/components/PagePicker.d.ts +3 -0
  129. package/dist/features/preview/components/PagePicker.d.ts.map +1 -0
  130. package/dist/features/preview/components/PagePicker.js +185 -0
  131. package/dist/features/preview/components/PageTree.d.ts +3 -0
  132. package/dist/features/preview/components/PageTree.d.ts.map +1 -0
  133. package/dist/features/preview/components/PageTree.js +410 -0
  134. package/dist/features/preview/components/PeekedBlock.d.ts +6 -0
  135. package/dist/features/preview/components/PeekedBlock.d.ts.map +1 -0
  136. package/dist/features/preview/components/PeekedBlock.js +95 -0
  137. package/dist/features/preview/components/PreviewPanel.d.ts +12 -0
  138. package/dist/features/preview/components/PreviewPanel.d.ts.map +1 -0
  139. package/dist/features/preview/components/PreviewPanel.js +192 -0
  140. package/dist/features/preview/components/PreviewSideSheet.d.ts +13 -0
  141. package/dist/features/preview/components/PreviewSideSheet.d.ts.map +1 -0
  142. package/dist/features/preview/components/PreviewSideSheet.js +28 -0
  143. package/dist/features/preview/components/PreviewToolbar.d.ts +2 -0
  144. package/dist/features/preview/components/PreviewToolbar.d.ts.map +1 -0
  145. package/dist/features/preview/components/PreviewToolbar.js +79 -0
  146. package/dist/features/preview/components/RepeatableItemsList.d.ts +14 -0
  147. package/dist/features/preview/components/RepeatableItemsList.d.ts.map +1 -0
  148. package/dist/features/preview/components/RepeatableItemsList.js +366 -0
  149. package/dist/features/preview/components/ShikiMarkdown.d.ts +4 -0
  150. package/dist/features/preview/components/ShikiMarkdown.d.ts.map +1 -0
  151. package/dist/features/preview/components/ShikiMarkdown.js +37 -0
  152. package/dist/features/preview/components/TextFormatToolbar.d.ts +2 -0
  153. package/dist/features/preview/components/TextFormatToolbar.d.ts.map +1 -0
  154. package/dist/features/preview/components/TextFormatToolbar.js +73 -0
  155. package/dist/features/preview/components/UnlinkAssetButton.d.ts +9 -0
  156. package/dist/features/preview/components/UnlinkAssetButton.d.ts.map +1 -0
  157. package/dist/features/preview/components/UnlinkAssetButton.js +55 -0
  158. package/dist/features/preview/overlayConstants.d.ts +19 -0
  159. package/dist/features/preview/overlayConstants.d.ts.map +1 -0
  160. package/dist/features/preview/overlayConstants.js +21 -0
  161. package/dist/features/preview/overlayMessages.d.ts +62 -0
  162. package/dist/features/preview/overlayMessages.d.ts.map +1 -0
  163. package/dist/features/preview/overlayMessages.js +9 -0
  164. package/dist/features/preview/previewConstants.d.ts +2 -0
  165. package/dist/features/preview/previewConstants.d.ts.map +1 -0
  166. package/dist/features/preview/previewStore.d.ts +116 -0
  167. package/dist/features/preview/previewStore.d.ts.map +1 -0
  168. package/dist/features/preview/previewStore.js +321 -0
  169. package/dist/features/provider/CamoxProvider.d.ts +11 -0
  170. package/dist/features/provider/CamoxProvider.d.ts.map +1 -0
  171. package/dist/features/provider/CamoxProvider.js +73 -0
  172. package/dist/features/provider/actionsStore.d.ts +39 -0
  173. package/dist/features/provider/actionsStore.d.ts.map +1 -0
  174. package/dist/features/provider/actionsStore.js +35 -0
  175. package/dist/features/provider/components/CamoxAppContext.d.ts +371 -0
  176. package/dist/features/provider/components/CamoxAppContext.d.ts.map +1 -0
  177. package/dist/features/provider/components/CamoxAppContext.js +17 -0
  178. package/dist/features/provider/components/CommandPalette.d.ts +3 -0
  179. package/dist/features/provider/components/CommandPalette.d.ts.map +1 -0
  180. package/dist/features/provider/components/CommandPalette.js +127 -0
  181. package/dist/features/provider/useAdminShortcuts.d.ts +5 -0
  182. package/dist/features/provider/useAdminShortcuts.d.ts.map +1 -0
  183. package/dist/features/provider/useAdminShortcuts.js +83 -0
  184. package/dist/features/routes/ogRoute.d.ts +7 -0
  185. package/dist/features/routes/ogRoute.d.ts.map +1 -0
  186. package/dist/features/routes/ogRoute.js +19 -0
  187. package/dist/features/routes/pageRoute.d.ts +135 -0
  188. package/dist/features/routes/pageRoute.d.ts.map +1 -0
  189. package/dist/features/routes/pageRoute.js +112 -0
  190. package/dist/features/studio/CamoxStudio.d.ts +7 -0
  191. package/dist/features/studio/CamoxStudio.d.ts.map +1 -0
  192. package/dist/features/studio/CamoxStudio.js +24 -0
  193. package/dist/features/studio/components/Navbar.d.ts +4 -0
  194. package/dist/features/studio/components/Navbar.d.ts.map +1 -0
  195. package/dist/features/studio/components/Navbar.js +95 -0
  196. package/dist/features/studio/components/ProjectMenu.d.ts +2 -0
  197. package/dist/features/studio/components/ProjectMenu.d.ts.map +1 -0
  198. package/dist/features/studio/components/ProjectMenu.js +132 -0
  199. package/dist/features/studio/components/UserButton.d.ts +2 -0
  200. package/dist/features/studio/components/UserButton.d.ts.map +1 -0
  201. package/dist/features/studio/components/UserButton.js +96 -0
  202. package/dist/features/studio/studioStore.d.ts +17 -0
  203. package/dist/features/studio/studioStore.d.ts.map +1 -0
  204. package/dist/features/studio/studioStore.js +44 -0
  205. package/dist/features/studio/useTheme.d.ts +9 -0
  206. package/dist/features/studio/useTheme.d.ts.map +1 -0
  207. package/dist/features/studio/useTheme.js +98 -0
  208. package/dist/features/vite/appGeneration.d.ts +4 -0
  209. package/dist/features/vite/appGeneration.d.ts.map +1 -0
  210. package/dist/features/vite/appGeneration.js +67 -0
  211. package/dist/features/vite/blockBoilerplate.d.ts +3 -0
  212. package/dist/features/vite/blockBoilerplate.d.ts.map +1 -0
  213. package/dist/features/vite/blockBoilerplate.js +59 -0
  214. package/dist/features/vite/convexSync.d.ts +6 -0
  215. package/dist/features/vite/convexSync.d.ts.map +1 -0
  216. package/dist/features/vite/convexSync.js +98 -0
  217. package/dist/features/vite/definitionsSync.d.ts +11 -0
  218. package/dist/features/vite/definitionsSync.d.ts.map +1 -0
  219. package/dist/features/vite/definitionsSync.js +157 -0
  220. package/dist/features/vite/routeGeneration.d.ts +4 -0
  221. package/dist/features/vite/routeGeneration.d.ts.map +1 -0
  222. package/dist/features/vite/routeGeneration.js +194 -0
  223. package/dist/features/vite/skillGeneration.d.ts +4 -0
  224. package/dist/features/vite/skillGeneration.d.ts.map +1 -0
  225. package/dist/features/vite/skillGeneration.js +69 -0
  226. package/dist/features/vite/utils.d.ts +2 -0
  227. package/dist/features/vite/utils.d.ts.map +1 -0
  228. package/dist/features/vite/utils.js +10 -0
  229. package/dist/features/vite/vite.d.ts +18 -0
  230. package/dist/features/vite/vite.d.ts.map +1 -0
  231. package/dist/features/vite/vite.js +77 -0
  232. package/dist/hooks/use-file-upload.d.ts +22 -0
  233. package/dist/hooks/use-file-upload.d.ts.map +1 -0
  234. package/dist/hooks/use-marquee-selection.d.ts +17 -0
  235. package/dist/hooks/use-marquee-selection.d.ts.map +1 -0
  236. package/dist/lib/analytics-client.d.ts +3 -0
  237. package/dist/lib/analytics-client.d.ts.map +1 -0
  238. package/dist/lib/analytics.d.ts +3 -0
  239. package/dist/lib/analytics.d.ts.map +1 -0
  240. package/dist/lib/analytics.js +24 -0
  241. package/dist/lib/auth.d.ts +3683 -0
  242. package/dist/lib/auth.d.ts.map +1 -0
  243. package/dist/lib/convex-site.d.ts +3 -0
  244. package/dist/lib/convex-site.d.ts.map +1 -0
  245. package/dist/lib/utils.d.ts +40 -0
  246. package/dist/lib/utils.d.ts.map +1 -0
  247. package/dist/studio.css +2 -0
  248. package/package.json +123 -10
  249. package/server/api.d.ts +1 -0
  250. package/server/api.js +1 -0
  251. package/server/dataModel.d.ts +1 -0
  252. package/server/dataModel.js +1 -0
  253. package/skills/camox-block/SKILL.md +357 -0
  254. package/skills/camox-layout/SKILL.md +181 -0
  255. package/index.js +0 -3
@@ -0,0 +1,15 @@
1
+ import { Doc } from 'camox/server/dataModel';
2
+ import * as React from "react";
3
+ interface BlockActionsPopoverProps {
4
+ block: Doc<"blocks"> | undefined | null;
5
+ children: React.ReactNode;
6
+ align?: "start" | "center" | "end";
7
+ open: boolean;
8
+ onOpenChange: (open: boolean) => void;
9
+ isLayoutBlock?: boolean;
10
+ layoutPlacement?: "before" | "after";
11
+ }
12
+ declare const BlockActionsPopover: ({ block, children, open, onOpenChange, align, isLayoutBlock, layoutPlacement, }: BlockActionsPopoverProps) => import("react/jsx-runtime").JSX.Element;
13
+ declare function useBlockActionsShortcuts(): void;
14
+ export { BlockActionsPopover, useBlockActionsShortcuts };
15
+ //# sourceMappingURL=BlockActionsPopover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockActionsPopover.d.ts","sourceRoot":"","sources":["../../../../src/features/preview/components/BlockActionsPopover.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAAE,GAAG,EAAM,MAAM,wBAAwB,CAAC;AAGjD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,UAAU,wBAAwB;IAChC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CACtC;AAED,QAAA,MAAM,mBAAmB,GAAI,iFAQ1B,wBAAwB,4CA+S1B,CAAC;AAsBF,iBAAS,wBAAwB,SA2PhC;AAED,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,CAAC"}
@@ -0,0 +1,506 @@
1
+ import { previewStore } from "../previewStore.js";
2
+ import { actionsStore } from "../../provider/actionsStore.js";
3
+ import { useCamoxApp } from "../../provider/components/CamoxAppContext.js";
4
+ import { usePreviewedPage } from "../CamoxPreview.js";
5
+ import { Popover, PopoverContent, PopoverTrigger } from "@camox/ui/popover";
6
+ import { toast } from "@camox/ui/toaster";
7
+ import { useSelector } from "@xstate/store/react";
8
+ import { api } from "camox/server/api";
9
+ import { useMutation } from "convex/react";
10
+ import * as React from "react";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { formatShortcut } from "@/lib/utils";
13
+ import { Button } from "@camox/ui/button";
14
+ import { Copy, Pen, Settings, Trash2 } from "lucide-react";
15
+ import { Command, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from "@camox/ui/command";
16
+ import { trackClientEvent } from "@/lib/analytics-client";
17
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@camox/ui/alert-dialog";
18
+ //#region src/features/preview/components/BlockActionsPopover.tsx
19
+ var BlockActionsPopover = ({ block, children, open, onOpenChange, align = "start", isLayoutBlock, layoutPlacement }) => {
20
+ const [blockToDelete, setBlockToDelete] = React.useState(null);
21
+ const camoxApp = useCamoxApp();
22
+ const page = usePreviewedPage();
23
+ const deleteBlockMutation = useMutation(api.blocks.deleteBlock);
24
+ const deleteBlocksMutation = useMutation(api.blocks.deleteBlocks);
25
+ const duplicateBlockMutation = useMutation(api.blocks.duplicateBlock);
26
+ const handleDeleteBlock = async (block) => {
27
+ try {
28
+ await deleteBlockMutation({ blockId: block._id });
29
+ trackClientEvent("block_deleted", {
30
+ projectId: page?.page.projectId,
31
+ blockType: block.type
32
+ });
33
+ toast.success(`Deleted "${block.summary}" block`);
34
+ } catch (error) {
35
+ console.error("Failed to delete block:", error);
36
+ toast.error("Could not delete block");
37
+ } finally {
38
+ setBlockToDelete(null);
39
+ }
40
+ };
41
+ const handleDuplicateBlock = async (block) => {
42
+ try {
43
+ await duplicateBlockMutation({ blockId: block._id });
44
+ trackClientEvent("block_duplicated", {
45
+ projectId: page?.page.projectId,
46
+ blockType: block.type
47
+ });
48
+ toast.success(`Duplicated "${block.summary}" block`);
49
+ } catch (error) {
50
+ console.error("Failed to duplicate block:", error);
51
+ toast.error("Could not duplicate block");
52
+ }
53
+ };
54
+ const handleAddBlockAbove = (block) => {
55
+ if (!page) return;
56
+ const blockIndex = page.blocks.findIndex((b) => b._id === block._id);
57
+ const afterPosition = blockIndex > 0 ? page.blocks[blockIndex - 1].position : "";
58
+ previewStore.send({
59
+ type: "openAddBlockSheet",
60
+ afterPosition
61
+ });
62
+ };
63
+ const handleAddBlockBelow = (block) => {
64
+ previewStore.send({
65
+ type: "openAddBlockSheet",
66
+ afterPosition: block.position
67
+ });
68
+ };
69
+ const getBlocksAbove = (block) => {
70
+ if (!page) return [];
71
+ const blockIndex = page.blocks.findIndex((b) => b._id === block._id);
72
+ return page.blocks.slice(0, blockIndex);
73
+ };
74
+ const getBlocksBelow = (block) => {
75
+ if (!page) return [];
76
+ const blockIndex = page.blocks.findIndex((b) => b._id === block._id);
77
+ return page.blocks.slice(blockIndex + 1);
78
+ };
79
+ const handleDeleteBlocksAbove = async (block) => {
80
+ const blocksAbove = getBlocksAbove(block);
81
+ if (blocksAbove.length === 0) return;
82
+ try {
83
+ await deleteBlocksMutation({ blockIds: blocksAbove.map((b) => b._id) });
84
+ toast.success(`Deleted ${blocksAbove.length} block${blocksAbove.length === 1 ? "" : "s"}`);
85
+ } catch (error) {
86
+ console.error("Failed to delete blocks above:", error);
87
+ toast.error("Could not delete blocks");
88
+ }
89
+ };
90
+ const handleDeleteBlocksBelow = async (block) => {
91
+ const blocksBelow = getBlocksBelow(block);
92
+ if (blocksBelow.length === 0) return;
93
+ try {
94
+ await deleteBlocksMutation({ blockIds: blocksBelow.map((b) => b._id) });
95
+ toast.success(`Deleted ${blocksBelow.length} block${blocksBelow.length === 1 ? "" : "s"}`);
96
+ } catch (error) {
97
+ console.error("Failed to delete blocks below:", error);
98
+ toast.error("Could not delete blocks");
99
+ }
100
+ };
101
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Popover, {
102
+ open,
103
+ onOpenChange,
104
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
105
+ asChild: true,
106
+ children
107
+ }), block && /* @__PURE__ */ jsx(PopoverContent, {
108
+ className: "w-[300px] p-0",
109
+ align,
110
+ children: /* @__PURE__ */ jsxs(Command, { children: [/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search actions..." }), /* @__PURE__ */ jsxs(CommandList, {
111
+ className: "max-h-[350px]",
112
+ children: [
113
+ /* @__PURE__ */ jsxs(CommandGroup, { children: [/* @__PURE__ */ jsxs(CommandItem, {
114
+ className: "justify-between",
115
+ onSelect: () => {
116
+ previewStore.send({
117
+ type: "openBlockContentSheet",
118
+ blockId: block._id
119
+ });
120
+ onOpenChange(false);
121
+ },
122
+ children: [/* @__PURE__ */ jsxs("div", {
123
+ className: "flex items-center gap-2",
124
+ children: [/* @__PURE__ */ jsx(Pen, { className: "h-4 w-4" }), "Edit in form"]
125
+ }), formatShortcut({
126
+ key: "j",
127
+ withMeta: true
128
+ })]
129
+ }), !isLayoutBlock && (() => {
130
+ const blockDef = camoxApp.getBlockById(block.type);
131
+ if (!(blockDef?.settingsSchema?.properties && Object.keys(blockDef.settingsSchema.properties).length > 0)) return null;
132
+ return /* @__PURE__ */ jsx(CommandItem, {
133
+ className: "justify-between",
134
+ onSelect: () => {
135
+ previewStore.send({
136
+ type: "openBlockContentSheet",
137
+ blockId: block._id
138
+ });
139
+ onOpenChange(false);
140
+ },
141
+ children: /* @__PURE__ */ jsxs("div", {
142
+ className: "flex items-center gap-2",
143
+ children: [/* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }), "Open settings"]
144
+ })
145
+ });
146
+ })()] }),
147
+ isLayoutBlock && layoutPlacement === "before" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CommandSeparator, {}), /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsx(CommandItem, {
148
+ onSelect: () => {
149
+ previewStore.send({
150
+ type: "openAddBlockSheet",
151
+ afterPosition: ""
152
+ });
153
+ onOpenChange(false);
154
+ },
155
+ children: /* @__PURE__ */ jsxs("div", {
156
+ className: "flex items-center gap-2",
157
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block below"]
158
+ })
159
+ }) })] }),
160
+ isLayoutBlock && layoutPlacement === "after" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CommandSeparator, {}), /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsx(CommandItem, {
161
+ onSelect: () => {
162
+ const lastPageBlock = page?.blocks[page.blocks.length - 1];
163
+ previewStore.send({
164
+ type: "openAddBlockSheet",
165
+ afterPosition: lastPageBlock?.position
166
+ });
167
+ onOpenChange(false);
168
+ },
169
+ children: /* @__PURE__ */ jsxs("div", {
170
+ className: "flex items-center gap-2",
171
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block above"]
172
+ })
173
+ }) })] }),
174
+ !isLayoutBlock && /* @__PURE__ */ jsxs(Fragment, { children: [
175
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
176
+ /* @__PURE__ */ jsxs(CommandGroup, { children: [/* @__PURE__ */ jsxs(CommandItem, {
177
+ className: "justify-between",
178
+ onSelect: () => {
179
+ handleAddBlockBelow(block);
180
+ onOpenChange(false);
181
+ },
182
+ children: [/* @__PURE__ */ jsxs("div", {
183
+ className: "flex items-center gap-2",
184
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block below"]
185
+ }), formatShortcut({ key: "o" })]
186
+ }), /* @__PURE__ */ jsxs(CommandItem, {
187
+ className: "justify-between",
188
+ onSelect: () => {
189
+ handleAddBlockAbove(block);
190
+ onOpenChange(false);
191
+ },
192
+ children: [/* @__PURE__ */ jsxs("div", {
193
+ className: "flex items-center gap-2",
194
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Add block above"]
195
+ }), formatShortcut({
196
+ key: "o",
197
+ withShift: true
198
+ })]
199
+ })] }),
200
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
201
+ /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsxs(CommandItem, {
202
+ className: "justify-between",
203
+ onSelect: () => {
204
+ handleDuplicateBlock(block);
205
+ onOpenChange(false);
206
+ },
207
+ children: [/* @__PURE__ */ jsxs("div", {
208
+ className: "flex items-center gap-2",
209
+ children: [/* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }), "Duplicate block"]
210
+ }), formatShortcut({
211
+ key: "d",
212
+ withMeta: true
213
+ })]
214
+ }) }),
215
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
216
+ /* @__PURE__ */ jsxs(CommandGroup, { children: [
217
+ /* @__PURE__ */ jsxs(CommandItem, {
218
+ onSelect: () => {
219
+ handleDeleteBlocksAbove(block);
220
+ onOpenChange(false);
221
+ },
222
+ disabled: getBlocksAbove(block).length === 0,
223
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Delete blocks above"]
224
+ }),
225
+ /* @__PURE__ */ jsxs(CommandItem, {
226
+ onSelect: () => {
227
+ handleDeleteBlocksBelow(block);
228
+ onOpenChange(false);
229
+ },
230
+ disabled: getBlocksBelow(block).length === 0,
231
+ children: [/* @__PURE__ */ jsx("span", { className: "w-4" }), "Delete blocks below"]
232
+ }),
233
+ /* @__PURE__ */ jsxs(CommandItem, {
234
+ className: "justify-between",
235
+ onSelect: () => {
236
+ handleDeleteBlock(block);
237
+ onOpenChange(false);
238
+ },
239
+ children: [/* @__PURE__ */ jsxs("div", {
240
+ className: "flex items-center gap-2",
241
+ children: [/* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }), "Delete block"]
242
+ }), formatShortcut({
243
+ key: "Backspace",
244
+ withMeta: true
245
+ })]
246
+ })
247
+ ] })
248
+ ] })
249
+ ]
250
+ })] })
251
+ })]
252
+ }), /* @__PURE__ */ jsx(AlertDialog, {
253
+ open: !!blockToDelete,
254
+ onOpenChange: (open) => !open && setBlockToDelete(null),
255
+ children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [/* @__PURE__ */ jsxs(AlertDialogHeader, { children: [/* @__PURE__ */ jsx(AlertDialogTitle, { children: "Delete block" }), /* @__PURE__ */ jsxs(AlertDialogDescription, { children: [
256
+ "Are you sure you want to delete ",
257
+ /* @__PURE__ */ jsx("strong", { children: blockToDelete?.summary }),
258
+ "? This action cannot be undone."
259
+ ] })] }), /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [/* @__PURE__ */ jsx(AlertDialogCancel, { children: "Cancel" }), /* @__PURE__ */ jsx(AlertDialogAction, {
260
+ onClick: () => blockToDelete && handleDeleteBlock(blockToDelete),
261
+ asChild: true,
262
+ children: /* @__PURE__ */ jsx(Button, {
263
+ variant: "destructive",
264
+ children: "Delete"
265
+ })
266
+ })] })] })
267
+ })] });
268
+ };
269
+ /**
270
+ * Walk breadcrumbs from deepest to shallowest and return the first
271
+ * RepeatableObject or Block entry — i.e. the closest ancestor that
272
+ * can be duplicated / deleted.
273
+ */
274
+ function findClosestActionable(breadcrumbs) {
275
+ for (let i = breadcrumbs.length - 1; i >= 0; i--) {
276
+ const crumb = breadcrumbs[i];
277
+ if (crumb.type === "RepeatableObject") return crumb;
278
+ if (crumb.type === "Block") return crumb;
279
+ }
280
+ return null;
281
+ }
282
+ function isLayoutBlockId(page, blockId) {
283
+ if (!page?.layout) return false;
284
+ return [...page.layout.beforeBlocks ?? [], ...page.layout.afterBlocks ?? []].some((b) => b._id === blockId);
285
+ }
286
+ function useBlockActionsShortcuts() {
287
+ const camoxApp = useCamoxApp();
288
+ const page = usePreviewedPage();
289
+ const selectionBreadcrumbs = useSelector(previewStore, (state) => state.context.selectionBreadcrumbs);
290
+ const deleteBlockMutation = useMutation(api.blocks.deleteBlock);
291
+ const duplicateBlockMutation = useMutation(api.blocks.duplicateBlock);
292
+ const updateBlockPositionMutation = useMutation(api.blocks.updateBlockPosition);
293
+ const deleteRepeatableItemMutation = useMutation(api.repeatableItems.deleteRepeatableItem);
294
+ const duplicateRepeatableItemMutation = useMutation(api.repeatableItems.duplicateRepeatableItem);
295
+ React.useEffect(() => {
296
+ const actions = [
297
+ {
298
+ id: "delete-selected",
299
+ label: "Delete selected",
300
+ groupLabel: "Preview",
301
+ shortcut: {
302
+ key: "Backspace",
303
+ withMeta: true
304
+ },
305
+ icon: "Trash2",
306
+ checkIfAvailable: () => {
307
+ const ctx = previewStore.getSnapshot().context;
308
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
309
+ const breadcrumbs = ctx.selectionBreadcrumbs;
310
+ const blockCrumb = breadcrumbs.find((b) => b.type === "Block");
311
+ if (blockCrumb && isLayoutBlockId(page, blockCrumb.id)) return false;
312
+ const target = findClosestActionable(breadcrumbs);
313
+ if (!target) return false;
314
+ if (target.type === "RepeatableObject") {
315
+ if (!page) return false;
316
+ if (!blockCrumb) return false;
317
+ const block = page.blocks.find((b) => b._id === blockCrumb.id);
318
+ if (!block) return false;
319
+ for (const [, value] of Object.entries(block.content)) {
320
+ if (!Array.isArray(value)) continue;
321
+ if (value.find((i) => i._id === target.id)) return value.length > 1;
322
+ }
323
+ return false;
324
+ }
325
+ return (page?.blocks.length ?? 0) > 1;
326
+ },
327
+ execute: () => {
328
+ const breadcrumbs = previewStore.getSnapshot().context.selectionBreadcrumbs;
329
+ const target = findClosestActionable(breadcrumbs);
330
+ if (!target) return;
331
+ if (target.type === "RepeatableObject") {
332
+ const itemId = target.id;
333
+ deleteRepeatableItemMutation({ itemId }).then(() => toast.success("Deleted item"), () => toast.error("Could not delete item"));
334
+ previewStore.send({ type: "selectParentBreadcrumb" });
335
+ return;
336
+ }
337
+ const blockId = target.id;
338
+ const block = page?.blocks.find((b) => b._id === blockId);
339
+ deleteBlockMutation({ blockId }).then(() => toast.success(`Deleted "${block?.summary}" block`), () => toast.error("Could not delete block"));
340
+ previewStore.send({ type: "clearSelection" });
341
+ }
342
+ },
343
+ {
344
+ id: "duplicate-selected",
345
+ label: "Duplicate selected",
346
+ groupLabel: "Preview",
347
+ shortcut: {
348
+ key: "d",
349
+ withMeta: true
350
+ },
351
+ icon: "Copy",
352
+ checkIfAvailable: () => {
353
+ const ctx = previewStore.getSnapshot().context;
354
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
355
+ const blockCrumb = ctx.selectionBreadcrumbs.find((b) => b.type === "Block");
356
+ if (blockCrumb && isLayoutBlockId(page, blockCrumb.id)) return false;
357
+ return findClosestActionable(ctx.selectionBreadcrumbs) !== null;
358
+ },
359
+ execute: () => {
360
+ const breadcrumbs = previewStore.getSnapshot().context.selectionBreadcrumbs;
361
+ const target = findClosestActionable(breadcrumbs);
362
+ if (!target) return;
363
+ if (target.type === "RepeatableObject") {
364
+ const itemId = target.id;
365
+ duplicateRepeatableItemMutation({ itemId }).then(() => toast.success("Duplicated item"), () => toast.error("Could not duplicate item"));
366
+ return;
367
+ }
368
+ const blockId = target.id;
369
+ const block = page?.blocks.find((b) => b._id === blockId);
370
+ duplicateBlockMutation({ blockId }).then(() => toast.success(`Duplicated "${block?.summary}" block`), () => toast.error("Could not duplicate block"));
371
+ }
372
+ },
373
+ {
374
+ id: "move-block-up",
375
+ label: "Move block up",
376
+ groupLabel: "Preview",
377
+ shortcut: {
378
+ key: "ArrowUp",
379
+ withAlt: true
380
+ },
381
+ icon: "ArrowUp",
382
+ checkIfAvailable: () => {
383
+ const ctx = previewStore.getSnapshot().context;
384
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
385
+ const blockCrumb = ctx.selectionBreadcrumbs.find((b) => b.type === "Block");
386
+ if (!blockCrumb || !page) return false;
387
+ if (isLayoutBlockId(page, blockCrumb.id)) return false;
388
+ return page.blocks.findIndex((b) => b._id === blockCrumb.id) > 0;
389
+ },
390
+ execute: () => {
391
+ const blockCrumb = previewStore.getSnapshot().context.selectionBreadcrumbs.find((b) => b.type === "Block");
392
+ if (!blockCrumb || !page) return;
393
+ const blockId = blockCrumb.id;
394
+ const index = page.blocks.findIndex((b) => b._id === blockId);
395
+ if (index <= 0) return;
396
+ const afterPosition = index > 1 ? page.blocks[index - 2].position : void 0;
397
+ const beforePosition = page.blocks[index - 1].position;
398
+ updateBlockPositionMutation({
399
+ blockId,
400
+ afterPosition,
401
+ beforePosition
402
+ }).then(() => {}, () => toast.error("Could not move block"));
403
+ }
404
+ },
405
+ {
406
+ id: "move-block-down",
407
+ label: "Move block down",
408
+ groupLabel: "Preview",
409
+ shortcut: {
410
+ key: "ArrowDown",
411
+ withAlt: true
412
+ },
413
+ icon: "ArrowDown",
414
+ checkIfAvailable: () => {
415
+ const ctx = previewStore.getSnapshot().context;
416
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
417
+ const blockCrumb = ctx.selectionBreadcrumbs.find((b) => b.type === "Block");
418
+ if (!blockCrumb || !page) return false;
419
+ if (isLayoutBlockId(page, blockCrumb.id)) return false;
420
+ const index = page.blocks.findIndex((b) => b._id === blockCrumb.id);
421
+ return index !== -1 && index < page.blocks.length - 1;
422
+ },
423
+ execute: () => {
424
+ const blockCrumb = previewStore.getSnapshot().context.selectionBreadcrumbs.find((b) => b.type === "Block");
425
+ if (!blockCrumb || !page) return;
426
+ const blockId = blockCrumb.id;
427
+ const index = page.blocks.findIndex((b) => b._id === blockId);
428
+ if (index === -1 || index >= page.blocks.length - 1) return;
429
+ const afterPosition = page.blocks[index + 1].position;
430
+ updateBlockPositionMutation({
431
+ blockId,
432
+ afterPosition,
433
+ beforePosition: index + 2 < page.blocks.length ? page.blocks[index + 2].position : void 0
434
+ }).then(() => {}, () => toast.error("Could not move block"));
435
+ }
436
+ },
437
+ {
438
+ id: "add-block-below",
439
+ label: "Add block below",
440
+ groupLabel: "Preview",
441
+ shortcut: { key: "o" },
442
+ checkIfAvailable: () => {
443
+ const ctx = previewStore.getSnapshot().context;
444
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
445
+ return ctx.selectionBreadcrumbs.find((b) => b.type === "Block") !== null;
446
+ },
447
+ execute: () => {
448
+ const blockCrumb = previewStore.getSnapshot().context.selectionBreadcrumbs.find((b) => b.type === "Block");
449
+ if (!blockCrumb || !page) return;
450
+ const block = page.blocks.find((b) => b._id === blockCrumb.id);
451
+ if (!block) return;
452
+ previewStore.send({
453
+ type: "openAddBlockSheet",
454
+ afterPosition: block.position
455
+ });
456
+ }
457
+ },
458
+ {
459
+ id: "add-block-above",
460
+ label: "Add block above",
461
+ groupLabel: "Preview",
462
+ shortcut: {
463
+ key: "o",
464
+ withShift: true
465
+ },
466
+ checkIfAvailable: () => {
467
+ const ctx = previewStore.getSnapshot().context;
468
+ if (ctx.isContentLocked || ctx.isPresentationMode) return false;
469
+ return ctx.selectionBreadcrumbs.find((b) => b.type === "Block") !== null;
470
+ },
471
+ execute: () => {
472
+ const blockCrumb = previewStore.getSnapshot().context.selectionBreadcrumbs.find((b) => b.type === "Block");
473
+ if (!blockCrumb || !page) return;
474
+ const blockIndex = page.blocks.findIndex((b) => b._id === blockCrumb.id);
475
+ if (blockIndex === -1) return;
476
+ const afterPosition = blockIndex > 0 ? page.blocks[blockIndex - 1].position : "";
477
+ previewStore.send({
478
+ type: "openAddBlockSheet",
479
+ afterPosition
480
+ });
481
+ }
482
+ }
483
+ ];
484
+ actionsStore.send({
485
+ type: "registerManyActions",
486
+ actions
487
+ });
488
+ return () => {
489
+ actionsStore.send({
490
+ type: "unregisterManyActions",
491
+ ids: actions.map((a) => a.id)
492
+ });
493
+ };
494
+ }, [
495
+ selectionBreadcrumbs,
496
+ page,
497
+ camoxApp,
498
+ deleteBlockMutation,
499
+ duplicateBlockMutation,
500
+ updateBlockPositionMutation,
501
+ deleteRepeatableItemMutation,
502
+ duplicateRepeatableItemMutation
503
+ ]);
504
+ }
505
+ //#endregion
506
+ export { BlockActionsPopover, useBlockActionsShortcuts };
@@ -0,0 +1,3 @@
1
+ declare const CreatePageSheet: () => import("react/jsx-runtime").JSX.Element;
2
+ export { CreatePageSheet };
3
+ //# sourceMappingURL=CreatePageSheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreatePageSheet.d.ts","sourceRoot":"","sources":["../../../../src/features/preview/components/CreatePageSheet.tsx"],"names":[],"mappings":"AAyBA,QAAA,MAAM,eAAe,+CAoJpB,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,CAAC"}