@actuate-media/cms-admin 0.9.0 → 0.11.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 (294) hide show
  1. package/dist/AdminRoot.d.ts.map +1 -1
  2. package/dist/AdminRoot.js +8 -5
  3. package/dist/AdminRoot.js.map +1 -1
  4. package/dist/__tests__/layout/primitives.test.d.ts +2 -0
  5. package/dist/__tests__/layout/primitives.test.d.ts.map +1 -0
  6. package/dist/__tests__/layout/primitives.test.js +34 -0
  7. package/dist/__tests__/layout/primitives.test.js.map +1 -0
  8. package/dist/__tests__/lib/cv.test.d.ts +2 -0
  9. package/dist/__tests__/lib/cv.test.d.ts.map +1 -0
  10. package/dist/__tests__/lib/cv.test.js +66 -0
  11. package/dist/__tests__/lib/cv.test.js.map +1 -0
  12. package/dist/actuate-admin.css +1 -1
  13. package/dist/assets/actuate-logo.d.ts +36 -0
  14. package/dist/assets/actuate-logo.d.ts.map +1 -0
  15. package/dist/assets/actuate-logo.js +15 -0
  16. package/dist/assets/actuate-logo.js.map +1 -0
  17. package/dist/components/Breadcrumbs.js +2 -2
  18. package/dist/components/CommandPalette.js +10 -10
  19. package/dist/components/ContentOverviewChart.js +3 -3
  20. package/dist/components/ErrorBoundary.js +1 -1
  21. package/dist/components/FocalPointPicker.js +2 -2
  22. package/dist/components/FolderTree.js +20 -20
  23. package/dist/components/LivePreview.js +3 -3
  24. package/dist/components/LocaleSwitcher.js +1 -1
  25. package/dist/components/MediaPickerModal.js +4 -4
  26. package/dist/components/PresenceIndicator.js +1 -1
  27. package/dist/components/SEOConfigPanel.d.ts +2 -0
  28. package/dist/components/SEOConfigPanel.d.ts.map +1 -0
  29. package/dist/components/SEOConfigPanel.js +174 -0
  30. package/dist/components/SEOConfigPanel.js.map +1 -0
  31. package/dist/components/SEOPanel.js +9 -9
  32. package/dist/components/SEOPerformance.js +2 -2
  33. package/dist/components/SchedulePublishDialog.d.ts +18 -0
  34. package/dist/components/SchedulePublishDialog.d.ts.map +1 -0
  35. package/dist/components/SchedulePublishDialog.js +106 -0
  36. package/dist/components/SchedulePublishDialog.js.map +1 -0
  37. package/dist/components/SharePreviewLinkDialog.d.ts +17 -0
  38. package/dist/components/SharePreviewLinkDialog.d.ts.map +1 -0
  39. package/dist/components/SharePreviewLinkDialog.js +83 -0
  40. package/dist/components/SharePreviewLinkDialog.js.map +1 -0
  41. package/dist/components/TipTapEditor.js +5 -5
  42. package/dist/components/VersionHistory.js +2 -2
  43. package/dist/components/ui/Badge.d.ts +33 -3
  44. package/dist/components/ui/Badge.d.ts.map +1 -1
  45. package/dist/components/ui/Badge.js +42 -8
  46. package/dist/components/ui/Badge.js.map +1 -1
  47. package/dist/components/ui/Button.d.ts +19 -8
  48. package/dist/components/ui/Button.d.ts.map +1 -1
  49. package/dist/components/ui/Button.js +35 -14
  50. package/dist/components/ui/Button.js.map +1 -1
  51. package/dist/components/ui/Card.d.ts +26 -0
  52. package/dist/components/ui/Card.d.ts.map +1 -0
  53. package/dist/components/ui/Card.js +45 -0
  54. package/dist/components/ui/Card.js.map +1 -0
  55. package/dist/components/ui/DataTable.js +1 -1
  56. package/dist/components/ui/Input.d.ts +15 -0
  57. package/dist/components/ui/Input.d.ts.map +1 -0
  58. package/dist/components/ui/Input.js +23 -0
  59. package/dist/components/ui/Input.js.map +1 -0
  60. package/dist/components/ui/SearchInput.js +1 -1
  61. package/dist/components/ui/Select.d.ts +16 -0
  62. package/dist/components/ui/Select.d.ts.map +1 -0
  63. package/dist/components/ui/Select.js +25 -0
  64. package/dist/components/ui/Select.js.map +1 -0
  65. package/dist/components/ui/Toast.js +1 -1
  66. package/dist/components/ui/index.d.ts +10 -4
  67. package/dist/components/ui/index.d.ts.map +1 -1
  68. package/dist/components/ui/index.js +5 -2
  69. package/dist/components/ui/index.js.map +1 -1
  70. package/dist/fields/BlockBuilderField.js +3 -3
  71. package/dist/fields/DateField.js +1 -1
  72. package/dist/fields/RelationshipField.js +3 -3
  73. package/dist/fields/TextField.js +1 -1
  74. package/dist/index.d.ts +6 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/layout/Header.js +1 -1
  79. package/dist/layout/Layout.d.ts +14 -0
  80. package/dist/layout/Layout.d.ts.map +1 -1
  81. package/dist/layout/Layout.js +17 -11
  82. package/dist/layout/Layout.js.map +1 -1
  83. package/dist/layout/Sidebar.d.ts.map +1 -1
  84. package/dist/layout/Sidebar.js +21 -11
  85. package/dist/layout/Sidebar.js.map +1 -1
  86. package/dist/layout/primitives/AdminShell.d.ts +43 -0
  87. package/dist/layout/primitives/AdminShell.d.ts.map +1 -0
  88. package/dist/layout/primitives/AdminShell.js +51 -0
  89. package/dist/layout/primitives/AdminShell.js.map +1 -0
  90. package/dist/layout/primitives/Box.d.ts +19 -0
  91. package/dist/layout/primitives/Box.d.ts.map +1 -0
  92. package/dist/layout/primitives/Box.js +12 -0
  93. package/dist/layout/primitives/Box.js.map +1 -0
  94. package/dist/layout/primitives/Cluster.d.ts +27 -0
  95. package/dist/layout/primitives/Cluster.d.ts.map +1 -0
  96. package/dist/layout/primitives/Cluster.js +37 -0
  97. package/dist/layout/primitives/Cluster.js.map +1 -0
  98. package/dist/layout/primitives/Grid.d.ts +45 -0
  99. package/dist/layout/primitives/Grid.d.ts.map +1 -0
  100. package/dist/layout/primitives/Grid.js +59 -0
  101. package/dist/layout/primitives/Grid.js.map +1 -0
  102. package/dist/layout/primitives/PageContainer.d.ts +36 -0
  103. package/dist/layout/primitives/PageContainer.d.ts.map +1 -0
  104. package/dist/layout/primitives/PageContainer.js +41 -0
  105. package/dist/layout/primitives/PageContainer.js.map +1 -0
  106. package/dist/layout/primitives/Split.d.ts +34 -0
  107. package/dist/layout/primitives/Split.d.ts.map +1 -0
  108. package/dist/layout/primitives/Split.js +27 -0
  109. package/dist/layout/primitives/Split.js.map +1 -0
  110. package/dist/layout/primitives/Stack.d.ts +23 -0
  111. package/dist/layout/primitives/Stack.d.ts.map +1 -0
  112. package/dist/layout/primitives/Stack.js +34 -0
  113. package/dist/layout/primitives/Stack.js.map +1 -0
  114. package/dist/layout/primitives/index.d.ts +30 -0
  115. package/dist/layout/primitives/index.d.ts.map +1 -0
  116. package/dist/layout/primitives/index.js +22 -0
  117. package/dist/layout/primitives/index.js.map +1 -0
  118. package/dist/layout/primitives/tokens.d.ts +48 -0
  119. package/dist/layout/primitives/tokens.d.ts.map +1 -0
  120. package/dist/layout/primitives/tokens.js +54 -0
  121. package/dist/layout/primitives/tokens.js.map +1 -0
  122. package/dist/lib/cv.d.ts +53 -0
  123. package/dist/lib/cv.d.ts.map +1 -0
  124. package/dist/lib/cv.js +39 -0
  125. package/dist/lib/cv.js.map +1 -0
  126. package/dist/views/ApiKeys.d.ts.map +1 -1
  127. package/dist/views/ApiKeys.js +13 -11
  128. package/dist/views/ApiKeys.js.map +1 -1
  129. package/dist/views/CollectionList.js +8 -8
  130. package/dist/views/Dashboard.d.ts.map +1 -1
  131. package/dist/views/Dashboard.js +333 -78
  132. package/dist/views/Dashboard.js.map +1 -1
  133. package/dist/views/DocumentEdit.d.ts.map +1 -1
  134. package/dist/views/DocumentEdit.js +17 -5
  135. package/dist/views/DocumentEdit.js.map +1 -1
  136. package/dist/views/ForgotPassword.js +2 -2
  137. package/dist/views/FormEditor.js +5 -5
  138. package/dist/views/FormSubmissions.js +6 -6
  139. package/dist/views/Forms.js +2 -2
  140. package/dist/views/Login.d.ts +16 -1
  141. package/dist/views/Login.d.ts.map +1 -1
  142. package/dist/views/Login.js +17 -7
  143. package/dist/views/Login.js.map +1 -1
  144. package/dist/views/MediaBrowser.js +16 -16
  145. package/dist/views/PageEditor.js +2 -2
  146. package/dist/views/Pages.js +10 -10
  147. package/dist/views/PostEditor.js +2 -2
  148. package/dist/views/Posts.js +4 -4
  149. package/dist/views/Redirects.js +4 -4
  150. package/dist/views/ResetPassword.js +2 -2
  151. package/dist/views/SEO.js +6 -6
  152. package/dist/views/ScriptTagEditor.js +4 -4
  153. package/dist/views/ScriptTags.js +2 -2
  154. package/dist/views/Settings.d.ts.map +1 -1
  155. package/dist/views/Settings.js +9 -8
  156. package/dist/views/Settings.js.map +1 -1
  157. package/dist/views/SetupWizard.js +2 -2
  158. package/dist/views/Users.js +4 -4
  159. package/dist/views/page-builder/AIBlockAssist.js +1 -1
  160. package/dist/views/page-builder/AIGenerateDialog.js +10 -10
  161. package/dist/views/page-builder/BlockEditor.js +10 -10
  162. package/dist/views/page-builder/BlockPicker.js +4 -4
  163. package/dist/views/page-builder/BottomBar.js +1 -1
  164. package/dist/views/page-builder/BuilderToolbar.js +2 -2
  165. package/dist/views/page-builder/ContextPanel.js +2 -2
  166. package/dist/views/page-builder/DesignScore.js +9 -9
  167. package/dist/views/page-builder/NodeSettings.js +8 -8
  168. package/dist/views/page-builder/PageBuilder.js +3 -3
  169. package/dist/views/page-builder/PageSettings.js +1 -1
  170. package/dist/views/page-builder/PageTemplates.js +2 -2
  171. package/dist/views/page-builder/SEOPanel.js +13 -13
  172. package/dist/views/page-builder/SavedSections.js +5 -5
  173. package/dist/views/page-builder/TemplatePicker.js +2 -2
  174. package/dist/views/page-builder/block-renderers/CTAPreview.js +5 -5
  175. package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
  176. package/dist/views/page-builder/block-renderers/CodePreview.js +1 -1
  177. package/dist/views/page-builder/block-renderers/FAQPreview.js +3 -3
  178. package/dist/views/page-builder/block-renderers/FallbackPreview.js +1 -1
  179. package/dist/views/page-builder/block-renderers/FormPreview.js +3 -3
  180. package/dist/views/page-builder/block-renderers/GalleryPreview.js +5 -5
  181. package/dist/views/page-builder/block-renderers/HeroPreview.js +3 -3
  182. package/dist/views/page-builder/block-renderers/ImagePreview.js +3 -3
  183. package/dist/views/page-builder/block-renderers/TextPreview.js +3 -3
  184. package/dist/views/page-builder/block-renderers/VideoPreview.js +4 -4
  185. package/dist/views/page-builder/canvas/BlockRenderer.js +1 -1
  186. package/dist/views/page-builder/canvas/BuilderCanvas.js +3 -3
  187. package/dist/views/page-builder/canvas/ColumnRenderer.js +2 -2
  188. package/dist/views/page-builder/canvas/ContainerRenderer.js +2 -2
  189. package/dist/views/page-builder/canvas/RowRenderer.js +2 -2
  190. package/dist/views/page-builder/canvas/SectionRenderer.js +2 -2
  191. package/package.json +6 -2
  192. package/src/AdminRoot.tsx +21 -11
  193. package/src/__tests__/layout/primitives.test.ts +37 -0
  194. package/src/__tests__/lib/cv.test.ts +74 -0
  195. package/src/assets/actuate-logo.tsx +72 -0
  196. package/src/components/Breadcrumbs.tsx +6 -6
  197. package/src/components/CommandPalette.tsx +34 -34
  198. package/src/components/ContentOverviewChart.tsx +3 -3
  199. package/src/components/ErrorBoundary.tsx +3 -3
  200. package/src/components/FocalPointPicker.tsx +4 -4
  201. package/src/components/FolderTree.tsx +38 -38
  202. package/src/components/LivePreview.tsx +16 -16
  203. package/src/components/LocaleSwitcher.tsx +7 -7
  204. package/src/components/MediaPickerModal.tsx +21 -21
  205. package/src/components/PresenceIndicator.tsx +2 -2
  206. package/src/components/SEOConfigPanel.tsx +582 -0
  207. package/src/components/SEOPanel.tsx +46 -46
  208. package/src/components/SEOPerformance.tsx +21 -21
  209. package/src/components/SchedulePublishDialog.tsx +241 -0
  210. package/src/components/SharePreviewLinkDialog.tsx +227 -0
  211. package/src/components/TipTapEditor.tsx +33 -33
  212. package/src/components/VersionHistory.tsx +16 -16
  213. package/src/components/ui/Badge.tsx +66 -14
  214. package/src/components/ui/Button.tsx +70 -33
  215. package/src/components/ui/Card.tsx +101 -0
  216. package/src/components/ui/DataTable.tsx +1 -1
  217. package/src/components/ui/Input.tsx +35 -0
  218. package/src/components/ui/SearchInput.tsx +4 -4
  219. package/src/components/ui/Select.tsx +56 -0
  220. package/src/components/ui/Toast.tsx +1 -1
  221. package/src/components/ui/index.ts +18 -4
  222. package/src/fields/BlockBuilderField.tsx +3 -3
  223. package/src/fields/DateField.tsx +1 -1
  224. package/src/fields/RelationshipField.tsx +10 -10
  225. package/src/fields/TextField.tsx +1 -1
  226. package/src/index.ts +32 -0
  227. package/src/layout/Header.tsx +28 -28
  228. package/src/layout/Layout.tsx +39 -46
  229. package/src/layout/Sidebar.tsx +37 -64
  230. package/src/layout/primitives/AdminShell.tsx +118 -0
  231. package/src/layout/primitives/Box.tsx +30 -0
  232. package/src/layout/primitives/Cluster.tsx +74 -0
  233. package/src/layout/primitives/Grid.tsx +120 -0
  234. package/src/layout/primitives/PageContainer.tsx +96 -0
  235. package/src/layout/primitives/Split.tsx +73 -0
  236. package/src/layout/primitives/Stack.tsx +67 -0
  237. package/src/layout/primitives/index.ts +36 -0
  238. package/src/layout/primitives/tokens.ts +76 -0
  239. package/src/lib/cv.ts +96 -0
  240. package/src/styles/build-input.css +1 -1
  241. package/src/views/ApiKeys.tsx +57 -57
  242. package/src/views/CollectionList.tsx +30 -30
  243. package/src/views/Dashboard.tsx +737 -186
  244. package/src/views/DocumentEdit.tsx +90 -10
  245. package/src/views/ForgotPassword.tsx +18 -18
  246. package/src/views/FormEditor.tsx +75 -75
  247. package/src/views/FormSubmissions.tsx +76 -76
  248. package/src/views/Forms.tsx +27 -27
  249. package/src/views/Login.tsx +65 -25
  250. package/src/views/MediaBrowser.tsx +127 -127
  251. package/src/views/PageEditor.tsx +25 -25
  252. package/src/views/Pages.tsx +59 -59
  253. package/src/views/PostEditor.tsx +37 -37
  254. package/src/views/Posts.tsx +48 -48
  255. package/src/views/Redirects.tsx +21 -21
  256. package/src/views/ResetPassword.tsx +28 -28
  257. package/src/views/SEO.tsx +144 -144
  258. package/src/views/ScriptTagEditor.tsx +24 -24
  259. package/src/views/ScriptTags.tsx +10 -10
  260. package/src/views/Settings.tsx +88 -80
  261. package/src/views/SetupWizard.tsx +28 -28
  262. package/src/views/Users.tsx +20 -20
  263. package/src/views/page-builder/AIBlockAssist.tsx +1 -1
  264. package/src/views/page-builder/AIGenerateDialog.tsx +63 -63
  265. package/src/views/page-builder/BlockEditor.tsx +26 -26
  266. package/src/views/page-builder/BlockPicker.tsx +22 -22
  267. package/src/views/page-builder/BottomBar.tsx +8 -8
  268. package/src/views/page-builder/BuilderToolbar.tsx +17 -17
  269. package/src/views/page-builder/ContextPanel.tsx +3 -3
  270. package/src/views/page-builder/DesignScore.tsx +21 -21
  271. package/src/views/page-builder/NodeSettings.tsx +27 -27
  272. package/src/views/page-builder/PageBuilder.tsx +11 -11
  273. package/src/views/page-builder/PageSettings.tsx +4 -4
  274. package/src/views/page-builder/PageTemplates.tsx +18 -18
  275. package/src/views/page-builder/SEOPanel.tsx +53 -53
  276. package/src/views/page-builder/SavedSections.tsx +37 -37
  277. package/src/views/page-builder/TemplatePicker.tsx +17 -17
  278. package/src/views/page-builder/block-renderers/CTAPreview.tsx +13 -13
  279. package/src/views/page-builder/block-renderers/CardsPreview.tsx +5 -5
  280. package/src/views/page-builder/block-renderers/CodePreview.tsx +6 -6
  281. package/src/views/page-builder/block-renderers/FAQPreview.tsx +13 -13
  282. package/src/views/page-builder/block-renderers/FallbackPreview.tsx +3 -3
  283. package/src/views/page-builder/block-renderers/FormPreview.tsx +20 -20
  284. package/src/views/page-builder/block-renderers/GalleryPreview.tsx +8 -8
  285. package/src/views/page-builder/block-renderers/HeroPreview.tsx +16 -16
  286. package/src/views/page-builder/block-renderers/ImagePreview.tsx +4 -4
  287. package/src/views/page-builder/block-renderers/TextPreview.tsx +14 -14
  288. package/src/views/page-builder/block-renderers/VideoPreview.tsx +12 -12
  289. package/src/views/page-builder/canvas/BlockRenderer.tsx +4 -4
  290. package/src/views/page-builder/canvas/BuilderCanvas.tsx +6 -6
  291. package/src/views/page-builder/canvas/ColumnRenderer.tsx +3 -3
  292. package/src/views/page-builder/canvas/ContainerRenderer.tsx +2 -2
  293. package/src/views/page-builder/canvas/RowRenderer.tsx +2 -2
  294. package/src/views/page-builder/canvas/SectionRenderer.tsx +2 -2
