@actuate-media/cms-admin 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +44 -42
  3. package/dist/AdminRoot.js.map +1 -1
  4. package/dist/__tests__/lib/search.test.js +10 -10
  5. package/dist/__tests__/lib/search.test.js.map +1 -1
  6. package/dist/__tests__/lib/utils.test.js.map +1 -1
  7. package/dist/__tests__/router/match-route.test.js.map +1 -1
  8. package/dist/__tests__/router/strip-base.test.js.map +1 -1
  9. package/dist/actuate-admin.css +1 -1
  10. package/dist/components/Breadcrumbs.d.ts.map +1 -1
  11. package/dist/components/Breadcrumbs.js +2 -4
  12. package/dist/components/Breadcrumbs.js.map +1 -1
  13. package/dist/components/CommandPalette.d.ts.map +1 -1
  14. package/dist/components/CommandPalette.js +7 -3
  15. package/dist/components/CommandPalette.js.map +1 -1
  16. package/dist/components/ContentOverviewChart.d.ts.map +1 -1
  17. package/dist/components/ContentOverviewChart.js.map +1 -1
  18. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  19. package/dist/components/ErrorBoundary.js.map +1 -1
  20. package/dist/components/FocalPointPicker.d.ts.map +1 -1
  21. package/dist/components/FocalPointPicker.js +4 -2
  22. package/dist/components/FocalPointPicker.js.map +1 -1
  23. package/dist/components/FolderTree.d.ts.map +1 -1
  24. package/dist/components/FolderTree.js +18 -10
  25. package/dist/components/FolderTree.js.map +1 -1
  26. package/dist/components/LivePreview.d.ts +1 -1
  27. package/dist/components/LivePreview.d.ts.map +1 -1
  28. package/dist/components/LivePreview.js +6 -2
  29. package/dist/components/LivePreview.js.map +1 -1
  30. package/dist/components/LocaleProvider.d.ts.map +1 -1
  31. package/dist/components/LocaleProvider.js.map +1 -1
  32. package/dist/components/LocaleSwitcher.d.ts.map +1 -1
  33. package/dist/components/LocaleSwitcher.js +1 -1
  34. package/dist/components/LocaleSwitcher.js.map +1 -1
  35. package/dist/components/MediaPickerModal.d.ts.map +1 -1
  36. package/dist/components/MediaPickerModal.js.map +1 -1
  37. package/dist/components/PresenceIndicator.d.ts.map +1 -1
  38. package/dist/components/PresenceIndicator.js +5 -2
  39. package/dist/components/PresenceIndicator.js.map +1 -1
  40. package/dist/components/SEOPanel.d.ts +1 -1
  41. package/dist/components/SEOPanel.d.ts.map +1 -1
  42. package/dist/components/SEOPanel.js +110 -24
  43. package/dist/components/SEOPanel.js.map +1 -1
  44. package/dist/components/SEOPerformance.d.ts.map +1 -1
  45. package/dist/components/SEOPerformance.js +2 -2
  46. package/dist/components/SEOPerformance.js.map +1 -1
  47. package/dist/components/ThemeProvider.d.ts.map +1 -1
  48. package/dist/components/ThemeProvider.js.map +1 -1
  49. package/dist/components/TipTapEditor.d.ts.map +1 -1
  50. package/dist/components/TipTapEditor.js +5 -1
  51. package/dist/components/TipTapEditor.js.map +1 -1
  52. package/dist/components/VersionHistory.d.ts +1 -1
  53. package/dist/components/VersionHistory.d.ts.map +1 -1
  54. package/dist/components/VersionHistory.js +1 -1
  55. package/dist/components/VersionHistory.js.map +1 -1
  56. package/dist/components/ui/Avatar.d.ts.map +1 -1
  57. package/dist/components/ui/Avatar.js.map +1 -1
  58. package/dist/components/ui/Badge.d.ts.map +1 -1
  59. package/dist/components/ui/Badge.js.map +1 -1
  60. package/dist/components/ui/Button.d.ts.map +1 -1
  61. package/dist/components/ui/Button.js.map +1 -1
  62. package/dist/components/ui/CommandPalette.d.ts.map +1 -1
  63. package/dist/components/ui/CommandPalette.js +8 -2
  64. package/dist/components/ui/CommandPalette.js.map +1 -1
  65. package/dist/components/ui/ConfirmDialog.d.ts.map +1 -1
  66. package/dist/components/ui/ConfirmDialog.js.map +1 -1
  67. package/dist/components/ui/DataTable.d.ts.map +1 -1
  68. package/dist/components/ui/DataTable.js +1 -3
  69. package/dist/components/ui/DataTable.js.map +1 -1
  70. package/dist/components/ui/EmptyState.d.ts.map +1 -1
  71. package/dist/components/ui/EmptyState.js +1 -1
  72. package/dist/components/ui/EmptyState.js.map +1 -1
  73. package/dist/components/ui/Modal.d.ts.map +1 -1
  74. package/dist/components/ui/Modal.js.map +1 -1
  75. package/dist/components/ui/Pagination.d.ts +1 -1
  76. package/dist/components/ui/Pagination.d.ts.map +1 -1
  77. package/dist/components/ui/Pagination.js +7 -2
  78. package/dist/components/ui/Pagination.js.map +1 -1
  79. package/dist/components/ui/SearchInput.d.ts.map +1 -1
  80. package/dist/components/ui/SearchInput.js.map +1 -1
  81. package/dist/components/ui/Skeleton.d.ts.map +1 -1
  82. package/dist/components/ui/Skeleton.js.map +1 -1
  83. package/dist/components/ui/Toast.d.ts.map +1 -1
  84. package/dist/components/ui/Toast.js.map +1 -1
  85. package/dist/components/ui/index.d.ts.map +1 -1
  86. package/dist/components/ui/index.js.map +1 -1
  87. package/dist/fields/ArrayField.d.ts.map +1 -1
  88. package/dist/fields/ArrayField.js +1 -1
  89. package/dist/fields/ArrayField.js.map +1 -1
  90. package/dist/fields/BlockBuilderField.d.ts.map +1 -1
  91. package/dist/fields/BlockBuilderField.js +7 -7
  92. package/dist/fields/BlockBuilderField.js.map +1 -1
  93. package/dist/fields/DateField.d.ts.map +1 -1
  94. package/dist/fields/DateField.js +1 -1
  95. package/dist/fields/DateField.js.map +1 -1
  96. package/dist/fields/FieldRenderer.d.ts.map +1 -1
  97. package/dist/fields/FieldRenderer.js.map +1 -1
  98. package/dist/fields/GroupField.d.ts.map +1 -1
  99. package/dist/fields/GroupField.js +1 -1
  100. package/dist/fields/GroupField.js.map +1 -1
  101. package/dist/fields/MediaField.d.ts.map +1 -1
  102. package/dist/fields/MediaField.js +1 -1
  103. package/dist/fields/MediaField.js.map +1 -1
  104. package/dist/fields/NavBuilderField.d.ts.map +1 -1
  105. package/dist/fields/NavBuilderField.js +2 -5
  106. package/dist/fields/NavBuilderField.js.map +1 -1
  107. package/dist/fields/NumberField.d.ts +1 -1
  108. package/dist/fields/NumberField.d.ts.map +1 -1
  109. package/dist/fields/NumberField.js +2 -2
  110. package/dist/fields/NumberField.js.map +1 -1
  111. package/dist/fields/RelationshipField.d.ts.map +1 -1
  112. package/dist/fields/RelationshipField.js +7 -3
  113. package/dist/fields/RelationshipField.js.map +1 -1
  114. package/dist/fields/RichTextField.d.ts +1 -1
  115. package/dist/fields/RichTextField.d.ts.map +1 -1
  116. package/dist/fields/RichTextField.js +2 -2
  117. package/dist/fields/RichTextField.js.map +1 -1
  118. package/dist/fields/SelectField.d.ts.map +1 -1
  119. package/dist/fields/SelectField.js +9 -7
  120. package/dist/fields/SelectField.js.map +1 -1
  121. package/dist/fields/SlugField.d.ts.map +1 -1
  122. package/dist/fields/SlugField.js +1 -1
  123. package/dist/fields/SlugField.js.map +1 -1
  124. package/dist/fields/TextField.d.ts +1 -1
  125. package/dist/fields/TextField.d.ts.map +1 -1
  126. package/dist/fields/TextField.js +2 -2
  127. package/dist/fields/TextField.js.map +1 -1
  128. package/dist/fields/ToggleField.d.ts.map +1 -1
  129. package/dist/fields/ToggleField.js +1 -1
  130. package/dist/fields/ToggleField.js.map +1 -1
  131. package/dist/fields/block-types.d.ts.map +1 -1
  132. package/dist/fields/block-types.js +28 -8
  133. package/dist/fields/block-types.js.map +1 -1
  134. package/dist/fields/index.d.ts.map +1 -1
  135. package/dist/fields/index.js.map +1 -1
  136. package/dist/hooks/useBuilderState.d.ts.map +1 -1
  137. package/dist/hooks/useBuilderState.js.map +1 -1
  138. package/dist/hooks/useContentLock.d.ts.map +1 -1
  139. package/dist/hooks/useContentLock.js.map +1 -1
  140. package/dist/hooks/useDebounce.js.map +1 -1
  141. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -1
  142. package/dist/hooks/useKeyboardShortcuts.js.map +1 -1
  143. package/dist/index.d.ts +2 -2
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js.map +1 -1
  146. package/dist/layout/Header.d.ts.map +1 -1
  147. package/dist/layout/Header.js.map +1 -1
  148. package/dist/layout/Layout.d.ts.map +1 -1
  149. package/dist/layout/Layout.js.map +1 -1
  150. package/dist/layout/Sidebar.d.ts +1 -1
  151. package/dist/layout/Sidebar.d.ts.map +1 -1
  152. package/dist/layout/Sidebar.js +5 -8
  153. package/dist/layout/Sidebar.js.map +1 -1
  154. package/dist/lib/api.js.map +1 -1
  155. package/dist/lib/search.d.ts.map +1 -1
  156. package/dist/lib/search.js +3 -5
  157. package/dist/lib/search.js.map +1 -1
  158. package/dist/lib/useApiData.d.ts.map +1 -1
  159. package/dist/lib/useApiData.js.map +1 -1
  160. package/dist/lib/utils.d.ts.map +1 -1
  161. package/dist/lib/utils.js.map +1 -1
  162. package/dist/router/index.d.ts.map +1 -1
  163. package/dist/router/index.js +1 -3
  164. package/dist/router/index.js.map +1 -1
  165. package/dist/views/CollectionList.d.ts.map +1 -1
  166. package/dist/views/CollectionList.js +56 -17
  167. package/dist/views/CollectionList.js.map +1 -1
  168. package/dist/views/Dashboard.d.ts.map +1 -1
  169. package/dist/views/Dashboard.js +26 -13
  170. package/dist/views/Dashboard.js.map +1 -1
  171. package/dist/views/DocumentEdit.d.ts +1 -1
  172. package/dist/views/DocumentEdit.d.ts.map +1 -1
  173. package/dist/views/DocumentEdit.js +33 -15
  174. package/dist/views/DocumentEdit.js.map +1 -1
  175. package/dist/views/ForgotPassword.d.ts.map +1 -1
  176. package/dist/views/ForgotPassword.js.map +1 -1
  177. package/dist/views/FormEditor.d.ts.map +1 -1
  178. package/dist/views/FormEditor.js +8 -2
  179. package/dist/views/FormEditor.js.map +1 -1
  180. package/dist/views/FormSubmissions.d.ts.map +1 -1
  181. package/dist/views/FormSubmissions.js +6 -6
  182. package/dist/views/FormSubmissions.js.map +1 -1
  183. package/dist/views/Forms.d.ts.map +1 -1
  184. package/dist/views/Forms.js.map +1 -1
  185. package/dist/views/Login.d.ts.map +1 -1
  186. package/dist/views/Login.js +5 -2
  187. package/dist/views/Login.js.map +1 -1
  188. package/dist/views/MediaBrowser.d.ts.map +1 -1
  189. package/dist/views/MediaBrowser.js +39 -19
  190. package/dist/views/MediaBrowser.js.map +1 -1
  191. package/dist/views/PageEditor.d.ts.map +1 -1
  192. package/dist/views/PageEditor.js.map +1 -1
  193. package/dist/views/Pages.d.ts.map +1 -1
  194. package/dist/views/Pages.js +20 -10
  195. package/dist/views/Pages.js.map +1 -1
  196. package/dist/views/PostEditor.d.ts.map +1 -1
  197. package/dist/views/PostEditor.js.map +1 -1
  198. package/dist/views/Posts.d.ts.map +1 -1
  199. package/dist/views/Posts.js +13 -7
  200. package/dist/views/Posts.js.map +1 -1
  201. package/dist/views/Redirects.d.ts.map +1 -1
  202. package/dist/views/Redirects.js +17 -5
  203. package/dist/views/Redirects.js.map +1 -1
  204. package/dist/views/ResetPassword.d.ts.map +1 -1
  205. package/dist/views/ResetPassword.js.map +1 -1
  206. package/dist/views/SEO.d.ts.map +1 -1
  207. package/dist/views/SEO.js +40 -17
  208. package/dist/views/SEO.js.map +1 -1
  209. package/dist/views/ScriptTagEditor.d.ts.map +1 -1
  210. package/dist/views/ScriptTagEditor.js +2 -1
  211. package/dist/views/ScriptTagEditor.js.map +1 -1
  212. package/dist/views/ScriptTags.d.ts.map +1 -1
  213. package/dist/views/ScriptTags.js.map +1 -1
  214. package/dist/views/Settings.d.ts.map +1 -1
  215. package/dist/views/Settings.js +38 -11
  216. package/dist/views/Settings.js.map +1 -1
  217. package/dist/views/SetupWizard.d.ts.map +1 -1
  218. package/dist/views/SetupWizard.js.map +1 -1
  219. package/dist/views/Users.d.ts.map +1 -1
  220. package/dist/views/Users.js +5 -3
  221. package/dist/views/Users.js.map +1 -1
  222. package/dist/views/page-builder/AIBlockAssist.d.ts.map +1 -1
  223. package/dist/views/page-builder/AIBlockAssist.js +1 -1
  224. package/dist/views/page-builder/AIBlockAssist.js.map +1 -1
  225. package/dist/views/page-builder/AIGenerateDialog.d.ts.map +1 -1
  226. package/dist/views/page-builder/AIGenerateDialog.js +4 -1
  227. package/dist/views/page-builder/AIGenerateDialog.js.map +1 -1
  228. package/dist/views/page-builder/BlockEditor.d.ts.map +1 -1
  229. package/dist/views/page-builder/BlockEditor.js +1 -1
  230. package/dist/views/page-builder/BlockEditor.js.map +1 -1
  231. package/dist/views/page-builder/BlockPicker.d.ts.map +1 -1
  232. package/dist/views/page-builder/BlockPicker.js.map +1 -1
  233. package/dist/views/page-builder/BottomBar.d.ts.map +1 -1
  234. package/dist/views/page-builder/BottomBar.js.map +1 -1
  235. package/dist/views/page-builder/BuilderToolbar.d.ts.map +1 -1
  236. package/dist/views/page-builder/BuilderToolbar.js.map +1 -1
  237. package/dist/views/page-builder/ContextPanel.d.ts.map +1 -1
  238. package/dist/views/page-builder/ContextPanel.js +4 -1
  239. package/dist/views/page-builder/ContextPanel.js.map +1 -1
  240. package/dist/views/page-builder/DesignScore.d.ts.map +1 -1
  241. package/dist/views/page-builder/DesignScore.js.map +1 -1
  242. package/dist/views/page-builder/NodeSettings.d.ts.map +1 -1
  243. package/dist/views/page-builder/NodeSettings.js +1 -1
  244. package/dist/views/page-builder/NodeSettings.js.map +1 -1
  245. package/dist/views/page-builder/PageBuilder.d.ts +1 -1
  246. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
  247. package/dist/views/page-builder/PageBuilder.js +4 -2
  248. package/dist/views/page-builder/PageBuilder.js.map +1 -1
  249. package/dist/views/page-builder/PageSettings.d.ts.map +1 -1
  250. package/dist/views/page-builder/PageSettings.js.map +1 -1
  251. package/dist/views/page-builder/PageTemplates.d.ts.map +1 -1
  252. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  253. package/dist/views/page-builder/SEOPanel.d.ts.map +1 -1
  254. package/dist/views/page-builder/SEOPanel.js +1 -3
  255. package/dist/views/page-builder/SEOPanel.js.map +1 -1
  256. package/dist/views/page-builder/SavedSections.d.ts.map +1 -1
  257. package/dist/views/page-builder/SavedSections.js +3 -7
  258. package/dist/views/page-builder/SavedSections.js.map +1 -1
  259. package/dist/views/page-builder/TemplatePicker.d.ts.map +1 -1
  260. package/dist/views/page-builder/TemplatePicker.js.map +1 -1
  261. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts.map +1 -1
  262. package/dist/views/page-builder/block-renderers/CTAPreview.js +1 -1
  263. package/dist/views/page-builder/block-renderers/CTAPreview.js.map +1 -1
  264. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts.map +1 -1
  265. package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
  266. package/dist/views/page-builder/block-renderers/CardsPreview.js.map +1 -1
  267. package/dist/views/page-builder/block-renderers/CodePreview.d.ts.map +1 -1
  268. package/dist/views/page-builder/block-renderers/CodePreview.js +1 -5
  269. package/dist/views/page-builder/block-renderers/CodePreview.js.map +1 -1
  270. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts.map +1 -1
  271. package/dist/views/page-builder/block-renderers/FAQPreview.js +4 -1
  272. package/dist/views/page-builder/block-renderers/FAQPreview.js.map +1 -1
  273. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts.map +1 -1
  274. package/dist/views/page-builder/block-renderers/FallbackPreview.js.map +1 -1
  275. package/dist/views/page-builder/block-renderers/FormPreview.d.ts.map +1 -1
  276. package/dist/views/page-builder/block-renderers/FormPreview.js +2 -2
  277. package/dist/views/page-builder/block-renderers/FormPreview.js.map +1 -1
  278. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts.map +1 -1
  279. package/dist/views/page-builder/block-renderers/GalleryPreview.js +1 -3
  280. package/dist/views/page-builder/block-renderers/GalleryPreview.js.map +1 -1
  281. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts.map +1 -1
  282. package/dist/views/page-builder/block-renderers/HeroPreview.js.map +1 -1
  283. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts.map +1 -1
  284. package/dist/views/page-builder/block-renderers/ImagePreview.js.map +1 -1
  285. package/dist/views/page-builder/block-renderers/TextPreview.d.ts.map +1 -1
  286. package/dist/views/page-builder/block-renderers/TextPreview.js +2 -6
  287. package/dist/views/page-builder/block-renderers/TextPreview.js.map +1 -1
  288. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts.map +1 -1
  289. package/dist/views/page-builder/block-renderers/VideoPreview.js +2 -5
  290. package/dist/views/page-builder/block-renderers/VideoPreview.js.map +1 -1
  291. package/dist/views/page-builder/block-renderers/index.d.ts.map +1 -1
  292. package/dist/views/page-builder/block-renderers/index.js.map +1 -1
  293. package/dist/views/page-builder/canvas/BlockRenderer.d.ts.map +1 -1
  294. package/dist/views/page-builder/canvas/BlockRenderer.js +1 -5
  295. package/dist/views/page-builder/canvas/BlockRenderer.js.map +1 -1
  296. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts.map +1 -1
  297. package/dist/views/page-builder/canvas/BuilderCanvas.js.map +1 -1
  298. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts.map +1 -1
  299. package/dist/views/page-builder/canvas/ColumnRenderer.js +1 -5
  300. package/dist/views/page-builder/canvas/ColumnRenderer.js.map +1 -1
  301. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts.map +1 -1
  302. package/dist/views/page-builder/canvas/ContainerRenderer.js +1 -5
  303. package/dist/views/page-builder/canvas/ContainerRenderer.js.map +1 -1
  304. package/dist/views/page-builder/canvas/RowRenderer.d.ts.map +1 -1
  305. package/dist/views/page-builder/canvas/RowRenderer.js +1 -5
  306. package/dist/views/page-builder/canvas/RowRenderer.js.map +1 -1
  307. package/dist/views/page-builder/canvas/SectionRenderer.d.ts.map +1 -1
  308. package/dist/views/page-builder/canvas/SectionRenderer.js +1 -5
  309. package/dist/views/page-builder/canvas/SectionRenderer.js.map +1 -1
  310. package/dist/views/page-builder/canvas/index.d.ts.map +1 -1
  311. package/dist/views/page-builder/canvas/index.js.map +1 -1
  312. package/package.json +2 -2
  313. package/src/AdminRoot.tsx +263 -191
  314. package/src/__tests__/lib/search.test.ts +60 -69
  315. package/src/__tests__/lib/utils.test.ts +12 -12
  316. package/src/__tests__/router/match-route.test.ts +24 -26
  317. package/src/__tests__/router/strip-base.test.ts +15 -15
  318. package/src/components/Breadcrumbs.tsx +27 -24
  319. package/src/components/CommandPalette.tsx +115 -99
  320. package/src/components/ContentOverviewChart.tsx +19 -14
  321. package/src/components/ErrorBoundary.tsx +13 -13
  322. package/src/components/FocalPointPicker.tsx +31 -20
  323. package/src/components/FolderTree.tsx +172 -139
  324. package/src/components/LivePreview.tsx +68 -41
  325. package/src/components/LocaleProvider.tsx +26 -20
  326. package/src/components/LocaleSwitcher.tsx +9 -11
  327. package/src/components/MediaPickerModal.tsx +46 -45
  328. package/src/components/PresenceIndicator.tsx +30 -27
  329. package/src/components/SEOPanel.tsx +378 -228
  330. package/src/components/SEOPerformance.tsx +52 -30
  331. package/src/components/ThemeProvider.tsx +46 -46
  332. package/src/components/TipTapEditor.tsx +60 -64
  333. package/src/components/VersionHistory.tsx +63 -52
  334. package/src/components/ui/Avatar.tsx +8 -8
  335. package/src/components/ui/Badge.tsx +7 -5
  336. package/src/components/ui/Button.tsx +24 -13
  337. package/src/components/ui/CommandPalette.tsx +56 -42
  338. package/src/components/ui/ConfirmDialog.tsx +14 -14
  339. package/src/components/ui/DataTable.tsx +37 -39
  340. package/src/components/ui/EmptyState.tsx +9 -11
  341. package/src/components/ui/Modal.tsx +21 -15
  342. package/src/components/ui/Pagination.tsx +34 -19
  343. package/src/components/ui/SearchInput.tsx +17 -7
  344. package/src/components/ui/Skeleton.tsx +7 -7
  345. package/src/components/ui/Toast.tsx +29 -22
  346. package/src/components/ui/index.ts +24 -24
  347. package/src/fields/ArrayField.tsx +43 -25
  348. package/src/fields/BlockBuilderField.tsx +80 -99
  349. package/src/fields/DateField.tsx +20 -12
  350. package/src/fields/FieldRenderer.tsx +34 -34
  351. package/src/fields/GroupField.tsx +8 -10
  352. package/src/fields/MediaField.tsx +8 -10
  353. package/src/fields/NavBuilderField.tsx +24 -25
  354. package/src/fields/NumberField.tsx +21 -14
  355. package/src/fields/RelationshipField.tsx +105 -91
  356. package/src/fields/RichTextField.tsx +16 -12
  357. package/src/fields/SelectField.tsx +42 -34
  358. package/src/fields/SlugField.tsx +29 -17
  359. package/src/fields/TextField.tsx +24 -16
  360. package/src/fields/ToggleField.tsx +7 -9
  361. package/src/fields/block-types.ts +50 -24
  362. package/src/fields/index.ts +17 -17
  363. package/src/hooks/useBuilderState.ts +260 -221
  364. package/src/hooks/useContentLock.ts +23 -20
  365. package/src/hooks/useDebounce.ts +7 -7
  366. package/src/hooks/useKeyboardShortcuts.ts +16 -16
  367. package/src/index.ts +69 -58
  368. package/src/layout/Header.tsx +21 -20
  369. package/src/layout/Layout.tsx +22 -24
  370. package/src/layout/Sidebar.tsx +107 -72
  371. package/src/lib/api.ts +34 -34
  372. package/src/lib/search.ts +30 -34
  373. package/src/lib/useApiData.ts +65 -62
  374. package/src/lib/utils.ts +3 -3
  375. package/src/router/index.ts +33 -35
  376. package/src/styles/build-input.css +2 -2
  377. package/src/styles/tailwind.css +1 -1
  378. package/src/styles/theme.css +26 -2
  379. package/src/views/CollectionList.tsx +275 -121
  380. package/src/views/Dashboard.tsx +164 -117
  381. package/src/views/DocumentEdit.tsx +298 -253
  382. package/src/views/ForgotPassword.tsx +27 -23
  383. package/src/views/FormEditor.tsx +165 -99
  384. package/src/views/FormSubmissions.tsx +261 -117
  385. package/src/views/Forms.tsx +56 -26
  386. package/src/views/Login.tsx +107 -84
  387. package/src/views/MediaBrowser.tsx +717 -523
  388. package/src/views/PageEditor.tsx +44 -46
  389. package/src/views/Pages.tsx +312 -149
  390. package/src/views/PostEditor.tsx +57 -51
  391. package/src/views/Posts.tsx +206 -74
  392. package/src/views/Redirects.tsx +173 -117
  393. package/src/views/ResetPassword.tsx +43 -32
  394. package/src/views/SEO.tsx +607 -160
  395. package/src/views/ScriptTagEditor.tsx +69 -69
  396. package/src/views/ScriptTags.tsx +54 -42
  397. package/src/views/Settings.tsx +430 -220
  398. package/src/views/SetupWizard.tsx +69 -46
  399. package/src/views/Users.tsx +154 -120
  400. package/src/views/page-builder/AIBlockAssist.tsx +21 -25
  401. package/src/views/page-builder/AIGenerateDialog.tsx +134 -127
  402. package/src/views/page-builder/BlockEditor.tsx +94 -96
  403. package/src/views/page-builder/BlockPicker.tsx +73 -88
  404. package/src/views/page-builder/BottomBar.tsx +15 -11
  405. package/src/views/page-builder/BuilderToolbar.tsx +32 -29
  406. package/src/views/page-builder/ContextPanel.tsx +57 -57
  407. package/src/views/page-builder/DesignScore.tsx +52 -59
  408. package/src/views/page-builder/NodeSettings.tsx +59 -59
  409. package/src/views/page-builder/PageBuilder.tsx +156 -155
  410. package/src/views/page-builder/PageSettings.tsx +16 -15
  411. package/src/views/page-builder/PageTemplates.tsx +23 -17
  412. package/src/views/page-builder/SEOPanel.tsx +90 -111
  413. package/src/views/page-builder/SavedSections.tsx +99 -105
  414. package/src/views/page-builder/TemplatePicker.tsx +44 -48
  415. package/src/views/page-builder/block-renderers/CTAPreview.tsx +11 -13
  416. package/src/views/page-builder/block-renderers/CardsPreview.tsx +13 -15
  417. package/src/views/page-builder/block-renderers/CodePreview.tsx +16 -16
  418. package/src/views/page-builder/block-renderers/FAQPreview.tsx +20 -23
  419. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +5 -5
  420. package/src/views/page-builder/block-renderers/FormPreview.tsx +9 -13
  421. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +22 -28
  422. package/src/views/page-builder/block-renderers/HeroPreview.tsx +17 -30
  423. package/src/views/page-builder/block-renderers/ImagePreview.tsx +12 -12
  424. package/src/views/page-builder/block-renderers/TextPreview.tsx +22 -22
  425. package/src/views/page-builder/block-renderers/VideoPreview.tsx +13 -18
  426. package/src/views/page-builder/block-renderers/index.ts +17 -17
  427. package/src/views/page-builder/canvas/BlockRenderer.tsx +19 -23
  428. package/src/views/page-builder/canvas/BuilderCanvas.tsx +17 -20
  429. package/src/views/page-builder/canvas/ColumnRenderer.tsx +22 -26
  430. package/src/views/page-builder/canvas/ContainerRenderer.tsx +20 -24
  431. package/src/views/page-builder/canvas/RowRenderer.tsx +19 -23
  432. package/src/views/page-builder/canvas/SectionRenderer.tsx +30 -34
  433. package/src/views/page-builder/canvas/index.ts +2 -2
