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
@@ -1,87 +1,103 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React, { useId, useMemo, useState } from 'react';
4
- let blockKeyCounter = 0;
5
- import { ActionIcon, Button, Group, Paper, Select, Stack, Text } from '@mantine/core';
6
- import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, } from '@dnd-kit/core';
7
- import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
8
- import { CSS } from '@dnd-kit/utilities';
3
+ import React, { useId, useRef, useState } from 'react';
4
+ import { ActionIcon, Box, Button, Group, Menu, Paper, ScrollArea, Stack, Text, Tooltip, } from '@mantine/core';
5
+ import { useMediaQuery } from '@mantine/hooks';
6
+ import { IconPlus } from '@tabler/icons-react';
7
+ import { ITEM_KEY, mintItemKey, withFreshItemKeys } from '../../item-keys.js';
8
+ import { isPlainRecord } from '../../validation/field-traversal.js';
9
9
  import { formatCanopyPath } from '../canopy-path.js';
10
- import { FieldDescription, groupDescriptionProps } from './FieldDescription.js';
10
+ import { useFieldCommentControl } from '../comments/field-comment-context.js';
11
+ import { ExpandAllButton } from './ExpandAllButton.js';
12
+ import { groupDescriptionProps } from './FieldDescription.js';
13
+ import { FieldLabel } from './FieldLabel.js';
14
+ import { ItemList } from './ItemList.js';
15
+ import { useItemExpansion } from './item-expansion.js';
16
+ import { useListItemKeys } from './list-item-keys.js';
17
+ import { listItemSecondary } from './list-item-title.js';
18
+ import { schemaLabel } from '../schema-label.js';
11
19
  const findTemplate = (templates, name) => templates.find((t) => t.name === name);
12
- const SortableBlock = ({ id, children }) => {
13
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
14
- id,
15
- });
16
- const style = {
17
- transform: CSS.Transform.toString(transform),
18
- transition,
19
- opacity: isDragging ? 0.85 : 1,
20
- };
21
- return (_jsx(Paper, { ref: setNodeRef, withBorder: true, radius: "md", p: "sm", shadow: "xs", style: style, children: _jsxs(Group, { align: "flex-start", gap: "sm", children: [_jsx(ActionIcon, { variant: "subtle", "aria-label": "Drag to reorder", ...attributes, ...listeners, style: { cursor: 'grab' }, children: "\u21C5" }, "drag-handle"), _jsx("div", { style: { flex: 1, minWidth: 0, width: '100%' }, children: children }, "content")] }) }));
20
+ const ADD_SECTION = 'Add section';
21
+ /**
22
+ * The block templates as a menu, each with its description, so an editor picks a section by
23
+ * what it is for. `target` is the control that opens it.
24
+ */
25
+ const TemplateMenu = ({ templates, onPick, onOpenChange, target }) => (_jsxs(Menu, { position: "bottom-start", withinPortal: true, shadow: "md", width: 320, onChange: onOpenChange, children: [target, _jsx(Menu.Dropdown, { "data-testid": "block-template-menu", children: _jsx(ScrollArea.Autosize, { mah: 360, type: "auto", children: templates.map((template) => (_jsxs(Menu.Item, { onClick: () => onPick(template.name), "data-testid": `block-template-${template.name}`, children: [_jsx(Text, { size: "sm", fw: 500, children: schemaLabel(template) }), template.description && (_jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: 'normal' }, children: template.description }))] }, template.name))) }) })] }));
26
+ /**
27
+ * The gap before a block. Its add control shows while the gap is hovered, the control is focused
28
+ * or its menu is open, and stays in the tab order, so a keyboard reaches it before each block.
29
+ */
30
+ const InsertBetween = ({ templates, onPick }) => {
31
+ const [hovered, setHovered] = useState(false);
32
+ const [focused, setFocused] = useState(false);
33
+ const [opened, setOpened] = useState(false);
34
+ // A touch screen has no hover, so the control stays faintly visible there.
35
+ const noHover = useMediaQuery('(hover: none)');
36
+ const shown = hovered || focused || opened;
37
+ const opacity = shown ? 1 : noHover ? 0.6 : 0;
38
+ return (_jsxs(Box, { h: 20, pos: "relative", onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), "data-testid": "block-insert-between", children: [_jsx(Box, { "aria-hidden": true, pos: "absolute", left: 0, right: 0, top: "50%", h: 2, bg: "var(--mantine-primary-color-filled)", style: { opacity: shown ? 1 : 0, transition: 'opacity 120ms ease' } }), _jsx(Group, { justify: "center", h: "100%", style: { position: 'relative' }, children: _jsx(TemplateMenu, { templates: templates, onPick: onPick, onOpenChange: setOpened, target: _jsx(Tooltip, { label: "Add section here", openDelay: 300, children: _jsx(Menu.Target, { children: _jsx(ActionIcon, { size: "sm", radius: "xl", variant: "default", "aria-label": "Add section here", onFocus: () => setFocused(true), onBlur: () => setFocused(false), style: { opacity, transition: 'opacity 120ms ease' }, children: _jsx(IconPlus, { size: 14, "aria-hidden": true }) }) }) }) }) })] }));
22
39
  };
