@actuate-media/cms-admin 0.7.3 → 0.8.1

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 (435) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +95 -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.d.ts.map +1 -1
  155. package/dist/lib/api.js +33 -4
  156. package/dist/lib/api.js.map +1 -1
  157. package/dist/lib/search.d.ts.map +1 -1
  158. package/dist/lib/search.js +3 -5
  159. package/dist/lib/search.js.map +1 -1
  160. package/dist/lib/useApiData.d.ts.map +1 -1
  161. package/dist/lib/useApiData.js.map +1 -1
  162. package/dist/lib/utils.d.ts.map +1 -1
  163. package/dist/lib/utils.js.map +1 -1
  164. package/dist/router/index.d.ts.map +1 -1
  165. package/dist/router/index.js +1 -3
  166. package/dist/router/index.js.map +1 -1
  167. package/dist/views/CollectionList.d.ts.map +1 -1
  168. package/dist/views/CollectionList.js +56 -17
  169. package/dist/views/CollectionList.js.map +1 -1
  170. package/dist/views/Dashboard.d.ts.map +1 -1
  171. package/dist/views/Dashboard.js +26 -13
  172. package/dist/views/Dashboard.js.map +1 -1
  173. package/dist/views/DocumentEdit.d.ts +1 -1
  174. package/dist/views/DocumentEdit.d.ts.map +1 -1
  175. package/dist/views/DocumentEdit.js +33 -15
  176. package/dist/views/DocumentEdit.js.map +1 -1
  177. package/dist/views/ForgotPassword.d.ts.map +1 -1
  178. package/dist/views/ForgotPassword.js.map +1 -1
  179. package/dist/views/FormEditor.d.ts.map +1 -1
  180. package/dist/views/FormEditor.js +8 -2
  181. package/dist/views/FormEditor.js.map +1 -1
  182. package/dist/views/FormSubmissions.d.ts.map +1 -1
  183. package/dist/views/FormSubmissions.js +6 -6
  184. package/dist/views/FormSubmissions.js.map +1 -1
  185. package/dist/views/Forms.d.ts.map +1 -1
  186. package/dist/views/Forms.js.map +1 -1
  187. package/dist/views/Login.d.ts.map +1 -1
  188. package/dist/views/Login.js +5 -2
  189. package/dist/views/Login.js.map +1 -1
  190. package/dist/views/MediaBrowser.d.ts.map +1 -1
  191. package/dist/views/MediaBrowser.js +39 -19
  192. package/dist/views/MediaBrowser.js.map +1 -1
  193. package/dist/views/PageEditor.d.ts.map +1 -1
  194. package/dist/views/PageEditor.js.map +1 -1
  195. package/dist/views/Pages.d.ts.map +1 -1
  196. package/dist/views/Pages.js +20 -10
  197. package/dist/views/Pages.js.map +1 -1
  198. package/dist/views/PostEditor.d.ts.map +1 -1
  199. package/dist/views/PostEditor.js.map +1 -1
  200. package/dist/views/Posts.d.ts.map +1 -1
  201. package/dist/views/Posts.js +13 -7
  202. package/dist/views/Posts.js.map +1 -1
  203. package/dist/views/Redirects.d.ts.map +1 -1
  204. package/dist/views/Redirects.js +17 -5
  205. package/dist/views/Redirects.js.map +1 -1
  206. package/dist/views/ResetPassword.d.ts.map +1 -1
  207. package/dist/views/ResetPassword.js.map +1 -1
  208. package/dist/views/SEO.d.ts.map +1 -1
  209. package/dist/views/SEO.js +39 -16
  210. package/dist/views/SEO.js.map +1 -1
  211. package/dist/views/ScriptTagEditor.d.ts.map +1 -1
  212. package/dist/views/ScriptTagEditor.js +2 -1
  213. package/dist/views/ScriptTagEditor.js.map +1 -1
  214. package/dist/views/ScriptTags.d.ts.map +1 -1
  215. package/dist/views/ScriptTags.js.map +1 -1
  216. package/dist/views/Settings.d.ts.map +1 -1
  217. package/dist/views/Settings.js +38 -11
  218. package/dist/views/Settings.js.map +1 -1
  219. package/dist/views/SetupWizard.d.ts.map +1 -1
  220. package/dist/views/SetupWizard.js.map +1 -1
  221. package/dist/views/Users.d.ts.map +1 -1
  222. package/dist/views/Users.js +5 -3
  223. package/dist/views/Users.js.map +1 -1
  224. package/dist/views/page-builder/AIBlockAssist.d.ts.map +1 -1
  225. package/dist/views/page-builder/AIBlockAssist.js +1 -1
  226. package/dist/views/page-builder/AIBlockAssist.js.map +1 -1
  227. package/dist/views/page-builder/AIGenerateDialog.d.ts.map +1 -1
  228. package/dist/views/page-builder/AIGenerateDialog.js +4 -1
  229. package/dist/views/page-builder/AIGenerateDialog.js.map +1 -1
  230. package/dist/views/page-builder/BlockEditor.d.ts.map +1 -1
  231. package/dist/views/page-builder/BlockEditor.js +94 -3
  232. package/dist/views/page-builder/BlockEditor.js.map +1 -1
  233. package/dist/views/page-builder/BlockPicker.d.ts.map +1 -1
  234. package/dist/views/page-builder/BlockPicker.js.map +1 -1
  235. package/dist/views/page-builder/BottomBar.d.ts.map +1 -1
  236. package/dist/views/page-builder/BottomBar.js.map +1 -1
  237. package/dist/views/page-builder/BuilderToolbar.d.ts.map +1 -1
  238. package/dist/views/page-builder/BuilderToolbar.js.map +1 -1
  239. package/dist/views/page-builder/ContextPanel.d.ts.map +1 -1
  240. package/dist/views/page-builder/ContextPanel.js +4 -1
  241. package/dist/views/page-builder/ContextPanel.js.map +1 -1
  242. package/dist/views/page-builder/DesignScore.d.ts.map +1 -1
  243. package/dist/views/page-builder/DesignScore.js.map +1 -1
  244. package/dist/views/page-builder/NodeSettings.d.ts.map +1 -1
  245. package/dist/views/page-builder/NodeSettings.js +1 -1
  246. package/dist/views/page-builder/NodeSettings.js.map +1 -1
  247. package/dist/views/page-builder/PageBuilder.d.ts +1 -1
  248. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
  249. package/dist/views/page-builder/PageBuilder.js +25 -3
  250. package/dist/views/page-builder/PageBuilder.js.map +1 -1
  251. package/dist/views/page-builder/PageSettings.d.ts.map +1 -1
  252. package/dist/views/page-builder/PageSettings.js.map +1 -1
  253. package/dist/views/page-builder/PageTemplates.d.ts.map +1 -1
  254. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  255. package/dist/views/page-builder/SEOPanel.d.ts.map +1 -1
  256. package/dist/views/page-builder/SEOPanel.js +1 -3
  257. package/dist/views/page-builder/SEOPanel.js.map +1 -1
  258. package/dist/views/page-builder/SavedSections.d.ts.map +1 -1
  259. package/dist/views/page-builder/SavedSections.js +3 -7
  260. package/dist/views/page-builder/SavedSections.js.map +1 -1
  261. package/dist/views/page-builder/TemplatePicker.d.ts.map +1 -1
  262. package/dist/views/page-builder/TemplatePicker.js.map +1 -1
  263. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts.map +1 -1
  264. package/dist/views/page-builder/block-renderers/CTAPreview.js +1 -1
  265. package/dist/views/page-builder/block-renderers/CTAPreview.js.map +1 -1
  266. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts.map +1 -1
  267. package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
  268. package/dist/views/page-builder/block-renderers/CardsPreview.js.map +1 -1
  269. package/dist/views/page-builder/block-renderers/CodePreview.d.ts.map +1 -1
  270. package/dist/views/page-builder/block-renderers/CodePreview.js +1 -5
  271. package/dist/views/page-builder/block-renderers/CodePreview.js.map +1 -1
  272. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts.map +1 -1
  273. package/dist/views/page-builder/block-renderers/FAQPreview.js +4 -1
  274. package/dist/views/page-builder/block-renderers/FAQPreview.js.map +1 -1
  275. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts.map +1 -1
  276. package/dist/views/page-builder/block-renderers/FallbackPreview.js.map +1 -1
  277. package/dist/views/page-builder/block-renderers/FormPreview.d.ts.map +1 -1
  278. package/dist/views/page-builder/block-renderers/FormPreview.js +2 -2
  279. package/dist/views/page-builder/block-renderers/FormPreview.js.map +1 -1
  280. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts.map +1 -1
  281. package/dist/views/page-builder/block-renderers/GalleryPreview.js +1 -3
  282. package/dist/views/page-builder/block-renderers/GalleryPreview.js.map +1 -1
  283. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts.map +1 -1
  284. package/dist/views/page-builder/block-renderers/HeroPreview.js.map +1 -1
  285. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts.map +1 -1
  286. package/dist/views/page-builder/block-renderers/ImagePreview.js.map +1 -1
  287. package/dist/views/page-builder/block-renderers/TextPreview.d.ts.map +1 -1
  288. package/dist/views/page-builder/block-renderers/TextPreview.js +2 -6
  289. package/dist/views/page-builder/block-renderers/TextPreview.js.map +1 -1
  290. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts.map +1 -1
  291. package/dist/views/page-builder/block-renderers/VideoPreview.js +2 -5
  292. package/dist/views/page-builder/block-renderers/VideoPreview.js.map +1 -1
  293. package/dist/views/page-builder/block-renderers/index.d.ts.map +1 -1
  294. package/dist/views/page-builder/block-renderers/index.js.map +1 -1
  295. package/dist/views/page-builder/canvas/BlockRenderer.d.ts.map +1 -1
  296. package/dist/views/page-builder/canvas/BlockRenderer.js +1 -5
  297. package/dist/views/page-builder/canvas/BlockRenderer.js.map +1 -1
  298. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts.map +1 -1
  299. package/dist/views/page-builder/canvas/BuilderCanvas.js.map +1 -1
  300. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts.map +1 -1
  301. package/dist/views/page-builder/canvas/ColumnRenderer.js +1 -5
  302. package/dist/views/page-builder/canvas/ColumnRenderer.js.map +1 -1
  303. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts.map +1 -1
  304. package/dist/views/page-builder/canvas/ContainerRenderer.js +1 -5
  305. package/dist/views/page-builder/canvas/ContainerRenderer.js.map +1 -1
  306. package/dist/views/page-builder/canvas/RowRenderer.d.ts.map +1 -1
  307. package/dist/views/page-builder/canvas/RowRenderer.js +1 -5
  308. package/dist/views/page-builder/canvas/RowRenderer.js.map +1 -1
  309. package/dist/views/page-builder/canvas/SectionRenderer.d.ts.map +1 -1
  310. package/dist/views/page-builder/canvas/SectionRenderer.js +1 -5
  311. package/dist/views/page-builder/canvas/SectionRenderer.js.map +1 -1
  312. package/dist/views/page-builder/canvas/index.d.ts.map +1 -1
  313. package/dist/views/page-builder/canvas/index.js.map +1 -1
  314. package/package.json +2 -2
  315. package/src/AdminRoot.tsx +302 -177
  316. package/src/__tests__/lib/search.test.ts +60 -69
  317. package/src/__tests__/lib/utils.test.ts +12 -12
  318. package/src/__tests__/router/match-route.test.ts +24 -26
  319. package/src/__tests__/router/strip-base.test.ts +15 -15
  320. package/src/components/Breadcrumbs.tsx +27 -24
  321. package/src/components/CommandPalette.tsx +115 -99
  322. package/src/components/ContentOverviewChart.tsx +19 -14
  323. package/src/components/ErrorBoundary.tsx +13 -13
  324. package/src/components/FocalPointPicker.tsx +31 -20
  325. package/src/components/FolderTree.tsx +172 -139
  326. package/src/components/LivePreview.tsx +68 -41
  327. package/src/components/LocaleProvider.tsx +26 -20
  328. package/src/components/LocaleSwitcher.tsx +9 -11
  329. package/src/components/MediaPickerModal.tsx +46 -45
  330. package/src/components/PresenceIndicator.tsx +30 -27
  331. package/src/components/SEOPanel.tsx +378 -228
  332. package/src/components/SEOPerformance.tsx +52 -30
  333. package/src/components/ThemeProvider.tsx +46 -46
  334. package/src/components/TipTapEditor.tsx +60 -64
  335. package/src/components/VersionHistory.tsx +63 -52
  336. package/src/components/ui/Avatar.tsx +8 -8
  337. package/src/components/ui/Badge.tsx +7 -5
  338. package/src/components/ui/Button.tsx +24 -13
  339. package/src/components/ui/CommandPalette.tsx +56 -42
  340. package/src/components/ui/ConfirmDialog.tsx +14 -14
  341. package/src/components/ui/DataTable.tsx +37 -39
  342. package/src/components/ui/EmptyState.tsx +9 -11
  343. package/src/components/ui/Modal.tsx +21 -15
  344. package/src/components/ui/Pagination.tsx +34 -19
  345. package/src/components/ui/SearchInput.tsx +17 -7
  346. package/src/components/ui/Skeleton.tsx +7 -7
  347. package/src/components/ui/Toast.tsx +29 -22
  348. package/src/components/ui/index.ts +24 -24
  349. package/src/fields/ArrayField.tsx +43 -25
  350. package/src/fields/BlockBuilderField.tsx +80 -99
  351. package/src/fields/DateField.tsx +20 -12
  352. package/src/fields/FieldRenderer.tsx +34 -34
  353. package/src/fields/GroupField.tsx +8 -10
  354. package/src/fields/MediaField.tsx +8 -10
  355. package/src/fields/NavBuilderField.tsx +24 -25
  356. package/src/fields/NumberField.tsx +21 -14
  357. package/src/fields/RelationshipField.tsx +105 -91
  358. package/src/fields/RichTextField.tsx +16 -12
  359. package/src/fields/SelectField.tsx +42 -34
  360. package/src/fields/SlugField.tsx +29 -17
  361. package/src/fields/TextField.tsx +24 -16
  362. package/src/fields/ToggleField.tsx +7 -9
  363. package/src/fields/block-types.ts +50 -24
  364. package/src/fields/index.ts +17 -17
  365. package/src/hooks/useBuilderState.ts +260 -221
  366. package/src/hooks/useContentLock.ts +23 -20
  367. package/src/hooks/useDebounce.ts +7 -7
  368. package/src/hooks/useKeyboardShortcuts.ts +16 -16
  369. package/src/index.ts +69 -58
  370. package/src/layout/Header.tsx +21 -20
  371. package/src/layout/Layout.tsx +22 -24
  372. package/src/layout/Sidebar.tsx +107 -72
  373. package/src/lib/api.ts +58 -30
  374. package/src/lib/search.ts +30 -34
  375. package/src/lib/useApiData.ts +65 -62
  376. package/src/lib/utils.ts +3 -3
  377. package/src/router/index.ts +33 -35
  378. package/src/styles/build-input.css +2 -2
  379. package/src/styles/tailwind.css +1 -1
  380. package/src/styles/theme.css +7 -1
  381. package/src/views/CollectionList.tsx +275 -121
  382. package/src/views/Dashboard.tsx +164 -117
  383. package/src/views/DocumentEdit.tsx +298 -253
  384. package/src/views/ForgotPassword.tsx +27 -23
  385. package/src/views/FormEditor.tsx +165 -99
  386. package/src/views/FormSubmissions.tsx +261 -117
  387. package/src/views/Forms.tsx +56 -26
  388. package/src/views/Login.tsx +107 -84
  389. package/src/views/MediaBrowser.tsx +717 -523
  390. package/src/views/PageEditor.tsx +44 -46
  391. package/src/views/Pages.tsx +312 -149
  392. package/src/views/PostEditor.tsx +57 -51
  393. package/src/views/Posts.tsx +206 -74
  394. package/src/views/Redirects.tsx +173 -117
  395. package/src/views/ResetPassword.tsx +43 -32
  396. package/src/views/SEO.tsx +589 -160
  397. package/src/views/ScriptTagEditor.tsx +69 -69
  398. package/src/views/ScriptTags.tsx +54 -42
  399. package/src/views/Settings.tsx +430 -220
  400. package/src/views/SetupWizard.tsx +69 -46
  401. package/src/views/Users.tsx +154 -120
  402. package/src/views/page-builder/AIBlockAssist.tsx +21 -25
  403. package/src/views/page-builder/AIGenerateDialog.tsx +134 -127
  404. package/src/views/page-builder/BlockEditor.tsx +258 -81
  405. package/src/views/page-builder/BlockPicker.tsx +73 -88
  406. package/src/views/page-builder/BottomBar.tsx +15 -11
  407. package/src/views/page-builder/BuilderToolbar.tsx +32 -29
  408. package/src/views/page-builder/ContextPanel.tsx +57 -57
  409. package/src/views/page-builder/DesignScore.tsx +52 -59
  410. package/src/views/page-builder/NodeSettings.tsx +59 -59
  411. package/src/views/page-builder/PageBuilder.tsx +164 -146
  412. package/src/views/page-builder/PageSettings.tsx +16 -15
  413. package/src/views/page-builder/PageTemplates.tsx +23 -17
  414. package/src/views/page-builder/SEOPanel.tsx +90 -111
  415. package/src/views/page-builder/SavedSections.tsx +99 -105
  416. package/src/views/page-builder/TemplatePicker.tsx +44 -48
  417. package/src/views/page-builder/block-renderers/CTAPreview.tsx +11 -13
  418. package/src/views/page-builder/block-renderers/CardsPreview.tsx +13 -15
  419. package/src/views/page-builder/block-renderers/CodePreview.tsx +16 -16
  420. package/src/views/page-builder/block-renderers/FAQPreview.tsx +20 -23
  421. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +5 -5
  422. package/src/views/page-builder/block-renderers/FormPreview.tsx +9 -13
  423. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +22 -28
  424. package/src/views/page-builder/block-renderers/HeroPreview.tsx +17 -30
  425. package/src/views/page-builder/block-renderers/ImagePreview.tsx +12 -12
  426. package/src/views/page-builder/block-renderers/TextPreview.tsx +22 -22
  427. package/src/views/page-builder/block-renderers/VideoPreview.tsx +13 -18
  428. package/src/views/page-builder/block-renderers/index.ts +17 -17
  429. package/src/views/page-builder/canvas/BlockRenderer.tsx +19 -23
  430. package/src/views/page-builder/canvas/BuilderCanvas.tsx +17 -20
  431. package/src/views/page-builder/canvas/ColumnRenderer.tsx +22 -26
  432. package/src/views/page-builder/canvas/ContainerRenderer.tsx +20 -24
  433. package/src/views/page-builder/canvas/RowRenderer.tsx +19 -23
  434. package/src/views/page-builder/canvas/SectionRenderer.tsx +30 -34
  435. package/src/views/page-builder/canvas/index.ts +2 -2
