@prenta/admin 2.6.0 → 2.7.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 (801) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/design-system/tokens.css +179 -85
  3. package/design-system/tokens.json +276 -85
  4. package/design-system/tokens.scss +148 -44
  5. package/design-system/tokens.tailwind.cjs +50 -1
  6. package/dist/AdminRoot.d.ts.map +1 -1
  7. package/dist/AdminRoot.js +42 -20
  8. package/dist/AdminRoot.js.map +1 -1
  9. package/dist/LoginRoot.d.ts.map +1 -1
  10. package/dist/LoginRoot.js +2 -1
  11. package/dist/LoginRoot.js.map +1 -1
  12. package/dist/__tests__/components/author-avatar.test.js +3 -17
  13. package/dist/__tests__/components/author-avatar.test.js.map +1 -1
  14. package/dist/__tests__/components/notification-bell.test.js +86 -15
  15. package/dist/__tests__/components/notification-bell.test.js.map +1 -1
  16. package/dist/__tests__/components/responsive-tiers.render.test.d.ts +2 -0
  17. package/dist/__tests__/components/responsive-tiers.render.test.d.ts.map +1 -0
  18. package/dist/__tests__/components/responsive-tiers.render.test.js +313 -0
  19. package/dist/__tests__/components/responsive-tiers.render.test.js.map +1 -0
  20. package/dist/__tests__/components/serp-preview.render.test.js +6 -3
  21. package/dist/__tests__/components/serp-preview.render.test.js.map +1 -1
  22. package/dist/__tests__/components/shell-primitives.render.test.d.ts +2 -0
  23. package/dist/__tests__/components/shell-primitives.render.test.d.ts.map +1 -0
  24. package/dist/__tests__/components/shell-primitives.render.test.js +716 -0
  25. package/dist/__tests__/components/shell-primitives.render.test.js.map +1 -0
  26. package/dist/__tests__/components/theme-provider-accent.test.js +49 -7
  27. package/dist/__tests__/components/theme-provider-accent.test.js.map +1 -1
  28. package/dist/__tests__/components/toggle.test.js +10 -3
  29. package/dist/__tests__/components/toggle.test.js.map +1 -1
  30. package/dist/__tests__/components/ui-primitives.test.js +3 -7
  31. package/dist/__tests__/components/ui-primitives.test.js.map +1 -1
  32. package/dist/__tests__/layout/build-nav-items.test.js +1 -1
  33. package/dist/__tests__/layout/build-nav-items.test.js.map +1 -1
  34. package/dist/__tests__/layout/shell-nav.render.test.d.ts +2 -0
  35. package/dist/__tests__/layout/shell-nav.render.test.d.ts.map +1 -0
  36. package/dist/__tests__/layout/shell-nav.render.test.js +736 -0
  37. package/dist/__tests__/layout/shell-nav.render.test.js.map +1 -0
  38. package/dist/__tests__/layout/sidebar-forms-submenu.render.test.js +8 -4
  39. package/dist/__tests__/layout/sidebar-forms-submenu.render.test.js.map +1 -1
  40. package/dist/__tests__/layout/sidebar-groups.render.test.d.ts +2 -0
  41. package/dist/__tests__/layout/sidebar-groups.render.test.d.ts.map +1 -0
  42. package/dist/__tests__/layout/sidebar-groups.render.test.js +56 -0
  43. package/dist/__tests__/layout/sidebar-groups.render.test.js.map +1 -0
  44. package/dist/__tests__/layout/sidebar-menus.render.test.d.ts +2 -0
  45. package/dist/__tests__/layout/sidebar-menus.render.test.d.ts.map +1 -0
  46. package/dist/__tests__/layout/sidebar-menus.render.test.js +82 -0
  47. package/dist/__tests__/layout/sidebar-menus.render.test.js.map +1 -0
  48. package/dist/__tests__/layout/sidebar-plugin-nav.test.js +1 -1
  49. package/dist/__tests__/layout/sidebar-plugin-nav.test.js.map +1 -1
  50. package/dist/__tests__/layout/sidebar-posts.test.js +48 -38
  51. package/dist/__tests__/layout/sidebar-posts.test.js.map +1 -1
  52. package/dist/__tests__/layout/sidebar-submenu.render.test.js +26 -10
  53. package/dist/__tests__/layout/sidebar-submenu.render.test.js.map +1 -1
  54. package/dist/__tests__/layout/topbar.render.test.d.ts +2 -0
  55. package/dist/__tests__/layout/topbar.render.test.d.ts.map +1 -0
  56. package/dist/__tests__/layout/topbar.render.test.js +406 -0
  57. package/dist/__tests__/layout/topbar.render.test.js.map +1 -0
  58. package/dist/__tests__/lib/api.test.js +2 -0
  59. package/dist/__tests__/lib/api.test.js.map +1 -1
  60. package/dist/__tests__/lib/job-drawer.test.d.ts +2 -0
  61. package/dist/__tests__/lib/job-drawer.test.d.ts.map +1 -0
  62. package/dist/__tests__/lib/job-drawer.test.js +393 -0
  63. package/dist/__tests__/lib/job-drawer.test.js.map +1 -0
  64. package/dist/__tests__/lib/job-view.test.d.ts +2 -0
  65. package/dist/__tests__/lib/job-view.test.d.ts.map +1 -0
  66. package/dist/__tests__/lib/job-view.test.js +387 -0
  67. package/dist/__tests__/lib/job-view.test.js.map +1 -0
  68. package/dist/__tests__/lib/jobs-service.test.d.ts +2 -0
  69. package/dist/__tests__/lib/jobs-service.test.d.ts.map +1 -0
  70. package/dist/__tests__/lib/jobs-service.test.js +88 -0
  71. package/dist/__tests__/lib/jobs-service.test.js.map +1 -0
  72. package/dist/__tests__/router/admin-route-order.test.d.ts +2 -0
  73. package/dist/__tests__/router/admin-route-order.test.d.ts.map +1 -0
  74. package/dist/__tests__/router/admin-route-order.test.js +36 -0
  75. package/dist/__tests__/router/admin-route-order.test.js.map +1 -0
  76. package/dist/__tests__/styles/ai-gradient-contrast.test.d.ts +2 -0
  77. package/dist/__tests__/styles/ai-gradient-contrast.test.d.ts.map +1 -0
  78. package/dist/__tests__/styles/ai-gradient-contrast.test.js +110 -0
  79. package/dist/__tests__/styles/ai-gradient-contrast.test.js.map +1 -0
  80. package/dist/__tests__/styles/breakpoint-order.test.d.ts +2 -0
  81. package/dist/__tests__/styles/breakpoint-order.test.d.ts.map +1 -0
  82. package/dist/__tests__/styles/breakpoint-order.test.js +52 -0
  83. package/dist/__tests__/styles/breakpoint-order.test.js.map +1 -0
  84. package/dist/__tests__/styles/responsive-layer.test.js +303 -12
  85. package/dist/__tests__/styles/responsive-layer.test.js.map +1 -1
  86. package/dist/__tests__/styles/tailwind-preset.test.d.ts +2 -0
  87. package/dist/__tests__/styles/tailwind-preset.test.d.ts.map +1 -0
  88. package/dist/__tests__/styles/tailwind-preset.test.js +147 -0
  89. package/dist/__tests__/styles/tailwind-preset.test.js.map +1 -0
  90. package/dist/__tests__/styles/theme-token-scope.test.js +9 -3
  91. package/dist/__tests__/styles/theme-token-scope.test.js.map +1 -1
  92. package/dist/__tests__/styles/tiers.test.d.ts +2 -0
  93. package/dist/__tests__/styles/tiers.test.d.ts.map +1 -0
  94. package/dist/__tests__/styles/tiers.test.js +121 -0
  95. package/dist/__tests__/styles/tiers.test.js.map +1 -0
  96. package/dist/__tests__/styles/tokens-drift.test.js +57 -6
  97. package/dist/__tests__/styles/tokens-drift.test.js.map +1 -1
  98. package/dist/__tests__/views/admin-lazy-route.render.test.js +27 -1
  99. package/dist/__tests__/views/admin-lazy-route.render.test.js.map +1 -1
  100. package/dist/__tests__/views/ai-settings.render.test.js +4 -4
  101. package/dist/__tests__/views/appearance-menus-route.render.test.d.ts +2 -0
  102. package/dist/__tests__/views/appearance-menus-route.render.test.d.ts.map +1 -0
  103. package/dist/__tests__/views/appearance-menus-route.render.test.js +50 -0
  104. package/dist/__tests__/views/appearance-menus-route.render.test.js.map +1 -0
  105. package/dist/__tests__/views/appearance-settings.render.test.js +8 -6
  106. package/dist/__tests__/views/appearance-settings.render.test.js.map +1 -1
  107. package/dist/__tests__/views/appearance-theme-provider.render.test.d.ts +2 -0
  108. package/dist/__tests__/views/appearance-theme-provider.render.test.d.ts.map +1 -0
  109. package/dist/__tests__/views/appearance-theme-provider.render.test.js +286 -0
  110. package/dist/__tests__/views/appearance-theme-provider.render.test.js.map +1 -0
  111. package/dist/__tests__/views/dashboard.test.js +37 -0
  112. package/dist/__tests__/views/dashboard.test.js.map +1 -1
  113. package/dist/__tests__/views/document-edit-navigation.render.test.d.ts +2 -0
  114. package/dist/__tests__/views/document-edit-navigation.render.test.d.ts.map +1 -0
  115. package/dist/__tests__/views/document-edit-navigation.render.test.js +101 -0
  116. package/dist/__tests__/views/document-edit-navigation.render.test.js.map +1 -0
  117. package/dist/__tests__/views/document-edit-routes.render.test.d.ts +2 -0
  118. package/dist/__tests__/views/document-edit-routes.render.test.d.ts.map +1 -0
  119. package/dist/__tests__/views/document-edit-routes.render.test.js +113 -0
  120. package/dist/__tests__/views/document-edit-routes.render.test.js.map +1 -0
  121. package/dist/__tests__/views/email-settings.render.test.js +2 -2
  122. package/dist/__tests__/views/form-entries.render.test.js +15 -0
  123. package/dist/__tests__/views/form-entries.render.test.js.map +1 -1
  124. package/dist/__tests__/views/form-submissions.render.test.js +18 -0
  125. package/dist/__tests__/views/form-submissions.render.test.js.map +1 -1
  126. package/dist/__tests__/views/forms-list.render.test.js +12 -0
  127. package/dist/__tests__/views/forms-list.render.test.js.map +1 -1
  128. package/dist/__tests__/views/general-settings.render.test.js +26 -10
  129. package/dist/__tests__/views/general-settings.render.test.js.map +1 -1
  130. package/dist/__tests__/views/jobs-drawer.render.test.d.ts +2 -0
  131. package/dist/__tests__/views/jobs-drawer.render.test.d.ts.map +1 -0
  132. package/dist/__tests__/views/jobs-drawer.render.test.js +908 -0
  133. package/dist/__tests__/views/jobs-drawer.render.test.js.map +1 -0
  134. package/dist/__tests__/views/jobs-list.render.test.d.ts +2 -0
  135. package/dist/__tests__/views/jobs-list.render.test.d.ts.map +1 -0
  136. package/dist/__tests__/views/jobs-list.render.test.js +695 -0
  137. package/dist/__tests__/views/jobs-list.render.test.js.map +1 -0
  138. package/dist/__tests__/views/kpi-grid.test.d.ts +2 -0
  139. package/dist/__tests__/views/kpi-grid.test.d.ts.map +1 -0
  140. package/dist/__tests__/views/kpi-grid.test.js +26 -0
  141. package/dist/__tests__/views/kpi-grid.test.js.map +1 -0
  142. package/dist/__tests__/views/mcp-connect.render.test.js +1 -0
  143. package/dist/__tests__/views/mcp-connect.render.test.js.map +1 -1
  144. package/dist/__tests__/views/post-section-editor.test.js +3 -1
  145. package/dist/__tests__/views/post-section-editor.test.js.map +1 -1
  146. package/dist/__tests__/views/script-tags.render.test.js +25 -0
  147. package/dist/__tests__/views/script-tags.render.test.js.map +1 -1
  148. package/dist/__tests__/views/security-settings.render.test.js +9 -8
  149. package/dist/__tests__/views/security-settings.render.test.js.map +1 -1
  150. package/dist/__tests__/views/seo-settings.render.test.js +7 -7
  151. package/dist/__tests__/views/seo-settings.render.test.js.map +1 -1
  152. package/dist/__tests__/views/settings-save-bar.render.test.d.ts +2 -0
  153. package/dist/__tests__/views/settings-save-bar.render.test.d.ts.map +1 -0
  154. package/dist/__tests__/views/settings-save-bar.render.test.js +68 -0
  155. package/dist/__tests__/views/settings-save-bar.render.test.js.map +1 -0
  156. package/dist/__tests__/views/settings-save-footer.render.test.js +23 -15
  157. package/dist/__tests__/views/settings-save-footer.render.test.js.map +1 -1
  158. package/dist/__tests__/views/settings-tabs.render.test.d.ts +2 -0
  159. package/dist/__tests__/views/settings-tabs.render.test.d.ts.map +1 -0
  160. package/dist/__tests__/views/settings-tabs.render.test.js +319 -0
  161. package/dist/__tests__/views/settings-tabs.render.test.js.map +1 -0
  162. package/dist/__tests__/views/updates-tab.render.test.js +4 -3
  163. package/dist/__tests__/views/updates-tab.render.test.js.map +1 -1
  164. package/dist/components/Breadcrumbs.d.ts +8 -1
  165. package/dist/components/Breadcrumbs.d.ts.map +1 -1
  166. package/dist/components/Breadcrumbs.js +6 -0
  167. package/dist/components/Breadcrumbs.js.map +1 -1
  168. package/dist/components/CommandPalette.d.ts.map +1 -1
  169. package/dist/components/CommandPalette.js +40 -4
  170. package/dist/components/CommandPalette.js.map +1 -1
  171. package/dist/components/LocaleSwitcher.d.ts.map +1 -1
  172. package/dist/components/LocaleSwitcher.js +1 -1
  173. package/dist/components/LocaleSwitcher.js.map +1 -1
  174. package/dist/components/NotificationBell.d.ts.map +1 -1
  175. package/dist/components/NotificationBell.js +44 -3
  176. package/dist/components/NotificationBell.js.map +1 -1
  177. package/dist/components/OfflineStatus.js +1 -1
  178. package/dist/components/OfflineStatus.js.map +1 -1
  179. package/dist/components/PresenceIndicator.d.ts.map +1 -1
  180. package/dist/components/PresenceIndicator.js +2 -1
  181. package/dist/components/PresenceIndicator.js.map +1 -1
  182. package/dist/components/ReflowMeter.js +2 -2
  183. package/dist/components/ReflowMeter.js.map +1 -1
  184. package/dist/components/SEOPanel.js +2 -2
  185. package/dist/components/SEOPanel.js.map +1 -1
  186. package/dist/components/ThemeProvider.d.ts +24 -4
  187. package/dist/components/ThemeProvider.d.ts.map +1 -1
  188. package/dist/components/ThemeProvider.js +80 -22
  189. package/dist/components/ThemeProvider.js.map +1 -1
  190. package/dist/components/TipTapEditor.d.ts.map +1 -1
  191. package/dist/components/TipTapEditor.js +3 -4
  192. package/dist/components/TipTapEditor.js.map +1 -1
  193. package/dist/components/forms/EmbedPanel.js +1 -1
  194. package/dist/components/forms/EmbedPanel.js.map +1 -1
  195. package/dist/components/forms/FormEntryDetailPane.js +6 -1
  196. package/dist/components/forms/FormEntryDetailPane.js.map +1 -1
  197. package/dist/components/forms/ShortcodeGlossary.d.ts.map +1 -1
  198. package/dist/components/forms/ShortcodeGlossary.js +6 -1
  199. package/dist/components/forms/ShortcodeGlossary.js.map +1 -1
  200. package/dist/components/forms/primitives.d.ts +15 -5
  201. package/dist/components/forms/primitives.d.ts.map +1 -1
  202. package/dist/components/forms/primitives.js +11 -11
  203. package/dist/components/forms/primitives.js.map +1 -1
  204. package/dist/components/pages/tag-badges.d.ts +2 -1
  205. package/dist/components/pages/tag-badges.d.ts.map +1 -1
  206. package/dist/components/pages/tag-badges.js +4 -3
  207. package/dist/components/pages/tag-badges.js.map +1 -1
  208. package/dist/components/seo/PageAuditPanel.js +2 -2
  209. package/dist/components/seo/PageAuditPanel.js.map +1 -1
  210. package/dist/components/seo/SerpPreview.d.ts +4 -4
  211. package/dist/components/seo/SerpPreview.js +1 -1
  212. package/dist/components/seo/SerpPreview.js.map +1 -1
  213. package/dist/components/seo/primitives.js +2 -2
  214. package/dist/components/seo/primitives.js.map +1 -1
  215. package/dist/components/ui/AuthorAvatar.d.ts +4 -4
  216. package/dist/components/ui/AuthorAvatar.d.ts.map +1 -1
  217. package/dist/components/ui/AuthorAvatar.js +11 -10
  218. package/dist/components/ui/AuthorAvatar.js.map +1 -1
  219. package/dist/components/ui/Badge.d.ts +1 -1
  220. package/dist/components/ui/Badge.js +1 -1
  221. package/dist/components/ui/Badge.js.map +1 -1
  222. package/dist/components/ui/Breadcrumb.d.ts +27 -0
  223. package/dist/components/ui/Breadcrumb.d.ts.map +1 -0
  224. package/dist/components/ui/Breadcrumb.js +41 -0
  225. package/dist/components/ui/Breadcrumb.js.map +1 -0
  226. package/dist/components/ui/Button.d.ts +2 -2
  227. package/dist/components/ui/Button.d.ts.map +1 -1
  228. package/dist/components/ui/Button.js +31 -16
  229. package/dist/components/ui/Button.js.map +1 -1
  230. package/dist/components/ui/Card.d.ts +8 -4
  231. package/dist/components/ui/Card.d.ts.map +1 -1
  232. package/dist/components/ui/Card.js +21 -13
  233. package/dist/components/ui/Card.js.map +1 -1
  234. package/dist/components/ui/CardListControls.d.ts +34 -0
  235. package/dist/components/ui/CardListControls.d.ts.map +1 -0
  236. package/dist/components/ui/CardListControls.js +25 -0
  237. package/dist/components/ui/CardListControls.js.map +1 -0
  238. package/dist/components/ui/CountChip.d.ts +20 -0
  239. package/dist/components/ui/CountChip.d.ts.map +1 -0
  240. package/dist/components/ui/CountChip.js +48 -0
  241. package/dist/components/ui/CountChip.js.map +1 -0
  242. package/dist/components/ui/FilterPill.d.ts +2 -1
  243. package/dist/components/ui/FilterPill.d.ts.map +1 -1
  244. package/dist/components/ui/FilterPill.js +3 -2
  245. package/dist/components/ui/FilterPill.js.map +1 -1
  246. package/dist/components/ui/Input.d.ts +1 -1
  247. package/dist/components/ui/InspectorPane.d.ts +1 -1
  248. package/dist/components/ui/InspectorPane.d.ts.map +1 -1
  249. package/dist/components/ui/InspectorPane.js +15 -4
  250. package/dist/components/ui/InspectorPane.js.map +1 -1
  251. package/dist/components/ui/Modal.d.ts.map +1 -1
  252. package/dist/components/ui/Modal.js +10 -2
  253. package/dist/components/ui/Modal.js.map +1 -1
  254. package/dist/components/ui/PageHeader.d.ts +28 -0
  255. package/dist/components/ui/PageHeader.d.ts.map +1 -0
  256. package/dist/components/ui/PageHeader.js +18 -0
  257. package/dist/components/ui/PageHeader.js.map +1 -0
  258. package/dist/components/ui/RowActions.d.ts +5 -0
  259. package/dist/components/ui/RowActions.d.ts.map +1 -1
  260. package/dist/components/ui/RowActions.js +7 -2
  261. package/dist/components/ui/RowActions.js.map +1 -1
  262. package/dist/components/ui/Segmented.d.ts +21 -0
  263. package/dist/components/ui/Segmented.d.ts.map +1 -0
  264. package/dist/components/ui/Segmented.js +41 -0
  265. package/dist/components/ui/Segmented.js.map +1 -0
  266. package/dist/components/ui/Toaster.d.ts +12 -0
  267. package/dist/components/ui/Toaster.d.ts.map +1 -0
  268. package/dist/components/ui/Toaster.js +103 -0
  269. package/dist/components/ui/Toaster.js.map +1 -0
  270. package/dist/components/ui/Toggle.d.ts +4 -3
  271. package/dist/components/ui/Toggle.d.ts.map +1 -1
  272. package/dist/components/ui/Toggle.js +16 -12
  273. package/dist/components/ui/Toggle.js.map +1 -1
  274. package/dist/components/ui/UnderlineTabs.d.ts +56 -0
  275. package/dist/components/ui/UnderlineTabs.d.ts.map +1 -0
  276. package/dist/components/ui/UnderlineTabs.js +205 -0
  277. package/dist/components/ui/UnderlineTabs.js.map +1 -0
  278. package/dist/components/ui/UnsavedBar.d.ts +25 -0
  279. package/dist/components/ui/UnsavedBar.d.ts.map +1 -0
  280. package/dist/components/ui/UnsavedBar.js +22 -0
  281. package/dist/components/ui/UnsavedBar.js.map +1 -0
  282. package/dist/components/ui/admin-links.d.ts +11 -0
  283. package/dist/components/ui/admin-links.d.ts.map +1 -0
  284. package/dist/components/ui/admin-links.js +10 -0
  285. package/dist/components/ui/admin-links.js.map +1 -0
  286. package/dist/components/ui/card-table.d.ts +43 -0
  287. package/dist/components/ui/card-table.d.ts.map +1 -0
  288. package/dist/components/ui/card-table.js +31 -0
  289. package/dist/components/ui/card-table.js.map +1 -0
  290. package/dist/components/virtual-window.d.ts +7 -0
  291. package/dist/components/virtual-window.d.ts.map +1 -1
  292. package/dist/components/virtual-window.js +5 -2
  293. package/dist/components/virtual-window.js.map +1 -1
  294. package/dist/fields/RelationshipField.js +1 -1
  295. package/dist/fields/RelationshipField.js.map +1 -1
  296. package/dist/files/dm-mono-latin-400-normal.woff +0 -0
  297. package/dist/files/dm-mono-latin-400-normal.woff2 +0 -0
  298. package/dist/files/dm-mono-latin-500-normal.woff +0 -0
  299. package/dist/files/dm-mono-latin-500-normal.woff2 +0 -0
  300. package/dist/files/dm-mono-latin-ext-400-normal.woff +0 -0
  301. package/dist/files/dm-mono-latin-ext-400-normal.woff2 +0 -0
  302. package/dist/files/dm-mono-latin-ext-500-normal.woff +0 -0
  303. package/dist/files/dm-mono-latin-ext-500-normal.woff2 +0 -0
  304. package/dist/files/dm-sans-latin-400-normal.woff +0 -0
  305. package/dist/files/dm-sans-latin-400-normal.woff2 +0 -0
  306. package/dist/files/dm-sans-latin-500-normal.woff +0 -0
  307. package/dist/files/dm-sans-latin-500-normal.woff2 +0 -0
  308. package/dist/files/dm-sans-latin-600-normal.woff +0 -0
  309. package/dist/files/dm-sans-latin-600-normal.woff2 +0 -0
  310. package/dist/files/dm-sans-latin-700-normal.woff +0 -0
  311. package/dist/files/dm-sans-latin-700-normal.woff2 +0 -0
  312. package/dist/files/dm-sans-latin-ext-400-normal.woff +0 -0
  313. package/dist/files/dm-sans-latin-ext-400-normal.woff2 +0 -0
  314. package/dist/files/dm-sans-latin-ext-500-normal.woff +0 -0
  315. package/dist/files/dm-sans-latin-ext-500-normal.woff2 +0 -0
  316. package/dist/files/dm-sans-latin-ext-600-normal.woff +0 -0
  317. package/dist/files/dm-sans-latin-ext-600-normal.woff2 +0 -0
  318. package/dist/files/dm-sans-latin-ext-700-normal.woff +0 -0
  319. package/dist/files/dm-sans-latin-ext-700-normal.woff2 +0 -0
  320. package/dist/hooks/useAppearanceBootstrap.d.ts.map +1 -1
  321. package/dist/hooks/useAppearanceBootstrap.js +9 -3
  322. package/dist/hooks/useAppearanceBootstrap.js.map +1 -1
  323. package/dist/index.d.ts +15 -0
  324. package/dist/index.d.ts.map +1 -1
  325. package/dist/index.js +8 -0
  326. package/dist/index.js.map +1 -1
  327. package/dist/layout/Header.d.ts +14 -5
  328. package/dist/layout/Header.d.ts.map +1 -1
  329. package/dist/layout/Header.js +78 -13
  330. package/dist/layout/Header.js.map +1 -1
  331. package/dist/layout/Layout.d.ts +5 -3
  332. package/dist/layout/Layout.d.ts.map +1 -1
  333. package/dist/layout/Layout.js +45 -54
  334. package/dist/layout/Layout.js.map +1 -1
  335. package/dist/layout/MobileTabBar.d.ts +20 -0
  336. package/dist/layout/MobileTabBar.d.ts.map +1 -0
  337. package/dist/layout/MobileTabBar.js +29 -0
  338. package/dist/layout/MobileTabBar.js.map +1 -0
  339. package/dist/layout/Sidebar.d.ts +8 -26
  340. package/dist/layout/Sidebar.d.ts.map +1 -1
  341. package/dist/layout/Sidebar.js +309 -345
  342. package/dist/layout/Sidebar.js.map +1 -1
  343. package/dist/layout/nav-config.d.ts +101 -0
  344. package/dist/layout/nav-config.d.ts.map +1 -0
  345. package/dist/layout/nav-config.js +297 -0
  346. package/dist/layout/nav-config.js.map +1 -0
  347. package/dist/layout/primitives/AdminShell.d.ts +10 -2
  348. package/dist/layout/primitives/AdminShell.d.ts.map +1 -1
  349. package/dist/layout/primitives/AdminShell.js +114 -6
  350. package/dist/layout/primitives/AdminShell.js.map +1 -1
  351. package/dist/layout/topbar-classes.d.ts +8 -0
  352. package/dist/layout/topbar-classes.d.ts.map +1 -0
  353. package/dist/layout/topbar-classes.js +8 -0
  354. package/dist/layout/topbar-classes.js.map +1 -0
  355. package/dist/layout/use-nav-items.d.ts +10 -0
  356. package/dist/layout/use-nav-items.d.ts.map +1 -0
  357. package/dist/layout/use-nav-items.js +39 -0
  358. package/dist/layout/use-nav-items.js.map +1 -0
  359. package/dist/lib/api.d.ts +6 -0
  360. package/dist/lib/api.d.ts.map +1 -1
  361. package/dist/lib/api.js +1 -1
  362. package/dist/lib/api.js.map +1 -1
  363. package/dist/lib/appearance-api.d.ts +3 -1
  364. package/dist/lib/appearance-api.d.ts.map +1 -1
  365. package/dist/lib/appearance-api.js +1 -0
  366. package/dist/lib/appearance-api.js.map +1 -1
  367. package/dist/lib/job-drawer.d.ts +128 -0
  368. package/dist/lib/job-drawer.d.ts.map +1 -0
  369. package/dist/lib/job-drawer.js +351 -0
  370. package/dist/lib/job-drawer.js.map +1 -0
  371. package/dist/lib/job-view.d.ts +187 -0
  372. package/dist/lib/job-view.d.ts.map +1 -0
  373. package/dist/lib/job-view.js +363 -0
  374. package/dist/lib/job-view.js.map +1 -0
  375. package/dist/lib/jobs-service.d.ts +134 -0
  376. package/dist/lib/jobs-service.d.ts.map +1 -0
  377. package/dist/lib/jobs-service.js +179 -0
  378. package/dist/lib/jobs-service.js.map +1 -0
  379. package/dist/lib/sheet-focus.d.ts +24 -0
  380. package/dist/lib/sheet-focus.d.ts.map +1 -0
  381. package/dist/lib/sheet-focus.js +61 -0
  382. package/dist/lib/sheet-focus.js.map +1 -0
  383. package/dist/lib/tiers.d.ts +30 -0
  384. package/dist/lib/tiers.d.ts.map +1 -0
  385. package/dist/lib/tiers.js +43 -0
  386. package/dist/lib/tiers.js.map +1 -0
  387. package/dist/prenta-admin.css +1 -1
  388. package/dist/router/admin-routes.d.ts.map +1 -1
  389. package/dist/router/admin-routes.js +8 -0
  390. package/dist/router/admin-routes.js.map +1 -1
  391. package/dist/router/index.d.ts +5 -1
  392. package/dist/router/index.d.ts.map +1 -1
  393. package/dist/router/index.js +7 -0
  394. package/dist/router/index.js.map +1 -1
  395. package/dist/views/ApiKeys.js +2 -2
  396. package/dist/views/ApiKeys.js.map +1 -1
  397. package/dist/views/AppearanceChrome.d.ts +6 -0
  398. package/dist/views/AppearanceChrome.d.ts.map +1 -0
  399. package/dist/views/AppearanceChrome.js +25 -0
  400. package/dist/views/AppearanceChrome.js.map +1 -0
  401. package/dist/views/CollectionList.d.ts.map +1 -1
  402. package/dist/views/CollectionList.js +73 -53
  403. package/dist/views/CollectionList.js.map +1 -1
  404. package/dist/views/Dashboard.d.ts.map +1 -1
  405. package/dist/views/Dashboard.js +14 -8
  406. package/dist/views/Dashboard.js.map +1 -1
  407. package/dist/views/DocumentEdit.d.ts +6 -1
  408. package/dist/views/DocumentEdit.d.ts.map +1 -1
  409. package/dist/views/DocumentEdit.js +44 -8
  410. package/dist/views/DocumentEdit.js.map +1 -1
  411. package/dist/views/FormDeliveries.d.ts.map +1 -1
  412. package/dist/views/FormDeliveries.js +7 -1
  413. package/dist/views/FormDeliveries.js.map +1 -1
  414. package/dist/views/FormEntries.d.ts.map +1 -1
  415. package/dist/views/FormEntries.js +11 -2
  416. package/dist/views/FormEntries.js.map +1 -1
  417. package/dist/views/FormSubmissions.d.ts +1 -1
  418. package/dist/views/FormSubmissions.d.ts.map +1 -1
  419. package/dist/views/FormSubmissions.js +15 -4
  420. package/dist/views/FormSubmissions.js.map +1 -1
  421. package/dist/views/Forms.d.ts.map +1 -1
  422. package/dist/views/Forms.js +6 -4
  423. package/dist/views/Forms.js.map +1 -1
  424. package/dist/views/FormsSettings.d.ts +2 -0
  425. package/dist/views/FormsSettings.d.ts.map +1 -0
  426. package/dist/views/FormsSettings.js +37 -0
  427. package/dist/views/FormsSettings.js.map +1 -0
  428. package/dist/views/Jobs/BusyButton.d.ts +15 -0
  429. package/dist/views/Jobs/BusyButton.d.ts.map +1 -0
  430. package/dist/views/Jobs/BusyButton.js +26 -0
  431. package/dist/views/Jobs/BusyButton.js.map +1 -0
  432. package/dist/views/Jobs/CancelJobDialog.d.ts +21 -0
  433. package/dist/views/Jobs/CancelJobDialog.d.ts.map +1 -0
  434. package/dist/views/Jobs/CancelJobDialog.js +66 -0
  435. package/dist/views/Jobs/CancelJobDialog.js.map +1 -0
  436. package/dist/views/Jobs/DrawerActivity.d.ts +16 -0
  437. package/dist/views/Jobs/DrawerActivity.d.ts.map +1 -0
  438. package/dist/views/Jobs/DrawerActivity.js +59 -0
  439. package/dist/views/Jobs/DrawerActivity.js.map +1 -0
  440. package/dist/views/Jobs/DrawerOverview.d.ts +28 -0
  441. package/dist/views/Jobs/DrawerOverview.d.ts.map +1 -0
  442. package/dist/views/Jobs/DrawerOverview.js +32 -0
  443. package/dist/views/Jobs/DrawerOverview.js.map +1 -0
  444. package/dist/views/Jobs/DrawerResults.d.ts +25 -0
  445. package/dist/views/Jobs/DrawerResults.d.ts.map +1 -0
  446. package/dist/views/Jobs/DrawerResults.js +50 -0
  447. package/dist/views/Jobs/DrawerResults.js.map +1 -0
  448. package/dist/views/Jobs/DrawerReview.d.ts +44 -0
  449. package/dist/views/Jobs/DrawerReview.d.ts.map +1 -0
  450. package/dist/views/Jobs/DrawerReview.js +110 -0
  451. package/dist/views/Jobs/DrawerReview.js.map +1 -0
  452. package/dist/views/Jobs/JobDrawer.d.ts +31 -0
  453. package/dist/views/Jobs/JobDrawer.d.ts.map +1 -0
  454. package/dist/views/Jobs/JobDrawer.js +353 -0
  455. package/dist/views/Jobs/JobDrawer.js.map +1 -0
  456. package/dist/views/Jobs/JobsTable.d.ts +19 -0
  457. package/dist/views/Jobs/JobsTable.d.ts.map +1 -0
  458. package/dist/views/Jobs/JobsTable.js +80 -0
  459. package/dist/views/Jobs/JobsTable.js.map +1 -0
  460. package/dist/views/Jobs/WorkerStrip.d.ts +22 -0
  461. package/dist/views/Jobs/WorkerStrip.d.ts.map +1 -0
  462. package/dist/views/Jobs/WorkerStrip.js +63 -0
  463. package/dist/views/Jobs/WorkerStrip.js.map +1 -0
  464. package/dist/views/Jobs/atoms.d.ts +19 -0
  465. package/dist/views/Jobs/atoms.d.ts.map +1 -0
  466. package/dist/views/Jobs/atoms.js +52 -0
  467. package/dist/views/Jobs/atoms.js.map +1 -0
  468. package/dist/views/Jobs/focus.d.ts +23 -0
  469. package/dist/views/Jobs/focus.d.ts.map +1 -0
  470. package/dist/views/Jobs/focus.js +54 -0
  471. package/dist/views/Jobs/focus.js.map +1 -0
  472. package/dist/views/Jobs/icons.d.ts +22 -0
  473. package/dist/views/Jobs/icons.d.ts.map +1 -0
  474. package/dist/views/Jobs/icons.js +23 -0
  475. package/dist/views/Jobs/icons.js.map +1 -0
  476. package/dist/views/Jobs/placeholders.d.ts +6 -0
  477. package/dist/views/Jobs/placeholders.d.ts.map +1 -0
  478. package/dist/views/Jobs/placeholders.js +20 -0
  479. package/dist/views/Jobs/placeholders.js.map +1 -0
  480. package/dist/views/Jobs/useJobDetail.d.ts +21 -0
  481. package/dist/views/Jobs/useJobDetail.d.ts.map +1 -0
  482. package/dist/views/Jobs/useJobDetail.js +39 -0
  483. package/dist/views/Jobs/useJobDetail.js.map +1 -0
  484. package/dist/views/Jobs/useJobsFeed.d.ts +35 -0
  485. package/dist/views/Jobs/useJobsFeed.d.ts.map +1 -0
  486. package/dist/views/Jobs/useJobsFeed.js +231 -0
  487. package/dist/views/Jobs/useJobsFeed.js.map +1 -0
  488. package/dist/views/Jobs/useReviewItems.d.ts +39 -0
  489. package/dist/views/Jobs/useReviewItems.d.ts.map +1 -0
  490. package/dist/views/Jobs/useReviewItems.js +140 -0
  491. package/dist/views/Jobs/useReviewItems.js.map +1 -0
  492. package/dist/views/Jobs.d.ts +10 -1
  493. package/dist/views/Jobs.d.ts.map +1 -1
  494. package/dist/views/Jobs.js +126 -35
  495. package/dist/views/Jobs.js.map +1 -1
  496. package/dist/views/MediaBrowser.d.ts.map +1 -1
  497. package/dist/views/MediaBrowser.js +37 -9
  498. package/dist/views/MediaBrowser.js.map +1 -1
  499. package/dist/views/Pages/PagesListView.d.ts +1 -1
  500. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  501. package/dist/views/Pages/PagesListView.js +34 -5
  502. package/dist/views/Pages/PagesListView.js.map +1 -1
  503. package/dist/views/Posts/NewPostTypeInstructions.d.ts.map +1 -1
  504. package/dist/views/Posts/NewPostTypeInstructions.js +12 -2
  505. package/dist/views/Posts/NewPostTypeInstructions.js.map +1 -1
  506. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  507. package/dist/views/Posts/PostTypesView.js +10 -1
  508. package/dist/views/Posts/PostTypesView.js.map +1 -1
  509. package/dist/views/Posts/PostsListView.d.ts +1 -2
  510. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  511. package/dist/views/Posts/PostsListView.js +31 -3
  512. package/dist/views/Posts/PostsListView.js.map +1 -1
  513. package/dist/views/SEO.d.ts.map +1 -1
  514. package/dist/views/SEO.js +3 -3
  515. package/dist/views/SEO.js.map +1 -1
  516. package/dist/views/ScriptTags.d.ts.map +1 -1
  517. package/dist/views/ScriptTags.js +20 -15
  518. package/dist/views/ScriptTags.js.map +1 -1
  519. package/dist/views/Settings.d.ts.map +1 -1
  520. package/dist/views/Settings.js +115 -51
  521. package/dist/views/Settings.js.map +1 -1
  522. package/dist/views/SpamFolder.d.ts +2 -0
  523. package/dist/views/SpamFolder.d.ts.map +1 -0
  524. package/dist/views/SpamFolder.js +14 -0
  525. package/dist/views/SpamFolder.js.map +1 -0
  526. package/dist/views/Trash.d.ts +6 -1
  527. package/dist/views/Trash.d.ts.map +1 -1
  528. package/dist/views/Trash.js +7 -2
  529. package/dist/views/Trash.js.map +1 -1
  530. package/dist/views/Users.js +2 -2
  531. package/dist/views/Users.js.map +1 -1
  532. package/dist/views/WidgetsPlaceholder.d.ts +2 -0
  533. package/dist/views/WidgetsPlaceholder.d.ts.map +1 -0
  534. package/dist/views/WidgetsPlaceholder.js +15 -0
  535. package/dist/views/WidgetsPlaceholder.js.map +1 -0
  536. package/dist/views/dashboard/kpi-grid.d.ts +18 -0
  537. package/dist/views/dashboard/kpi-grid.d.ts.map +1 -0
  538. package/dist/views/dashboard/kpi-grid.js +36 -0
  539. package/dist/views/dashboard/kpi-grid.js.map +1 -0
  540. package/dist/views/lazy-views.d.ts +4 -0
  541. package/dist/views/lazy-views.d.ts.map +1 -1
  542. package/dist/views/lazy-views.js +4 -0
  543. package/dist/views/lazy-views.js.map +1 -1
  544. package/dist/views/page-editor/PageTab.js +1 -1
  545. package/dist/views/page-editor/PageTab.js.map +1 -1
  546. package/dist/views/page-editor/ReviewBar.js +1 -1
  547. package/dist/views/page-editor/ReviewBar.js.map +1 -1
  548. package/dist/views/page-editor/VersionHistoryPanel.js +1 -1
  549. package/dist/views/page-editor/VersionHistoryPanel.js.map +1 -1
  550. package/dist/views/seo/AuditTab.js +1 -1
  551. package/dist/views/seo/AuditTab.js.map +1 -1
  552. package/dist/views/seo/OverviewTab.d.ts.map +1 -1
  553. package/dist/views/seo/OverviewTab.js +2 -2
  554. package/dist/views/seo/OverviewTab.js.map +1 -1
  555. package/dist/views/seo/ProposalsTab.js +1 -1
  556. package/dist/views/seo/ProposalsTab.js.map +1 -1
  557. package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
  558. package/dist/views/settings/AISettingsTab.js +4 -2
  559. package/dist/views/settings/AISettingsTab.js.map +1 -1
  560. package/dist/views/settings/AccessProtectionCard.js +1 -1
  561. package/dist/views/settings/AccessProtectionCard.js.map +1 -1
  562. package/dist/views/settings/AdminThemeCard.d.ts.map +1 -1
  563. package/dist/views/settings/AdminThemeCard.js +63 -15
  564. package/dist/views/settings/AdminThemeCard.js.map +1 -1
  565. package/dist/views/settings/AppearanceTab.d.ts.map +1 -1
  566. package/dist/views/settings/AppearanceTab.js +4 -2
  567. package/dist/views/settings/AppearanceTab.js.map +1 -1
  568. package/dist/views/settings/BrandPreviewCard.js +1 -1
  569. package/dist/views/settings/BrandPreviewCard.js.map +1 -1
  570. package/dist/views/settings/BrandVoiceCard.js +1 -1
  571. package/dist/views/settings/BrandVoiceCard.js.map +1 -1
  572. package/dist/views/settings/EmailSettingsTab.d.ts.map +1 -1
  573. package/dist/views/settings/EmailSettingsTab.js +5 -3
  574. package/dist/views/settings/EmailSettingsTab.js.map +1 -1
  575. package/dist/views/settings/GeneralSettingsTab.d.ts.map +1 -1
  576. package/dist/views/settings/GeneralSettingsTab.js +4 -2
  577. package/dist/views/settings/GeneralSettingsTab.js.map +1 -1
  578. package/dist/views/settings/McpConnectTab.d.ts.map +1 -1
  579. package/dist/views/settings/McpConnectTab.js +1 -1
  580. package/dist/views/settings/McpConnectTab.js.map +1 -1
  581. package/dist/views/settings/ProviderConnectionCard.js +1 -1
  582. package/dist/views/settings/ProviderConnectionCard.js.map +1 -1
  583. package/dist/views/settings/SearchDataCard.js +1 -1
  584. package/dist/views/settings/SearchDataCard.js.map +1 -1
  585. package/dist/views/settings/SecurityStatusCard.js +2 -2
  586. package/dist/views/settings/SecurityStatusCard.js.map +1 -1
  587. package/dist/views/settings/SecurityTab.d.ts.map +1 -1
  588. package/dist/views/settings/SecurityTab.js +4 -2
  589. package/dist/views/settings/SecurityTab.js.map +1 -1
  590. package/dist/views/settings/SeoAutopilotCard.js +2 -2
  591. package/dist/views/settings/SeoAutopilotCard.js.map +1 -1
  592. package/dist/views/settings/SeoSettingsTab.d.ts.map +1 -1
  593. package/dist/views/settings/SeoSettingsTab.js +5 -3
  594. package/dist/views/settings/SeoSettingsTab.js.map +1 -1
  595. package/dist/views/settings/SiteIndexStatusCard.js +1 -1
  596. package/dist/views/settings/SiteIndexStatusCard.js.map +1 -1
  597. package/dist/views/settings/SiteThemeCard.js +1 -1
  598. package/dist/views/settings/UpdatesTab.d.ts.map +1 -1
  599. package/dist/views/settings/UpdatesTab.js +6 -5
  600. package/dist/views/settings/UpdatesTab.js.map +1 -1
  601. package/dist/views/settings/components.d.ts +7 -11
  602. package/dist/views/settings/components.d.ts.map +1 -1
  603. package/dist/views/settings/components.js +18 -12
  604. package/dist/views/settings/components.js.map +1 -1
  605. package/dist/views/settings/useAppearanceSettings.d.ts +7 -1
  606. package/dist/views/settings/useAppearanceSettings.d.ts.map +1 -1
  607. package/dist/views/settings/useAppearanceSettings.js +89 -22
  608. package/dist/views/settings/useAppearanceSettings.js.map +1 -1
  609. package/dist/views/users/UserDetailDrawer.js +1 -1
  610. package/dist/views/users/UserDetailDrawer.js.map +1 -1
  611. package/package.json +11 -9
  612. package/src/AdminRoot.tsx +88 -30
  613. package/src/LoginRoot.tsx +2 -1
  614. package/src/__tests__/components/author-avatar.test.tsx +3 -20
  615. package/src/__tests__/components/notification-bell.test.tsx +146 -14
  616. package/src/__tests__/components/responsive-tiers.render.test.tsx +461 -0
  617. package/src/__tests__/components/serp-preview.render.test.tsx +6 -3
  618. package/src/__tests__/components/shell-primitives.render.test.tsx +951 -0
  619. package/src/__tests__/components/theme-provider-accent.test.tsx +83 -8
  620. package/src/__tests__/components/toggle.test.tsx +11 -3
  621. package/src/__tests__/components/ui-primitives.test.tsx +5 -8
  622. package/src/__tests__/layout/build-nav-items.test.ts +1 -1
  623. package/src/__tests__/layout/shell-nav.render.test.tsx +983 -0
  624. package/src/__tests__/layout/sidebar-forms-submenu.render.test.tsx +8 -4
  625. package/src/__tests__/layout/sidebar-groups.render.test.tsx +116 -0
  626. package/src/__tests__/layout/sidebar-menus.render.test.tsx +116 -0
  627. package/src/__tests__/layout/sidebar-plugin-nav.test.ts +1 -1
  628. package/src/__tests__/layout/sidebar-posts.test.ts +48 -40
  629. package/src/__tests__/layout/sidebar-submenu.render.test.tsx +35 -10
  630. package/src/__tests__/layout/topbar.render.test.tsx +464 -0
  631. package/src/__tests__/lib/api.test.ts +2 -0
  632. package/src/__tests__/lib/job-drawer.test.ts +493 -0
  633. package/src/__tests__/lib/job-view.test.ts +437 -0
  634. package/src/__tests__/lib/jobs-service.test.ts +98 -0
  635. package/src/__tests__/router/admin-route-order.test.ts +39 -0
  636. package/src/__tests__/styles/ai-gradient-contrast.test.ts +135 -0
  637. package/src/__tests__/styles/breakpoint-order.test.ts +68 -0
  638. package/src/__tests__/styles/responsive-layer.test.ts +367 -12
  639. package/src/__tests__/styles/tailwind-preset.test.ts +154 -0
  640. package/src/__tests__/styles/theme-token-scope.test.ts +10 -3
  641. package/src/__tests__/styles/tiers.test.ts +136 -0
  642. package/src/__tests__/styles/tokens-drift.test.ts +67 -6
  643. package/src/__tests__/views/admin-lazy-route.render.test.tsx +41 -1
  644. package/src/__tests__/views/ai-settings.render.test.tsx +4 -4
  645. package/src/__tests__/views/appearance-menus-route.render.test.tsx +58 -0
  646. package/src/__tests__/views/appearance-settings.render.test.tsx +10 -8
  647. package/src/__tests__/views/appearance-theme-provider.render.test.tsx +347 -0
  648. package/src/__tests__/views/dashboard.test.tsx +48 -0
  649. package/src/__tests__/views/document-edit-navigation.render.test.tsx +130 -0
  650. package/src/__tests__/views/document-edit-routes.render.test.tsx +130 -0
  651. package/src/__tests__/views/email-settings.render.test.tsx +2 -2
  652. package/src/__tests__/views/form-entries.render.test.tsx +22 -0
  653. package/src/__tests__/views/form-submissions.render.test.tsx +22 -0
  654. package/src/__tests__/views/forms-list.render.test.tsx +13 -0
  655. package/src/__tests__/views/general-settings.render.test.tsx +38 -11
  656. package/src/__tests__/views/jobs-drawer.render.test.tsx +1047 -0
  657. package/src/__tests__/views/jobs-list.render.test.tsx +850 -0
  658. package/src/__tests__/views/kpi-grid.test.ts +29 -0
  659. package/src/__tests__/views/mcp-connect.render.test.tsx +1 -0
  660. package/src/__tests__/views/post-section-editor.test.tsx +5 -1
  661. package/src/__tests__/views/script-tags.render.test.tsx +29 -0
  662. package/src/__tests__/views/security-settings.render.test.tsx +9 -10
  663. package/src/__tests__/views/seo-settings.render.test.tsx +7 -9
  664. package/src/__tests__/views/settings-save-bar.render.test.tsx +91 -0
  665. package/src/__tests__/views/settings-save-footer.render.test.tsx +25 -15
  666. package/src/__tests__/views/settings-tabs.render.test.tsx +371 -0
  667. package/src/__tests__/views/updates-tab.render.test.tsx +4 -3
  668. package/src/components/Breadcrumbs.tsx +7 -1
  669. package/src/components/CommandPalette.tsx +51 -3
  670. package/src/components/LocaleSwitcher.tsx +5 -6
  671. package/src/components/NotificationBell.tsx +74 -18
  672. package/src/components/OfflineStatus.tsx +1 -1
  673. package/src/components/PresenceIndicator.tsx +2 -1
  674. package/src/components/ReflowMeter.tsx +3 -3
  675. package/src/components/SEOPanel.tsx +2 -2
  676. package/src/components/ThemeProvider.tsx +122 -42
  677. package/src/components/TipTapEditor.tsx +3 -4
  678. package/src/components/forms/EmbedPanel.tsx +1 -1
  679. package/src/components/forms/FormEntryDetailPane.tsx +7 -1
  680. package/src/components/forms/ShortcodeGlossary.tsx +7 -1
  681. package/src/components/forms/primitives.tsx +37 -21
  682. package/src/components/pages/tag-badges.tsx +4 -3
  683. package/src/components/seo/PageAuditPanel.tsx +2 -2
  684. package/src/components/seo/SerpPreview.tsx +5 -5
  685. package/src/components/seo/primitives.tsx +2 -2
  686. package/src/components/ui/AuthorAvatar.tsx +11 -10
  687. package/src/components/ui/Badge.tsx +1 -1
  688. package/src/components/ui/Breadcrumb.tsx +109 -0
  689. package/src/components/ui/Button.tsx +40 -15
  690. package/src/components/ui/Card.tsx +35 -32
  691. package/src/components/ui/CardListControls.tsx +90 -0
  692. package/src/components/ui/CountChip.tsx +90 -0
  693. package/src/components/ui/FilterPill.tsx +5 -3
  694. package/src/components/ui/InspectorPane.tsx +21 -7
  695. package/src/components/ui/Modal.tsx +20 -6
  696. package/src/components/ui/PageHeader.tsx +63 -0
  697. package/src/components/ui/RowActions.tsx +7 -2
  698. package/src/components/ui/Segmented.tsx +97 -0
  699. package/src/components/ui/Toaster.tsx +139 -0
  700. package/src/components/ui/Toggle.tsx +18 -14
  701. package/src/components/ui/UnderlineTabs.tsx +373 -0
  702. package/src/components/ui/UnsavedBar.tsx +119 -0
  703. package/src/components/ui/admin-links.tsx +20 -0
  704. package/src/components/ui/card-table.ts +34 -0
  705. package/src/components/virtual-window.tsx +13 -2
  706. package/src/fields/RelationshipField.tsx +1 -1
  707. package/src/hooks/useAppearanceBootstrap.ts +9 -3
  708. package/src/index.ts +19 -0
  709. package/src/layout/Header.tsx +210 -135
  710. package/src/layout/Layout.tsx +61 -108
  711. package/src/layout/MobileTabBar.tsx +92 -0
  712. package/src/layout/Sidebar.tsx +555 -593
  713. package/src/layout/nav-config.tsx +425 -0
  714. package/src/layout/primitives/AdminShell.tsx +154 -6
  715. package/src/layout/topbar-classes.ts +8 -0
  716. package/src/layout/use-nav-items.ts +40 -0
  717. package/src/lib/api.ts +7 -1
  718. package/src/lib/appearance-api.ts +4 -0
  719. package/src/lib/job-drawer.ts +424 -0
  720. package/src/lib/job-view.ts +456 -0
  721. package/src/lib/jobs-service.ts +290 -0
  722. package/src/lib/sheet-focus.ts +71 -0
  723. package/src/lib/tiers.ts +43 -0
  724. package/src/router/admin-routes.ts +8 -0
  725. package/src/router/index.ts +9 -1
  726. package/src/styles/prenta-tokens.css +263 -82
  727. package/src/styles/responsive.css +460 -22
  728. package/src/styles/theme.css +177 -28
  729. package/src/views/ApiKeys.tsx +2 -2
  730. package/src/views/AppearanceChrome.tsx +74 -0
  731. package/src/views/CollectionList.tsx +264 -205
  732. package/src/views/Dashboard.tsx +26 -13
  733. package/src/views/DocumentEdit.tsx +111 -56
  734. package/src/views/FormDeliveries.tsx +30 -17
  735. package/src/views/FormEntries.tsx +28 -20
  736. package/src/views/FormSubmissions.tsx +32 -34
  737. package/src/views/Forms.tsx +55 -34
  738. package/src/views/FormsSettings.tsx +94 -0
  739. package/src/views/Jobs/BusyButton.tsx +56 -0
  740. package/src/views/Jobs/CancelJobDialog.tsx +127 -0
  741. package/src/views/Jobs/DrawerActivity.tsx +142 -0
  742. package/src/views/Jobs/DrawerOverview.tsx +139 -0
  743. package/src/views/Jobs/DrawerResults.tsx +155 -0
  744. package/src/views/Jobs/DrawerReview.tsx +464 -0
  745. package/src/views/Jobs/JobDrawer.tsx +556 -0
  746. package/src/views/Jobs/JobsTable.tsx +260 -0
  747. package/src/views/Jobs/WorkerStrip.tsx +144 -0
  748. package/src/views/Jobs/atoms.tsx +93 -0
  749. package/src/views/Jobs/focus.ts +56 -0
  750. package/src/views/Jobs/icons.tsx +111 -0
  751. package/src/views/Jobs/placeholders.tsx +66 -0
  752. package/src/views/Jobs/useJobDetail.ts +64 -0
  753. package/src/views/Jobs/useJobsFeed.ts +249 -0
  754. package/src/views/Jobs/useReviewItems.ts +187 -0
  755. package/src/views/Jobs.tsx +282 -105
  756. package/src/views/MediaBrowser.tsx +71 -21
  757. package/src/views/Pages/PagesListView.tsx +115 -39
  758. package/src/views/Posts/NewPostTypeInstructions.tsx +15 -10
  759. package/src/views/Posts/PostTypesView.tsx +28 -6
  760. package/src/views/Posts/PostsListView.tsx +130 -40
  761. package/src/views/SEO.tsx +23 -8
  762. package/src/views/ScriptTags.tsx +233 -153
  763. package/src/views/Settings.tsx +215 -256
  764. package/src/views/SpamFolder.tsx +32 -0
  765. package/src/views/Trash.tsx +12 -1
  766. package/src/views/Users.tsx +2 -2
  767. package/src/views/WidgetsPlaceholder.tsx +33 -0
  768. package/src/views/dashboard/kpi-grid.ts +38 -0
  769. package/src/views/lazy-views.tsx +12 -0
  770. package/src/views/page-editor/PageTab.tsx +2 -2
  771. package/src/views/page-editor/ReviewBar.tsx +1 -1
  772. package/src/views/page-editor/VersionHistoryPanel.tsx +1 -1
  773. package/src/views/seo/AuditTab.tsx +1 -1
  774. package/src/views/seo/OverviewTab.tsx +6 -5
  775. package/src/views/seo/ProposalsTab.tsx +1 -1
  776. package/src/views/settings/AISettingsTab.tsx +10 -6
  777. package/src/views/settings/AccessProtectionCard.tsx +1 -1
  778. package/src/views/settings/AdminThemeCard.tsx +228 -35
  779. package/src/views/settings/AppearanceTab.tsx +10 -6
  780. package/src/views/settings/BrandPreviewCard.tsx +1 -1
  781. package/src/views/settings/BrandVoiceCard.tsx +1 -1
  782. package/src/views/settings/EmailSettingsTab.tsx +11 -7
  783. package/src/views/settings/GeneralSettingsTab.tsx +10 -6
  784. package/src/views/settings/McpConnectTab.tsx +2 -1
  785. package/src/views/settings/ProviderConnectionCard.tsx +1 -1
  786. package/src/views/settings/SearchDataCard.tsx +1 -1
  787. package/src/views/settings/SecurityStatusCard.tsx +2 -2
  788. package/src/views/settings/SecurityTab.tsx +10 -6
  789. package/src/views/settings/SeoAutopilotCard.tsx +2 -2
  790. package/src/views/settings/SeoSettingsTab.tsx +13 -9
  791. package/src/views/settings/SiteIndexStatusCard.tsx +1 -1
  792. package/src/views/settings/SiteThemeCard.tsx +1 -1
  793. package/src/views/settings/UpdatesTab.tsx +107 -101
  794. package/src/views/settings/components.tsx +26 -62
  795. package/src/views/settings/useAppearanceSettings.ts +116 -25
  796. package/src/views/users/UserDetailDrawer.tsx +1 -1
  797. package/dist/components/ui/StatPill.d.ts +0 -18
  798. package/dist/components/ui/StatPill.d.ts.map +0 -1
  799. package/dist/components/ui/StatPill.js +0 -5
  800. package/dist/components/ui/StatPill.js.map +0 -1
  801. package/src/components/ui/StatPill.tsx +0 -37
