@actuate-media/cms-admin 0.64.0 → 0.66.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 (196) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/__tests__/components/ui-primitives.test.d.ts +2 -0
  3. package/dist/__tests__/components/ui-primitives.test.d.ts.map +1 -0
  4. package/dist/__tests__/components/ui-primitives.test.js +45 -0
  5. package/dist/__tests__/components/ui-primitives.test.js.map +1 -0
  6. package/dist/__tests__/views/updates-tab.render.test.js +1 -1
  7. package/dist/__tests__/views/updates-tab.render.test.js.map +1 -1
  8. package/dist/actuate-admin.css +1 -1
  9. package/dist/components/SEOPanel.d.ts.map +1 -1
  10. package/dist/components/SEOPanel.js +2 -1
  11. package/dist/components/SEOPanel.js.map +1 -1
  12. package/dist/components/forms/primitives.d.ts.map +1 -1
  13. package/dist/components/forms/primitives.js +5 -8
  14. package/dist/components/forms/primitives.js.map +1 -1
  15. package/dist/components/posts/badges.d.ts.map +1 -1
  16. package/dist/components/posts/badges.js +7 -13
  17. package/dist/components/posts/badges.js.map +1 -1
  18. package/dist/components/seo/RedirectEditorDrawer.d.ts.map +1 -1
  19. package/dist/components/seo/RedirectEditorDrawer.js +2 -1
  20. package/dist/components/seo/RedirectEditorDrawer.js.map +1 -1
  21. package/dist/components/seo/SeoEditorDrawer.d.ts.map +1 -1
  22. package/dist/components/seo/SeoEditorDrawer.js +3 -2
  23. package/dist/components/seo/SeoEditorDrawer.js.map +1 -1
  24. package/dist/components/seo/primitives.d.ts.map +1 -1
  25. package/dist/components/seo/primitives.js +9 -14
  26. package/dist/components/seo/primitives.js.map +1 -1
  27. package/dist/components/ui/FilterPill.d.ts +14 -0
  28. package/dist/components/ui/FilterPill.d.ts.map +1 -0
  29. package/dist/components/ui/FilterPill.js +8 -0
  30. package/dist/components/ui/FilterPill.js.map +1 -0
  31. package/dist/components/ui/RowActions.d.ts +19 -0
  32. package/dist/components/ui/RowActions.d.ts.map +1 -0
  33. package/dist/components/ui/RowActions.js +16 -0
  34. package/dist/components/ui/RowActions.js.map +1 -0
  35. package/dist/components/ui/StatPill.d.ts +18 -0
  36. package/dist/components/ui/StatPill.d.ts.map +1 -0
  37. package/dist/components/ui/StatPill.js +5 -0
  38. package/dist/components/ui/StatPill.js.map +1 -0
  39. package/dist/components/ui/StatusBadge.d.ts +25 -0
  40. package/dist/components/ui/StatusBadge.d.ts.map +1 -0
  41. package/dist/components/ui/StatusBadge.js +41 -0
  42. package/dist/components/ui/StatusBadge.js.map +1 -0
  43. package/dist/components/ui/index.d.ts +8 -0
  44. package/dist/components/ui/index.d.ts.map +1 -1
  45. package/dist/components/ui/index.js +4 -0
  46. package/dist/components/ui/index.js.map +1 -1
  47. package/dist/fields/PropInput.d.ts.map +1 -1
  48. package/dist/fields/PropInput.js +2 -1
  49. package/dist/fields/PropInput.js.map +1 -1
  50. package/dist/fields/ToggleField.d.ts.map +1 -1
  51. package/dist/fields/ToggleField.js +2 -1
  52. package/dist/fields/ToggleField.js.map +1 -1
  53. package/dist/layout/Header.js +1 -1
  54. package/dist/layout/Header.js.map +1 -1
  55. package/dist/layout/Layout.js +8 -38
  56. package/dist/layout/Layout.js.map +1 -1
  57. package/dist/layout/primitives/PageContainer.d.ts.map +1 -1
  58. package/dist/layout/primitives/PageContainer.js +1 -1
  59. package/dist/layout/primitives/PageContainer.js.map +1 -1
  60. package/dist/lib/pages-service.d.ts +9 -0
  61. package/dist/lib/pages-service.d.ts.map +1 -1
  62. package/dist/lib/pages-service.js +14 -0
  63. package/dist/lib/pages-service.js.map +1 -1
  64. package/dist/lib/posts-service.d.ts +11 -0
  65. package/dist/lib/posts-service.d.ts.map +1 -1
  66. package/dist/lib/posts-service.js +13 -0
  67. package/dist/lib/posts-service.js.map +1 -1
  68. package/dist/lib/seo-service.d.ts +3 -0
  69. package/dist/lib/seo-service.d.ts.map +1 -1
  70. package/dist/lib/seo-service.js.map +1 -1
  71. package/dist/views/Dashboard.d.ts.map +1 -1
  72. package/dist/views/Dashboard.js +9 -1
  73. package/dist/views/Dashboard.js.map +1 -1
  74. package/dist/views/FormEditor.d.ts.map +1 -1
  75. package/dist/views/FormEditor.js +2 -1
  76. package/dist/views/FormEditor.js.map +1 -1
  77. package/dist/views/FormEntries.js +1 -1
  78. package/dist/views/FormEntries.js.map +1 -1
  79. package/dist/views/FormSubmissions.js +1 -1
  80. package/dist/views/FormSubmissions.js.map +1 -1
  81. package/dist/views/Forms.js +1 -1
  82. package/dist/views/Forms.js.map +1 -1
  83. package/dist/views/MediaBrowser.d.ts.map +1 -1
  84. package/dist/views/MediaBrowser.js +30 -2
  85. package/dist/views/MediaBrowser.js.map +1 -1
  86. package/dist/views/Pages/PageTagManager.d.ts.map +1 -1
  87. package/dist/views/Pages/PageTagManager.js +1 -1
  88. package/dist/views/Pages/PageTagManager.js.map +1 -1
  89. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  90. package/dist/views/Pages/PagesListView.js +59 -10
  91. package/dist/views/Pages/PagesListView.js.map +1 -1
  92. package/dist/views/Pages.js +1 -1
  93. package/dist/views/Pages.js.map +1 -1
  94. package/dist/views/Posts/NewPostPicker.d.ts.map +1 -1
  95. package/dist/views/Posts/NewPostPicker.js +1 -1
  96. package/dist/views/Posts/NewPostPicker.js.map +1 -1
  97. package/dist/views/Posts/NewPostTypeInstructions.d.ts.map +1 -1
  98. package/dist/views/Posts/NewPostTypeInstructions.js +1 -1
  99. package/dist/views/Posts/NewPostTypeInstructions.js.map +1 -1
  100. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  101. package/dist/views/Posts/PostTypesView.js +1 -1
  102. package/dist/views/Posts/PostTypesView.js.map +1 -1
  103. package/dist/views/Posts/PostsListView.d.ts.map +1 -1
  104. package/dist/views/Posts/PostsListView.js +66 -9
  105. package/dist/views/Posts/PostsListView.js.map +1 -1
  106. package/dist/views/Profile.js +1 -1
  107. package/dist/views/Profile.js.map +1 -1
  108. package/dist/views/Redirects.js +1 -1
  109. package/dist/views/Redirects.js.map +1 -1
  110. package/dist/views/SEO.js +1 -1
  111. package/dist/views/SEO.js.map +1 -1
  112. package/dist/views/ScriptTagEditor.d.ts.map +1 -1
  113. package/dist/views/ScriptTagEditor.js +1 -1
  114. package/dist/views/ScriptTagEditor.js.map +1 -1
  115. package/dist/views/ScriptTags.d.ts.map +1 -1
  116. package/dist/views/ScriptTags.js +2 -1
  117. package/dist/views/ScriptTags.js.map +1 -1
  118. package/dist/views/Settings.js +1 -1
  119. package/dist/views/Settings.js.map +1 -1
  120. package/dist/views/Users.d.ts.map +1 -1
  121. package/dist/views/Users.js +2 -6
  122. package/dist/views/Users.js.map +1 -1
  123. package/dist/views/page-builder/BlockEditor.d.ts.map +1 -1
  124. package/dist/views/page-builder/BlockEditor.js +2 -2
  125. package/dist/views/page-builder/BlockEditor.js.map +1 -1
  126. package/dist/views/page-builder/NodeSettings.js +3 -3
  127. package/dist/views/page-builder/NodeSettings.js.map +1 -1
  128. package/dist/views/page-builder/PageTemplates.js +1 -1
  129. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  130. package/dist/views/page-builder/SavedSections.js +2 -2
  131. package/dist/views/page-builder/SavedSections.js.map +1 -1
  132. package/dist/views/page-builder/Widgets.js +1 -1
  133. package/dist/views/page-builder/Widgets.js.map +1 -1
  134. package/dist/views/page-editor/SectionInspector.d.ts.map +1 -1
  135. package/dist/views/page-editor/SectionInspector.js +2 -1
  136. package/dist/views/page-editor/SectionInspector.js.map +1 -1
  137. package/dist/views/post-editor/PostHeaderPanel.d.ts.map +1 -1
  138. package/dist/views/post-editor/PostHeaderPanel.js +2 -1
  139. package/dist/views/post-editor/PostHeaderPanel.js.map +1 -1
  140. package/dist/views/seo/TechnicalTab.d.ts.map +1 -1
  141. package/dist/views/seo/TechnicalTab.js +15 -0
  142. package/dist/views/seo/TechnicalTab.js.map +1 -1
  143. package/dist/views/settings/components.d.ts.map +1 -1
  144. package/dist/views/settings/components.js +2 -1
  145. package/dist/views/settings/components.js.map +1 -1
  146. package/package.json +2 -2
  147. package/src/__tests__/components/ui-primitives.test.tsx +58 -0
  148. package/src/__tests__/views/updates-tab.render.test.tsx +2 -1
  149. package/src/components/SEOPanel.tsx +2 -11
  150. package/src/components/forms/primitives.tsx +6 -16
  151. package/src/components/posts/badges.tsx +8 -21
  152. package/src/components/seo/RedirectEditorDrawer.tsx +12 -16
  153. package/src/components/seo/SeoEditorDrawer.tsx +16 -24
  154. package/src/components/seo/primitives.tsx +10 -27
  155. package/src/components/ui/FilterPill.tsx +43 -0
  156. package/src/components/ui/RowActions.tsx +50 -0
  157. package/src/components/ui/StatPill.tsx +37 -0
  158. package/src/components/ui/StatusBadge.tsx +66 -0
  159. package/src/components/ui/index.ts +8 -0
  160. package/src/fields/PropInput.tsx +6 -15
  161. package/src/fields/ToggleField.tsx +3 -15
  162. package/src/layout/Header.tsx +2 -2
  163. package/src/layout/Layout.tsx +8 -80
  164. package/src/layout/primitives/PageContainer.tsx +1 -5
  165. package/src/lib/pages-service.ts +18 -0
  166. package/src/lib/posts-service.ts +26 -0
  167. package/src/lib/seo-service.ts +3 -0
  168. package/src/views/Dashboard.tsx +48 -18
  169. package/src/views/FormEditor.tsx +6 -9
  170. package/src/views/FormEntries.tsx +1 -1
  171. package/src/views/FormSubmissions.tsx +1 -1
  172. package/src/views/Forms.tsx +1 -1
  173. package/src/views/MediaBrowser.tsx +36 -8
  174. package/src/views/Pages/PageTagManager.tsx +1 -3
  175. package/src/views/Pages/PagesListView.tsx +115 -10
  176. package/src/views/Pages.tsx +1 -1
  177. package/src/views/Posts/NewPostPicker.tsx +1 -3
  178. package/src/views/Posts/NewPostTypeInstructions.tsx +1 -3
  179. package/src/views/Posts/PostTypesView.tsx +1 -3
  180. package/src/views/Posts/PostsListView.tsx +135 -10
  181. package/src/views/Profile.tsx +1 -1
  182. package/src/views/Redirects.tsx +1 -1
  183. package/src/views/SEO.tsx +1 -1
  184. package/src/views/ScriptTagEditor.tsx +1 -3
  185. package/src/views/ScriptTags.tsx +17 -1
  186. package/src/views/Settings.tsx +1 -1
  187. package/src/views/Users.tsx +6 -18
  188. package/src/views/page-builder/BlockEditor.tsx +3 -6
  189. package/src/views/page-builder/NodeSettings.tsx +7 -16
  190. package/src/views/page-builder/PageTemplates.tsx +1 -1
  191. package/src/views/page-builder/SavedSections.tsx +2 -2
  192. package/src/views/page-builder/Widgets.tsx +1 -1
  193. package/src/views/page-editor/SectionInspector.tsx +9 -21
  194. package/src/views/post-editor/PostHeaderPanel.tsx +10 -20
  195. package/src/views/seo/TechnicalTab.tsx +15 -0
  196. package/src/views/settings/components.tsx +8 -16
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import * as Dialog from '@radix-ui/react-dialog';
4
4
  import { AlertTriangle, Check, Loader2, Lock } from 'lucide-react';