@@ -1,215 +1,243 @@
1
- 'use client';
2
-
3
- import { useState, useEffect, useCallback, useRef } from 'react';
4
- import { AlertTriangle, Eye, EyeOff, Save, Copy, Loader2, Clock } from 'lucide-react';
5
- import { toast } from 'sonner';
6
- import { FieldRenderer } from '../fields/FieldRenderer.js';
7
- import { RelationshipField } from '../fields/RelationshipField.js';
8
- import { Button } from '../components/ui/Button.js';
9
- import { Badge } from '../components/ui/Badge.js';
10
- import { LivePreview } from '../components/LivePreview.js';
11
- import { VersionHistory } from '../components/VersionHistory.js';
12
- import { PresenceIndicator } from '../components/PresenceIndicator.js';
13
- import { SEOPanel } from '../components/SEOPanel.js';
14
- import type { SEOData } from '../components/SEOPanel.js';
15
- import { cmsApi } from '../lib/api.js';
1
+ 'use client'
2
+
3
+ import { useState, useEffect, useCallback, useRef } from 'react'
4
+ import { AlertTriangle, Eye, EyeOff, Save, Copy, Loader2, Clock } from 'lucide-react'
5
+ import { toast } from 'sonner'
6
+ import { FieldRenderer } from '../fields/FieldRenderer.js'
7
+ import { RelationshipField } from '../fields/RelationshipField.js'
8
+ import { Button } from '../components/ui/Button.js'
9
+ import { Badge } from '../components/ui/Badge.js'
10
+ import { LivePreview } from '../components/LivePreview.js'
11
+ import { VersionHistory } from '../components/VersionHistory.js'
12
+ import { PresenceIndicator } from '../components/PresenceIndicator.js'
13
+ import { SEOPanel } from '../components/SEOPanel.js'
14
+ import type { SEOData } from '../components/SEOPanel.js'
15
+ import { cmsApi } from '../lib/api.js'
16
16
 
