camox 0.44.0 → 0.45.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 (411) hide show
  1. package/dist/components/AuthGate.js +0 -6
  2. package/dist/components/DeviceSelector.js +96 -0
  3. package/dist/components/PlatformLabel.js +20 -24
  4. package/dist/core/components/lexical/HighlightNode.js +1 -1
  5. package/dist/core/components/lexical/InlineContentEditable.js +15 -19
  6. package/dist/core/components/lexical/InlineLexicalEditor.js +54 -74
  7. package/dist/core/components/lexical/InlineStylesPlugin.js +53 -53
  8. package/dist/core/components/lexical/MaxLengthPlugin.js +59 -0
  9. package/dist/core/components/lexical/SelectionBroadcaster.js +53 -54
  10. package/dist/core/components/lexical/SidebarLexicalEditor.js +322 -229
  11. package/dist/core/components/lexical/SummaryToggleGuard.js +42 -0
  12. package/dist/core/components/lexical/TextLinkPopover.js +169 -180
  13. package/dist/core/createApp.d.ts +241 -312
  14. package/dist/core/createApp.js +123 -29
  15. package/dist/core/createBlock.d.ts +5 -5
  16. package/dist/core/createBlock.js +385 -152
  17. package/dist/core/createCollection.d.ts +55 -0
  18. package/dist/core/createCollection.js +93 -0
  19. package/dist/core/createLayout.d.ts +197 -61
  20. package/dist/core/createLayout.js +114 -56
  21. package/dist/core/defineDocument.d.ts +3 -5
  22. package/dist/core/derivedRoutes.js +49 -1
  23. package/dist/core/dom.d.ts +13 -4
  24. package/dist/core/dom.js +44 -1
  25. package/dist/core/editing/BlockEditingRuntime.d.ts +16 -0
  26. package/dist/core/editing/BlockEditingRuntime.js +6 -15
  27. package/dist/core/editing/CompleteBlockEditingRuntime.js +28 -23
  28. package/dist/core/editing/createEditableBlock.d.ts +754 -633
  29. package/dist/core/editing/createEditableBlock.js +2113 -1066
  30. package/dist/core/editing/referenceWrites.js +51 -0
  31. package/dist/core/editing/useLatestRecord.js +90 -0
  32. package/dist/core/hooks/useArtifactHost.js +139 -0
  33. package/dist/core/hooks/useFieldSelection.js +43 -18
  34. package/dist/core/hooks/useIsEditable.js +12 -10
  35. package/dist/core/hooks/useOverlayMessage.js +15 -19
  36. package/dist/core/lib/artifact.d.ts +21 -0
  37. package/dist/core/lib/artifact.js +154 -0
  38. package/dist/core/lib/artifactColors.js +123 -0
  39. package/dist/core/lib/artifactData.d.ts +1 -0
  40. package/dist/core/lib/artifactData.js +131 -0
  41. package/dist/core/lib/artifactHost.js +205 -0
  42. package/dist/core/lib/artifactRuntime.js +36 -0
  43. package/dist/core/lib/artifactTheme.js +57 -0
  44. package/dist/core/lib/contentType.d.ts +302 -106
  45. package/dist/core/lib/contentType.js +201 -173
  46. package/dist/core/lib/fieldTypes.js +3 -0
  47. package/dist/core/lib/iconTypes.d.ts +3 -3
  48. package/dist/core/lib/icons.d.ts +4 -4
  49. package/dist/core/lib/icons.js +40 -44
  50. package/dist/core/lib/imagePlaceholder.js +177 -0
  51. package/dist/core/lib/imageTransform.js +1 -1
  52. package/dist/core/lib/lexicalReact.d.ts +3 -1
  53. package/dist/core/lib/lexicalState.js +1 -1
  54. package/dist/core/lib/previewPaused.js +9 -0
  55. package/dist/core/lib/recordScope.js +316 -0
  56. package/dist/core/lib/reference.d.ts +81 -0
  57. package/dist/core/lib/reference.js +29 -0
  58. package/dist/core/lib/textLinks.js +7 -5
  59. package/dist/core/lib/textStyles.d.ts +5 -7
  60. package/dist/core/lib/textStyles.js +2 -2
  61. package/dist/core/notFound.d.ts +7 -0
  62. package/dist/core/notFound.js +11 -0
  63. package/dist/core/pageDestinations.js +6 -3
  64. package/dist/core/recordItem.js +34 -0
  65. package/dist/core/requestContext.d.ts +26 -0
  66. package/dist/core/requestContext.js +20 -0
  67. package/dist/features/canvas/CamoxCanvas.js +1734 -0
  68. package/dist/features/canvas/CanvasBlockFrame.js +353 -0
  69. package/dist/features/canvas/CanvasBlockHeader.js +55 -0
  70. package/dist/features/canvas/CanvasLoadingScreen.js +35 -0
  71. package/dist/features/canvas/CanvasOverlays.js +254 -0
  72. package/dist/features/canvas/CanvasPageEdge.js +87 -0
  73. package/dist/features/canvas/CanvasPageFrame.js +335 -0
  74. package/dist/features/canvas/CanvasPageHeader.js +125 -0
  75. package/dist/features/canvas/CanvasPreviewPageSlot.js +103 -0
  76. package/dist/features/canvas/CanvasShelfMarker.js +255 -0
  77. package/dist/features/canvas/DerivedPagePathInput.js +238 -0
  78. package/dist/features/canvas/canvasCamera.js +229 -0
  79. package/dist/features/canvas/canvasFlight.js +104 -0
  80. package/dist/features/canvas/canvasFrameCapture.js +364 -0
  81. package/dist/features/canvas/canvasFrameDocument.js +317 -0
  82. package/dist/features/canvas/canvasFrameMode.js +53 -0
  83. package/dist/features/canvas/canvasInsertionSeams.js +44 -0
  84. package/dist/features/canvas/canvasItems.js +120 -0
  85. package/dist/features/canvas/canvasOverlayGeometry.js +240 -0
  86. package/dist/features/canvas/canvasPages.js +79 -0
  87. package/dist/features/canvas/canvasScreenSpace.js +26 -0
  88. package/dist/features/canvas/canvasSelection.js +18 -0
  89. package/dist/features/canvas/canvasStore.js +149 -0
  90. package/dist/features/canvas/canvasThumbnails.js +304 -0
  91. package/dist/features/canvas/canvasZoom.js +10 -0
  92. package/dist/features/canvas/sidebar/CanvasInspector.js +202 -0
  93. package/dist/features/canvas/sidebar/CanvasNavigator.js +226 -0
  94. package/dist/features/canvas/sidebar/CanvasSidebar.js +60 -0
  95. package/dist/features/canvas/sidebar/CanvasSidebarFrame.js +48 -0
  96. package/dist/features/canvas/sidebar/CanvasSidebarSkeleton.js +39 -0
  97. package/dist/features/canvas/sidebar/CatalogBlockInspector.js +189 -0
  98. package/dist/features/canvas/sidebar/CuratedPageInspector.js +69 -0
  99. package/dist/features/canvas/sidebar/DerivedPageInspector.js +37 -0
  100. package/dist/features/canvas/sidebar/LayoutPageBlocks.js +78 -0
  101. package/dist/features/canvas/sidebar/LayoutPageOverview.js +71 -0
  102. package/dist/features/canvas/sidebar/PageInspector.js +157 -0
  103. package/dist/features/canvas/sidebar/PageInspectorSkeleton.js +90 -0
  104. package/dist/features/canvas/sidebar/PageOverview.js +27 -0
  105. package/dist/features/canvas/sidebar/SingletonPageInspector.js +31 -0
  106. package/dist/features/canvas/useCanvasCamera.js +803 -0
  107. package/dist/features/canvas/useCanvasFrame.js +149 -0
  108. package/dist/features/canvas/useCanvasFrameInput.js +97 -0
  109. package/dist/features/canvas/useCanvasNearness.js +57 -0
  110. package/dist/features/canvas/useDiscoveredPreviewPaths.js +62 -0
  111. package/dist/features/content/CamoxContent.d.ts +2 -5
  112. package/dist/features/content/CamoxContent.js +174 -271
  113. package/dist/features/content/CollectionItemSheetContext.js +106 -0
  114. package/dist/features/content/ContentAssets.js +315 -0
  115. package/dist/features/content/ContentCollection.js +663 -0
  116. package/dist/features/content/collection-form.js +58 -0
  117. package/dist/features/content/components/AssetCard.js +80 -84
  118. package/dist/features/content/components/AssetCardSkeleton.js +4 -8
  119. package/dist/features/content/components/ContentSidebar.js +129 -18
  120. package/dist/features/content/components/ContentSidebarGroup.js +37 -0
  121. package/dist/features/content/components/DeleteCollectionItemButton.js +202 -0
  122. package/dist/features/content/components/MissingFromLocale.js +282 -0
  123. package/dist/features/content/components/UploadDropZone.js +27 -31
  124. package/dist/features/content/components/UploadProgressDrawer.js +90 -98
  125. package/dist/features/navigation/navigation.d.ts +66 -20
  126. package/dist/features/navigation/navigation.js +257 -90
  127. package/dist/features/og/defaultFonts.js +8 -8
  128. package/dist/features/og/geist-variable-ttf-base64.js +1 -1
  129. package/dist/features/og/imageResponse.d.ts +8 -0
  130. package/dist/features/og/imageResponse.js +26 -0
  131. package/dist/features/page/CuratedPageContent.js +167 -0
  132. package/dist/features/page/DerivedPageContent.js +26 -30
  133. package/dist/features/page/SharedLayoutContent.js +25 -27
  134. package/dist/features/preview/CamoxPreview.d.ts +23 -61
  135. package/dist/features/preview/CamoxPreview.js +816 -537
  136. package/dist/features/preview/EditablePageContent.js +1 -1
  137. package/dist/features/preview/EditablePageExperience.js +16 -22
  138. package/dist/features/preview/components/AddBlockDialog.js +270 -0
  139. package/dist/features/preview/components/AssetFieldEditor.js +173 -154
  140. package/dist/features/preview/components/AssetLightbox.js +181 -134
  141. package/dist/features/preview/components/AssetPickerModal.js +153 -170
  142. package/dist/features/preview/components/BlockActionsPopover.js +150 -149
  143. package/dist/features/preview/components/BlockErrorBoundary.js +8 -12
  144. package/dist/features/preview/components/BlockThumbnail.js +176 -100
  145. package/dist/features/preview/components/CanvasPreview.js +243 -0
  146. package/dist/features/preview/components/CreatePageModal.js +128 -137
  147. package/dist/features/preview/components/DebouncedFieldEditor.js +29 -33
  148. package/dist/features/preview/components/DerivedLayoutDialog.js +21 -19
  149. package/dist/features/preview/components/DrillRow.js +150 -0
  150. package/dist/features/preview/components/FieldOverlayStyles.js +11 -8
  151. package/dist/features/preview/components/FieldToolbar.js +160 -110
  152. package/dist/features/preview/components/Frame.js +108 -20
  153. package/dist/features/preview/components/IconFieldEditor.js +62 -66
  154. package/dist/features/preview/components/ItemFieldsEditor.js +231 -205
  155. package/dist/features/preview/components/LinkFieldEditor.js +135 -139
  156. package/dist/features/preview/components/Metadata.js +22 -30
  157. package/dist/features/preview/components/MobilePreviewDrawer.js +89 -108
  158. package/dist/features/preview/components/MultipleAssetFieldEditor.js +334 -246
  159. package/dist/features/preview/components/OverlayTracker.js +9 -41
  160. package/dist/features/preview/components/Overlays.js +81 -69
  161. package/dist/features/preview/components/PageInfo.js +1748 -0
  162. package/dist/features/preview/components/PageInfoSkeleton.js +51 -0
  163. package/dist/features/preview/components/PageLocationFieldset.js +112 -116
  164. package/dist/features/preview/components/PageNavigatorHeader.js +24 -0
  165. package/dist/features/preview/components/PageNicknameField.js +22 -26
  166. package/dist/features/preview/components/PagePicker.js +128 -130
  167. package/dist/features/preview/components/PageTree.js +525 -532
  168. package/dist/features/preview/components/PreviewActivation.js +28 -32
  169. package/dist/features/preview/components/PreviewPanel.js +620 -319
  170. package/dist/features/preview/components/PreviewToolbar.js +105 -333
  171. package/dist/features/preview/components/RecordCard.js +80 -0
  172. package/dist/features/preview/components/RecordCombobox.js +178 -0
  173. package/dist/features/preview/components/ReferenceFieldEditor.js +149 -0
  174. package/dist/features/preview/components/ReferenceListFieldEditor.js +432 -0
  175. package/dist/features/preview/components/RemovedBlockPlaceholder.js +95 -0
  176. package/dist/features/preview/components/RepeatableItemsList.js +125 -138
  177. package/dist/features/preview/components/SelectionEditor.js +993 -0
  178. package/dist/features/preview/components/ShikiMarkdown.js +14 -18
  179. package/dist/features/preview/components/SidebarSection.js +52 -64
  180. package/dist/features/preview/components/StudioEditingFallback.js +56 -0
  181. package/dist/features/preview/components/UnlinkAssetButton.js +104 -107
  182. package/dist/features/preview/components/blockGridNavigation.js +15 -0
  183. package/dist/features/preview/components/contentFieldSchema.js +8 -0
  184. package/dist/features/preview/components/useFieldWriter.js +200 -0
  185. package/dist/features/preview/components/useRecordView.js +383 -0
  186. package/dist/features/preview/components/useRepeatableItemActions.js +35 -37
  187. package/dist/features/preview/components/useUpdateBlockPosition.js +37 -37
  188. package/dist/features/preview/editingFrame.js +197 -0
  189. package/dist/features/preview/overlayHighlights.js +17 -44
  190. package/dist/features/preview/overlayMessages.js +72 -1
  191. package/dist/features/preview/pageRecord.js +189 -0
  192. package/dist/features/preview/previewConstants.js +6 -2
  193. package/dist/features/preview/previewPageFrame.js +95 -0
  194. package/dist/features/preview/previewPreparation.js +7 -0
  195. package/dist/features/preview/previewSelection.js +32 -63
  196. package/dist/features/preview/previewStore.js +225 -123
  197. package/dist/features/preview/referencePickerFocus.js +29 -0
  198. package/dist/features/preview/repeatableItemTargets.js +56 -0
  199. package/dist/features/preview/selectionReveal.js +21 -0
  200. package/dist/features/preview/usePreviewViewportActions.js +114 -0
  201. package/dist/features/preview/viewportContinuity.js +109 -0
  202. package/dist/features/provider/AuthenticatedCamoxProvider.js +69 -44
  203. package/dist/features/provider/CamoxProvider.d.ts +3 -6
  204. package/dist/features/provider/CamoxProvider.js +38 -50
  205. package/dist/features/provider/CoreCamoxProvider.js +66 -50
  206. package/dist/features/provider/LocalhostPreviewProvider.js +78 -114
  207. package/dist/features/provider/PreviewSignInPage.js +54 -0
  208. package/dist/features/provider/components/CamoxAppContext.js +11 -11
  209. package/dist/features/provider/components/CommandPalette.js +75 -82
  210. package/dist/features/provider/useAdminShortcuts.js +7 -11
  211. package/dist/features/routes/pageRuntime.d.ts +44 -4
  212. package/dist/features/routes/pageRuntime.js +244 -137
  213. package/dist/features/runtime/RuntimeChrome.js +117 -115
  214. package/dist/features/runtime/alternates.js +64 -0
  215. package/dist/features/runtime/analytics.d.ts +7 -0
  216. package/dist/features/runtime/analytics.js +66 -0
  217. package/dist/features/runtime/artifactSources.js +87 -0
  218. package/dist/features/runtime/editingFallback.js +20 -0
  219. package/dist/features/runtime/linkPrefetch.js +97 -0
  220. package/dist/features/runtime/livePages.js +62 -0
  221. package/dist/features/runtime/llmsTxt.js +40 -0
  222. package/dist/features/runtime/loopbackFetch.js +18 -0
  223. package/dist/features/runtime/navigationAccessibility.js +51 -0
  224. package/dist/features/runtime/navigationTarget.js +23 -2
  225. package/dist/features/runtime/pageApp.js +229 -158
  226. package/dist/features/runtime/pageBlockTypes.js +20 -0
  227. package/dist/features/runtime/pageClient.d.ts +2 -4
  228. package/dist/features/runtime/pageClient.js +18 -3
  229. package/dist/features/runtime/pageNavigation.js +254 -32
  230. package/dist/features/runtime/pageServer.d.ts +2 -4
  231. package/dist/features/runtime/pageServer.js +6 -2
  232. package/dist/features/runtime/pageViewport.js +7 -0
  233. package/dist/features/runtime/runtime.d.ts +59 -24
  234. package/dist/features/runtime/runtime.js +779 -191
  235. package/dist/features/runtime/runtimeChromeLoader.js +58 -0
  236. package/dist/features/runtime/runtimeRoutes.d.ts +19 -0
  237. package/dist/features/runtime/runtimeRoutes.js +25 -0
  238. package/dist/features/runtime/scrollRestoration.js +133 -0
  239. package/dist/features/runtime/studioApp.d.ts +4 -3
  240. package/dist/features/runtime/studioApp.js +5 -9
  241. package/dist/features/runtime/studioClient.d.ts +2 -4
  242. package/dist/features/runtime/studioClient.js +12 -3
  243. package/dist/features/runtime/studioServer.d.ts +2 -4
  244. package/dist/features/runtime/studioServer.js +6 -1
  245. package/dist/features/runtime/worker.d.ts +6 -0
  246. package/dist/features/runtime/worker.js +23 -0
  247. package/dist/features/runtime/workerRequest.js +44 -0
  248. package/dist/features/studio/CamoxStudio.d.ts +2 -6
  249. package/dist/features/studio/CamoxStudio.js +34 -49
  250. package/dist/features/studio/FollowAgentProvider.js +338 -0
  251. package/dist/features/studio/components/ChatSidebar.js +356 -0
  252. package/dist/features/studio/components/DraftsControl.js +676 -0
  253. package/dist/features/studio/components/FaviconDialog.js +318 -0
  254. package/dist/features/studio/components/LocalePicker.js +785 -0
  255. package/dist/features/studio/components/Navbar.js +123 -103
  256. package/dist/features/studio/components/ProjectMenu.js +239 -260
  257. package/dist/features/studio/components/RenameDraftDialog.js +206 -0
  258. package/dist/features/studio/components/ReviewDraftSheet.js +1472 -0
  259. package/dist/features/studio/components/ThreadComposer.js +157 -0
  260. package/dist/features/studio/components/ThreadMarkdown.js +113 -0
  261. package/dist/features/studio/components/ThreadMessages.js +270 -0
  262. package/dist/features/studio/components/UserButton.js +34 -23
  263. package/dist/features/studio/draftLabel.js +33 -0
  264. package/dist/features/studio/draftNotice.js +13 -0
  265. package/dist/features/studio/followAgent.js +250 -0
  266. package/dist/features/studio/followAgentContext.js +7 -0
  267. package/dist/features/studio/localeOptions.js +118 -0
  268. package/dist/features/studio/localeSwitch.js +19 -0
  269. package/dist/features/studio/routes.js +48 -1
  270. package/dist/features/studio/studioStore.js +64 -1
  271. package/dist/features/studio/useTheme.js +24 -27
  272. package/dist/features/vite/artifactRuntimeMinification.js +36 -0
  273. package/dist/features/vite/blockBoilerplate.js +6 -5
  274. package/dist/features/vite/blockChunks.js +31 -0
  275. package/dist/features/vite/bundlerLogs.js +17 -0
  276. package/dist/features/vite/definitionsSync.js +158 -226
  277. package/dist/features/vite/devAuthentication.js +4 -16
  278. package/dist/features/vite/devSignIn.js +87 -0
  279. package/dist/features/vite/iconGeneration.js +1 -1
  280. package/dist/features/vite/layoutGeneration.js +11 -1
  281. package/dist/features/vite/publishSeededContent.js +30 -0
  282. package/dist/features/vite/routeGeneration.js +6 -7
  283. package/dist/features/vite/runtimeDev.js +80 -99
  284. package/dist/features/vite/vite.d.ts +51 -31
  285. package/dist/features/vite/vite.js +224 -127
  286. package/dist/features/vite/workerBuild.js +39 -0
  287. package/dist/hooks/use-debounced-field.js +116 -47
  288. package/dist/hooks/use-file-upload.js +114 -67
  289. package/dist/hooks/use-marquee-selection.js +32 -36
  290. package/dist/hooks/use-page-destinations.js +69 -37
  291. package/dist/lib/api-client-server.d.ts +5 -0
  292. package/dist/lib/api-client-server.js +10 -4
  293. package/dist/lib/api-client.d.ts +6 -0
  294. package/dist/lib/api-client.js +51 -16
  295. package/dist/lib/api-socket.js +17 -0
  296. package/dist/lib/auth-page-styles.js +39 -0
  297. package/dist/lib/auth.js +117 -61
  298. package/dist/lib/collection-cache.js +23 -0
  299. package/dist/lib/draft-scope.d.ts +4 -0
  300. package/dist/lib/draft-scope.js +222 -0
  301. package/dist/lib/html.js +12 -0
  302. package/dist/lib/link-pages.js +154 -0
  303. package/dist/lib/locale-path.d.ts +22 -0
  304. package/dist/lib/locale-path.js +57 -0
  305. package/dist/lib/normalized-data.js +252 -152
  306. package/dist/lib/preview-handoff.js +2 -2
  307. package/dist/lib/queries.d.ts +11 -0
  308. package/dist/lib/queries.js +70 -141
  309. package/dist/lib/studio-reads.d.ts +14 -0
  310. package/dist/lib/studio-reads.js +574 -0
  311. package/dist/lib/use-project-room.js +50 -50
  312. package/dist/lib/use-thread.js +310 -0
  313. package/dist/lib/utils.js +25 -29
  314. package/dist/lib/view-locale-context.js +22 -0
  315. package/dist/lib/view-locale.js +46 -0
  316. package/dist/package.js +5 -0
  317. package/dist/studio-overlays.css +41 -151
  318. package/dist/studio.css +2 -2
  319. package/package.json +70 -73
  320. package/skills/camox/SKILL.md +16 -11
  321. package/skills/camox/references/artifacts.md +179 -0
  322. package/skills/camox/references/block-definitions.md +75 -59
  323. package/skills/camox/references/cli-common.md +9 -11
  324. package/skills/camox/references/cli-content.md +92 -69
  325. package/skills/camox/references/cli-publishing.md +26 -0
  326. package/skills/camox/references/dom-integrations.md +27 -0
  327. package/skills/camox/references/field-styling.md +4 -4
  328. package/skills/camox/references/layout-definitions.md +16 -14
  329. package/skills/camox/references/localization.md +56 -0
  330. package/skills/camox/references/routed-layouts.md +133 -15
  331. package/skills/camox-expand/SKILL.md +69 -0
  332. package/skills/camox-expand/references/jobs.md +39 -0
  333. package/skills/camoxify/SKILL.md +29 -7
  334. package/dist/core/components/AddBlockControlBar.js +0 -78
  335. package/dist/core/hooks/useRequireDraftSource.js +0 -23
  336. package/dist/features/metadata/sitemap.d.ts +0 -8
  337. package/dist/features/metadata/sitemap.js +0 -17
  338. package/dist/features/og/imageResponse.node.d.ts +0 -12
  339. package/dist/features/og/imageResponse.node.js +0 -49
  340. package/dist/features/og/imageResponse.workerd.d.ts +0 -12
  341. package/dist/features/og/imageResponse.workerd.js +0 -40
  342. package/dist/features/page/PublishedPageContent.js +0 -205
  343. package/dist/features/page/PublishedPageExperience.js +0 -23
  344. package/dist/features/preview/DerivedPreview.js +0 -134
  345. package/dist/features/preview/commentsEnabled.js +0 -8
  346. package/dist/features/preview/components/AddBlockSidebar.js +0 -381
  347. package/dist/features/preview/components/AttachedComments.js +0 -331
  348. package/dist/features/preview/components/CommentHeader.js +0 -122
  349. package/dist/features/preview/components/CommentSidebar.js +0 -29
  350. package/dist/features/preview/components/CommentTargetQuote.js +0 -167
  351. package/dist/features/preview/components/DerivedLayoutSidebar.d.ts +0 -5
  352. package/dist/features/preview/components/DerivedLayoutSidebar.js +0 -179
  353. package/dist/features/preview/components/DerivedPageInfoSidebar.js +0 -69
  354. package/dist/features/preview/components/LeftSidebar.js +0 -68
  355. package/dist/features/preview/components/PageEditorSidebar.js +0 -563
  356. package/dist/features/preview/components/PageInfoSidebar.js +0 -1551
  357. package/dist/features/preview/components/PageNavigatorSidebar.js +0 -78
  358. package/dist/features/preview/components/PageStatusBadge.js +0 -97
  359. package/dist/features/preview/components/PeekedBlock.js +0 -217
  360. package/dist/features/preview/components/PreviewComments.js +0 -56
  361. package/dist/features/preview/components/PreviewToolbarSpacer.js +0 -43
  362. package/dist/features/preview/components/PublicationRow.js +0 -422
  363. package/dist/features/preview/components/PublishDialog.js +0 -194
  364. package/dist/features/preview/components/RightSidebar.js +0 -59
  365. package/dist/features/preview/components/SendFeedbackDialog.js +0 -83
  366. package/dist/features/preview/previewCommentsStore.js +0 -135
  367. package/dist/features/preview/publication.js +0 -81
  368. package/dist/features/preview/usePageComments.js +0 -39
  369. package/dist/features/runtime/SharedChromeContext.js +0 -7
  370. package/dist/features/studio/components/EnvironmentMenu.js +0 -425
  371. package/dist/features/vite/appGeneration.js +0 -89
  372. package/dist/lib/view-queries.js +0 -28
  373. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/Matches.d.ts +0 -114
  374. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/RouterProvider.d.ts +0 -25
  375. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/config.d.ts +0 -1
  376. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/defer.d.ts +0 -1
  377. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/fileRoute.d.ts +0 -20
  378. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/global.d.ts +0 -8
  379. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/hash-scroll.d.ts +0 -1
  380. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/index.d.ts +0 -18
  381. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/link.d.ts +0 -161
  382. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/load-matches.d.ts +0 -6
  383. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/location.d.ts +0 -54
  384. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/lru-cache.d.ts +0 -8
  385. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/manifest.d.ts +0 -32
  386. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/new-process-route-tree.d.ts +0 -115
  387. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/not-found.d.ts +0 -1
  388. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/redirect.d.ts +0 -49
  389. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/rewrite.d.ts +0 -1
  390. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/root.d.ts +0 -6
  391. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/route.d.ts +0 -343
  392. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/routeInfo.d.ts +0 -48
  393. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/router.d.ts +0 -695
  394. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/scroll-restoration.d.ts +0 -1
  395. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchMiddleware.d.ts +0 -1
  396. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/searchParams.d.ts +0 -5
  397. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/RawStream.d.ts +0 -38
  398. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/seroval-plugins.d.ts +0 -1
  399. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/ssr/serializer/transformer.d.ts +0 -65
  400. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/stores.d.ts +0 -69
  401. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/structuralSharing.d.ts +0 -1
  402. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/typePrimitives.d.ts +0 -1
  403. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderData.d.ts +0 -1
  404. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useLoaderDeps.d.ts +0 -1
  405. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useNavigate.d.ts +0 -10
  406. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useParams.d.ts +0 -1
  407. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useRouteContext.d.ts +0 -1
  408. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/useSearch.d.ts +0 -1
  409. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/utils.d.ts +0 -28
  410. package/dist/node_modules/.pnpm/@tanstack_router-core@1.168.14/node_modules/@tanstack/router-core/dist/esm/validators.d.ts +0 -49
  411. package/skills/camox/references/cli-environments.md +0 -37
