canopycms 0.0.68-int.98 → 0.1.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 (688) hide show
  1. package/CHANGELOG.md +2131 -0
  2. package/README.md +47 -63
  3. package/dist/ai/generate.d.ts +5 -0
  4. package/dist/ai/generate.js +244 -115
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/json-to-markdown.d.ts +21 -1
  7. package/dist/ai/json-to-markdown.js +120 -57
  8. package/dist/ai/references.d.ts +72 -0
  9. package/dist/ai/references.js +223 -0
  10. package/dist/ai/resolve-branch.js +9 -2
  11. package/dist/ai/to-plain-text.d.ts +17 -8
  12. package/dist/ai/to-plain-text.js +18 -15
  13. package/dist/ai/types.d.ts +84 -3
  14. package/dist/api/admin-branch-health.d.ts +24 -1
  15. package/dist/api/admin-branch-health.js +52 -20
  16. package/dist/api/admin.d.ts +23 -5
  17. package/dist/api/admin.js +36 -1
  18. package/dist/api/assets.js +88 -78
  19. package/dist/api/branch-create-window.d.ts +12 -0
  20. package/dist/api/branch-create-window.js +13 -0
  21. package/dist/api/branch-merge.d.ts +1 -1
  22. package/dist/api/branch-merge.js +1 -1
  23. package/dist/api/branch-review.d.ts +3 -3
  24. package/dist/api/branch-review.js +16 -7
  25. package/dist/api/branch-status.d.ts +16 -6
  26. package/dist/api/branch-status.js +57 -12
  27. package/dist/api/branch-withdraw.d.ts +2 -2
  28. package/dist/api/branch-withdraw.js +8 -3
  29. package/dist/api/branch.d.ts +25 -12
  30. package/dist/api/branch.js +164 -103
  31. package/dist/api/client.d.ts +78 -58
  32. package/dist/api/client.js +150 -117
  33. package/dist/api/comments.d.ts +12 -3
  34. package/dist/api/comments.js +118 -9
  35. package/dist/api/content.d.ts +9 -9
  36. package/dist/api/content.js +131 -22
  37. package/dist/api/entries-constants.d.ts +14 -3
  38. package/dist/api/entries-constants.js +14 -3
  39. package/dist/api/entries.d.ts +40 -2
  40. package/dist/api/entries.js +102 -6
  41. package/dist/api/github-sync.d.ts +19 -0
  42. package/dist/api/github-sync.js +50 -3
  43. package/dist/api/groups.d.ts +4 -4
  44. package/dist/api/groups.js +2 -1
  45. package/dist/api/guards.js +23 -3
  46. package/dist/api/index.d.ts +3 -1
  47. package/dist/api/index.js +1 -0
  48. package/dist/api/permissions.d.ts +21 -2
  49. package/dist/api/permissions.js +50 -3
  50. package/dist/api/request-deadline.d.ts +59 -0
  51. package/dist/api/request-deadline.js +73 -0
  52. package/dist/api/resolve-references.js +8 -7
  53. package/dist/api/route-builder.d.ts +14 -0
  54. package/dist/api/route-builder.js +14 -1
  55. package/dist/api/schema.d.ts +11 -9
  56. package/dist/api/schema.js +2 -0
  57. package/dist/api/settings-helpers.d.ts +5 -1
  58. package/dist/api/settings-helpers.js +10 -2
  59. package/dist/api/types.d.ts +18 -0
  60. package/dist/api/users-constants.d.ts +6 -0
  61. package/dist/api/users-constants.js +6 -0
  62. package/dist/assets/asset-url.d.ts +28 -16
  63. package/dist/assets/asset-url.js +51 -25
  64. package/dist/assets/finalize.js +3 -0
  65. package/dist/assets/index.d.ts +1 -1
  66. package/dist/assets/materialize.d.ts +153 -0
  67. package/dist/assets/materialize.js +402 -0
  68. package/dist/assets/store-local.d.ts +19 -5
  69. package/dist/assets/store-local.js +69 -10
  70. package/dist/assets/store-s3.d.ts +38 -7
  71. package/dist/assets/store-s3.js +128 -22
  72. package/dist/assets/transform-directives.d.ts +52 -13
  73. package/dist/assets/transform-directives.js +87 -27
  74. package/dist/assets/transform.d.ts +3 -3
  75. package/dist/assets/transform.js +13 -8
  76. package/dist/assets/types.d.ts +31 -4
  77. package/dist/auth/cache.d.ts +1 -1
  78. package/dist/auth/cache.js +1 -1
  79. package/dist/auth/caching-auth-plugin.d.ts +2 -0
  80. package/dist/auth/caching-auth-plugin.js +12 -2
  81. package/dist/auth/file-based-auth-cache.d.ts +8 -0
  82. package/dist/auth/file-based-auth-cache.js +18 -8
  83. package/dist/auth/person-name.d.ts +5 -0
  84. package/dist/auth/person-name.js +8 -0
  85. package/dist/auth/plugin.d.ts +10 -1
  86. package/dist/auth/types.d.ts +2 -0
  87. package/dist/auth/user-metadata-lookup.d.ts +21 -0
  88. package/dist/auth/user-metadata-lookup.js +116 -0
  89. package/dist/authorization/branch.d.ts +1 -1
  90. package/dist/authorization/branch.js +12 -13
  91. package/dist/authorization/groups/schema.d.ts +4 -4
  92. package/dist/authorization/helpers.d.ts +8 -0
  93. package/dist/authorization/helpers.js +8 -0
  94. package/dist/authorization/index.d.ts +1 -1
  95. package/dist/authorization/index.js +1 -1
  96. package/dist/authorization/protected-branch.d.ts +5 -4
  97. package/dist/authorization/protected-branch.js +7 -5
  98. package/dist/branch-health.d.ts +35 -8
  99. package/dist/branch-health.js +54 -18
  100. package/dist/branch-metadata-error.d.ts +27 -0
  101. package/dist/branch-metadata-error.js +23 -0
  102. package/dist/branch-metadata-file.d.ts +205 -24
  103. package/dist/branch-metadata-file.js +126 -25
  104. package/dist/branch-metadata.d.ts +45 -6
  105. package/dist/branch-metadata.js +142 -50
  106. package/dist/branch-provisioning.d.ts +167 -0
  107. package/dist/branch-provisioning.js +501 -0
  108. package/dist/branch-registry.d.ts +8 -0
  109. package/dist/branch-registry.js +61 -9
  110. package/dist/branch-schema-cache.d.ts +29 -12
  111. package/dist/branch-schema-cache.js +64 -21
  112. package/dist/branch-sparse.d.ts +23 -0
  113. package/dist/branch-sparse.js +118 -0
  114. package/dist/branch-workspace.d.ts +42 -3
  115. package/dist/branch-workspace.js +239 -100
  116. package/dist/build/asset-refs.d.ts +94 -0
  117. package/dist/build/asset-refs.js +267 -0
  118. package/dist/build/generate-ai-content.js +5 -0
  119. package/dist/build/inline-flight.d.ts +37 -0
  120. package/dist/build/inline-flight.js +142 -0
  121. package/dist/cli/asset-refs.d.ts +52 -0
  122. package/dist/cli/asset-refs.js +194 -0
  123. package/dist/cli/cli.d.ts +15 -1
  124. package/dist/cli/cli.js +8543 -3193
  125. package/dist/cli/configured-asset-store.d.ts +12 -0
  126. package/dist/cli/configured-asset-store.js +46 -0
  127. package/dist/cli/generate-ai-content.js +4244 -1072
  128. package/dist/cli/init.js +217 -126
  129. package/dist/cli/project-detect.d.ts +2 -0
  130. package/dist/cli/project-detect.js +2 -0
  131. package/dist/cli/template-files/Dockerfile.cms.template +13 -5
  132. package/dist/cli/template-files/cms-stack.ts.template +16 -13
  133. package/dist/client.d.ts +1 -2
  134. package/dist/client.js +1 -2
  135. package/dist/comment-store.d.ts +25 -0
  136. package/dist/comment-store.js +43 -8
  137. package/dist/config/flatten.js +2 -0
  138. package/dist/config/helpers.js +2 -2
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/config/schemas/config.d.ts +12 -29
  141. package/dist/config/schemas/config.js +9 -12
  142. package/dist/config/schemas/field.d.ts +3 -0
  143. package/dist/config/schemas/field.js +58 -4
  144. package/dist/config/schemas/media.d.ts +4 -13
  145. package/dist/config/schemas/media.js +5 -8
  146. package/dist/config/schemas/url.d.ts +2 -20
  147. package/dist/config/schemas/url.js +2 -25
  148. package/dist/config/types.d.ts +116 -22
  149. package/dist/config/types.js +3 -9
  150. package/dist/config/validation.d.ts +25 -4
  151. package/dist/config/validation.js +116 -3
  152. package/dist/content-id-index.js +2 -2
  153. package/dist/content-index-generation.d.ts +1 -1
  154. package/dist/content-index-generation.js +1 -1
  155. package/dist/content-listing.d.ts +10 -1
  156. package/dist/content-listing.js +22 -5
  157. package/dist/content-reader.d.ts +9 -0
  158. package/dist/content-reader.js +16 -11
  159. package/dist/content-store.d.ts +75 -12
  160. package/dist/content-store.js +249 -86
  161. package/dist/content-tree.js +2 -2
  162. package/dist/context.js +5 -2
  163. package/dist/dangling-reference-log.d.ts +17 -0
  164. package/dist/dangling-reference-log.js +29 -0
  165. package/dist/dev-content-watcher.d.ts +1 -1
  166. package/dist/dev-content-watcher.js +1 -1
  167. package/dist/editor/BranchManager.d.ts +23 -7
  168. package/dist/editor/BranchManager.js +119 -54
  169. package/dist/editor/CanopyEditor.d.ts +1 -1
  170. package/dist/editor/CanopyEditor.js +1 -2
  171. package/dist/editor/CommentsPanel.d.ts +14 -0
  172. package/dist/editor/CommentsPanel.js +68 -43
  173. package/dist/editor/Editor.d.ts +11 -5
  174. package/dist/editor/Editor.js +891 -218
  175. package/dist/editor/EditorAuthGate.d.ts +7 -1
  176. package/dist/editor/EditorAuthGate.js +41 -9
  177. package/dist/editor/EntryNavigator.d.ts +22 -0
  178. package/dist/editor/EntryNavigator.js +353 -105
  179. package/dist/editor/FormHeader.d.ts +25 -0
  180. package/dist/editor/FormHeader.js +82 -0
  181. package/dist/editor/FormRenderer.d.ts +27 -3
  182. package/dist/editor/FormRenderer.js +171 -76
  183. package/dist/editor/PreviewFrame.d.ts +40 -0
  184. package/dist/editor/PreviewFrame.js +215 -0
  185. package/dist/editor/PreviewPane.d.ts +47 -0
  186. package/dist/editor/PreviewPane.js +147 -0
  187. package/dist/editor/PreviewToolbarTools.d.ts +22 -0
  188. package/dist/editor/PreviewToolbarTools.js +73 -0
  189. package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
  190. package/dist/editor/admin/SystemHealthPanel.js +163 -33
  191. package/dist/editor/admin/useSystemHealth.d.ts +18 -0
  192. package/dist/editor/admin/useSystemHealth.js +70 -1
  193. package/dist/editor/branch-status.d.ts +17 -0
  194. package/dist/editor/branch-status.js +29 -0
  195. package/dist/editor/canopy-path.d.ts +9 -6
  196. package/dist/editor/canopy-path.js +8 -11
  197. package/dist/editor/client-reference-resolver.d.ts +43 -16
  198. package/dist/editor/client-reference-resolver.js +155 -64
  199. package/dist/editor/comments/BranchComments.d.ts +1 -1
  200. package/dist/editor/comments/BranchComments.js +2 -2
  201. package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
  202. package/dist/editor/comments/CloseRefusedNotice.js +7 -0
  203. package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
  204. package/dist/editor/comments/CommentThreadsPopover.js +274 -0
  205. package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
  206. package/dist/editor/comments/CommentWriteAlert.js +13 -0
  207. package/dist/editor/comments/EntryComments.d.ts +10 -4
  208. package/dist/editor/comments/EntryComments.js +14 -17
  209. package/dist/editor/comments/FieldWrapper.d.ts +18 -4
  210. package/dist/editor/comments/FieldWrapper.js +62 -28
  211. package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
  212. package/dist/editor/comments/InlineCommentThread.js +11 -47
  213. package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
  214. package/dist/editor/comments/ThreadCarousel.js +18 -21
  215. package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
  216. package/dist/editor/comments/ThreadReplyControls.js +92 -0
  217. package/dist/editor/comments/field-comment-context.d.ts +14 -0
  218. package/dist/editor/comments/field-comment-context.js +14 -0
  219. package/dist/editor/comments/form-comments.d.ts +48 -0
  220. package/dist/editor/comments/form-comments.js +178 -0
  221. package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
  222. package/dist/editor/comments/item-anchor-copy.js +6 -0
  223. package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
  224. package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
  225. package/dist/editor/comments/popover-placement.d.ts +18 -0
  226. package/dist/editor/comments/popover-placement.js +58 -0
  227. package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
  228. package/dist/editor/comments/use-tracked-writes.js +53 -0
  229. package/dist/editor/components/BranchAccessList.d.ts +15 -0
  230. package/dist/editor/components/BranchAccessList.js +52 -0
  231. package/dist/editor/components/BranchLockBanner.d.ts +22 -0
  232. package/dist/editor/components/BranchLockBanner.js +39 -0
  233. package/dist/editor/components/BranchPill.d.ts +32 -0
  234. package/dist/editor/components/BranchPill.js +33 -0
  235. package/dist/editor/components/BranchesDrawer.d.ts +11 -0
  236. package/dist/editor/components/BranchesDrawer.js +5 -0
  237. package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
  238. package/dist/editor/components/ConfirmDeleteModal.js +3 -2
  239. package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
  240. package/dist/editor/components/DestructiveMenuItem.js +8 -0
  241. package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
  242. package/dist/editor/components/EditorCrashScreen.js +22 -0
  243. package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
  244. package/dist/editor/components/EditorErrorBoundary.js +40 -0
  245. package/dist/editor/components/EditorHeader.d.ts +56 -106
  246. package/dist/editor/components/EditorHeader.js +130 -131
  247. package/dist/editor/components/EditorRail.d.ts +49 -0
  248. package/dist/editor/components/EditorRail.js +65 -0
  249. package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
  250. package/dist/editor/components/EntryBreadcrumb.js +56 -0
  251. package/dist/editor/components/EntryCreateModal.d.ts +12 -7
  252. package/dist/editor/components/EntryCreateModal.js +51 -57
  253. package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
  254. package/dist/editor/components/NoEditPermissionNotice.js +5 -4
  255. package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
  256. package/dist/editor/components/QuickOpenPalette.js +66 -0
  257. package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
  258. package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
  259. package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
  260. package/dist/editor/components/ReasonedMenuItem.js +15 -0
  261. package/dist/editor/components/ReferencedByList.d.ts +11 -0
  262. package/dist/editor/components/ReferencedByList.js +28 -0
  263. package/dist/editor/components/RelativeTime.d.ts +10 -0
  264. package/dist/editor/components/RelativeTime.js +10 -0
  265. package/dist/editor/components/RenameEntryModal.d.ts +9 -1
  266. package/dist/editor/components/RenameEntryModal.js +19 -31
  267. package/dist/editor/components/RetryToastMessage.d.ts +9 -0
  268. package/dist/editor/components/RetryToastMessage.js +6 -0
  269. package/dist/editor/components/SaveAllResult.d.ts +25 -0
  270. package/dist/editor/components/SaveAllResult.js +86 -0
  271. package/dist/editor/components/SaveSplitButton.d.ts +30 -0
  272. package/dist/editor/components/SaveSplitButton.js +108 -0
  273. package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
  274. package/dist/editor/components/StagedChangesDrawer.js +92 -0
  275. package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
  276. package/dist/editor/components/UnavailableEntryNotice.js +9 -0
  277. package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
  278. package/dist/editor/components/UnavailableTypeMessage.js +9 -0
  279. package/dist/editor/components/UndoToastMessage.d.ts +18 -0
  280. package/dist/editor/components/UndoToastMessage.js +10 -0
  281. package/dist/editor/components/UserBadge.d.ts +2 -5
  282. package/dist/editor/components/UserBadge.js +62 -33
  283. package/dist/editor/components/ValidationSummary.d.ts +14 -0
  284. package/dist/editor/components/ValidationSummary.js +24 -0
  285. package/dist/editor/components/index.d.ts +2 -2
  286. package/dist/editor/components/index.js +2 -2
  287. package/dist/editor/context/ApiClientContext.d.ts +8 -2
  288. package/dist/editor/context/ApiClientContext.js +19 -8
  289. package/dist/editor/context/AssetContext.d.ts +13 -35
  290. package/dist/editor/context/AssetContext.js +12 -31
  291. package/dist/editor/context/EditorStateContext.d.ts +4 -4
  292. package/dist/editor/context/EditorStateContext.js +4 -4
  293. package/dist/editor/context/SWRProvider.d.ts +3 -3
  294. package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
  295. package/dist/editor/context/SiteMdxAllowContext.js +7 -0
  296. package/dist/editor/context/index.d.ts +2 -1
  297. package/dist/editor/context/index.js +2 -1
  298. package/dist/editor/contrast.d.ts +19 -0
  299. package/dist/editor/contrast.js +41 -0
  300. package/dist/editor/copy.d.ts +18 -0
  301. package/dist/editor/copy.js +18 -0
  302. package/dist/editor/editor-config.js +16 -0
  303. package/dist/editor/editor-utils.d.ts +34 -8
  304. package/dist/editor/editor-utils.js +42 -20
  305. package/dist/editor/entry-search.d.ts +20 -0
  306. package/dist/editor/entry-search.js +34 -0
  307. package/dist/editor/field-breadcrumb.d.ts +12 -0
  308. package/dist/editor/field-breadcrumb.js +85 -0
  309. package/dist/editor/field-props.d.ts +86 -0
  310. package/dist/editor/field-props.js +27 -0
  311. package/dist/editor/field-target.d.ts +30 -0
  312. package/dist/editor/field-target.js +77 -0
  313. package/dist/editor/fields/BlockField.d.ts +12 -0
  314. package/dist/editor/fields/BlockField.js +89 -73
  315. package/dist/editor/fields/CodeField.d.ts +2 -0
  316. package/dist/editor/fields/CodeField.js +6 -2
  317. package/dist/editor/fields/DateTimeField.d.ts +4 -29
  318. package/dist/editor/fields/DateTimeField.js +79 -41
  319. package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
  320. package/dist/editor/fields/ExpandAllButton.js +4 -0
  321. package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
  322. package/dist/editor/fields/FieldCrashFallback.js +30 -0
  323. package/dist/editor/fields/FieldLabel.d.ts +37 -0
  324. package/dist/editor/fields/FieldLabel.js +19 -0
  325. package/dist/editor/fields/ImageField.d.ts +4 -0
  326. package/dist/editor/fields/ImageField.js +29 -14
  327. package/dist/editor/fields/InlineGroupField.js +4 -3
  328. package/dist/editor/fields/ItemList.d.ts +42 -0
  329. package/dist/editor/fields/ItemList.js +130 -0
  330. package/dist/editor/fields/MarkdownField.d.ts +32 -0
  331. package/dist/editor/fields/MarkdownField.js +223 -46
  332. package/dist/editor/fields/MdxImageDialog.js +1 -1
  333. package/dist/editor/fields/NumberField.d.ts +2 -0
  334. package/dist/editor/fields/NumberField.js +8 -5
  335. package/dist/editor/fields/NumberListField.d.ts +2 -0
  336. package/dist/editor/fields/NumberListField.js +19 -16
  337. package/dist/editor/fields/ObjectField.d.ts +2 -7
  338. package/dist/editor/fields/ObjectField.js +15 -5
  339. package/dist/editor/fields/ObjectListField.d.ts +29 -0
  340. package/dist/editor/fields/ObjectListField.js +57 -0
  341. package/dist/editor/fields/ReferenceField.d.ts +2 -0
  342. package/dist/editor/fields/ReferenceField.js +34 -9
  343. package/dist/editor/fields/SelectField.d.ts +2 -0
  344. package/dist/editor/fields/SelectField.js +11 -2
  345. package/dist/editor/fields/StringListField.d.ts +4 -1
  346. package/dist/editor/fields/StringListField.js +22 -8
  347. package/dist/editor/fields/TextField.d.ts +2 -0
  348. package/dist/editor/fields/TextField.js +6 -2
  349. package/dist/editor/fields/ToggleField.d.ts +2 -0
  350. package/dist/editor/fields/ToggleField.js +8 -3
  351. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
  352. package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
  353. package/dist/editor/fields/form-expansion.d.ts +9 -0
  354. package/dist/editor/fields/form-expansion.js +2 -0
  355. package/dist/editor/fields/item-expansion.d.ts +15 -0
  356. package/dist/editor/fields/item-expansion.js +60 -0
  357. package/dist/editor/fields/list-item-keys.d.ts +8 -0
  358. package/dist/editor/fields/list-item-keys.js +50 -0
  359. package/dist/editor/fields/list-item-title.d.ts +20 -0
  360. package/dist/editor/fields/list-item-title.js +85 -0
  361. package/dist/editor/fields/markdown-export-options.d.ts +2 -0
  362. package/dist/editor/fields/markdown-export-options.js +8 -0
  363. package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
  364. package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
  365. package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
  366. package/dist/editor/fields/mdx-jsx-support.js +157 -69
  367. package/dist/editor/fields/rich-text-failures.d.ts +5 -0
  368. package/dist/editor/fields/rich-text-failures.js +26 -0
  369. package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
  370. package/dist/editor/fields/toolbar-wrap.js +35 -0
  371. package/dist/editor/form-outline.d.ts +13 -0
  372. package/dist/editor/form-outline.js +70 -0
  373. package/dist/editor/group-manager/GroupCard.d.ts +4 -1
  374. package/dist/editor/group-manager/GroupCard.js +12 -3
  375. package/dist/editor/group-manager/GroupForm.js +1 -1
  376. package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
  377. package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
  378. package/dist/editor/group-manager/MemberList.d.ts +2 -1
  379. package/dist/editor/group-manager/MemberList.js +15 -4
  380. package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
  381. package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
  382. package/dist/editor/group-manager/index.js +34 -5
  383. package/dist/editor/group-manager/types.d.ts +5 -2
  384. package/dist/editor/hooks/create-branch-request.d.ts +20 -0
  385. package/dist/editor/hooks/create-branch-request.js +54 -0
  386. package/dist/editor/hooks/save-all.d.ts +68 -0
  387. package/dist/editor/hooks/save-all.js +61 -0
  388. package/dist/editor/hooks/useBranchActions.d.ts +11 -1
  389. package/dist/editor/hooks/useBranchActions.js +42 -19
  390. package/dist/editor/hooks/useBranchManager.d.ts +21 -0
  391. package/dist/editor/hooks/useBranchManager.js +321 -125
  392. package/dist/editor/hooks/useBranchesData.d.ts +8 -4
  393. package/dist/editor/hooks/useBranchesData.js +9 -5
  394. package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
  395. package/dist/editor/hooks/useCommentSystem.js +79 -55
  396. package/dist/editor/hooks/useCommentsData.d.ts +11 -7
  397. package/dist/editor/hooks/useCommentsData.js +20 -19
  398. package/dist/editor/hooks/useDraftManager.d.ts +77 -3
  399. package/dist/editor/hooks/useDraftManager.js +887 -94
  400. package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
  401. package/dist/editor/hooks/useEditorLayout.js +98 -20
  402. package/dist/editor/hooks/useEntriesData.d.ts +2 -1
  403. package/dist/editor/hooks/useEntriesData.js +18 -4
  404. package/dist/editor/hooks/useEntryManager.d.ts +41 -2
  405. package/dist/editor/hooks/useEntryManager.js +227 -41
  406. package/dist/editor/hooks/useGroupManager.js +13 -16
  407. package/dist/editor/hooks/usePermissionManager.js +14 -6
  408. package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
  409. package/dist/editor/hooks/usePreviewMarks.js +33 -0
  410. package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
  411. package/dist/editor/hooks/useReferenceResolution.js +34 -177
  412. package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
  413. package/dist/editor/hooks/useSchemaManager.js +97 -39
  414. package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
  415. package/dist/editor/hooks/useUserMetadata.js +76 -47
  416. package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
  417. package/dist/editor/hooks/user-metadata-batcher.js +33 -0
  418. package/dist/editor/media/AssetCard.d.ts +6 -7
  419. package/dist/editor/media/AssetCard.js +24 -31
  420. package/dist/editor/media/AssetListRow.d.ts +16 -0
  421. package/dist/editor/media/AssetListRow.js +41 -0
  422. package/dist/editor/media/CropStep.js +6 -1
  423. package/dist/editor/media/MediaLibrary.d.ts +4 -3
  424. package/dist/editor/media/MediaLibrary.js +11 -4
  425. package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
  426. package/dist/editor/media/MediaLibraryBody.js +195 -80
  427. package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
  428. package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
  429. package/dist/editor/media/crop-math.d.ts +3 -4
  430. package/dist/editor/media/crop-math.js +11 -22
  431. package/dist/editor/media/editor-image-src.d.ts +8 -0
  432. package/dist/editor/media/editor-image-src.js +10 -0
  433. package/dist/editor/media/format-bytes.d.ts +2 -0
  434. package/dist/editor/media/format-bytes.js +23 -0
  435. package/dist/editor/media/media-library-prefs.d.ts +23 -0
  436. package/dist/editor/media/media-library-prefs.js +49 -0
  437. package/dist/editor/media/media-library-view.d.ts +34 -0
  438. package/dist/editor/media/media-library-view.js +40 -0
  439. package/dist/editor/media/useAssetLibrary.d.ts +30 -0
  440. package/dist/editor/media/useAssetLibrary.js +126 -0
  441. package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
  442. package/dist/editor/media/useStableAssetOrder.js +37 -0
  443. package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
  444. package/dist/editor/media/useThumbnailFailure.js +16 -0
  445. package/dist/editor/permission-manager/GroupSelector.js +2 -2
  446. package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
  447. package/dist/editor/permission-manager/PermissionEditor.js +15 -4
  448. package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
  449. package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
  450. package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
  451. package/dist/editor/permission-manager/UserSelector.js +3 -3
  452. package/dist/editor/permission-manager/index.js +12 -3
  453. package/dist/editor/permission-manager/types.d.ts +5 -2
  454. package/dist/editor/platform.d.ts +3 -0
  455. package/dist/editor/platform.js +9 -0
  456. package/dist/editor/preview-asset-base.d.ts +9 -0
  457. package/dist/editor/preview-asset-base.js +17 -0
  458. package/dist/editor/preview-bridge.d.ts +51 -27
  459. package/dist/editor/preview-bridge.js +103 -144
  460. package/dist/editor/preview-marks.d.ts +15 -0
  461. package/dist/editor/preview-marks.js +74 -0
  462. package/dist/editor/preview-path.d.ts +12 -0
  463. package/dist/editor/preview-path.js +45 -1
  464. package/dist/editor/preview-scale.d.ts +27 -0
  465. package/dist/editor/preview-scale.js +34 -0
  466. package/dist/editor/raw-asset-base.d.ts +5 -0
  467. package/dist/editor/raw-asset-base.js +14 -0
  468. package/dist/editor/relative-time.d.ts +4 -4
  469. package/dist/editor/relative-time.js +16 -8
  470. package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
  471. package/dist/editor/schema-editor/CollectionEditor.js +361 -62
  472. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
  473. package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
  474. package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
  475. package/dist/editor/schema-editor/collection-draft.js +40 -0
  476. package/dist/editor/schema-editor/index.d.ts +1 -1
  477. package/dist/editor/schema-label.d.ts +10 -0
  478. package/dist/editor/schema-label.js +17 -0
  479. package/dist/editor/settings-conflict.d.ts +5 -0
  480. package/dist/editor/settings-conflict.js +8 -0
  481. package/dist/editor/shell/ActivityRail.d.ts +37 -0
  482. package/dist/editor/shell/ActivityRail.js +91 -0
  483. package/dist/editor/shell/EditorShell.d.ts +17 -0
  484. package/dist/editor/shell/EditorShell.js +31 -0
  485. package/dist/editor/shell/PaneLayout.d.ts +28 -0
  486. package/dist/editor/shell/PaneLayout.js +116 -0
  487. package/dist/editor/shell/SidePanelHost.d.ts +35 -0
  488. package/dist/editor/shell/SidePanelHost.js +184 -0
  489. package/dist/editor/shell/TopBar.d.ts +12 -0
  490. package/dist/editor/shell/TopBar.js +14 -0
  491. package/dist/editor/shell/host-chrome.d.ts +16 -0
  492. package/dist/editor/shell/host-chrome.js +69 -0
  493. package/dist/editor/slug.d.ts +16 -0
  494. package/dist/editor/slug.js +43 -0
  495. package/dist/editor/theme.d.ts +2 -1
  496. package/dist/editor/theme.js +314 -13
  497. package/dist/editor/unanswered.d.ts +17 -0
  498. package/dist/editor/unanswered.js +26 -0
  499. package/dist/editor/unavailable-entry-type.d.ts +20 -0
  500. package/dist/editor/unavailable-entry-type.js +28 -0
  501. package/dist/editor/undo-removal.d.ts +57 -0
  502. package/dist/editor/undo-removal.js +163 -0
  503. package/dist/editor/user-display.d.ts +4 -0
  504. package/dist/editor/user-display.js +5 -0
  505. package/dist/editor/utils/confirm-modal.d.ts +8 -0
  506. package/dist/editor/utils/confirm-modal.js +12 -0
  507. package/dist/editor/utils/editor-errors.d.ts +19 -0
  508. package/dist/editor/utils/editor-errors.js +32 -0
  509. package/dist/editor/utils/focus-return.d.ts +56 -0
  510. package/dist/editor/utils/focus-return.js +106 -0
  511. package/dist/entry-link-resolver.d.ts +11 -1
  512. package/dist/entry-link-resolver.js +65 -5
  513. package/dist/entry-schema-registry.d.ts +3 -3
  514. package/dist/entry-schema-registry.js +7 -4
  515. package/dist/entry-schema.d.ts +49 -3
  516. package/dist/entry-schema.js +18 -0
  517. package/dist/git-manager.d.ts +172 -10
  518. package/dist/git-manager.js +449 -107
  519. package/dist/github-service.d.ts +39 -2
  520. package/dist/github-service.js +101 -7
  521. package/dist/http/handler.js +74 -9
  522. package/dist/http/types.d.ts +2 -0
  523. package/dist/http/worker-not-ready.d.ts +9 -4
  524. package/dist/http/worker-not-ready.js +59 -6
  525. package/dist/index.d.ts +2 -0
  526. package/dist/index.js +3 -0
  527. package/dist/item-keys.d.ts +46 -0
  528. package/dist/item-keys.js +235 -0
  529. package/dist/operating-mode/editor-mode-check.d.ts +15 -0
  530. package/dist/operating-mode/editor-mode-check.js +24 -0
  531. package/dist/operating-mode/mode-env.d.ts +13 -14
  532. package/dist/operating-mode/mode-env.js +13 -14
  533. package/dist/operating-mode/types.d.ts +2 -2
  534. package/dist/paths/branch.d.ts +0 -1
  535. package/dist/paths/branch.js +1 -8
  536. package/dist/paths/index.d.ts +1 -1
  537. package/dist/paths/index.js +1 -1
  538. package/dist/paths/validation.js +0 -2
  539. package/dist/preview.d.ts +8 -0
  540. package/dist/preview.js +7 -0
  541. package/dist/reference-resolver.js +1 -0
  542. package/dist/resolve-canopy-user.d.ts +1 -1
  543. package/dist/resolve-canopy-user.js +1 -1
  544. package/dist/schema/meta-loader.d.ts +18 -8
  545. package/dist/schema/meta-loader.js +42 -9
  546. package/dist/schema/registry-fingerprint.d.ts +14 -0
  547. package/dist/schema/registry-fingerprint.js +63 -0
  548. package/dist/schema/resolver.d.ts +7 -4
  549. package/dist/schema/resolver.js +7 -6
  550. package/dist/schema/schema-store.d.ts +7 -10
  551. package/dist/schema/schema-store.js +13 -11
  552. package/dist/schema/schema-unavailable-error.d.ts +11 -0
  553. package/dist/schema/schema-unavailable-error.js +15 -0
  554. package/dist/schema/types.d.ts +22 -0
  555. package/dist/schema-registry-record.d.ts +35 -0
  556. package/dist/schema-registry-record.js +134 -0
  557. package/dist/server.d.ts +79 -9
  558. package/dist/server.js +62 -8
  559. package/dist/services.d.ts +33 -5
  560. package/dist/services.js +155 -37
  561. package/dist/settings-workspace.d.ts +23 -3
  562. package/dist/settings-workspace.js +159 -45
  563. package/dist/stamp-on-publish.d.ts +36 -0
  564. package/dist/stamp-on-publish.js +71 -0
  565. package/dist/static/index.d.ts +58 -5
  566. package/dist/static/index.js +133 -3
  567. package/dist/static/seo.d.ts +5 -5
  568. package/dist/static/seo.js +5 -5
  569. package/dist/submission-attribution.d.ts +8 -0
  570. package/dist/submission-attribution.js +22 -0
  571. package/dist/system-users.d.ts +12 -0
  572. package/dist/system-users.js +12 -0
  573. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  574. package/dist/task-queue/cms-task-queue.js +1 -1
  575. package/dist/task-queue/index.d.ts +1 -1
  576. package/dist/task-queue/index.js +1 -1
  577. package/dist/task-queue/task-queue.d.ts +6 -0
  578. package/dist/task-queue/task-queue.js +29 -0
  579. package/dist/task-queue/worker-status.d.ts +35 -9
  580. package/dist/task-queue/worker-status.js +84 -17
  581. package/dist/types.d.ts +90 -9
  582. package/dist/url-collision.js +3 -3
  583. package/dist/url-exclusivity-fixtures.d.ts +8 -1
  584. package/dist/url-exclusivity-fixtures.js +11 -1
  585. package/dist/user.js +2 -1
  586. package/dist/utils/atomic-write.js +2 -1
  587. package/dist/utils/base-branch.d.ts +13 -0
  588. package/dist/utils/base-branch.js +23 -0
  589. package/dist/utils/content-serialize.d.ts +15 -7
  590. package/dist/utils/content-serialize.js +353 -51
  591. package/dist/utils/content-write-lock.d.ts +6 -1
  592. package/dist/utils/content-write-lock.js +21 -6
  593. package/dist/utils/debug.d.ts +1 -1
  594. package/dist/utils/debug.js +5 -3
  595. package/dist/utils/error.js +13 -2
  596. package/dist/utils/escape-text.d.ts +7 -0
  597. package/dist/utils/escape-text.js +27 -0
  598. package/dist/utils/fs.d.ts +12 -4
  599. package/dist/utils/fs.js +18 -5
  600. package/dist/utils/git.d.ts +21 -1
  601. package/dist/utils/git.js +63 -8
  602. package/dist/utils/json-source-splice.d.ts +14 -0
  603. package/dist/utils/json-source-splice.js +120 -0
  604. package/dist/utils/markdown-body-splice.d.ts +39 -0
  605. package/dist/utils/markdown-body-splice.js +421 -0
  606. package/dist/utils/occ-json-write.js +18 -12
  607. package/dist/utils/provision-log.d.ts +25 -0
  608. package/dist/utils/provision-log.js +49 -0
  609. package/dist/utils/provisioning-lock.d.ts +32 -1
  610. package/dist/utils/provisioning-lock.js +78 -32
  611. package/dist/utils/sanitize-href.d.ts +9 -23
  612. package/dist/utils/sanitize-href.js +14 -28
  613. package/dist/utils/title-field.d.ts +10 -0
  614. package/dist/utils/title-field.js +47 -0
  615. package/dist/utils/yaml-source-splice.d.ts +58 -0
  616. package/dist/utils/yaml-source-splice.js +515 -0
  617. package/dist/validation/block-structural-keys.d.ts +1 -1
  618. package/dist/validation/block-structural-keys.js +1 -1
  619. package/dist/validation/deletion-checker.d.ts +21 -29
  620. package/dist/validation/deletion-checker.js +41 -117
  621. package/dist/validation/entry-validator.d.ts +6 -10
  622. package/dist/validation/entry-validator.js +19 -26
  623. package/dist/validation/field-traversal.d.ts +22 -0
  624. package/dist/validation/field-traversal.js +39 -8
  625. package/dist/validation/markdown-safety.d.ts +68 -0
  626. package/dist/validation/markdown-safety.js +596 -0
  627. package/dist/validation/mdx-allowlist.d.ts +55 -0
  628. package/dist/validation/mdx-allowlist.js +183 -0
  629. package/dist/validation/reference-validator.d.ts +2 -0
  630. package/dist/validation/reference-validator.js +3 -0
  631. package/dist/version.d.ts +1 -1
  632. package/dist/version.js +1 -1
  633. package/dist/worker/branch-policy.d.ts +124 -0
  634. package/dist/worker/branch-policy.js +243 -0
  635. package/dist/worker/bundle-header.d.ts +117 -0
  636. package/dist/worker/bundle-header.js +253 -0
  637. package/dist/worker/cms-worker.d.ts +236 -142
  638. package/dist/worker/cms-worker.js +772 -285
  639. package/dist/worker/gateway-egress.d.ts +43 -0
  640. package/dist/worker/gateway-egress.js +209 -0
  641. package/dist/worker/gateway-instance.d.ts +42 -0
  642. package/dist/worker/gateway-instance.js +129 -0
  643. package/dist/worker/git-process.d.ts +81 -0
  644. package/dist/worker/git-process.js +234 -0
  645. package/dist/worker/git-sync.d.ts +34 -17
  646. package/dist/worker/git-sync.js +394 -131
  647. package/dist/worker/github-auth.d.ts +9 -9
  648. package/dist/worker/github-auth.js +13 -15
  649. package/dist/worker/github-gateway-http.d.ts +62 -0
  650. package/dist/worker/github-gateway-http.js +977 -0
  651. package/dist/worker/github-gateway-wire.d.ts +590 -0
  652. package/dist/worker/github-gateway-wire.js +488 -0
  653. package/dist/worker/github-gateway.d.ts +238 -0
  654. package/dist/worker/github-gateway.js +726 -0
  655. package/dist/worker/github-mirror-upkeep.d.ts +75 -0
  656. package/dist/worker/github-mirror-upkeep.js +266 -0
  657. package/dist/worker/github-mirror.d.ts +364 -0
  658. package/dist/worker/github-mirror.js +1030 -0
  659. package/dist/worker/github-transfer.d.ts +56 -0
  660. package/dist/worker/github-transfer.js +444 -0
  661. package/dist/worker/history-rewrite.d.ts +4 -5
  662. package/dist/worker/history-rewrite.js +12 -17
  663. package/dist/worker/provisioned-workspace.d.ts +5 -5
  664. package/dist/worker/provisioned-workspace.js +5 -5
  665. package/dist/worker/rebase.d.ts +1 -1
  666. package/dist/worker/rebase.js +58 -54
  667. package/dist/worker/remote-git-maintenance.d.ts +3 -0
  668. package/dist/worker/remote-git-maintenance.js +12 -0
  669. package/dist/worker/schema-gate.d.ts +49 -0
  670. package/dist/worker/schema-gate.js +226 -0
  671. package/dist/worker/self-checks.d.ts +107 -0
  672. package/dist/worker/self-checks.js +358 -0
  673. package/dist/worker/shared-repo-git.d.ts +96 -0
  674. package/dist/worker/shared-repo-git.js +459 -0
  675. package/dist/worker/sparse-cone.d.ts +20 -0
  676. package/dist/worker/sparse-cone.js +136 -0
  677. package/dist/worker/stale-mirror.d.ts +82 -0
  678. package/dist/worker/stale-mirror.js +130 -0
  679. package/dist/worker/task-runner.d.ts +5 -3
  680. package/dist/worker/task-runner.js +287 -186
  681. package/dist/worker/worker-context.d.ts +36 -37
  682. package/package.json +35 -7
  683. package/dist/editor/EditorPanes.d.ts +0 -10
  684. package/dist/editor/EditorPanes.js +0 -98
  685. package/dist/editor/components/EditorFooter.d.ts +0 -11
  686. package/dist/editor/components/EditorFooter.js +0 -9
  687. package/dist/editor/components/EditorSidebar.d.ts +0 -67
  688. package/dist/editor/components/EditorSidebar.js +0 -22