@@ -1,24 +1,26 @@
1
- 'use client';
1
+ 'use client'
2
2
 
3
- import { useState, useMemo, useCallback } from 'react';
4
- import { Star, Copy, Trash2 } from 'lucide-react';
5
- import * as SwitchPrimitive from '@radix-ui/react-switch';
6
- import type { BlockNode, BlockTypeDefinition, FieldDefinition } from '@actuate-media/cms-core';
7
- import { BlockCatalog } from '@actuate-media/cms-core';
8
- import { AIBlockAssist } from './AIBlockAssist.js';
3
+ import { useState, useMemo, useCallback } from 'react'
4
+ import { Star, Copy, Trash2 } from 'lucide-react'
5
+ import * as SwitchPrimitive from '@radix-ui/react-switch'
6
+ import type { BlockNode, BlockTypeDefinition, FieldDefinition } from '@actuate-media/cms-core'
7
+ import { BlockCatalog } from '@actuate-media/cms-core'
8
+ import { AIBlockAssist } from './AIBlockAssist.js'
9
+ import { TipTapEditor } from '../../components/TipTapEditor.js'
10
+ import { MediaPickerModal } from '../../components/MediaPickerModal.js'
9
11
 
10
12
  export interface BlockEditorProps {
11
- node: BlockNode;
12
- onUpdateBlock: (id: string, data: Record<string, unknown>) => void;
13
- onUpdateSettings: (id: string, settings: Record<string, unknown>) => void;
14
- onRemoveNode: (id: string) => void;
15
- onDuplicateNode: (id: string) => void;
16
- config: any;
13
+ node: BlockNode
14
+ onUpdateBlock: (id: string, data: Record<string, unknown>) => void
15
+ onUpdateSettings: (id: string, settings: Record<string, unknown>) => void
16
+ onRemoveNode: (id: string) => void
17
+ onDuplicateNode: (id: string) => void
18
+ config: any
17
19
  }
