@prenta/admin 2.6.1 → 2.8.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 (864) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/design-system/tokens.css +196 -85
  3. package/design-system/tokens.json +310 -85
  4. package/design-system/tokens.scss +163 -44
  5. package/design-system/tokens.tailwind.cjs +64 -1
  6. package/dist/AdminRoot.d.ts.map +1 -1
  7. package/dist/AdminRoot.js +43 -21
  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/batch-wizard.test.d.ts +2 -0
  61. package/dist/__tests__/lib/batch-wizard.test.d.ts.map +1 -0
  62. package/dist/__tests__/lib/batch-wizard.test.js +144 -0
  63. package/dist/__tests__/lib/batch-wizard.test.js.map +1 -0
  64. package/dist/__tests__/lib/job-drawer.test.d.ts +2 -0
  65. package/dist/__tests__/lib/job-drawer.test.d.ts.map +1 -0
  66. package/dist/__tests__/lib/job-drawer.test.js +395 -0
  67. package/dist/__tests__/lib/job-drawer.test.js.map +1 -0
  68. package/dist/__tests__/lib/job-view.test.d.ts +2 -0
  69. package/dist/__tests__/lib/job-view.test.d.ts.map +1 -0
  70. package/dist/__tests__/lib/job-view.test.js +484 -0
  71. package/dist/__tests__/lib/job-view.test.js.map +1 -0
  72. package/dist/__tests__/lib/jobs-service.test.d.ts +2 -0
  73. package/dist/__tests__/lib/jobs-service.test.d.ts.map +1 -0
  74. package/dist/__tests__/lib/jobs-service.test.js +142 -0
  75. package/dist/__tests__/lib/jobs-service.test.js.map +1 -0
  76. package/dist/__tests__/router/admin-route-order.test.d.ts +2 -0
  77. package/dist/__tests__/router/admin-route-order.test.d.ts.map +1 -0
  78. package/dist/__tests__/router/admin-route-order.test.js +36 -0
  79. package/dist/__tests__/router/admin-route-order.test.js.map +1 -0
  80. package/dist/__tests__/styles/ai-gradient-contrast.test.d.ts +2 -0
  81. package/dist/__tests__/styles/ai-gradient-contrast.test.d.ts.map +1 -0
  82. package/dist/__tests__/styles/ai-gradient-contrast.test.js +110 -0
  83. package/dist/__tests__/styles/ai-gradient-contrast.test.js.map +1 -0
  84. package/dist/__tests__/styles/breakpoint-order.test.d.ts +2 -0
  85. package/dist/__tests__/styles/breakpoint-order.test.d.ts.map +1 -0
  86. package/dist/__tests__/styles/breakpoint-order.test.js +52 -0
  87. package/dist/__tests__/styles/breakpoint-order.test.js.map +1 -0
  88. package/dist/__tests__/styles/responsive-layer.test.js +303 -12
  89. package/dist/__tests__/styles/responsive-layer.test.js.map +1 -1
  90. package/dist/__tests__/styles/tailwind-preset.test.d.ts +2 -0
  91. package/dist/__tests__/styles/tailwind-preset.test.d.ts.map +1 -0
  92. package/dist/__tests__/styles/tailwind-preset.test.js +147 -0
  93. package/dist/__tests__/styles/tailwind-preset.test.js.map +1 -0
  94. package/dist/__tests__/styles/theme-token-scope.test.js +9 -3
  95. package/dist/__tests__/styles/theme-token-scope.test.js.map +1 -1
  96. package/dist/__tests__/styles/tiers.test.d.ts +2 -0
  97. package/dist/__tests__/styles/tiers.test.d.ts.map +1 -0
  98. package/dist/__tests__/styles/tiers.test.js +121 -0
  99. package/dist/__tests__/styles/tiers.test.js.map +1 -0
  100. package/dist/__tests__/styles/tokens-drift.test.js +57 -6
  101. package/dist/__tests__/styles/tokens-drift.test.js.map +1 -1
  102. package/dist/__tests__/views/admin-lazy-route.render.test.js +27 -1
  103. package/dist/__tests__/views/admin-lazy-route.render.test.js.map +1 -1
  104. package/dist/__tests__/views/ai-settings.render.test.js +4 -4
  105. package/dist/__tests__/views/appearance-chrome.render.test.d.ts +2 -0
  106. package/dist/__tests__/views/appearance-chrome.render.test.d.ts.map +1 -0
  107. package/dist/__tests__/views/appearance-chrome.render.test.js +688 -0
  108. package/dist/__tests__/views/appearance-chrome.render.test.js.map +1 -0
  109. package/dist/__tests__/views/appearance-menus-route.render.test.d.ts +2 -0
  110. package/dist/__tests__/views/appearance-menus-route.render.test.d.ts.map +1 -0
  111. package/dist/__tests__/views/appearance-menus-route.render.test.js +50 -0
  112. package/dist/__tests__/views/appearance-menus-route.render.test.js.map +1 -0
  113. package/dist/__tests__/views/appearance-settings.render.test.js +8 -6
  114. package/dist/__tests__/views/appearance-settings.render.test.js.map +1 -1
  115. package/dist/__tests__/views/appearance-theme-provider.render.test.d.ts +2 -0
  116. package/dist/__tests__/views/appearance-theme-provider.render.test.d.ts.map +1 -0
  117. package/dist/__tests__/views/appearance-theme-provider.render.test.js +286 -0
  118. package/dist/__tests__/views/appearance-theme-provider.render.test.js.map +1 -0
  119. package/dist/__tests__/views/dashboard.test.js +37 -0
  120. package/dist/__tests__/views/dashboard.test.js.map +1 -1
  121. package/dist/__tests__/views/document-edit-navigation.render.test.d.ts +2 -0
  122. package/dist/__tests__/views/document-edit-navigation.render.test.d.ts.map +1 -0
  123. package/dist/__tests__/views/document-edit-navigation.render.test.js +101 -0
  124. package/dist/__tests__/views/document-edit-navigation.render.test.js.map +1 -0
  125. package/dist/__tests__/views/document-edit-routes.render.test.d.ts +2 -0
  126. package/dist/__tests__/views/document-edit-routes.render.test.d.ts.map +1 -0
  127. package/dist/__tests__/views/document-edit-routes.render.test.js +113 -0
  128. package/dist/__tests__/views/document-edit-routes.render.test.js.map +1 -0
  129. package/dist/__tests__/views/email-settings.render.test.js +2 -2
  130. package/dist/__tests__/views/form-entries.render.test.js +15 -0
  131. package/dist/__tests__/views/form-entries.render.test.js.map +1 -1
  132. package/dist/__tests__/views/form-submissions.render.test.js +18 -0
  133. package/dist/__tests__/views/form-submissions.render.test.js.map +1 -1
  134. package/dist/__tests__/views/forms-list.render.test.js +12 -0
  135. package/dist/__tests__/views/forms-list.render.test.js.map +1 -1
  136. package/dist/__tests__/views/general-settings.render.test.js +26 -10
  137. package/dist/__tests__/views/general-settings.render.test.js.map +1 -1
  138. package/dist/__tests__/views/header-footer-form.test.d.ts +2 -0
  139. package/dist/__tests__/views/header-footer-form.test.d.ts.map +1 -0
  140. package/dist/__tests__/views/header-footer-form.test.js +266 -0
  141. package/dist/__tests__/views/header-footer-form.test.js.map +1 -0
  142. package/dist/__tests__/views/jobs-drawer.render.test.d.ts +2 -0
  143. package/dist/__tests__/views/jobs-drawer.render.test.d.ts.map +1 -0
  144. package/dist/__tests__/views/jobs-drawer.render.test.js +1348 -0
  145. package/dist/__tests__/views/jobs-drawer.render.test.js.map +1 -0
  146. package/dist/__tests__/views/jobs-list.render.test.d.ts +2 -0
  147. package/dist/__tests__/views/jobs-list.render.test.d.ts.map +1 -0
  148. package/dist/__tests__/views/jobs-list.render.test.js +697 -0
  149. package/dist/__tests__/views/jobs-list.render.test.js.map +1 -0
  150. package/dist/__tests__/views/jobs-wizard.render.test.d.ts +2 -0
  151. package/dist/__tests__/views/jobs-wizard.render.test.d.ts.map +1 -0
  152. package/dist/__tests__/views/jobs-wizard.render.test.js +588 -0
  153. package/dist/__tests__/views/jobs-wizard.render.test.js.map +1 -0
  154. package/dist/__tests__/views/kpi-grid.test.d.ts +2 -0
  155. package/dist/__tests__/views/kpi-grid.test.d.ts.map +1 -0
  156. package/dist/__tests__/views/kpi-grid.test.js +26 -0
  157. package/dist/__tests__/views/kpi-grid.test.js.map +1 -0
  158. package/dist/__tests__/views/post-section-editor.test.js +3 -1
  159. package/dist/__tests__/views/post-section-editor.test.js.map +1 -1
  160. package/dist/__tests__/views/script-tags.render.test.js +25 -0
  161. package/dist/__tests__/views/script-tags.render.test.js.map +1 -1
  162. package/dist/__tests__/views/security-settings.render.test.js +9 -8
  163. package/dist/__tests__/views/security-settings.render.test.js.map +1 -1
  164. package/dist/__tests__/views/seo-settings.render.test.js +7 -7
  165. package/dist/__tests__/views/seo-settings.render.test.js.map +1 -1
  166. package/dist/__tests__/views/settings-save-bar.render.test.d.ts +2 -0
  167. package/dist/__tests__/views/settings-save-bar.render.test.d.ts.map +1 -0
  168. package/dist/__tests__/views/settings-save-bar.render.test.js +68 -0
  169. package/dist/__tests__/views/settings-save-bar.render.test.js.map +1 -0
  170. package/dist/__tests__/views/settings-save-footer.render.test.js +23 -15
  171. package/dist/__tests__/views/settings-save-footer.render.test.js.map +1 -1
  172. package/dist/__tests__/views/settings-tabs.render.test.d.ts +2 -0
  173. package/dist/__tests__/views/settings-tabs.render.test.d.ts.map +1 -0
  174. package/dist/__tests__/views/settings-tabs.render.test.js +319 -0
  175. package/dist/__tests__/views/settings-tabs.render.test.js.map +1 -0
  176. package/dist/__tests__/views/updates-tab.render.test.js +4 -3
  177. package/dist/__tests__/views/updates-tab.render.test.js.map +1 -1
  178. package/dist/components/Breadcrumbs.d.ts +8 -1
  179. package/dist/components/Breadcrumbs.d.ts.map +1 -1
  180. package/dist/components/Breadcrumbs.js +6 -0
  181. package/dist/components/Breadcrumbs.js.map +1 -1
  182. package/dist/components/CommandPalette.d.ts.map +1 -1
  183. package/dist/components/CommandPalette.js +40 -4
  184. package/dist/components/CommandPalette.js.map +1 -1
  185. package/dist/components/LocaleSwitcher.d.ts.map +1 -1
  186. package/dist/components/LocaleSwitcher.js +1 -1
  187. package/dist/components/LocaleSwitcher.js.map +1 -1
  188. package/dist/components/NotificationBell.d.ts.map +1 -1
  189. package/dist/components/NotificationBell.js +44 -3
  190. package/dist/components/NotificationBell.js.map +1 -1
  191. package/dist/components/OfflineStatus.js +1 -1
  192. package/dist/components/OfflineStatus.js.map +1 -1
  193. package/dist/components/PresenceIndicator.d.ts.map +1 -1
  194. package/dist/components/PresenceIndicator.js +2 -1
  195. package/dist/components/PresenceIndicator.js.map +1 -1
  196. package/dist/components/ReflowMeter.js +2 -2
  197. package/dist/components/ReflowMeter.js.map +1 -1
  198. package/dist/components/SEOPanel.js +2 -2
  199. package/dist/components/SEOPanel.js.map +1 -1
  200. package/dist/components/ThemeProvider.d.ts +24 -4
  201. package/dist/components/ThemeProvider.d.ts.map +1 -1
  202. package/dist/components/ThemeProvider.js +80 -22
  203. package/dist/components/ThemeProvider.js.map +1 -1
  204. package/dist/components/TipTapEditor.d.ts.map +1 -1
  205. package/dist/components/TipTapEditor.js +3 -4
  206. package/dist/components/TipTapEditor.js.map +1 -1
  207. package/dist/components/forms/EmbedPanel.js +1 -1
  208. package/dist/components/forms/EmbedPanel.js.map +1 -1
  209. package/dist/components/forms/FormEntryDetailPane.js +6 -1
  210. package/dist/components/forms/FormEntryDetailPane.js.map +1 -1
  211. package/dist/components/forms/ShortcodeGlossary.d.ts.map +1 -1
  212. package/dist/components/forms/ShortcodeGlossary.js +6 -1
  213. package/dist/components/forms/ShortcodeGlossary.js.map +1 -1
  214. package/dist/components/forms/primitives.d.ts +15 -5
  215. package/dist/components/forms/primitives.d.ts.map +1 -1
  216. package/dist/components/forms/primitives.js +11 -11
  217. package/dist/components/forms/primitives.js.map +1 -1
  218. package/dist/components/pages/tag-badges.d.ts +2 -1
  219. package/dist/components/pages/tag-badges.d.ts.map +1 -1
  220. package/dist/components/pages/tag-badges.js +4 -3
  221. package/dist/components/pages/tag-badges.js.map +1 -1
  222. package/dist/components/seo/PageAuditPanel.js +2 -2
  223. package/dist/components/seo/PageAuditPanel.js.map +1 -1
  224. package/dist/components/seo/SerpPreview.d.ts +4 -4
  225. package/dist/components/seo/SerpPreview.js +1 -1
  226. package/dist/components/seo/SerpPreview.js.map +1 -1
  227. package/dist/components/seo/primitives.js +2 -2
  228. package/dist/components/seo/primitives.js.map +1 -1
  229. package/dist/components/ui/AuthorAvatar.d.ts +4 -4
  230. package/dist/components/ui/AuthorAvatar.d.ts.map +1 -1
  231. package/dist/components/ui/AuthorAvatar.js +11 -10
  232. package/dist/components/ui/AuthorAvatar.js.map +1 -1
  233. package/dist/components/ui/Badge.d.ts +1 -1
  234. package/dist/components/ui/Badge.js +1 -1
  235. package/dist/components/ui/Badge.js.map +1 -1
  236. package/dist/components/ui/Breadcrumb.d.ts +27 -0
  237. package/dist/components/ui/Breadcrumb.d.ts.map +1 -0
  238. package/dist/components/ui/Breadcrumb.js +41 -0
  239. package/dist/components/ui/Breadcrumb.js.map +1 -0
  240. package/dist/components/ui/Button.d.ts +2 -2
  241. package/dist/components/ui/Button.d.ts.map +1 -1
  242. package/dist/components/ui/Button.js +31 -16
  243. package/dist/components/ui/Button.js.map +1 -1
  244. package/dist/components/ui/Card.d.ts +8 -4
  245. package/dist/components/ui/Card.d.ts.map +1 -1
  246. package/dist/components/ui/Card.js +21 -13
  247. package/dist/components/ui/Card.js.map +1 -1
  248. package/dist/components/ui/CardListControls.d.ts +34 -0
  249. package/dist/components/ui/CardListControls.d.ts.map +1 -0
  250. package/dist/components/ui/CardListControls.js +25 -0
  251. package/dist/components/ui/CardListControls.js.map +1 -0
  252. package/dist/components/ui/CountChip.d.ts +20 -0
  253. package/dist/components/ui/CountChip.d.ts.map +1 -0
  254. package/dist/components/ui/CountChip.js +48 -0
  255. package/dist/components/ui/CountChip.js.map +1 -0
  256. package/dist/components/ui/FilterPill.d.ts +2 -1
  257. package/dist/components/ui/FilterPill.d.ts.map +1 -1
  258. package/dist/components/ui/FilterPill.js +3 -2
  259. package/dist/components/ui/FilterPill.js.map +1 -1
  260. package/dist/components/ui/Input.d.ts +1 -1
  261. package/dist/components/ui/InspectorPane.d.ts +1 -1
  262. package/dist/components/ui/InspectorPane.d.ts.map +1 -1
  263. package/dist/components/ui/InspectorPane.js +15 -4
  264. package/dist/components/ui/InspectorPane.js.map +1 -1
  265. package/dist/components/ui/Modal.d.ts.map +1 -1
  266. package/dist/components/ui/Modal.js +10 -2
  267. package/dist/components/ui/Modal.js.map +1 -1
  268. package/dist/components/ui/PageHeader.d.ts +28 -0
  269. package/dist/components/ui/PageHeader.d.ts.map +1 -0
  270. package/dist/components/ui/PageHeader.js +18 -0
  271. package/dist/components/ui/PageHeader.js.map +1 -0
  272. package/dist/components/ui/RowActions.d.ts +5 -0
  273. package/dist/components/ui/RowActions.d.ts.map +1 -1
  274. package/dist/components/ui/RowActions.js +7 -2
  275. package/dist/components/ui/RowActions.js.map +1 -1
  276. package/dist/components/ui/Segmented.d.ts +21 -0
  277. package/dist/components/ui/Segmented.d.ts.map +1 -0
  278. package/dist/components/ui/Segmented.js +41 -0
  279. package/dist/components/ui/Segmented.js.map +1 -0
  280. package/dist/components/ui/Toaster.d.ts +12 -0
  281. package/dist/components/ui/Toaster.d.ts.map +1 -0
  282. package/dist/components/ui/Toaster.js +103 -0
  283. package/dist/components/ui/Toaster.js.map +1 -0
  284. package/dist/components/ui/Toggle.d.ts +4 -3
  285. package/dist/components/ui/Toggle.d.ts.map +1 -1
  286. package/dist/components/ui/Toggle.js +16 -12
  287. package/dist/components/ui/Toggle.js.map +1 -1
  288. package/dist/components/ui/UnderlineTabs.d.ts +56 -0
  289. package/dist/components/ui/UnderlineTabs.d.ts.map +1 -0
  290. package/dist/components/ui/UnderlineTabs.js +205 -0
  291. package/dist/components/ui/UnderlineTabs.js.map +1 -0
  292. package/dist/components/ui/UnsavedBar.d.ts +25 -0
  293. package/dist/components/ui/UnsavedBar.d.ts.map +1 -0
  294. package/dist/components/ui/UnsavedBar.js +22 -0
  295. package/dist/components/ui/UnsavedBar.js.map +1 -0
  296. package/dist/components/ui/admin-links.d.ts +11 -0
  297. package/dist/components/ui/admin-links.d.ts.map +1 -0
  298. package/dist/components/ui/admin-links.js +10 -0
  299. package/dist/components/ui/admin-links.js.map +1 -0
  300. package/dist/components/ui/card-table.d.ts +43 -0
  301. package/dist/components/ui/card-table.d.ts.map +1 -0
  302. package/dist/components/ui/card-table.js +31 -0
  303. package/dist/components/ui/card-table.js.map +1 -0
  304. package/dist/components/virtual-window.d.ts +7 -0
  305. package/dist/components/virtual-window.d.ts.map +1 -1
  306. package/dist/components/virtual-window.js +5 -2
  307. package/dist/components/virtual-window.js.map +1 -1
  308. package/dist/fields/RelationshipField.js +1 -1
  309. package/dist/fields/RelationshipField.js.map +1 -1
  310. package/dist/files/dm-mono-latin-400-normal.woff +0 -0
  311. package/dist/files/dm-mono-latin-400-normal.woff2 +0 -0
  312. package/dist/files/dm-mono-latin-500-normal.woff +0 -0
  313. package/dist/files/dm-mono-latin-500-normal.woff2 +0 -0
  314. package/dist/files/dm-mono-latin-ext-400-normal.woff +0 -0
  315. package/dist/files/dm-mono-latin-ext-400-normal.woff2 +0 -0
  316. package/dist/files/dm-mono-latin-ext-500-normal.woff +0 -0
  317. package/dist/files/dm-mono-latin-ext-500-normal.woff2 +0 -0
  318. package/dist/files/dm-sans-latin-400-normal.woff +0 -0
  319. package/dist/files/dm-sans-latin-400-normal.woff2 +0 -0
  320. package/dist/files/dm-sans-latin-500-normal.woff +0 -0
  321. package/dist/files/dm-sans-latin-500-normal.woff2 +0 -0
  322. package/dist/files/dm-sans-latin-600-normal.woff +0 -0
  323. package/dist/files/dm-sans-latin-600-normal.woff2 +0 -0
  324. package/dist/files/dm-sans-latin-700-normal.woff +0 -0
  325. package/dist/files/dm-sans-latin-700-normal.woff2 +0 -0
  326. package/dist/files/dm-sans-latin-ext-400-normal.woff +0 -0
  327. package/dist/files/dm-sans-latin-ext-400-normal.woff2 +0 -0
  328. package/dist/files/dm-sans-latin-ext-500-normal.woff +0 -0
  329. package/dist/files/dm-sans-latin-ext-500-normal.woff2 +0 -0
  330. package/dist/files/dm-sans-latin-ext-600-normal.woff +0 -0
  331. package/dist/files/dm-sans-latin-ext-600-normal.woff2 +0 -0
  332. package/dist/files/dm-sans-latin-ext-700-normal.woff +0 -0
  333. package/dist/files/dm-sans-latin-ext-700-normal.woff2 +0 -0
  334. package/dist/hooks/useAppearanceBootstrap.d.ts.map +1 -1
  335. package/dist/hooks/useAppearanceBootstrap.js +9 -3
  336. package/dist/hooks/useAppearanceBootstrap.js.map +1 -1
  337. package/dist/index.d.ts +15 -0
  338. package/dist/index.d.ts.map +1 -1
  339. package/dist/index.js +8 -0
  340. package/dist/index.js.map +1 -1
  341. package/dist/layout/Header.d.ts +14 -5
  342. package/dist/layout/Header.d.ts.map +1 -1
  343. package/dist/layout/Header.js +78 -13
  344. package/dist/layout/Header.js.map +1 -1
  345. package/dist/layout/Layout.d.ts +5 -3
  346. package/dist/layout/Layout.d.ts.map +1 -1
  347. package/dist/layout/Layout.js +45 -54
  348. package/dist/layout/Layout.js.map +1 -1
  349. package/dist/layout/MobileTabBar.d.ts +20 -0
  350. package/dist/layout/MobileTabBar.d.ts.map +1 -0
  351. package/dist/layout/MobileTabBar.js +29 -0
  352. package/dist/layout/MobileTabBar.js.map +1 -0
  353. package/dist/layout/Sidebar.d.ts +8 -26
  354. package/dist/layout/Sidebar.d.ts.map +1 -1
  355. package/dist/layout/Sidebar.js +309 -345
  356. package/dist/layout/Sidebar.js.map +1 -1
  357. package/dist/layout/nav-config.d.ts +101 -0
  358. package/dist/layout/nav-config.d.ts.map +1 -0
  359. package/dist/layout/nav-config.js +297 -0
  360. package/dist/layout/nav-config.js.map +1 -0
  361. package/dist/layout/primitives/AdminShell.d.ts +10 -2
  362. package/dist/layout/primitives/AdminShell.d.ts.map +1 -1
  363. package/dist/layout/primitives/AdminShell.js +114 -6
  364. package/dist/layout/primitives/AdminShell.js.map +1 -1
  365. package/dist/layout/topbar-classes.d.ts +8 -0
  366. package/dist/layout/topbar-classes.d.ts.map +1 -0
  367. package/dist/layout/topbar-classes.js +8 -0
  368. package/dist/layout/topbar-classes.js.map +1 -0
  369. package/dist/layout/use-nav-items.d.ts +10 -0
  370. package/dist/layout/use-nav-items.d.ts.map +1 -0
  371. package/dist/layout/use-nav-items.js +39 -0
  372. package/dist/layout/use-nav-items.js.map +1 -0
  373. package/dist/lib/api.d.ts +8 -0
  374. package/dist/lib/api.d.ts.map +1 -1
  375. package/dist/lib/api.js +8 -1
  376. package/dist/lib/api.js.map +1 -1
  377. package/dist/lib/appearance-api.d.ts +3 -1
  378. package/dist/lib/appearance-api.d.ts.map +1 -1
  379. package/dist/lib/appearance-api.js +1 -0
  380. package/dist/lib/appearance-api.js.map +1 -1
  381. package/dist/lib/batch-wizard.d.ts +84 -0
  382. package/dist/lib/batch-wizard.d.ts.map +1 -0
  383. package/dist/lib/batch-wizard.js +122 -0
  384. package/dist/lib/batch-wizard.js.map +1 -0
  385. package/dist/lib/chrome-service.d.ts +69 -0
  386. package/dist/lib/chrome-service.d.ts.map +1 -0
  387. package/dist/lib/chrome-service.js +108 -0
  388. package/dist/lib/chrome-service.js.map +1 -0
  389. package/dist/lib/job-drawer.d.ts +128 -0
  390. package/dist/lib/job-drawer.d.ts.map +1 -0
  391. package/dist/lib/job-drawer.js +351 -0
  392. package/dist/lib/job-drawer.js.map +1 -0
  393. package/dist/lib/job-view.d.ts +230 -0
  394. package/dist/lib/job-view.d.ts.map +1 -0
  395. package/dist/lib/job-view.js +419 -0
  396. package/dist/lib/job-view.js.map +1 -0
  397. package/dist/lib/jobs-service.d.ts +152 -0
  398. package/dist/lib/jobs-service.d.ts.map +1 -0
  399. package/dist/lib/jobs-service.js +220 -0
  400. package/dist/lib/jobs-service.js.map +1 -0
  401. package/dist/lib/sheet-focus.d.ts +24 -0
  402. package/dist/lib/sheet-focus.d.ts.map +1 -0
  403. package/dist/lib/sheet-focus.js +61 -0
  404. package/dist/lib/sheet-focus.js.map +1 -0
  405. package/dist/lib/tiers.d.ts +30 -0
  406. package/dist/lib/tiers.d.ts.map +1 -0
  407. package/dist/lib/tiers.js +43 -0
  408. package/dist/lib/tiers.js.map +1 -0
  409. package/dist/prenta-admin.css +1 -1
  410. package/dist/router/admin-routes.d.ts.map +1 -1
  411. package/dist/router/admin-routes.js +8 -0
  412. package/dist/router/admin-routes.js.map +1 -1
  413. package/dist/router/index.d.ts +5 -1
  414. package/dist/router/index.d.ts.map +1 -1
  415. package/dist/router/index.js +7 -0
  416. package/dist/router/index.js.map +1 -1
  417. package/dist/views/ApiKeys.js +2 -2
  418. package/dist/views/ApiKeys.js.map +1 -1
  419. package/dist/views/AppearanceChrome.d.ts +24 -0
  420. package/dist/views/AppearanceChrome.d.ts.map +1 -0
  421. package/dist/views/AppearanceChrome.js +461 -0
  422. package/dist/views/AppearanceChrome.js.map +1 -0
  423. package/dist/views/CollectionList.d.ts.map +1 -1
  424. package/dist/views/CollectionList.js +73 -53
  425. package/dist/views/CollectionList.js.map +1 -1
  426. package/dist/views/Dashboard.d.ts.map +1 -1
  427. package/dist/views/Dashboard.js +14 -8
  428. package/dist/views/Dashboard.js.map +1 -1
  429. package/dist/views/DocumentEdit.d.ts +6 -1
  430. package/dist/views/DocumentEdit.d.ts.map +1 -1
  431. package/dist/views/DocumentEdit.js +44 -8
  432. package/dist/views/DocumentEdit.js.map +1 -1
  433. package/dist/views/FormDeliveries.d.ts.map +1 -1
  434. package/dist/views/FormDeliveries.js +7 -1
  435. package/dist/views/FormDeliveries.js.map +1 -1
  436. package/dist/views/FormEntries.d.ts.map +1 -1
  437. package/dist/views/FormEntries.js +11 -2
  438. package/dist/views/FormEntries.js.map +1 -1
  439. package/dist/views/FormSubmissions.d.ts +1 -1
  440. package/dist/views/FormSubmissions.d.ts.map +1 -1
  441. package/dist/views/FormSubmissions.js +15 -4
  442. package/dist/views/FormSubmissions.js.map +1 -1
  443. package/dist/views/Forms.d.ts.map +1 -1
  444. package/dist/views/Forms.js +6 -4
  445. package/dist/views/Forms.js.map +1 -1
  446. package/dist/views/FormsSettings.d.ts +2 -0
  447. package/dist/views/FormsSettings.d.ts.map +1 -0
  448. package/dist/views/FormsSettings.js +37 -0
  449. package/dist/views/FormsSettings.js.map +1 -0
  450. package/dist/views/Jobs/BusyButton.d.ts +15 -0
  451. package/dist/views/Jobs/BusyButton.d.ts.map +1 -0
  452. package/dist/views/Jobs/BusyButton.js +26 -0
  453. package/dist/views/Jobs/BusyButton.js.map +1 -0
  454. package/dist/views/Jobs/CancelJobDialog.d.ts +27 -0
  455. package/dist/views/Jobs/CancelJobDialog.d.ts.map +1 -0
  456. package/dist/views/Jobs/CancelJobDialog.js +76 -0
  457. package/dist/views/Jobs/CancelJobDialog.js.map +1 -0
  458. package/dist/views/Jobs/DrawerActivity.d.ts +16 -0
  459. package/dist/views/Jobs/DrawerActivity.d.ts.map +1 -0
  460. package/dist/views/Jobs/DrawerActivity.js +59 -0
  461. package/dist/views/Jobs/DrawerActivity.js.map +1 -0
  462. package/dist/views/Jobs/DrawerOverview.d.ts +28 -0
  463. package/dist/views/Jobs/DrawerOverview.d.ts.map +1 -0
  464. package/dist/views/Jobs/DrawerOverview.js +32 -0
  465. package/dist/views/Jobs/DrawerOverview.js.map +1 -0
  466. package/dist/views/Jobs/DrawerResults.d.ts +25 -0
  467. package/dist/views/Jobs/DrawerResults.d.ts.map +1 -0
  468. package/dist/views/Jobs/DrawerResults.js +50 -0
  469. package/dist/views/Jobs/DrawerResults.js.map +1 -0
  470. package/dist/views/Jobs/DrawerReview.d.ts +51 -0
  471. package/dist/views/Jobs/DrawerReview.d.ts.map +1 -0
  472. package/dist/views/Jobs/DrawerReview.js +110 -0
  473. package/dist/views/Jobs/DrawerReview.js.map +1 -0
  474. package/dist/views/Jobs/JobDrawer.d.ts +51 -0
  475. package/dist/views/Jobs/JobDrawer.d.ts.map +1 -0
  476. package/dist/views/Jobs/JobDrawer.js +378 -0
  477. package/dist/views/Jobs/JobDrawer.js.map +1 -0
  478. package/dist/views/Jobs/JobsTable.d.ts +21 -0
  479. package/dist/views/Jobs/JobsTable.d.ts.map +1 -0
  480. package/dist/views/Jobs/JobsTable.js +81 -0
  481. package/dist/views/Jobs/JobsTable.js.map +1 -0
  482. package/dist/views/Jobs/NewBatchJob.d.ts +34 -0
  483. package/dist/views/Jobs/NewBatchJob.d.ts.map +1 -0
  484. package/dist/views/Jobs/NewBatchJob.js +282 -0
  485. package/dist/views/Jobs/NewBatchJob.js.map +1 -0
  486. package/dist/views/Jobs/WorkerStrip.d.ts +24 -0
  487. package/dist/views/Jobs/WorkerStrip.d.ts.map +1 -0
  488. package/dist/views/Jobs/WorkerStrip.js +63 -0
  489. package/dist/views/Jobs/WorkerStrip.js.map +1 -0
  490. package/dist/views/Jobs/atoms.d.ts +19 -0
  491. package/dist/views/Jobs/atoms.d.ts.map +1 -0
  492. package/dist/views/Jobs/atoms.js +52 -0
  493. package/dist/views/Jobs/atoms.js.map +1 -0
  494. package/dist/views/Jobs/focus.d.ts +29 -0
  495. package/dist/views/Jobs/focus.d.ts.map +1 -0
  496. package/dist/views/Jobs/focus.js +64 -0
  497. package/dist/views/Jobs/focus.js.map +1 -0
  498. package/dist/views/Jobs/icons.d.ts +22 -0
  499. package/dist/views/Jobs/icons.d.ts.map +1 -0
  500. package/dist/views/Jobs/icons.js +23 -0
  501. package/dist/views/Jobs/icons.js.map +1 -0
  502. package/dist/views/Jobs/useJobDetail.d.ts +21 -0
  503. package/dist/views/Jobs/useJobDetail.d.ts.map +1 -0
  504. package/dist/views/Jobs/useJobDetail.js +39 -0
  505. package/dist/views/Jobs/useJobDetail.js.map +1 -0
  506. package/dist/views/Jobs/useJobsFeed.d.ts +35 -0
  507. package/dist/views/Jobs/useJobsFeed.d.ts.map +1 -0
  508. package/dist/views/Jobs/useJobsFeed.js +231 -0
  509. package/dist/views/Jobs/useJobsFeed.js.map +1 -0
  510. package/dist/views/Jobs/useReviewItems.d.ts +39 -0
  511. package/dist/views/Jobs/useReviewItems.d.ts.map +1 -0
  512. package/dist/views/Jobs/useReviewItems.js +140 -0
  513. package/dist/views/Jobs/useReviewItems.js.map +1 -0
  514. package/dist/views/Jobs.d.ts +19 -1
  515. package/dist/views/Jobs.d.ts.map +1 -1
  516. package/dist/views/Jobs.js +204 -35
  517. package/dist/views/Jobs.js.map +1 -1
  518. package/dist/views/MediaBrowser.d.ts.map +1 -1
  519. package/dist/views/MediaBrowser.js +37 -9
  520. package/dist/views/MediaBrowser.js.map +1 -1
  521. package/dist/views/Pages/PagesListView.d.ts +1 -1
  522. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  523. package/dist/views/Pages/PagesListView.js +34 -5
  524. package/dist/views/Pages/PagesListView.js.map +1 -1
  525. package/dist/views/Posts/NewPostTypeInstructions.d.ts.map +1 -1
  526. package/dist/views/Posts/NewPostTypeInstructions.js +12 -2
  527. package/dist/views/Posts/NewPostTypeInstructions.js.map +1 -1
  528. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  529. package/dist/views/Posts/PostTypesView.js +10 -1
  530. package/dist/views/Posts/PostTypesView.js.map +1 -1
  531. package/dist/views/Posts/PostsListView.d.ts +1 -2
  532. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  533. package/dist/views/Posts/PostsListView.js +31 -3
  534. package/dist/views/Posts/PostsListView.js.map +1 -1
  535. package/dist/views/SEO.d.ts.map +1 -1
  536. package/dist/views/SEO.js +3 -3
  537. package/dist/views/SEO.js.map +1 -1
  538. package/dist/views/ScriptTags.d.ts.map +1 -1
  539. package/dist/views/ScriptTags.js +20 -15
  540. package/dist/views/ScriptTags.js.map +1 -1
  541. package/dist/views/Settings.d.ts.map +1 -1
  542. package/dist/views/Settings.js +115 -51
  543. package/dist/views/Settings.js.map +1 -1
  544. package/dist/views/SpamFolder.d.ts +2 -0
  545. package/dist/views/SpamFolder.d.ts.map +1 -0
  546. package/dist/views/SpamFolder.js +14 -0
  547. package/dist/views/SpamFolder.js.map +1 -0
  548. package/dist/views/Trash.d.ts +6 -1
  549. package/dist/views/Trash.d.ts.map +1 -1
  550. package/dist/views/Trash.js +7 -2
  551. package/dist/views/Trash.js.map +1 -1
  552. package/dist/views/Users.js +2 -2
  553. package/dist/views/Users.js.map +1 -1
  554. package/dist/views/WidgetsPlaceholder.d.ts +2 -0
  555. package/dist/views/WidgetsPlaceholder.d.ts.map +1 -0
  556. package/dist/views/WidgetsPlaceholder.js +15 -0
  557. package/dist/views/WidgetsPlaceholder.js.map +1 -0
  558. package/dist/views/dashboard/kpi-grid.d.ts +18 -0
  559. package/dist/views/dashboard/kpi-grid.d.ts.map +1 -0
  560. package/dist/views/dashboard/kpi-grid.js +36 -0
  561. package/dist/views/dashboard/kpi-grid.js.map +1 -0
  562. package/dist/views/header-footer/AnnouncementTab.d.ts +15 -0
  563. package/dist/views/header-footer/AnnouncementTab.d.ts.map +1 -0
  564. package/dist/views/header-footer/AnnouncementTab.js +43 -0
  565. package/dist/views/header-footer/AnnouncementTab.js.map +1 -0
  566. package/dist/views/header-footer/ChromeField.d.ts +25 -0
  567. package/dist/views/header-footer/ChromeField.d.ts.map +1 -0
  568. package/dist/views/header-footer/ChromeField.js +99 -0
  569. package/dist/views/header-footer/ChromeField.js.map +1 -0
  570. package/dist/views/header-footer/ChromePreview.d.ts +31 -0
  571. package/dist/views/header-footer/ChromePreview.d.ts.map +1 -0
  572. package/dist/views/header-footer/ChromePreview.js +195 -0
  573. package/dist/views/header-footer/ChromePreview.js.map +1 -0
  574. package/dist/views/header-footer/DeveloperTab.d.ts +17 -0
  575. package/dist/views/header-footer/DeveloperTab.d.ts.map +1 -0
  576. package/dist/views/header-footer/DeveloperTab.js +98 -0
  577. package/dist/views/header-footer/DeveloperTab.js.map +1 -0
  578. package/dist/views/header-footer/RegionTab.d.ts +27 -0
  579. package/dist/views/header-footer/RegionTab.d.ts.map +1 -0
  580. package/dist/views/header-footer/RegionTab.js +80 -0
  581. package/dist/views/header-footer/RegionTab.js.map +1 -0
  582. package/dist/views/header-footer/chrome-form.d.ts +137 -0
  583. package/dist/views/header-footer/chrome-form.d.ts.map +1 -0
  584. package/dist/views/header-footer/chrome-form.js +518 -0
  585. package/dist/views/header-footer/chrome-form.js.map +1 -0
  586. package/dist/views/header-footer/code-samples.d.ts +30 -0
  587. package/dist/views/header-footer/code-samples.d.ts.map +1 -0
  588. package/dist/views/header-footer/code-samples.js +127 -0
  589. package/dist/views/header-footer/code-samples.js.map +1 -0
  590. package/dist/views/header-footer/controls.d.ts +57 -0
  591. package/dist/views/header-footer/controls.d.ts.map +1 -0
  592. package/dist/views/header-footer/controls.js +43 -0
  593. package/dist/views/header-footer/controls.js.map +1 -0
  594. package/dist/views/lazy-views.d.ts +4 -0
  595. package/dist/views/lazy-views.d.ts.map +1 -1
  596. package/dist/views/lazy-views.js +4 -0
  597. package/dist/views/lazy-views.js.map +1 -1
  598. package/dist/views/page-editor/PageTab.js +1 -1
  599. package/dist/views/page-editor/PageTab.js.map +1 -1
  600. package/dist/views/page-editor/ReviewBar.js +1 -1
  601. package/dist/views/page-editor/ReviewBar.js.map +1 -1
  602. package/dist/views/page-editor/VersionHistoryPanel.js +1 -1
  603. package/dist/views/page-editor/VersionHistoryPanel.js.map +1 -1
  604. package/dist/views/seo/AuditTab.js +1 -1
  605. package/dist/views/seo/AuditTab.js.map +1 -1
  606. package/dist/views/seo/OverviewTab.d.ts.map +1 -1
  607. package/dist/views/seo/OverviewTab.js +2 -2
  608. package/dist/views/seo/OverviewTab.js.map +1 -1
  609. package/dist/views/seo/ProposalsTab.js +1 -1
  610. package/dist/views/seo/ProposalsTab.js.map +1 -1
  611. package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
  612. package/dist/views/settings/AISettingsTab.js +4 -2
  613. package/dist/views/settings/AISettingsTab.js.map +1 -1
  614. package/dist/views/settings/AccessProtectionCard.js +1 -1
  615. package/dist/views/settings/AccessProtectionCard.js.map +1 -1
  616. package/dist/views/settings/AdminThemeCard.d.ts.map +1 -1
  617. package/dist/views/settings/AdminThemeCard.js +63 -15
  618. package/dist/views/settings/AdminThemeCard.js.map +1 -1
  619. package/dist/views/settings/AppearanceTab.d.ts.map +1 -1
  620. package/dist/views/settings/AppearanceTab.js +4 -2
  621. package/dist/views/settings/AppearanceTab.js.map +1 -1
  622. package/dist/views/settings/BrandPreviewCard.js +1 -1
  623. package/dist/views/settings/BrandPreviewCard.js.map +1 -1
  624. package/dist/views/settings/BrandVoiceCard.js +1 -1
  625. package/dist/views/settings/BrandVoiceCard.js.map +1 -1
  626. package/dist/views/settings/EmailSettingsTab.d.ts.map +1 -1
  627. package/dist/views/settings/EmailSettingsTab.js +5 -3
  628. package/dist/views/settings/EmailSettingsTab.js.map +1 -1
  629. package/dist/views/settings/GeneralSettingsTab.d.ts.map +1 -1
  630. package/dist/views/settings/GeneralSettingsTab.js +4 -2
  631. package/dist/views/settings/GeneralSettingsTab.js.map +1 -1
  632. package/dist/views/settings/ProviderConnectionCard.js +1 -1
  633. package/dist/views/settings/ProviderConnectionCard.js.map +1 -1
  634. package/dist/views/settings/SearchDataCard.js +1 -1
  635. package/dist/views/settings/SearchDataCard.js.map +1 -1
  636. package/dist/views/settings/SecurityStatusCard.js +2 -2
  637. package/dist/views/settings/SecurityStatusCard.js.map +1 -1
  638. package/dist/views/settings/SecurityTab.d.ts.map +1 -1
  639. package/dist/views/settings/SecurityTab.js +4 -2
  640. package/dist/views/settings/SecurityTab.js.map +1 -1
  641. package/dist/views/settings/SeoAutopilotCard.js +2 -2
  642. package/dist/views/settings/SeoAutopilotCard.js.map +1 -1
  643. package/dist/views/settings/SeoSettingsTab.d.ts.map +1 -1
  644. package/dist/views/settings/SeoSettingsTab.js +5 -3
  645. package/dist/views/settings/SeoSettingsTab.js.map +1 -1
  646. package/dist/views/settings/SiteIndexStatusCard.js +1 -1
  647. package/dist/views/settings/SiteIndexStatusCard.js.map +1 -1
  648. package/dist/views/settings/SiteThemeCard.js +1 -1
  649. package/dist/views/settings/UpdatesTab.d.ts.map +1 -1
  650. package/dist/views/settings/UpdatesTab.js +6 -5
  651. package/dist/views/settings/UpdatesTab.js.map +1 -1
  652. package/dist/views/settings/components.d.ts +7 -11
  653. package/dist/views/settings/components.d.ts.map +1 -1
  654. package/dist/views/settings/components.js +18 -12
  655. package/dist/views/settings/components.js.map +1 -1
  656. package/dist/views/settings/useAppearanceSettings.d.ts +7 -1
  657. package/dist/views/settings/useAppearanceSettings.d.ts.map +1 -1
  658. package/dist/views/settings/useAppearanceSettings.js +89 -22
  659. package/dist/views/settings/useAppearanceSettings.js.map +1 -1
  660. package/dist/views/users/UserDetailDrawer.js +1 -1
  661. package/dist/views/users/UserDetailDrawer.js.map +1 -1
  662. package/package.json +10 -8
  663. package/src/AdminRoot.tsx +103 -31
  664. package/src/LoginRoot.tsx +2 -1
  665. package/src/__tests__/components/author-avatar.test.tsx +3 -20
  666. package/src/__tests__/components/notification-bell.test.tsx +146 -14
  667. package/src/__tests__/components/responsive-tiers.render.test.tsx +461 -0
  668. package/src/__tests__/components/serp-preview.render.test.tsx +6 -3
  669. package/src/__tests__/components/shell-primitives.render.test.tsx +951 -0
  670. package/src/__tests__/components/theme-provider-accent.test.tsx +83 -8
  671. package/src/__tests__/components/toggle.test.tsx +11 -3
  672. package/src/__tests__/components/ui-primitives.test.tsx +5 -8
  673. package/src/__tests__/layout/build-nav-items.test.ts +1 -1
  674. package/src/__tests__/layout/shell-nav.render.test.tsx +983 -0
  675. package/src/__tests__/layout/sidebar-forms-submenu.render.test.tsx +8 -4
  676. package/src/__tests__/layout/sidebar-groups.render.test.tsx +116 -0
  677. package/src/__tests__/layout/sidebar-menus.render.test.tsx +116 -0
  678. package/src/__tests__/layout/sidebar-plugin-nav.test.ts +1 -1
  679. package/src/__tests__/layout/sidebar-posts.test.ts +48 -40
  680. package/src/__tests__/layout/sidebar-submenu.render.test.tsx +35 -10
  681. package/src/__tests__/layout/topbar.render.test.tsx +464 -0
  682. package/src/__tests__/lib/api.test.ts +2 -0
  683. package/src/__tests__/lib/batch-wizard.test.ts +199 -0
  684. package/src/__tests__/lib/job-drawer.test.ts +495 -0
  685. package/src/__tests__/lib/job-view.test.ts +558 -0
  686. package/src/__tests__/lib/jobs-service.test.ts +167 -0
  687. package/src/__tests__/router/admin-route-order.test.ts +39 -0
  688. package/src/__tests__/styles/ai-gradient-contrast.test.ts +135 -0
  689. package/src/__tests__/styles/breakpoint-order.test.ts +68 -0
  690. package/src/__tests__/styles/responsive-layer.test.ts +367 -12
  691. package/src/__tests__/styles/tailwind-preset.test.ts +154 -0
  692. package/src/__tests__/styles/theme-token-scope.test.ts +10 -3
  693. package/src/__tests__/styles/tiers.test.ts +136 -0
  694. package/src/__tests__/styles/tokens-drift.test.ts +67 -6
  695. package/src/__tests__/views/admin-lazy-route.render.test.tsx +41 -1
  696. package/src/__tests__/views/ai-settings.render.test.tsx +4 -4
  697. package/src/__tests__/views/appearance-chrome.render.test.tsx +818 -0
  698. package/src/__tests__/views/appearance-menus-route.render.test.tsx +58 -0
  699. package/src/__tests__/views/appearance-settings.render.test.tsx +10 -8
  700. package/src/__tests__/views/appearance-theme-provider.render.test.tsx +347 -0
  701. package/src/__tests__/views/dashboard.test.tsx +48 -0
  702. package/src/__tests__/views/document-edit-navigation.render.test.tsx +130 -0
  703. package/src/__tests__/views/document-edit-routes.render.test.tsx +130 -0
  704. package/src/__tests__/views/email-settings.render.test.tsx +2 -2
  705. package/src/__tests__/views/form-entries.render.test.tsx +22 -0
  706. package/src/__tests__/views/form-submissions.render.test.tsx +22 -0
  707. package/src/__tests__/views/forms-list.render.test.tsx +13 -0
  708. package/src/__tests__/views/general-settings.render.test.tsx +38 -11
  709. package/src/__tests__/views/header-footer-form.test.ts +333 -0
  710. package/src/__tests__/views/jobs-drawer.render.test.tsx +1553 -0
  711. package/src/__tests__/views/jobs-list.render.test.tsx +853 -0
  712. package/src/__tests__/views/jobs-wizard.render.test.tsx +707 -0
  713. package/src/__tests__/views/kpi-grid.test.ts +29 -0
  714. package/src/__tests__/views/post-section-editor.test.tsx +5 -1
  715. package/src/__tests__/views/script-tags.render.test.tsx +29 -0
  716. package/src/__tests__/views/security-settings.render.test.tsx +9 -10
  717. package/src/__tests__/views/seo-settings.render.test.tsx +7 -9
  718. package/src/__tests__/views/settings-save-bar.render.test.tsx +91 -0
  719. package/src/__tests__/views/settings-save-footer.render.test.tsx +25 -15
  720. package/src/__tests__/views/settings-tabs.render.test.tsx +371 -0
  721. package/src/__tests__/views/updates-tab.render.test.tsx +4 -3
  722. package/src/components/Breadcrumbs.tsx +7 -1
  723. package/src/components/CommandPalette.tsx +51 -3
  724. package/src/components/LocaleSwitcher.tsx +5 -6
  725. package/src/components/NotificationBell.tsx +74 -18
  726. package/src/components/OfflineStatus.tsx +1 -1
  727. package/src/components/PresenceIndicator.tsx +2 -1
  728. package/src/components/ReflowMeter.tsx +3 -3
  729. package/src/components/SEOPanel.tsx +2 -2
  730. package/src/components/ThemeProvider.tsx +122 -42
  731. package/src/components/TipTapEditor.tsx +3 -4
  732. package/src/components/forms/EmbedPanel.tsx +1 -1
  733. package/src/components/forms/FormEntryDetailPane.tsx +7 -1
  734. package/src/components/forms/ShortcodeGlossary.tsx +7 -1
  735. package/src/components/forms/primitives.tsx +37 -21
  736. package/src/components/pages/tag-badges.tsx +4 -3
  737. package/src/components/seo/PageAuditPanel.tsx +2 -2
  738. package/src/components/seo/SerpPreview.tsx +5 -5
  739. package/src/components/seo/primitives.tsx +2 -2
  740. package/src/components/ui/AuthorAvatar.tsx +11 -10
  741. package/src/components/ui/Badge.tsx +1 -1
  742. package/src/components/ui/Breadcrumb.tsx +109 -0
  743. package/src/components/ui/Button.tsx +40 -15
  744. package/src/components/ui/Card.tsx +35 -32
  745. package/src/components/ui/CardListControls.tsx +90 -0
  746. package/src/components/ui/CountChip.tsx +90 -0
  747. package/src/components/ui/FilterPill.tsx +5 -3
  748. package/src/components/ui/InspectorPane.tsx +21 -7
  749. package/src/components/ui/Modal.tsx +20 -6
  750. package/src/components/ui/PageHeader.tsx +63 -0
  751. package/src/components/ui/RowActions.tsx +7 -2
  752. package/src/components/ui/Segmented.tsx +97 -0
  753. package/src/components/ui/Toaster.tsx +139 -0
  754. package/src/components/ui/Toggle.tsx +18 -14
  755. package/src/components/ui/UnderlineTabs.tsx +373 -0
  756. package/src/components/ui/UnsavedBar.tsx +119 -0
  757. package/src/components/ui/admin-links.tsx +20 -0
  758. package/src/components/ui/card-table.ts +34 -0
  759. package/src/components/virtual-window.tsx +13 -2
  760. package/src/fields/RelationshipField.tsx +1 -1
  761. package/src/hooks/useAppearanceBootstrap.ts +9 -3
  762. package/src/index.ts +19 -0
  763. package/src/layout/Header.tsx +210 -135
  764. package/src/layout/Layout.tsx +61 -108
  765. package/src/layout/MobileTabBar.tsx +92 -0
  766. package/src/layout/Sidebar.tsx +555 -593
  767. package/src/layout/nav-config.tsx +425 -0
  768. package/src/layout/primitives/AdminShell.tsx +154 -6
  769. package/src/layout/topbar-classes.ts +8 -0
  770. package/src/layout/use-nav-items.ts +40 -0
  771. package/src/lib/api.ts +18 -1
  772. package/src/lib/appearance-api.ts +4 -0
  773. package/src/lib/batch-wizard.ts +188 -0
  774. package/src/lib/chrome-service.ts +200 -0
  775. package/src/lib/job-drawer.ts +424 -0
  776. package/src/lib/job-view.ts +550 -0
  777. package/src/lib/jobs-service.ts +345 -0
  778. package/src/lib/sheet-focus.ts +71 -0
  779. package/src/lib/tiers.ts +43 -0
  780. package/src/router/admin-routes.ts +8 -0
  781. package/src/router/index.ts +9 -1
  782. package/src/styles/prenta-tokens.css +280 -82
  783. package/src/styles/responsive.css +460 -22
  784. package/src/styles/theme.css +192 -28
  785. package/src/views/ApiKeys.tsx +2 -2
  786. package/src/views/AppearanceChrome.tsx +732 -0
  787. package/src/views/CollectionList.tsx +264 -205
  788. package/src/views/Dashboard.tsx +26 -13
  789. package/src/views/DocumentEdit.tsx +111 -56
  790. package/src/views/FormDeliveries.tsx +30 -17
  791. package/src/views/FormEntries.tsx +28 -20
  792. package/src/views/FormSubmissions.tsx +32 -34
  793. package/src/views/Forms.tsx +55 -34
  794. package/src/views/FormsSettings.tsx +94 -0
  795. package/src/views/Jobs/BusyButton.tsx +56 -0
  796. package/src/views/Jobs/CancelJobDialog.tsx +145 -0
  797. package/src/views/Jobs/DrawerActivity.tsx +142 -0
  798. package/src/views/Jobs/DrawerOverview.tsx +139 -0
  799. package/src/views/Jobs/DrawerResults.tsx +155 -0
  800. package/src/views/Jobs/DrawerReview.tsx +464 -0
  801. package/src/views/Jobs/JobDrawer.tsx +636 -0
  802. package/src/views/Jobs/JobsTable.tsx +267 -0
  803. package/src/views/Jobs/NewBatchJob.tsx +857 -0
  804. package/src/views/Jobs/WorkerStrip.tsx +149 -0
  805. package/src/views/Jobs/atoms.tsx +93 -0
  806. package/src/views/Jobs/focus.ts +67 -0
  807. package/src/views/Jobs/icons.tsx +111 -0
  808. package/src/views/Jobs/useJobDetail.ts +64 -0
  809. package/src/views/Jobs/useJobsFeed.ts +249 -0
  810. package/src/views/Jobs/useReviewItems.ts +187 -0
  811. package/src/views/Jobs.tsx +396 -105
  812. package/src/views/MediaBrowser.tsx +71 -21
  813. package/src/views/Pages/PagesListView.tsx +115 -39
  814. package/src/views/Posts/NewPostTypeInstructions.tsx +15 -10
  815. package/src/views/Posts/PostTypesView.tsx +28 -6
  816. package/src/views/Posts/PostsListView.tsx +130 -40
  817. package/src/views/SEO.tsx +23 -8
  818. package/src/views/ScriptTags.tsx +233 -153
  819. package/src/views/Settings.tsx +215 -256
  820. package/src/views/SpamFolder.tsx +32 -0
  821. package/src/views/Trash.tsx +12 -1
  822. package/src/views/Users.tsx +2 -2
  823. package/src/views/WidgetsPlaceholder.tsx +33 -0
  824. package/src/views/dashboard/kpi-grid.ts +38 -0
  825. package/src/views/header-footer/AnnouncementTab.tsx +231 -0
  826. package/src/views/header-footer/ChromeField.tsx +358 -0
  827. package/src/views/header-footer/ChromePreview.tsx +497 -0
  828. package/src/views/header-footer/DeveloperTab.tsx +331 -0
  829. package/src/views/header-footer/RegionTab.tsx +398 -0
  830. package/src/views/header-footer/chrome-form.ts +603 -0
  831. package/src/views/header-footer/code-samples.ts +146 -0
  832. package/src/views/header-footer/controls.tsx +166 -0
  833. package/src/views/lazy-views.tsx +12 -0
  834. package/src/views/page-editor/PageTab.tsx +2 -2
  835. package/src/views/page-editor/ReviewBar.tsx +1 -1
  836. package/src/views/page-editor/VersionHistoryPanel.tsx +1 -1
  837. package/src/views/seo/AuditTab.tsx +1 -1
  838. package/src/views/seo/OverviewTab.tsx +6 -5
  839. package/src/views/seo/ProposalsTab.tsx +1 -1
  840. package/src/views/settings/AISettingsTab.tsx +10 -6
  841. package/src/views/settings/AccessProtectionCard.tsx +1 -1
  842. package/src/views/settings/AdminThemeCard.tsx +228 -35
  843. package/src/views/settings/AppearanceTab.tsx +10 -6
  844. package/src/views/settings/BrandPreviewCard.tsx +1 -1
  845. package/src/views/settings/BrandVoiceCard.tsx +1 -1
  846. package/src/views/settings/EmailSettingsTab.tsx +11 -7
  847. package/src/views/settings/GeneralSettingsTab.tsx +10 -6
  848. package/src/views/settings/ProviderConnectionCard.tsx +1 -1
  849. package/src/views/settings/SearchDataCard.tsx +1 -1
  850. package/src/views/settings/SecurityStatusCard.tsx +2 -2
  851. package/src/views/settings/SecurityTab.tsx +10 -6
  852. package/src/views/settings/SeoAutopilotCard.tsx +2 -2
  853. package/src/views/settings/SeoSettingsTab.tsx +13 -9
  854. package/src/views/settings/SiteIndexStatusCard.tsx +1 -1
  855. package/src/views/settings/SiteThemeCard.tsx +1 -1
  856. package/src/views/settings/UpdatesTab.tsx +107 -101
  857. package/src/views/settings/components.tsx +26 -62
  858. package/src/views/settings/useAppearanceSettings.ts +116 -25
  859. package/src/views/users/UserDetailDrawer.tsx +1 -1
  860. package/dist/components/ui/StatPill.d.ts +0 -18
  861. package/dist/components/ui/StatPill.d.ts.map +0 -1
  862. package/dist/components/ui/StatPill.js +0 -5
  863. package/dist/components/ui/StatPill.js.map +0 -1
  864. package/src/components/ui/StatPill.tsx +0 -37
