@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,67 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import type { ContainerNode } from '@prenta/core'
5
- import { RowRenderer } from './RowRenderer.js'
6
-
7
- export interface ContainerRendererProps {
8
- node: ContainerNode
9
- selectedNodeId: string | null
10
- onSelectNode: (id: string | null) => void
11
- }
12
-
13
- export function ContainerRenderer({ node, selectedNodeId, onSelectNode }: ContainerRendererProps) {
14
- const [hovered, setHovered] = useState(false)
15
- const isSelected = selectedNodeId === node.id
16
- const maxWidth = node.settings.maxWidth ?? '1200px'
17
- const alignment = node.settings.alignment ?? 'center'
18
- const padding = node.settings.padding
19
-
20
- const marginMap: Record<string, string> = {
21
- left: '0 auto 0 0',
22
- center: '0 auto',
23
- right: '0 0 0 auto',
24
- }
25
-
26
- const handleClick = (e: React.MouseEvent) => {
27
- e.stopPropagation()
28
- onSelectNode(node.id)
29
- }
30
-
31
- return (
32
- <div
33
- data-node-id={node.id}
34
- className={`relative transition-shadow ${
35
- isSelected ? 'ring-primary ring-2 ring-offset-2' : hovered ? 'ring-primary/50 ring-1' : ''
36
- }`}
37
- style={{
38
- maxWidth,
39
- margin: marginMap[alignment] ?? '0 auto',
40
- padding,
41
- }}
42
- onClick={handleClick}
43
- onMouseEnter={(e) => {
44
- e.stopPropagation()
45
- setHovered(true)
46
- }}
47
- onMouseLeave={() => setHovered(false)}
48
- >
49
- {(hovered || isSelected) && (
50
- <span className="bg-primary text-primary-foreground absolute -top-2 -left-1 z-10 rounded px-1.5 py-0.5 text-xs font-medium">
51
- Container
52
- </span>
53
- )}
54
-
55
- <div className="flex flex-col gap-4">
56
- {node.children.map((row) => (
57
- <RowRenderer
58
- key={row.id}
59
- node={row}
60
- selectedNodeId={selectedNodeId}
61
- onSelectNode={onSelectNode}
62
- />
63
- ))}
64
- </div>
65
- </div>
66
- )
67
- }
@@ -1,68 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import type { RowNode } from '@prenta/core'
5
- import { ColumnRenderer } from './ColumnRenderer.js'
6
-
7
- export interface RowRendererProps {
8
- node: RowNode
9
- selectedNodeId: string | null
10
- onSelectNode: (id: string | null) => void
11
- }
12
-
13
- export function RowRenderer({ node, selectedNodeId, onSelectNode }: RowRendererProps) {
14
- const [hovered, setHovered] = useState(false)
15
- const isSelected = selectedNodeId === node.id
16
- const gap = node.settings.gap ?? '16px'
17
- const verticalAlign = node.settings.verticalAlign ?? 'stretch'
18
-
19
- const alignMap: Record<string, string> = {
20
- top: 'start',
21
- center: 'center',
22
- bottom: 'end',
23
- stretch: 'stretch',
24
- }
25
-
26
- const handleClick = (e: React.MouseEvent) => {
27
- e.stopPropagation()
28
- onSelectNode(node.id)
29
- }
30
-
31
- return (
32
- <div
33
- data-node-id={node.id}
34
- className={`relative transition-shadow ${
35
- isSelected ? 'ring-primary ring-2 ring-offset-2' : hovered ? 'ring-primary/50 ring-1' : ''
36
- }`}
37
- onClick={handleClick}
38
- onMouseEnter={(e) => {
39
- e.stopPropagation()
40
- setHovered(true)
41
- }}
42
- onMouseLeave={() => setHovered(false)}
43
- >
44
- {(hovered || isSelected) && (
45
- <span className="bg-primary text-primary-foreground absolute -top-2 -left-1 z-10 rounded px-1.5 py-0.5 text-xs font-medium">
46
- Row
47
- </span>
48
- )}
49
-
50
- <div
51
- className="grid grid-cols-12"
52
- style={{
53
- gap,
54
- alignItems: alignMap[verticalAlign] ?? 'stretch',
55
- }}
56
- >
57
- {node.children.map((col) => (
58
- <ColumnRenderer
59
- key={col.id}
60
- node={col}
61
- selectedNodeId={selectedNodeId}
62
- onSelectNode={onSelectNode}
63
- />
64
- ))}
65
- </div>
66
- </div>
67
- )
68
- }
@@ -1,93 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import type { SectionNode } from '@prenta/core'
5
- import { ContainerRenderer } from './ContainerRenderer.js'
6
- import { RowRenderer } from './RowRenderer.js'
7
-
8
- export interface SectionRendererProps {
9
- node: SectionNode
10
- selectedNodeId: string | null
11
- onSelectNode: (id: string | null) => void
12
- }
13
-
14
- export function SectionRenderer({ node, selectedNodeId, onSelectNode }: SectionRendererProps) {
15
- const [hovered, setHovered] = useState(false)
16
- const isSelected = selectedNodeId === node.id
17
-
18
- const handleClick = (e: React.MouseEvent) => {
19
- e.stopPropagation()
20
- onSelectNode(node.id)
21
- }
22
-
23
- const backgroundStyle: React.CSSProperties = {}
24
- if (node.settings.background) {
25
- backgroundStyle.backgroundColor = node.settings.background
26
- }
27
- if (node.settings.backgroundImage) {
28
- backgroundStyle.backgroundImage = `url(${node.settings.backgroundImage})`
29
- backgroundStyle.backgroundSize = 'cover'
30
- backgroundStyle.backgroundPosition = 'center'
31
- }
32
- if (node.settings.backgroundGradient) {
33
- backgroundStyle.backgroundImage = node.settings.backgroundGradient
34
- }
35
- if (node.settings.paddingTop) {
36
- backgroundStyle.paddingTop = node.settings.paddingTop
37
- }
38
- if (node.settings.paddingBottom) {
39
- backgroundStyle.paddingBottom = node.settings.paddingBottom
40
- }
41
- if (node.settings.marginTop) {
42
- backgroundStyle.marginTop = node.settings.marginTop
43
- }
44
- if (node.settings.marginBottom) {
45
- backgroundStyle.marginBottom = node.settings.marginBottom
46
- }
47
-
48
- return (
49
- <div
50
- data-node-id={node.id}
51
- className={`relative w-full transition-shadow ${
52
- isSelected ? 'ring-primary ring-2 ring-offset-2' : hovered ? 'ring-primary/50 ring-1' : ''
53
- }`}
54
- style={backgroundStyle}
55
- onClick={handleClick}
56
- onMouseEnter={(e) => {
57
- e.stopPropagation()
58
- setHovered(true)
59
- }}
60
- onMouseLeave={() => setHovered(false)}
61
- >
62
- {(hovered || isSelected) && (
63
- <span className="bg-primary text-primary-foreground absolute -top-2 -left-1 z-10 rounded px-1.5 py-0.5 text-xs font-medium">
64
- Section
65
- </span>
66
- )}
67
-
68
- {node.children.map((child) => {
69
- if (child.type === 'container') {
70
- return (
71
- <ContainerRenderer
72
- key={child.id}
73
- node={child}
74
- selectedNodeId={selectedNodeId}
75
- onSelectNode={onSelectNode}
76
- />
77
- )
78
- }
79
- if (child.type === 'row') {
80
- return (
81
- <RowRenderer
82
- key={child.id}
83
- node={child}
84
- selectedNodeId={selectedNodeId}
85
- onSelectNode={onSelectNode}
86
- />
87
- )
88
- }
89
- return null
90
- })}
91
- </div>
92
- )
93
- }
@@ -1,2 +0,0 @@
1
- export { BuilderCanvas } from './BuilderCanvas.js'
2
- export type { BuilderCanvasProps } from './BuilderCanvas.js'
@@ -1,105 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useState } from 'react'
4
- import { AlertTriangle, Loader2, Pencil, X } from 'lucide-react'
5
- import { fetchPageForEditor, type EditorPage } from '../../lib/page-editor-service.js'
6
- import { SectionRenderer } from './sections/index.js'
7
-
8
- interface PagePreviewProps {
9
- documentId: string
10
- onNavigate: (path: string) => void
11
- }
12
-
13
- /**
14
- * Clean, chrome-free render of a page using the SAME section renderers as
15
- * the editor canvas — so the preview reflects what will actually ship.
16
- * Only visible sections are rendered (hidden sections are omitted, exactly
17
- * as the public page would behave).
18
- */
19
- export function PagePreview({ documentId, onNavigate }: PagePreviewProps) {
20
- const [page, setPage] = useState<EditorPage | null>(null)
21
- const [loading, setLoading] = useState(true)
22
- const [error, setError] = useState<string | null>(null)
23
-
24
- useEffect(() => {
25
- let cancelled = false
26
- setLoading(true)
27
- fetchPageForEditor(documentId)
28
- .then((p) => !cancelled && setPage(p))
29
- .catch((err) => !cancelled && setError(err instanceof Error ? err.message : 'Failed to load'))
30
- .finally(() => !cancelled && setLoading(false))
31
- return () => {
32
- cancelled = true
33
- }
34
- }, [documentId])
35
-
36
- if (loading) {
37
- return (
38
- <div className="bg-background flex h-full items-center justify-center">
39
- <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" aria-hidden />
40
- <span className="sr-only">Loading preview…</span>
41
- </div>
42
- )
43
- }
44
-
45
- if (error || !page) {
46
- return (
47
- <div className="bg-background flex h-full items-center justify-center p-6">
48
- <div className="border-destructive/30 bg-destructive/5 flex max-w-md items-center gap-3 rounded-lg border p-4">
49
- <AlertTriangle className="text-destructive shrink-0" size={20} aria-hidden />
50
- <p className="text-foreground text-sm font-medium">{error ?? 'Page not found.'}</p>
51
- </div>
52
- </div>
53
- )
54
- }
55
-
56
- const visible = page.sections.filter((s) => s.visible)
57
-
58
- return (
59
- <div className="flex h-full flex-col">
60
- {/* Slim preview bar — the only chrome; the page itself renders clean.
61
- This view opens in its own browser tab, so actions are tab-scoped. */}
62
- <div className="bg-card border-border flex h-12 shrink-0 items-center justify-between border-b px-4">
63
- <button
64
- type="button"
65
- onClick={() => {
66
- // Opened via the editor's "Preview" (script-opened tab) → close
67
- // it. Opened by navigating to the URL directly (no opener, so
68
- // `window.close()` is a no-op) → fall back to the editor so the
69
- // button is never dead.
70
- if (window.opener) window.close()
71
- else onNavigate(`/pages/${documentId}/edit`)
72
- }}
73
- className="text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5 text-sm"
74
- aria-label="Close preview tab"
75
- >
76
- <X className="h-4 w-4" aria-hidden />
77
- Close
78
- </button>
79
- <span className="text-muted-foreground text-xs">
80
- Preview · {page.title || 'Untitled'} {page.path}
81
- </span>
82
- <button
83
- type="button"
84
- onClick={() => onNavigate(`/pages/${documentId}/edit`)}
85
- className="bg-primary text-primary-foreground hover:bg-primary/90 inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium"
86
- >
87
- <Pencil className="h-3.5 w-3.5" aria-hidden />
88
- Open editor
89
- </button>
90
- </div>
91
-
92
- {/* The canvas is intentionally white regardless of the admin theme:
93
- it emulates the public page surface, not admin chrome. */}
94
- <div className="prenta-canvas bg-card flex-1 overflow-auto">
95
- {visible.length === 0 ? (
96
- <div className="text-muted-foreground flex h-full items-center justify-center text-sm">
97
- This page has no visible sections yet.
98
- </div>
99
- ) : (
100
- visible.map((section) => <SectionRenderer key={section.id} section={section} />)
101
- )}
102
- </div>
103
- </div>
104
- )
105
- }
@@ -1,250 +0,0 @@
1
- 'use client'
2
-
3
- import { useEffect, useLayoutEffect, useRef, useState } from 'react'
4
- import { Loader2 } from 'lucide-react'
5
- import { injectPreviewEditChrome } from '../../lib/canvas-edit-chrome.js'
6
- import {
7
- canvasOriginFromSrc,
8
- isPreviewBridgeMessage,
9
- isPreviewEditMessage,
10
- isPreviewRequestMediaMessage,
11
- PREVIEW_BRIDGE_VERSION,
12
- PREVIEW_SECTIONS_DEBOUNCE_MS,
13
- toPreviewSectionPayload,
14
- type PreviewHighlightMessage,
15
- type PreviewModeMessage,
16
- type PreviewSectionPayload,
17
- type PreviewSectionsMessage,
18
- } from '../../lib/preview-bridge.js'
19
- import { getViewport, type ViewportId } from './viewports.js'
20
-
21
- export interface CanvasEditPayload {
22
- sectionId: string
23
- fieldPath: string
24
- value: string
25
- }
26
-
27
- export interface CanvasMediaRequestPayload {
28
- sectionId: string
29
- fieldPath: string
30
- }
31
-
32
- interface SitePreviewFrameProps {
33
- /** Canvas draft URL; null while the preview token is still minting. */
34
- src: string | null
35
- viewport: ViewportId
36
- /** Changing this remounts the iframe so it reloads the persisted draft. */
37
- reloadKey: number
38
- title?: string
39
- /** Currently selected section in the editor — pushed to the canvas as a highlight. */
40
- selectedId?: string | null
41
- /** Live editor sections — debounced push after canvas ready (Phase 3). */
42
- sections?: PreviewSectionPayload[]
43
- /**
44
- * Increment after a canvas-originated text edit so the next sections push is
45
- * skipped (avoids remounting a focused contenteditable).
46
- */
47
- suppressSectionsEcho?: number
48
- /** Canvas → admin: section (and optional field) clicked in the real design. */
49
- onSelectSection?: (sectionId: string | null, fieldPath?: string) => void
50
- /** Canvas → admin: inline text edit (Stage 3). */
51
- onCanvasEdit?: (edit: CanvasEditPayload) => void
52
- /** Canvas → admin: open media picker for a field (Stage 3 wave B). */
53
- onCanvasRequestMedia?: (request: CanvasMediaRequestPayload) => void
54
- }
55
-
56
- /**
57
- * Inline branded preview surface — Next builder route in an iframe at the
58
- * selected viewport's *true* CSS width, CSS-`transform: scale()`'d to fit
59
- * (never crop). Stage 3: mode / edit / request-media + suppress-echo for
60
- * canvas-originated text edits.
61
- */
62
- export function SitePreviewFrame({
63
- src,
64
- viewport,
65
- reloadKey,
66
- title = 'Site preview',
67
- selectedId = null,
68
- sections,
69
- suppressSectionsEcho = 0,
70
- onSelectSection,
71
- onCanvasEdit,
72
- onCanvasRequestMedia,
73
- }: SitePreviewFrameProps) {
74
- const vp = getViewport(viewport)
75
- const containerRef = useRef<HTMLDivElement>(null)
76
- const sentinelRef = useRef<HTMLDivElement>(null)
77
- const iframeRef = useRef<HTMLIFrameElement>(null)
78
- const [scale, setScale] = useState(1)
79
- const [frameHeight, setFrameHeight] = useState(600)
80
- const [loaded, setLoaded] = useState(false)
81
- const [canvasReady, setCanvasReady] = useState(false)
82
- const canvasOrigin = canvasOriginFromSrc(src)
83
- const lastSuppressRef = useRef(suppressSectionsEcho)
84
-
85
- /**
86
- * Measure from a zero-height sentinel, never `clientWidth - 48`.
87
- *
88
- * The 48 was `p-6` written down a second time, in a second unit, four
89
- * hundred lines from the class it mirrors. It disagrees with reality the
90
- * moment a scrollbar appears, and it rots silently if the gutter ever
91
- * changes — nothing fails, the preview just scales slightly wrong.
92
- *
93
- * The sentinel is subject to the same padding, the same scrollbar and the
94
- * same host scaling as the frame, so its `offsetWidth` IS the usable width
95
- * and there is no arithmetic to get wrong. Same rule as `CanvasSurface`,
96
- * which is where this was first learned; this file is the third copy of the
97
- * arithmetic and the last one to go.
98
- *
99
- * Height still comes from the container, because the sentinel is
100
- * deliberately zero-height and can say nothing about it — but it is read as
101
- * `clientHeight - (clientWidth - sentinelWidth)`, deriving the vertical
102
- * gutter from the measured horizontal one rather than hardcoding it again.
103
- * That holds for the symmetric `p-6` this uses and degrades to the old
104
- * behaviour rather than breaking if it ever stops being symmetric.
105
- */
106
- useLayoutEffect(() => {
107
- const container = containerRef.current
108
- const sentinel = sentinelRef.current
109
- if (!container || !sentinel) return
110
- const recompute = () => {
111
- const availableW = sentinel.offsetWidth
112
- if (availableW <= 0) return
113
- const gutter = Math.max(0, container.clientWidth - availableW)
114
- const availableH = container.clientHeight - gutter
115
- const next = Math.min(1, availableW / vp.width)
116
- setScale(next > 0 ? next : 1)
117
- setFrameHeight(availableH > 0 ? availableH : 600)
118
- }
119
- recompute()
120
- const ro = new ResizeObserver(recompute)
121
- ro.observe(container)
122
- ro.observe(sentinel)
123
- return () => ro.disconnect()
124
- }, [vp.width])
125
-
126
- useEffect(() => {
127
- setLoaded(false)
128
- setCanvasReady(false)
129
- }, [src, reloadKey])
130
-
131
- // Canvas → admin: ready handshake + select + edit + request-media.
132
- useEffect(() => {
133
- if (!canvasOrigin) return
134
- const onMessage = (event: MessageEvent) => {
135
- if (event.origin !== canvasOrigin) return
136
- if (!isPreviewBridgeMessage(event.data)) return
137
- if (event.data.type === 'prenta-preview:ready') {
138
- setCanvasReady(true)
139
- return
140
- }
141
- if (event.data.type === 'prenta-preview:select' && onSelectSection) {
142
- onSelectSection(event.data.sectionId, event.data.fieldPath)
143
- return
144
- }
145
- if (isPreviewEditMessage(event.data) && onCanvasEdit) {
146
- onCanvasEdit({
147
- sectionId: event.data.sectionId,
148
- fieldPath: event.data.fieldPath,
149
- value: event.data.value,
150
- })
151
- return
152
- }
153
- if (isPreviewRequestMediaMessage(event.data) && onCanvasRequestMedia) {
154
- onCanvasRequestMedia({
155
- sectionId: event.data.sectionId,
156
- fieldPath: event.data.fieldPath,
157
- })
158
- }
159
- }
160
- window.addEventListener('message', onMessage)
161
- return () => window.removeEventListener('message', onMessage)
162
- }, [canvasOrigin, onSelectSection, onCanvasEdit, onCanvasRequestMedia])
163
-
164
- // Admin → canvas: enable inline editing once the canvas is ready.
165
- useEffect(() => {
166
- if (!canvasOrigin || !loaded || !canvasReady) return
167
- const win = iframeRef.current?.contentWindow
168
- if (!win) return
169
- const msg: PreviewModeMessage = {
170
- type: 'prenta-preview:mode',
171
- v: PREVIEW_BRIDGE_VERSION,
172
- editing: true,
173
- }
174
- win.postMessage(msg, canvasOrigin)
175
- // Same-origin only — cross-origin previews skip silently.
176
- injectPreviewEditChrome(iframeRef.current)
177
- }, [canvasOrigin, loaded, canvasReady, reloadKey])
178
-
179
- // Admin → canvas: highlight the selected section.
180
- useEffect(() => {
181
- if (!canvasOrigin || !loaded || !canvasReady) return
182
- const win = iframeRef.current?.contentWindow
183
- if (!win) return
184
- const msg: PreviewHighlightMessage = {
185
- type: 'prenta-preview:highlight',
186
- v: PREVIEW_BRIDGE_VERSION,
187
- sectionId: selectedId,
188
- }
189
- win.postMessage(msg, canvasOrigin)
190
- }, [canvasOrigin, selectedId, loaded, canvasReady, reloadKey])
191
-
192
- // Admin → canvas: live section content (debounced). Skip one cycle after
193
- // canvas-originated text edits so contenteditable does not remount.
194
- useEffect(() => {
195
- if (!canvasOrigin || !loaded || !canvasReady || !sections) return
196
- if (suppressSectionsEcho !== lastSuppressRef.current) {
197
- lastSuppressRef.current = suppressSectionsEcho
198
- return
199
- }
200
- const win = iframeRef.current?.contentWindow
201
- if (!win) return
202
- const timer = window.setTimeout(() => {
203
- const msg: PreviewSectionsMessage = {
204
- type: 'prenta-preview:sections',
205
- v: PREVIEW_BRIDGE_VERSION,
206
- sections: sections.map(toPreviewSectionPayload),
207
- }
208
- win.postMessage(msg, canvasOrigin)
209
- }, PREVIEW_SECTIONS_DEBOUNCE_MS)
210
- return () => window.clearTimeout(timer)
211
- }, [canvasOrigin, loaded, canvasReady, sections, reloadKey, suppressSectionsEcho])
212
-
213
- return (
214
- <div ref={containerRef} className="bg-muted relative h-full overflow-hidden p-6">
215
- {/*
216
- * Zero-height sentinel — see the measurement effect above. Must stay the
217
- * first child and must stay zero-height. `absolute` would defeat it: it
218
- * has to sit in the padding box to inherit the gutter it is measuring.
219
- */}
220
- <div ref={sentinelRef} aria-hidden className="h-0" />
221
- {(!src || !loaded) && (
222
- <div
223
- className="absolute inset-0 z-10 flex flex-col items-center justify-center gap-2"
224
- aria-live="polite"
225
- >
226
- <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" aria-hidden />
227
- <span className="text-muted-foreground text-sm">Loading site preview…</span>
228
- </div>
229
- )}
230
- {src && (
231
- <div className="mx-auto" style={{ width: vp.width * scale, height: frameHeight }}>
232
- <iframe
233
- key={reloadKey}
234
- ref={iframeRef}
235
- src={src}
236
- title={title}
237
- onLoad={() => setLoaded(true)}
238
- className="border-border bg-card rounded-xl border shadow-sm"
239
- style={{
240
- width: vp.width,
241
- height: frameHeight / scale,
242
- transform: `scale(${scale})`,
243
- transformOrigin: 'top left',
244
- }}
245
- />
246
- </div>
247
- )}
248
- </div>
249
- )
250
- }