18
20
 
19
21
  const INPUT_CLASS =
20
- 'w-full px-3 py-2 text-sm bg-background border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring';
21
- const LABEL_CLASS = 'text-sm font-medium text-foreground mb-1 block';
22
+ 'w-full px-3 py-2 text-sm bg-background border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring'
23
+ const LABEL_CLASS = 'text-sm font-medium text-foreground mb-1 block'
22
24
 
23
25
  export function BlockEditor({
24
26
  node,
@@ -28,36 +30,36 @@ export function BlockEditor({
28
30
  onDuplicateNode,
29
31
  config,
30
32
  }: BlockEditorProps) {
31
- const [confirmDelete, setConfirmDelete] = useState(false);
33
+ const [confirmDelete, setConfirmDelete] = useState(false)
32
34
 
33
- const catalog = useMemo(() => new BlockCatalog(), []);
35
+ const catalog = useMemo(() => new BlockCatalog(), [])
34
36
  const blockDef = useMemo(
35
37
  () => catalog.get(node.settings.blockType),
36
- [catalog, node.settings.blockType]
37
- );
38
+ [catalog, node.settings.blockType],
39
+ )
38
40
 
39
41
  const handleFieldChange = useCallback(
40
42
  (fieldName: string, value: unknown) => {
41
- onUpdateBlock(node.id, { [fieldName]: value });
43
+ onUpdateBlock(node.id, { [fieldName]: value })
42
44
  },
43
- [node.id, onUpdateBlock]
44
- );
45
+ [node.id, onUpdateBlock],
46
+ )
45
47
 
46
48
  const handleVariantChange = useCallback(
47
49
  (variantName: string) => {
48
- onUpdateSettings(node.id, { variant: variantName });
50
+ onUpdateSettings(node.id, { variant: variantName })
49
51
  },
50
- [node.id, onUpdateSettings]
51
- );
52
+ [node.id, onUpdateSettings],
53
+ )
52
54
 