17
17
  export interface DocumentEditProps {
18
- collectionSlug: string;
19
- documentId?: string;
20
- config: any;
21
- onNavigate?: (path: string) => void;
18
+ collectionSlug: string
19
+ documentId?: string
20
+ config: any
21
+ onNavigate?: (path: string) => void
22
22
  }
23
23
 
24
- export function DocumentEdit({ collectionSlug, documentId, config, onNavigate }: DocumentEditProps) {
25
- const isNew = !documentId;
26
- const [values, setValues] = useState<Record<string, any>>({});
27
- const [initialValues, setInitialValues] = useState<Record<string, any>>({});
28
- const [seoData, setSeoData] = useState<SEOData>({});
29
- const [initialSeoData, setInitialSeoData] = useState<SEOData>({});
30
- const [layoutAssignments, setLayoutAssignments] = useState<Record<string, string>>({});
31
- const [initialLayoutAssignments, setInitialLayoutAssignments] = useState<Record<string, string>>({});
32
- const [saving, setSaving] = useState(false);
33
- const [loading, setLoading] = useState(!isNew);
34
- const [showPreview, setShowPreview] = useState(false);
35
- const [showVersions, setShowVersions] = useState(false);
36
- const [docStatus, setDocStatus] = useState<string>('DRAFT');
37
- const hasLoadedRef = useRef(false);
38
-
39
- const collections = config?.collections;
24
+ export function DocumentEdit({
25
+ collectionSlug,
26
+ documentId,
27
+ config,
28
+ onNavigate,
29
+ }: DocumentEditProps) {
30
+ const isNew = !documentId
31
+ const [values, setValues] = useState<Record<string, any>>({})
32
+ const [initialValues, setInitialValues] = useState<Record<string, any>>({})
33
+ const [seoData, setSeoData] = useState<SEOData>({})
34
+ const [initialSeoData, setInitialSeoData] = useState<SEOData>({})
35
+ const [layoutAssignments, setLayoutAssignments] = useState<Record<string, string>>({})
36
+ const [initialLayoutAssignments, setInitialLayoutAssignments] = useState<Record<string, string>>(
37
+ {},
38
+ )
39
+ const [saving, setSaving] = useState(false)
40
+ const [loading, setLoading] = useState(!isNew)
41
+ const [showPreview, setShowPreview] = useState(false)
42
+ const [showVersions, setShowVersions] = useState(false)
43
+ const [docStatus, setDocStatus] = useState<string>('DRAFT')
44
+ const hasLoadedRef = useRef(false)
45
+
46
+ const collections = config?.collections
40
47
  const collection = Array.isArray(collections)
41
48
  ? collections.find((c: any) => c.slug === collectionSlug)
42
- : collections?.[collectionSlug];
43
-
44
- const layoutConfig = config?.layout;
45
- const layoutRegions: Array<{ name: string; collection: string; label: string }> = layoutConfig?.regions
46
- ? Object.entries(layoutConfig.regions).map(([name, region]: [string, any]) => ({
47
- name,
48
- collection: region.collection,
49
- label: region.label ?? name.charAt(0).toUpperCase() + name.slice(1),
50
- }))
51
- : [];
52
- const hasLayout = layoutRegions.length > 0 && (collection?.type === 'page' || collection?.urlPrefix !== undefined);
53
-
54
- const previewUrl = collection?.admin?.preview ? collection.admin.preview({}) : undefined;
49
+ : collections?.[collectionSlug]
50
+
51
+ const layoutConfig = config?.layout
52
+ const layoutRegions: Array<{ name: string; collection: string; label: string }> =
53
+ layoutConfig?.regions
54
+ ? Object.entries(layoutConfig.regions).map(([name, region]: [string, any]) => ({
55
+ name,
56
+ collection: region.collection,
57
+ label: region.label ?? name.charAt(0).toUpperCase() + name.slice(1),
58
+ }))
59
+ : []
60
+ const hasLayout =
61
+ layoutRegions.length > 0 && (collection?.type === 'page' || collection?.urlPrefix !== undefined)
62
+
63
+ const previewUrl = collection?.admin?.preview ? collection.admin.preview({}) : undefined
55
64
  const fields: any[] = collection?.fields
56
- ? (Array.isArray(collection.fields)
57
- ? collection.fields
58
- : Object.entries(collection.fields).map(([name, def]: [string, any]) => ({ name, ...def })))
59
- : [];
65
+ ? Array.isArray(collection.fields)
66
+ ? collection.fields
67
+ : Object.entries(collection.fields).map(([name, def]: [string, any]) => ({ name, ...def }))
68
+ : []
60
69
 
61
- const useAsTitleField = collection?.admin?.useAsTitle ?? 'title';
70
+ const useAsTitleField = collection?.admin?.useAsTitle ?? 'title'
62
71
  const displayTitle = isNew
63
72
  ? `New ${collection?.labels?.singular ?? collectionSlug}`
64
- : `Edit ${values[useAsTitleField] ?? 'Document'}`;
73
+ : `Edit ${values[useAsTitleField] ?? 'Document'}`
65
74
 
66
- const isDirty = JSON.stringify(values) !== JSON.stringify(initialValues)
67
- || JSON.stringify(seoData) !== JSON.stringify(initialSeoData)
68
- || JSON.stringify(layoutAssignments) !== JSON.stringify(initialLayoutAssignments);
75
+ const isDirty =
76
+ JSON.stringify(values) !== JSON.stringify(initialValues) ||
77
+ JSON.stringify(seoData) !== JSON.stringify(initialSeoData) ||
78
+ JSON.stringify(layoutAssignments) !== JSON.stringify(initialLayoutAssignments)
69
79
 
70
80
  useEffect(() => {
71
81
  if (!isNew && documentId && !hasLoadedRef.current) {
72
- hasLoadedRef.current = true;
73
- loadDocument();
82
+ hasLoadedRef.current = true
83
+ loadDocument()
74
84
  }
75
- }, [documentId, isNew]);
85
+ }, [documentId, isNew])
76
86
 