@@ -127,9 +127,9 @@ export function BlockPicker({ open, onClose, onSelect }: BlockPickerProps) {
127
127
  return (
128
128
  <Dialog.Root open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
129
129
  <Dialog.Portal>
130
- <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50 motion-safe:animate-in motion-safe:fade-in-0" />
130
+ <Dialog.Overlay className="motion-safe:animate-in motion-safe:fade-in-0 fixed inset-0 z-50 bg-black/50" />
131
131
  <Dialog.Content
132
- className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card rounded-xl shadow-2xl border border-border z-50 w-full max-w-2xl max-h-[80vh] overflow-hidden flex flex-col"
132
+ className="bg-card border-border fixed top-1/2 left-1/2 z-50 flex max-h-[80vh] w-full max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border shadow-2xl"
133
133
  aria-describedby={undefined}
134
134
  onEscapeKeyDown={() => {
135
135
  if (selectedBlock) {
@@ -182,13 +182,13 @@ function BlockTypeGrid({
182
182
  onKeyDown,
183
183
  }: BlockTypeGridProps) {
184
184
  return (
185
- <div className="flex flex-col h-full" onKeyDown={onKeyDown}>
185
+ <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
186
186
  <div className="flex items-center justify-between gap-3 px-5 pt-5 pb-3">
187
- <Dialog.Title className="text-lg font-medium text-foreground">Add Block</Dialog.Title>
187
+ <Dialog.Title className="text-foreground text-lg font-medium">Add Block</Dialog.Title>
188
188
  <Dialog.Close asChild>
189
189
  <button
190
190
  type="button"
191
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
191
+ className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
192
192
  aria-label="Close"
193
193
  >
194
194
  <X size={18} />
@@ -199,7 +199,7 @@ function BlockTypeGrid({
199
199
  <div className="px-5 pb-3">
200
200
  <div className="relative">
201
201
  <Search
202
- className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none"
202
+ className="text-muted-foreground pointer-events-none absolute top-1/2 left-3 -translate-y-1/2"
203
203
  size={16}
204
204
  />
205
205
  <input
@@ -208,7 +208,7 @@ function BlockTypeGrid({
208
208
  placeholder="Search blocks..."
209
209
  value={search}
210
210
  onChange={(e) => onSearchChange(e.target.value)}
211
- className="w-full pl-9 pr-3 py-2 text-sm bg-background border border-input rounded-md focus:outline-none focus:ring-2 focus:ring-ring"
211
+ className="bg-background border-input focus:ring-ring w-full rounded-md border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
212
212
  aria-label="Search block types"
213
213
  />
214
214
  </div>
@@ -218,7 +218,7 @@ function BlockTypeGrid({
218
218
  {filteredBlocks.length === 0 ? (
219
219
  <div className="flex flex-col items-center justify-center py-12 text-center">
220
220
  <Search size={24} className="text-muted-foreground mb-2" />
221
- <p className="text-sm text-muted-foreground">No blocks match &ldquo;{search}&rdquo;</p>
221
+ <p className="text-muted-foreground text-sm">No blocks match &ldquo;{search}&rdquo;</p>
222
222
  </div>
223
223
  ) : (
224
224
  <div className="grid grid-cols-2 gap-3" role="list" aria-label="Available block types">
@@ -230,15 +230,15 @@ function BlockTypeGrid({
230
230
  type="button"
231
231
  role="listitem"
232
232
  onClick={() => onBlockClick(block)}
233
- className="p-4 border border-border rounded-lg hover:border-primary cursor-pointer transition-colors bg-card text-left flex items-start gap-3 group focus:outline-none focus:ring-2 focus:ring-ring"
233
+ className="border-border hover:border-primary bg-card group focus:ring-ring flex cursor-pointer items-start gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
234
234
  >
235
- <div className="shrink-0 w-9 h-9 rounded-md bg-accent flex items-center justify-center text-foreground group-hover:bg-primary/10 group-hover:text-primary transition-colors">
235
+ <div className="bg-accent text-foreground group-hover:bg-primary/10 group-hover:text-primary flex h-9 w-9 shrink-0 items-center justify-center rounded-md transition-colors">
236
236
  <Icon size={18} />
237
237
  </div>
238
238
  <div className="min-w-0">
239
- <p className="text-sm font-medium text-foreground truncate">{block.label}</p>
239
+ <p className="text-foreground truncate text-sm font-medium">{block.label}</p>
240
240
  {block.description && (
241
- <p className="text-xs text-muted-foreground mt-0.5 line-clamp-2">
241
+ <p className="text-muted-foreground mt-0.5 line-clamp-2 text-xs">
242
242
  {block.description}
243
243
  </p>
244
244
  )}
@@ -271,24 +271,24 @@ function VariantView({
271
271
  const Icon = resolveIcon(block.icon)
272
272
 
273
273
  return (
274
- <div className="flex flex-col h-full" onKeyDown={onKeyDown}>
274
+ <div className="flex h-full flex-col" onKeyDown={onKeyDown}>
275
275
  <div className="flex items-center gap-3 px-5 pt-5 pb-3">
276
276
  <button
277
277
  type="button"
278
278
  onClick={onBack}
279
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
279
+ className="text-muted-foreground hover:text-foreground hover:bg-accent rounded-md p-1.5 transition-colors"
280
280
  aria-label="Back to block types"
281
281
  >
282
282
  <ArrowLeft size={18} />
283
283
  </button>
284
- <div className="flex items-center gap-2 min-w-0">
284
+ <div className="flex min-w-0 items-center gap-2">
285
285
  <Icon size={18} className="text-foreground shrink-0" />
286
- <h2 className="text-lg font-medium text-foreground truncate">{block.label}</h2>
286
+ <h2 className="text-foreground truncate text-lg font-medium">{block.label}</h2>
287
287
  </div>
288
288
  </div>
289
289
 
290
290
  {block.description && (
291
- <p className="text-sm text-muted-foreground px-5 pb-3">{block.description}</p>
291
+ <p className="text-muted-foreground px-5 pb-3 text-sm">{block.description}</p>
292
292
  )}
293
293
 
294
294
  <div className="flex-1 overflow-y-auto px-5 pb-5" ref={variantListRef}>
@@ -300,19 +300,19 @@ function VariantView({
300
300
  role="listitem"
301
301
  data-variant={variant.name}
302
302
  onClick={() => onVariantClick(variant)}
303
- className="w-full p-4 border border-border rounded-lg hover:border-primary cursor-pointer transition-colors bg-card text-left flex items-center gap-3 group focus:outline-none focus:ring-2 focus:ring-ring"
303
+ className="border-border hover:border-primary bg-card group focus:ring-ring flex w-full cursor-pointer items-center gap-3 rounded-lg border p-4 text-left transition-colors focus:ring-2 focus:outline-none"
304
304
  >
305
- <div className="flex-1 min-w-0">
305
+ <div className="min-w-0 flex-1">
306
306
  <div className="flex items-center gap-2">
307
- <p className="text-sm font-medium text-foreground">{variant.label}</p>
307
+ <p className="text-foreground text-sm font-medium">{variant.label}</p>
308
308
  {index === 0 && (
309
- <span className="inline-flex items-center gap-1 text-xs text-primary bg-primary/10 px-1.5 py-0.5 rounded">
309
+ <span className="text-primary bg-primary/10 inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs">
310
310
  <Check size={10} />
311
311
  Default
312
312
  </span>
313
313
  )}
314
314
  </div>
315
- <p className="text-xs text-muted-foreground mt-0.5">{variant.description}</p>
315
+ <p className="text-muted-foreground mt-0.5 text-xs">{variant.description}</p>
316
316
  </div>
317
317
  </button>
318
318
  ))}
@@ -25,14 +25,14 @@ export function BottomBar({
25
25
  }: BottomBarProps) {
26
26
  return (
27
27
  <div
28
- className="h-10 bg-card border-t border-border flex items-center px-4 gap-4 shrink-0"
28
+ className="bg-card border-border flex h-10 shrink-0 items-center gap-4 border-t px-4"
29
29
  role="toolbar"
30
30
  aria-label="Builder actions"
31
31
  >
32
32
  {/* Add Section */}
33
33
  <button
34
34
  onClick={onAddSection}
35
- className="flex items-center gap-1.5 px-3 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
35
+ className="text-muted-foreground hover:text-foreground flex items-center gap-1.5 px-3 py-2 text-sm transition-colors"
36
36
  aria-label="Add a new section"
37
37
  >
38
38
  <Plus size={14} />
@@ -40,27 +40,27 @@ export function BottomBar({
40
40
  </button>
41
41
 
42
42
  {/* Divider */}
43
- <div className="w-px h-5 bg-border" />
43
+ <div className="bg-border h-5 w-px" />
44
44
 
45
45
  {/* Grid overlay toggle */}
46
- <label className="flex items-center gap-2 cursor-pointer">
46
+ <label className="flex cursor-pointer items-center gap-2">
47
47
  <Grid3X3 size={14} className="text-muted-foreground" />
48
48
  <Switch.Root
49
49
  checked={showGridOverlay}
50
50
  onCheckedChange={onToggleGrid}
51
- className="w-8 h-[18px] bg-input-background rounded-full relative data-[state=checked]:bg-primary transition-colors"
51
+ className="bg-input-background data-[state=checked]:bg-primary relative h-[18px] w-8 rounded-full transition-colors"
52
52
  aria-label="Toggle grid overlay"
53
53
  >
54
- <Switch.Thumb className="block w-3.5 h-3.5 bg-background rounded-full shadow-sm transition-transform translate-x-0.5 data-[state=checked]:translate-x-[14px]" />
54
+ <Switch.Thumb className="bg-background block h-3.5 w-3.5 translate-x-0.5 rounded-full shadow-sm transition-transform data-[state=checked]:translate-x-[14px]" />
55
55
  </Switch.Root>
56
- <span className="text-xs text-muted-foreground">Grid</span>
56
+ <span className="text-muted-foreground text-xs">Grid</span>
57
57
  </label>
58
58
 
59
59
  {/* Spacer */}
60
60
  <div className="flex-1" />
61
61
 
62
62
  {/* Zoom / device width display */}
63
- <span className="text-xs text-muted-foreground tabular-nums">
63
+ <span className="text-muted-foreground text-xs tabular-nums">
64
64
  {DEVICE_LABELS[deviceMode]}
65
65
  </span>
66
66
  </div>
@@ -59,14 +59,14 @@ export function BuilderToolbar({
59
59
 
60
60
  return (
61
61
  <div
62
- className="h-14 bg-card border-b border-border flex items-center px-4 gap-3 shrink-0"
62
+ className="bg-card border-border flex h-14 shrink-0 items-center gap-3 border-b px-4"
63
63
  role="toolbar"
64
64
  aria-label="Page builder toolbar"
65
65
  >
66
66
  {/* Back button */}
67
67
  <button
68
68
  onClick={() => onNavigate(`/collections/${collectionSlug}`)}
69
- className="flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
69
+ className="text-muted-foreground hover:text-foreground flex items-center gap-1 text-sm transition-colors"
70
70
  aria-label={`Back to ${collectionLabel}`}
71
71
  >
72
72
  <ChevronLeft size={16} />
@@ -74,7 +74,7 @@ export function BuilderToolbar({
74
74
  </button>
75
75
 
76
76
  {/* Divider */}
77
- <div className="w-px h-6 bg-border" />
77
+ <div className="bg-border h-6 w-px" />
78
78
 
79
79
  {/* Page title */}
80
80
  <input
@@ -82,13 +82,13 @@ export function BuilderToolbar({
82
82
  value={pageSettings.title}
83
83
  onChange={(e) => onTitleChange(e.target.value)}
84
84
  placeholder="Untitled Page"
85
- className="flex-1 min-w-0 text-sm font-medium text-foreground bg-transparent border-none outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm placeholder:text-muted-foreground"
85
+ className="text-foreground focus-visible:ring-ring placeholder:text-muted-foreground min-w-0 flex-1 rounded-sm border-none bg-transparent text-sm font-medium outline-none focus-visible:ring-2 focus-visible:ring-offset-2"
86
86
  aria-label="Page title"
87
87
  />
88
88
 
89
89
  {/* Status badge */}
90
90
  <span
91
- className={`text-xs font-medium px-2 py-0.5 rounded-md whitespace-nowrap ${STATUS_STYLES[status] ?? STATUS_STYLES.DRAFT}`}
91
+ className={`rounded-md px-2 py-0.5 text-xs font-medium whitespace-nowrap ${STATUS_STYLES[status] ?? STATUS_STYLES.DRAFT}`}
92
92
  >
93
93
  {status}
94
94
  </span>
@@ -96,21 +96,21 @@ export function BuilderToolbar({
96
96
  {/* Unsaved indicator */}
97
97
  {dirty && !saving && (
98
98
  <span
99
- className="w-2 h-2 rounded-full bg-destructive shrink-0"
99
+ className="bg-destructive h-2 w-2 shrink-0 rounded-full"
100
100
  title="Unsaved changes"
101
101
  aria-label="Unsaved changes"
102
102
  />
103
103
  )}
104
104
 
105
105
  {/* Divider */}
106
- <div className="w-px h-6 bg-border" />
106
+ <div className="bg-border h-6 w-px" />
107
107
 
108
108
  {/* Undo / Redo */}
109
109
  <div className="flex items-center gap-1">
110
110
  <button
111
111
  onClick={onUndo}
112
112
  disabled={!canUndo}
113
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-30 disabled:pointer-events-none transition-colors"
113
+ className="text-muted-foreground hover:text-foreground hover:bg-muted rounded-md p-1.5 transition-colors disabled:pointer-events-none disabled:opacity-30"
114
114
  aria-label="Undo"
115
115
  >
116
116
  <Undo2 size={16} />
@@ -118,7 +118,7 @@ export function BuilderToolbar({
118
118
  <button
119
119
  onClick={onRedo}
120
120
  disabled={!canRedo}
121
- className="p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted disabled:opacity-30 disabled:pointer-events-none transition-colors"
121
+ className="text-muted-foreground hover:text-foreground hover:bg-muted rounded-md p-1.5 transition-colors disabled:pointer-events-none disabled:opacity-30"
122
122
  aria-label="Redo"
123
123
  >
124
124
  <Redo2 size={16} />
@@ -126,10 +126,10 @@ export function BuilderToolbar({
126
126
  </div>
127
127
 
128
128
  {/* Divider */}
129
- <div className="w-px h-6 bg-border" />
129
+ <div className="bg-border h-6 w-px" />
130
130
 
131
131
  {/* Device toggle */}
132
- <div className="flex items-center gap-0.5 bg-muted rounded-md p-0.5">
132
+ <div className="bg-muted flex items-center gap-0.5 rounded-md p-0.5">
133
133
  <DeviceButton
134
134
  active={deviceMode === 'desktop'}
135
135
  onClick={() => onDeviceMode('desktop')}
@@ -154,20 +154,20 @@ export function BuilderToolbar({
154
154
  </div>
155
155
 
156
156
  {/* Divider */}
157
- <div className="w-px h-6 bg-border" />
157
+ <div className="bg-border h-6 w-px" />
158
158
 
159
159
  {/* AI Generate */}
160
160
  {onOpenAI && (
161
161
  <>
162
162
  <button
163
163
  onClick={onOpenAI}
164
- className="flex items-center gap-1.5 px-2.5 py-1.5 text-sm font-medium text-primary bg-primary/10 rounded-md hover:bg-primary/20 transition-colors"
164
+ className="text-primary bg-primary/10 hover:bg-primary/20 flex items-center gap-1.5 rounded-md px-2.5 py-1.5 text-sm font-medium transition-colors"
165
165
  aria-label="Generate page with AI"
166
166
  >
167
167
  <Sparkles size={14} />
168
168
  <span className="hidden sm:inline">AI</span>
169
169
  </button>
170
- <div className="w-px h-6 bg-border" />
170
+ <div className="bg-border h-6 w-px" />
171
171
  </>
172
172
  )}
173
173
 
@@ -176,7 +176,7 @@ export function BuilderToolbar({
176
176
  <button
177
177
  onClick={onSave}
178
178
  disabled={saving || !dirty}
179
- className="bg-muted text-muted-foreground rounded-md px-3 py-1.5 text-sm font-medium hover:bg-muted/80 disabled:opacity-50 disabled:pointer-events-none transition-colors flex items-center gap-1.5"
179
+ className="bg-muted text-muted-foreground hover:bg-muted/80 flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50"
180
180
  >
181
181
  {saving && <Loader2 size={14} className="animate-spin" />}
182
182
  {saving ? 'Saving...' : 'Save'}
@@ -184,7 +184,7 @@ export function BuilderToolbar({
184
184
  <button
185
185
  onClick={onPublish}
186
186
  disabled={saving}
187
- className="bg-primary text-primary-foreground rounded-md px-3 py-1.5 text-sm font-medium hover:bg-primary/90 disabled:opacity-50 disabled:pointer-events-none transition-colors"
187
+ className="bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50"
188
188
  >
189
189
  Publish
190
190
  </button>
@@ -207,7 +207,7 @@ function DeviceButton({
207
207
  return (
208
208
  <button
209
209
  onClick={onClick}
210
- className={`p-1.5 rounded-md transition-colors ${
210
+ className={`rounded-md p-1.5 transition-colors ${
211
211
  active
212
212
  ? 'bg-background text-foreground shadow-sm'
213
213
  : 'text-muted-foreground hover:text-foreground'
@@ -72,19 +72,19 @@ export function ContextPanel({
72
72
  }, [activeTab, availableTabs, selectedNode])
73
73
 
74
74
  return (
75
- <div className="w-full h-full bg-card overflow-y-auto">
75
+ <div className="bg-card h-full w-full overflow-y-auto">
76
76
  <Tabs.Root
77
77
  value={effectiveTab}
78
78
  onValueChange={(value) => onTabChange(value as ContextPanelProps['activeTab'])}
79
79
  >
80
- <Tabs.List className="flex border-b border-border bg-muted/30">
80
+ <Tabs.List className="border-border bg-muted/30 flex border-b">
81
81
  {availableTabs.map((tab) => {
82
82
  const Icon = tab.icon
83
83
  return (
84
84
  <Tabs.Trigger
85
85
  key={tab.value}
86
86
  value={tab.value}
87
- className="flex-1 flex items-center justify-center gap-1.5 px-2 py-2.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-b-2 data-[state=active]:border-primary data-[state=active]:bg-background"
87
+ className="text-muted-foreground hover:text-foreground data-[state=active]:text-foreground data-[state=active]:border-primary data-[state=active]:bg-background flex flex-1 items-center justify-center gap-1.5 px-2 py-2.5 text-xs font-medium transition-colors data-[state=active]:border-b-2"
88
88
  >
89
89
  <Icon size={14} />
90
90
  <span>{tab.label}</span>
@@ -53,11 +53,11 @@ function getRingStrokeColor(score: number): string {
53
53
  function StatusIcon({ status }: { status: BuilderDesignCheck['status'] }) {
54
54
  switch (status) {
55
55
  case 'good':
56
- return <CheckCircle2 size={14} className="text-green-500 shrink-0" />
56
+ return <CheckCircle2 size={14} className="shrink-0 text-green-500" />
57
57
  case 'warning':
58
- return <AlertCircle size={14} className="text-amber-500 shrink-0" />
58
+ return <AlertCircle size={14} className="shrink-0 text-amber-500" />
59
59
  case 'error':
60
- return <XCircle size={14} className="text-red-500 shrink-0" />
60
+ return <XCircle size={14} className="shrink-0 text-red-500" />
61
61
  }
62
62
  }
63
63
 
@@ -69,7 +69,7 @@ function SeverityBadge({ severity }: { severity: DesignSuggestion['severity'] })
69
69
  }
70
70
 
71
71
  return (
72
- <span className={`inline-block px-1.5 py-0.5 rounded text-xs font-medium ${classes[severity]}`}>
72
+ <span className={`inline-block rounded px-1.5 py-0.5 text-xs font-medium ${classes[severity]}`}>
73
73
  {severity}
74
74
  </span>
75
75
  )
@@ -112,7 +112,7 @@ function ScoreRing({ score }: { score: number }) {
112
112
  <span className={`text-lg font-medium ${getScoreColor(score, 100)}`}>{score}</span>
113
113
  </div>
114
114
  </div>
115
- <span className="text-xs text-muted-foreground">{getScoreLabel(score)}</span>
115
+ <span className="text-muted-foreground text-xs">{getScoreLabel(score)}</span>
116
116
  </div>
117
117
  )
118
118
  }
@@ -129,17 +129,17 @@ function CategoryRow({
129
129
  const percentage = category.maxScore > 0 ? (category.score / category.maxScore) * 100 : 0
130
130
 
131
131
  return (
132
- <div className="border-b border-border last:border-b-0">
132
+ <div className="border-border border-b last:border-b-0">
133
133
  <button
134
134
  type="button"
135
- className="w-full text-left px-4 py-3 flex flex-col gap-2 hover:bg-muted/50 transition-colors"
135
+ className="hover:bg-muted/50 flex w-full flex-col gap-2 px-4 py-3 text-left transition-colors"
136
136
  onClick={onToggle}
137
137
  aria-expanded={expanded}
138
138
  >
139
139
  <div className="flex items-center justify-between">
140
- <span className="text-xs font-medium text-foreground">{category.label}</span>
140
+ <span className="text-foreground text-xs font-medium">{category.label}</span>
141
141
  <div className="flex items-center gap-2">
142
- <span className="text-xs text-muted-foreground">
142
+ <span className="text-muted-foreground text-xs">
143
143
  {category.score}/{category.maxScore}
144
144
  </span>
145
145
  {expanded ? (
@@ -149,7 +149,7 @@ function CategoryRow({
149
149
  )}
150
150
  </div>
151
151
  </div>
152
- <div className="w-full h-1.5 rounded-full bg-muted overflow-hidden">
152
+ <div className="bg-muted h-1.5 w-full overflow-hidden rounded-full">
153
153
  <div
154
154
  className={`h-full rounded-full transition-all duration-500 ease-out ${getBarColor(category.score, category.maxScore)}`}
155
155
  style={{ width: `${percentage}%` }}
@@ -158,13 +158,13 @@ function CategoryRow({
158
158
  </button>
159
159
 
160
160
  {expanded && category.checks.length > 0 && (
161
- <div className="px-4 pb-3 flex flex-col gap-2">
161
+ <div className="flex flex-col gap-2 px-4 pb-3">
162
162
  {category.checks.map((check) => (
163
163
  <div key={check.id} className="flex items-start gap-2 pl-1">
164
164
  <StatusIcon status={check.status} />
165
165
  <div className="flex flex-col">
166
- <span className="text-xs font-medium text-foreground">{check.label}</span>
167
- <span className="text-xs text-muted-foreground">{check.detail}</span>
166
+ <span className="text-foreground text-xs font-medium">{check.label}</span>
167
+ <span className="text-muted-foreground text-xs">{check.detail}</span>
168
168
  </div>
169
169
  </div>
170
170
  ))}
@@ -187,16 +187,16 @@ function SuggestionsList({ suggestions }: { suggestions: DesignSuggestion[] }) {
187
187
  if (sorted.length === 0) return null
188
188
 
189
189
  return (
190
- <div className="px-4 py-3 border-t border-border">
191
- <div className="flex items-center gap-2 mb-3">
190
+ <div className="border-border border-t px-4 py-3">
191
+ <div className="mb-3 flex items-center gap-2">
192
192
  <Lightbulb size={14} className="text-muted-foreground" />
193
- <span className="text-xs font-medium text-foreground">Suggestions</span>
193
+ <span className="text-foreground text-xs font-medium">Suggestions</span>
194
194
  </div>
195
195
  <div className="flex flex-col gap-2.5">
196
196
  {sorted.map((suggestion) => (
197
197
  <div key={suggestion.id} className="flex items-start gap-2">
198
198
  <SeverityBadge severity={suggestion.severity} />
199
- <span className="text-xs text-muted-foreground leading-relaxed">
199
+ <span className="text-muted-foreground text-xs leading-relaxed">
200
200
  {suggestion.message}
201
201
  </span>
202
202
  </div>
@@ -218,10 +218,10 @@ export function DesignScorePanel({ tree }: DesignScorePanelProps) {
218
218
 
219
219
  if (!tree.children || tree.children.length === 0) {
220
220
  return (
221
- <div className="p-6 flex flex-col items-center justify-center text-center min-h-[200px]">
221
+ <div className="flex min-h-[200px] flex-col items-center justify-center p-6 text-center">
222
222
  <Palette size={32} className="text-muted-foreground mb-3" />
223
- <p className="text-sm font-medium text-foreground mb-1">Design Score</p>
224
- <p className="text-xs text-muted-foreground">
223
+ <p className="text-foreground mb-1 text-sm font-medium">Design Score</p>
224
+ <p className="text-muted-foreground text-xs">
225
225
  Add sections to your page to see the design analysis
226
226
  </p>
227
227
  </div>
@@ -230,7 +230,7 @@ export function DesignScorePanel({ tree }: DesignScorePanelProps) {
230
230
 
231
231
  return (
232
232
  <div className="flex flex-col">
233
- <div className="flex flex-col items-center py-5 border-b border-border">
233
+ <div className="border-border flex flex-col items-center border-b py-5">
234
234
  <ScoreRing score={analysis.score} />
235
235
  </div>
236
236