53
55
  const handleDelete = useCallback(() => {
54
56
  if (confirmDelete) {
55
- onRemoveNode(node.id);
56
- setConfirmDelete(false);
57
+ onRemoveNode(node.id)
58
+ setConfirmDelete(false)
57
59
  } else {
58
- setConfirmDelete(true);
60
+ setConfirmDelete(true)
59
61
  }
60
- }, [confirmDelete, node.id, onRemoveNode]);
62
+ }, [confirmDelete, node.id, onRemoveNode])
61
63
 
62
64
  if (!blockDef) {
63
65
  return (
@@ -66,7 +68,7 @@ export function BlockEditor({
66
68
  Unknown block type: <code className="text-xs">{node.settings.blockType}</code>
67
69
  </p>
68
70
  </div>
69
- );
71
+ )
70
72
  }
71
73
 
72
74
  return (
@@ -75,10 +77,7 @@ export function BlockEditor({
75
77
  <div className="flex items-center gap-2">
76
78
  <Star size={16} className="text-muted-foreground" />
77
79
  <span className="text-sm font-medium text-foreground flex-1">{blockDef.label}</span>
78
- <AIBlockAssist
79
- block={node}
80
- onUpdateData={(data) => onUpdateBlock(node.id, data)}
81
- />
80
+ <AIBlockAssist block={node} onUpdateData={(data) => onUpdateBlock(node.id, data)} />
82
81
  </div>
83
82
  {blockDef.description && (
84
83
  <p className="text-xs text-muted-foreground mt-1">{blockDef.description}</p>
@@ -148,18 +147,18 @@ export function BlockEditor({
148
147
  </button>
149
148
  </div>
150
149
  </div>
151
- );
150
+ )
152
151
  }
153
152
 
154
153
  interface FieldRendererProps {
155
- name: string;
156
- definition: FieldDefinition;
157
- value: unknown;
158
- onChange: (value: unknown) => void;
154
+ name: string
155
+ definition: FieldDefinition
156
+ value: unknown
157
+ onChange: (value: unknown) => void
159
158
  }
160
159
 
161
160
  function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps) {
162
- const label = definition.label || name;
161
+ const label = definition.label || name
163
162
 
164
163
  switch (definition.type) {
165
164
  case 'text':
@@ -174,21 +173,21 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
174
173
  className={INPUT_CLASS}
175
174
  />
176
175
  </div>
177
- );
176
+ )
178
177
 
179
178
  case 'richText':
180
179
  return (
181
180
  <div>
182
181
  <label className={LABEL_CLASS}>{label}</label>
183
- <textarea
184
- value={(value as string) ?? ''}
185
- onChange={(e) => onChange(e.target.value)}
186
- placeholder={definition.admin?.placeholder}
187
- rows={4}
188
- className={`${INPUT_CLASS} resize-y`}
189
- />
182
+ <div className="rounded-md border border-input overflow-hidden bg-background">
183
+ <TipTapEditor
184
+ content={(value as string) ?? ''}
185
+ onChange={(html) => onChange(html)}
186
+ placeholder={definition.admin?.placeholder}
187
+ />
188
+ </div>
190
189
  </div>
191
- );
190
+ )
192
191
 
193
192
  case 'url':
194
193
  return (
@@ -202,7 +201,7 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
202
201
  className={INPUT_CLASS}
203
202
  />
204
203
  </div>
205
- );
204
+ )
206
205
 
207
206
  case 'number':
208
207
  return (
@@ -218,7 +217,7 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
218
217
  className={INPUT_CLASS}
219
218
  />
220
219
  </div>
221
- );
220
+ )
222
221
 
223
222
  case 'boolean':
224
223
  return (
@@ -233,29 +232,10 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
233
232
  <SwitchPrimitive.Thumb className="block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" />
234
233
  </SwitchPrimitive.Root>
235
234
  </div>
236
- );
235
+ )
237
236
 