77
87
  useEffect(() => {
78
- if (!isDirty) return;
88
+ if (!isDirty) return
79
89
  const handler = (e: BeforeUnloadEvent) => {
80
- e.preventDefault();
81
- };
82
- window.addEventListener('beforeunload', handler);
83
- return () => window.removeEventListener('beforeunload', handler);
84
- }, [isDirty]);
90
+ e.preventDefault()
91
+ }
92
+ window.addEventListener('beforeunload', handler)
93
+ return () => window.removeEventListener('beforeunload', handler)
94
+ }, [isDirty])
85
95
 
86
96
  const SEO_FIELDS: (keyof SEOData)[] = [
87
- 'metaTitle', 'metaDescription', 'focusKeyphrase', 'canonical',
88
- 'robotsPolicy', 'noIndex', 'noFollow', 'ogTitle', 'ogDescription', 'ogImage',
89
- 'twitterTitle', 'twitterDescription', 'twitterImage',
90
- 'isCornerstone', 'schemaType',
91
- ];
97
+ 'metaTitle',
98
+ 'metaDescription',
99
+ 'focusKeyphrase',
100
+ 'canonical',
101
+ 'robotsPolicy',
102
+ 'noIndex',
103
+ 'noFollow',
104
+ 'ogTitle',
105
+ 'ogDescription',
106
+ 'ogImage',
107
+ 'twitterTitle',
108
+ 'twitterDescription',
109
+ 'twitterImage',
110
+ 'isCornerstone',
111
+ 'schemaType',
112
+ ]
92
113
 