@@ -0,0 +1,33 @@
1
+ 'use client'
2
+
3
+ import { Breadcrumb } from '../components/ui/Breadcrumb.js'
4
+ import { PageHeader } from '../components/ui/PageHeader.js'
5
+ import { EmptyState } from '../components/ui/EmptyState.js'
6
+ import { LayoutGrid } from 'lucide-react'
7
+
8
+ export function WidgetsPlaceholder() {
9
+ return (
10
+ <div className="flex flex-col gap-6 p-6">
11
+ <PageHeader
12
+ flush
13
+ title="Widgets"
14
+ subtitle="Widget areas will be editable here."
15
+ breadcrumb={
16
+ <Breadcrumb
17
+ items={[
18
+ { label: 'Dashboard', path: '/' },
19
+ // No Appearance landing screen exists yet, so the section is not a link.
20
+ { label: 'Appearance' },
21
+ { label: 'Widgets' },
22
+ ]}
23
+ />
24
+ }
25
+ />
26
+ <EmptyState
27
+ icon={<LayoutGrid size={24} aria-hidden />}
28
+ title="No widgets yet"
29
+ description="This screen is a placeholder. Header and footer are edited from Appearance."
30
+ />
31
+ </div>
32
+ )
33
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Dashboard KPI grid (SHELL.md §8, Dashboard.html `.kpis`).
3
+ *
4
+ * Five cards: one row of five from 1400px; below that a six-track grid where
5
+ * the first two cards span three tracks and the rest two (2+3); on phones two
6
+ * columns, the last card spanning both.
7
+ *
8
+ * Any other count (four, when the site has a single content collection) gets
9
+ * the same tiers without empty slots: one row from 1400px, two columns below,
10
+ * and an odd last card spanning both columns.
11
+ *
12
+ * 1400px is the kit's own step, not a layout tier, so it uses the stock
13
+ * `min-[1400px]:` variant. The classes are written out in full so Tailwind
14
+ * sees them.
15
+ */
16
+
17
+ const WIDE_COLUMNS: Record<number, string> = {
18
+ 1: 'min-[1400px]:grid-cols-1',
19
+ 2: 'min-[1400px]:grid-cols-2',
20
+ 3: 'min-[1400px]:grid-cols-3',
21
+ 4: 'min-[1400px]:grid-cols-4',
22
+ 5: 'min-[1400px]:grid-cols-5',
23
+ }
24
+
25
+ export function kpiGridClass(count: number): string {
26
+ const wide = WIDE_COLUMNS[count] ?? 'min-[1400px]:grid-cols-5'
27
+ const base = count === 5 ? 'grid-cols-6 mobile:grid-cols-2' : 'grid-cols-2'
28
+ return `grid gap-3 mobile:gap-2 ${base} ${wide}`
29
+ }
30
+
31
+ export function kpiCardSpan(index: number, count: number): string {
32
+ const last = index === count - 1
33
+ if (count === 5) {
34
+ const tablet = index < 2 ? 'col-span-3' : 'col-span-2'
35
+ return `${tablet} min-[1400px]:col-span-1 ${last ? 'mobile:col-span-2' : 'mobile:col-span-1'}`
36
+ }
37
+ return last && count % 2 === 1 ? 'col-span-2 min-[1400px]:col-span-1' : ''
38
+ }
@@ -18,6 +18,18 @@ export const MediaBrowser = lazy(() =>
18
18
  )
19
19
  export const Settings = lazy(() => import('./Settings.js').then((m) => ({ default: m.Settings })))
20
20
  export const Jobs = lazy(() => import('./Jobs.js').then((m) => ({ default: m.Jobs })))
21
+ export const AppearanceChrome = lazy(() =>
22
+ import('./AppearanceChrome.js').then((m) => ({ default: m.AppearanceChrome })),
23
+ )
24
+ export const WidgetsPlaceholder = lazy(() =>
25
+ import('./WidgetsPlaceholder.js').then((m) => ({ default: m.WidgetsPlaceholder })),
26
+ )
27
+ export const FormsSettings = lazy(() =>
28
+ import('./FormsSettings.js').then((m) => ({ default: m.FormsSettings })),
29
+ )
30
+ export const SpamFolder = lazy(() =>
31
+ import('./SpamFolder.js').then((m) => ({ default: m.SpamFolder })),
32
+ )
21
33
  export const Profile = lazy(() => import('./Profile.js').then((m) => ({ default: m.Profile })))
22
34
  export const Forms = lazy(() => import('./Forms.js').then((m) => ({ default: m.Forms })))
23
35
  export const FormEditor = lazy(() =>
@@ -157,7 +157,7 @@ export function PageTab({
157
157
  breaks nothing, and warning about it would train editors to dismiss
158
158
  the warning that matters. */}
159
159
  {move && (
160
- <div className="bg-warning/10 border-warning/30 space-y-2 rounded-lg border p-2.5">
160
+ <div className="bg-warn-l border-warning/30 space-y-2 rounded-lg border p-2.5">
161
161
  <div className="flex gap-2">
162
162
  <AlertTriangle size={14} className="text-warning mt-px shrink-0" aria-hidden />
163
163
  <p className="text-[11.5px] leading-normal">
@@ -336,7 +336,7 @@ export function PageTab({
336
336
  </div>
337
337
 
338
338
  {!directives.index && (
339
- <div className="bg-warning/10 border-warning/30 flex gap-2 rounded-lg border p-2.5">
339
+ <div className="bg-warn-l border-warning/30 flex gap-2 rounded-lg border p-2.5">
340
340
  <AlertTriangle size={14} className="text-warning mt-px shrink-0" aria-hidden />
341
341
  <p className="text-[11.5px] leading-normal">
342
342
  <b className="font-semibold">This page is hidden from search.</b> Publishing will not
@@ -36,7 +36,7 @@ export function ReviewBar({
36
36
  // whole canvas means, and a screen-reader user gets no equivalent of the
37
37
  // amber colour that announces it to everyone else.
38
38
  role="status"
39
- className="border-warning/35 bg-warning/10 text-foreground mx-auto mb-3 flex w-fit max-w-full flex-wrap items-center gap-2.5 rounded-full border py-1.5 pr-1.5 pl-3.5 text-[11.5px]"
39
+ className="border-warning/35 bg-warn-l text-foreground mx-auto mb-3 flex w-fit max-w-full flex-wrap items-center gap-2.5 rounded-full border py-1.5 pr-1.5 pl-3.5 text-[11.5px]"
40
40
  >
41
41
  <History className="text-warning h-3.5 w-3.5 shrink-0" aria-hidden />
42
42
  <span className="min-w-0">
@@ -159,7 +159,7 @@ export function VersionHistoryPanel({
159
159
 
160
160
  const TONE_CLASS: Record<string, string> = {
161
161
  live: 'bg-success/15 text-success',
162
- draft: 'bg-warning/15 text-warning',
162
+ draft: 'bg-warn-l text-warning',
163
163
  neutral: 'bg-muted text-muted-foreground',
164
164
  danger: 'bg-destructive/15 text-destructive',
165
165
  }
@@ -125,7 +125,7 @@ function AuditSummaryCards({ refetchKey }: { refetchKey: number }) {
125
125
  {coverage?.partial ? (
126
126
  <div
127
127
  role="status"
128
- className="border-warning/30 bg-warning/10 text-foreground rounded-lg border p-4"
128
+ className="border-warning/30 bg-warn-l text-foreground rounded-lg border p-4"
129
129
  >
130
130
  <div className="flex items-start gap-3">
131
131
  <AlertTriangle size={20} className="text-warning shrink-0" aria-hidden="true" />
@@ -57,9 +57,10 @@ export function OverviewTab({
57
57
 
58
58
  return (
59
59
  <div className="space-y-6">
60
- {/* Site score + metrics */}
61
- <div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
62
- <SectionCard title="Site SEO Score" className="lg:col-span-1">
60
+ {/* Site score + metrics. One column up to 1024px, where the score stops
61
+ fighting the metrics (cms-layouts.css `.ov-top`, tablet). */}
62
+ <div className="not-narrow:grid-cols-3 grid grid-cols-1 gap-4">
63
+ <SectionCard title="Site SEO Score" className="not-narrow:col-span-1">
63
64
  <div className="flex items-center gap-4">
64
65
  <div className="flex flex-col">
65
66
  <span className="text-foreground text-4xl font-medium tabular-nums">
@@ -98,7 +99,7 @@ export function OverviewTab({
98
99
  )}
99
100
  </SectionCard>
100
101
 
101
- <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:col-span-2">
102
+ <div className="not-narrow:col-span-2 grid grid-cols-1 gap-4 sm:grid-cols-2">
102
103
  {metrics.length === 0 ? (
103
104
  <div className="sm:col-span-2">
104
105
  <SeoEmptyState
@@ -165,7 +166,7 @@ export function OverviewTab({
165
166
  tone === 'poor'
166
167
  ? 'bg-destructive/10 text-destructive'
167
168
  : tone === 'fair'
168
- ? 'bg-warning/10 text-warning'
169
+ ? 'bg-warn-l text-warning'
169
170
  : 'bg-success/10 text-success'
170
171
  return (
171
172
  <li key={w.id} className="flex items-start justify-between gap-3 py-3">
@@ -233,7 +233,7 @@ function AutopilotChip({
233
233
  ? `Autopilot paused — ${chipPauseLabel(autopilot.pausedReason)}`
234
234
  : `Autopilot on · ${autopilot.appliedLast7d} applied this week`
235
235
  const tone = paused
236
- ? 'border-warning/40 bg-warning/10 text-foreground hover:bg-warning/20'
236
+ ? 'border-warning/40 bg-warn-l text-foreground hover:bg-warning/20'
237
237
  : 'border-border bg-muted/40 text-foreground hover:bg-accent'
238
238
  return (
239
239
  <button
@@ -8,7 +8,8 @@ import { BrandVoiceCard, type BrandVoiceAiReadiness } from './BrandVoiceCard.js'
8
8
  import { ModelSelector } from './ModelSelector.js'
9
9
  import { MonthlyUsageCard } from './MonthlyUsageCard.js'
10
10
  import { ProviderConnectionCard } from './ProviderConnectionCard.js'
11
- import { SettingsCard, SettingsSaveBar } from './components.js'
11
+ import { UnsavedBar } from '../../components/ui/UnsavedBar.js'
12
+ import { SettingsCard, useSavedToast } from './components.js'
12
13
  import {
13
14
  useAiSettings,
14
15
  type AiProviderKey,
@@ -37,6 +38,7 @@ export interface AISettingsTabProps {
37
38
  export function AISettingsTab({ role, config }: AISettingsTabProps) {
38
39
  const canEdit = role === 'ADMIN'
39
40
  const ai = useAiSettings(canEdit)
41
+ useSavedToast(ai.saveState)
40
42
 
41
43
  const brandVoiceAiReadiness = useMemo((): BrandVoiceAiReadiness => {
42
44
  const contentWriting = ai.form.features.find((f) => f.key === 'ai.features.contentWriting')
@@ -165,13 +167,15 @@ export function AISettingsTab({ role, config }: AISettingsTabProps) {
165
167
  </div>
166
168
  )}
167
169
 
168
- <SettingsSaveBar
170
+ <UnsavedBar
169
171
  dirty={ai.dirty}
170
- canEdit={canEdit}
171
- hasErrors={Boolean(ai.budgetError)}
172
- saveState={ai.saveState}
172
+ saving={ai.saveState === 'saving'}
173
+ saveDisabled={!canEdit || Boolean(ai.budgetError)}
173
174
  onSave={ai.save}
174
- onReset={ai.reset}
175
+ onDiscard={ai.reset}
176
+ discardLabel="Reset"
177
+ saveLabel="Save changes"
178
+ variant="card"
175
179
  />
176
180
  </div>
177
181
  )
@@ -78,7 +78,7 @@ export function AccessProtectionCard({
78
78
  </p>
79
79
  )}
80
80
  {entries.length > 0 && (
81
- <div className="border-warning/30 bg-warning/10 text-warning flex items-start gap-2 rounded-md border p-2.5 text-sm">
81
+ <div className="border-warning/30 bg-warn-l text-warning flex items-start gap-2 rounded-md border p-2.5 text-sm">
82
82
  <AlertTriangle size={15} className="mt-0.5 shrink-0" aria-hidden="true" />
83
83
  <span>
84
84
  Make sure your own IP
@@ -1,18 +1,44 @@
1
1
  'use client'
2
2
 
3
- import { ACCENT_PRESET_LIST } from '@prenta/core/appearance'
4
- import type { ColorMode, SidebarDensity } from '@prenta/core/appearance'
5
- import { Check, Monitor, Moon, Sun } from 'lucide-react'
3
+ import {
4
+ ACCENT_PRESETS,
5
+ ACCENT_PRESET_LIST,
6
+ isAccentPreset,
7
+ toHex,
8
+ type SidebarDensity,
9
+ } from '@prenta/core/appearance'
10
+ import { Check } from 'lucide-react'
11
+ import { useState } from 'react'
6
12
 
13
+ import type { ThemeBase } from '../../components/ThemeProvider.js'
14
+ import { inputVariants } from '../../components/ui/Input.js'
15
+ import { Toggle } from '../../components/ui/Toggle.js'
7
16
  import { SettingsSourceBadge } from './components.js'
8
17
  import type { UseAppearanceSettings } from './useAppearanceSettings.js'
9
18
 
10
- const COLOR_MODES: { value: ColorMode; label: string; Icon: typeof Sun }[] = [
11
- { value: 'light', label: 'Light', Icon: Sun },
12
- { value: 'dark', label: 'Dark', Icon: Moon },
13
- { value: 'system', label: 'System', Icon: Monitor },
19
+ /** The kit's three bases (prototype/design-system/theme.js `BASES`). */
20
+ const BASES: { id: ThemeBase; name: string; desc: string }[] = [
21
+ { id: 'porcelain', name: 'Porcelain', desc: 'Cool neutral light' },
22
+ { id: 'linen', name: 'Linen', desc: 'Warm neutral light' },
23
+ { id: 'graphite', name: 'Graphite', desc: 'Neutral dark' },
14
24
  ]
15
25
 
26
+ const DEFAULT_ACCENT = ACCENT_PRESET_LIST[0]!
27
+
28
+ /** A typed or picked hex that equals a preset swatch is stored as that preset. */
29
+ function accentFromHex(hex: string): string {
30
+ return ACCENT_PRESET_LIST.find((p) => p.swatch.toLowerCase() === hex)?.name ?? hex
31
+ }
32
+
33
+ /**
34
+ * Rainbow behind the custom-color swatch, built from the preset picks so it
35
+ * stays tied to the palette instead of carrying its own hex values.
36
+ */
37
+ const CUSTOM_SWATCH_BG = `conic-gradient(from 0deg, ${[
38
+ ...[2, 3, 1, 0, 4].map((i) => ACCENT_PRESET_LIST[i]!.swatch),
39
+ ACCENT_PRESET_LIST[2]!.swatch,
40
+ ].join(', ')})`
41
+
16
42
  const DENSITIES: { value: SidebarDensity; label: string }[] = [
17
43
  { value: 'default', label: 'Default' },
18
44
  { value: 'compact', label: 'Compact' },
@@ -27,7 +53,7 @@ function SegmentedGroup<T extends string>({
27
53
  }: {
28
54
  label: string
29
55
  value: T
30
- options: { value: T; label: string; Icon?: typeof Sun }[]
56
+ options: { value: T; label: string }[]
31
57
  canEdit: boolean
32
58
  onChange: (v: T) => void
33
59
  }) {
@@ -37,7 +63,7 @@ function SegmentedGroup<T extends string>({
37
63
  aria-label={label}
38
64
  className="border-border bg-muted inline-flex flex-wrap rounded-md border p-0.5"
39
65
  >
40
- {options.map(({ value: v, label: text, Icon }) => {
66
+ {options.map(({ value: v, label: text }) => {
41
67
  const active = value === v
42
68
  return (
43
69
  <button
@@ -53,7 +79,6 @@ function SegmentedGroup<T extends string>({
53
79
  : 'text-muted-foreground hover:text-foreground'
54
80
  }`}
55
81
  >
56
- {Icon && <Icon size={14} aria-hidden="true" />}
57
82
  {text}
58
83
  </button>
59
84
  )
@@ -62,7 +87,86 @@ function SegmentedGroup<T extends string>({
62
87
  )
63
88
  }
64
89
 
90
+ /**
91
+ * A base card. The preview paints with that base's real tokens
92
+ * (`.prenta-base-preview[data-base]` in prenta-tokens.css) and the picked
93
+ * accent, so it can't drift from what the admin renders.
94
+ */
95
+ function BaseCard({
96
+ base,
97
+ checked,
98
+ disabled,
99
+ onPick,
100
+ }: {
101
+ base: (typeof BASES)[number]
102
+ checked: boolean
103
+ disabled: boolean
104
+ onPick: () => void
105
+ }) {
106
+ return (
107
+ <button
108
+ type="button"
109
+ role="radio"
110
+ aria-checked={checked}
111
+ disabled={disabled}
112
+ onClick={onPick}
113
+ className={`bg-card focus-visible:shadow-ring flex flex-col overflow-hidden rounded-[11px] border-[1.5px] text-left transition-colors duration-[var(--mo-fast)] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${
114
+ checked ? 'border-acc shadow-[0_0_0_3px_var(--acc-l)]' : 'border-bdr hover:border-faint'
115
+ }`}
116
+ >
117
+ <div aria-hidden="true" className="prenta-base-preview w-full" data-base={base.id}>
118
+ <div className="border-bdr bg-bg flex h-[92px] gap-[7px] border-b p-[9px]">
119
+ <div className="border-bdr bg-card rounded-5 flex w-[30%] flex-col gap-[5px] border p-1.5">
120
+ <i className="bg-acc block h-[5px] rounded-[3px]" />
121
+ <i className="bg-bdr block h-[5px] rounded-[3px]" />
122
+ <i className="bg-bdr block h-[5px] rounded-[3px]" />
123
+ </div>
124
+ <div className="flex flex-1">
125
+ <div className="border-bdr bg-card rounded-5 flex flex-1 flex-col gap-1.5 border p-2">
126
+ <i className="bg-txt block h-[5px] w-[46%] rounded-[3px]" />
127
+ <i className="bg-bdr block h-[5px] w-[78%] rounded-[3px]" />
128
+ <span className="bg-acc rounded-4 mt-auto h-3 w-[38px]" />
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ <div className="relative flex items-baseline gap-2 px-3 py-2.5">
134
+ <span className="text-body text-txt font-semibold">{base.name}</span>
135
+ <span className="text-hint text-sub">{base.desc}</span>
136
+ {checked && (
137
+ <span className="bg-acc text-acc-on absolute top-[9px] right-2.5 flex h-5 w-5 items-center justify-center rounded-full">
138
+ <Check size={13} aria-hidden="true" />
139
+ </span>
140
+ )}
141
+ </div>
142
+ </button>
143
+ )
144
+ }
145
+
65
146
  export function AdminThemeCard({ s, canEdit }: { s: UseAppearanceSettings; canEdit: boolean }) {
147
+ const { colorMode, lightBase, accent } = s.appearance
148
+ const matchSystem = colorMode === 'system'
149
+ const current: ThemeBase = colorMode === 'dark' ? 'graphite' : lightBase
150
+ const accentEditable = canEdit && s.sources.accent?.editable !== false
151
+
152
+ // Legacy names (`purple`, `blue`, …) are stored aliases of a picker preset.
153
+ const preset = isAccentPreset(accent)
154
+ ? ACCENT_PRESET_LIST.find((p) => p.swatch === ACCENT_PRESETS[accent].swatch)
155
+ : undefined
156
+ const accentHex = preset?.swatch ?? toHex(accent) ?? DEFAULT_ACCENT.swatch
157
+ // What the hex field shows while a value is half-typed; null shows the accent.
158
+ const [hexDraft, setHexDraft] = useState<string | null>(null)
159
+
160
+ const onHex = (raw: string) => {
161
+ const v = raw.startsWith('#') ? raw : `#${raw}`
162
+ if (/^#[0-9a-f]{6}$/i.test(v)) {
163
+ setHexDraft(null)
164
+ s.setAccent(accentFromHex(v.toLowerCase()))
165
+ } else {
166
+ setHexDraft(v)
167
+ }
168
+ }
169
+
66
170
  return (
67
171
  <section className="border-border bg-card rounded-lg border p-6">
68
172
  <header className="mb-4">
@@ -75,61 +179,150 @@ export function AdminThemeCard({ s, canEdit }: { s: UseAppearanceSettings; canEd
75
179
  <div className="space-y-5">
76
180
  <div>
77
181
  <div className="mb-2 flex items-center gap-2">
78
- <span className="text-foreground text-base font-medium">Color mode</span>
182
+ <span id="admin-theme-base" className="text-sm2 text-txt font-semibold">
183
+ Base theme
184
+ </span>
79
185
  <SettingsSourceBadge meta={s.sources.colorMode} />
80
186
  </div>
81
- <SegmentedGroup
82
- label="Color mode"
83
- value={s.appearance.colorMode}
84
- options={COLOR_MODES}
85
- canEdit={canEdit}
86
- onChange={s.setColorMode}
187
+ <div
188
+ role="radiogroup"
189
+ aria-labelledby="admin-theme-base"
190
+ className="grid grid-cols-[repeat(auto-fill,minmax(180px,1fr))] gap-3"
191
+ >
192
+ {BASES.map((base) => (
193
+ <BaseCard
194
+ key={base.id}
195
+ base={base}
196
+ checked={!matchSystem && current === base.id}
197
+ disabled={!canEdit}
198
+ onPick={() => s.setBase(base.id)}
199
+ />
200
+ ))}
201
+ </div>
202
+ </div>
203
+
204
+ <div className="flex items-center justify-between gap-5">
205
+ <div>
206
+ <div id="admin-theme-system" className="text-body text-txt font-semibold">
207
+ Match operating system
208
+ </div>
209
+ <div id="admin-theme-system-hint" className="text-hint text-sub mt-[3px]">
210
+ Uses {lightBase === 'linen' ? 'Linen' : 'Porcelain'} by day and Graphite when your OS
211
+ is in dark mode.
212
+ </div>
213
+ </div>
214
+ <Toggle
215
+ checked={matchSystem}
216
+ onCheckedChange={s.setMatchSystem}
217
+ disabled={!canEdit}
218
+ aria-labelledby="admin-theme-system"
219
+ aria-describedby="admin-theme-system-hint"
87
220
  />
88
221
  </div>
89
222
 
90
223
  <div>
91
224
  <div className="mb-2 flex items-center gap-2">
92
- <span className="text-foreground text-base font-medium">Accent color</span>
225
+ <span id="admin-theme-accent" className="text-sm2 text-txt font-semibold">
226
+ Accent color
227
+ </span>
93
228
  <SettingsSourceBadge meta={s.sources.accent} />
94
229
  </div>
95
230
  <div
96
231
  role="radiogroup"
97
- aria-label="Accent color"
232
+ aria-labelledby="admin-theme-accent"
98
233
  className="flex flex-wrap items-center gap-3"
99
234
  >
100
- {ACCENT_PRESET_LIST.map((preset) => {
101
- const active = s.appearance.accent === preset.name
102
- const editable = s.sources.accent?.editable !== false
235
+ {ACCENT_PRESET_LIST.map((p) => {
236
+ const active = preset === p
103
237
  return (
104
238
  <button
105
- key={preset.name}
239
+ key={p.name}
106
240
  type="button"
107
241
  role="radio"
108
242
  aria-checked={active}
109
- aria-label={preset.label}
110
- title={preset.label}
111
- disabled={!canEdit || !editable}
112
- onClick={() => s.setAccent(preset.name)}
113
- className={`focus-visible:ring-ring relative flex h-9 w-9 items-center justify-center rounded-full transition-transform focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${
114
- active ? 'ring-foreground ring-2 ring-offset-2' : ''
243
+ aria-label={p.label}
244
+ title={p.label}
245
+ disabled={!accentEditable}
246
+ onClick={() => s.setAccent(p.name)}
247
+ className={`border-card text-acc-on focus-visible:shadow-ring relative flex h-[30px] w-[30px] items-center justify-center rounded-full border-2 transition-transform hover:scale-110 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${
248
+ active
249
+ ? 'shadow-[0_0_0_2px_var(--card),0_0_0_4px_var(--txt)]'
250
+ : 'shadow-[0_0_0_1px_var(--bdr)]'
115
251
  }`}
116
- style={{ backgroundColor: preset.swatch }}
252
+ style={{ backgroundColor: p.swatch }}
117
253
  >
118
- {active && <Check size={16} className="text-white" aria-hidden="true" />}
254
+ {active && <Check size={15} className="text-white" aria-hidden="true" />}
119
255
  </button>
120
256
  )
121
257
  })}
258
+ <label
259
+ title="Custom color"
260
+ className={`border-card has-[:focus-visible]:shadow-ring relative flex h-[30px] w-[30px] cursor-pointer items-center justify-center overflow-hidden rounded-full border-2 transition-transform hover:scale-110 ${
261
+ preset
262
+ ? 'shadow-[0_0_0_1px_var(--bdr)]'
263
+ : 'shadow-[0_0_0_2px_var(--card),0_0_0_4px_var(--txt)]'
264
+ } ${accentEditable ? '' : 'pointer-events-none opacity-50'}`}
265
+ style={{ background: preset ? CUSTOM_SWATCH_BG : accentHex }}
266
+ >
267
+ <input
268
+ type="color"
269
+ aria-label="Custom accent"
270
+ value={toHex(accentHex)!}
271
+ disabled={!accentEditable}
272
+ onChange={(e) => s.setAccent(accentFromHex(e.target.value.toLowerCase()))}
273
+ className="absolute inset-0 h-full w-full cursor-pointer border-0 p-0 opacity-0"
274
+ />
275
+ {preset ? (
276
+ <span
277
+ aria-hidden="true"
278
+ className="pointer-events-none text-[15px] font-bold text-white [text-shadow:0_1px_2px_rgba(0,0,0,0.35)]"
279
+ >
280
+ +
281
+ </span>
282
+ ) : (
283
+ <Check size={15} className="pointer-events-none text-white" aria-hidden="true" />
284
+ )}
285
+ </label>
122
286
  {/* Text label so accent is not communicated by color alone. */}
123
- <span className="text-muted-foreground text-sm">
124
- {ACCENT_PRESET_LIST.find((p) => p.name === s.appearance.accent)?.label ??
125
- s.appearance.accent}
287
+ <span className="text-body text-txt ml-1 font-semibold">
288
+ {preset?.label ?? 'Custom'}
126
289
  </span>
127
290
  </div>
291
+ <div className="mt-3 flex items-center gap-2">
292
+ <span
293
+ aria-hidden="true"
294
+ className="rounded-5 h-[18px] w-[18px] shrink-0 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.1)]"
295
+ style={{ background: accentHex }}
296
+ />
297
+ <input
298
+ aria-label="Accent hex value"
299
+ value={(hexDraft ?? accentHex).toUpperCase()}
300
+ spellCheck={false}
301
+ maxLength={7}
302
+ disabled={!accentEditable}
303
+ onChange={(e) => onHex(e.target.value)}
304
+ onBlur={() => setHexDraft(null)}
305
+ className={`${inputVariants({ size: 'sm' })} max-w-[120px] font-mono uppercase`}
306
+ />
307
+ {preset !== DEFAULT_ACCENT && accentEditable && (
308
+ <button
309
+ type="button"
310
+ onClick={() => s.setAccent(DEFAULT_ACCENT.name)}
311
+ className="text-sm2 text-sub hover:bg-acc-l hover:text-acc rounded-7 px-2.5 py-1.5 whitespace-nowrap transition-colors"
312
+ >
313
+ Reset to Cobalt
314
+ </button>
315
+ )}
316
+ </div>
317
+ <p className="text-hint text-faint mt-2 leading-[1.45]">
318
+ Tints, focus rings and the dark-mode variant are derived automatically. Pick a mid-tone
319
+ so white button text stays legible.
320
+ </p>
128
321
  </div>
129
322
 
130
323
  <div>
131
324
  <div className="mb-2 flex items-center gap-2">
132
- <span className="text-foreground text-base font-medium">Sidebar density</span>
325
+ <span className="text-sm2 text-txt font-semibold">Sidebar density</span>
133
326
  </div>
134
327
  <SegmentedGroup
135
328
  label="Sidebar density"
@@ -6,7 +6,8 @@ import { AdminThemeCard } from './AdminThemeCard.js'
6
6
  import { SiteThemeCard } from './SiteThemeCard.js'
7
7
  import { BrandPreviewCard } from './BrandPreviewCard.js'
8
8
  import { BrandingCard } from './BrandingCard.js'
9
- import { SettingsSaveBar, SettingsValidationSummary } from './components.js'
9
+ import { UnsavedBar } from '../../components/ui/UnsavedBar.js'
10
+ import { SettingsValidationSummary, useSavedToast } from './components.js'
10
11
  import { TypographyMotionCard } from './TypographyMotionCard.js'
11
12
  import { useAppearanceSettings } from './useAppearanceSettings.js'
12
13
 
@@ -23,6 +24,7 @@ function CardSkeleton() {
23
24
  export function AppearanceTab({ role, config }: AppearanceTabProps) {
24
25
  const canEdit = role === 'ADMIN'
25
26
  const s = useAppearanceSettings(canEdit, config)
27
+ useSavedToast(s.saveState)
26
28
 
27
29
  if (s.loading) {
28
30
  return (
@@ -70,13 +72,15 @@ export function AppearanceTab({ role, config }: AppearanceTabProps) {
70
72
  <TypographyMotionCard s={s} canEdit={canEdit} />
71
73
  <BrandPreviewCard s={s} />
72
74
 
73
- <SettingsSaveBar
75
+ <UnsavedBar
74
76
  dirty={s.dirty}
75
- canEdit={canEdit}
76
- hasErrors={s.issues.some((i) => i.severity === 'error')}
77
- saveState={s.saveState}
77
+ saving={s.saveState === 'saving'}
78
+ saveDisabled={!canEdit || s.issues.some((i) => i.severity === 'error')}
78
79
  onSave={s.save}
79
- onReset={s.reset}
80
+ onDiscard={s.reset}
81
+ discardLabel="Reset"
82
+ saveLabel="Save changes"
83
+ variant="card"
80
84
  />
81
85
  </div>
82
86
  )
@@ -66,7 +66,7 @@ export function BrandPreviewCard({ s }: { s: UseAppearanceSettings }) {
66
66
  </p>
67
67
  </div>
68
68
  {s.dirty && (
69
- <span className="text-warning bg-warning/10 border-warning/30 rounded-md border px-2 py-0.5 text-xs">
69
+ <span className="text-warning bg-warn-l border-warning/30 rounded-md border px-2 py-0.5 text-xs">
70
70
  Unsaved
71
71
  </span>
72
72
  )}
@@ -344,7 +344,7 @@ export function BrandVoiceCard({
344
344
  {aiReadiness && !aiReadiness.ready && aiReadiness.message && (
345
345
  <div
346
346
  role="status"
347
- className="border-warning/40 bg-warning/10 text-foreground flex items-start gap-3 rounded-lg border p-4 text-sm"
347
+ className="border-warning/40 bg-warn-l text-foreground flex items-start gap-3 rounded-lg border p-4 text-sm"
348
348
  >
349
349
  <AlertTriangle size={16} className="text-warning mt-0.5 shrink-0" aria-hidden="true" />
350
350
  <p>{aiReadiness.message}</p>