@prenta/admin 0.98.1 → 1.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 (371) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/AdminRoot.d.ts.map +1 -1
  3. package/dist/AdminRoot.js +22 -84
  4. package/dist/AdminRoot.js.map +1 -1
  5. package/dist/__tests__/components/breakpoint-controls.render.test.js +4 -4
  6. package/dist/__tests__/components/breakpoint-controls.render.test.js.map +1 -1
  7. package/dist/__tests__/components/seo-score-bands.test.js +0 -3
  8. package/dist/__tests__/components/seo-score-bands.test.js.map +1 -1
  9. package/dist/__tests__/layout/sidebar-posts.test.js +6 -11
  10. package/dist/__tests__/layout/sidebar-posts.test.js.map +1 -1
  11. package/dist/__tests__/layout/sidebar-submenu.render.test.js +3 -2
  12. package/dist/__tests__/layout/sidebar-submenu.render.test.js.map +1 -1
  13. package/dist/__tests__/lib/open-public-site-tab.test.d.ts +2 -0
  14. package/dist/__tests__/lib/open-public-site-tab.test.d.ts.map +1 -0
  15. package/dist/__tests__/lib/open-public-site-tab.test.js +64 -0
  16. package/dist/__tests__/lib/open-public-site-tab.test.js.map +1 -0
  17. package/dist/__tests__/lib/page-editor-service-api.test.js +26 -23
  18. package/dist/__tests__/lib/page-editor-service-api.test.js.map +1 -1
  19. package/dist/__tests__/lib/view-site-chrome.test.d.ts +2 -0
  20. package/dist/__tests__/lib/view-site-chrome.test.d.ts.map +1 -0
  21. package/dist/__tests__/lib/view-site-chrome.test.js +59 -0
  22. package/dist/__tests__/lib/view-site-chrome.test.js.map +1 -0
  23. package/dist/__tests__/router/admin-routes.test.js +4 -0
  24. package/dist/__tests__/router/admin-routes.test.js.map +1 -1
  25. package/dist/__tests__/views/canvas-surface-shared.test.js +0 -16
  26. package/dist/__tests__/views/canvas-surface-shared.test.js.map +1 -1
  27. package/dist/__tests__/views/editor-top-bar.render.test.js +44 -22
  28. package/dist/__tests__/views/editor-top-bar.render.test.js.map +1 -1
  29. package/dist/__tests__/views/page-section-editor.test.js +30 -10
  30. package/dist/__tests__/views/page-section-editor.test.js.map +1 -1
  31. package/dist/__tests__/views/page-tab.render.test.js +0 -1
  32. package/dist/__tests__/views/page-tab.render.test.js.map +1 -1
  33. package/dist/__tests__/views/post-section-editor.test.js +23 -0
  34. package/dist/__tests__/views/post-section-editor.test.js.map +1 -1
  35. package/dist/components/BreakpointPicker.d.ts +3 -2
  36. package/dist/components/BreakpointPicker.d.ts.map +1 -1
  37. package/dist/components/BreakpointPicker.js +5 -3
  38. package/dist/components/BreakpointPicker.js.map +1 -1
  39. package/dist/components/CanvasEditTip.js +1 -1
  40. package/dist/components/CanvasEditTip.js.map +1 -1
  41. package/dist/index.d.ts +1 -4
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -3
  44. package/dist/index.js.map +1 -1
  45. package/dist/layout/Sidebar.d.ts +3 -4
  46. package/dist/layout/Sidebar.d.ts.map +1 -1
  47. package/dist/layout/Sidebar.js +7 -38
  48. package/dist/layout/Sidebar.js.map +1 -1
  49. package/dist/lib/editor-preview.d.ts +4 -1
  50. package/dist/lib/editor-preview.d.ts.map +1 -1
  51. package/dist/lib/editor-preview.js +4 -1
  52. package/dist/lib/editor-preview.js.map +1 -1
  53. package/dist/lib/open-public-site-tab.d.ts +14 -0
  54. package/dist/lib/open-public-site-tab.d.ts.map +1 -0
  55. package/dist/lib/open-public-site-tab.js +46 -0
  56. package/dist/lib/open-public-site-tab.js.map +1 -0
  57. package/dist/lib/page-editor-service.d.ts +0 -7
  58. package/dist/lib/page-editor-service.d.ts.map +1 -1
  59. package/dist/lib/page-editor-service.js +9 -9
  60. package/dist/lib/page-editor-service.js.map +1 -1
  61. package/dist/lib/view-site-chrome.d.ts +16 -0
  62. package/dist/lib/view-site-chrome.d.ts.map +1 -0
  63. package/dist/lib/view-site-chrome.js +15 -0
  64. package/dist/lib/view-site-chrome.js.map +1 -0
  65. package/dist/prenta-admin.css +1 -1
  66. package/dist/router/admin-routes.d.ts.map +1 -1
  67. package/dist/router/admin-routes.js +0 -2
  68. package/dist/router/admin-routes.js.map +1 -1
  69. package/dist/views/PageEditor.d.ts +2 -2
  70. package/dist/views/PageEditor.js +2 -2
  71. package/dist/views/page-editor/EditorCanvas.d.ts +1 -2
  72. package/dist/views/page-editor/EditorCanvas.d.ts.map +1 -1
  73. package/dist/views/page-editor/EditorCanvas.js +2 -2
  74. package/dist/views/page-editor/EditorCanvas.js.map +1 -1
  75. package/dist/views/page-editor/EditorTopBar.d.ts +13 -17
  76. package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
  77. package/dist/views/page-editor/EditorTopBar.js +19 -21
  78. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  79. package/dist/views/page-editor/PageSectionEditor.d.ts +1 -7
  80. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  81. package/dist/views/page-editor/PageSectionEditor.js +38 -110
  82. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  83. package/dist/views/page-editor/StructureNotice.d.ts +2 -5
  84. package/dist/views/page-editor/StructureNotice.d.ts.map +1 -1
  85. package/dist/views/page-editor/StructureNotice.js +6 -10
  86. package/dist/views/page-editor/StructureNotice.js.map +1 -1
  87. package/dist/views/post-editor/PostEditorCanvas.d.ts +1 -3
  88. package/dist/views/post-editor/PostEditorCanvas.d.ts.map +1 -1
  89. package/dist/views/post-editor/PostEditorCanvas.js +3 -3
  90. package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
  91. package/dist/views/post-editor/PostSectionEditor.d.ts +1 -15
  92. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  93. package/dist/views/post-editor/PostSectionEditor.js +30 -88
  94. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  95. package/package.json +3 -3
  96. package/src/AdminRoot.tsx +18 -138
  97. package/src/__tests__/components/breakpoint-controls.render.test.tsx +6 -4
  98. package/src/__tests__/components/seo-score-bands.test.ts +0 -3
  99. package/src/__tests__/layout/sidebar-posts.test.ts +6 -11
  100. package/src/__tests__/layout/sidebar-submenu.render.test.tsx +3 -2
  101. package/src/__tests__/lib/open-public-site-tab.test.ts +74 -0
  102. package/src/__tests__/lib/page-editor-service-api.test.ts +27 -25
  103. package/src/__tests__/lib/view-site-chrome.test.ts +65 -0
  104. package/src/__tests__/router/admin-routes.test.ts +5 -0
  105. package/src/__tests__/views/canvas-surface-shared.test.ts +0 -19
  106. package/src/__tests__/views/editor-top-bar.render.test.tsx +85 -22
  107. package/src/__tests__/views/page-section-editor.test.tsx +42 -10
  108. package/src/__tests__/views/page-tab.render.test.tsx +0 -1
  109. package/src/__tests__/views/post-section-editor.test.tsx +35 -0
  110. package/src/components/BreakpointPicker.tsx +6 -3
  111. package/src/components/CanvasEditTip.tsx +2 -2
  112. package/src/index.ts +1 -11
  113. package/src/layout/Sidebar.tsx +6 -41
  114. package/src/lib/editor-preview.ts +4 -1
  115. package/src/lib/open-public-site-tab.ts +57 -0
  116. package/src/lib/page-editor-service.ts +9 -16
  117. package/src/lib/view-site-chrome.ts +34 -0
  118. package/src/router/admin-routes.ts +0 -2
  119. package/src/styles/theme.css +4 -4
  120. package/src/views/PageEditor.tsx +2 -2
  121. package/src/views/page-editor/EditorCanvas.tsx +1 -6
  122. package/src/views/page-editor/EditorTopBar.tsx +81 -82
  123. package/src/views/page-editor/PageSectionEditor.tsx +85 -194
  124. package/src/views/page-editor/StructureNotice.tsx +7 -42
  125. package/src/views/post-editor/PostEditorCanvas.tsx +2 -8
  126. package/src/views/post-editor/PostSectionEditor.tsx +66 -138
  127. package/dist/__tests__/views/page-builder-block-renderer.render.test.d.ts +0 -2
  128. package/dist/__tests__/views/page-builder-block-renderer.render.test.d.ts.map +0 -1
  129. package/dist/__tests__/views/page-builder-block-renderer.render.test.js +0 -48
  130. package/dist/__tests__/views/page-builder-block-renderer.render.test.js.map +0 -1
  131. package/dist/__tests__/views/page-builder-form-picker.render.test.d.ts +0 -2
  132. package/dist/__tests__/views/page-builder-form-picker.render.test.d.ts.map +0 -1
  133. package/dist/__tests__/views/page-builder-form-picker.render.test.js +0 -44
  134. package/dist/__tests__/views/page-builder-form-picker.render.test.js.map +0 -1
  135. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts +0 -2
  136. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts.map +0 -1
  137. package/dist/__tests__/views/page-builder-sections-panel.render.test.js +0 -121
  138. package/dist/__tests__/views/page-builder-sections-panel.render.test.js.map +0 -1
  139. package/dist/__tests__/views/page-builder-seo-panel.render.test.d.ts +0 -2
  140. package/dist/__tests__/views/page-builder-seo-panel.render.test.d.ts.map +0 -1
  141. package/dist/__tests__/views/page-builder-seo-panel.render.test.js +0 -65
  142. package/dist/__tests__/views/page-builder-seo-panel.render.test.js.map +0 -1
  143. package/dist/__tests__/views/page-builder-template-seed.render.test.d.ts +0 -2
  144. package/dist/__tests__/views/page-builder-template-seed.render.test.d.ts.map +0 -1
  145. package/dist/__tests__/views/page-builder-template-seed.render.test.js +0 -48
  146. package/dist/__tests__/views/page-builder-template-seed.render.test.js.map +0 -1
  147. package/dist/__tests__/views/page-templates.render.test.d.ts +0 -2
  148. package/dist/__tests__/views/page-templates.render.test.d.ts.map +0 -1
  149. package/dist/__tests__/views/page-templates.render.test.js +0 -126
  150. package/dist/__tests__/views/page-templates.render.test.js.map +0 -1
  151. package/dist/__tests__/views/use-site-preview.render.test.d.ts +0 -2
  152. package/dist/__tests__/views/use-site-preview.render.test.d.ts.map +0 -1
  153. package/dist/__tests__/views/use-site-preview.render.test.js +0 -120
  154. package/dist/__tests__/views/use-site-preview.render.test.js.map +0 -1
  155. package/dist/hooks/useBuilderState.d.ts +0 -49
  156. package/dist/hooks/useBuilderState.d.ts.map +0 -1
  157. package/dist/hooks/useBuilderState.js +0 -238
  158. package/dist/hooks/useBuilderState.js.map +0 -1
  159. package/dist/views/page-builder/AIBlockAssist.d.ts +0 -9
  160. package/dist/views/page-builder/AIBlockAssist.d.ts.map +0 -1
  161. package/dist/views/page-builder/AIBlockAssist.js +0 -40
  162. package/dist/views/page-builder/AIBlockAssist.js.map +0 -1
  163. package/dist/views/page-builder/AIGenerateDialog.d.ts +0 -8
  164. package/dist/views/page-builder/AIGenerateDialog.d.ts.map +0 -1
  165. package/dist/views/page-builder/AIGenerateDialog.js +0 -173
  166. package/dist/views/page-builder/AIGenerateDialog.js.map +0 -1
  167. package/dist/views/page-builder/BlockEditor.d.ts +0 -11
  168. package/dist/views/page-builder/BlockEditor.d.ts.map +0 -1
  169. package/dist/views/page-builder/BlockEditor.js +0 -159
  170. package/dist/views/page-builder/BlockEditor.js.map +0 -1
  171. package/dist/views/page-builder/BlockPicker.d.ts +0 -7
  172. package/dist/views/page-builder/BlockPicker.d.ts.map +0 -1
  173. package/dist/views/page-builder/BlockPicker.js +0 -103
  174. package/dist/views/page-builder/BlockPicker.js.map +0 -1
  175. package/dist/views/page-builder/BottomBar.d.ts +0 -9
  176. package/dist/views/page-builder/BottomBar.d.ts.map +0 -1
  177. package/dist/views/page-builder/BottomBar.js +0 -13
  178. package/dist/views/page-builder/BottomBar.js.map +0 -1
  179. package/dist/views/page-builder/BuilderSectionsPanel.d.ts +0 -20
  180. package/dist/views/page-builder/BuilderSectionsPanel.d.ts.map +0 -1
  181. package/dist/views/page-builder/BuilderSectionsPanel.js +0 -105
  182. package/dist/views/page-builder/BuilderSectionsPanel.js.map +0 -1
  183. package/dist/views/page-builder/BuilderToolbar.d.ts +0 -21
  184. package/dist/views/page-builder/BuilderToolbar.d.ts.map +0 -1
  185. package/dist/views/page-builder/BuilderToolbar.js +0 -18
  186. package/dist/views/page-builder/BuilderToolbar.js.map +0 -1
  187. package/dist/views/page-builder/ContextPanel.d.ts +0 -20
  188. package/dist/views/page-builder/ContextPanel.d.ts.map +0 -1
  189. package/dist/views/page-builder/ContextPanel.js +0 -43
  190. package/dist/views/page-builder/ContextPanel.js.map +0 -1
  191. package/dist/views/page-builder/DesignScore.d.ts +0 -6
  192. package/dist/views/page-builder/DesignScore.d.ts.map +0 -1
  193. package/dist/views/page-builder/DesignScore.js +0 -93
  194. package/dist/views/page-builder/DesignScore.js.map +0 -1
  195. package/dist/views/page-builder/NodeSettings.d.ts +0 -12
  196. package/dist/views/page-builder/NodeSettings.d.ts.map +0 -1
  197. package/dist/views/page-builder/NodeSettings.js +0 -80
  198. package/dist/views/page-builder/NodeSettings.js.map +0 -1
  199. package/dist/views/page-builder/PageBuilder.d.ts +0 -10
  200. package/dist/views/page-builder/PageBuilder.d.ts.map +0 -1
  201. package/dist/views/page-builder/PageBuilder.js +0 -222
  202. package/dist/views/page-builder/PageBuilder.js.map +0 -1
  203. package/dist/views/page-builder/PageSettings.d.ts +0 -7
  204. package/dist/views/page-builder/PageSettings.d.ts.map +0 -1
  205. package/dist/views/page-builder/PageSettings.js +0 -27
  206. package/dist/views/page-builder/PageSettings.js.map +0 -1
  207. package/dist/views/page-builder/PageTemplates.d.ts +0 -5
  208. package/dist/views/page-builder/PageTemplates.d.ts.map +0 -1
  209. package/dist/views/page-builder/PageTemplates.js +0 -146
  210. package/dist/views/page-builder/PageTemplates.js.map +0 -1
  211. package/dist/views/page-builder/RelationshipField.d.ts +0 -15
  212. package/dist/views/page-builder/RelationshipField.d.ts.map +0 -1
  213. package/dist/views/page-builder/RelationshipField.js +0 -65
  214. package/dist/views/page-builder/RelationshipField.js.map +0 -1
  215. package/dist/views/page-builder/SEOPanel.d.ts +0 -9
  216. package/dist/views/page-builder/SEOPanel.d.ts.map +0 -1
  217. package/dist/views/page-builder/SEOPanel.js +0 -38
  218. package/dist/views/page-builder/SEOPanel.js.map +0 -1
  219. package/dist/views/page-builder/SavedSections.d.ts +0 -6
  220. package/dist/views/page-builder/SavedSections.d.ts.map +0 -1
  221. package/dist/views/page-builder/SavedSections.js +0 -141
  222. package/dist/views/page-builder/SavedSections.js.map +0 -1
  223. package/dist/views/page-builder/TemplatePicker.d.ts +0 -7
  224. package/dist/views/page-builder/TemplatePicker.d.ts.map +0 -1
  225. package/dist/views/page-builder/TemplatePicker.js +0 -68
  226. package/dist/views/page-builder/TemplatePicker.js.map +0 -1
  227. package/dist/views/page-builder/Widgets.d.ts +0 -13
  228. package/dist/views/page-builder/Widgets.d.ts.map +0 -1
  229. package/dist/views/page-builder/Widgets.js +0 -15
  230. package/dist/views/page-builder/Widgets.js.map +0 -1
  231. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts +0 -3
  232. package/dist/views/page-builder/block-renderers/CTAPreview.d.ts.map +0 -1
  233. package/dist/views/page-builder/block-renderers/CTAPreview.js +0 -19
  234. package/dist/views/page-builder/block-renderers/CTAPreview.js.map +0 -1
  235. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts +0 -3
  236. package/dist/views/page-builder/block-renderers/CardsPreview.d.ts.map +0 -1
  237. package/dist/views/page-builder/block-renderers/CardsPreview.js +0 -22
  238. package/dist/views/page-builder/block-renderers/CardsPreview.js.map +0 -1
  239. package/dist/views/page-builder/block-renderers/CodePreview.d.ts +0 -3
  240. package/dist/views/page-builder/block-renderers/CodePreview.d.ts.map +0 -1
  241. package/dist/views/page-builder/block-renderers/CodePreview.js +0 -12
  242. package/dist/views/page-builder/block-renderers/CodePreview.js.map +0 -1
  243. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts +0 -3
  244. package/dist/views/page-builder/block-renderers/FAQPreview.d.ts.map +0 -1
  245. package/dist/views/page-builder/block-renderers/FAQPreview.js +0 -27
  246. package/dist/views/page-builder/block-renderers/FAQPreview.js.map +0 -1
  247. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts +0 -6
  248. package/dist/views/page-builder/block-renderers/FallbackPreview.d.ts.map +0 -1
  249. package/dist/views/page-builder/block-renderers/FallbackPreview.js +0 -7
  250. package/dist/views/page-builder/block-renderers/FallbackPreview.js.map +0 -1
  251. package/dist/views/page-builder/block-renderers/FormPreview.d.ts +0 -9
  252. package/dist/views/page-builder/block-renderers/FormPreview.d.ts.map +0 -1
  253. package/dist/views/page-builder/block-renderers/FormPreview.js +0 -52
  254. package/dist/views/page-builder/block-renderers/FormPreview.js.map +0 -1
  255. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts +0 -3
  256. package/dist/views/page-builder/block-renderers/GalleryPreview.d.ts.map +0 -1
  257. package/dist/views/page-builder/block-renderers/GalleryPreview.js +0 -19
  258. package/dist/views/page-builder/block-renderers/GalleryPreview.js.map +0 -1
  259. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts +0 -3
  260. package/dist/views/page-builder/block-renderers/HeroPreview.d.ts.map +0 -1
  261. package/dist/views/page-builder/block-renderers/HeroPreview.js +0 -19
  262. package/dist/views/page-builder/block-renderers/HeroPreview.js.map +0 -1
  263. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts +0 -3
  264. package/dist/views/page-builder/block-renderers/ImagePreview.d.ts.map +0 -1
  265. package/dist/views/page-builder/block-renderers/ImagePreview.js +0 -17
  266. package/dist/views/page-builder/block-renderers/ImagePreview.js.map +0 -1
  267. package/dist/views/page-builder/block-renderers/TextPreview.d.ts +0 -3
  268. package/dist/views/page-builder/block-renderers/TextPreview.d.ts.map +0 -1
  269. package/dist/views/page-builder/block-renderers/TextPreview.js +0 -22
  270. package/dist/views/page-builder/block-renderers/TextPreview.js.map +0 -1
  271. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts +0 -3
  272. package/dist/views/page-builder/block-renderers/VideoPreview.d.ts.map +0 -1
  273. package/dist/views/page-builder/block-renderers/VideoPreview.js +0 -18
  274. package/dist/views/page-builder/block-renderers/VideoPreview.js.map +0 -1
  275. package/dist/views/page-builder/block-renderers/index.d.ts +0 -9
  276. package/dist/views/page-builder/block-renderers/index.d.ts.map +0 -1
  277. package/dist/views/page-builder/block-renderers/index.js +0 -25
  278. package/dist/views/page-builder/block-renderers/index.js.map +0 -1
  279. package/dist/views/page-builder/canvas/BlockRenderer.d.ts +0 -8
  280. package/dist/views/page-builder/canvas/BlockRenderer.d.ts.map +0 -1
  281. package/dist/views/page-builder/canvas/BlockRenderer.js +0 -20
  282. package/dist/views/page-builder/canvas/BlockRenderer.js.map +0 -1
  283. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts +0 -10
  284. package/dist/views/page-builder/canvas/BuilderCanvas.d.ts.map +0 -1
  285. package/dist/views/page-builder/canvas/BuilderCanvas.js +0 -26
  286. package/dist/views/page-builder/canvas/BuilderCanvas.js.map +0 -1
  287. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts +0 -8
  288. package/dist/views/page-builder/canvas/ColumnRenderer.d.ts.map +0 -1
  289. package/dist/views/page-builder/canvas/ColumnRenderer.js +0 -32
  290. package/dist/views/page-builder/canvas/ColumnRenderer.js.map +0 -1
  291. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts +0 -8
  292. package/dist/views/page-builder/canvas/ContainerRenderer.d.ts.map +0 -1
  293. package/dist/views/page-builder/canvas/ContainerRenderer.js +0 -29
  294. package/dist/views/page-builder/canvas/ContainerRenderer.js.map +0 -1
  295. package/dist/views/page-builder/canvas/RowRenderer.d.ts +0 -8
  296. package/dist/views/page-builder/canvas/RowRenderer.d.ts.map +0 -1
  297. package/dist/views/page-builder/canvas/RowRenderer.js +0 -28
  298. package/dist/views/page-builder/canvas/RowRenderer.js.map +0 -1
  299. package/dist/views/page-builder/canvas/SectionRenderer.d.ts +0 -8
  300. package/dist/views/page-builder/canvas/SectionRenderer.d.ts.map +0 -1
  301. package/dist/views/page-builder/canvas/SectionRenderer.js +0 -50
  302. package/dist/views/page-builder/canvas/SectionRenderer.js.map +0 -1
  303. package/dist/views/page-builder/canvas/index.d.ts +0 -3
  304. package/dist/views/page-builder/canvas/index.d.ts.map +0 -1
  305. package/dist/views/page-builder/canvas/index.js +0 -2
  306. package/dist/views/page-builder/canvas/index.js.map +0 -1
  307. package/dist/views/page-editor/PagePreview.d.ts +0 -13
  308. package/dist/views/page-editor/PagePreview.d.ts.map +0 -1
  309. package/dist/views/page-editor/PagePreview.js +0 -46
  310. package/dist/views/page-editor/PagePreview.js.map +0 -1
  311. package/dist/views/page-editor/SitePreviewFrame.d.ts +0 -43
  312. package/dist/views/page-editor/SitePreviewFrame.d.ts.map +0 -1
  313. package/dist/views/page-editor/SitePreviewFrame.js +0 -165
  314. package/dist/views/page-editor/SitePreviewFrame.js.map +0 -1
  315. package/dist/views/page-editor/useSitePreview.d.ts +0 -47
  316. package/dist/views/page-editor/useSitePreview.d.ts.map +0 -1
  317. package/dist/views/page-editor/useSitePreview.js +0 -96
  318. package/dist/views/page-editor/useSitePreview.js.map +0 -1
  319. package/dist/views/post-editor/PostPreview.d.ts +0 -14
  320. package/dist/views/post-editor/PostPreview.d.ts.map +0 -1
  321. package/dist/views/post-editor/PostPreview.js +0 -63
  322. package/dist/views/post-editor/PostPreview.js.map +0 -1
  323. package/src/__tests__/views/page-builder-block-renderer.render.test.tsx +0 -66
  324. package/src/__tests__/views/page-builder-form-picker.render.test.tsx +0 -54
  325. package/src/__tests__/views/page-builder-sections-panel.render.test.tsx +0 -138
  326. package/src/__tests__/views/page-builder-seo-panel.render.test.tsx +0 -77
  327. package/src/__tests__/views/page-builder-template-seed.render.test.tsx +0 -59
  328. package/src/__tests__/views/page-templates.render.test.tsx +0 -182
  329. package/src/__tests__/views/use-site-preview.render.test.tsx +0 -164
  330. package/src/hooks/useBuilderState.ts +0 -361
  331. package/src/views/page-builder/AIBlockAssist.tsx +0 -64
  332. package/src/views/page-builder/AIGenerateDialog.tsx +0 -593
  333. package/src/views/page-builder/BlockEditor.tsx +0 -523
  334. package/src/views/page-builder/BlockPicker.tsx +0 -324
  335. package/src/views/page-builder/BottomBar.tsx +0 -65
  336. package/src/views/page-builder/BuilderSectionsPanel.tsx +0 -304
  337. package/src/views/page-builder/BuilderToolbar.tsx +0 -221
  338. package/src/views/page-builder/ContextPanel.tsx +0 -144
  339. package/src/views/page-builder/DesignScore.tsx +0 -251
  340. package/src/views/page-builder/NodeSettings.tsx +0 -500
  341. package/src/views/page-builder/PageBuilder.tsx +0 -405
  342. package/src/views/page-builder/PageSettings.tsx +0 -162
  343. package/src/views/page-builder/PageTemplates.tsx +0 -435
  344. package/src/views/page-builder/RelationshipField.tsx +0 -113
  345. package/src/views/page-builder/SEOPanel.tsx +0 -222
  346. package/src/views/page-builder/SavedSections.tsx +0 -480
  347. package/src/views/page-builder/TemplatePicker.tsx +0 -197
  348. package/src/views/page-builder/Widgets.tsx +0 -44
  349. package/src/views/page-builder/block-renderers/CTAPreview.tsx +0 -79
  350. package/src/views/page-builder/block-renderers/CardsPreview.tsx +0 -69
  351. package/src/views/page-builder/block-renderers/CodePreview.tsx +0 -46
  352. package/src/views/page-builder/block-renderers/FAQPreview.tsx +0 -87
  353. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +0 -18
  354. package/src/views/page-builder/block-renderers/FormPreview.tsx +0 -117
  355. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +0 -87
  356. package/src/views/page-builder/block-renderers/HeroPreview.tsx +0 -90
  357. package/src/views/page-builder/block-renderers/ImagePreview.tsx +0 -54
  358. package/src/views/page-builder/block-renderers/TextPreview.tsx +0 -81
  359. package/src/views/page-builder/block-renderers/VideoPreview.tsx +0 -73
  360. package/src/views/page-builder/block-renderers/index.ts +0 -34
  361. package/src/views/page-builder/canvas/BlockRenderer.tsx +0 -56
  362. package/src/views/page-builder/canvas/BuilderCanvas.tsx +0 -87
  363. package/src/views/page-builder/canvas/ColumnRenderer.tsx +0 -82
  364. package/src/views/page-builder/canvas/ContainerRenderer.tsx +0 -67
  365. package/src/views/page-builder/canvas/RowRenderer.tsx +0 -68
  366. package/src/views/page-builder/canvas/SectionRenderer.tsx +0 -93
  367. package/src/views/page-builder/canvas/index.ts +0 -2
  368. package/src/views/page-editor/PagePreview.tsx +0 -105
  369. package/src/views/page-editor/SitePreviewFrame.tsx +0 -250
  370. package/src/views/page-editor/useSitePreview.ts +0 -158
  371. package/src/views/post-editor/PostPreview.tsx +0 -125