93
114
  async function loadDocument() {
94
- setLoading(true);
95
- const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`);
115
+ setLoading(true)
116
+ const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`)
96
117
  if (res.data) {
97
- const doc = res.data;
98
- const docData = (doc.data && typeof doc.data === 'object') ? doc.data : {};
99
- const merged = { ...docData, title: doc.title ?? docData.title, slug: doc.slug ?? docData.slug };
100
- setValues(merged);
101
- setInitialValues(merged);
102
- setDocStatus(doc.status ?? 'DRAFT');
103
-
104
- const loadedSeo: SEOData = {};
118
+ const doc = res.data
119
+ const docData = doc.data && typeof doc.data === 'object' ? doc.data : {}
120
+ const merged = {
121
+ ...docData,
122
+ title: doc.title ?? docData.title,
123
+ slug: doc.slug ?? docData.slug,
124
+ }
125
+ setValues(merged)
126
+ setInitialValues(merged)
127
+ setDocStatus(doc.status ?? 'DRAFT')
128
+
129
+ const loadedSeo: SEOData = {}
105
130
  for (const key of SEO_FIELDS) {
106
131
  if (docData[key] !== undefined) {
107
- (loadedSeo as any)[key] = docData[key];
132
+ ;(loadedSeo as any)[key] = docData[key]
108
133
  }
109
134
  }
110
- setSeoData(loadedSeo);
111
- setInitialSeoData(loadedSeo);
135
+ setSeoData(loadedSeo)
136
+ setInitialSeoData(loadedSeo)
112
137
 
113
138
  if (docData._layout && typeof docData._layout === 'object') {
114
- const loaded = docData._layout as Record<string, string>;
115
- setLayoutAssignments(loaded);
116
- setInitialLayoutAssignments(loaded);
139
+ const loaded = docData._layout as Record<string, string>
140
+ setLayoutAssignments(loaded)
141
+ setInitialLayoutAssignments(loaded)
117
142
  }
118
143
  } else if (res.error) {
119
- toast.error(`Failed to load document: ${res.error}`);
144
+ toast.error(`Failed to load document: ${res.error}`)
120
145
  }
