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,6 +1,4 @@
1
1
  import { CamoxApp } from "../../core/createApp.js";
2
-
3
2
  //#region src/features/runtime/pageClient.d.ts
4
- declare function hydratePageWithApp(camoxApp: CamoxApp): void;
5
- //#endregion
6
- export { hydratePageWithApp };
3
+ export declare function hydratePageWithApp(camoxApp: CamoxApp): Promise<void>;
4
+ //#endregion
@@ -1,17 +1,32 @@
1
+ import { createDraftScope } from "../../lib/draft-scope.js";
2
+ import { restoreArtifactSources } from "./artifactSources.js";
3
+ import { getPageBlockTypes } from "./pageBlockTypes.js";
4
+ import { loadRuntimeChrome } from "./runtimeChromeLoader.js";
1
5
  import { PageApp } from "./pageApp.js";
2
6
  import { readHydrationData } from "./hydrationData.js";
3
- import { QueryClient } from "@tanstack/react-query";
4
7
  import { jsx } from "react/jsx-runtime";
8
+ import { QueryClient } from "@tanstack/react-query";
5
9
  import { hydrateRoot } from "react-dom/client";
6
10
 
7
11
  //#region src/features/runtime/pageClient.tsx
8
- function hydratePageWithApp(camoxApp) {
12
+ async function hydratePageWithApp(camoxApp) {
9
13
  const root = document.getElementById("root");
10
14
  if (!root) throw new Error("Camox runtime root element was not found.");
11
15
  const queryClient = new QueryClient();
16
+ const hydrationData = readHydrationData();
17
+ const input = {
18
+ ...hydrationData,
19
+ dehydratedState: restoreArtifactSources(hydrationData.dehydratedState, root)
20
+ };
21
+ await Promise.all([camoxApp.loadBlocks(getPageBlockTypes(input.dehydratedState)).catch((error) => console.error("Camox: a block of this page failed to load.", error)), input.presentation === "studio" ? loadRuntimeChrome() : void 0]);
22
+ const draftScope = createDraftScope({
23
+ queryClient,
24
+ browser: window
25
+ });
12
26
  hydrateRoot(root, /* @__PURE__ */ jsx(PageApp, {
13
27
  camoxApp,
14
- input: readHydrationData(),
28
+ draftScope,
29
+ input,
15
30
  queryClient
16
31
  }));
17
32
  }
@@ -1,61 +1,156 @@
1
+ import { DraftScopeContext, draftNamedBy } from "../../lib/draft-scope.js";
2
+ import { PageAlternatesContext, ViewLocaleContext } from "../../lib/view-locale-context.js";
1
3
  import { NavigationProvider } from "../navigation/navigation.js";
4
+ import { fetchRuntimeJson, getNavigationTarget } from "./navigationTarget.js";
5
+ import { reads } from "../../lib/studio-reads.js";
6
+ import { createPrefetchCache, listenForLinkIntent } from "./linkPrefetch.js";
7
+ import { PageViewportContext } from "./pageViewport.js";
8
+ import { sendPageView } from "./analytics.js";
9
+ import { getPageBlockTypes } from "./pageBlockTypes.js";
2
10
  import { createPageHeadInput } from "./runtime.js";
11
+ import { createRouteAnnouncer, focusNewPage } from "./navigationAccessibility.js";
3
12
  import { createNavigationRequestTracker } from "./navigationRequest.js";
4
- import { getNavigationTarget, runtimePath } from "./navigationTarget.js";
5
- import { hydrate } from "@tanstack/react-query";
13
+ import { createScrollRestoration } from "./scrollRestoration.js";
14
+ import { c } from "react/compiler-runtime";
6
15
  import * as React from "react";
7
16
  import { jsx } from "react/jsx-runtime";
17
+ import { hydrate } from "@tanstack/react-query";
8
18
  import { createHead, renderDOMHead } from "@unhead/react/client";
9
19
 
10
20
  //#region src/features/runtime/pageNavigation.tsx
11
21
  function preserveStableLayoutBlockCaches(dehydratedState, current, next) {
12
- if (!current || !next || current.id !== next.id || current.layoutId !== next.layoutId || current.version !== next.version) return dehydratedState;
22
+ if (!current || !next || current.layoutId !== next.layoutId || current.version !== next.version) return dehydratedState;
13
23
  if (!dehydratedState || typeof dehydratedState !== "object" || !("queries" in dehydratedState) || !Array.isArray(dehydratedState.queries)) return dehydratedState;
14
24
  const ids = new Set(current.blockIds);
15
25
  return {
16
26
  ...dehydratedState,
17
27
  queries: dehydratedState.queries.filter((query) => {
18
- const key = query.queryKey;
19
- return !(key?.[0] === "camox" && key[1] === "blocks" && key[2] === "get" && typeof key[3] === "number" && ids.has(key[3]));
28
+ const blockId = query.queryKey && reads.blockBundle.paramsOf(query.queryKey);
29
+ return !(blockId && ids.has(blockId));
20
30
  })
21
31
  };
22
32
  }
23
- function PageNavigationProvider({ children, initialInput, queryClient }) {
24
- const [input, setInput] = React.useState(initialInput);
33
+ function sameLocale(a, b) {
34
+ return a.tag === b.tag && a.isDefault === b.isDefault;
35
+ }
36
+ /**
37
+ * `value`, kept while it says the same: each render's response is new JSON, which would otherwise
38
+ * give every consumer a new value.
39
+ */
40
+ function useSameJson(value) {
41
+ const $ = c(4);
42
+ let t0;
43
+ if ($[0] !== value) {
44
+ t0 = JSON.stringify(value);
45
+ $[0] = value;
46
+ $[1] = t0;
47
+ } else t0 = $[1];
48
+ const json = t0;
49
+ let t1;
50
+ if ($[2] !== json) {
51
+ t1 = JSON.parse(json);
52
+ $[2] = json;
53
+ $[3] = t1;
54
+ } else t1 = $[3];
55
+ return t1;
56
+ }
57
+ function prefetchKey(pathname, draft) {
58
+ return JSON.stringify({
59
+ pathname,
60
+ draft
61
+ });
62
+ }
63
+ function PageNavigationProvider({ camoxApp, children, initialInput, queryClient }) {
64
+ const draftScope = React.useContext(DraftScopeContext);
65
+ if (!draftScope) throw new Error("PageNavigationProvider needs a DraftScopeContext provider");
66
+ const [{ input, source, generation }, setLocation] = React.useState(() => {
67
+ draftScope.adopt(initialInput);
68
+ return {
69
+ input: initialInput,
70
+ generation: 0
71
+ };
72
+ });
25
73
  const current = React.useRef(initialInput);
26
74
  const [requests] = React.useState(createNavigationRequestTracker);
75
+ const ownsWindow = initialInput.presentation !== "studio";
76
+ const scroll = React.useRef(null);
77
+ const restoration = React.useCallback(() => scroll.current ??= createScrollRestoration(window), []);
78
+ const pendingScroll = React.useRef(null);
79
+ const takeScroll = (href) => {
80
+ const pending = pendingScroll.current;
81
+ if (pending?.href !== href) return null;
82
+ pendingScroll.current = null;
83
+ return pending.intent;
84
+ };
85
+ const position = React.useCallback((viewport, intent, href) => {
86
+ const fragment = restoration().apply(viewport, intent, new URL(href).hash);
87
+ if (intent !== "resume" && (fragment || intent !== "fragment")) focusNewPage(viewport.document, fragment);
88
+ }, [restoration]);
89
+ const pendingAnnouncement = React.useRef(null);
90
+ const announcer = React.useRef(null);
91
+ const loadPage = React.useCallback(async (pathname, draft, signal) => {
92
+ const response = await fetchRuntimeJson(draftScope, "/_camox/data", initialInput.runtimeBasePath, { path: pathname }, draft, signal);
93
+ if (!response.ok) throw new Error(`Navigation failed: ${response.status}`);
94
+ const next = await response.json();
95
+ if (next.pathname !== pathname || !next.dehydratedState) throw new Error("Invalid navigation response");
96
+ await camoxApp.loadBlocks(getPageBlockTypes(next.dehydratedState));
97
+ return next;
98
+ }, [
99
+ camoxApp,
100
+ draftScope,
101
+ initialInput.runtimeBasePath
102
+ ]);
103
+ const [prefetched] = React.useState(() => createPrefetchCache());
27
104
  const headManager = React.useRef(null);
28
- const navigate = React.useCallback(async ({ to, replace, pop = false }) => {
105
+ const { analytics } = initialInput;
106
+ const navigate = React.useCallback(async ({ to, replace, source, draft, pop = false, refresh = false }) => {
29
107
  const request = requests.begin();
30
- const target = getNavigationTarget(to, window.location.href, initialInput.runtimeBasePath);
108
+ const href = pop ? to : draftScope.hrefFor(to, {
109
+ from: window.location.href,
110
+ draft
111
+ });
112
+ const target = getNavigationTarget(href, window.location.href, initialInput.runtimeBasePath);
31
113
  if (!target) {
32
114
  if (replace) window.location.replace(to);
33
115
  else window.location.assign(to);
34
116
  return;
35
117
  }
118
+ if (pop) restoration().save();
119
+ if (!pop && !refresh && target.url.href === current.current.href) {
120
+ const viewport = restoration().viewport();
121
+ if (target.url.hash && viewport) position(viewport, "fragment", target.url.href);
122
+ return;
123
+ }
36
124
  try {
37
125
  let next = current.current;
38
- if (target.pathname !== next.pathname || pop) {
39
- const url = new URL(runtimePath("/_camox/data", initialInput.runtimeBasePath), window.location.origin);
40
- url.searchParams.set("path", target.pathname);
41
- const response = await fetch(url, {
42
- credentials: "same-origin",
43
- headers: { Accept: "application/json" },
44
- signal: request.signal
45
- });
46
- if (!response.ok) throw new Error(`Navigation failed: ${response.status}`);
47
- next = await response.json();
48
- if (next.pathname !== target.pathname || !next.dehydratedState) throw new Error("Invalid navigation response");
49
- }
126
+ const targetDraft = draftNamedBy(target.url.href);
127
+ const fetched = target.pathname !== next.pathname || refresh || targetDraft !== draftNamedBy(next.href);
128
+ if (fetched) next = await (!refresh && prefetched.take(prefetchKey(target.pathname, targetDraft)) || loadPage(target.pathname, targetDraft, request.signal));
50
129
  if (!request.isCurrent()) return;
51
- hydrate(queryClient, preserveStableLayoutBlockCaches(next.dehydratedState, current.current.layoutIdentity, next.layoutIdentity));
130
+ const switching = (next.draftId ?? null) !== (current.current.draftId ?? null) || !sameLocale(next.locale, current.current.locale);
131
+ const positions = restoration();
132
+ if (!pop) {
133
+ if (replace || refresh) window.history.replaceState(window.history.state, "", target.url.href);
134
+ else {
135
+ positions.save();
136
+ window.history.pushState(positions.stateForNewEntry(), "", target.url.href);
137
+ }
138
+ }
139
+ positions.entered();
140
+ const intent = pop ? "restore" : refresh || replace && !fetched ? null : fetched ? "enter" : "fragment";
141
+ pendingScroll.current = intent && {
142
+ href: window.location.href,
143
+ intent
144
+ };
145
+ pendingAnnouncement.current = fetched && !refresh ? next.pathname : null;
146
+ if (fetched) draftScope.adopt(next);
147
+ hydrate(queryClient, switching ? next.dehydratedState : preserveStableLayoutBlockCaches(next.dehydratedState, current.current.layoutIdentity, next.layoutIdentity));
52
148
  next = {
53
149
  ...next,
54
- href: target.url.href
150
+ href: window.location.href
55
151
  };
152
+ const previous = current.current;
56
153
  current.current = next;
57
- if (!pop) if (replace) window.history.replaceState(null, "", target.url.href);
58
- else window.history.pushState(null, "", target.url.href);
59
154
  if (!headManager.current) {
60
155
  document.querySelectorAll("[data-camox-page-head]").forEach((element) => element.remove());
61
156
  headManager.current = { head: createHead() };
@@ -64,8 +159,13 @@ function PageNavigationProvider({ children, initialInput, queryClient }) {
64
159
  manager.entry?.dispose();
65
160
  manager.entry = manager.head.push(createPageHeadInput(next.head ?? {}));
66
161
  renderDOMHead(manager.head);
67
- React.startTransition(() => setInput(next));
68
- if (!pop && !replace && !target.url.hash) window.scrollTo({ top: 0 });
162
+ if (ownsWindow && analytics && next.pathname !== previous.pathname) sendPageView(analytics, window);
163
+ if (ownsWindow) document.documentElement.lang = next.locale.tag;
164
+ React.startTransition(() => setLocation((location) => ({
165
+ input: next,
166
+ source: pop ? void 0 : source,
167
+ generation: location.generation + (switching ? 1 : 0)
168
+ })));
69
169
  } catch {
70
170
  if (!request.isCurrent()) return;
71
171
  if (pop) window.location.reload();
@@ -73,10 +173,117 @@ function PageNavigationProvider({ children, initialInput, queryClient }) {
73
173
  else window.location.assign(target.url.href);
74
174
  }
75
175
  }, [
176
+ analytics,
177
+ draftScope,
76
178
  initialInput.runtimeBasePath,
179
+ loadPage,
180
+ ownsWindow,
181
+ position,
182
+ prefetched,
77
183
  queryClient,
78
- requests
184
+ requests,
185
+ restoration
186
+ ]);
187
+ const prefetchLink = React.useCallback((anchor) => {
188
+ if (anchor.hasAttribute("download") || anchor.target && anchor.target !== "_self") return;
189
+ const href = draftScope.hrefFor(anchor.href, { from: window.location.href });
190
+ const target = getNavigationTarget(href, window.location.href, initialInput.runtimeBasePath);
191
+ if (!target || target.pathname === current.current.pathname) return;
192
+ const draft = draftNamedBy(target.url.href);
193
+ prefetched.prefetch(prefetchKey(target.pathname, draft), () => loadPage(target.pathname, draft, new AbortController().signal));
194
+ }, [
195
+ draftScope,
196
+ initialInput.runtimeBasePath,
197
+ loadPage,
198
+ prefetched
199
+ ]);
200
+ const pageViewport = React.useMemo(() => ({
201
+ opened(viewport, href) {
202
+ restoration().apply(viewport, takeScroll(href) ?? "restore", new URL(href).hash);
203
+ },
204
+ placed(href) {
205
+ takeScroll(href);
206
+ },
207
+ attach(viewport) {
208
+ restoration().setViewport(viewport);
209
+ return () => {
210
+ const positions = restoration();
211
+ if (positions.viewport() === viewport) positions.setViewport(ownsWindow ? window : null);
212
+ };
213
+ },
214
+ prefetchLink
215
+ }), [
216
+ ownsWindow,
217
+ position,
218
+ prefetchLink,
219
+ restoration
79
220
  ]);
221
+ React.useEffect(() => {
222
+ const positions = restoration();
223
+ if (ownsWindow) {
224
+ positions.setViewport(window);
225
+ positions.apply(window, "resume", window.location.hash);
226
+ }
227
+ announcer.current = createRouteAnnouncer(document);
228
+ return () => {
229
+ announcer.current?.dispose();
230
+ announcer.current = null;
231
+ scroll.current?.dispose();
232
+ scroll.current = null;
233
+ };
234
+ }, [ownsWindow, restoration]);
235
+ const firstPageView = React.useRef(false);
236
+ React.useEffect(() => {
237
+ if (!ownsWindow || !analytics || firstPageView.current) return;
238
+ firstPageView.current = true;
239
+ sendPageView(analytics, window);
240
+ }, [analytics, ownsWindow]);
241
+ React.useEffect(() => {
242
+ if (!ownsWindow) return;
243
+ return listenForLinkIntent(document, prefetchLink);
244
+ }, [ownsWindow, prefetchLink]);
245
+ React.useEffect(() => {
246
+ const unsubscribe = draftScope.subscribe(() => prefetched.clear());
247
+ return () => {
248
+ unsubscribe();
249
+ prefetched.clear();
250
+ };
251
+ }, [draftScope, prefetched]);
252
+ React.useLayoutEffect(() => {
253
+ const intent = takeScroll(input.href);
254
+ const viewport = scroll.current?.viewport();
255
+ if (intent && viewport) position(viewport, intent, input.href);
256
+ const announced = pendingAnnouncement.current;
257
+ pendingAnnouncement.current = null;
258
+ if (announced) {
259
+ const viewport = scroll.current?.viewport();
260
+ announcer.current?.announce(viewport?.document ?? document, announced);
261
+ }
262
+ }, [input]);
263
+ React.useEffect(() => {
264
+ const adoptBrowserUrl = () => {
265
+ const url = new URL(window.location.href);
266
+ if (url.href === current.current.href || url.pathname !== new URL(current.current.href).pathname) return;
267
+ const next = {
268
+ ...current.current,
269
+ href: url.href,
270
+ draftId: draftScope.current() ?? void 0
271
+ };
272
+ current.current = next;
273
+ setLocation((location) => ({
274
+ ...location,
275
+ input: next
276
+ }));
277
+ };
278
+ adoptBrowserUrl();
279
+ return draftScope.subscribe(({ move }) => {
280
+ if (move === "started") return adoptBrowserUrl();
281
+ if (move === "left") navigate({
282
+ to: window.location.href,
283
+ refresh: true
284
+ });
285
+ });
286
+ }, [draftScope, navigate]);
80
287
  React.useEffect(() => {
81
288
  const onClick = (event) => {
82
289
  if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;
@@ -102,16 +309,31 @@ function PageNavigationProvider({ children, initialInput, queryClient }) {
102
309
  initialInput.runtimeBasePath,
103
310
  requests
104
311
  ]);
105
- const url_0 = new URL(input.href);
312
+ const url = new URL(input.href);
313
+ const viewLocale = useSameJson({
314
+ locale: input.locale,
315
+ locales: input.locales
316
+ });
317
+ const alternates = useSameJson(input.alternates ?? null);
106
318
  return /* @__PURE__ */ jsx(NavigationProvider, {
107
319
  location: {
108
320
  href: input.href,
109
321
  pathname: input.pathname,
110
- hash: url_0.hash,
111
- search: url_0.search
322
+ hash: url.hash,
323
+ search: url.search,
324
+ source
112
325
  },
113
326
  navigate,
114
- children: children(input)
327
+ children: /* @__PURE__ */ jsx(ViewLocaleContext, {
328
+ value: viewLocale,
329
+ children: /* @__PURE__ */ jsx(PageAlternatesContext, {
330
+ value: alternates,
331
+ children: /* @__PURE__ */ jsx(PageViewportContext, {
332
+ value: pageViewport,
333
+ children: /* @__PURE__ */ jsx(React.Fragment, { children: children(input) }, generation)
334
+ })
335
+ })
336
+ })
115
337
  });
116
338
  }
117
339
 
@@ -1,9 +1,7 @@
1
1
  import { CamoxApp } from "../../core/createApp.js";
2
2
  import { PageRenderInput } from "./runtime.js";
3
-
4
3
  //#region src/features/runtime/pageServer.d.ts
5
- declare function renderPageWithApp(input: PageRenderInput & {
4
+ export declare function renderPageWithApp(input: PageRenderInput & {
6
5
  camoxApp: CamoxApp;
7
6
  }): Promise<string>;
8
- //#endregion
9
- export { renderPageWithApp };
7
+ //#endregion
@@ -1,17 +1,21 @@
1
+ import { createDraftScope } from "../../lib/draft-scope.js";
1
2
  import { prefetchIcons } from "../../core/lib/icons.js";
3
+ import { loadRuntimeChrome } from "./runtimeChromeLoader.js";
2
4
  import { PageApp } from "./pageApp.js";
3
- import { QueryClient, dehydrate, hydrate } from "@tanstack/react-query";
4
5
  import { jsx } from "react/jsx-runtime";
6
+ import { QueryClient, dehydrate, hydrate } from "@tanstack/react-query";
5
7
  import { renderToString } from "react-dom/server";
6
8
 
7
9
  //#region src/features/runtime/pageServer.tsx
8
10
  async function renderPageWithApp(input) {
9
11
  const queryClient = new QueryClient();
10
12
  hydrate(queryClient, input.dehydratedState);
11
- await prefetchIcons(queryClient, input.dehydratedState, input.camoxApp.getSerializableDefinitions());
13
+ await Promise.all([prefetchIcons(queryClient, input.dehydratedState, input.camoxApp.getBlocks().map(({ _internal }) => [_internal.contentSchema, _internal.settingsSchema])), input.presentation === "studio" ? loadRuntimeChrome() : void 0]);
12
14
  Object.assign(input.dehydratedState, dehydrate(queryClient));
15
+ const draftScope = createDraftScope({ queryClient });
13
16
  return renderToString(/* @__PURE__ */ jsx(PageApp, {
14
17
  camoxApp: input.camoxApp,
18
+ draftScope,
15
19
  input,
16
20
  queryClient
17
21
  }));
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/features/runtime/pageViewport.ts
4
+ const PageViewportContext = React.createContext(null);
5
+
6
+ //#endregion
7
+ export { PageViewportContext };
@@ -1,67 +1,102 @@
1
- import { CamoxApp } from "../../core/createApp.js";
2
1
  import { CamoxDocument } from "../../core/defineDocument.js";
3
- import { createServerApiClient } from "../routes/pageRuntime.js";
2
+ import { AnyLayoutLoaderResult } from "../../core/createLayout.js";
3
+ import { CamoxApp } from "../../core/createApp.js";
4
+ import { AlternatePath, LocaleView } from "../../lib/locale-path.js";
5
+ import { AnalyticsProviders } from "./analytics.js";
6
+ import { RuntimeOwnedRouteKind } from "./runtimeRoutes.js";
4
7
  import { StudioRenderInput } from "./studioApp.js";
8
+ import { DraftRead, MemberProject, createServerApiClient } from "../routes/pageRuntime.js";
5
9
  import { UseHeadInput } from "unhead/types";
6
-
7
10
  //#region src/features/runtime/runtime.d.ts
8
- type RuntimeRouteKind = "data" | "health" | "og" | "page" | "registry" | "sitemap" | "studio" | "studio-content" | "studio-nested";
9
- interface RuntimeRouteMatch {
11
+ export type RuntimeRouteKind = RuntimeOwnedRouteKind | "canvas" | "page" | "studio" | "studio-content" | "studio-nested";
12
+ export interface RuntimeRouteMatch {
10
13
  kind: RuntimeRouteKind;
11
14
  pathname: string;
12
15
  }
13
- interface LayoutIdentity {
14
- blockIds: number[];
15
- id: number;
16
+ export interface LayoutIdentity {
17
+ blockIds: string[];
16
18
  layoutId: string;
17
19
  version: string;
18
20
  }
19
- interface PageRenderInput {
20
- /** Authenticate before looking up a page that may exist only in draft. */
21
+ export interface PageRenderInput extends DraftRead {
22
+ /**
23
+ * The page in every locale it exists in, the rendered one included, which the alternates hook
24
+ * returns. Left out where the render shows no page.
25
+ */
26
+ alternates?: AlternatePath[];
27
+ /**
28
+ * The analytics providers whose scripts the server added, so the page client sends them page
29
+ * views. Only a visitor's Live page carries them.
30
+ */
31
+ analytics?: AnalyticsProviders;
32
+ /** Authenticate before rendering, to show the Studio around the page. */
21
33
  previewHandoff?: boolean;
22
34
  previewDocument?: string;
23
35
  routeKind?: "studio" | "studio-content" | "studio-nested";
24
- project?: Awaited<ReturnType<ReturnType<typeof createServerApiClient>["projects"]["getBySlug"]>>;
36
+ /**
37
+ * A location only the Canvas shows, instead of a Page: the Canvas
38
+ * with nothing selected, or with a block of the Block Catalog selected.
39
+ */
40
+ canvasOnly?: {
41
+ blockId?: string;
42
+ };
43
+ project?: MemberProject;
25
44
  presentation?: "public" | "studio";
26
45
  derived?: {
27
46
  layoutId: string;
28
- data: unknown;
47
+ result?: AnyLayoutLoaderResult;
29
48
  layout: Awaited<ReturnType<ReturnType<typeof createServerApiClient>["layouts"]["get"]>>["layout"];
30
49
  };
31
50
  apiUrl: string;
32
51
  authenticationUrl: string;
33
52
  dehydratedState: unknown;
34
- environmentName?: string;
35
53
  head: unknown;
36
54
  href: string;
37
55
  layoutIdentity: LayoutIdentity | null;
38
56
  loaderData: unknown;
57
+ /** The locale the render shows, named by the path's prefix. */
58
+ locale: LocaleView;
59
+ /** The locales of the scope the render reads: Live's, or its draft's. */
60
+ locales: LocaleView[];
61
+ /**
62
+ * The full runtime path, with the locale's prefix (`/de/preise`). The locale-relative path is
63
+ * `parseLocalePath(pathname, locales).path`.
64
+ */
39
65
  pathname: string;
40
- projectSlug: string;
66
+ projectUuid: string;
41
67
  runtimeBasePath: string;
42
- source: "live" | "draft";
43
68
  }
44
- interface RuntimeOptions {
69
+ export interface RuntimeOptions {
45
70
  apiUrl?: string;
46
71
  authenticationUrl?: string;
47
- environmentName?: string;
72
+ /** Where the browser loads each block from, so a page can preload the blocks it renders. */
73
+ blockPreloads?: {
74
+ /** Each block's module path, by block id. */
75
+ modulePaths: Record<string, string>;
76
+ /** The built chunks each block module needs, by module path. `null` in dev. */
77
+ chunks: Record<string, string[]> | null;
78
+ };
79
+ /**
80
+ * Dev mode: every render reads the caller's development draft and ignores the URL's draft
81
+ * (ADR 0006).
82
+ */
83
+ developmentDraft?: boolean;
48
84
  pageClientEntryUrl?: string;
49
85
  studioClientEntryUrl?: string;
50
86
  getCamoxApp?: () => Promise<CamoxApp>;
51
87
  getDocument?: () => Promise<CamoxDocument>;
52
- projectSlug?: string;
88
+ projectUuid?: string;
53
89
  renderPage?: (input: PageRenderInput) => Promise<string>;
54
90
  renderStudio?: (input: StudioRenderInput) => Promise<string>;
55
91
  runtimeBasePath?: string;
56
92
  stylesheetUrl?: string;
57
93
  studioStylesheetUrl?: string;
58
94
  }
59
- declare function getRuntimePathname(url: string, runtimeBasePath?: string): string | null;
60
- declare function matchRuntimeRoute(pathname: string): RuntimeRouteMatch;
61
- declare function createPageHeadInput(head: {
95
+ export declare function getRuntimePathname(url: string, runtimeBasePath?: string): string | null;
96
+ export declare function matchRuntimeRoute(pathname: string): RuntimeRouteMatch;
97
+ export declare function createPageHeadInput(head: {
62
98
  meta?: Array<Record<string, string>>;
63
99
  links?: Array<Record<string, string>>;
64
100
  }): UseHeadInput;
65
- declare function handleCamoxRequest(request: Request, options?: RuntimeOptions): Promise<Response | null>;
66
- //#endregion
67
- export { LayoutIdentity, PageRenderInput, RuntimeOptions, RuntimeRouteKind, RuntimeRouteMatch, createPageHeadInput, getRuntimePathname, handleCamoxRequest, matchRuntimeRoute };
101
+ export declare function handleCamoxRequest(request: Request, options?: RuntimeOptions): Promise<Response | null>;
102
+ //#endregion