@@ -0,0 +1,373 @@
1
+ 'use client'
2
+
3
+ import {
4
+ useCallback,
5
+ useEffect,
6
+ useId,
7
+ useLayoutEffect,
8
+ useRef,
9
+ useState,
10
+ type HTMLAttributes,
11
+ type KeyboardEvent,
12
+ type ReactNode,
13
+ } from 'react'
14
+ import { ChevronLeft, ChevronRight } from 'lucide-react'
15
+
16
+ export interface UnderlineTab {
17
+ id: string
18
+ label: string
19
+ /** Leading icon, 15px (Settings and Form Settings tabs). */
20
+ icon?: ReactNode
21
+ count?: number
22
+ /** Trailing badge, e.g. a "Live" pill. Rendered after the count. */
23
+ badge?: ReactNode
24
+ }
25
+
26
+ export interface UnderlineTabsProps {
27
+ tabs: UnderlineTab[]
28
+ value: string
29
+ onChange: (id: string) => void
30
+ /** Accessible name for the tab list. */
31
+ label: string
32
+ /**
33
+ * Prefix for the tab and panel ids. Pass the same value to `UnderlineTabPanel`
34
+ * so each tab's `aria-controls` points at its panel. Defaults to a generated id.
35
+ */
36
+ idBase?: string
37
+ /**
38
+ * `page` is a page-level strip (Settings.html `.pg-tabs`): 13px / 500 tabs
39
+ * in `--muted`, 10px 16px, no gap. `drawer` is the Jobs drawer's `.jd-tabs`:
40
+ * 9px 11px with a 6px gap and no divider of its own, because the drawer
41
+ * header draws the line under it (its edges still fade when tabs are
42
+ * hidden, as every strip's do). The default is SHELL.md §6: 13px / 600
43
+ * in `--sub`, 10px 12px.
44
+ */
45
+ variant?: 'default' | 'page' | 'drawer'
46
+ /** Classes for the scrolling strip (e.g. the page gutter as padding). */
47
+ className?: string
48
+ }
49
+
50
+ function underlineTabId(idBase: string, tabId: string) {
51
+ return `${idBase}-tab-${tabId}`
52
+ }
53
+
54
+ function underlineTabPanelId(idBase: string, tabId: string) {
55
+ return `${idBase}-panel-${tabId}`
56
+ }
57
+
58
+ /** Width of each edge fade (SHELL.md §6), and the room a revealed tab keeps from it. */
59
+ const FADE = 48
60
+
61
+ // Each edge with hidden tabs fades out over 48px. Written out in full so
62
+ // Tailwind sees the classes.
63
+ const MASKS = {
64
+ end: '[mask-image:linear-gradient(90deg,black_calc(100%-48px),transparent)]',
65
+ start: '[mask-image:linear-gradient(90deg,transparent,black_48px)]',
66
+ both: '[mask-image:linear-gradient(90deg,transparent,black_48px,black_calc(100%-48px),transparent)]',
67
+ } as const
68
+
69
+ const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect
70
+
71
+ interface Overflow {
72
+ /** Tabs are hidden to the left. */
73
+ start: boolean
74
+ /** Tabs are hidden to the right. */
75
+ end: boolean
76
+ }
77
+
78
+ /**
79
+ * Underline tabs (SHELL.md §6). The active mark is `box-shadow: inset 0 -2px 0`,
80
+ * never a border with a negative margin, so the strip can scroll without a
81
+ * vertical scrollbar. Arrow keys, Home and End move between tabs.
82
+ *
83
+ * When the tabs don't fit, the strip scrolls with its scrollbar hidden, and
84
+ * each edge that hides tabs fades out over 48px. The kit fades the right edge
85
+ * at ≤1280px unless the last tab is active; here the fade follows what is
86
+ * actually hidden, so it also shows on wide screens with more tabs and goes
87
+ * once the strip is scrolled to its end. Over each fade sits a chevron button
88
+ * that scrolls the strip for mouse users without a horizontal wheel; keyboard
89
+ * and screen-reader users reach every tab through the tab list itself, so the
90
+ * buttons are `aria-hidden` and out of the Tab order.
91
+ */
92
+ export function UnderlineTabs({
93
+ tabs,
94
+ value,
95
+ onChange,
96
+ label,
97
+ idBase,
98
+ variant = 'default',
99
+ className = '',
100
+ }: UnderlineTabsProps) {
101
+ const generatedId = useId()
102
+ const base = idBase ?? generatedId
103
+ const listRef = useRef<HTMLDivElement | null>(null)
104
+ const refs = useRef<Array<HTMLButtonElement | null>>([])
105
+ const [overflow, setOverflow] = useState<Overflow>({ start: false, end: false })
106
+ const matchIndex = tabs.findIndex((tab) => tab.id === value)
107
+ // Roving tab stop only: with no matching value no tab is selected, but the
108
+ // first one still takes focus.
109
+ const selectedIndex = Math.max(0, matchIndex)
110
+
111
+ const measure = useCallback(() => {
112
+ const list = listRef.current
113
+ if (!list) return
114
+ // 1px of slack for fractional widths at a zoom level.
115
+ const start = list.scrollLeft > 1
116
+ const end = list.scrollLeft + list.clientWidth < list.scrollWidth - 1
117
+ setOverflow((current) =>
118
+ current.start === start && current.end === end ? current : { start, end },
119
+ )
120
+ }, [])
121
+
122
+ /** Scroll the strip sideways (never the page) until `index` clears the fades. */
123
+ const reveal = useCallback(
124
+ (index: number) => {
125
+ const list = listRef.current
126
+ const tab = refs.current[index]
127
+ if (!list || !tab) return
128
+ const left = tab.offsetLeft - FADE
129
+ const right = tab.offsetLeft + tab.offsetWidth + FADE - list.clientWidth
130
+ if (list.scrollLeft > left) list.scrollLeft = Math.max(0, left)
131
+ else if (list.scrollLeft < right) list.scrollLeft = right
132
+ measure()
133
+ },
134
+ [measure],
135
+ )
136
+
137
+ /** `reveal` without the glide: on first paint and after the strip resizes. */
138
+ const revealNow = useCallback(
139
+ (index: number) => {
140
+ const list = listRef.current
141
+ if (!list) return
142
+ list.style.scrollBehavior = 'auto'
143
+ reveal(index)
144
+ list.style.scrollBehavior = ''
145
+ },
146
+ [reveal],
147
+ )
148
+
149
+ // The selected tab is in view on first paint (a deep link to the last
150
+ // Settings tab) and after every change, however it was chosen. The first
151
+ // reveal jumps; later ones follow the strip's scroll-behavior.
152
+ const revealed = useRef(false)
153
+ const selectedRef = useRef(matchIndex)
154
+ selectedRef.current = matchIndex
155
+ useIsomorphicLayoutEffect(() => {
156
+ if (matchIndex < 0) {
157
+ measure()
158
+ return
159
+ }
160
+ if (revealed.current) reveal(matchIndex)
161
+ else revealNow(matchIndex)
162
+ revealed.current = true
163
+ }, [matchIndex, reveal, revealNow, measure])
164
+
165
+ // Labels, counts and the window all change what fits. When the strip itself
166
+ // changes width (a rotated tablet, a resized window, a late web font), the
167
+ // selected tab is brought back clear of the fades. Keyed on the tab ids, not
168
+ // the array, so callers that build `tabs` inline don't re-observe on every
169
+ // render.
170
+ const tabKey = tabs.map((tab) => tab.id).join('\n')
171
+ useEffect(() => {
172
+ const list = listRef.current
173
+ if (!list) return
174
+ measure()
175
+ if (typeof ResizeObserver === 'undefined') return
176
+ let width = list.clientWidth
177
+ const observer = new ResizeObserver(() => {
178
+ measure()
179
+ if (list.clientWidth === width) return
180
+ width = list.clientWidth
181
+ if (selectedRef.current >= 0) revealNow(selectedRef.current)
182
+ })
183
+ observer.observe(list)
184
+ for (const tab of refs.current) if (tab) observer.observe(tab)
185
+ return () => observer.disconnect()
186
+ }, [tabKey, measure, revealNow])
187
+
188
+ // A scroll button stays under the pointer after its edge runs out (inert
189
+ // and invisible) until the pointer leaves, so the second click of a quick
190
+ // double click can't land on the tab beneath it.
191
+ const [hovered, setHovered] = useState<'start' | 'end' | null>(null)
192
+
193
+ function scrollByPage(direction: -1 | 1) {
194
+ const list = listRef.current
195
+ if (!list) return
196
+ // `scrollBy` without a behaviour follows the strip's CSS scroll-behavior,
197
+ // so reduced motion (system or the Appearance setting) skips the glide.
198
+ list.scrollBy({ left: direction * Math.max(list.clientWidth - 2 * FADE, FADE) })
199
+ }
200
+
201
+ /** Selecting the open tab again is not a change (no extra history entry). */
202
+ function select(id: string) {
203
+ if (id !== value) onChange(id)
204
+ }
205
+
206
+ function onKeyDown(event: KeyboardEvent<HTMLDivElement>) {
207
+ // Alt+Left and Alt+Right are the browser's Back and Forward.
208
+ if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return
209
+ const last = tabs.length - 1
210
+ let next: number
211
+ if (event.key === 'ArrowRight') next = selectedIndex === last ? 0 : selectedIndex + 1
212
+ else if (event.key === 'ArrowLeft') next = selectedIndex === 0 ? last : selectedIndex - 1
213
+ else if (event.key === 'Home') next = 0
214
+ else if (event.key === 'End') next = last
215
+ else return
216
+ event.preventDefault()
217
+ const tab = tabs[next]
218
+ if (!tab) return
219
+ select(tab.id)
220
+ refs.current[next]?.focus({ preventScroll: true })
221
+ reveal(next)
222
+ }
223
+
224
+ const mask =
225
+ overflow.start && overflow.end
226
+ ? MASKS.both
227
+ : overflow.start
228
+ ? MASKS.start
229
+ : overflow.end
230
+ ? MASKS.end
231
+ : ''
232
+ const page = variant === 'page'
233
+ const drawer = variant === 'drawer'
234
+
235
+ return (
236
+ <div className="relative min-w-0">
237
+ <div
238
+ ref={listRef}
239
+ role="tablist"
240
+ aria-label={label}
241
+ onKeyDown={onKeyDown}
242
+ onScroll={measure}
243
+ data-overflow-start={overflow.start || undefined}
244
+ data-overflow-end={overflow.end || undefined}
245
+ // Forced colors drop box-shadows: there the divider is a border.
246
+ className={`relative flex scroll-px-12 overflow-x-auto overflow-y-hidden [scrollbar-width:none] motion-safe:scroll-smooth [&::-webkit-scrollbar]:hidden ${
247
+ drawer ? '' : 'shadow-[inset_0_-1px_0_var(--bdr)] forced-colors:border-b'
248
+ } ${page ? '' : 'gap-0.5'} ${mask} ${className}`}
249
+ >
250
+ {tabs.map((tab, index) => {
251
+ const selected = tab.id === value
252
+ return (
253
+ <button
254
+ key={tab.id}
255
+ ref={(el) => {
256
+ refs.current[index] = el
257
+ }}
258
+ id={underlineTabId(base, tab.id)}
259
+ type="button"
260
+ role="tab"
261
+ aria-selected={selected}
262
+ // Only when the caller renders panels (it passed `idBase`); a
263
+ // dangling aria-controls is an a11y error.
264
+ aria-controls={idBase ? underlineTabPanelId(idBase, tab.id) : undefined}
265
+ tabIndex={index === selectedIndex ? 0 : -1}
266
+ onClick={() => select(tab.id)}
267
+ // 40px on phones and 44px on touch screens (cms-layouts.css).
268
+ // Forced colors drop the inset mark, so the selected tab gets an
269
+ // outline there, as the current nav row does.
270
+ className={`text-body prenta-touch-target mobile:min-h-10 flex shrink-0 cursor-pointer items-center border-0 bg-transparent leading-[normal] whitespace-nowrap ${
271
+ page
272
+ ? 'gap-[7px] px-4 py-2.5 font-medium'
273
+ : drawer
274
+ ? 'gap-1.5 px-[11px] py-[9px] font-semibold'
275
+ : 'gap-[7px] px-3 py-2.5 font-semibold'
276
+ } ${
277
+ selected
278
+ ? 'text-acc shadow-[inset_0_-2px_0_var(--acc)] forced-colors:outline-2 forced-colors:-outline-offset-2 forced-colors:outline-solid'
279
+ : `${page ? 'text-faint' : 'text-sub'} hover:text-txt`
280
+ }`}
281
+ >
282
+ {tab.icon ? (
283
+ <span aria-hidden="true" className="flex [&>svg]:h-[15px] [&>svg]:w-[15px]">
284
+ {tab.icon}
285
+ </span>
286
+ ) : null}
287
+ {tab.label}
288
+ {typeof tab.count === 'number' ? (
289
+ <span
290
+ className={`rounded-pill text-count px-1.5 py-px font-semibold tabular-nums ${
291
+ selected ? 'bg-acc-l text-acc' : 'bg-bg text-sub'
292
+ }`}
293
+ >
294
+ {tab.count}
295
+ </span>
296
+ ) : null}
297
+ {tab.badge}
298
+ </button>
299
+ )
300
+ })}
301
+ </div>
302
+ {(['start', 'end'] as const).map((side) =>
303
+ overflow[side] || hovered === side ? (
304
+ <ScrollButton
305
+ key={side}
306
+ side={side}
307
+ active={overflow[side]}
308
+ onClick={() => scrollByPage(side === 'start' ? -1 : 1)}
309
+ onHover={(over) => setHovered(over ? side : null)}
310
+ />
311
+ ) : null,
312
+ )}
313
+ </div>
314
+ )
315
+ }
316
+
317
+ /**
318
+ * A chevron over one edge's fade that scrolls the strip for mouse users.
319
+ * Inactive, it is invisible and swallows clicks until the pointer leaves.
320
+ */
321
+ function ScrollButton({
322
+ side,
323
+ active,
324
+ onClick,
325
+ onHover,
326
+ }: {
327
+ side: 'start' | 'end'
328
+ active: boolean
329
+ onClick: () => void
330
+ onHover: (over: boolean) => void
331
+ }) {
332
+ const Icon = side === 'start' ? ChevronLeft : ChevronRight
333
+ return (
334
+ <button
335
+ type="button"
336
+ aria-hidden="true"
337
+ tabIndex={-1}
338
+ data-tabs-scroll={side}
339
+ data-inactive={active ? undefined : ''}
340
+ // Keep focus where it is: a hidden control must not take it.
341
+ onMouseDown={(event) => event.preventDefault()}
342
+ onClick={active ? onClick : undefined}
343
+ onPointerEnter={() => onHover(true)}
344
+ onPointerLeave={() => onHover(false)}
345
+ className={`text-sub hover:text-acc absolute inset-y-0 flex w-6 items-center justify-center border-0 bg-transparent p-0 ${
346
+ active ? 'cursor-pointer' : 'cursor-default opacity-0'
347
+ } ${side === 'start' ? 'left-0' : 'right-0'}`}
348
+ >
349
+ <Icon size={16} strokeWidth={1.8} />
350
+ </button>
351
+ )
352
+ }
353
+
354
+ export interface UnderlineTabPanelProps extends HTMLAttributes<HTMLDivElement> {
355
+ /** Same `idBase` as the `UnderlineTabs` it belongs to. */
356
+ idBase: string
357
+ tabId: string
358
+ }
359
+
360
+ /** The panel for one underline tab: `role="tabpanel"`, labelled by its tab. */
361
+ export function UnderlineTabPanel({ idBase, tabId, children, ...rest }: UnderlineTabPanelProps) {
362
+ return (
363
+ <div
364
+ role="tabpanel"
365
+ id={underlineTabPanelId(idBase, tabId)}
366
+ aria-labelledby={underlineTabId(idBase, tabId)}
367
+ tabIndex={0}
368
+ {...rest}
369
+ >
370
+ {children}
371
+ </div>
372
+ )
373
+ }
@@ -0,0 +1,119 @@
1
+ 'use client'
2
+
3
+ export interface UnsavedBarProps {
4
+ dirty: boolean
5
+ onDiscard: () => void
6
+ onSave: () => void
7
+ /** Message on the left. Defaults to "Unsaved changes". */
8
+ label?: string
9
+ saving?: boolean
10
+ /** Blocks Save while the form is invalid or the user can't edit. */
11
+ saveDisabled?: boolean
12
+ saveLabel?: string
13
+ discardLabel?: string
14
+ /**
15
+ * `floating` (default): the dark pill (SHELL.md §7, `.ap-bar`).
16
+ * `card`: the Settings bar (Settings.html `.ap-save`), a full-width card
17
+ * pinned to the bottom with a warning dot beside the note.
18
+ */
19
+ variant?: 'floating' | 'card'
20
+ }
21
+
22
+ // Bar buttons (`.ap-bar .ap-btn`): 32px, 0 12px, radius 8, 13px / 550.
23
+ const BAR_BUTTON =
24
+ 'rounded-8 text-body inline-flex h-8 cursor-pointer items-center gap-[7px] border border-transparent px-3 leading-[normal] font-[550] whitespace-nowrap disabled:cursor-not-allowed disabled:opacity-45'
25
+
26
+ /**
27
+ * Unsaved-changes bar. Renders only while the form is dirty, plus an always
28
+ * mounted, visually hidden live region: a region inserted together with its
29
+ * text is usually not announced, so the text changes inside one that exists.
30
+ */
31
+ export function UnsavedBar({
32
+ dirty,
33
+ onDiscard,
34
+ onSave,
35
+ label = 'Unsaved changes',
36
+ saving = false,
37
+ saveDisabled = false,
38
+ saveLabel = 'Save',
39
+ discardLabel = 'Discard',
40
+ variant = 'floating',
41
+ }: UnsavedBarProps) {
42
+ // `fixed`, not sr-only's `absolute`: an absolute box with no positioned
43
+ // ancestor sits at its static position in the admin root, and at the end of
44
+ // a long tab it stretched the root's scroll area (the whole shell scrolled).
45
+ const live = (
46
+ <span className="sr-only fixed! top-0 left-0" role="status" aria-live="polite">
47
+ {dirty ? label : ''}
48
+ </span>
49
+ )
50
+ if (!dirty) return live
51
+
52
+ if (variant === 'card') {
53
+ return (
54
+ <>
55
+ {live}
56
+ <div
57
+ role="region"
58
+ aria-label="Unsaved changes"
59
+ className="rounded-12 border-bdr bg-card shadow-save sticky bottom-0 z-[5] mt-[22px] flex items-center justify-between gap-3 border px-4 py-[13px]"
60
+ >
61
+ <span className="text-meta text-sub flex items-center gap-2 leading-[normal]">
62
+ <span className="bg-warn h-[7px] w-[7px] shrink-0 rounded-full" aria-hidden />
63
+ {label}
64
+ </span>
65
+ <span className="flex items-center gap-2.5">
66
+ {/* Settings.html `.btn-ghost` and `.btn-p`. */}
67
+ <button
68
+ type="button"
69
+ onClick={onDiscard}
70
+ disabled={saving}
71
+ className="prenta-touch-target rounded-7 text-sm2 text-sub hover:bg-acc-l hover:text-acc inline-flex cursor-pointer items-center gap-[5px] border-0 bg-transparent px-2.5 py-1.5 leading-[normal] whitespace-nowrap disabled:cursor-not-allowed disabled:opacity-45"
72
+ >
73
+ {discardLabel}
74
+ </button>
75
+ <button
76
+ type="button"
77
+ onClick={onSave}
78
+ disabled={saving || saveDisabled}
79
+ aria-busy={saving || undefined}
80
+ className="prenta-touch-target rounded-8 text-body bg-acc text-acc-on inline-flex cursor-pointer items-center gap-1.5 border-0 px-4 py-2 leading-[normal] font-medium whitespace-nowrap hover:opacity-88 disabled:cursor-not-allowed disabled:opacity-45"
81
+ >
82
+ {saving ? 'Saving…' : saveLabel}
83
+ </button>
84
+ </span>
85
+ </div>
86
+ </>
87
+ )
88
+ }
89
+
90
+ return (
91
+ <>
92
+ {live}
93
+ <div
94
+ role="region"
95
+ aria-label="Unsaved changes"
96
+ className="prenta-inverse rounded-12 bg-txt text-body text-bg shadow-bar sticky bottom-4 z-[var(--z-bar)] ml-auto flex w-[min(520px,100%)] items-center gap-2.5 py-2.5 pr-2.5 pl-4 leading-[normal] font-[550]"
97
+ >
98
+ <span className="min-w-0 flex-1">{label}</span>
99
+ <button
100
+ type="button"
101
+ onClick={onDiscard}
102
+ disabled={saving}
103
+ className={`${BAR_BUTTON} text-bg bg-transparent opacity-85 hover:bg-[color-mix(in_srgb,var(--bg)_8%,transparent)] hover:opacity-100 focus-visible:opacity-100`}
104
+ >
105
+ {discardLabel}
106
+ </button>
107
+ <button
108
+ type="button"
109
+ onClick={onSave}
110
+ disabled={saving || saveDisabled}
111
+ aria-busy={saving || undefined}
112
+ className={`${BAR_BUTTON} bg-acc text-acc-on hover:brightness-[1.06]`}
113
+ >
114
+ {saving ? 'Saving…' : saveLabel}
115
+ </button>
116
+ </div>
117
+ </>
118
+ )
119
+ }
@@ -0,0 +1,20 @@
1
+ 'use client'
2
+
3
+ import { createContext, useContext } from 'react'
4
+
5
+ export interface AdminLinks {
6
+ /** Absolute URL for an admin path (adds the admin base path). */
7
+ href: (path: string) => string
8
+ /** In-app navigation; plain clicks on admin links go through it. */
9
+ navigate?: (path: string) => void
10
+ }
11
+
12
+ const AdminLinksContext = createContext<AdminLinks>({ href: (path) => path })
13
+
14
+ /** Provided by `AdminRoot` from its router. */
15
+ export const AdminLinksProvider = AdminLinksContext.Provider
16
+
17
+ /** Build real hrefs for admin paths, so links can open in a new tab. */
18
+ export function useAdminLinks(): AdminLinks {
19
+ return useContext(AdminLinksContext)
20
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Attributes for a list table that renders as cards on mobile
3
+ * (`table[data-cards]` in responsive.css, cms-layouts.css in the kit).
4
+ *
5
+ * Spread them on the table's own elements:
6
+ *
7
+ * <table {...cardTable}>
8
+ * <thead {...cardRowGroup}><tr {...cardRow}><th {...cardColumnHeader}>…
9
+ * <tbody {...cardRowGroup}>
10
+ * <tr {...cardRow}>
11
+ * <td {...cardCell({ role: 'check' })}>…</td>
12
+ * <td {...cardCell({ role: 'title' })}>…</td>
13
+ * <td {...cardCell({ label: 'Status' })}>…</td>
14
+ * <td {...cardCell({ role: 'actions' })}>…</td>
15
+ *
16
+ * The explicit table roles keep the semantics when the card layout changes
17
+ * the elements' `display` (some engines drop them otherwise). A cell's
18
+ * `label` is its column's visible header, shown before the value on a card.
19
+ */
20
+ export const cardTable = { 'data-cards': '', role: 'table' } as const
21
+ export const cardRowGroup = { role: 'rowgroup' } as const
22
+ export const cardRow = { role: 'row' } as const
23
+ export const cardColumnHeader = { role: 'columnheader' } as const
24
+
25
+ /** How a cell sits on its card: see `table[data-cards]` in responsive.css. */
26
+ export type CardCellRole = 'title' | 'check' | 'actions' | 'media'
27
+
28
+ export function cardCell({ label, role }: { label?: string; role?: CardCellRole } = {}) {
29
+ return {
30
+ role: 'cell',
31
+ 'data-label': label || undefined,
32
+ 'data-role': role,
33
+ } as const
34
+ }
@@ -29,18 +29,29 @@ export function useVirtualWindow(options: {
29
29
  scrollRef: RefObject<HTMLElement | null>
30
30
  estimateSize: number
31
31
  overscan?: number
32
+ /**
33
+ * `false` mounts every row with no padding. For layouts whose rows aren't
34
+ * `estimateSize` tall, such as list tables drawn as cards on mobile
35
+ * (`table[data-cards]`): rows are placed by the estimate, so taller rows
36
+ * would scroll past rows that were never mounted.
37
+ */
38
+ enabled?: boolean
32
39
  }): { rows: VirtualWindowRow[]; paddingTop: number; paddingBottom: number } {
33
- const { count, scrollRef, estimateSize, overscan = 8 } = options
40
+ const { count, scrollRef, estimateSize, overscan = 8, enabled = true } = options
34
41
  const getScrollElement = useCallback(() => scrollRef.current, [scrollRef])
35
42
  const estimate = useCallback(() => estimateSize, [estimateSize])
36
43
  const virtualizer = useVirtualizer({
37
- count,
44
+ count: enabled ? count : 0,
38
45
  getScrollElement,
39
46
  estimateSize: estimate,
40
47
  overscan,
41
48
  initialRect: { width: 1024, height: 640 },
42
49
  })
43
50
 
51
+ if (!enabled) {
52
+ return { rows: rowsInRange(0, count, estimateSize), paddingTop: 0, paddingBottom: 0 }
53
+ }
54
+
44
55
  const items = virtualizer.getVirtualItems()
45
56
  // Zero-height shells (happy-dom) report an empty range. Short lists stay
46
57
  // fully mounted. A 1k-row list still windows against the initial viewport
@@ -27,7 +27,7 @@ interface RelatedDoc {
27
27
 
28
28
  const STATUS_STYLES: Record<string, string> = {
29
29
  PUBLISHED: 'bg-success/10 text-success',
30
- DRAFT: 'bg-warning/10 text-warning',
30
+ DRAFT: 'bg-warn-l text-warning',
31
31
  ARCHIVED: 'bg-muted text-muted-foreground',
32
32
  SCHEDULED: 'bg-info/10 text-info',
33
33
  }
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import { useEffect } from 'react'
3
+ import { useEffect, useRef } from 'react'
4
4
 
5
5
  import { useTheme } from '../components/ThemeProvider.js'
6
6
  import { appearanceApiToSnapshot, type AppearanceApiResponse } from '../lib/appearance-api.js'
@@ -15,6 +15,12 @@ import { cmsApi } from '../lib/api.js'
15
15
  export function useAppearanceBootstrap(session: unknown) {
16
16
  const { applyAppearance } = useTheme()
17
17
  const active = Boolean(session)
18
+ // Fetch once per sign-in. A new `applyAppearance` identity must not refetch
19
+ // and overwrite a change the user just made.
20
+ const applyRef = useRef(applyAppearance)
21
+ useEffect(() => {
22
+ applyRef.current = applyAppearance
23
+ }, [applyAppearance])
18
24
 
19
25
  useEffect(() => {
20
26
  if (!active) return
@@ -25,7 +31,7 @@ export function useAppearanceBootstrap(session: unknown) {
25
31
  try {
26
32
  const res = await cmsApi<AppearanceApiResponse>('/appearance')
27
33
  if (cancelled || res.error || !res.data) return
28
- applyAppearance(appearanceApiToSnapshot(res.data))
34
+ applyRef.current(appearanceApiToSnapshot(res.data))
29
35
  } catch {
30
36
  /* keep localStorage / config fallbacks */
31
37
  }
@@ -36,5 +42,5 @@ export function useAppearanceBootstrap(session: unknown) {
36
42
  return () => {
37
43
  cancelled = true
38
44
  }
39
- }, [active, applyAppearance])
45
+ }, [active])
40
46
  }
package/src/index.ts CHANGED
@@ -118,6 +118,25 @@ export type { SharePreviewLinkDialogProps } from './components/SharePreviewLinkD
118
118
  export { MediaPickerModal } from './components/MediaPickerModal.js'
119
119
  export type { MediaPickerModalProps } from './components/MediaPickerModal.js'
120
120
  export { ThemeProvider, useTheme } from './components/ThemeProvider.js'
121
+ export { PageHeader } from './components/ui/PageHeader.js'
122
+ export type { PageHeaderProps } from './components/ui/PageHeader.js'
123
+ export { Breadcrumb } from './components/ui/Breadcrumb.js'
124
+ export type { BreadcrumbProps, BreadcrumbItem } from './components/ui/Breadcrumb.js'
125
+ /** Gives `Breadcrumb` path items real hrefs (admin base path) outside `AdminRoot`. */
126
+ export { AdminLinksProvider } from './components/ui/admin-links.js'
127
+ export type { AdminLinks } from './components/ui/admin-links.js'
128
+ export { CountChip } from './components/ui/CountChip.js'
129
+ export type { CountChipProps } from './components/ui/CountChip.js'
130
+ export { UnderlineTabs, UnderlineTabPanel } from './components/ui/UnderlineTabs.js'
131
+ export type {
132
+ UnderlineTabsProps,
133
+ UnderlineTab,
134
+ UnderlineTabPanelProps,
135
+ } from './components/ui/UnderlineTabs.js'
136
+ export { Segmented } from './components/ui/Segmented.js'
137
+ export type { SegmentedProps, SegmentedOption } from './components/ui/Segmented.js'
138
+ export { UnsavedBar } from './components/ui/UnsavedBar.js'
139
+ export type { UnsavedBarProps } from './components/ui/UnsavedBar.js'
121
140
  export { FocalPointPicker } from './components/FocalPointPicker.js'
122
141
  export { PresenceIndicator } from './components/PresenceIndicator.js'
123
142
  export { NotificationBell } from './components/NotificationBell.js'