238
237
  case 'media':
239
- return (
240
- <div>
241
- <label className={LABEL_CLASS}>{label}</label>
242
- <div className="flex gap-2">
243
- <input
244
- type="text"
245
- value={(value as string) ?? ''}
246
- onChange={(e) => onChange(e.target.value)}
247
- placeholder="Select media..."
248
- className={`${INPUT_CLASS} flex-1`}
249
- />
250
- <button
251
- type="button"
252
- className="px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors"
253
- >
254
- Browse
255
- </button>
256
- </div>
257
- </div>
258
- );
238
+ return <MediaFieldRenderer label={label} value={value} onChange={onChange} />
259
239
 
260
240
  case 'select':
261
241
  return (
@@ -274,17 +254,46 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
274
254
  ))}
275
255
  </select>
276
256
  </div>
277
- );
257
+ )
278
258
 
279
259
  case 'array':
260
+ return <ArrayFieldRenderer label={label} value={value} onChange={onChange} />
261
+
262
+ case 'json':
263
+ return <JsonFieldRenderer label={label} value={value} onChange={onChange} />
264
+
265
+ case 'date':
280
266
  return (
281
267
  <div>
282
268
  <label className={LABEL_CLASS}>{label}</label>
283
- <div className="px-3 py-2 text-sm bg-muted border border-input rounded-md text-muted-foreground">
284
- {Array.isArray(value) ? `${value.length} items` : '0 items'}
285
- </div>
269
+ <input
270
+ type="date"
271
+ value={typeof value === 'string' && value ? value.slice(0, 10) : ''}
272
+ onChange={(e) => onChange(e.target.value || undefined)}
273
+ className={INPUT_CLASS}
274
+ />
275
+ </div>
276
+ )
277
+
278
+ case 'slug':
279
+ return (
280
+ <div>
281
+ <label className={LABEL_CLASS}>{label}</label>
282
+ <input
283
+ type="text"
284
+ value={(value as string) ?? ''}
285
+ onChange={(e) => {
286
+ const slug = e.target.value
287
+ .toLowerCase()
288
+ .replace(/[^a-z0-9-]+/g, '-')
289
+ .replace(/^-+|-+$/g, '')
290
+ onChange(slug)
291
+ }}
292
+ placeholder={definition.admin?.placeholder ?? 'page-slug'}
293
+ className={INPUT_CLASS}
294
+ />
286
295
  </div>
287
- );
296
+ )
288
297
 