121
- setLoading(false);
146
+ setLoading(false)
122
147
  }
123
148
 
124
149
  function handleFieldChange(name: string, value: any) {
125
- setValues((prev) => ({ ...prev, [name]: value }));
150
+ setValues((prev) => ({ ...prev, [name]: value }))
126
151
  }
127
152
 
128
153
  async function handleSave() {
129
- setSaving(true);
130
- const layoutPayload = Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {};
131
- const payload = { ...values, ...seoData, ...layoutPayload };
154
+ setSaving(true)
155
+ const layoutPayload =
156
+ Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
157
+ const payload = { ...values, ...seoData, ...layoutPayload }
132
158
  try {
133
159
  if (isNew) {
134
160
  const res = await cmsApi<any>(`/collections/${collectionSlug}`, {
135
161
  method: 'POST',
136
162
  body: JSON.stringify(payload),
137
- });
163
+ })
138
164
  if (res.error) {
139
- toast.error(res.error);
165
+ toast.error(res.error)
140
166
  } else {
141
- toast.success('Document created');
142
- const newId = res.data?.id;
143
- setInitialValues(values);
144
- setInitialSeoData(seoData);
145
- setInitialLayoutAssignments(layoutAssignments);
167
+ toast.success('Document created')
168
+ const newId = res.data?.id
169
+ setInitialValues(values)
170
+ setInitialSeoData(seoData)
171
+ setInitialLayoutAssignments(layoutAssignments)
146
172
  if (newId && onNavigate) {
147
- onNavigate(`/${collectionSlug}/${newId}`);
173
+ onNavigate(`/${collectionSlug}/${newId}`)
148
174
  }
149
175
  }
150
176
  } else {
151
177
  const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
152
178
  method: 'PUT',
153
179
  body: JSON.stringify(payload),
154
- });
180
+ })
155
181
  if (res.error) {
156
- toast.error(res.error);
182
+ toast.error(res.error)
157
183
  } else {
158
- toast.success('Changes saved');
159
- setInitialValues(values);
160
- setInitialSeoData(seoData);
161
- setInitialLayoutAssignments(layoutAssignments);
162
- if (res.data?.status) setDocStatus(res.data.status);
184
+ toast.success('Changes saved')
185
+ setInitialValues(values)
186
+ setInitialSeoData(seoData)
187
+ setInitialLayoutAssignments(layoutAssignments)
188
+ if (res.data?.status) setDocStatus(res.data.status)
163
189
  }
164
190
  }
165
191
  } catch {
166
- toast.error('An unexpected error occurred');
192
+ toast.error('An unexpected error occurred')
167
193
  }
168
- setSaving(false);
194
+ setSaving(false)
169
195
  }
170
196
 