@@ -12,15 +12,17 @@
12
12
  * })` -- see the comment on `fetchBranches` for why it doesn't just call
13
13
  * `mutate()` to revalidate.
14
14
  */
15
- import useSWR from 'swr';
15
+ import useSWR, { useSWRConfig } from 'swr';
16
16
  import { isNonApiResponse } from '../../api/client.js';
17
+ import { seedUserProfiles } from './useUserMetadata.js';
17
18
  /** Cache key for the branches list. */
18
19
  export const BRANCHES_KEY = 'canopy:branches';
19
20
  /**
20
- * Fetch the branches list. Exported for direct testing and for the
21
- * imperative reload path.
21
+ * Fetch the branches list, writing the owners it names into the user-metadata cache before the
22
+ * listing lands, so owner badges render named. Exported for direct testing and for the imperative
23
+ * reload path.
22
24
  */
23
- export async function fetchBranches(apiClient) {
25
+ export async function fetchBranches(apiClient, swr) {
24
26
  const result = await apiClient.branches.list();
25
27
  if (result.status === 404 && !isNonApiResponse(result)) {
26
28
  // No branch endpoint available; stay branchless rather than erroring --
@@ -31,6 +33,7 @@ export async function fetchBranches(apiClient) {
31
33
  if (!result.ok) {
32
34
  throw new Error(result.error ?? `Failed to load branches: ${result.status}`);
33
35
  }
36
+ await seedUserProfiles(swr, result.data?.users ?? []);
34
37
  return {
35
38
  branches: result.data?.branches ?? [],
36
39
  defaultBranch: result.data?.defaultBranch,
@@ -69,7 +72,8 @@ export function hasInFlightBranch(data) {
69
72
  * `refreshInterval`, and narrower than the pre-SWR behavior it replaces.
70
73
  */
71
74
  export function useBranchesData(apiClient) {
72
- return useSWR(BRANCHES_KEY, () => fetchBranches(apiClient), {
75
+ const { cache, mutate } = useSWRConfig();
76
+ return useSWR(BRANCHES_KEY, () => fetchBranches(apiClient, { cache, mutate }), {
73
77
  refreshInterval: (data) => hasInFlightBranch(data) ? IN_FLIGHT_POLL_MS : 0,
74
78
  });
75
79
  }
@@ -1,4 +1,5 @@
1
1
  import type { CommentThread } from '../../comment-store.js';
2
+ import type { UserSearchResult } from '../../auth/types.js';
2
3
  import type { EditorEntry } from '../Editor.js';
3
4
  export interface UseCommentSystemOptions {
4
5
  branchName: string;
@@ -8,10 +9,14 @@ export interface UseCommentSystemOptions {
8
9
  canResolveComments: boolean;
9
10
  setSelectedPath: (id: string) => void;
10
11
  setBranchManagerOpen: (open: boolean) => void;
12
+ /** Uncovers the form before anything here focuses one of its fields. */
13
+ onRevealForm?: () => void;
11
14
  onCommentsChange?: (comments: CommentThread[]) => void;
12
15
  }
13
16
  export interface UseCommentSystemReturn {
14
17
  comments: CommentThread[];
18
+ /** Resolves a user from the seeded cache, without email or a request (`useSeededUserResolver`). */
19
+ getCommentUser: (userId: string) => Promise<UserSearchResult | null>;
15
20
  focusedFieldPath: string | undefined;
16
21
  setFocusedFieldPath: (path: string | undefined) => void;
17
22
  highlightThreadId: string | undefined;
@@ -30,13 +35,20 @@ export interface UseCommentSystemReturn {
30
35
  } | null) => void;
31
36
  activeThreads: CommentThread[];
32
37
  activeContextLabel: string;
33
- handleAddComment: (text: string, type: 'field' | 'entry' | 'branch', entryPath?: string, canopyPath?: string, threadId?: string) => Promise<void>;
38
+ /** `itemKeys`: for a new field thread, the keys of the list items on `canopyPath`. */
39
+ handleAddComment: (text: string, type: 'field' | 'entry' | 'branch', entryPath?: string, canopyPath?: string, threadId?: string, itemKeys?: string[]) => Promise<void>;
34
40
  handleResolveThread: (threadId: string) => Promise<void>;
35
- loadComments: (branch: string) => Promise<void>;
41
+ loadComments: (branch: string) => Promise<CommentThread[] | undefined>;
36
42
  handleJumpToField: (entryPath: string, canopyPath: string, threadId: string) => void;
37
43
  handleJumpToEntry: (entryPath: string, threadId: string) => void;
38
44
  handleJumpToBranch: (threadId: string) => void;
39
45
  }
46
+ /** @internal Exported for tests. */
47
+ export declare const COMMENT_NOT_ADDED = "Couldn't add the comment. Try again.";
48
+ /** @internal Exported for tests. */
49
+ export declare const COMMENT_MAY_BE_ADDED = "The server didn't answer, and the comments don't show yours yet, but it may still be posted. Wait a moment and check before sending it again.";
50
+ /** @internal Exported for tests. */
51
+ export declare const THREAD_NOT_RESOLVED = "Couldn't resolve the thread. Try again.";
40
52
  /**
41
53
  * Custom hook for managing the comment system.
42
54
  */
@@ -1,17 +1,24 @@
1
1
  import { useEffect, useMemo, useState } from 'react';
2
2
  import { useSWRConfig } from 'swr';
3
- import { notifications } from '@mantine/notifications';
4
- import { normalizeCanopyPath } from '../canopy-path.js';
3
+ import { findFieldTarget, whenRevealed } from '../field-target.js';
5
4
  import { useApiClient } from '../context/index.js';
5
+ import { isGatewayFailure, isUnanswered, MayHaveLandedError } from '../unanswered.js';
6
6
  import { resolveMessageOrigin } from '../preview-bridge.js';
7
7
  import { isSamePreviewPath } from '../preview-path.js';
8
- import { commentsKey, fetchComments, useCommentsData } from './useCommentsData.js';
8
+ import { commentsKey, fetchCommentsSeedingUsers, useCommentsData } from './useCommentsData.js';
9
+ import { useSeededUserResolver } from './useUserMetadata.js';
10
+ /** @internal Exported for tests. */
11
+ export const COMMENT_NOT_ADDED = "Couldn't add the comment. Try again.";
12
+ /** @internal Exported for tests. */
13
+ export const COMMENT_MAY_BE_ADDED = "The server didn't answer, and the comments don't show yours yet, but it may still be posted. Wait a moment and check before sending it again.";
14
+ /** @internal Exported for tests. */
15
+ export const THREAD_NOT_RESOLVED = "Couldn't resolve the thread. Try again.";
9
16
  /**
10
17
  * Custom hook for managing the comment system.
11
18
  */
12
19
  export function useCommentSystem(options) {
13
20
  const apiClient = useApiClient();
14
- const { mutate: globalMutate } = useSWRConfig();
21
+ const { cache, mutate: globalMutate } = useSWRConfig();
15
22
  const [focusedFieldPath, setFocusedFieldPath] = useState(undefined);
16
23
  const [highlightThreadId, setHighlightThreadId] = useState(undefined);
17
24
  const [commentsPanelOpen, setCommentsPanelOpen] = useState(false);
@@ -21,64 +28,81 @@ export function useCommentSystem(options) {
21
28
  // Mode's double effect invoke collapses to a single request). Switching
22
29
  // branches re-keys automatically, so no manual branch-change effect is
23
30
  // needed.
24
- const { data: commentsData } = useCommentsData(apiClient, options.branchName);
31
+ const { data: commentsData, error: commentsError } = useCommentsData(apiClient, options.branchName);
25
32
  const comments = commentsData?.threads ?? [];
33
+ const getCommentUser = useSeededUserResolver();
26
34
  // Deliberately omits `options.onCommentsChange` from the deps: it's a
27
35
  // stable setState passthrough, and this file is plain .ts (not .tsx), so
28
36
  // the react-hooks/exhaustive-deps rule isn't active here anyway --
29
37
  // including it would refire this on every Editor.tsx render regardless.
38
+ // A branch whose comments never loaded reports none, not the previous branch's.
30
39
  useEffect(() => {
31
40
  if (commentsData)
32
41
  options.onCommentsChange?.(commentsData.threads);
33
- }, [commentsData]);
42
+ else if (commentsError)
43
+ options.onCommentsChange?.([]);
44
+ }, [commentsData, commentsError]);
34
45
  // Explicit reload: always issues a fresh, independent fetch (raw call, not
35
46
  // SWR's `mutate()` revalidate path) so a caller requesting a reload right
36
47
  // after mount isn't coalesced against the still-in-flight automatic load
37
48
  // -- then writes the result into the shared cache so useCommentsData's
38
49
  // bound hook (and the effect above) pick it up.
50
+ // A failed reload logs and keeps the threads already shown. Resolves to the reloaded threads.
39
51
  const loadComments = async (branch) => {
40
52
  if (!branch)
41
- return;
42
- const fresh = await fetchComments(apiClient, branch);
53
+ return undefined;
54
+ let fresh;
55
+ try {
56
+ fresh = await fetchCommentsSeedingUsers(apiClient, { cache, mutate: globalMutate }, branch);
57
+ }
58
+ catch (err) {
59
+ console.error('Failed to load comments:', err);
60
+ return undefined;
61
+ }
43
62
  await globalMutate(commentsKey(branch), fresh, { revalidate: false });
63
+ return fresh.threads;
44
64
  };
45
- const handleAddComment = async (text, type, entryPath, canopyPath, threadId) => {
46
- if (!options.branchName)
65
+ // Both reject on failure, so the caller keeps the person's text and shows the error where they
66
+ // wrote it. Success shows itself in the thread, so it has no toast.
67
+ const handleAddComment = async (text, type, entryPath, canopyPath, threadId, itemKeys) => {
68
+ const branch = options.branchName;
69
+ if (!branch)
47
70
  return;
48
- try {
49
- const result = await apiClient.comments.add({ branch: options.branchName }, {
50
- text,
51
- threadId,
52
- type,
53
- entryPath,
54
- canopyPath,
55
- });
56
- if (!result.ok)
57
- throw new Error('Failed to add comment');
58
- await loadComments(options.branchName);
59
- // Branch summaries auto-update via useMemo watching comments
60
- notifications.show({ message: 'Comment added', color: 'green' });
61
- }
62
- catch {
63
- notifications.show({ message: 'Failed to add comment', color: 'red' });
71
+ // What was on screen at send, so only a comment that is new since can count as this one.
72
+ const loaded = commentsData !== undefined;
73
+ const shownComments = new Set(comments.flatMap((t) => t.comments.map((c) => c.id)));
74
+ const isThis = (c) => !shownComments.has(c.id) && c.userId === options.currentUser && c.text === text;
75
+ const result = await apiClient.comments
76
+ .add({ branch }, { text, threadId, type, entryPath, canopyPath, itemKeys })
77
+ .catch((err) => (isUnanswered(err) ? 'unanswered' : null));
78
+ if (result === 'unanswered' || (result && isGatewayFailure(result))) {
79
+ // Landed, it is a new comment of theirs: in the thread replied to, or opening one here.
80
+ const reloaded = await loadComments(branch);
81
+ const posted = loaded &&
82
+ reloaded?.some((t) => threadId
83
+ ? t.id === threadId && t.comments.some(isThis)
84
+ : t.type === type &&
85
+ t.entryPath === entryPath &&
86
+ t.canopyPath === canopyPath &&
87
+ t.comments[0] !== undefined &&
88
+ isThis(t.comments[0]));
89
+ if (posted)
90
+ return;
91
+ throw new MayHaveLandedError(COMMENT_MAY_BE_ADDED);
64
92
  }
93
+ if (!result?.ok)
94
+ throw new Error(COMMENT_NOT_ADDED);
95
+ await loadComments(branch);
65
96
  };
66
97
  const handleResolveThread = async (threadId) => {
67
98
  if (!options.branchName)
68
99
  return;
69
- try {
70
- const result = await apiClient.comments.resolve({
71
- branch: options.branchName,
72
- threadId,
73
- });
74
- if (!result.ok)
75
- throw new Error('Failed to resolve thread');
76
- await loadComments(options.branchName);
77
- notifications.show({ message: 'Thread resolved', color: 'green' });
78
- }
79
- catch {
80
- notifications.show({ message: 'Failed to resolve thread', color: 'red' });
81
- }
100
+ const result = await apiClient.comments
101
+ .resolve({ branch: options.branchName, threadId })
102
+ .catch(() => null);
103
+ if (!result?.ok)
104
+ throw new Error(THREAD_NOT_RESOLVED);
105
+ await loadComments(options.branchName);
82
106
  };
83
107
  // Compute active comment threads for the thread panel
84
108
  const activeThreads = useMemo(() => {
@@ -87,7 +111,8 @@ export function useCommentSystem(options) {
87
111
  if (activeCommentContext.type === 'field' && activeCommentContext.canopyPath) {
88
112
  return comments.filter((t) => t.type === 'field' &&
89
113
  t.entryPath === options.selectedPath &&
90
- t.canopyPath === activeCommentContext.canopyPath);
114
+ t.canopyPath === activeCommentContext.canopyPath &&
115
+ !t.onRemovedItem);
91
116
  }
92
117
  else if (activeCommentContext.type === 'entry') {
93
118
  return comments.filter((t) => t.type === 'entry' && t.entryPath === options.selectedPath);
@@ -138,23 +163,19 @@ export function useCommentSystem(options) {
138
163
  currentPath === undefined ||
139
164
  !isSamePreviewPath(msg.entryPath, currentPath)))
140
165
  return;
141
- const normalizedPath = msg.fieldPath ? normalizeCanopyPath(msg.fieldPath) : undefined;
142
- const target = normalizedPath
143
- ? document.querySelector(`[data-canopy-field="${normalizedPath}"]`)
144
- : null;
145
- if (target) {
146
- target.scrollIntoView({ behavior: 'smooth', block: 'center' });
166
+ const found = typeof msg.fieldPath === 'string' ? findFieldTarget(msg.fieldPath) : undefined;
167
+ if (found) {
168
+ const target = found.element;
169
+ whenRevealed(target, () => target.scrollIntoView({ behavior: 'smooth', block: 'center' }));
147
170
  const previous = target.style.boxShadow;
148
171
  target.style.boxShadow = '0 0 0 3px rgba(79, 70, 229, 0.35)';
149
172
  later(() => {
150
173
  target.style.boxShadow = previous;
151
174
  }, 1200);
152
- // Set focused field path to trigger FieldWrapper auto-focus
153
- if (normalizedPath) {
154
- setFocusedFieldPath(normalizedPath);
155
- // Clear after brief delay to allow FieldWrapper to detect the change
156
- later(() => setFocusedFieldPath(undefined), 100);
157
- }
175
+ options.onRevealForm?.();
176
+ // Cleared shortly after, once FieldWrapper has seen it and scrolled to the field.
177
+ setFocusedFieldPath(found.path);
178
+ later(() => setFocusedFieldPath(undefined), 100);
158
179
  }
159
180
  };
160
181
  window.addEventListener('message', handleFocus);
@@ -172,10 +193,11 @@ export function useCommentSystem(options) {
172
193
  options.setSelectedPath(entryPath);
173
194
  }
174
195
  window.setTimeout(() => {
175
- const fieldElement = document.querySelector(`[data-canopy-field="${canopyPath}"]`);
176
- if (fieldElement) {
177
- fieldElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
196
+ const target = findFieldTarget(canopyPath)?.element;
197
+ if (target) {
198
+ whenRevealed(target, () => target.scrollIntoView({ behavior: 'smooth', block: 'center' }));
178
199
  }
200
+ options.onRevealForm?.();
179
201
  setFocusedFieldPath(canopyPath);
180
202
  setHighlightThreadId(threadId);
181
203
  window.setTimeout(() => {
@@ -194,6 +216,7 @@ export function useCommentSystem(options) {
194
216
  if (formElement) {
195
217
  formElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
196
218
  }
219
+ options.onRevealForm?.();
197
220
  setHighlightThreadId(threadId);
198
221
  window.setTimeout(() => {
199
222
  setHighlightThreadId(undefined);
@@ -209,6 +232,7 @@ export function useCommentSystem(options) {
209
232
  };
210
233
  return {
211
234
  comments,
235
+ getCommentUser,
212
236
  focusedFieldPath,
213
237
  setFocusedFieldPath,
214
238
  highlightThreadId,
@@ -6,23 +6,27 @@
6
6
  * its own branch-keyed effect. See useBranchesData.ts for the same pattern
7
7
  * applied to the branches list.
8
8
  */
9
- import { type SWRResponse } from 'swr';
9
+ import { type Cache, type ScopedMutator, type SWRResponse } from 'swr';
10
10
  import type { ApiClient } from '../context/index.js';
11
11
  import type { CommentThread } from '../../comment-store.js';
12
+ import type { UserProfile } from '../../auth/types.js';
12
13
  /** Cache key for a branch's comment threads. */
13
14
  export declare const commentsKey: (branch: string) => string;
14
15
  export interface CommentsData {
15
16
  threads: CommentThread[];
17
+ /** Who wrote or resolved `threads`: name and avatar, never email. */
18
+ users: UserProfile[];
16
19
  }
17
20
  /**
18
- * Fetch a branch's comment threads. Never throws -- matches the pre-SWR
19
- * `loadComments` behavior of logging and resolving to an empty list on
20
- * failure rather than surfacing an error state (comments have no error UI).
21
- * Exported for direct testing and for the imperative reload path.
21
+ * {@link fetchComments}, with the users it names written into the user-metadata cache before the
22
+ * threads that show them land, so their badges render named.
22
23
  */
23
- export declare function fetchComments(apiClient: Pick<ApiClient, 'comments'>, branch: string): Promise<CommentsData>;
24
+ export declare function fetchCommentsSeedingUsers(apiClient: Pick<ApiClient, 'comments'>, swr: {
25
+ cache: Cache;
26
+ mutate: ScopedMutator;
27
+ }, branch: string): Promise<CommentsData>;
24
28
  /**
25
29
  * SWR-backed read of a branch's comment threads. `branch` may be empty
26
30
  * (branchless start), in which case fetching is disabled entirely (null key).
27
31
  */
28
- export declare function useCommentsData(apiClient: Pick<ApiClient, 'comments'>, branch: string): SWRResponse<CommentsData, never>;
32
+ export declare function useCommentsData(apiClient: Pick<ApiClient, 'comments'>, branch: string): SWRResponse<CommentsData, unknown>;
@@ -7,33 +7,34 @@
7
7
  * its own branch-keyed effect. See useBranchesData.ts for the same pattern
8
8
  * applied to the branches list.
9
9
  */
10
- import useSWR from 'swr';
10
+ import useSWR, { useSWRConfig } from 'swr';
11
+ import { seedUserProfiles } from './useUserMetadata.js';
11
12
  /** Cache key for a branch's comment threads. */
12
13
  export const commentsKey = (branch) => `canopy:comments:${branch}`;
13
14
  /**
14
- * Fetch a branch's comment threads. Never throws -- matches the pre-SWR
15
- * `loadComments` behavior of logging and resolving to an empty list on
16
- * failure rather than surfacing an error state (comments have no error UI).
17
- * Exported for direct testing and for the imperative reload path.
15
+ * A branch's comment threads. Rejects when they can't be read, so a failed reload leaves the
16
+ * threads already shown in place rather than emptying them.
18
17
  */
19
- export async function fetchComments(apiClient, branch) {
20
- try {
21
- const result = await apiClient.comments.list({ branch });
22
- if (!result.ok) {
23
- console.error('Failed to load comments:', result.status);
24
- return { threads: [] };
25
- }
26
- return { threads: result.data?.threads ?? [] };
27
- }
28
- catch (err) {
29
- console.error('Failed to load comments:', err);
30
- return { threads: [] };
31
- }
18
+ async function fetchComments(apiClient, branch) {
19
+ const result = await apiClient.comments.list({ branch });
20
+ if (!result.ok)
21
+ throw new Error(`Failed to load comments (HTTP ${result.status})`);
22
+ return { threads: result.data?.threads ?? [], users: result.data?.users ?? [] };
23
+ }
24
+ /**
25
+ * {@link fetchComments}, with the users it names written into the user-metadata cache before the
26
+ * threads that show them land, so their badges render named.
27
+ */
28
+ export async function fetchCommentsSeedingUsers(apiClient, swr, branch) {
29
+ const data = await fetchComments(apiClient, branch);
30
+ await seedUserProfiles(swr, data.users);
31
+ return data;
32
32
  }
33
33
  /**
34
34
  * SWR-backed read of a branch's comment threads. `branch` may be empty
35
35
  * (branchless start), in which case fetching is disabled entirely (null key).
36
36
  */
37
37
  export function useCommentsData(apiClient, branch) {
38
- return useSWR(branch ? commentsKey(branch) : null, () => fetchComments(apiClient, branch));
38
+ const { cache, mutate } = useSWRConfig();
39
+ return useSWR(branch ? commentsKey(branch) : null, () => fetchCommentsSeedingUsers(apiClient, { cache, mutate }, branch), { onError: (err) => console.error('Failed to load comments:', err) });
39
40
  }
@@ -1,6 +1,24 @@
1
1
  import type { EditorEntry } from '../Editor.js';
2
2
  import type { LogicalPath } from '../../paths/types.js';
3
3
  import type { FormValue } from '../FormRenderer.js';
4
+ import type { StampedEntry } from '../../stamp-on-publish.js';
5
+ import { type SaveAllProgress, type SaveAllResult } from './save-all.js';
6
+ /** @internal Exported for tests. */
7
+ export declare const SAVE_TIMED_OUT_MESSAGE = "Save didn't finish, and may not have gone through. Your changes are still here, so save again.";
8
+ /** @internal Exported for tests. Shown when a save may already have landed, until a reload. */
9
+ export declare const SAVE_MAY_HAVE_LANDED_MESSAGE = "Your last save may already have gone through. Before saving again, choose \"Refresh from server\" in the entry's menu, on its name; your unsaved edits will be lost.";
10
+ /** @internal Exported for tests. A save refused because the entry was deleted. */
11
+ export declare const ENTRY_DELETED_MESSAGE = "This entry was deleted since you opened it, so it was not saved. Your changes are still in the form until the content list next refreshes and closes it: choose \"Save as new entry\" to keep them.";
12
+ /** @internal Exported for tests. A save refused because the entry was renamed; the editor has opened it. */
13
+ export declare const ENTRY_RENAMED_MESSAGE = "This entry was renamed since you opened it, so it was not saved. Your changes moved with it and are still in the form: save again to keep them.";
14
+ /** @internal Exported for tests. "Save as new entry" refused because an entry, possibly the user's own earlier attempt, now holds the path. */
15
+ export declare const RECREATE_TAKEN_MESSAGE = "An entry with this entry's name already exists, perhaps from your own earlier attempt, so it was not saved as a new entry. Your changes are still in the form: copy what you want to keep into that entry.";
16
+ /** @internal Exported for tests. The save was refused as gone, and the check for a rename failed. */
17
+ export declare const ENTRY_GONE_UNCHECKED_MESSAGE = "This entry was deleted or renamed since you opened it, so it was not saved, and the editor could not check which. Your changes are still in the form until the content list next refreshes and closes it: copy what you want to keep.";
18
+ /** @internal Exported for tests. "Save as new entry" landed, but the content list does not show it yet. */
19
+ export declare const RECREATED_NOT_LISTED_MESSAGE = "Saved as a new entry, but the content list doesn't show it yet. Reload the page in a moment to open it.";
20
+ /** @internal Exported for tests. "Save as new entry" got no answer. */
21
+ export declare const RECREATE_TIMED_OUT_MESSAGE = "Saving as a new entry may have gone through even though the server didn't answer. Choose \"Save as new entry\" to try again: if it went through, you'll be told an entry with this name already exists.";
4
22
  export interface UseDraftManagerOptions {
5
23
  branchName: string;
6
24
  selectedPath: string;
@@ -8,6 +26,12 @@ export interface UseDraftManagerOptions {
8
26
  entries: EditorEntry[];
9
27
  initialValues?: Record<string, FormValue>;
10
28
  loadEntry: (entry: EditorEntry) => Promise<FormValue>;
29
+ /**
30
+ * Server read that records no OCC token (useEntryManager's `readEntryValue`),
31
+ * for checking restored drafts of unopened entries. Without it they stay
32
+ * unverified and count as dirty.
33
+ */
34
+ readEntryValue?: (entry: EditorEntry) => Promise<FormValue>;
11
35
  saveEntry: (entry: EditorEntry, value: FormValue) => Promise<FormValue>;
12
36
  /**
13
37
  * The OCC version token currently held for an entry on the branch being
@@ -17,6 +41,8 @@ export interface UseDraftManagerOptions {
17
41
  * conflict detection falls back entirely to saveEntry's token check.
18
42
  */
19
43
  getEntryVersion?: (contentId: string) => number | undefined;
44
+ /** Holds a version the server moved an entry to itself (useEntryManager's `adoptEntryVersion`). */
45
+ adoptEntryVersion?: (contentId: string, version: number) => void;
20
46
  setBusy: (busy: boolean) => void;
21
47
  /**
22
48
  * Fired (fire-and-forget) after a successful save. Lets callers refresh
@@ -25,6 +51,23 @@ export interface UseDraftManagerOptions {
25
51
  * instead of the stale label from the last entries fetch.
26
52
  */
27
53
  onSaved?: () => void;
54
+ /** A save was refused for field errors, which the form now shows. */
55
+ onSaveBlocked?: () => void;
56
+ /**
57
+ * Fired when drafts are thrown away for the server's copy: Discard (one entry, or every entry
58
+ * when `contentId` is undefined) and Reload. Anything built on the discarded draft, such as an
59
+ * Undo, no longer applies.
60
+ */
61
+ onDraftsReset?: (contentId?: string) => void;
62
+ /** Finds an entry a save reported gone under its new name (useEntryManager's `followMovedEntry`). */
63
+ followMovedEntry?: (entry: EditorEntry) => Promise<EditorEntry | undefined>;
64
+ /** Creates a deleted entry again from its draft (useEntryManager's `recreateEntry`). */
65
+ recreateEntry?: (entry: EditorEntry, value: FormValue) => Promise<EditorEntry | undefined>;
66
+ }
67
+ /** The unsaved work a branch-level action would leave behind. `labels` names the entries (it may be shorter than `count`). */
68
+ export interface UnsavedSummary {
69
+ count: number;
70
+ labels: string[];
28
71
  }
29
72
  export interface UseDraftManagerReturn {
30
73
  drafts: Record<string, FormValue>;
@@ -40,12 +83,39 @@ export interface UseDraftManagerReturn {
40
83
  label: string;
41
84
  }>;
42
85
  handleSave: () => Promise<void>;
43
- handleDiscardDrafts: () => void;
44
- handleDiscardFileDraft: () => void;
45
- handleReload: () => Promise<void>;
86
+ /** The entry a single Save is writing, while it is in flight. */
87
+ singleSaving: {
88
+ branch: string;
89
+ contentId: string;
90
+ } | null;
91
+ /** The last Save that landed; its `seq` rises with each, and the Save button says "Saved". */
92
+ lastSaved: {
93
+ branch: string;
94
+ contentId: string;
95
+ seq: number;
96
+ } | null;
97
+ /**
98
+ * Saves every entry with unsaved changes on the branch, one at a time. Undefined when a run or
99
+ * a single Save is already in flight, or the branch changed or the editor unmounted meanwhile.
100
+ */
101
+ handleSaveAll: () => Promise<SaveAllResult | undefined>;
102
+ /** Set while Save all runs. */
103
+ saveAllProgress: SaveAllProgress | null;
104
+ /** Whether Save all is running now, read at the moment of a click rather than a render. */
105
+ isSaveAllRunning: () => boolean;
106
+ handleDiscardDrafts: (returnFocusTo?: () => HTMLElement | null) => void;
107
+ /** `announce` toasts the discard, for a draft the form isn't showing (a read-only branch's). */
108
+ handleDiscardFileDraft: (returnFocusTo?: () => HTMLElement | null, options?: {
109
+ announce?: boolean;
110
+ }) => void;
111
+ handleReload: (returnFocusTo?: () => HTMLElement | null) => Promise<void>;
46
112
  isDirtyForEntry: (entryPath: string) => boolean;
47
113
  isSelectedDirty: () => boolean;
48
114
  isAnyDirty: () => boolean;
115
+ /** Resolves once restored drafts have been checked against the server (or a read failed), capped so a hung read cannot block. */
116
+ whenDraftsVerified: () => Promise<void>;
117
+ /** `whenDraftsVerified`, then the entries still counted dirty. */
118
+ resolveUnsaved: () => Promise<UnsavedSummary>;
49
119
  /**
50
120
  * Per-field validation errors for the selected entry, keyed by canonical
51
121
  * canopy path (e.g. `blocks[0].title`). Populated when a save is blocked by
@@ -54,6 +124,10 @@ export interface UseDraftManagerReturn {
54
124
  * errors disappear as fields are fixed.
55
125
  */
56
126
  fieldErrors: Record<string, string>;
127
+ /** True while the last write of drafts to localStorage failed. */
128
+ draftStorageFailed: boolean;
129
+ /** Moves loaded values, tokens and drafts onto the versions a submit's stamps left. */
130
+ applySubmitStamps: (stamped: readonly StampedEntry[]) => void;
57
131
  }
58
132
  /**
59
133
  * Custom hook for managing draft state (localStorage persistence, save/discard).