@@ -1,4 +1,6 @@
1
1
  import { getAuthCookieHeader, getAuthRequestCredentials } from "./auth.js";
2
+ import { localeHeaders } from "./locale-path.js";
3
+ import { DRAFT_HEADER, isContentWrite } from "@camox/api-contract/drafts";
2
4
  import { createORPCClient } from "@orpc/client";
3
5
  import { RPCLink } from "@orpc/client/fetch";
4
6
  import { createTanstackQueryUtils } from "@orpc/tanstack-query";
@@ -7,29 +9,57 @@ import { createTanstackQueryUtils } from "@orpc/tanstack-query";
7
9
  let _client = null;
8
10
  let _orpc = null;
9
11
  let _apiUrl = null;
10
- let _environmentName = null;
11
- function initApiClient(apiUrl, environmentName) {
12
+ let _draftScope = null;
13
+ const _readClients = /* @__PURE__ */ new Map();
14
+ /** Creates the window's API client, whose requests read and write the draft `draftScope` views. */
15
+ function initApiClient(apiUrl, draftScope) {
12
16
  _apiUrl = apiUrl;
13
- _environmentName = environmentName ?? null;
17
+ _draftScope = draftScope;
18
+ _readClients.clear();
19
+ _client = createStudioClient(apiUrl, (path) => draftScope.requestHeaders(isContentWrite(path)));
20
+ _orpc = createTanstackQueryUtils(_client);
21
+ return _client;
22
+ }
23
+ /**
24
+ * A client of the window's API whose requests name `draft` (null for Live) and `locale` (the
25
+ * default locale without it), whatever the studio views by the time they're sent. The studio's
26
+ * reads fetch through it, so a read caches only the draft and locale its key names.
27
+ */
28
+ function getDraftReadClient(draft, locale) {
29
+ const headers = {
30
+ ...draft && { [DRAFT_HEADER]: draft },
31
+ ...localeHeaders(locale)
32
+ };
33
+ const cacheKey = JSON.stringify(headers);
34
+ let client = _readClients.get(cacheKey);
35
+ if (client) return client;
36
+ client = createStudioClient(getApiUrl(), () => ({
37
+ headers,
38
+ settle: () => {}
39
+ }));
40
+ _readClients.set(cacheKey, client);
41
+ return client;
42
+ }
43
+ function createStudioClient(apiUrl, draftHeaders) {
14
44
  const headers = { "x-camox-client": "studio" };
15
- if (environmentName) headers["x-environment-name"] = environmentName;
16
45
  if (__CAMOX_TELEMETRY_DISABLED__) headers["x-camox-telemetry-disabled"] = "1";
17
- _client = createORPCClient(new RPCLink({
46
+ const link = new RPCLink({
18
47
  url: `${apiUrl}/rpc`,
19
48
  headers,
20
- fetch: (request, init) => {
49
+ fetch: async (request, init, _options, path) => {
21
50
  const authCookieHeader = getAuthCookieHeader();
22
- if (request instanceof Request) {
23
- if (authCookieHeader) request.headers.set("Better-Auth-Cookie", authCookieHeader);
24
- }
25
- return fetch(request, {
51
+ if (authCookieHeader) request.headers.set("Better-Auth-Cookie", authCookieHeader);
52
+ const draft = draftHeaders(path);
53
+ for (const [name, value] of Object.entries(draft.headers)) request.headers.set(name, value);
54
+ const response = await fetch(request, {
26
55
  ...init,
27
56
  credentials: getAuthRequestCredentials(authCookieHeader)
28
57
  });
58
+ draft.settle(response.ok);
59
+ return response;
29
60
  }
30
- }));
31
- _orpc = createTanstackQueryUtils(_client);
32
- return _client;
61
+ });
62
+ return createORPCClient(link);
33
63
  }
34
64
  function getApiClient() {
35
65
  if (!_client) throw new Error("API client not initialized — call initApiClient first");
@@ -43,9 +73,14 @@ function getApiUrl() {
43
73
  if (!_apiUrl) throw new Error("API client not initialized — call initApiClient first");
44
74
  return _apiUrl;
45
75
  }
46
- function getEnvironmentName() {
47
- return _environmentName;
76
+ /**
77
+ * Headers for a content write sent outside oRPC, such as a file upload: on Live it starts a draft
78
+ * like any other content write. Report the outcome through `settle`.
79
+ */
80
+ function getContentWriteHeaders() {
81
+ if (!_draftScope) throw new Error("API client not initialized — call initApiClient first");
82
+ return _draftScope.requestHeaders(true);
48
83
  }
49
84
 
50
85
  //#endregion
51
- export { getApiClient, getApiUrl, getEnvironmentName, getOrpc, initApiClient };
86
+ export { getApiClient, getApiUrl, getContentWriteHeaders, getDraftReadClient, getOrpc, initApiClient };
@@ -0,0 +1,17 @@
1
+ import { getAuthCookieHeader } from "./auth.js";
2
+
3
+ //#region src/lib/api-socket.ts
4
+ /**
5
+ * PartySocket options reaching the API at `apiUrl` as the signed-in editor. WebSocket upgrades
6
+ * can't carry custom headers, so the session is relayed in the query.
7
+ */
8
+ function apiSocketOptions(apiUrl) {
9
+ return {
10
+ host: apiUrl.replace(/^https?:\/\//, "").replace(/\/+$/, ""),
11
+ protocol: new URL(apiUrl).protocol === "http:" ? "ws" : "wss",
12
+ query: () => ({ _authCookie: getAuthCookieHeader() })
13
+ };
14
+ }
15
+
16
+ //#endregion
17
+ export { apiSocketOptions };
@@ -0,0 +1,39 @@
1
+ //#region src/lib/auth-page-styles.ts
2
+ const authPageStyles = `
3
+ .camox-auth-page {
4
+ align-items: center;
5
+ background: #09090b;
6
+ box-sizing: border-box;
7
+ color: #fafafa;
8
+ color-scheme: dark;
9
+ display: flex;
10
+ flex-direction: column;
11
+ font: 16px/1.5 Inter, ui-sans-serif, system-ui, sans-serif;
12
+ gap: 16px;
13
+ inset: 0;
14
+ justify-content: center;
15
+ margin: 0;
16
+ overflow: auto;
17
+ padding: 24px;
18
+ position: fixed;
19
+ text-align: center;
20
+ }
21
+ .camox-auth-page .camox-auth-spinner {
22
+ animation: camox-auth-spin 800ms linear infinite;
23
+ border: 2px solid #3f3f46;
24
+ border-radius: 999px;
25
+ border-top-color: #fafafa;
26
+ box-sizing: content-box;
27
+ flex-shrink: 0;
28
+ height: 24px;
29
+ width: 24px;
30
+ }
31
+ .camox-auth-page p { color: #a1a1aa; margin: 0; max-width: 32rem; }
32
+ @keyframes camox-auth-spin { to { transform: rotate(360deg); } }
33
+ @media (prefers-reduced-motion: reduce) {
34
+ .camox-auth-page .camox-auth-spinner { animation: none; }
35
+ }
36
+ `;
37
+
38
+ //#endregion
39
+ export { authPageStyles };
package/dist/lib/auth.js CHANGED
@@ -183,8 +183,10 @@ function createCamoxAuthClient(apiUrl) {
183
183
  * Verifies the token against the API backend and notifies the session store.
184
184
  *
185
185
  * Reports completion and explicit handoff failures instead of silently showing live content.
186
+ * Keeps the handoff marker until SSR confirms authentication on the subsequent load.
186
187
  */
187
- function useProcessOtt(authClient, target) {
188
+ function useProcessOtt(authClient, target, initialAuthenticated = false) {
189
+ const { projectUuid, apiUrl } = target;
188
190
  const [error, setError] = React.useState(null);
189
191
  const processing = React.useRef(false);
190
192
  const [ready, setReady] = React.useState(() => {
@@ -193,15 +195,25 @@ function useProcessOtt(authClient, target) {
193
195
  });
194
196
  React.useEffect(() => {
195
197
  const url = new URL(window.location.href);
196
- const targetError = validatePreviewTarget(url.searchParams.get("camox-preview"), target);
198
+ const targetError = validatePreviewTarget(url.searchParams.get("camox-preview"), {
199
+ projectUuid,
200
+ apiUrl
201
+ });
197
202
  if (targetError) {
198
203
  url.searchParams.delete("ott");
199
- window.history.replaceState({}, "", url);
204
+ window.history.replaceState(window.history.state, "", url);
200
205
  setError(targetError);
201
206
  setReady(true);
202
207
  return;
203
208
  }
204
- if (ready || processing.current) return;
209
+ if (ready) {
210
+ if (initialAuthenticated && !error && url.searchParams.has("camox-preview")) {
211
+ url.searchParams.delete("camox-preview");
212
+ window.history.replaceState(window.history.state, "", url);
213
+ }
214
+ return;
215
+ }
216
+ if (processing.current) return;
205
217
  const ott = url.searchParams.get("ott");
206
218
  if (!ott) {
207
219
  setReady(true);
@@ -209,7 +221,7 @@ function useProcessOtt(authClient, target) {
209
221
  }
210
222
  processing.current = true;
211
223
  url.searchParams.delete("ott");
212
- window.history.replaceState({}, "", url);
224
+ window.history.replaceState(window.history.state, "", url);
213
225
  (async () => {
214
226
  try {
215
227
  const verification = await authClient.oneTimeToken.verify({ token: ott });
@@ -225,9 +237,10 @@ function useProcessOtt(authClient, target) {
225
237
  }, [
226
238
  authClient,
227
239
  ready,
228
- target.projectSlug,
229
- target.environmentName,
230
- target.apiUrl
240
+ error,
241
+ initialAuthenticated,
242
+ projectUuid,
243
+ apiUrl
231
244
  ]);
232
245
  return {
233
246
  ready,
@@ -236,76 +249,119 @@ function useProcessOtt(authClient, target) {
236
249
  }
237
250
  const AuthContext = React.createContext(null);
238
251
  function useAuthContext() {
239
- const $ = c(1);
240
- if ($[0] !== "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525") {
241
- for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
242
- $[0] = "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525";
243
- }
244
252
  const ctx = React.useContext(AuthContext);
245
253
  if (!ctx) throw new Error("Missing CamoxProvider");
246
254
  return ctx;
247
255
  }
248
- function useProjectSlug() {
249
- const $ = c(1);
250
- if ($[0] !== "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525") {
251
- for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
252
- $[0] = "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525";
253
- }
254
- return useAuthContext().projectSlug;
256
+ function useProjectUuid() {
257
+ return useAuthContext().projectUuid;
255
258
  }
256
259
  const subscribeToHydration = () => () => {};
260
+ function hasStoredAuthCookie() {
261
+ return getCookie(localStorage.getItem("better-auth_cookie") || "{}") !== "";
262
+ }
263
+ const noSubscription = () => () => {};
264
+ /**
265
+ * The session, from the client's session store. Listening to the store fetches the session from
266
+ * the API, so an untracked session stays unfetched.
267
+ */
268
+ function useSessionState(authClient, track) {
269
+ const $ = c(4);
270
+ const sessionAtom = authClient.$store.atoms.session;
271
+ let t0;
272
+ if ($[0] !== sessionAtom) {
273
+ t0 = () => sessionAtom.value;
274
+ $[0] = sessionAtom;
275
+ $[1] = t0;
276
+ } else t0 = $[1];
277
+ const getSnapshot = t0;
278
+ let t1;
279
+ if ($[2] !== sessionAtom) {
280
+ t1 = (onChange) => sessionAtom.listen(onChange);
281
+ $[2] = sessionAtom;
282
+ $[3] = t1;
283
+ } else t1 = $[3];
284
+ const subscribe = t1;
285
+ return React.useSyncExternalStore(track ? subscribe : noSubscription, getSnapshot, getSnapshot);
286
+ }
257
287
  function useAuthState() {
258
- const { authClient, initialAuthenticated = false } = useAuthContext();
259
- const { data: session, isPending } = authClient.useSession();
260
- const useInitial = !React.useSyncExternalStore(subscribeToHydration, () => true, () => false) || isPending;
261
- return {
262
- isAuthenticated: useInitial ? initialAuthenticated : !!session,
263
- isLoading: useInitial && !initialAuthenticated
264
- };
288
+ const $ = c(8);
289
+ const { authClient, initialAuthenticated: t0 } = useAuthContext();
290
+ const initialAuthenticated = t0 === void 0 ? false : t0;
291
+ const hydrated = React.useSyncExternalStore(subscribeToHydration, _temp2, _temp3);
292
+ let t1;
293
+ if ($[0] !== hydrated || $[1] !== initialAuthenticated) {
294
+ t1 = initialAuthenticated || hydrated && hasStoredAuthCookie();
295
+ $[0] = hydrated;
296
+ $[1] = initialAuthenticated;
297
+ $[2] = t1;
298
+ } else t1 = $[2];
299
+ const tracksSession = t1;
300
+ const { data: session, isPending } = useSessionState(authClient, tracksSession);
301
+ if (!tracksSession) {
302
+ const t2 = !hydrated;
303
+ let t3;
304
+ if ($[3] !== t2) {
305
+ t3 = {
306
+ isAuthenticated: false,
307
+ isLoading: t2
308
+ };
309
+ $[3] = t2;
310
+ $[4] = t3;
311
+ } else t3 = $[4];
312
+ return t3;
313
+ }
314
+ const useInitial = !hydrated || isPending;
315
+ const t2 = useInitial ? initialAuthenticated : !!session;
316
+ const t3 = useInitial && !initialAuthenticated;
317
+ let t4;
318
+ if ($[5] !== t2 || $[6] !== t3) {
319
+ t4 = {
320
+ isAuthenticated: t2,
321
+ isLoading: t3
322
+ };
323
+ $[5] = t2;
324
+ $[6] = t3;
325
+ $[7] = t4;
326
+ } else t4 = $[7];
327
+ return t4;
328
+ }
329
+ function _temp3() {
330
+ return false;
331
+ }
332
+ function _temp2() {
333
+ return true;
265
334
  }
266
335
  function useIsAuthenticated() {
267
- const $ = c(1);
268
- if ($[0] !== "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525") {
269
- for (let $i = 0; $i < 1; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
270
- $[0] = "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525";
271
- }
272
336
  const { isAuthenticated } = useAuthState();
273
337
  return isAuthenticated;
274
338
  }
275
339
  function useSignInRedirect(callbackHref) {
276
- const $ = c(4);
277
- if ($[0] !== "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525") {
278
- for (let $i = 0; $i < 4; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
279
- $[0] = "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525";
280
- }
340
+ const $ = c(3);
281
341
  const { authenticationUrl } = useAuthContext();
282
342
  let t0;
283
- if ($[1] !== authenticationUrl || $[2] !== callbackHref) {
343
+ if ($[0] !== authenticationUrl || $[1] !== callbackHref) {
284
344
  t0 = () => {
285
345
  if (typeof window === "undefined") return;
286
346
  const href = typeof callbackHref === "function" ? callbackHref() : callbackHref;
287
347
  const callback = encodeURIComponent(href ?? window.location.href);
288
348
  window.location.href = `${authenticationUrl}/studio-authorize?callback=${callback}`;
289
349
  };
290
- $[1] = authenticationUrl;
291
- $[2] = callbackHref;
292
- $[3] = t0;
293
- } else t0 = $[3];
350
+ $[0] = authenticationUrl;
351
+ $[1] = callbackHref;
352
+ $[2] = t0;
353
+ } else t0 = $[2];
294
354
  return t0;
295
355
  }
296
356
  /**
297
357
  * Registers sign-out and manage-account actions in the command palette.
298
358
  */
299
359
  function useAuthActions() {
300
- const $ = c(5);
301
- if ($[0] !== "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525") {
302
- for (let $i = 0; $i < 5; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
303
- $[0] = "2870dba5d074cbe2d9a238f9ae39bb51493bf31c0dd30caa79404003309e1525";
304
- }
360
+ const $ = c(4);
305
361
  const { authClient, authenticationUrl } = useAuthContext();
306
362
  let t0;
307
363
  let t1;
308
- if ($[1] !== authClient || $[2] !== authenticationUrl) {
364
+ if ($[0] !== authClient || $[1] !== authenticationUrl) {
309
365
  t0 = () => {
310
366
  actionsStore.send({
311
367
  type: "registerManyActions",
@@ -318,7 +374,7 @@ function useAuthActions() {
318
374
  "User settings"
319
375
  ],
320
376
  groupLabel: "Studio",
321
- checkIfAvailable: _temp,
377
+ checkIfAvailable: _temp4,
322
378
  execute: () => {
323
379
  window.open(`${authenticationUrl}/profile`, "_blank");
324
380
  }
@@ -327,35 +383,35 @@ function useAuthActions() {
327
383
  label: "Log out",
328
384
  aliases: ["Sign out", "Logout"],
329
385
  groupLabel: "Studio",
330
- checkIfAvailable: _temp2,
386
+ checkIfAvailable: _temp5,
331
387
  execute: () => authClient.signOut()
332
388
  }]
333
389
  });
334
- return _temp3;
390
+ return _temp6;
335
391
  };
336
392
  t1 = [authClient, authenticationUrl];
337
- $[1] = authClient;
338
- $[2] = authenticationUrl;
339
- $[3] = t0;
340
- $[4] = t1;
393
+ $[0] = authClient;
394
+ $[1] = authenticationUrl;
395
+ $[2] = t0;
396
+ $[3] = t1;
341
397
  } else {
342
- t0 = $[3];
343
- t1 = $[4];
398
+ t0 = $[2];
399
+ t1 = $[3];
344
400
  }
345
401
  React.useEffect(t0, t1);
346
402
  }
347
- function _temp3() {
403
+ function _temp6() {
348
404
  actionsStore.send({
349
405
  type: "unregisterManyActions",
350
406
  ids: ["manage-account", "log-out"]
351
407
  });
352
408
  }
353
- function _temp2() {
409
+ function _temp5() {
354
410
  return true;
355
411
  }
356
- function _temp() {
412
+ function _temp4() {
357
413
  return true;
358
414
  }
359
415
 
360
416
  //#endregion
361
- export { AuthContext, createCamoxAuthClient, getAuthCookieHeader, getAuthRequestCredentials, useAuthActions, useAuthContext, useAuthState, useIsAuthenticated, useProcessOtt, useProjectSlug, useSignInRedirect };
417
+ export { AuthContext, createCamoxAuthClient, getAuthCookieHeader, getAuthRequestCredentials, useAuthActions, useAuthContext, useAuthState, useIsAuthenticated, useProcessOtt, useProjectUuid, useSignInRedirect };
@@ -0,0 +1,23 @@
1
+ import { queryKeys } from "@camox/api-contract/query-keys";
2
+
3
+ //#region src/lib/collection-cache.ts
4
+ /**
5
+ * Refreshes a collection's records in every placement, in every scope, as the API's broadcast
6
+ * after a record edit does, so the edit shows even without a realtime connection.
7
+ */
8
+ function invalidateCollectionRecordViews(studioCache, projectUuid, collectionId) {
9
+ return studioCache.receive({
10
+ type: "invalidate",
11
+ draftId: null,
12
+ targets: [
13
+ queryKeys.collections.records(projectUuid, collectionId),
14
+ ["camox", "blocks"],
15
+ queryKeys.pages.getByPathAll,
16
+ queryKeys.pages.list,
17
+ queryKeys.layouts.all
18
+ ]
19
+ }, 0);
20
+ }
21
+
22
+ //#endregion
23
+ export { invalidateCollectionRecordViews };
@@ -0,0 +1,4 @@
1
+ import "../features/routes/pageRuntime.js";
2
+ import "react";
3
+ import { EndedDraft } from "@camox/api-contract/drafts";
4
+ import { QueryClient } from "@tanstack/react-query";
@@ -0,0 +1,222 @@
1
+ import { UNNAMED_DEFAULT_LOCALE, localeHeaders } from "./locale-path.js";
2
+ import { getApiClient } from "./api-client.js";
3
+ import { c } from "react/compiler-runtime";
4
+ import * as React from "react";
5
+ import { generateUuidv7 } from "@camox/api-contract/ids";
6
+ import { DEVELOPMENT_DRAFT, DRAFT_CREATE_HEADER, DRAFT_HEADER, DRAFT_SEARCH_PARAM } from "@camox/api-contract/drafts";
7
+ import { LIVE_KEY_SCOPE, scopeOfKey } from "@camox/api-contract/query-keys";
8
+
9
+ //#region src/lib/draft-scope.ts
10
+ /** The draft a URL names, if any. */
11
+ function draftNamedBy(href) {
12
+ return new URL(href, "http://camox.local").searchParams.get(DRAFT_SEARCH_PARAM) || null;
13
+ }
14
+ /** The URL without the draft param. */
15
+ function withoutDraft(href) {
16
+ const url = new URL(href);
17
+ url.searchParams.delete(DRAFT_SEARCH_PARAM);
18
+ return url.href;
19
+ }
20
+ function buildIsDevelopmentMode() {
21
+ return typeof __CAMOX_DEVELOPMENT_DRAFT__ !== "undefined" && __CAMOX_DEVELOPMENT_DRAFT__;
22
+ }
23
+ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevelopmentMode(), loadDevelopmentDraftId = async (projectId) => (await getApiClient().drafts.get({ projectId }))?.id }) {
24
+ let current = developmentMode ? DEVELOPMENT_DRAFT : null;
25
+ let locale = UNNAMED_DEFAULT_LOCALE;
26
+ let pending = null;
27
+ let developmentDraftId;
28
+ let adoptedRender = false;
29
+ const listeners = /* @__PURE__ */ new Set();
30
+ const noticeListeners = /* @__PURE__ */ new Set();
31
+ const pendingNotices = [];
32
+ const draftOfRender = (rendered) => {
33
+ if (!developmentMode) return rendered.draftId ?? null;
34
+ return rendered.refusedDraft ? null : DEVELOPMENT_DRAFT;
35
+ };
36
+ const notify = (move) => {
37
+ for (const listener of listeners) listener({
38
+ draftId: current,
39
+ move
40
+ });
41
+ };
42
+ const report = (notice) => {
43
+ if (noticeListeners.size === 0) return void pendingNotices.push(notice);
44
+ for (const listener of noticeListeners) listener(notice);
45
+ };
46
+ const replaceUrl = (draftId) => {
47
+ if (!browser) return;
48
+ const url = new URL(browser.location.href);
49
+ if (draftId === url.searchParams.get(DRAFT_SEARCH_PARAM)) return;
50
+ if (draftId) url.searchParams.set(DRAFT_SEARCH_PARAM, draftId);
51
+ else url.searchParams.delete(DRAFT_SEARCH_PARAM);
52
+ browser.history.replaceState(browser.history.state, "", url.pathname + url.search + url.hash);
53
+ };
54
+ const enterStartedDraft = (draftId) => {
55
+ pending = null;
56
+ current = draftId;
57
+ replaceUrl(draftId);
58
+ for (const query of queryClient.getQueryCache().findAll({ queryKey: ["camox"] })) {
59
+ if (scopeOfKey(query.queryKey) !== LIVE_KEY_SCOPE || query.state.data === void 0) continue;
60
+ queryClient.setQueryData([...query.queryKey.slice(0, -1), draftId], query.state.data);
61
+ }
62
+ queryClient.invalidateQueries({
63
+ queryKey: ["camox"],
64
+ predicate: (query) => scopeOfKey(query.queryKey) !== LIVE_KEY_SCOPE
65
+ });
66
+ notify("started");
67
+ };
68
+ const headersFor = (contentWrite) => {
69
+ const noop = () => {};
70
+ const inLocale = localeHeaders(locale);
71
+ if (current) return {
72
+ headers: {
73
+ [DRAFT_HEADER]: current,
74
+ ...inLocale
75
+ },
76
+ settle: noop
77
+ };
78
+ if (!contentWrite || developmentMode) return {
79
+ headers: inLocale,
80
+ settle: noop
81
+ };
82
+ pending ??= {
83
+ id: generateUuidv7(),
84
+ inFlight: 0
85
+ };
86
+ const started = pending;
87
+ started.inFlight += 1;
88
+ return {
89
+ headers: {
90
+ [DRAFT_HEADER]: started.id,
91
+ [DRAFT_CREATE_HEADER]: "1",
92
+ ...inLocale
93
+ },
94
+ settle: (ok) => {
95
+ if (pending !== started) return;
96
+ started.inFlight -= 1;
97
+ if (ok) return enterStartedDraft(started.id);
98
+ if (started.inFlight === 0) pending = null;
99
+ }
100
+ };
101
+ };
102
+ return {
103
+ current: () => current,
104
+ locale: () => locale,
105
+ developmentMode,
106
+ subscribe(listener) {
107
+ listeners.add(listener);
108
+ return () => listeners.delete(listener);
109
+ },
110
+ requestHeaders: headersFor,
111
+ enterStarted(draftId) {
112
+ if (current !== null) return false;
113
+ enterStartedDraft(draftId);
114
+ return true;
115
+ },
116
+ hrefFor(to, { from, draft } = {}) {
117
+ if (developmentMode) return to;
118
+ const base = new URL(from ?? browser?.location.href ?? "http://camox.local");
119
+ const target = new URL(to, base);
120
+ if (target.origin !== base.origin) return to;
121
+ if (draft === void 0 && target.searchParams.has(DRAFT_SEARCH_PARAM)) return to;
122
+ const next = draft === void 0 ? current : draft;
123
+ if (next) target.searchParams.set(DRAFT_SEARCH_PARAM, next);
124
+ else target.searchParams.delete(DRAFT_SEARCH_PARAM);
125
+ if (target.href === new URL(to, base).href) return to;
126
+ return /^[a-z][a-z\d+.-]*:/i.test(to) || to.startsWith("//") ? target.href : `${target.pathname}${target.search}${target.hash}`;
127
+ },
128
+ adopt(rendered) {
129
+ if (rendered.locale) locale = rendered.locale;
130
+ if (rendered.refusedDraft) {
131
+ replaceUrl(null);
132
+ if (rendered.refusedDraft.notice) report(rendered.refusedDraft.notice);
133
+ }
134
+ const next = draftOfRender(rendered);
135
+ if (next !== null) pending = null;
136
+ const firstRender = !adoptedRender;
137
+ adoptedRender = true;
138
+ if (next === current) return;
139
+ current = next;
140
+ if (!firstRender) {
141
+ const entered = next ?? LIVE_KEY_SCOPE;
142
+ queryClient.invalidateQueries({
143
+ queryKey: ["camox"],
144
+ predicate: (query) => scopeOfKey(query.queryKey) === entered,
145
+ refetchType: "none"
146
+ });
147
+ }
148
+ notify("adopted");
149
+ },
150
+ leave(ended, { notice = false } = {}) {
151
+ queryClient.invalidateQueries({ queryKey: ["camox"] });
152
+ if (developmentMode) return false;
153
+ pending = null;
154
+ current = null;
155
+ replaceUrl(null);
156
+ if (notice && ended) report({
157
+ reason: "ended",
158
+ ...ended
159
+ });
160
+ notify("left");
161
+ return true;
162
+ },
163
+ onNotice(listener) {
164
+ noticeListeners.add(listener);
165
+ for (const notice of pendingNotices.splice(0)) listener(notice);
166
+ return () => noticeListeners.delete(listener);
167
+ },
168
+ async keyScopeOfDraft(draftId, projectId) {
169
+ if (current !== DEVELOPMENT_DRAFT) return draftId;
170
+ developmentDraftId ??= loadDevelopmentDraftId(projectId).catch(() => {
171
+ developmentDraftId = void 0;
172
+ });
173
+ return draftId === await developmentDraftId ? DEVELOPMENT_DRAFT : draftId;
174
+ }
175
+ };
176
+ }
177
+ const DraftScopeContext = React.createContext(null);
178
+ /**
179
+ * The draft scope the studio is in, for handlers and effects. Render code reads the draft it
180
+ * views from `useCurrentDraftId`: the scope object never changes, so a memoized render reading
181
+ * `current()` from it would keep showing the draft of its first render.
182
+ */
183
+ function useDraftScope() {
184
+ const scope = React.useContext(DraftScopeContext);
185
+ if (!scope) throw new Error("useDraftScope must be used inside a DraftScopeContext provider");
186
+ return scope;
187
+ }
188
+ const noScope = () => null;
189
+ const noSubscription = () => () => {};
190
+ /** The draft the studio is in, or null for Live. The caller re-renders after every move. */
191
+ function useCurrentDraftId() {
192
+ const scope = useDraftScope();
193
+ return React.useSyncExternalStore(scope.subscribe, scope.current, scope.current);
194
+ }
195
+ /** The draft scope and the draft it views, outside the studio too, where there is none. */
196
+ function useOptionalDraftScope() {
197
+ const $ = c(3);
198
+ const scope = React.useContext(DraftScopeContext);
199
+ const current = scope?.current ?? noScope;
200
+ const draftId = React.useSyncExternalStore(scope?.subscribe ?? noSubscription, current, current);
201
+ let t0;
202
+ if ($[0] !== draftId || $[1] !== scope) {
203
+ t0 = {
204
+ scope,
205
+ draftId
206
+ };
207
+ $[0] = draftId;
208
+ $[1] = scope;
209
+ $[2] = t0;
210
+ } else t0 = $[2];
211
+ return t0;
212
+ }
213
+ /**
214
+ * Follows the draft a browser URL names, for a studio mounted in a host application, whose
215
+ * navigation renders nothing the scope could adopt.
216
+ */
217
+ function followUrl(scope, href) {
218
+ scope.adopt({ draftId: draftNamedBy(href) ?? void 0 });
219
+ }
220
+
221
+ //#endregion
222
+ export { DraftScopeContext, createDraftScope, draftNamedBy, followUrl, useCurrentDraftId, useDraftScope, useOptionalDraftScope, withoutDraft };