23
- export const BlockField = ({ label, description, templates, value, onChange, renderField, path, dataCanopyField, }) => {
40
+ export const BlockField = ({ label, required, description, templates, value, onChange, renderField, path, dataCanopyField, readOnly = false, resetKey = '', hasErrors, onRemoved, }) => {
24
41
  const descriptionBaseId = useId();
25
- const [itemKeys, setItemKeys] = useState(() => value.map(() => `block-${blockKeyCounter++}`));
26
- const [pendingTemplate, setPendingTemplate] = useState(null);
27
- // Keeps itemKeys in sync with value's length; setState runs directly in render, not an effect.
28
- if (value.length > itemKeys.length) {
29
- const extras = Array.from({ length: value.length - itemKeys.length }, () => `block-${blockKeyCounter++}`);
30
- setItemKeys((prev) => [...prev, ...extras]);
31
- }
32
- else if (value.length < itemKeys.length) {
33
- setItemKeys((prev) => prev.slice(0, value.length));
34
- }
35
- const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }), useSensor(KeyboardSensor, {
36
- coordinateGetter: sortableKeyboardCoordinates,
37
- }));
38
- const addBlock = (templateName) => {
39
- const template = findTemplate(templates, templateName);
40
- if (!template)
41
- return;
42
- onChange([...value, { template: templateName, value: {} }]);
43
- setItemKeys((prev) => [
44
- ...prev,
45
- `block-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
46
- ]);
42
+ const commentControl = useFieldCommentControl(dataCanopyField ?? formatCanopyPath(path));
43
+ const keysFor = useListItemKeys();
44
+ const itemKeys = keysFor(value, 'blocks');
45
+ const expansion = useItemExpansion(itemKeys, resetKey);
46
+ const focusAfterRenderRef = useRef(null);
47
+ const emit = (next) => {
48
+ if (!readOnly)
49
+ onChange(next);
47
50
  };
48
- const moveBlock = (from, to) => {
49
- if (from === to || from < 0 || to < 0 || from >= value.length || to >= value.length)
50
- return;
51
- onChange(arrayMove(value, from, to));
52
- setItemKeys((prev) => arrayMove(prev, from, to));
51
+ const insertAt = (index, block) => {
52
+ focusAfterRenderRef.current = index;
53
+ emit([...value.slice(0, index), block, ...value.slice(index)]);
53
54
  };
54
- const removeBlock = (index) => {
55
- onChange(value.filter((_, idx) => idx !== index));
56
- setItemKeys((prev) => prev.filter((_, idx) => idx !== index));
55
+ const addAt = (index) => (templateName) => {
56
+ if (findTemplate(templates, templateName))
57
+ insertAt(index, { template: templateName, value: {}, [ITEM_KEY]: mintItemKey() });
57
58
  };
58
59
  const updateBlockValue = (index, val) => {
59
60
  const next = [...value];
60
61
  next[index] = { ...next[index], value: val };
61
- onChange(next);
62
- };
63
- const handleDragEnd = (event) => {
64
- const { active, over } = event;
65
- if (!over || active.id === over.id)
66
- return;
67
- const oldIndex = itemKeys.indexOf(String(active.id));
68
- const newIndex = itemKeys.indexOf(String(over.id));
69
- if (oldIndex === -1 || newIndex === -1)
70
- return;
71
- moveBlock(oldIndex, newIndex);
62
+ emit(next);
72
63
  };
73
- const selectableTemplates = useMemo(() => templates.map((t) => ({ value: t.name, label: t.label ?? t.name })), [templates]);
74
- return (_jsx(Paper, { withBorder: true, radius: "md", p: "md", bg: "gray.0", "data-canopy-field": dataCanopyField ?? formatCanopyPath(path), shadow: "xs", ...groupDescriptionProps(descriptionBaseId, description), children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Group, { justify: "space-between", children: [_jsx(Text, { size: "xs", fw: 700, c: "dimmed", children: label ?? 'Blocks' }), _jsx(Select, { "aria-label": "Add block", placeholder: "Add block...", data: selectableTemplates, value: pendingTemplate, onChange: (next) => {
75
- if (next) {
76
- addBlock(next);
77
- }
78
- setPendingTemplate(null);
79
- }, allowDeselect: true, size: "xs", w: 180 })] }), _jsx(FieldDescription, { baseId: descriptionBaseId, description: description }), _jsx(DndContext, { sensors: sensors, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: itemKeys, strategy: verticalListSortingStrategy, children: _jsx(Stack, { gap: "sm", children: value.map((block, idx) => {
80
- const template = findTemplate(templates, block.template);
81
- const currentPath = [...path, idx];
82
- return (_jsx(SortableBlock, { id: itemKeys[idx], children: _jsxs(Stack, { gap: "xs", children: [_jsxs(Group, { justify: "space-between", align: "flex-start", children: [_jsx(Text, { size: "sm", fw: 600, children: template?.label ?? block.template ?? 'Unknown block' }), _jsxs(Group, { gap: 4, children: [_jsx(ActionIcon, { variant: "light", "aria-label": "Move block up", disabled: idx === 0, onClick: () => moveBlock(idx, idx - 1), children: "\u2191" }), _jsx(ActionIcon, { variant: "light", "aria-label": "Move block down", disabled: idx === value.length - 1, onClick: () => moveBlock(idx, idx + 1), children: "\u2193" }), _jsx(Button, { variant: "subtle", color: "red", size: "xs", onClick: () => removeBlock(idx), children: "Remove" })] })] }), template ? (_jsx(Stack, { gap: "sm", children: template.fields.map((f) => (_jsx(React.Fragment, { children: renderField(f, block.value?.[f.name], (next) => updateBlockValue(idx, {
83
- ...block.value,
84
- [f.name]: next,
85
- }), [...currentPath, f.name]) }, f.name))) })) : (_jsxs(Text, { size: "xs", c: "red", children: ["No template found for \"", block.template, "\""] }))] }) }, itemKeys[idx]));
86
- }) }) }) })] }) }));
64
+ return (_jsx(Paper, { withBorder: true, p: "md", bg: "var(--canopy-surface-subtle)", "data-canopy-field": dataCanopyField ?? formatCanopyPath(path), role: "group", "aria-label": label ?? 'Blocks', "data-removal-focus": true, tabIndex: -1, shadow: "xs", ...groupDescriptionProps(descriptionBaseId, description), children: _jsxs(Stack, { gap: "sm", children: [_jsx(FieldLabel, { label: label ?? 'Blocks', required: required, description: description, descriptionBaseId: descriptionBaseId, commentControl: commentControl, actions: value.length > 1 && _jsx(ExpandAllButton, { expansion: expansion }) }), _jsx(ItemList, { items: value, itemKeys: itemKeys, path: path, readOnly: readOnly, expansion: expansion, focusAfterRenderRef: focusAfterRenderRef, hasErrors: hasErrors, summarize: (block) => {
65
+ const template = findTemplate(templates, block.template);
66
+ return {
67
+ title: template ? schemaLabel(template) : (block.template ?? 'Unknown block'),
68
+ secondary: template ? listItemSecondary(block.value, template.fields) : undefined,
69
+ };
70
+ }, describe: (block) => findTemplate(templates, block.template)?.description, onMove: (from, to) => {
71
+ if (from === to || to < 0 || to >= value.length)
72
+ return;
73
+ const next = [...value];
74
+ const [moved] = next.splice(from, 1);
75
+ next.splice(to, 0, moved);
76
+ emit(next);
77
+ }, onDuplicate: (idx) =>
78
+ // Focus stays on the row's menu, which stands in for the item that acted. The copy
79
+ // gets new keys, so no comment thread follows it.
80
+ emit([
81
+ ...value.slice(0, idx + 1),
82
+ withFreshItemKeys({ type: 'block', name: 'blocks', templates }, structuredClone(value[idx])),
83
+ ...value.slice(idx + 1),
84
+ ]), onRemove: (idx) => {
85
+ if (readOnly)
86
+ return;
87
+ const block = value[idx];
88
+ emit(value.filter((_, i) => i !== idx));
89
+ onRemoved?.(idx, block);
90
+ }, renderBetween: readOnly
91
+ ? undefined
92
+ : (idx) => _jsx(InsertBetween, { templates: templates, onPick: addAt(idx) }), renderItem: (block, idx) => {
93
+ const template = findTemplate(templates, block.template);
94
+ const currentPath = [...path, idx];
95
+ if (!template) {
96
+ return (_jsxs(Text, { size: "sm", c: "var(--canopy-danger-text)", children: ["No template found for \"", block.template, "\""] }));
97
+ }
98
+ return template.fields.map((f) => (_jsx(React.Fragment, { children: renderField(f, block.value?.[f.name], (next) => updateBlockValue(idx, {
99
+ ...(isPlainRecord(block.value) ? block.value : {}),
100
+ [f.name]: next,
101
+ }), [...currentPath, f.name]) }, f.name)));
102
+ } }), value.length === 0 && (_jsx(Text, { size: "sm", c: "dimmed", children: readOnly ? 'No sections.' : 'No sections yet.' })), !readOnly && (_jsx(Group, { children: _jsx(TemplateMenu, { templates: templates, onPick: addAt(value.length), target: _jsx(Menu.Target, { children: _jsx(Button, { variant: "light", size: "xs", leftSection: _jsx(IconPlus, { size: 14, "aria-hidden": true }), "data-testid": "block-add-section", children: ADD_SECTION }) }) }) }))] }) }));
87
103
  };
@@ -7,5 +7,7 @@ export interface CodeFieldProps {
7
7
  onChange: (value: string) => void;
8
8
  language?: string;
9
9
  dataCanopyField?: string;
10
+ /** Shows the value without accepting edits. */
11
+ readOnly?: boolean;
10
12
  }
11
13
  export declare const CodeField: React.FC<CodeFieldProps>;
@@ -1,9 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useId } from 'react';
3
3
  import { Textarea } from '@mantine/core';
4
+ import { LabelledInput } from './FieldLabel.js';
4
5
  // Placeholder for Monaco integration; host app can provide custom renderer for production.
5
- export const CodeField = ({ id, label, description, value, onChange, language, dataCanopyField, }) => {
6
+ export const CodeField = ({ id, label, description, value, onChange, language, dataCanopyField, readOnly = false, }) => {
6
7
  const generatedId = useId();
7
8
  const inputId = id ?? generatedId;
8
- return (_jsx(Textarea, { id: inputId, label: label, description: description, value: value, onChange: (e) => onChange(e.currentTarget.value), placeholder: language ? `Code (${language})` : 'Code', autosize: true, minRows: 6, size: "sm", "data-canopy-field": dataCanopyField, styles: { input: { fontFamily: 'Menlo, Consolas, monospace' } } }));
9
+ return (_jsx(LabelledInput, { label: label, inputId: inputId, canopyPath: dataCanopyField, children: _jsx(Textarea, { id: inputId, description: description, value: value, readOnly: readOnly, onChange: (e) => {
10
+ if (!readOnly)
11
+ onChange(e.currentTarget.value);
12
+ }, placeholder: language ? `Code (${language})` : 'Code', autosize: true, minRows: 6, size: "sm", "data-canopy-field": dataCanopyField, styles: { input: { fontFamily: 'Menlo, Consolas, monospace' } } }) }));
9
13
  };
@@ -6,34 +6,9 @@ export interface DateTimeFieldProps {
6
6
  value: string;
7
7
  onChange: (value: string) => void;
8
8
  dataCanopyField?: string;
9
+ /** Shows the value without accepting edits. */
10
+ readOnly?: boolean;
11
+ /** The field's `stampOnPublish`: the description says when a submit fills it. */
12
+ stampOnPublish?: boolean;
9
13
  }
10
- /**
11
- * Converts a stored value (ISO 8601 UTC, e.g. `YYYY-MM-DDTHH:mm:ss.sssZ`)
12
- * into the local wall-clock string a `datetime-local` input expects
13
- * (`YYYY-MM-DDTHH:mm:ss`, no timezone). Returns '' for '' or an unparsable value.
14
- * @internal Exported for tests.
15
- */
16
- export declare function isoToDatetimeLocalValue(iso: string): string;
17
- /**
18
- * Convert a `datetime-local` input's local wall-clock string back into the
19
- * ISO 8601 UTC storage format. Returns '' for '' or an unparsable value.
20
- * @internal Exported for tests.
21
- */
22
- export declare function datetimeLocalValueToIso(local: string): string;
23
- /**
24
- * Editor for `type: 'datetime'` fields.
25
- *
26
- * Storage format: ISO 8601 UTC string (e.g. `YYYY-MM-DDTHH:mm:ss.sssZ`) — what
27
- * `Date.prototype.toISOString()` produces and `validation/entry-validator.ts`'s
28
- * datetime check (`Date.parse`) accepts. Empty string means "not set".
29
- *
30
- * Uses a native `datetime-local` input in Mantine's `Input.Wrapper` rather than
31
- * `@mantine/dates` (not a dependency here) — a real picker with zero new deps.
32
- *
33
- * `datetime-local` has no timezone: converts UTC ISO -> local for display and
34
- * back on change, so an unedited load-then-save round-trips exactly instead of
35
- * drifting by the browser's offset. `step={1}` preserves seconds in that
36
- * round-trip; sub-second precision is not preserved (no milliseconds field),
37
- * so a value with non-zero milliseconds is zeroed out once resaved.
38
- */
39
14
  export declare const DateTimeField: React.FC<DateTimeFieldProps>;
@@ -1,56 +1,94 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useId } from 'react';
3
- import { Input } from '@mantine/core';
2
+ import { useId, useRef } from 'react';
3
+ import { ActionIcon, Tooltip } from '@mantine/core';
4
+ import { DateTimePicker } from '@mantine/dates';
5
+ import { IconX } from '@tabler/icons-react';
6
+ import dayjs from 'dayjs';
7
+ import { LabelledInput } from './FieldLabel.js';
8
+ /** Whether the locale uses a 12-hour clock, as the dropdown's native time input then does. */
9
+ const usesTwelveHourClock = () => {
10
+ const { hour12, hourCycle } = new Intl.DateTimeFormat(undefined, {
11
+ hour: 'numeric',
12
+ }).resolvedOptions();
13
+ return hour12 ?? (hourCycle === 'h11' || hourCycle === 'h12');
14
+ };
15
+ const valueFormat = () => `D MMM YYYY, ${usesTwelveHourClock() ? 'h:mm:ss A' : 'HH:mm:ss'}`;
16
+ const REMOVE_LABEL = 'Remove date and time';
17
+ // The picker's own controls are icon-only or unlabelled without these.
18
+ const CALENDAR_LABELS = {
19
+ previousMonth: 'Previous month',
20
+ nextMonth: 'Next month',
21
+ previousYear: 'Previous year',
22
+ nextYear: 'Next year',
23
+ previousDecade: 'Previous decade',
24
+ nextDecade: 'Next decade',
25
+ monthLevelControl: 'Choose a month',
26
+ yearLevelControl: 'Choose a year',
27
+ };
28
+ const DATE_PART = /^(\d{4})-(\d{2})-(\d{2})([Tt ]|$)/;
29
+ /** Whether the written year, month and day name a real day; `Date` rolls 30 Feb on to 1 Mar. */
30
+ const isCalendarDate = (year, month, day) => {
31
+ const lastOfMonth = new Date(0);
32
+ lastOfMonth.setUTCFullYear(year, month, 0);
33
+ return month >= 1 && month <= 12 && day >= 1 && day <= lastOfMonth.getUTCDate();
34
+ };
4
35
  /**
5
- * Converts a stored value (ISO 8601 UTC, e.g. `YYYY-MM-DDTHH:mm:ss.sssZ`)
6
- * into the local wall-clock string a `datetime-local` input expects
7
- * (`YYYY-MM-DDTHH:mm:ss`, no timezone). Returns '' for '' or an unparsable value.
8
- * @internal Exported for tests.
36
+ * The stored value as a Date, or null for '', an unparsable value or a day that does not exist. A
37
+ * date-only value is local midnight; `Date` reads UTC midnight, the evening before west of UTC.
9
38
  */
10
- export function isoToDatetimeLocalValue(iso) {
39
+ const toDate = (iso) => {
11
40
  if (!iso)
12
- return '';
41
+ return null;
42
+ const datePart = DATE_PART.exec(iso);
43
+ if (datePart) {
44
+ const [year, month, day] = datePart.slice(1, 4).map(Number);
45
+ if (!isCalendarDate(year, month, day))
46
+ return null;
47
+ if (datePart[4] === '') {
48
+ // setFullYear, since the constructor maps years 0-99 to 1900-1999.
49
+ const local = new Date(0);
50
+ local.setFullYear(year, month - 1, day);
51
+ local.setHours(0, 0, 0, 0);
52
+ return local;
53
+ }
54
+ }
13
55
  const date = new Date(iso);
14
- if (Number.isNaN(date.getTime()))
15
- return '';
16
- const pad = (n) => String(n).padStart(2, '0');
17
- const base = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +
18
- `T${pad(date.getHours())}:${pad(date.getMinutes())}`;
19
- // Seconds are included only when non-zero, matching a real browser's own
20
- // `datetime-local` serialization, so the value we set agrees with what the control reports back.
21
- return date.getSeconds() === 0 ? base : `${base}:${pad(date.getSeconds())}`;
22
- }
23
- /**
24
- * Convert a `datetime-local` input's local wall-clock string back into the
25
- * ISO 8601 UTC storage format. Returns '' for '' or an unparsable value.
26
- * @internal Exported for tests.
27
- */
28
- export function datetimeLocalValueToIso(local) {
29
- if (!local)
30
- return '';
31
- const date = new Date(local);
32
- if (Number.isNaN(date.getTime()))
33
- return '';
34
- return date.toISOString();
35
- }
56
+ return Number.isNaN(date.getTime()) ? null : date;
57
+ };
58
+ /** The browser's zone as it abbreviates it ("MDT"), which the field shows times in. */
59
+ const zoneName = (at) => new Intl.DateTimeFormat(undefined, { timeZoneName: 'short' })
60
+ .formatToParts(at)
61
+ .find((part) => part.type === 'timeZoneName')?.value;
36
62
  /**
37
- * Editor for `type: 'datetime'` fields.
63
+ * Editor for `type: 'datetime'` fields, a Mantine `DateTimePicker` in the browser's time zone,
64
+ * which its description names.
38
65
  *
39
66
  * Storage format: ISO 8601 UTC string (e.g. `YYYY-MM-DDTHH:mm:ss.sssZ`) — what
40
67
  * `Date.prototype.toISOString()` produces and `validation/entry-validator.ts`'s
41
68
  * datetime check (`Date.parse`) accepts. Empty string means "not set".
42
69
  *
43
- * Uses a native `datetime-local` input in Mantine's `Input.Wrapper` rather than
44
- * `@mantine/dates` (not a dependency here) — a real picker with zero new deps.
45
- *
46
- * `datetime-local` has no timezone: converts UTC ISO -> local for display and
47
- * back on change, so an unedited load-then-save round-trips exactly instead of
48
- * drifting by the browser's offset. `step={1}` preserves seconds in that
49
- * round-trip; sub-second precision is not preserved (no milliseconds field),
50
- * so a value with non-zero milliseconds is zeroed out once resaved.
70
+ * Only a pick or Remove writes, so a loaded value, date-only or unparsable, saves back unchanged.
71
+ * A pick keeps seconds (`withSeconds`).
51
72
  */
52
- export const DateTimeField = ({ id, label, description, value, onChange, dataCanopyField, }) => {
73
+ /** Conditional: the editor cannot tell whether an entry is new to the base, and only a new one is stamped. */
74
+ const STAMP_NOTE = "If left empty on a new entry, it's set to the time its branch is first submitted for review.";
75
+ export const DateTimeField = ({ id, label, description, value, onChange, dataCanopyField, readOnly = false, stampOnPublish = false, }) => {
53
76
  const generatedId = useId();
54
77
  const inputId = id ?? generatedId;
55
- return (_jsx(Input.Wrapper, { id: inputId, label: label, description: description, size: "sm", children: _jsx(Input, { type: "datetime-local", step: 1, size: "sm", value: isoToDatetimeLocalValue(value), onChange: (e) => onChange(datetimeLocalValueToIso(e.currentTarget.value)), "data-canopy-field": dataCanopyField }) }));
78
+ const triggerRef = useRef(null);
79
+ const date = toDate(value);
80
+ const zone = zoneName(date ?? new Date());
81
+ const zoneNote = zone ? `In your time zone (${zone}).` : undefined;
82
+ const stampNote = stampOnPublish ? STAMP_NOTE : undefined;
83
+ const format = valueFormat();
84
+ return (_jsx(LabelledInput, { label: label, inputId: inputId, canopyPath: dataCanopyField, children: _jsx(DateTimePicker, { ref: triggerRef, id: inputId, "aria-label": `${label ?? 'Date and time'}, ${date ? dayjs(date).format(format) : 'not set'}`, description: [description, stampNote, zoneNote].filter(Boolean).join(' ') || undefined, size: "sm", value: date, onChange: (next) => {
85
+ if (!readOnly)
86
+ onChange(next ? next.toISOString() : '');
87
+ }, withSeconds: true, valueFormat: format, placeholder: readOnly ? undefined : 'Pick a date and time', ariaLabels: CALENDAR_LABELS, timeInputProps: { 'aria-label': 'Time' }, submitButtonProps: { 'aria-label': 'Done' },
88
+ // Red is for errors here, so weekends look like other days.
89
+ weekendDays: [], rightSection: date && !readOnly ? (_jsx(Tooltip, { label: REMOVE_LABEL, children: _jsx(ActionIcon, { variant: "subtle", color: "gray", "aria-label": REMOVE_LABEL, onClick: () => {
90
+ onChange('');
91
+ // The control goes with the value, so focus returns to the field.
92
+ triggerRef.current?.focus();
93
+ }, children: _jsx(IconX, { size: 14, "aria-hidden": true }) }) })) : undefined, rightSectionPointerEvents: "all", readOnly: readOnly, "data-canopy-field": dataCanopyField }) }));
56
94
  };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import type { ItemExpansion } from './item-expansion.js';
3
+ /** One button for a collapsible list: "Collapse all" once every row is open, else "Expand all". */
4
+ export declare const ExpandAllButton: React.FC<{
5
+ expansion: ItemExpansion;
6
+ }>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button } from '@mantine/core';
3
+ /** One button for a collapsible list: "Collapse all" once every row is open, else "Expand all". */
4
+ export const ExpandAllButton = ({ expansion }) => (_jsx(Button, { variant: "subtle", color: "gray", c: "dimmed", size: "compact-xs", onClick: () => expansion.setAll(!expansion.allExpanded), "data-testid": "list-expand-all", children: expansion.allExpanded ? 'Collapse all' : 'Expand all' }));
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { type CaughtEditorError } from '../components/EditorErrorBoundary.js';
3
+ export interface FieldCrashFallbackProps {
4
+ label: string;
5
+ fieldType: string;
6
+ value: unknown;
7
+ /** Used only by markdown and mdx fields, whose raw text is edited directly; absent when read-only. */
8
+ onChange?: (value: unknown) => void;
9
+ caught: CaughtEditorError;
10
+ dataCanopyField?: string;
11
+ }
12
+ /**
13
+ * What a field that threw while rendering shows: its value read-only, so Save writes back
14
+ * exactly what is on screen, or, for a markdown or mdx field holding text, that text, still
15
+ * editable when there is an `onChange`.
16
+ */
17
+ export declare const FieldCrashFallback: React.FC<FieldCrashFallbackProps>;
@@ -0,0 +1,30 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Alert, Code, Group, Paper, Stack, Text } from '@mantine/core';
4
+ import { IconAlertTriangle } from '@tabler/icons-react';
5
+ import { CopyErrorDetailsButton } from '../components/EditorErrorBoundary.js';
6
+ import { getErrorMessage, sanitizeErrorMessage } from '../../utils/error.js';
7
+ import { MarkdownSourceEditor } from './MarkdownField.js';
8
+ const displayValue = (value) => {
9
+ if (value === undefined || value === null || value === '')
10
+ return '(empty)';
11
+ if (typeof value === 'string')
12
+ return value;
13
+ try {
14
+ return JSON.stringify(value, null, 2) ?? String(value);
15
+ }
16
+ catch {
17
+ return String(value);
18
+ }
19
+ };
20
+ /**
21
+ * What a field that threw while rendering shows: its value read-only, so Save writes back
22
+ * exactly what is on screen, or, for a markdown or mdx field holding text, that text, still
23
+ * editable when there is an `onChange`.
24
+ */
25
+ export const FieldCrashFallback = ({ label, fieldType, value, onChange, caught, dataCanopyField, }) => {
26
+ // Only text is editable as source; any other value would show as an empty box to type over.
27
+ const textSource = (fieldType === 'markdown' || fieldType === 'mdx') &&
28
+ (typeof value === 'string' || value === undefined || value === null);
29
+ return (_jsx(Paper, { withBorder: true, radius: "sm", p: "sm", "data-testid": "field-crash-fallback", "data-canopy-field": dataCanopyField, children: _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", fw: 500, children: label }), textSource ? (_jsx(MarkdownSourceEditor, { label: label, value: typeof value === 'string' ? value : '', onChange: (next) => onChange?.(next), readOnly: !onChange, failure: sanitizeErrorMessage(getErrorMessage(caught.error)) })) : (_jsxs(_Fragment, { children: [_jsx(Alert, { color: "red", variant: "light", icon: _jsx(IconAlertTriangle, { size: 16 }), children: _jsxs(Text, { size: "sm", children: ["This field couldn't be shown because of an error. Its value is below and won't be changed.", onChange && ' You can keep editing the other fields and save.'] }) }), _jsx(Code, { block: true, "data-testid": "field-crash-value", style: { whiteSpace: 'pre-wrap' }, children: displayValue(value) })] })), _jsx(Group, { children: _jsx(CopyErrorDetailsButton, { caught: caught }) })] }) }));
30
+ };
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ /**
3
+ * The label row shared by fields and field groups: label, comment-control slot, right-aligned
4
+ * actions slot, and the description beneath.
5
+ */
6
+ export interface FieldLabelProps {
7
+ /** Visible label text. When absent and there are no actions or commentControl, only the description renders. */
8
+ label?: React.ReactNode;
9
+ /** Shows Mantine's required asterisk. */
10
+ required?: boolean;
11
+ /** Guidance under the label; rendered via FieldDescription so its id matches groupDescriptionProps(baseId, ...). */
12
+ description?: string;
13
+ /** Base id shared with groupDescriptionProps/fieldDescriptionId; without it, no description renders. */
14
+ descriptionBaseId?: string;
15
+ /** When set, the label is a <label for=...>; otherwise it is a <div> (groups have no single input). */
16
+ htmlFor?: string;
17
+ /** id on the label element, so a container can aria-labelledby it. */
18
+ labelId?: string;
19
+ /** Slot right after the label text, for the field's comment control. */
20
+ commentControl?: React.ReactNode;
21
+ /** Right-aligned slot for field actions (Expand all, Clear). */
22
+ actions?: React.ReactNode;
23
+ }
24
+ export declare const FieldLabel: React.FC<FieldLabelProps>;
25
+ /**
26
+ * A Mantine input under a `FieldLabel` row, in place of the input's own `label` prop, so the
27
+ * row can carry the field's comment control: a button inside the input's `<label>` would be
28
+ * invalid HTML and join the input's accessible name. The input keeps its own `description`.
29
+ */
30
+ export declare const LabelledInput: React.FC<{
31
+ label?: string;
32
+ /** The input's id, which the label's `for` names. */
33
+ inputId: string;
34
+ /** The field's canopy path, which picks its comment control. */
35
+ canopyPath?: string;
36
+ children: React.ReactNode;
37
+ }>;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Group, Input, Stack } from '@mantine/core';
3
+ import { useFieldCommentControl } from '../comments/field-comment-context.js';
4
+ import { FieldDescription } from './FieldDescription.js';
5
+ export const FieldLabel = ({ label, required, description, descriptionBaseId, htmlFor, labelId, commentControl, actions, }) => {
6
+ const hasRow = Boolean(label) || Boolean(commentControl) || Boolean(actions);
7
+ if (!hasRow && !description)
8
+ return null;
9
+ return (_jsxs(Stack, { gap: 2, children: [hasRow && (_jsxs(Group, { justify: "space-between", wrap: "nowrap", gap: "xs", align: "center", children: [_jsxs(Group, { gap: 4, wrap: "nowrap", style: { minWidth: 0 }, children: [label && (_jsx(Input.Label, { required: required, htmlFor: htmlFor, id: labelId, labelElement: htmlFor ? 'label' : 'div', children: label })), commentControl] }), actions && (_jsx(Group, { gap: "xs", wrap: "nowrap", style: { flexShrink: 0 }, children: actions }))] })), descriptionBaseId && (_jsx(FieldDescription, { baseId: descriptionBaseId, description: description }))] }));
10
+ };
11
+ /**
12
+ * A Mantine input under a `FieldLabel` row, in place of the input's own `label` prop, so the
13
+ * row can carry the field's comment control: a button inside the input's `<label>` would be
14
+ * invalid HTML and join the input's accessible name. The input keeps its own `description`.
15
+ */
16
+ export const LabelledInput = ({ label, inputId, canopyPath, children }) => {
17
+ const commentControl = useFieldCommentControl(canopyPath);
18
+ return (_jsxs(Stack, { gap: 4, children: [_jsx(FieldLabel, { label: label, htmlFor: inputId, commentControl: commentControl }), children] }));
19
+ };
@@ -17,6 +17,10 @@ export interface ImageFieldProps {
17
17
  altOptional?: boolean;
18
18
  dataCanopyField?: string;
19
19
  errors?: ImageFieldErrors;
20
+ /** No upload, pick, crop or remove; the alt text is read-only. */
21
+ readOnly?: boolean;
22
+ /** Told of the image Remove takes out, so the caller can offer Undo. */
23
+ onRemoved?: (removed: ImageFieldValue) => void;
20
24
  }
21
25
  export declare const ImageField: React.FC<ImageFieldProps>;
22
26
  export {};