@@ -1,64 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useCallback } from 'react'
4
- import { Sparkles, Loader2 } from 'lucide-react'
5
- import { toast } from 'sonner'
6
- import { cmsApi } from '../../lib/api.js'
7
- import type { BlockNode } from '@prenta/core'
8
-
9
- export interface AIBlockAssistProps {
10
- block: BlockNode
11
- pageTitle?: string
12
- businessName?: string
13
- onUpdateData: (data: Record<string, unknown>) => void
14
- }
15
-
16
- export function AIBlockAssist({
17
- block,
18
- pageTitle,
19
- businessName,
20
- onUpdateData,
21
- }: AIBlockAssistProps) {
22
- const [generating, setGenerating] = useState(false)
23
-
24
- const handleGenerate = useCallback(async () => {
25
- setGenerating(true)
26
-
27
- try {
28
- const res = await cmsApi<Record<string, unknown>>('/page-builder/generate-block', {
29
- method: 'POST',
30
- body: JSON.stringify({
31
- blockType: block.settings.blockType,
32
- variant: block.settings.variant,
33
- pageContext: {
34
- pageTitle,
35
- businessName,
36
- },
37
- }),
38
- })
39
-
40
- if (res.error) {
41
- toast.error(res.error)
42
- } else if (res.data) {
43
- onUpdateData(res.data)
44
- toast.success('Content generated')
45
- }
46
- } catch {
47
- toast.error('Failed to generate content')
48
- } finally {
49
- setGenerating(false)
50
- }
51
- }, [block, pageTitle, businessName, onUpdateData])
52
-
53
- return (
54
- <button
55
- onClick={handleGenerate}
56
- disabled={generating}
57
- className="text-primary hover:bg-primary/10 flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors disabled:opacity-50"
58
- title="Generate content with AI"
59
- >
60
- {generating ? <Loader2 size={12} className="animate-spin" /> : <Sparkles size={12} />}
61
- {generating ? 'Generating...' : 'AI Fill'}
62
- </button>
63
- )
64
- }
@@ -1,593 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useCallback } from 'react'
4
- import * as Dialog from '@radix-ui/react-dialog'
5
- import {
6
- Sparkles,
7
- X,
8
- Loader2,
9
- Check,
10
- ChevronDown,
11
- ChevronUp,
12
- AlertTriangle,
13
- Wand2,
14
- FileText,
15
- Search,
16
- Accessibility,
17
- ArrowRight,
18
- } from 'lucide-react'
19
- import { toast } from 'sonner'
20
- import { cmsApi } from '../../lib/api.js'
21
- import { adminPortalContainer } from '../../lib/portal-container.js'
22
- import type { PageNode, GenerationStep } from '@prenta/core'
23
-
24
- export interface AIGenerateDialogProps {
25
- open: boolean
26
- onClose: () => void
27
- onAccept: (tree: PageNode) => void
28
- }
29
-
30
- interface StepInfo {
31
- key: GenerationStep
32
- label: string
33
- icon: React.ReactNode
34
- description: string
35
- }
36
-
37
- const ALL_STEPS: StepInfo[] = [
38
- {
39
- key: 'structure',
40
- label: 'Structure',
41
- icon: <Wand2 size={14} />,
42
- description: 'Generate page layout and block placement',
43
- },
44
- {
45
- key: 'content',
46
- label: 'Content',
47
- icon: <FileText size={14} />,
48
- description: 'Write compelling copy for every block',
49
- },
50
- {
51
- key: 'seo',
52
- label: 'SEO',
53
- icon: <Search size={14} />,
54
- description: 'Optimize headings, meta tags, and keywords',
55
- },
56
- {
57
- key: 'accessibility',
58
- label: 'Accessibility',
59
- icon: <Accessibility size={14} />,
60
- description: 'Fix heading hierarchy, alt text, and ARIA',
61
- },
62
- ]
63
-
64
- type Tone = 'professional' | 'casual' | 'friendly' | 'technical' | 'luxury'
65
-
66
- const TONES: { value: Tone; label: string }[] = [
67
- { value: 'professional', label: 'Professional' },
68
- { value: 'casual', label: 'Casual' },
69
- { value: 'friendly', label: 'Friendly' },
70
- { value: 'technical', label: 'Technical' },
71
- { value: 'luxury', label: 'Luxury' },
72
- ]
73
-
74
- type Phase = 'prompt' | 'generating' | 'review'
75
-
76
- interface GenerationStepResult {
77
- step: string
78
- metadata: {
79
- tokensUsed: number
80
- durationMs: number
81
- changes: string[]
82
- }
83
- }
84
-
85
- interface GenerationResultData {
86
- tree: PageNode
87
- steps: GenerationStepResult[]
88
- totalTokensUsed: number
89
- totalDurationMs: number
90
- }
91
-
92
- export function AIGenerateDialog({ open, onClose, onAccept }: AIGenerateDialogProps) {
93
- const [phase, setPhase] = useState<Phase>('prompt')
94
- const [prompt, setPrompt] = useState('')
95
- const [tone, setTone] = useState<Tone>('professional')
96
- const [enabledSteps, setEnabledSteps] = useState<Set<GenerationStep>>(
97
- new Set(['structure', 'content', 'seo', 'accessibility']),
98
- )
99
- const [showContext, setShowContext] = useState(false)
100
- const [businessName, setBusiness] = useState('')
101
- const [industry, setIndustry] = useState('')
102
- const [phone, setPhone] = useState('')
103
- const [address, setAddress] = useState('')
104
- const [services, setServices] = useState('')
105
-
106
- const [currentStep, setCurrentStep] = useState<string>('')
107
- const [completedSteps, setCompletedSteps] = useState<string[]>([])
108
- const [stepMessage, setStepMessage] = useState('')
109
-
110
- const [result, setResult] = useState<GenerationResultData | null>(null)
111
- const [error, setError] = useState<string | null>(null)
112
- const [expandedStep, setExpandedStep] = useState<string | null>(null)
113
-
114
- const toggleStep = (step: GenerationStep) => {
115
- const next = new Set(enabledSteps)
116
- if (step === 'structure') return
117
- if (next.has(step)) {
118
- next.delete(step)
119
- } else {
120
- next.add(step)
121
- }
122
- setEnabledSteps(next)
123
- }
124
-
125
- const resetState = useCallback(() => {
126
- setPhase('prompt')
127
- setPrompt('')
128
- setTone('professional')
129
- setEnabledSteps(new Set(['structure', 'content', 'seo', 'accessibility']))
130
- setShowContext(false)
131
- setBusiness('')
132
- setIndustry('')
133
- setPhone('')
134
- setAddress('')
135
- setServices('')
136
- setCurrentStep('')
137
- setCompletedSteps([])
138
- setStepMessage('')
139
- setResult(null)
140
- setError(null)
141
- setExpandedStep(null)
142
- }, [])
143
-
144
- const handleClose = useCallback(() => {
145
- resetState()
146
- onClose()
147
- }, [resetState, onClose])
148
-
149
- const handleGenerate = useCallback(async () => {
150
- if (!prompt.trim()) {
151
- toast.error('Please describe the page you want to create')
152
- return
153
- }
154
-
155
- setPhase('generating')
156
- setError(null)
157
-
158
- const steps = ALL_STEPS.filter((s) => enabledSteps.has(s.key)).map((s) => s.key)
159
-
160
- setCurrentStep(steps[0]!)
161
- setStepMessage('Starting generation...')
162
-
163
- const context: Record<string, unknown> = {}
164
- if (businessName) context.businessName = businessName
165
- if (industry) context.industry = industry
166
- if (phone) context.phone = phone
167
- if (address) context.address = address
168
- if (services)
169
- context.services = services
170
- .split(',')
171
- .map((s) => s.trim())
172
- .filter(Boolean)
173
-
174
- try {
175
- const res = await cmsApi<GenerationResultData>('/page-builder/generate', {
176
- method: 'POST',
177
- body: JSON.stringify({
178
- prompt: prompt.trim(),
179
- steps,
180
- tone,
181
- context: Object.keys(context).length > 0 ? context : undefined,
182
- }),
183
- })
184
-
185
- if (res.error) {
186
- setError(res.error)
187
- setPhase('prompt')
188
- return
189
- }
190
-
191
- if (res.data) {
192
- setResult(res.data)
193
- setCompletedSteps(res.data.steps.map((s) => s.step))
194
- setPhase('review')
195
- }
196
- } catch (err) {
197
- setError(err instanceof Error ? err.message : 'Generation failed')
198
- setPhase('prompt')
199
- }
200
- }, [prompt, tone, enabledSteps, businessName, industry, phone, address, services])
201
-
202
- const handleAccept = useCallback(() => {
203
- if (result?.tree) {
204
- onAccept(result.tree)
205
- toast.success('AI-generated page applied')
206
- handleClose()
207
- }
208
- }, [result, onAccept, handleClose])
209
-
210
- return (
211
- <Dialog.Root open={open} onOpenChange={(next) => !next && handleClose()}>
212
- <Dialog.Portal container={adminPortalContainer()}>
213
- <Dialog.Overlay className="fixed inset-0 z-50 bg-black/50" />
214
- <Dialog.Content className="bg-card border-border text-card-foreground fixed top-1/2 left-1/2 z-50 flex max-h-[85vh] w-[calc(100%-2rem)] max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border shadow-2xl focus:outline-none">
215
- {/* Header */}
216
- <div className="border-border flex items-center justify-between border-b px-6 py-4">
217
- <div className="flex items-center gap-2.5">
218
- <div className="bg-primary/10 rounded-lg p-1.5">
219
- <Sparkles size={18} className="text-primary" aria-hidden />
220
- </div>
221
- <div>
222
- <Dialog.Title className="text-foreground text-base font-medium">
223
- AI Page Generator
224
- </Dialog.Title>
225
- <Dialog.Description className="text-muted-foreground text-xs">
226
- Describe your page and let AI build it
227
- </Dialog.Description>
228
- </div>
229
- </div>
230
- <Dialog.Close asChild>
231
- <button
232
- type="button"
233
- className="hover:bg-muted text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded-md p-1.5 transition-colors focus-visible:ring-2 focus-visible:outline-none"
234
- aria-label="Close AI page generator"
235
- >
236
- <X size={16} aria-hidden />
237
- </button>
238
- </Dialog.Close>
239
- </div>
240
-
241
- {/* Content */}
242
- <div className="flex-1 overflow-y-auto p-6">
243
- {phase === 'prompt' && (
244
- <div className="space-y-5">
245
- {error && (
246
- <div className="bg-destructive/5 border-destructive/20 flex items-start gap-2.5 rounded-lg border p-3">
247
- <AlertTriangle size={16} className="text-destructive mt-0.5 shrink-0" />
248
- <p className="text-destructive text-sm">{error}</p>
249
- </div>
250
- )}
251
-
252
- {/* Prompt */}
253
- <div>
254
- <label className="text-foreground mb-1.5 block text-sm font-medium">
255
- Describe your page
256
- </label>
257
- <textarea
258
- value={prompt}
259
- onChange={(e) => setPrompt(e.target.value)}
260
- placeholder="e.g. A landing page for a plumbing company with a hero section, service cards, testimonials, and a contact form"
261
- rows={4}
262
- className="bg-background border-border focus:ring-primary/40 text-foreground placeholder:text-muted-foreground w-full resize-none rounded-lg border px-3 py-2.5 text-sm focus:ring-2 focus:outline-none"
263
- autoFocus
264
- />
265
- </div>
266
-
267
- {/* Tone */}
268
- <div>
269
- <label className="text-foreground mb-1.5 block text-sm font-medium">Tone</label>
270
- <div className="flex flex-wrap gap-2">
271
- {TONES.map((t) => (
272
- <button
273
- key={t.value}
274
- onClick={() => setTone(t.value)}
275
- className={`rounded-full border px-3 py-1.5 text-xs transition-colors ${
276
- tone === t.value
277
- ? 'border-primary bg-primary/10 text-primary'
278
- : 'border-border bg-background text-muted-foreground hover:border-primary/40'
279
- }`}
280
- >
281
- {t.label}
282
- </button>
283
- ))}
284
- </div>
285
- </div>
286
-
287
- {/* Steps */}
288
- <div>
289
- <label className="text-foreground mb-1.5 block text-sm font-medium">
290
- Generation steps
291
- </label>
292
- <div className="space-y-1.5">
293
- {ALL_STEPS.map((step) => (
294
- <label
295
- key={step.key}
296
- className={`flex cursor-pointer items-center gap-3 rounded-lg border p-2.5 transition-colors ${
297
- enabledSteps.has(step.key)
298
- ? 'border-primary/30 bg-primary/5'
299
- : 'border-border bg-background'
300
- } ${step.key === 'structure' ? 'cursor-not-allowed opacity-70' : 'hover:border-primary/20'}`}
301
- >
302
- <input
303
- type="checkbox"
304
- checked={enabledSteps.has(step.key)}
305
- onChange={() => toggleStep(step.key)}
306
- disabled={step.key === 'structure'}
307
- className="sr-only"
308
- />
309
- <div
310
- className={`flex h-5 w-5 shrink-0 items-center justify-center rounded ${
311
- enabledSteps.has(step.key)
312
- ? 'bg-primary text-primary-foreground'
313
- : 'bg-muted border-border border'
314
- }`}
315
- >
316
- {enabledSteps.has(step.key) && <Check size={12} />}
317
- </div>
318
- <div className="flex min-w-0 flex-1 items-center gap-2">
319
- <span className="text-muted-foreground">{step.icon}</span>
320
- <div>
321
- <span className="text-foreground text-sm">{step.label}</span>
322
- <span className="text-muted-foreground ml-2 text-xs">
323
- {step.description}
324
- </span>
325
- </div>
326
- </div>
327
- </label>
328
- ))}
329
- </div>
330
- </div>
331
-
332
- {/* Business context (collapsible) */}
333
- <div>
334
- <button
335
- onClick={() => setShowContext(!showContext)}
336
- className="text-muted-foreground hover:text-foreground flex items-center gap-1.5 text-sm transition-colors"
337
- >
338
- {showContext ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
339
- Business context (optional)
340
- </button>
341
- {showContext && (
342
- <div className="bg-muted/50 border-border mt-3 space-y-3 rounded-lg border p-4">
343
- <div className="grid grid-cols-2 gap-3">
344
- <div>
345
- <label className="text-muted-foreground mb-1 block text-xs">
346
- Business name
347
- </label>
348
- <input
349
- type="text"
350
- value={businessName}
351
- onChange={(e) => setBusiness(e.target.value)}
352
- className="bg-background border-border focus:ring-primary/40 text-foreground w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-2 focus:outline-none"
353
- />
354
- </div>
355
- <div>
356
- <label className="text-muted-foreground mb-1 block text-xs">
357
- Industry
358
- </label>
359
- <input
360
- type="text"
361
- value={industry}
362
- onChange={(e) => setIndustry(e.target.value)}
363
- className="bg-background border-border focus:ring-primary/40 text-foreground w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-2 focus:outline-none"
364
- />
365
- </div>
366
- <div>
367
- <label className="text-muted-foreground mb-1 block text-xs">Phone</label>
368
- <input
369
- type="text"
370
- value={phone}
371
- onChange={(e) => setPhone(e.target.value)}
372
- className="bg-background border-border focus:ring-primary/40 text-foreground w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-2 focus:outline-none"
373
- />
374
- </div>
375
- <div>
376
- <label className="text-muted-foreground mb-1 block text-xs">
377
- Address
378
- </label>
379
- <input
380
- type="text"
381
- value={address}
382
- onChange={(e) => setAddress(e.target.value)}
383
- className="bg-background border-border focus:ring-primary/40 text-foreground w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-2 focus:outline-none"
384
- />
385
- </div>
386
- </div>
387
- <div>
388
- <label className="text-muted-foreground mb-1 block text-xs">
389
- Services (comma-separated)
390
- </label>
391
- <input
392
- type="text"
393
- value={services}
394
- onChange={(e) => setServices(e.target.value)}
395
- placeholder="e.g. Web design, SEO, Content marketing"
396
- className="bg-background border-border focus:ring-primary/40 text-foreground placeholder:text-muted-foreground w-full rounded-md border px-2.5 py-1.5 text-sm focus:ring-2 focus:outline-none"
397
- />
398
- </div>
399
- </div>
400
- )}
401
- </div>
402
- </div>
403
- )}
404
-
405
- {phase === 'generating' && (
406
- <div className="space-y-6 py-8">
407
- <div className="text-center">
408
- <Loader2 size={32} className="text-primary mx-auto mb-3 animate-spin" />
409
- <p className="text-foreground text-sm font-medium">
410
- {stepMessage || 'Generating...'}
411
- </p>
412
- <p className="text-muted-foreground mt-1 text-xs">This may take 15-30 seconds</p>
413
- </div>
414
-
415
- <div className="space-y-2">
416
- {ALL_STEPS.filter((s) => enabledSteps.has(s.key)).map((step) => {
417
- const isComplete = completedSteps.includes(step.key)
418
- const isCurrent = currentStep === step.key
419
-
420
- return (
421
- <div
422
- key={step.key}
423
- className={`flex items-center gap-3 rounded-lg border p-3 transition-colors ${
424
- isComplete
425
- ? 'border-primary/30 bg-primary/5'
426
- : isCurrent
427
- ? 'border-primary/50 bg-primary/10'
428
- : 'border-border bg-muted/30'
429
- }`}
430
- >
431
- <div className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full">
432
- {isComplete ? (
433
- <div className="bg-primary flex h-6 w-6 items-center justify-center rounded-full">
434
- <Check size={12} className="text-primary-foreground" />
435
- </div>
436
- ) : isCurrent ? (
437
- <Loader2 size={16} className="text-primary animate-spin" />
438
- ) : (
439
- <div className="bg-muted border-border h-6 w-6 rounded-full border" />
440
- )}
441
- </div>
442
- <div className="flex items-center gap-2">
443
- <span className="text-muted-foreground">{step.icon}</span>
444
- <span
445
- className={`text-sm ${isCurrent || isComplete ? 'text-foreground' : 'text-muted-foreground'}`}
446
- >
447
- {step.label}
448
- </span>
449
- </div>
450
- </div>
451
- )
452
- })}
453
- </div>
454
- </div>
455
- )}
456
-
457
- {phase === 'review' && result && (
458
- <div className="space-y-5">
459
- {/* Summary */}
460
- <div className="bg-primary/5 border-primary/20 flex items-center gap-3 rounded-lg border p-4">
461
- <div className="bg-primary/10 flex h-10 w-10 shrink-0 items-center justify-center rounded-full">
462
- <Sparkles size={18} className="text-primary" />
463
- </div>
464
- <div>
465
- <p className="text-foreground text-sm font-medium">
466
- Page generated successfully
467
- </p>
468
- <p className="text-muted-foreground mt-0.5 text-xs">
469
- {result.totalTokensUsed.toLocaleString()} tokens
470
- {' \u00B7 '}
471
- {(result.totalDurationMs / 1000).toFixed(1)}s{' \u00B7 '}
472
- {result.steps.length} step{result.steps.length !== 1 ? 's' : ''}
473
- </p>
474
- </div>
475
- </div>
476
-
477
- {/* Step details */}
478
- <div className="space-y-2">
479
- <h3 className="text-foreground text-sm font-medium">Generation steps</h3>
480
- {result.steps.map((step) => {
481
- const info = ALL_STEPS.find((s) => s.key === step.step)
482
- const isExpanded = expandedStep === step.step
483
-
484
- return (
485
- <div
486
- key={step.step}
487
- className="border-border overflow-hidden rounded-lg border"
488
- >
489
- <button
490
- onClick={() => setExpandedStep(isExpanded ? null : step.step)}
491
- className="hover:bg-muted/50 flex w-full items-center gap-3 p-3 text-left transition-colors"
492
- >
493
- <div className="bg-primary flex h-6 w-6 shrink-0 items-center justify-center rounded-full">
494
- <Check size={12} className="text-primary-foreground" />
495
- </div>
496
- <span className="text-muted-foreground">{info?.icon}</span>
497
- <span className="text-foreground flex-1 text-sm">{info?.label}</span>
498
- <span className="text-muted-foreground text-xs">
499
- {(step.metadata.durationMs / 1000).toFixed(1)}s
500
- </span>
501
- {isExpanded ? (
502
- <ChevronUp size={14} className="text-muted-foreground" />
503
- ) : (
504
- <ChevronDown size={14} className="text-muted-foreground" />
505
- )}
506
- </button>
507
- {isExpanded && (
508
- <div className="border-border border-t px-3 pt-2 pb-3">
509
- <ul className="space-y-1">
510
- {step.metadata.changes.map((change, i) => (
511
- <li
512
- key={i}
513
- className="text-muted-foreground flex items-start gap-2 text-xs"
514
- >
515
- <ArrowRight size={10} className="mt-0.5 shrink-0" />
516
- {change}
517
- </li>
518
- ))}
519
- </ul>
520
- <p className="text-muted-foreground mt-2 text-xs">
521
- Tokens: {step.metadata.tokensUsed.toLocaleString()}
522
- </p>
523
- </div>
524
- )}
525
- </div>
526
- )
527
- })}
528
- </div>
529
-
530
- <p className="text-muted-foreground text-xs">
531
- Review the generated page in the canvas after accepting. You can always undo to
532
- revert.
533
- </p>
534
- </div>
535
- )}
536
- </div>
537
-
538
- {/* Footer */}
539
- <div className="border-border flex items-center justify-end gap-3 border-t px-6 py-4">
540
- {phase === 'prompt' && (
541
- <>
542
- <button
543
- onClick={handleClose}
544
- className="text-muted-foreground hover:text-foreground px-4 py-2 text-sm transition-colors"
545
- >
546
- Cancel
547
- </button>
548
- <button
549
- onClick={handleGenerate}
550
- disabled={!prompt.trim()}
551
- className="bg-primary text-primary-foreground hover:bg-primary/90 flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50"
552
- >
553
- <Sparkles size={14} />
554
- Generate Page
555
- </button>
556
- </>
557
- )}
558
-
559
- {phase === 'generating' && (
560
- <button
561
- onClick={handleClose}
562
- className="text-muted-foreground hover:text-foreground px-4 py-2 text-sm transition-colors"
563
- >
564
- Cancel
565
- </button>
566
- )}
567
-
568
- {phase === 'review' && (
569
- <>
570
- <button
571
- onClick={() => {
572
- setPhase('prompt')
573
- setResult(null)
574
- }}
575
- className="text-muted-foreground hover:text-foreground px-4 py-2 text-sm transition-colors"
576
- >
577
- Regenerate
578
- </button>
579
- <button
580
- onClick={handleAccept}
581
- className="bg-primary text-primary-foreground hover:bg-primary/90 flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors"
582
- >
583
- <Check size={14} />
584
- Accept &amp; Apply
585
- </button>
586
- </>
587
- )}
588
- </div>
589
- </Dialog.Content>
590
- </Dialog.Portal>
591
- </Dialog.Root>
592
- )
593
- }