@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,324 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useMemo, useRef, useEffect, useCallback } from 'react'
4
- import * as Dialog from '@radix-ui/react-dialog'
5
- import { adminPortalContainer } from '../../lib/portal-container.js'
6
- import {
7
- Star,
8
- Type,
9
- Image,
10
- LayoutGrid,
11
- MousePointer,
12
- Play,
13
- Grid,
14
- HelpCircle,
15
- FileText,
16
- Code,
17
- Box,
18
- X,
19
- ArrowLeft,
20
- Search,
21
- Check,
22
- } from 'lucide-react'
23
- import type { LucideIcon } from 'lucide-react'
24
- import { BlockCatalog } from '@prenta/core/page-builder'
25
- import type { BlockTypeDefinition, VariantDefinition } from '@prenta/core'
26
-
27
- export interface BlockPickerProps {
28
- open: boolean
29
- onClose: () => void
30
- onSelect: (blockType: string, variant?: string) => void
31
- }
32
-
33
- const iconMap: Record<string, LucideIcon> = {
34
- Star,
35
- Type,
36
- Image,
37
- LayoutGrid,
38
- MousePointer,
39
- Play,
40
- Grid,
41
- HelpCircle,
42
- FileText,
43
- Code,
44
- }
45
-
46
- function resolveIcon(name: string): LucideIcon {
47
- return iconMap[name] ?? Box
48
- }
49
-
50
- export function BlockPicker({ open, onClose, onSelect }: BlockPickerProps) {
51
- const [search, setSearch] = useState('')
52
- const [selectedBlock, setSelectedBlock] = useState<BlockTypeDefinition | null>(null)
53
- const searchInputRef = useRef<HTMLInputElement>(null)
54
- const variantListRef = useRef<HTMLDivElement>(null)
55
-
56
- const catalog = useMemo(() => new BlockCatalog(), [])
57
- const allBlocks = useMemo(() => catalog.getAll(), [catalog])
58
-
59
- const filteredBlocks = useMemo(() => {
60
- if (!search.trim()) return allBlocks
61
- const q = search.toLowerCase()
62
- return allBlocks.filter(
63
- (block) =>
64
- block.label.toLowerCase().includes(q) ||
65
- (block.description?.toLowerCase().includes(q) ?? false),
66
- )
67
- }, [allBlocks, search])
68
-
69
- const resetState = useCallback(() => {
70
- setSearch('')
71
- setSelectedBlock(null)
72
- }, [])
73
-
74
- useEffect(() => {
75
- if (open) {
76
- resetState()
77
- }
78
- }, [open, resetState])
79
-
80
- useEffect(() => {
81
- if (open && !selectedBlock) {
82
- const timer = setTimeout(() => searchInputRef.current?.focus(), 50)
83
- return () => clearTimeout(timer)
84
- }
85
- }, [open, selectedBlock])
86
-
87
- useEffect(() => {
88
- if (selectedBlock && variantListRef.current) {
89
- const firstButton =
90
- variantListRef.current.querySelector<HTMLButtonElement>('button[data-variant]')
91
- firstButton?.focus()
92
- }
93
- }, [selectedBlock])
94
-
95
- function handleBlockClick(block: BlockTypeDefinition) {
96
- if (block.variants.length === 1) {
97
- onSelect(block.type, block.variants[0]!.name)
98
- onClose()
99
- return
100
- }
101
- setSelectedBlock(block)
102
- }
103
-
104
- function handleVariantClick(variant: VariantDefinition) {
105
- if (!selectedBlock) return
106
- onSelect(selectedBlock.type, variant.name)
107
- onClose()
108
- }
109
-
110
- function handleBack() {
111
- setSelectedBlock(null)
112
- }
113
-
114
- function handleKeyDownOnGrid(e: React.KeyboardEvent) {
115
- if (e.key === 'Escape') {
116
- e.stopPropagation()
117
- onClose()
118
- }
119
- }
120
-
121
- function handleKeyDownOnVariants(e: React.KeyboardEvent) {
122
- if (e.key === 'Escape') {
123
- e.stopPropagation()
124
- handleBack()
125
- }
126
- }
127
-
128
- return (
129
- <Dialog.Root open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
130
- <Dialog.Portal container={adminPortalContainer()}>
131
- <Dialog.Overlay className="motion-safe:animate-in motion-safe:fade-in-0 fixed inset-0 z-50 bg-black/50" />
132
- <Dialog.Content
133
- className="bg-card border-border fixed top-1/2 left-1/2 z-50 flex max-h-[80vh] w-full max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border shadow-2xl"
134
- aria-describedby={undefined}
135
- onEscapeKeyDown={() => {
136
- if (selectedBlock) {
137
- handleBack()
138
- }
139
- }}
140
- >
141
- {selectedBlock ? (
142
- <VariantView
143
- block={selectedBlock}
144
- variantListRef={variantListRef}
145
- onBack={handleBack}
146
- onVariantClick={handleVariantClick}
147
- onKeyDown={handleKeyDownOnVariants}
148
- />
149
- ) : (
150
- <BlockTypeGrid
151
- search={search}
152
- filteredBlocks={filteredBlocks}
153
- searchInputRef={searchInputRef}
154
- onSearchChange={setSearch}
155
- onBlockClick={handleBlockClick}
156
- onClose={onClose}
157
- onKeyDown={handleKeyDownOnGrid}
158
- />
159
- )}
160
- </Dialog.Content>
161
- </Dialog.Portal>
162
- </Dialog.Root>
163
- )
164
- }
165
-
166
- interface BlockTypeGridProps {
167
- search: string
168
- filteredBlocks: BlockTypeDefinition[]
169
- searchInputRef: React.RefObject<HTMLInputElement | null>
170
- onSearchChange: (value: string) => void
171
- onBlockClick: (block: BlockTypeDefinition) => void
172
- onClose: () => void
173
- onKeyDown: (e: React.KeyboardEvent) => void
174
- }
175
-
176
- function BlockTypeGrid({
177
- search,
178
- filteredBlocks,
179
- searchInputRef,
180
- onSearchChange,
181
- onBlockClick,
182
- onClose,
183
- onKeyDown,
184
- }: BlockTypeGridProps) {
185
- return (
186
- <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
187
- <div className="flex items-center justify-between gap-3 px-5 pt-5 pb-3">
188
- <Dialog.Title className="text-foreground text-lg font-medium">Add Block</Dialog.Title>
189
- <Dialog.Close asChild>
190
- <button
191
- type="button"
192
- className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
193
- aria-label="Close"
194
- >
195
- <X size={18} />
196
- </button>
197
- </Dialog.Close>
198
- </div>
199
-
200
- <div className="px-5 pb-3">
201
- <div className="relative">
202
- <Search
203
- className="text-muted-foreground pointer-events-none absolute top-1/2 left-3 -translate-y-1/2"
204
- size={16}
205
- />
206
- <input
207
- ref={searchInputRef}
208
- type="text"
209
- placeholder="Search blocks..."
210
- value={search}
211
- onChange={(e) => onSearchChange(e.target.value)}
212
- className="bg-background border-input focus:ring-ring w-full rounded-md border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
213
- aria-label="Search block types"
214
- />
215
- </div>
216
- </div>
217
-
218
- <div className="flex-1 overflow-y-auto px-5 pb-5">
219
- {filteredBlocks.length === 0 ? (
220
- <div className="flex flex-col items-center justify-center py-12 text-center">
221
- <Search size={24} className="text-muted-foreground mb-2" />
222
- <p className="text-muted-foreground text-sm">No blocks match &ldquo;{search}&rdquo;</p>
223
- </div>
224
- ) : (
225
- <div className="grid grid-cols-2 gap-3" role="list" aria-label="Available block types">
226
- {filteredBlocks.map((block) => {
227
- const Icon = resolveIcon(block.icon)
228
- return (
229
- <button
230
- key={block.type}
231
- type="button"
232
- role="listitem"
233
- onClick={() => onBlockClick(block)}
234
- className="border-border hover:border-primary bg-card group focus:ring-ring flex cursor-pointer items-start gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
235
- >
236
- <div className="bg-accent text-foreground group-hover:bg-primary/10 group-hover:text-primary flex h-9 w-9 shrink-0 items-center justify-center rounded-md transition-colors">
237
- <Icon size={18} />
238
- </div>
239
- <div className="min-w-0">
240
- <p className="text-foreground truncate text-sm font-medium">{block.label}</p>
241
- {block.description && (
242
- <p className="text-muted-foreground mt-0.5 line-clamp-2 text-xs">
243
- {block.description}
244
- </p>
245
- )}
246
- </div>
247
- </button>
248
- )
249
- })}
250
- </div>
251
- )}
252
- </div>
253
- </div>
254
- )
255
- }
256
-
257
- interface VariantViewProps {
258
- block: BlockTypeDefinition
259
- variantListRef: React.RefObject<HTMLDivElement | null>
260
- onBack: () => void
261
- onVariantClick: (variant: VariantDefinition) => void
262
- onKeyDown: (e: React.KeyboardEvent) => void
263
- }
264
-
265
- function VariantView({
266
- block,
267
- variantListRef,
268
- onBack,
269
- onVariantClick,
270
- onKeyDown,
271
- }: VariantViewProps) {
272
- const Icon = resolveIcon(block.icon)
273
-
274
- return (
275
- <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
276
- <div className="flex items-center gap-3 px-5 pt-5 pb-3">
277
- <button
278
- type="button"
279
- onClick={onBack}
280
- className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
281
- aria-label="Back to block types"
282
- >
283
- <ArrowLeft size={18} />
284
- </button>
285
- <div className="flex min-w-0 items-center gap-2">
286
- <Icon size={18} className="text-foreground shrink-0" />
287
- <h2 className="text-foreground truncate text-lg font-medium">{block.label}</h2>
288
- </div>
289
- </div>
290
-
291
- {block.description && (
292
- <p className="text-muted-foreground px-5 pb-3 text-sm">{block.description}</p>
293
- )}
294
-
295
- <div className="flex-1 overflow-y-auto px-5 pb-5" ref={variantListRef}>
296
- <div className="space-y-2" role="list" aria-label={`${block.label} variants`}>
297
- {block.variants.map((variant, index) => (
298
- <button
299
- key={variant.name}
300
- type="button"
301
- role="listitem"
302
- data-variant={variant.name}
303
- onClick={() => onVariantClick(variant)}
304
- className="border-border hover:border-primary bg-card group focus:ring-ring flex w-full cursor-pointer items-center gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
305
- >
306
- <div className="min-w-0 flex-1">
307
- <div className="flex items-center gap-2">
308
- <p className="text-foreground text-sm font-medium">{variant.label}</p>
309
- {index === 0 && (
310
- <span className="text-primary bg-primary/10 inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs">
311
- <Check size={10} />
312
- Default
313
- </span>
314
- )}
315
- </div>
316
- <p className="text-muted-foreground mt-0.5 text-xs">{variant.description}</p>
317
- </div>
318
- </button>
319
- ))}
320
- </div>
321
- </div>
322
- </div>
323
- )
324
- }
@@ -1,65 +0,0 @@
1
- 'use client'
2
-
3
- import { Plus, Grid3X3 } from 'lucide-react'
4
- import { Toggle } from '../../components/ui/Toggle.js'
5
- import type { DeviceMode } from '../../hooks/useBuilderState.js'
6
-
7
- export interface BottomBarProps {
8
- deviceMode: DeviceMode
9
- showGridOverlay: boolean
10
- onAddSection: () => void
11
- onToggleGrid: (show: boolean) => void
12
- }
13
-
14
- const DEVICE_LABELS: Record<DeviceMode, string> = {
15
- desktop: '100%',
16
- tablet: '768px',
17
- mobile: '375px',
18
- }
19
-
20
- export function BottomBar({
21
- deviceMode,
22
- showGridOverlay,
23
- onAddSection,
24
- onToggleGrid,
25
- }: BottomBarProps) {
26
- return (
27
- <div
28
- className="bg-card border-border flex h-10 shrink-0 items-center gap-4 border-t px-4"
29
- role="toolbar"
30
- aria-label="Builder actions"
31
- >
32
- {/* Add Section */}
33
- <button
34
- onClick={onAddSection}
35
- className="text-muted-foreground hover:text-foreground flex items-center gap-1.5 px-3 py-2 text-sm transition-colors"
36
- aria-label="Add a new section"
37
- >
38
- <Plus size={14} />
39
- <span>Add Section</span>
40
- </button>
41
-
42
- {/* Divider */}
43
- <div className="bg-border h-5 w-px" />
44
-
45
- {/* Grid overlay toggle */}
46
- <label className="flex cursor-pointer items-center gap-2">
47
- <Grid3X3 size={14} className="text-muted-foreground" />
48
- <Toggle
49
- checked={showGridOverlay}
50
- onCheckedChange={onToggleGrid}
51
- aria-label="Toggle grid overlay"
52
- />
53
- <span className="text-muted-foreground text-xs">Grid</span>
54
- </label>
55
-
56
- {/* Spacer */}
57
- <div className="flex-1" />
58
-
59
- {/* Zoom / device width display */}
60
- <span className="text-muted-foreground text-xs tabular-nums">
61
- {DEVICE_LABELS[deviceMode]}
62
- </span>
63
- </div>
64
- )
65
- }
@@ -1,304 +0,0 @@
1
- 'use client'
2
-
3
- import { useMemo } from 'react'
4
- import {
5
- DndContext,
6
- KeyboardSensor,
7
- PointerSensor,
8
- closestCenter,
9
- useSensor,
10
- useSensors,
11
- type DragEndEvent,
12
- } from '@dnd-kit/core'
13
- import {
14
- SortableContext,
15
- sortableKeyboardCoordinates,
16
- useSortable,
17
- verticalListSortingStrategy,
18
- } from '@dnd-kit/sortable'
19
- import { CSS } from '@dnd-kit/utilities'
20
- import {
21
- Bookmark,
22
- Code,
23
- FileText,
24
- Grid,
25
- GripVertical,
26
- HelpCircle,
27
- Image,
28
- LayoutGrid,
29
- LayoutTemplate,
30
- MousePointer,
31
- PanelLeftClose,
32
- PanelLeftOpen,
33
- Play,
34
- Plus,
35
- Star,
36
- Type,
37
- type LucideIcon,
38
- } from 'lucide-react'
39
- import { BlockCatalog } from '@prenta/core/page-builder'
40
- import type { BuilderNode, PageNode } from '@prenta/core'
41
-
42
- export interface BuilderSectionsPanelProps {
43
- tree: PageNode
44
- selectedNodeId: string | null
45
- /** Collapsed to a slim rail. State is owned by PageBuilder (persisted). */
46
- collapsed: boolean
47
- onToggleCollapsed: () => void
48
- onSelect: (id: string) => void
49
- /** Move a top-level section to `toIndex` within the page. */
50
- onReorder: (id: string, toIndex: number) => void
51
- onAddSection: () => void
52
- }
53
-
54
- interface SectionEntry {
55
- id: string
56
- name: string
57
- meta: string
58
- icon: LucideIcon
59
- hidden: boolean
60
- }
61
-
62
- /** Same icon-name → component mapping the BlockPicker uses for the catalog. */
63
- const BLOCK_ICONS: Record<string, LucideIcon> = {
64
- Star,
65
- Type,
66
- Image,
67
- LayoutGrid,
68
- MousePointer,
69
- Play,
70
- Grid,
71
- HelpCircle,
72
- FileText,
73
- Code,
74
- }
75
-
76
- function collectBlockTypes(node: BuilderNode, out: string[]): void {
77
- if (node.type === 'block') {
78
- out.push(node.settings.blockType)
79
- return
80
- }
81
- if (node.type === 'savedSectionRef') return
82
- for (const child of node.children) collectBlockTypes(child, out)
83
- }
84
-
85
- function humanize(type: string): string {
86
- return type.charAt(0).toUpperCase() + type.slice(1)
87
- }
88
-
89
- /**
90
- * Builder sections have no user-facing title, so each row derives its name
91
- * from the section's first block (via the catalog label) and summarizes its
92
- * contents as the kind label — enough for the editor to recognize and jump
93
- * between sections without inventing data we don't store.
94
- */
95
- function buildEntries(tree: PageNode, catalog: BlockCatalog): SectionEntry[] {
96
- return tree.children.map((node, index) => {
97
- if (node.type === 'savedSectionRef') {
98
- return {
99
- id: node.id,
100
- name: 'Saved section',
101
- meta: 'From the section library',
102
- icon: Bookmark,
103
- hidden: false,
104
- }
105
- }
106
- const blockTypes: string[] = []
107
- collectBlockTypes(node, blockTypes)
108
- const firstType = blockTypes[0]
109
- const def = firstType ? catalog.get(firstType) : undefined
110
- return {
111
- id: node.id,
112
- name: def?.label ?? (firstType ? humanize(firstType) : `Section ${index + 1}`),
113
- meta:
114
- blockTypes.length === 0
115
- ? 'Empty section'
116
- : `${blockTypes.length} block${blockTypes.length === 1 ? '' : 's'}`,
117
- icon: (def && BLOCK_ICONS[def.icon]) ?? LayoutTemplate,
118
- hidden: node.settings.visibility === 'hidden',
119
- }
120
- })
121
- }
122
-
123
- const ICON_BUTTON_CLASS =
124
- 'flex h-8 w-8 items-center justify-center rounded-[7px] text-[var(--sub)] transition-colors duration-[var(--motion-fast)] hover:bg-[var(--acc-l)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none'
125
-
126
- /**
127
- * Design-parity left rail for the Page Builder (PageBuilder.html): the page's
128
- * sections listed in order with drag-to-reorder, click-to-select (which
129
- * highlights the section on the canvas and opens its settings in the existing
130
- * right-hand context panel), and an "Add Section" affordance at the bottom.
131
- */
132
- export function BuilderSectionsPanel({
133
- tree,
134
- selectedNodeId,
135
- collapsed,
136
- onToggleCollapsed,
137
- onSelect,
138
- onReorder,
139
- onAddSection,
140
- }: BuilderSectionsPanelProps) {
141
- const catalog = useMemo(() => new BlockCatalog(), [])
142
- const entries = useMemo(() => buildEntries(tree, catalog), [tree, catalog])
143
-
144
- const sensors = useSensors(
145
- useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
146
- useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
147
- )
148
-
149
- function handleDragEnd(event: DragEndEvent) {
150
- const { active, over } = event
151
- if (!over || active.id === over.id) return
152
- const ids = entries.map((e) => e.id)
153
- const to = ids.indexOf(String(over.id))
154
- if (to === -1 || !ids.includes(String(active.id))) return
155
- onReorder(String(active.id), to)
156
- }
157
-
158
- if (collapsed) {
159
- return (
160
- <nav
161
- aria-label="Page sections"
162
- className="flex w-11 shrink-0 flex-col items-center border-r border-[var(--bdr)] bg-[var(--sb)] py-2"
163
- >
164
- <button
165
- type="button"
166
- onClick={onToggleCollapsed}
167
- aria-expanded={false}
168
- aria-label="Expand sections panel"
169
- className={ICON_BUTTON_CLASS}
170
- >
171
- <PanelLeftOpen size={16} aria-hidden />
172
- </button>
173
- </nav>
174
- )
175
- }
176
-
177
- return (
178
- <nav
179
- aria-label="Page sections"
180
- className="flex w-[280px] shrink-0 flex-col overflow-hidden border-r border-[var(--bdr)] bg-[var(--sb)]"
181
- >
182
- <div className="flex items-center justify-between border-b border-[var(--bdr)] py-2 pr-2 pl-3.5">
183
- <div className="flex items-center gap-2">
184
- <h2 className="text-[13px] font-medium text-[var(--txt)]">Sections</h2>
185
- <span className="rounded-[4px] bg-[var(--acc-l)] px-[7px] py-0.5 text-[11px] font-medium text-[var(--acc)] tabular-nums">
186
- {entries.length}
187
- </span>
188
- </div>
189
- <button
190
- type="button"
191
- onClick={onToggleCollapsed}
192
- aria-expanded
193
- aria-label="Collapse sections panel"
194
- className={ICON_BUTTON_CLASS}
195
- >
196
- <PanelLeftClose size={16} aria-hidden />
197
- </button>
198
- </div>
199
-
200
- <div className="flex-1 overflow-y-auto">
201
- {entries.length === 0 ? (
202
- <p className="px-4 py-6 text-center text-[12.5px] text-[var(--muted)]">
203
- No sections yet. Add one below to start building.
204
- </p>
205
- ) : (
206
- <DndContext
207
- sensors={sensors}
208
- collisionDetection={closestCenter}
209
- onDragEnd={handleDragEnd}
210
- >
211
- <SortableContext
212
- items={entries.map((e) => e.id)}
213
- strategy={verticalListSortingStrategy}
214
- >
215
- <ul aria-label="Sections in page order">
216
- {entries.map((entry) => (
217
- <SortableSectionRow
218
- key={entry.id}
219
- entry={entry}
220
- selected={entry.id === selectedNodeId}
221
- onSelect={onSelect}
222
- />
223
- ))}
224
- </ul>
225
- </SortableContext>
226
- </DndContext>
227
- )}
228
- </div>
229
-
230
- <div className="border-t border-[var(--bdr)]">
231
- <button
232
- type="button"
233
- onClick={onAddSection}
234
- className="flex w-full items-center gap-2 px-3.5 py-3 text-[13px] font-medium text-[var(--acc)] transition-colors duration-[var(--motion-fast)] hover:bg-[var(--acc-l)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none focus-visible:ring-inset"
235
- >
236
- <Plus size={14} aria-hidden />
237
- Add Section
238
- </button>
239
- </div>
240
- </nav>
241
- )
242
- }
243
-
244
- interface SortableSectionRowProps {
245
- entry: SectionEntry
246
- selected: boolean
247
- onSelect: (id: string) => void
248
- }
249
-
250
- function SortableSectionRow({ entry, selected, onSelect }: SortableSectionRowProps) {
251
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
252
- id: entry.id,
253
- })
254
- const Icon = entry.icon
255
-
256
- const style = {
257
- transform: CSS.Transform.toString(transform),
258
- transition,
259
- zIndex: isDragging ? 10 : undefined,
260
- }
261
-
262
- return (
263
- <li ref={setNodeRef} style={style} className={isDragging ? 'shadow-[var(--shd2)]' : undefined}>
264
- <div
265
- className={`flex items-center gap-1.5 border-b border-[var(--bdr)] py-2 pr-2.5 pl-1.5 transition-colors duration-[var(--motion-fast)] ${
266
- selected ? 'bg-[var(--acc-l)]' : 'hover:bg-[var(--acc-l)]'
267
- }`}
268
- >
269
- <button
270
- type="button"
271
- aria-label={`Drag to reorder ${entry.name}`}
272
- {...attributes}
273
- {...listeners}
274
- className="shrink-0 cursor-grab touch-none rounded p-1 text-[var(--muted)] transition-colors duration-[var(--motion-fast)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none active:cursor-grabbing"
275
- >
276
- <GripVertical size={15} aria-hidden />
277
- </button>
278
- <button
279
- type="button"
280
- onClick={() => onSelect(entry.id)}
281
- aria-current={selected ? 'true' : undefined}
282
- className="flex min-w-0 flex-1 items-center gap-2.5 rounded text-left focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
283
- >
284
- <span
285
- aria-hidden
286
- className="flex h-7 w-7 shrink-0 items-center justify-center rounded-[7px] bg-[var(--acc-l)] text-[var(--acc)]"
287
- >
288
- <Icon size={14} />
289
- </span>
290
- <span className="flex min-w-0 flex-col">
291
- <span
292
- className={`truncate text-[13px] font-medium ${
293
- entry.hidden ? 'text-[var(--muted)] line-through' : 'text-[var(--txt)]'
294
- }`}
295
- >
296
- {entry.name}
297
- </span>
298
- <span className="truncate text-[11px] text-[var(--muted)]">{entry.meta}</span>
299
- </span>
300
- </button>
301
- </div>
302
- </li>
303
- )
304
- }