5
5
  import { useId } from 'react';
6
6
  import { Card, CardContent, CardDescription, CardHeader } from '../../components/ui/Card.js';
7
+ import { Toggle } from '../../components/ui/Toggle.js';
7
8
  import { adminPortalContainer } from '../../lib/portal-container.js';
8
9
  /**
9
10
  * The canonical Settings section card: a bordered `bg-card` surface with a
@@ -53,7 +54,7 @@ export function SettingsSourceBadge({ meta }) {
53
54
  }
54
55
  /** A labelled switch row with description, used for the SEO defaults. */
55
56
  export function SettingsToggleRow({ label, description, checked, onChange, disabled = false, badge, }) {
56
- return (_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-foreground text-base font-medium", children: label }), badge] }), _jsx("p", { className: "text-muted-foreground mt-0.5 text-sm", children: description })] }), _jsx("button", { type: "button", role: "switch", "aria-checked": checked, "aria-label": label, disabled: disabled, onClick: () => onChange(!checked), className: `focus-visible:ring-ring relative mt-0.5 h-6 w-11 shrink-0 rounded-full transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${checked ? 'bg-brand' : 'bg-switch-background'}`, children: _jsx("span", { className: `bg-card absolute top-0.5 block h-5 w-5 rounded-full shadow-sm transition-transform ${checked ? 'translate-x-[22px]' : 'translate-x-0.5'}` }) })] }));
57
+ return (_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-foreground text-base font-medium", children: label }), badge] }), _jsx("p", { className: "text-muted-foreground mt-0.5 text-sm", children: description })] }), _jsx("div", { className: "mt-0.5 shrink-0", children: _jsx(Toggle, { checked: checked, onCheckedChange: onChange, disabled: disabled, "aria-label": label }) })] }));
57
58
  }
58
59
  /** Aggregated validation messages shown above the cards. */
59
60
  export function SettingsValidationSummary({ issues }) {
@@ -1 +1 @@
1
- {"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,KAAK,EAAkB,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC5F,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAGpE;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,OAAO,EACP,QAAQ,EACR,SAAS,EACT,YAAY,EAAE,OAAO,GAAG,IAAI,GAU7B;IACC,MAAM,SAAS,GAAG,KAAK,EAAE,CAAA;IACzB,OAAO,CACL,MAAC,IAAI,IAAC,OAAO,EAAC,MAAM,qBAAkB,SAAS,EAAE,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,SAAS,aACjF,MAAC,UAAU,IAAC,SAAS,EAAC,wCAAwC,aAC5D,eAAK,SAAS,EAAC,SAAS,aACtB,KAAC,OAAO,IACN,EAAE,EAAE,SAAS,EACb,SAAS,EAAC,8DAA8D,YAEvE,KAAK,GACE,EACT,WAAW,IAAI,KAAC,eAAe,cAAE,WAAW,GAAmB,IAC5D,EACL,OAAO,IAAI,cAAK,SAAS,EAAC,kCAAkC,YAAE,OAAO,GAAO,IAClE,EACb,KAAC,WAAW,IAAC,SAAS,EAAC,wBAAwB,YAAE,QAAQ,GAAe,IACnE,CACR,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,GAMV;IACC,OAAO,CACL,eAAK,SAAS,EAAE,+BAA+B,SAAS,IAAI,EAAE,EAAE,aAC9D,cAAK,SAAS,EAAC,uCAAuC,YAAE,KAAK,GAAO,EACnE,WAAW,IAAI,YAAG,SAAS,EAAC,sCAAsC,YAAE,WAAW,GAAK,EACpF,QAAQ,IACL,CACP,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,GAAG,QAAQ,EAChB,SAAS,GAaV;IACC,MAAM,UAAU,GAAG,6CAA6C,CAAA;IAChE,OAAO,CACL,eACE,SAAS,EAAE,8BAA8B,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,IAAI,SAAS,IAAI,EAAE,EAAE,aAEjH,eAAK,SAAS,EAAC,iCAAiC,aAC7C,OAAO,EACR,eAAK,SAAS,EAAC,SAAS,aACrB,OAAO,CAAC,CAAC,CAAC,CACT,gBAAO,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,YAC3C,KAAK,GACA,CACT,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAE,UAAU,YAAG,KAAK,GAAQ,CAC5C,EACA,WAAW,IAAI,YAAG,SAAS,EAAC,sCAAsC,YAAE,WAAW,GAAK,IACjF,IACF,EACN,cAAK,SAAS,EAAC,kCAAkC,YAAE,OAAO,GAAO,IAC7D,CACP,CAAA;AACH,CAAC;AAED,MAAM,YAAY,GAAqD;IACrE,MAAM,EAAE,gBAAgB;IACxB,WAAW,EAAE,qBAAqB;IAClC,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,gBAAgB;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAA;AAED,8DAA8D;AAC9D,MAAM,UAAU,mBAAmB,CAAC,EAAE,IAAI,EAAqC;IAC7E,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAA;IACvE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAA;IAC7B,OAAO,CACL,gBACE,SAAS,EAAC,qHAAqH,EAC/H,KAAK,EAAE,IAAI,CAAC,MAAM,aAEjB,MAAM,IAAI,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,EAC/C,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IACrB,CACR,CAAA;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,EAChC,KAAK,EACL,WAAW,EACX,OAAO,EACP,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,KAAK,GAQN;IACC,OAAO,CACL,eAAK,SAAS,EAAC,wCAAwC,aACrD,eAAK,SAAS,EAAC,QAAQ,aACrB,eAAK,SAAS,EAAC,yBAAyB,aACtC,eAAM,SAAS,EAAC,uCAAuC,YAAE,KAAK,GAAQ,EACrE,KAAK,IACF,EACN,YAAG,SAAS,EAAC,sCAAsC,YAAE,WAAW,GAAK,IACjE,EACN,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,MAAM,IACL,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,QAAQ,EACzB,QAAQ,EAAE,QAAQ,gBACN,KAAK,GACjB,GACE,IACF,CACP,CAAA;AACH,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,yBAAyB,CAAC,EAAE,MAAM,EAAiC;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAA;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAA;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;IACjC,OAAO,CACL,eACE,IAAI,EAAC,OAAO,eACF,QAAQ,EAClB,SAAS,EAAE,wDACT,OAAO;YACL,CAAC,CAAC,0DAA0D;YAC5D,CAAC,CAAC,8CACN,EAAE,aAEF,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,iBAAiB,iBAAa,MAAM,GAAG,EAC1E,cAAK,SAAS,EAAC,WAAW,YACvB,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAC1C,sBAAgC,KAAK,CAAC,OAAO,IAArC,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,EAAE,CAAqB,CACnD,CAAC,GACE,IACF,CACP,CAAA;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,eAAe,CAAC,EAC9B,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,OAAO,GAQR;IACC,MAAM,MAAM,GAAG,SAAS,KAAK,QAAQ,CAAA;IACrC,OAAO,CACL,eAAK,SAAS,EAAC,qHAAqH,aACjI,SAAS,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CACpC,gBAAM,SAAS,EAAC,gDAAgD,eAAW,QAAQ,aACjF,KAAC,KAAK,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,cACjC,CACR,EACA,KAAK,IAAI,CAAC,MAAM,IAAI,CACnB,eAAM,SAAS,EAAC,+BAA+B,eAAW,QAAQ,gCAE3D,CACR,EACD,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,KAAK,IAAI,MAAM,EAC1B,SAAS,EAAC,8IAA8I,sBAGjJ,EACT,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,SAAS,IAAI,MAAM,EACnD,SAAS,EAAC,sQAAsQ,aAE/Q,MAAM,IAAI,KAAC,OAAO,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,cAAc,iBAAa,MAAM,GAAG,EAC3E,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,IAC7B,IACL,CACP,CAAA;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,6BAA6B,CAAC,EAC5C,IAAI,EACJ,KAAK,EACL,WAAW,EACX,YAAY,GAAG,UAAU,EACzB,SAAS,EACT,QAAQ,GAQT;IACC,OAAO,CACL,KAAC,MAAM,CAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,YAC5D,MAAC,MAAM,CAAC,MAAM,IAAC,SAAS,EAAE,oBAAoB,EAAE,aAC9C,KAAC,MAAM,CAAC,OAAO,IAAC,SAAS,EAAC,gCAAgC,GAAG,EAC7D,MAAC,MAAM,CAAC,OAAO,IAAC,SAAS,EAAC,qIAAqI,aAC7J,eAAK,SAAS,EAAC,8BAA8B,aAC3C,eAAM,SAAS,EAAC,kFAAkF,YAChG,KAAC,aAAa,IAAC,IAAI,EAAE,EAAE,iBAAc,MAAM,GAAG,GACzC,EACP,KAAC,MAAM,CAAC,KAAK,IAAC,SAAS,EAAC,qCAAqC,YAAE,KAAK,GAAgB,IAChF,EACN,KAAC,MAAM,CAAC,WAAW,IAAC,SAAS,EAAC,oCAAoC,YAC/D,WAAW,GACO,EACrB,eAAK,SAAS,EAAC,qCAAqC,aAClD,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,uGAAuG,uBAG1G,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,SAAS,EAClB,SAAS,EAAC,2HAA2H,YAEpI,YAAY,GACN,IACL,IACS,IACH,GACJ,CACf,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-admin",
3
- "version": "0.64.0",
3
+ "version": "0.66.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",
@@ -95,7 +95,7 @@
95
95
  "tailwindcss": "^4.0.0",
96
96
  "typescript": "^5.7.0",
97
97
  "vitest": "^4.1.0",
98
- "@actuate-media/cms-core": "0.85.2",
98
+ "@actuate-media/cms-core": "0.86.0",
99
99
  "@actuate-media/component-blocks": "0.2.1"
100
100
  },
101
101
  "scripts": {
@@ -0,0 +1,58 @@
1
+ // @vitest-environment happy-dom
2
+ import { describe, expect, it, vi } from 'vitest'
3
+ import { render, screen } from '@testing-library/react'
4
+ import { StatusBadge } from '../../components/ui/StatusBadge.js'
5
+ import { FilterPill } from '../../components/ui/FilterPill.js'
6
+ import { StatPill } from '../../components/ui/StatPill.js'
7
+
8
+ describe('StatusBadge', () => {
9
+ it('renders the label with a leading dot by default', () => {
10
+ const { container } = render(<StatusBadge tone="success">Published</StatusBadge>)
11
+ expect(screen.getByText('Published')).toBeTruthy()
12
+ expect(container.querySelectorAll('[aria-hidden]')).toHaveLength(1)
13
+ })
14
+ it('omits the dot when dot={false}', () => {
15
+ const { container } = render(
16
+ <StatusBadge tone="neutral" dot={false}>
17
+ Draft
18
+ </StatusBadge>,
19
+ )
20
+ expect(container.querySelectorAll('[aria-hidden]')).toHaveLength(0)
21
+ })
22
+ it('forwards aria-label for screen readers', () => {
23
+ const { container } = render(
24
+ <StatusBadge tone="warning" aria-label="Status: Scheduled">
25
+ Scheduled
26
+ </StatusBadge>,
27
+ )
28
+ expect(container.querySelector('[aria-label="Status: Scheduled"]')).toBeTruthy()
29
+ })
30
+ })
31
+
32
+ describe('FilterPill', () => {
33
+ it('exposes active state via aria-pressed and fires onClick', () => {
34
+ const onClick = vi.fn()
35
+ render(
36
+ <FilterPill active onClick={onClick}>
37
+ All
38
+ </FilterPill>,
39
+ )
40
+ const btn = screen.getByRole('button', { name: 'All' })
41
+ expect(btn.getAttribute('aria-pressed')).toBe('true')
42
+ btn.click()
43
+ expect(onClick).toHaveBeenCalledTimes(1)
44
+ })
45
+ it('renders an optional count', () => {
46
+ render(<FilterPill count={12}>Admin</FilterPill>)
47
+ expect(screen.getByText('12')).toBeTruthy()
48
+ expect(screen.getByRole('button', { name: /Admin/ }).getAttribute('aria-pressed')).toBe('false')
49
+ })
50
+ })
51
+
52
+ describe('StatPill', () => {
53
+ it('renders value and label', () => {
54
+ render(<StatPill value={8} label="Active" />)
55
+ expect(screen.getByText('8')).toBeTruthy()
56
+ expect(screen.getByText('Active')).toBeTruthy()
57
+ })
58
+ })
@@ -54,7 +54,8 @@ function updateAvailable(overrides: Record<string, unknown> = {}) {
54
54
  pluginCompatibility: [
55
55
  { name: '@actuate-media/plugin-seo', compatible: true, minVersion: '0.46.0' },
56
56
  ],
57
- updateCommand: 'npm update @actuate-media/cms-core',
57
+ updateCommand:
58
+ 'npx actuate upgrade && npm install && npx actuate db:sync && npx prisma migrate deploy',
58
59
  canManage: true,
59
60
  hasGithubToken: false,
60
61
  githubRepo: '',
@@ -22,6 +22,7 @@ import {
22
22
  Star,
23
23
  } from 'lucide-react'
24
24
  import { SEO_SCHEMA_TYPES } from '../lib/seo-service.js'
25
+ import { Toggle } from './ui/Toggle.js'
25
26
 
26
27
  export interface SEOData {
27
28
  metaTitle?: string
@@ -469,17 +470,7 @@ function ToggleSwitch({
469
470
  <label className="text-sm font-medium text-[var(--foreground)]">{label}</label>
470
471
  <p className="mt-0.5 text-xs text-[var(--muted-foreground)]">{description}</p>
471
472
  </div>
472
- <button
473
- type="button"
474
- role="switch"
475
- aria-checked={checked}
476
- onClick={() => onChange(!checked)}
477
- className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full transition-colors ${checked ? 'bg-[var(--primary)]' : 'bg-[var(--muted)]'}`}
478
- >
479
- <span
480
- className={`bg-card pointer-events-none mt-0.5 block h-5 w-5 rounded-full shadow-sm transition-transform ${checked ? 'translate-x-[22px]' : 'translate-x-0.5'}`}
481
- />
482
- </button>
473
+ <Toggle checked={checked} onCheckedChange={onChange} aria-label={label} />
483
474
  </div>
484
475
  )
485
476
  }
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import type { ReactNode } from 'react'
11
11
  import { AlertTriangle, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react'
12
+ import { StatusBadge, type StatusBadgeTone } from '../ui/StatusBadge.js'
12
13
  import type { FormFieldType, FormStatus } from '../../lib/forms-service.js'
13
14
 
14
15
  // ─── Field-type badges ─────────────────────────────────────────────────────
@@ -70,26 +71,15 @@ export function FieldTypeBadge({ type }: { type: FormFieldType }) {
70
71
 
71
72
  // ─── Status badges ─────────────────────────────────────────────────────────
72
73
 
73
- const STATUS_META: Record<FormStatus, { label: string; cls: string; dot: string }> = {
74
- active: { label: 'Active', cls: 'bg-success/10 text-success', dot: 'bg-success' },
75
- draft: { label: 'Draft', cls: 'bg-warning/10 text-warning', dot: 'bg-warning' },
76
- archived: {
77
- label: 'Archived',
78
- cls: 'bg-muted text-muted-foreground',
79
- dot: 'bg-muted-foreground',
80
- },
74
+ const STATUS_META: Record<FormStatus, { label: string; tone: StatusBadgeTone }> = {
75
+ active: { label: 'Active', tone: 'success' },
76
+ draft: { label: 'Draft', tone: 'warning' },
77
+ archived: { label: 'Archived', tone: 'muted' },
81
78
  }
82
79
 
83
80
  export function FormStatusBadge({ status }: { status: FormStatus }) {
84
81
  const meta = STATUS_META[status] ?? STATUS_META.draft
85
- return (
86
- <span
87
- className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium ${meta.cls}`}
88
- >
89
- <span className={`h-1.5 w-1.5 rounded-full ${meta.dot}`} aria-hidden />
90
- {meta.label}
91
- </span>
92
- )
82
+ return <StatusBadge tone={meta.tone}>{meta.label}</StatusBadge>
93
83
  }
94
84
 
95
85
  /** Small red count badge for unread submissions. Hidden when count is 0. */
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import type { ReactNode } from 'react'
4
+ import { StatusBadge, type StatusBadgeTone } from '../ui/StatusBadge.js'
4
5
  import type { PostStatus } from '../../lib/posts-service.js'
5
6
 
6
7
  /**
@@ -65,32 +66,18 @@ const STATUS_LABEL: Record<PostStatus, string> = {
65
66
  ARCHIVED: 'Archived',
66
67
  }
67
68
 
68
- const STATUS_PALETTE: Record<PostStatus, string> = {
69
- PUBLISHED: 'green',
70
- DRAFT: 'gray',
71
- SCHEDULED: 'orange',
72
- ARCHIVED: 'gray',
73
- }
74
-
75
- const STATUS_GLYPH: Record<PostStatus, string> = {
76
- PUBLISHED: '●',
77
- DRAFT: '○',
78
- SCHEDULED: '◐',
79
- ARCHIVED: '◌',
69
+ const STATUS_TONE: Record<PostStatus, StatusBadgeTone> = {
70
+ PUBLISHED: 'success',
71
+ DRAFT: 'neutral',
72
+ SCHEDULED: 'warning',
73
+ ARCHIVED: 'muted',
80
74
  }
81
75
 
82
76
  export function PostStatusBadge({ status }: { status: PostStatus }) {
83
- const p = paletteFor(STATUS_PALETTE[status])
84
77
  return (
85
- <span
86
- className={`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${p.bg} ${p.text}`}
87
- aria-label={`Status: ${STATUS_LABEL[status]}`}
88
- >
89
- <span aria-hidden className="text-[10px] leading-none">
90
- {STATUS_GLYPH[status]}
91
- </span>
78
+ <StatusBadge tone={STATUS_TONE[status]} aria-label={`Status: ${STATUS_LABEL[status]}`}>
92
79
  {STATUS_LABEL[status]}
93
- </span>
80
+ </StatusBadge>
94
81
  )
95
82
  }
96
83
 
@@ -11,6 +11,7 @@ import {
11
11
  } from '../../lib/seo-service.js'
12
12
  import { Drawer } from './Drawer.js'
13
13
  import { btnPrimary, btnSecondary } from './primitives.js'
14
+ import { Toggle } from '../ui/Toggle.js'
14
15
 
15
16
  const STATUS_CODES: { value: RedirectStatusCode; label: string }[] = [
16
17
  { value: 301, label: '301 — Permanent' },
@@ -197,19 +198,17 @@ export function RedirectEditorDrawer({
197
198
  </div>
198
199
 
199
200
  <div className="border-border space-y-3 rounded-lg border p-4">
200
- <label className="flex items-center justify-between gap-3">
201
+ <div className="flex items-center justify-between gap-3">
201
202
  <span className="text-foreground text-sm font-medium">Enabled</span>
202
- <input
203
- type="checkbox"
204
- role="switch"
205
- aria-checked={!!form.enabled}
203
+ <Toggle
206
204
  checked={!!form.enabled}
207
- onChange={(e) => update({ enabled: e.target.checked })}
208
- className="accent-primary h-4 w-4"
205
+ onCheckedChange={(v) => update({ enabled: v })}
206
+ variant="enabled"
207
+ aria-label="Enabled"
209
208
  />
210
- </label>
209
+ </div>
211
210
  {!isGone && (
212
- <label className="flex items-center justify-between gap-3">
211
+ <div className="flex items-center justify-between gap-3">
213
212
  <span className="min-w-0">
214
213
  <span className="text-foreground block text-sm font-medium">
215
214
  Preserve query string
@@ -218,15 +217,12 @@ export function RedirectEditorDrawer({
218
217
  Append the original query params to the destination.
219
218
  </span>
220
219
  </span>
221
- <input
222
- type="checkbox"
223
- role="switch"
224
- aria-checked={!!form.preserveQuery}
220
+ <Toggle
225
221
  checked={!!form.preserveQuery}
226
- onChange={(e) => update({ preserveQuery: e.target.checked })}
227
- className="accent-primary h-4 w-4 shrink-0"
222
+ onCheckedChange={(v) => update({ preserveQuery: v })}
223
+ aria-label="Preserve query string"
228
224
  />
229
- </label>
225
+ </div>
230
226
  )}
231
227
  </div>
232
228
  </div>
@@ -17,6 +17,7 @@ import { fixBrandVoiceContent } from '../../lib/brand-voice-client.js'
17
17
  import { BrandVoiceAlignmentBadge } from '../BrandVoiceAlignmentBadge.js'
18
18
  import { Drawer } from './Drawer.js'
19
19
  import { SeoLoading, SeoErrorState, btnPrimary, btnSecondary, gradeMeta } from './primitives.js'
20
+ import { Toggle } from '../ui/Toggle.js'
20
21
 
21
22
  const META_TITLE_MAX = 60
22
23
  const META_DESC_MAX = 160
@@ -422,38 +423,32 @@ export function SeoEditorDrawer({
422
423
 
423
424
  {/* Indexing toggles */}
424
425
  <div className="border-border space-y-3 rounded-lg border p-4">
425
- <label className="flex items-center justify-between gap-3">
426
+ <div className="flex items-center justify-between gap-3">
426
427
  <span className="min-w-0">
427
428
  <span className="text-foreground block text-sm font-medium">No-index</span>
428
429
  <span className="text-muted-foreground block text-sm">
429
430
  Hide this page from search engines.
430
431
  </span>
431
432
  </span>
432
- <input
433
- type="checkbox"
434
- role="switch"
435
- aria-checked={!!form.noindex}
433
+ <Toggle
436
434
  checked={!!form.noindex}
437
- onChange={(e) => update({ noindex: e.target.checked })}
438
- className="accent-primary h-4 w-4"
435
+ onCheckedChange={(v) => update({ noindex: v })}
436
+ aria-label="No-index"
439
437
  />
440
- </label>
441
- <label className="flex items-center justify-between gap-3">
438
+ </div>
439
+ <div className="flex items-center justify-between gap-3">
442
440
  <span className="min-w-0">
443
441
  <span className="text-foreground block text-sm font-medium">No-follow</span>
444
442
  <span className="text-muted-foreground block text-sm">
445
443
  Tell crawlers not to follow links on this page.
446
444
  </span>
447
445
  </span>
448
- <input
449
- type="checkbox"
450
- role="switch"
451
- aria-checked={!!form.nofollow}
446
+ <Toggle
452
447
  checked={!!form.nofollow}
453
- onChange={(e) => update({ nofollow: e.target.checked })}
454
- className="accent-primary h-4 w-4"
448
+ onCheckedChange={(v) => update({ nofollow: v })}
449
+ aria-label="No-follow"
455
450
  />
456
- </label>
451
+ </div>
457
452
  </div>
458
453
 
459
454
  {/* llms.txt curation */}
@@ -499,22 +494,19 @@ export function SeoEditorDrawer({
499
494
  placeholder="Defaults to the content type"
500
495
  />
501
496
  </Field>
502
- <label className="flex items-center justify-between gap-3">
497
+ <div className="flex items-center justify-between gap-3">
503
498
  <span className="min-w-0">
504
499
  <span className="text-foreground block text-sm font-medium">Optional</span>
505
500
  <span className="text-muted-foreground block text-sm">
506
501
  Group under “Optional” — agents skip these first when context is tight.
507
502
  </span>
508
503
  </span>
509
- <input
510
- type="checkbox"
511
- role="switch"
512
- aria-checked={!!form.llmsOptional}
504
+ <Toggle
513
505
  checked={!!form.llmsOptional}
514
- onChange={(e) => update({ llmsOptional: e.target.checked })}
515
- className="accent-primary h-4 w-4"
506
+ onCheckedChange={(v) => update({ llmsOptional: v })}
507
+ aria-label="Optional in llms.txt"
516
508
  />
517
- </label>
509
+ </div>
518
510
  </div>
519
511
 
520
512
  {/* Score summary */}
@@ -8,6 +8,7 @@
8
8
  import type { ReactNode } from 'react'
9
9
  import { AlertTriangle, Loader2 } from 'lucide-react'
10
10
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/Card.js'
11
+ import { StatusBadge, type StatusBadgeTone } from '../ui/StatusBadge.js'
11
12
  import type { SeoGrade, SeoSeverity } from '../../lib/seo-service.js'
12
13
 
13
14
  // ─── Grade + severity styling ────────────────────────────────────────
@@ -73,6 +74,14 @@ export function severityMeta(severity: SeoSeverity): GradeMeta {
73
74
 
74
75
  // ─── Badges + bars ───────────────────────────────────────────────────
75
76
 
77
+ const SEO_TONE: Record<'good' | 'fair' | 'poor' | 'critical' | 'neutral', StatusBadgeTone> = {
78
+ good: 'success',
79
+ fair: 'warning',
80
+ poor: 'danger',
81
+ critical: 'danger',
82
+ neutral: 'neutral',
83
+ }
84
+
76
85
  export function SeoStatusBadge({
77
86
  label,
78
87
  tone,
@@ -80,33 +89,7 @@ export function SeoStatusBadge({
80
89
  label: string
81
90
  tone: 'good' | 'fair' | 'poor' | 'critical' | 'neutral'
82
91
  }) {
83
- const cls =
84
- tone === 'good'
85
- ? 'bg-success/10 text-success'
86
- : tone === 'fair'
87
- ? 'bg-warning/10 text-warning'
88
- : tone === 'poor' || tone === 'critical'
89
- ? 'bg-destructive/10 text-destructive'
90
- : 'bg-muted text-muted-foreground'
91
- return (
92
- <span
93
- className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium ${cls}`}
94
- >
95
- <span
96
- className={`h-1.5 w-1.5 rounded-full ${
97
- tone === 'good'
98
- ? 'bg-success'
99
- : tone === 'fair'
100
- ? 'bg-warning'
101
- : tone === 'neutral'
102
- ? 'bg-muted-foreground'
103
- : 'bg-destructive'
104
- }`}
105
- aria-hidden
106
- />
107
- {label}
108
- </span>
109
- )
92
+ return <StatusBadge tone={SEO_TONE[tone]}>{label}</StatusBadge>
110
93
  }
111
94
 
112
95
  /** A horizontal score bar (0-100), coloured by grade. */
@@ -0,0 +1,43 @@
1
+ 'use client'
2
+
3
+ import type { ButtonHTMLAttributes, ReactNode } from 'react'
4
+
5
+ /**
6
+ * Design-system filter pill (`.pill` / `.pill.act`): bordered card-surface
7
+ * chip that fills with the accent color when active. Used for status / role /
8
+ * category filter rows above list views.
9
+ */
10
+ export interface FilterPillProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {
11
+ active?: boolean
12
+ /** Optional trailing count rendered in tabular numerals. */
13
+ count?: number
14
+ children: ReactNode
15
+ }
16
+
17
+ export function FilterPill({
18
+ active = false,
19
+ count,
20
+ className,
21
+ children,
22
+ ...rest
23
+ }: FilterPillProps) {
24
+ return (
25
+ <button
26
+ type="button"
27
+ aria-pressed={active}
28
+ className={`inline-flex items-center gap-1.5 rounded-[7px] border px-3 py-1.5 text-[12.5px] font-medium transition-colors duration-[var(--motion-fast)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none ${
29
+ active
30
+ ? 'border-[var(--acc)] bg-[var(--acc)] text-white'
31
+ : 'border-[var(--bdr)] bg-[var(--card)] text-[var(--sub)] hover:border-[var(--acc-m)] hover:text-[var(--acc)]'
32
+ } ${className ?? ''}`}
33
+ {...rest}
34
+ >
35
+ {children}
36
+ {count !== undefined && (
37
+ <span className={`tabular-nums ${active ? 'text-white/80' : 'text-[var(--muted)]'}`}>
38
+ {count}
39
+ </span>
40
+ )}
41
+ </button>
42
+ )
43
+ }
@@ -0,0 +1,50 @@
1
+ 'use client'
2
+
3
+ import type { ButtonHTMLAttributes, ReactNode } from 'react'
4
+
5
+ /**
6
+ * Design-system table row actions (`.row-actions` / `.ra-icon-btn`): a
7
+ * right-aligned cluster of 27px bordered icon buttons that fades in on row
8
+ * hover (the row must have the `group` class) and on keyboard focus.
9
+ */
10
+ export function RowActions({ children, className }: { children: ReactNode; className?: string }) {
11
+ return (
12
+ <div
13
+ className={`flex items-center justify-end gap-1 opacity-0 transition-opacity duration-[var(--motion-fast)] group-hover:opacity-100 focus-within:opacity-100 ${className ?? ''}`}
14
+ >
15
+ {children}
16
+ </div>
17
+ )
18
+ }
19
+
20
+ export interface RowActionButtonProps extends Omit<
21
+ ButtonHTMLAttributes<HTMLButtonElement>,
22
+ 'type'
23
+ > {
24
+ /** Accessible label — required, these are icon-only buttons. */
25
+ 'aria-label': string
26
+ /** Red hover treatment for destructive actions. */
27
+ danger?: boolean
28
+ children: ReactNode
29
+ }
30
+
31
+ export function RowActionButton({
32
+ danger = false,
33
+ className,
34
+ children,
35
+ ...rest
36
+ }: RowActionButtonProps) {
37
+ return (
38
+ <button
39
+ type="button"
40
+ className={`flex h-[27px] w-[27px] items-center justify-center rounded-[6px] border border-[var(--bdr)] bg-[var(--card)] text-[var(--muted)] transition-colors duration-[var(--motion-fast)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 ${
41
+ danger
42
+ ? 'hover:border-[var(--err)] hover:bg-[var(--err-l)] hover:text-[var(--err)]'
43
+ : 'hover:border-[var(--acc-m)] hover:bg-[var(--acc-l)] hover:text-[var(--acc)]'
44
+ } ${className ?? ''}`}
45
+ {...rest}
46
+ >
47
+ {children}
48
+ </button>
49
+ )
50
+ }
@@ -0,0 +1,37 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react'
2
+
3
+ /**
4
+ * Design-system stat pill (`.stat-pill`): a compact card-surface chip with a
5
+ * bold count and a muted label, used in page headers to summarize list
6
+ * contents (e.g. "12 Total · 8 Active · 4 Inactive").
7
+ */
8
+ export interface StatPillProps extends HTMLAttributes<HTMLSpanElement> {
9
+ /** The count/value, rendered bold in `--txt` (override color via valueClassName). */
10
+ value: ReactNode
11
+ /** Muted label shown after the value. */
12
+ label: ReactNode
13
+ /** Optional leading icon. */
14
+ icon?: ReactNode
15
+ /** Extra classes for the value (e.g. `text-[var(--suc)]` for an Active count). */
16
+ valueClassName?: string
17
+ }
18
+
19
+ export function StatPill({
20
+ value,
21
+ label,
22
+ icon,
23
+ valueClassName,
24
+ className,
25
+ ...rest
26
+ }: StatPillProps) {
27
+ return (
28
+ <span
29
+ className={`inline-flex items-center gap-[5px] rounded-[6px] border border-[var(--bdr)] bg-[var(--card)] px-2.5 py-1 text-[length:var(--fs-sub)] text-[var(--sub)] ${className ?? ''}`}
30
+ {...rest}
31
+ >
32
+ {icon}
33
+ <b className={`font-semibold text-[var(--txt)] ${valueClassName ?? ''}`}>{value}</b>
34
+ {label}
35
+ </span>
36
+ )
37
+ }