171
197
  async function handlePublish() {
172
- if (isNew) return;
173
- setSaving(true);
174
- const layoutPayload = Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {};
198
+ if (isNew) return
199
+ setSaving(true)
200
+ const layoutPayload =
201
+ Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
175
202
  const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
176
203
  method: 'PUT',
177
204
  body: JSON.stringify({ ...values, ...seoData, ...layoutPayload, status: 'PUBLISHED' }),
178
- });
205
+ })
179
206
  if (res.error) {
180
- toast.error(res.error);
207
+ toast.error(res.error)
181
208
  } else {
182
- toast.success('Document published');
183
- setDocStatus('PUBLISHED');
184
- setInitialValues(values);
185
- setInitialSeoData(seoData);
186
- setInitialLayoutAssignments(layoutAssignments);
209
+ toast.success('Document published')
210
+ setDocStatus('PUBLISHED')
211
+ setInitialValues(values)
212
+ setInitialSeoData(seoData)
213
+ setInitialLayoutAssignments(layoutAssignments)
187
214
  }
188
- setSaving(false);
215
+ setSaving(false)
189
216
  }
190
217
 
191
218
  async function handleUnpublish() {
192
- if (isNew) return;
193
- setSaving(true);
194
- const layoutPayload = Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {};
219
+ if (isNew) return
220
+ setSaving(true)
221
+ const layoutPayload =
222
+ Object.keys(layoutAssignments).length > 0 ? { _layout: layoutAssignments } : {}
195
223
  const res = await cmsApi<any>(`/collections/${collectionSlug}/${documentId}`, {
196
224
  method: 'PUT',
197
225
  body: JSON.stringify({ ...values, ...seoData, ...layoutPayload, status: 'DRAFT' }),
198
- });
226
+ })
199
227
  if (res.error) {
200
- toast.error(res.error);
228
+ toast.error(res.error)
201
229
  } else {
202
- toast.success('Document unpublished');
203
- setDocStatus('DRAFT');
204
- setInitialValues(values);
205
- setInitialSeoData(seoData);
206
- setInitialLayoutAssignments(layoutAssignments);
230
+ toast.success('Document unpublished')
231
+ setDocStatus('DRAFT')
232
+ setInitialValues(values)
233
+ setInitialSeoData(seoData)
234
+ setInitialLayoutAssignments(layoutAssignments)
207
235
  }
208
- setSaving(false);
236
+ setSaving(false)
209
237
  }
210
238
 
211
239
  async function handleDuplicate() {
212
- if (isNew || !documentId) return;
240
+ if (isNew || !documentId) return
213
241
  const res = await cmsApi<any>(`/collections/${collectionSlug}`, {
214
242
  method: 'POST',
215
243
  body: JSON.stringify({
@@ -217,41 +245,44 @@ export function DocumentEdit({ collectionSlug, documentId, config, onNavigate }:
217
245
  title: values.title ? `${values.title} (Copy)` : undefined,
218
246
  slug: values.slug ? `${values.slug}-copy` : undefined,
219
247
  }),
220
- });
248
+ })
221
249
  if (res.error) {
222
- toast.error(res.error);
250
+ toast.error(res.error)
223
251
  } else {
224
- toast.success('Document duplicated');
225
- const newId = res.data?.id;
252
+ toast.success('Document duplicated')
253
+ const newId = res.data?.id
226
254
  if (newId && onNavigate) {
227
- onNavigate(`/${collectionSlug}/${newId}`);
255
+ onNavigate(`/${collectionSlug}/${newId}`)
228
256
  }
229
257
  }
230
258
  }
231
259
 
232
260
  const mainFields = fields.filter(
233
261
  (f: any) => !['status', 'publishedAt', 'featured', 'featuredImage'].includes(f.name),
234
- );
262
+ )
235
263
  const sidebarFields = fields.filter((f: any) =>
236
264
  ['publishedAt', 'featured', 'featuredImage'].includes(f.name),
237
- );
265
+ )
238
266
 
239
267
  const contentField = fields.find(
240
268
  (f: any) => f.type === 'richText' || f.name === 'content' || f.name === 'body',
241
- );
242
- const htmlContent = contentField ? (values[contentField.name] ?? '') : '';
243
- const docSlug = values.slug ?? '';
269
+ )
270
+ const htmlContent = contentField ? (values[contentField.name] ?? '') : ''
271
+ const docSlug = values.slug ?? ''
244
272
 
245
- const statusColor = docStatus === 'PUBLISHED' ? 'bg-green-100 text-green-800'
246
- : docStatus === 'SCHEDULED' ? 'bg-blue-100 text-blue-800'
247
- : 'bg-yellow-100 text-yellow-800';
273
+ const statusColor =
274
+ docStatus === 'PUBLISHED'
275
+ ? 'bg-green-100 text-green-800'
276
+ : docStatus === 'SCHEDULED'
277
+ ? 'bg-blue-100 text-blue-800'
278
+ : 'bg-yellow-100 text-yellow-800'
248
279
 
249
280
  if (loading) {
250
281
  return (
251
282
  <div className="flex items-center justify-center min-h-[300px]">
252
283
  <Loader2 className="w-8 h-8 animate-spin text-gray-400" />
253
284
  </div>
254
- );
285
+ )
255
286
  }
256
287
 