289
298
  case 'relationship':
290
299
  return (
@@ -298,7 +307,7 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
298
307
  className={INPUT_CLASS}
299
308
  />
300
309
  </div>
301
- );
310
+ )
302
311
 
303
312
  case 'email':
304
313
  return (
@@ -312,7 +321,7 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
312
321
  className={INPUT_CLASS}
313
322
  />
314
323
  </div>
315
- );
324
+ )
316
325
 
317
326
  case 'color':
318
327
  return (
@@ -334,7 +343,7 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
334
343
  />
335
344
  </div>
336
345
  </div>
337
- );
346
+ )
338
347
 
339
348
  default:
340
349
  return (
@@ -347,6 +356,174 @@ function FieldRenderer({ name, definition, value, onChange }: FieldRendererProps
347
356
  className={INPUT_CLASS}
348
357
  />
349
358
  </div>
350
- );
359
+ )
360
+ }
361
+ }
362
+
363
+ interface SimpleFieldProps {
364
+ label: string
365
+ value: unknown
366
+ onChange: (value: unknown) => void
367
+ }
368
+
369
+ /**
370
+ * Block-level media picker. Wires the cross-cutting MediaPickerModal so
371
+ * custom blocks declared with `type: 'media'` actually get a working
372
+ * browse-and-select flow instead of a free-text input.
373
+ */
374
+ function MediaFieldRenderer({ label, value, onChange }: SimpleFieldProps) {
375
+ const [open, setOpen] = useState(false)
376
+ const url =
377
+ typeof value === 'string'
378
+ ? value
379
+ : value && typeof value === 'object' && 'url' in (value as any)
380
+ ? String((value as any).url)
381
+ : ''
382
+
383
+ return (
384
+ <div>
385
+ <label className={LABEL_CLASS}>{label}</label>
386
+ <div className="flex gap-2">
387
+ <input
388
+ type="text"
389
+ value={url}
390
+ onChange={(e) => onChange(e.target.value)}
391
+ placeholder="https://..."
392
+ className={`${INPUT_CLASS} flex-1`}
393
+ />
394
+ <button
395
+ type="button"
396
+ onClick={() => setOpen(true)}
397
+ className="px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors"
398
+ >
399
+ Browse
400
+ </button>
401
+ </div>
402
+ {url && /\.(png|jpe?g|gif|webp|avif|svg)(\?|$)/i.test(url) && (
403
+ <div className="mt-2 rounded-md border border-border overflow-hidden bg-muted">
404
+ {/* Plain img is fine here; admin only and we don't have next/image in scope. */}
405
+ <img src={url} alt="" className="w-full h-32 object-contain bg-checkered" />
406
+ </div>
407
+ )}
408
+ <MediaPickerModal
409
+ open={open}
410
+ onClose={() => setOpen(false)}
411
+ onSelect={(selectedUrl) => {
412
+ onChange(selectedUrl)
413
+ setOpen(false)
414
+ }}
415
+ />
416
+ </div>
417
+ )
418
+ }
419
+
420
+ /**
421
+ * JSON editor for free-form object/array fields. The textarea is the
422
+ * source of truth while the user is typing — we only commit a parsed
423
+ * value back upstream once the JSON is well-formed, otherwise the user
424
+ * sees a validation error inline. This prevents typing-induced state
425
+ * loss and keeps the UI usable for arrays of objects (a common shape
426
+ * for custom blocks).
427
+ */
428
+ function JsonFieldRenderer({ label, value, onChange }: SimpleFieldProps) {
429
+ const initial = useMemo(() => {
430
+ if (value === undefined || value === null) return ''
431
+ try {
432
+ return JSON.stringify(value, null, 2)
433
+ } catch {
434
+ return ''
435
+ }
436
+ }, [value])
437
+ const [draft, setDraft] = useState(initial)
438
+ const [error, setError] = useState<string | null>(null)
439
+
440
+ const handleChange = (next: string) => {
441
+ setDraft(next)
442
+ if (next.trim() === '') {
443
+ setError(null)
444
+ onChange(undefined)
445
+ return
446
+ }
447
+ try {
448
+ onChange(JSON.parse(next))
449
+ setError(null)
450
+ } catch (err) {
451
+ setError(err instanceof Error ? err.message : 'Invalid JSON')
452
+ }
453
+ }
454
+
455
+ return (
456
+ <div>
457
+ <label className={LABEL_CLASS}>{label}</label>
458
+ <textarea
459
+ value={draft}
460
+ onChange={(e) => handleChange(e.target.value)}
461
+ rows={6}
462
+ spellCheck={false}
463
+ className={`${INPUT_CLASS} font-mono text-xs resize-y`}
464
+ />
465
+ {error && (
466
+ <p className="mt-1 text-xs text-destructive" role="alert">
467
+ {error}
468
+ </p>
469
+ )}
470
+ </div>
471
+ )
472
+ }
473
+
474
+ /**
475
+ * Lightweight array editor — supports homogenous arrays of strings or
476
+ * objects. For block fields we deliberately keep this simple: full
477
+ * nested-field editing belongs in the document-level FieldRenderer.
478
+ */
479
+ function ArrayFieldRenderer({ label, value, onChange }: SimpleFieldProps) {
480
+ const items = Array.isArray(value) ? value : []
481
+ const isObjectArray = items.length > 0 && typeof items[0] === 'object' && items[0] !== null
482
+
483
+ if (isObjectArray) {
484
+ // For object arrays fall back to JSON — mirrors what most consumers
485
+ // expect when their block declares `type: 'array'` with no schema.
486
+ return <JsonFieldRenderer label={label} value={value} onChange={onChange} />
487
+ }
488
+
489
+ const updateItem = (idx: number, next: string) => {
490
+ const copy = [...items]
491
+ copy[idx] = next
492
+ onChange(copy)
351
493
  }
494
+ const addItem = () => onChange([...items, ''])
495
+ const removeItem = (idx: number) => onChange(items.filter((_, i) => i !== idx))
496
+
497
+ return (
498
+ <div>
499
+ <label className={LABEL_CLASS}>{label}</label>
500
+ <div className="space-y-2">
501
+ {items.map((item, idx) => (
502
+ <div key={idx} className="flex gap-2">
503
+ <input
504
+ type="text"
505
+ value={typeof item === 'string' ? item : ''}
506
+ onChange={(e) => updateItem(idx, e.target.value)}
507
+ className={`${INPUT_CLASS} flex-1`}
508
+ />
509
+ <button
510
+ type="button"
511
+ onClick={() => removeItem(idx)}
512
+ aria-label={`Remove item ${idx + 1}`}
513
+ className="px-2 py-2 text-xs text-destructive border border-input rounded-md hover:bg-destructive/10 transition-colors"
514
+ >
515
+ <Trash2 size={14} />
516
+ </button>
517
+ </div>
518
+ ))}
519
+ <button
520
+ type="button"
521
+ onClick={addItem}
522
+ className="w-full px-3 py-2 text-xs font-medium bg-accent text-foreground border border-input rounded-md hover:bg-accent/80 transition-colors"
523
+ >
524
+ + Add item
525
+ </button>
526
+ </div>
527
+ </div>
528
+ )
352
529
  }