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,232 @@
1
+ import { AssetLightbox } from "./AssetLightbox.js";
2
+ import { AssetPickerGrid } from "./AssetPickerGrid.js";
3
+ import { UnlinkAssetButton } from "./UnlinkAssetButton.js";
4
+ import { AssetActionButtons } from "./AssetFieldEditor.js";
5
+ import { api } from "camox/server/api";
6
+ import { useMutation } from "convex/react";
7
+ import * as React from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { useLocation } from "@tanstack/react-router";
10
+ import { cn } from "@/lib/utils";
11
+ import { Button } from "@camox/ui/button";
12
+ import { FileIcon, GripVertical } from "lucide-react";
13
+ import { UploadDropZone } from "@/features/content/components/UploadDropZone";
14
+ import { useFileUpload } from "@/hooks/use-file-upload";
15
+ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
16
+ import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
17
+ import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
18
+ import { CSS } from "@dnd-kit/utilities";
19
+ import { generateKeyBetween } from "fractional-indexing";
20
+ //#region src/features/preview/components/MultipleAssetFieldEditor.tsx
21
+ var SortableAssetItem = ({ item, assetType, contentKey, onRemove, onAssetOpen }) => {
22
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: item._id });
23
+ const style = {
24
+ transform: CSS.Transform.toString(transform),
25
+ transition,
26
+ opacity: isDragging ? .5 : 1
27
+ };
28
+ const asset = item.content?.[contentKey];
29
+ const url = asset?.url ?? "";
30
+ const alt = asset?.alt ?? "";
31
+ const filename = asset?.filename ?? "Untitled";
32
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("div", {
33
+ ref: setNodeRef,
34
+ style,
35
+ className: cn("flex flex-row items-center gap-2 px-1 py-1 max-w-full rounded-lg text-foreground transition-none group", !isDragging && "hover:bg-accent/75"),
36
+ children: [
37
+ /* @__PURE__ */ jsx(Button, {
38
+ type: "button",
39
+ variant: "ghost",
40
+ size: "icon-sm",
41
+ className: "text-muted-foreground hover:text-foreground flex shrink-0 cursor-grab active:cursor-grabbing",
42
+ ...attributes,
43
+ ...listeners,
44
+ children: /* @__PURE__ */ jsx(GripVertical, { className: "h-4 w-4" })
45
+ }),
46
+ /* @__PURE__ */ jsxs("button", {
47
+ type: "button",
48
+ className: "flex min-w-0 flex-1 cursor-zoom-in items-center gap-2",
49
+ onClick: () => onAssetOpen(item),
50
+ children: [assetType === "Image" ? /* @__PURE__ */ jsx("div", {
51
+ className: "border-border h-12 w-12 shrink-0 overflow-hidden rounded border",
52
+ children: /* @__PURE__ */ jsx("img", {
53
+ src: url,
54
+ alt: alt || filename,
55
+ className: "h-full w-full object-cover"
56
+ })
57
+ }) : /* @__PURE__ */ jsx("div", {
58
+ className: "border-border bg-muted flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded border",
59
+ children: /* @__PURE__ */ jsx(FileIcon, { className: "text-muted-foreground h-6 w-6" })
60
+ }), /* @__PURE__ */ jsx("p", {
61
+ className: "flex-1 truncate text-left text-sm",
62
+ title: filename,
63
+ children: filename
64
+ })]
65
+ }),
66
+ /* @__PURE__ */ jsx(UnlinkAssetButton, {
67
+ fileId: asset?._fileId,
68
+ onUnlink: () => onRemove(item._id),
69
+ className: "hidden group-focus-within:flex group-hover:flex"
70
+ })
71
+ ]
72
+ }) });
73
+ };
74
+ var MultipleAssetFieldEditor = ({ fieldName, assetType, currentData, blockId }) => {
75
+ const { pathname } = useLocation();
76
+ const contentKey = assetType === "Image" ? "image" : "file";
77
+ const isImage = assetType === "Image";
78
+ const fileInputRef = React.useRef(null);
79
+ const createItemMutation = useMutation(api.repeatableItems.createRepeatableItem);
80
+ const deleteItemMutation = useMutation(api.repeatableItems.deleteRepeatableItem);
81
+ const updatePositionMutation = useMutation(api.repeatableItems.updateRepeatableItemPosition).withOptimisticUpdate((localStore, args) => {
82
+ const currentPage = localStore.getQuery(api.pages.getPage, { fullPath: pathname });
83
+ if (!currentPage) return;
84
+ const updatedBlocks = currentPage.blocks.map((block) => {
85
+ if (!Object.entries(block.content).some(([_, value]) => {
86
+ if (Array.isArray(value)) return value.some((item) => item._id === args.itemId);
87
+ return false;
88
+ })) return block;
89
+ const updatedContent = { ...block.content };
90
+ for (const [fieldName, fieldValue] of Object.entries(block.content)) {
91
+ if (!Array.isArray(fieldValue)) continue;
92
+ const items = fieldValue;
93
+ const itemIndex = items.findIndex((item) => item._id === args.itemId);
94
+ if (itemIndex === -1) continue;
95
+ const item = items[itemIndex];
96
+ const newPosition = generateKeyBetween(args.afterPosition ?? null, args.beforePosition ?? null);
97
+ const updatedItem = {
98
+ ...item,
99
+ position: newPosition
100
+ };
101
+ const newItems = [...items];
102
+ newItems[itemIndex] = updatedItem;
103
+ newItems.sort((a, b) => {
104
+ if (a.position < b.position) return -1;
105
+ if (a.position > b.position) return 1;
106
+ return 0;
107
+ });
108
+ updatedContent[fieldName] = newItems;
109
+ }
110
+ return {
111
+ ...block,
112
+ content: updatedContent
113
+ };
114
+ });
115
+ localStore.setQuery(api.pages.getPage, { fullPath: pathname }, {
116
+ ...currentPage,
117
+ blocks: updatedBlocks
118
+ });
119
+ });
120
+ const { uploads, uploadFiles } = useFileUpload({ onFileCommitted: (result) => {
121
+ createItemMutation({
122
+ blockId,
123
+ fieldName,
124
+ content: { [contentKey]: {
125
+ url: result.url,
126
+ alt: "",
127
+ filename: result.filename,
128
+ mimeType: result.mimeType,
129
+ _fileId: result.fileId
130
+ } }
131
+ });
132
+ } });
133
+ const items = (currentData[fieldName] ?? []).filter((item) => {
134
+ return !!(item.content?.[contentKey])?.url;
135
+ });
136
+ const [pickerOpen, setPickerOpen] = React.useState(false);
137
+ const [lightboxItem, setLightboxItem] = React.useState(null);
138
+ const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
139
+ const handleDragEnd = async (event) => {
140
+ const { active, over } = event;
141
+ if (!over || active.id === over.id) return;
142
+ const dbItems = items;
143
+ const oldIndex = dbItems.findIndex((item) => item._id === active.id);
144
+ const newIndex = dbItems.findIndex((item) => item._id === over.id);
145
+ if (oldIndex === -1 || newIndex === -1) return;
146
+ let afterPosition;
147
+ let beforePosition;
148
+ if (oldIndex < newIndex) {
149
+ afterPosition = dbItems[newIndex].position;
150
+ beforePosition = newIndex < dbItems.length - 1 ? dbItems[newIndex + 1].position : void 0;
151
+ } else {
152
+ afterPosition = newIndex > 0 ? dbItems[newIndex - 1].position : void 0;
153
+ beforePosition = dbItems[newIndex].position;
154
+ }
155
+ await updatePositionMutation({
156
+ itemId: active.id,
157
+ afterPosition,
158
+ beforePosition
159
+ });
160
+ };
161
+ const handleRemove = (itemId) => {
162
+ deleteItemMutation({ itemId });
163
+ };
164
+ const handleAssetOpen = (item) => {
165
+ setLightboxItem(item);
166
+ };
167
+ const handleSelectMultiple = async (files) => {
168
+ for (const file of files) await createItemMutation({
169
+ blockId,
170
+ fieldName,
171
+ content: { [contentKey]: {
172
+ url: file.url,
173
+ alt: file.alt,
174
+ filename: file.filename,
175
+ mimeType: file.mimeType,
176
+ _fileId: file._id
177
+ } }
178
+ });
179
+ setPickerOpen(false);
180
+ };
181
+ return /* @__PURE__ */ jsxs(UploadDropZone, {
182
+ onDrop: uploadFiles,
183
+ children: [pickerOpen ? /* @__PURE__ */ jsx(AssetPickerGrid, {
184
+ assetType,
185
+ mode: "multiple",
186
+ onSelectSingle: () => {},
187
+ onSelectMultiple: handleSelectMultiple,
188
+ onClose: () => setPickerOpen(false)
189
+ }) : /* @__PURE__ */ jsxs("div", {
190
+ className: "space-y-4 px-4 py-4",
191
+ children: [items.length > 0 && /* @__PURE__ */ jsx(DndContext, {
192
+ sensors,
193
+ collisionDetection: closestCenter,
194
+ onDragEnd: handleDragEnd,
195
+ modifiers: [restrictToVerticalAxis],
196
+ children: /* @__PURE__ */ jsx(SortableContext, {
197
+ items: items.map((item) => item._id),
198
+ strategy: verticalListSortingStrategy,
199
+ children: /* @__PURE__ */ jsx("ul", {
200
+ className: "flex flex-col gap-1",
201
+ children: items.map((item) => /* @__PURE__ */ jsx(SortableAssetItem, {
202
+ item,
203
+ assetType,
204
+ contentKey,
205
+ onRemove: handleRemove,
206
+ onAssetOpen: handleAssetOpen
207
+ }, item._id))
208
+ })
209
+ })
210
+ }), /* @__PURE__ */ jsx(AssetActionButtons, {
211
+ isImage,
212
+ multiple: true,
213
+ fileInputRef,
214
+ onPickerOpen: () => setPickerOpen(true),
215
+ onFilesSelected: uploadFiles,
216
+ uploads
217
+ })]
218
+ }), (() => {
219
+ const asset = lightboxItem?.content?.[contentKey];
220
+ if (!asset?._fileId) return null;
221
+ return /* @__PURE__ */ jsx(AssetLightbox, {
222
+ open: !!lightboxItem,
223
+ onOpenChange: (open) => {
224
+ if (!open) setLightboxItem(null);
225
+ },
226
+ fileId: asset._fileId
227
+ });
228
+ })()]
229
+ });
230
+ };
231
+ //#endregion
232
+ export { MultipleAssetFieldEditor };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * OverlayTracker runs inside the iframe and handles:
3
+ * Listening for focus commands from parent (for sidebar-triggered focus)
4
+ */
5
+ export declare const OverlayTracker: () => null;
6
+ //# sourceMappingURL=OverlayTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OverlayTracker.d.ts","sourceRoot":"","sources":["../../../../src/features/preview/components/OverlayTracker.tsx"],"names":[],"mappings":"AAOA;;;GAGG;AACH,eAAO,MAAM,cAAc,YAoD1B,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { isOverlayMessage } from "../overlayMessages.js";
2
+ import { previewStore } from "../previewStore.js";
3
+ import { useFrame } from "@camox/ui/frame";
4
+ import { useSelector } from "@xstate/store/react";
5
+ import * as React from "react";
6
+ //#region src/features/preview/components/OverlayTracker.tsx
7
+ /**
8
+ * OverlayTracker runs inside the iframe and handles:
9
+ * Listening for focus commands from parent (for sidebar-triggered focus)
10
+ */
11
+ var OverlayTracker = () => {
12
+ const { window: iframeWindow } = useFrame();
13
+ const isPageContentSheetOpen = useSelector(previewStore, (state) => state.context.isPageContentSheetOpen);
14
+ const isAddBlockSheetOpen = useSelector(previewStore, (state) => state.context.isAddBlockSheetOpen);
15
+ React.useEffect(() => {
16
+ if (!iframeWindow || !isAddBlockSheetOpen) return;
17
+ const handleClick = () => {
18
+ previewStore.send({ type: "exitPeekedBlock" });
19
+ };
20
+ iframeWindow.document.addEventListener("click", handleClick);
21
+ return () => iframeWindow.document.removeEventListener("click", handleClick);
22
+ }, [iframeWindow, isAddBlockSheetOpen]);
23
+ React.useEffect(() => {
24
+ if (!iframeWindow) return;
25
+ const handleMessage = (event) => {
26
+ if (!isOverlayMessage(event.data)) return;
27
+ const { type } = event.data;
28
+ if (type === "CAMOX_FOCUS_FIELD") {
29
+ if (isPageContentSheetOpen) return;
30
+ const { fieldId } = event.data;
31
+ const element = iframeWindow.document.querySelector(`[data-camox-field-id="${fieldId}"]`);
32
+ if (element) element.focus();
33
+ }
34
+ };
35
+ iframeWindow.addEventListener("message", handleMessage);
36
+ return () => iframeWindow.removeEventListener("message", handleMessage);
37
+ }, [iframeWindow, isPageContentSheetOpen]);
38
+ return null;
39
+ };
40
+ //#endregion
41
+ export { OverlayTracker };
@@ -0,0 +1,6 @@
1
+ interface OverlaysProps {
2
+ iframeElement: HTMLIFrameElement | null;
3
+ }
4
+ export declare const Overlays: ({ iframeElement }: OverlaysProps) => null;
5
+ export {};
6
+ //# sourceMappingURL=Overlays.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Overlays.d.ts","sourceRoot":"","sources":["../../../../src/features/preview/components/Overlays.tsx"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACrB,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,QAAQ,GAAI,mBAAmB,aAAa,SAgFxD,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { isOverlayMessage } from "../overlayMessages.js";
2
+ import { previewStore } from "../previewStore.js";
3
+ import { usePreviewedPage } from "../CamoxPreview.js";
4
+ import { useSelector } from "@xstate/store/react";
5
+ import * as React from "react";
6
+ //#region src/features/preview/components/Overlays.tsx
7
+ var Overlays = ({ iframeElement }) => {
8
+ const isPageContentSheetOpen = useSelector(previewStore, (state) => state.context.isPageContentSheetOpen);
9
+ const selectionBreadcrumbs = useSelector(previewStore, (state) => state.context.selectionBreadcrumbs);
10
+ const peekedBlock = useSelector(previewStore, (state) => state.context.peekedBlock);
11
+ const page = usePreviewedPage();
12
+ React.useEffect(() => {
13
+ const handleMessage = (event) => {
14
+ if (!isOverlayMessage(event.data)) return;
15
+ const message = event.data;
16
+ if (message.type === "CAMOX_ADD_BLOCK_REQUEST") {
17
+ const { blockPosition, insertPosition } = message;
18
+ let afterPosition = null;
19
+ if (message.afterPosition !== void 0) afterPosition = message.afterPosition;
20
+ else if (insertPosition === "after") afterPosition = blockPosition;
21
+ else {
22
+ const blockIndex = page?.blocks.findIndex((b) => b.position === blockPosition);
23
+ if (blockIndex !== void 0 && blockIndex > 0) afterPosition = page?.blocks[blockIndex - 1].position ?? null;
24
+ else if (blockIndex === 0) afterPosition = "";
25
+ }
26
+ previewStore.send({
27
+ type: "openAddBlockSheet",
28
+ afterPosition
29
+ });
30
+ }
31
+ };
32
+ window.addEventListener("message", handleMessage);
33
+ return () => window.removeEventListener("message", handleMessage);
34
+ }, [page]);
35
+ React.useEffect(() => {
36
+ if (isPageContentSheetOpen) return;
37
+ if (peekedBlock) return;
38
+ if (selectionBreadcrumbs.length === 0) return;
39
+ const fieldBreadcrumb = selectionBreadcrumbs.find((b) => b.type === "String");
40
+ if (!fieldBreadcrumb) return;
41
+ const blockBreadcrumb = selectionBreadcrumbs.find((b) => b.type === "Block");
42
+ if (!blockBreadcrumb) return;
43
+ const repeatableItemBreadcrumb = selectionBreadcrumbs.find((b) => b.type === "RepeatableObject");
44
+ const message = {
45
+ type: "CAMOX_FOCUS_FIELD",
46
+ fieldId: repeatableItemBreadcrumb ? `${blockBreadcrumb.id}__${repeatableItemBreadcrumb.id}__${fieldBreadcrumb.id}` : `${blockBreadcrumb.id}__${fieldBreadcrumb.id}`
47
+ };
48
+ iframeElement?.contentWindow?.postMessage(message, "*");
49
+ }, [
50
+ selectionBreadcrumbs,
51
+ isPageContentSheetOpen,
52
+ peekedBlock,
53
+ iframeElement
54
+ ]);
55
+ return null;
56
+ };
57
+ //#endregion
58
+ export { Overlays };
@@ -0,0 +1,3 @@
1
+ declare const PageContentSheet: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export { PageContentSheet };
3
+ //# sourceMappingURL=PageContentSheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageContentSheet.d.ts","sourceRoot":"","sources":["../../../../src/features/preview/components/PageContentSheet.tsx"],"names":[],"mappings":"AAqKA,QAAA,MAAM,gBAAgB,sDAijBrB,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}