257
288
  return (
@@ -259,13 +290,13 @@ export function DocumentEdit({ collectionSlug, documentId, config, onNavigate }:
259
290
  <div className="flex items-center justify-between">
260
291
  <div className="flex items-center gap-3">
261
292
  <h1 className="text-2xl font-bold">{displayTitle}</h1>
262
- <span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${statusColor}`}>
293
+ <span
294
+ className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${statusColor}`}
295
+ >
263
296
  {docStatus}
264
297
  </span>
265
298
  {documentId && <PresenceIndicator documentId={documentId} />}
266
- {isDirty && (
267
- <span className="text-xs text-amber-600 font-medium">Unsaved changes</span>
268
- )}
299
+ {isDirty && <span className="text-xs text-amber-600 font-medium">Unsaved changes</span>}
269
300
  </div>
270
301
  <div className="flex items-center gap-2">
271
302
  <button
@@ -306,119 +337,133 @@ export function DocumentEdit({ collectionSlug, documentId, config, onNavigate }:
306
337
  <div className="w-12 h-12 rounded-full bg-gray-100 flex items-center justify-center mb-4">
307
338
  <AlertTriangle className="w-6 h-6 text-gray-400" />
308
339
  </div>
309
- <h3 className="text-sm font-medium text-gray-900 mb-1">Collection schema not found</h3>
340
+ <h3 className="text-sm font-medium text-gray-900 mb-1">
341
+ Collection schema not found
342
+ </h3>
310
343
  <p className="text-sm text-gray-500">No fields are defined for this collection.</p>
311
344
  </div>
312
345
  ) : (
313
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
314
- <div className="space-y-6 lg:col-span-2">
315
- {mainFields.map((field: any) => (
316
- <FieldRenderer
317
- key={field.name}
318
- field={field}
319
- value={values[field.name]}
320
- onChange={(val) => handleFieldChange(field.name, val)}
321
- />
322
- ))}
323
- </div>
324
-
325
- <div className="space-y-6">
326
- <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
327
- <h3 className="mb-4 font-semibold">Status</h3>
328
- <div className="space-y-3">
329
- {!isNew && docStatus === 'DRAFT' && (
330
- <Button variant="primary" className="w-full" onClick={handlePublish} loading={saving}>
331
- Publish
332
- </Button>
333
- )}
334
- {!isNew && docStatus === 'PUBLISHED' && (
335
- <Button variant="secondary" className="w-full" onClick={handleUnpublish} loading={saving}>
336
- Unpublish
337
- </Button>
338
- )}
339
- </div>
346
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
347
+ <div className="space-y-6 lg:col-span-2">
348
+ {mainFields.map((field: any) => (
349
+ <FieldRenderer
350
+ key={field.name}
351
+ field={field}
352
+ value={values[field.name]}
353
+ onChange={(val) => handleFieldChange(field.name, val)}
354
+ />
355
+ ))}
340
356
  </div>
341
357
 
342
- {sidebarFields.length > 0 && (
358
+ <div className="space-y-6">
343
359
  <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
344
- <h3 className="mb-4 font-semibold">Metadata</h3>
345
- {sidebarFields.map((field: any) => (
346
- <div key={field.name} className="mb-4">
347
- <FieldRenderer
348
- field={field}
349
- value={values[field.name]}
350
- onChange={(val) => handleFieldChange(field.name, val)}
351
- />
352
- </div>
353
- ))}
360
+ <h3 className="mb-4 font-semibold">Status</h3>
361
+ <div className="space-y-3">
362
+ {!isNew && docStatus === 'DRAFT' && (
363
+ <Button
364
+ variant="primary"
365
+ className="w-full"
366
+ onClick={handlePublish}
367
+ loading={saving}
368
+ >
369
+ Publish
370
+ </Button>
371
+ )}
372
+ {!isNew && docStatus === 'PUBLISHED' && (
373
+ <Button
374
+ variant="secondary"
375
+ className="w-full"
376
+ onClick={handleUnpublish}
377
+ loading={saving}
378
+ >
379
+ Unpublish
380
+ </Button>
381
+ )}
382
+ </div>
354
383
  </div>
355
- )}
356
-
357
- <SEOPanel
358
- title={values[useAsTitleField] ?? values.title ?? ''}
359
- slug={docSlug}
360
- content={htmlContent}
361
- seoData={seoData}
362
- onChange={setSeoData}
363
- siteUrl={config?.siteUrl}
364
- />
365
-
366
- {hasLayout && (
367
- <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
368
- <h3 className="mb-1 font-semibold">Layout</h3>
369
- <p className="mb-4 text-xs text-[var(--muted-foreground)]">
370
- Assign header/footer variants. Child pages inherit from ancestors.
371
- </p>
372
- <div className="space-y-4">
373
- {layoutRegions.map((region) => (
374
- <div key={region.name}>
375
- <RelationshipField
376
- label={region.label}
377
- value={layoutAssignments[region.name] ?? ''}
378
- onChange={(val) => {
379
- setLayoutAssignments((prev) => {
380
- const next = { ...prev };
381
- if (val && typeof val === 'string') {
382
- next[region.name] = val;
383
- } else {
384
- delete next[region.name];
385
- }
386
- return next;
387
- });
388
- }}
389
- relationTo={region.collection}
390
- helpText={
391
- !layoutAssignments[region.name]
392
- ? 'Inheriting from parent page or site default'
393
- : undefined
394
- }
384
+
385
+ {sidebarFields.length > 0 && (
386
+ <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
387
+ <h3 className="mb-4 font-semibold">Metadata</h3>
388
+ {sidebarFields.map((field: any) => (
389
+ <div key={field.name} className="mb-4">
390
+ <FieldRenderer
391
+ field={field}
392
+ value={values[field.name]}
393
+ onChange={(val) => handleFieldChange(field.name, val)}
395
394
  />
396
- {layoutAssignments[region.name] && (
397
- <button
398
- type="button"
399
- onClick={() => {
400
- setLayoutAssignments((prev) => {
401
- const next = { ...prev };
402
- delete next[region.name];
403
- return next;
404
- });
405
- }}
406
- className="mt-1 text-xs text-[var(--primary)] hover:underline"
407
- >
408
- Clear override (inherit from parent)
409
- </button>
410
- )}
411
395
  </div>
412
396
  ))}
413
397
  </div>
414
- </div>
415
- )}
398
+ )}
399
+
400
+ <SEOPanel
401
+ title={values[useAsTitleField] ?? values.title ?? ''}
402
+ slug={docSlug}
403
+ content={htmlContent}
404
+ seoData={seoData}
405
+ onChange={setSeoData}
406
+ siteUrl={config?.siteUrl}
407
+ />
408
+
409
+ {hasLayout && (
410
+ <div className="rounded-lg border border-[var(--border)] bg-[var(--card)] p-4">
411
+ <h3 className="mb-1 font-semibold">Layout</h3>
412
+ <p className="mb-4 text-xs text-[var(--muted-foreground)]">
413
+ Assign header/footer variants. Child pages inherit from ancestors.
414
+ </p>
415
+ <div className="space-y-4">
416
+ {layoutRegions.map((region) => (
417
+ <div key={region.name}>
418
+ <RelationshipField
419
+ label={region.label}
420
+ value={layoutAssignments[region.name] ?? ''}
421
+ onChange={(val) => {
422
+ setLayoutAssignments((prev) => {
423
+ const next = { ...prev }
424
+ if (val && typeof val === 'string') {
425
+ next[region.name] = val
426
+ } else {
427
+ delete next[region.name]
428
+ }
429
+ return next
430
+ })
431
+ }}
432
+ relationTo={region.collection}
433
+ helpText={
434
+ !layoutAssignments[region.name]
435
+ ? 'Inheriting from parent page or site default'
436
+ : undefined
437
+ }
438
+ />
439
+ {layoutAssignments[region.name] && (
440
+ <button
441
+ type="button"
442
+ onClick={() => {
443
+ setLayoutAssignments((prev) => {
444
+ const next = { ...prev }
445
+ delete next[region.name]
446
+ return next
447
+ })
448
+ }}
449
+ className="mt-1 text-xs text-[var(--primary)] hover:underline"
450
+ >
451
+ Clear override (inherit from parent)
452
+ </button>
453
+ )}
454
+ </div>
455
+ ))}
456
+ </div>
457
+ </div>
458
+ )}
459
+ </div>
416
460
  </div>
417
- </div>
418
461
  )}
419
462
 
420
463
  <div className="sticky bottom-0 flex items-center justify-end gap-3 border-t border-[var(--border)] bg-[var(--background)] px-4 py-3">
421
- <Button variant="secondary" onClick={() => onNavigate?.(`/${collectionSlug}`)}>Cancel</Button>
464
+ <Button variant="secondary" onClick={() => onNavigate?.(`/${collectionSlug}`)}>
465
+ Cancel
466
+ </Button>
422
467
  <Button variant="primary" loading={saving} onClick={handleSave} data-shortcut="save">
423
468
  <Save className="h-4 w-4 mr-1.5" />
424
469
  {isNew ? 'Create' : 'Save Changes'}
@@ -444,12 +489,12 @@ export function DocumentEdit({ collectionSlug, documentId, config, onNavigate }:
444
489
  open={showVersions}
445
490
  onClose={() => setShowVersions(false)}
446
491
  onRestore={(data) => {
447
- const restoredData = data as Record<string, any>;
448
- setValues(restoredData);
449
- setInitialValues(restoredData);
492
+ const restoredData = data as Record<string, any>
493
+ setValues(restoredData)
494
+ setInitialValues(restoredData)
450
495
  }}
451
496
  />
452
497
  )}
453
498
  </div>
454
- );
499
+ )
455
500
  }