@actuate-media/cms-admin 0.66.0 → 0.68.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 (244) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/AdminRoot.d.ts.map +1 -1
  3. package/dist/AdminRoot.js +36 -9
  4. package/dist/AdminRoot.js.map +1 -1
  5. package/dist/__tests__/components/inspector-pane.test.d.ts +2 -0
  6. package/dist/__tests__/components/inspector-pane.test.d.ts.map +1 -0
  7. package/dist/__tests__/components/inspector-pane.test.js +31 -0
  8. package/dist/__tests__/components/inspector-pane.test.js.map +1 -0
  9. package/dist/__tests__/hooks/useIdleLogout.test.d.ts +2 -0
  10. package/dist/__tests__/hooks/useIdleLogout.test.d.ts.map +1 -0
  11. package/dist/__tests__/hooks/useIdleLogout.test.js +64 -0
  12. package/dist/__tests__/hooks/useIdleLogout.test.js.map +1 -0
  13. package/dist/__tests__/lib/pages-tree.test.d.ts +2 -0
  14. package/dist/__tests__/lib/pages-tree.test.d.ts.map +1 -0
  15. package/dist/__tests__/lib/pages-tree.test.js +173 -0
  16. package/dist/__tests__/lib/pages-tree.test.js.map +1 -0
  17. package/dist/__tests__/lib/post-types-service.test.d.ts +2 -0
  18. package/dist/__tests__/lib/post-types-service.test.d.ts.map +1 -0
  19. package/dist/__tests__/lib/post-types-service.test.js +88 -0
  20. package/dist/__tests__/lib/post-types-service.test.js.map +1 -0
  21. package/dist/__tests__/views/collection-list-nav.render.test.js +43 -5
  22. package/dist/__tests__/views/collection-list-nav.render.test.js.map +1 -1
  23. package/dist/__tests__/views/dashboard.test.js +7 -3
  24. package/dist/__tests__/views/dashboard.test.js.map +1 -1
  25. package/dist/__tests__/views/forms-list.render.test.js +25 -6
  26. package/dist/__tests__/views/forms-list.render.test.js.map +1 -1
  27. package/dist/__tests__/views/media-seo-audit.render.test.d.ts +2 -0
  28. package/dist/__tests__/views/media-seo-audit.render.test.d.ts.map +1 -0
  29. package/dist/__tests__/views/media-seo-audit.render.test.js +102 -0
  30. package/dist/__tests__/views/media-seo-audit.render.test.js.map +1 -0
  31. package/dist/__tests__/views/onboarding-block.render.test.d.ts +2 -0
  32. package/dist/__tests__/views/onboarding-block.render.test.d.ts.map +1 -0
  33. package/dist/__tests__/views/onboarding-block.render.test.js +146 -0
  34. package/dist/__tests__/views/onboarding-block.render.test.js.map +1 -0
  35. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts +2 -0
  36. package/dist/__tests__/views/page-builder-sections-panel.render.test.d.ts.map +1 -0
  37. package/dist/__tests__/views/page-builder-sections-panel.render.test.js +121 -0
  38. package/dist/__tests__/views/page-builder-sections-panel.render.test.js.map +1 -0
  39. package/dist/__tests__/views/page-templates.render.test.d.ts +2 -0
  40. package/dist/__tests__/views/page-templates.render.test.d.ts.map +1 -0
  41. package/dist/__tests__/views/page-templates.render.test.js +105 -0
  42. package/dist/__tests__/views/page-templates.render.test.js.map +1 -0
  43. package/dist/__tests__/views/pages-list-view.test.js +77 -1
  44. package/dist/__tests__/views/pages-list-view.test.js.map +1 -1
  45. package/dist/__tests__/views/post-type-editor.render.test.d.ts +2 -0
  46. package/dist/__tests__/views/post-type-editor.render.test.d.ts.map +1 -0
  47. package/dist/__tests__/views/post-type-editor.render.test.js +102 -0
  48. package/dist/__tests__/views/post-type-editor.render.test.js.map +1 -0
  49. package/dist/__tests__/views/security-settings.render.test.js +85 -4
  50. package/dist/__tests__/views/security-settings.render.test.js.map +1 -1
  51. package/dist/__tests__/views/seo-content-pane.render.test.d.ts +2 -0
  52. package/dist/__tests__/views/seo-content-pane.render.test.d.ts.map +1 -0
  53. package/dist/__tests__/views/seo-content-pane.render.test.js +117 -0
  54. package/dist/__tests__/views/seo-content-pane.render.test.js.map +1 -0
  55. package/dist/actuate-admin.css +1 -1
  56. package/dist/components/collections/EntryDetailPane.d.ts +10 -0
  57. package/dist/components/collections/EntryDetailPane.d.ts.map +1 -0
  58. package/dist/components/collections/EntryDetailPane.js +92 -0
  59. package/dist/components/collections/EntryDetailPane.js.map +1 -0
  60. package/dist/components/forms/FieldsPanel.js +1 -1
  61. package/dist/components/forms/FieldsPanel.js.map +1 -1
  62. package/dist/components/forms/FormSchemaPane.d.ts +8 -0
  63. package/dist/components/forms/FormSchemaPane.d.ts.map +1 -0
  64. package/dist/components/forms/FormSchemaPane.js +95 -0
  65. package/dist/components/forms/FormSchemaPane.js.map +1 -0
  66. package/dist/components/script-tags/ScriptTagEditorPane.d.ts +26 -0
  67. package/dist/components/script-tags/ScriptTagEditorPane.d.ts.map +1 -0
  68. package/dist/components/script-tags/ScriptTagEditorPane.js +160 -0
  69. package/dist/components/script-tags/ScriptTagEditorPane.js.map +1 -0
  70. package/dist/components/seo/SeoEditorPane.d.ts +9 -0
  71. package/dist/components/seo/SeoEditorPane.d.ts.map +1 -0
  72. package/dist/components/seo/SeoEditorPane.js +175 -0
  73. package/dist/components/seo/SeoEditorPane.js.map +1 -0
  74. package/dist/components/ui/Badge.d.ts +1 -1
  75. package/dist/components/ui/Button.d.ts +1 -1
  76. package/dist/components/ui/InspectorPane.d.ts +51 -0
  77. package/dist/components/ui/InspectorPane.d.ts.map +1 -0
  78. package/dist/components/ui/InspectorPane.js +42 -0
  79. package/dist/components/ui/InspectorPane.js.map +1 -0
  80. package/dist/components/ui/StatusBadge.d.ts +1 -1
  81. package/dist/components/ui/index.d.ts +2 -0
  82. package/dist/components/ui/index.d.ts.map +1 -1
  83. package/dist/components/ui/index.js +1 -0
  84. package/dist/components/ui/index.js.map +1 -1
  85. package/dist/hooks/useIdleLogout.d.ts +18 -0
  86. package/dist/hooks/useIdleLogout.d.ts.map +1 -0
  87. package/dist/hooks/useIdleLogout.js +66 -0
  88. package/dist/hooks/useIdleLogout.js.map +1 -0
  89. package/dist/lib/api.d.ts +1 -0
  90. package/dist/lib/api.d.ts.map +1 -1
  91. package/dist/lib/api.js +7 -1
  92. package/dist/lib/api.js.map +1 -1
  93. package/dist/lib/page-editor-service.d.ts +11 -2
  94. package/dist/lib/page-editor-service.d.ts.map +1 -1
  95. package/dist/lib/page-editor-service.js +8 -2
  96. package/dist/lib/page-editor-service.js.map +1 -1
  97. package/dist/lib/pages-tree.d.ts +44 -0
  98. package/dist/lib/pages-tree.d.ts.map +1 -0
  99. package/dist/lib/pages-tree.js +106 -0
  100. package/dist/lib/pages-tree.js.map +1 -0
  101. package/dist/lib/post-types-service.d.ts +44 -0
  102. package/dist/lib/post-types-service.d.ts.map +1 -0
  103. package/dist/lib/post-types-service.js +83 -0
  104. package/dist/lib/post-types-service.js.map +1 -0
  105. package/dist/views/CollectionList.d.ts.map +1 -1
  106. package/dist/views/CollectionList.js +23 -4
  107. package/dist/views/CollectionList.js.map +1 -1
  108. package/dist/views/Dashboard.d.ts.map +1 -1
  109. package/dist/views/Dashboard.js +31 -2
  110. package/dist/views/Dashboard.js.map +1 -1
  111. package/dist/views/Forms.d.ts.map +1 -1
  112. package/dist/views/Forms.js +25 -21
  113. package/dist/views/Forms.js.map +1 -1
  114. package/dist/views/MediaBrowser.d.ts.map +1 -1
  115. package/dist/views/MediaBrowser.js +28 -2
  116. package/dist/views/MediaBrowser.js.map +1 -1
  117. package/dist/views/MediaSeoAudit.d.ts +25 -0
  118. package/dist/views/MediaSeoAudit.d.ts.map +1 -0
  119. package/dist/views/MediaSeoAudit.js +97 -0
  120. package/dist/views/MediaSeoAudit.js.map +1 -0
  121. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  122. package/dist/views/Pages/PagesListView.js +90 -10
  123. package/dist/views/Pages/PagesListView.js.map +1 -1
  124. package/dist/views/Pages/PagesTreeTable.d.ts +35 -0
  125. package/dist/views/Pages/PagesTreeTable.d.ts.map +1 -0
  126. package/dist/views/Pages/PagesTreeTable.js +28 -0
  127. package/dist/views/Pages/PagesTreeTable.js.map +1 -0
  128. package/dist/views/Posts/PostTypeEditor.d.ts +16 -0
  129. package/dist/views/Posts/PostTypeEditor.d.ts.map +1 -0
  130. package/dist/views/Posts/PostTypeEditor.js +159 -0
  131. package/dist/views/Posts/PostTypeEditor.js.map +1 -0
  132. package/dist/views/Posts/PostTypesView.d.ts +3 -2
  133. package/dist/views/Posts/PostTypesView.d.ts.map +1 -1
  134. package/dist/views/Posts/PostTypesView.js +1 -1
  135. package/dist/views/Posts/PostTypesView.js.map +1 -1
  136. package/dist/views/ScriptTags.d.ts +5 -1
  137. package/dist/views/ScriptTags.d.ts.map +1 -1
  138. package/dist/views/ScriptTags.js +32 -7
  139. package/dist/views/ScriptTags.js.map +1 -1
  140. package/dist/views/dashboard/OnboardingBlock.d.ts +29 -0
  141. package/dist/views/dashboard/OnboardingBlock.d.ts.map +1 -0
  142. package/dist/views/dashboard/OnboardingBlock.js +71 -0
  143. package/dist/views/dashboard/OnboardingBlock.js.map +1 -0
  144. package/dist/views/page-builder/BuilderSectionsPanel.d.ts +20 -0
  145. package/dist/views/page-builder/BuilderSectionsPanel.d.ts.map +1 -0
  146. package/dist/views/page-builder/BuilderSectionsPanel.js +105 -0
  147. package/dist/views/page-builder/BuilderSectionsPanel.js.map +1 -0
  148. package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
  149. package/dist/views/page-builder/PageBuilder.js +51 -2
  150. package/dist/views/page-builder/PageBuilder.js.map +1 -1
  151. package/dist/views/page-builder/PageTemplates.d.ts.map +1 -1
  152. package/dist/views/page-builder/PageTemplates.js +113 -6
  153. package/dist/views/page-builder/PageTemplates.js.map +1 -1
  154. package/dist/views/page-editor/PageSectionEditor.d.ts +7 -1
  155. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  156. package/dist/views/page-editor/PageSectionEditor.js +3 -3
  157. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  158. package/dist/views/page-editor/PageSettingsModal.d.ts +1 -1
  159. package/dist/views/page-editor/PageSettingsModal.d.ts.map +1 -1
  160. package/dist/views/page-editor/PageSettingsModal.js +42 -3
  161. package/dist/views/page-editor/PageSettingsModal.js.map +1 -1
  162. package/dist/views/seo/ContentTab.d.ts.map +1 -1
  163. package/dist/views/seo/ContentTab.js +22 -6
  164. package/dist/views/seo/ContentTab.js.map +1 -1
  165. package/dist/views/settings/AccessProtectionCard.d.ts +5 -1
  166. package/dist/views/settings/AccessProtectionCard.d.ts.map +1 -1
  167. package/dist/views/settings/AccessProtectionCard.js +13 -10
  168. package/dist/views/settings/AccessProtectionCard.js.map +1 -1
  169. package/dist/views/settings/SecurityTab.d.ts.map +1 -1
  170. package/dist/views/settings/SecurityTab.js +3 -3
  171. package/dist/views/settings/SecurityTab.js.map +1 -1
  172. package/dist/views/settings/SessionPolicyCard.d.ts +1 -2
  173. package/dist/views/settings/SessionPolicyCard.d.ts.map +1 -1
  174. package/dist/views/settings/SessionPolicyCard.js +12 -5
  175. package/dist/views/settings/SessionPolicyCard.js.map +1 -1
  176. package/dist/views/settings/useSecuritySettings.d.ts +13 -1
  177. package/dist/views/settings/useSecuritySettings.d.ts.map +1 -1
  178. package/dist/views/settings/useSecuritySettings.js +47 -4
  179. package/dist/views/settings/useSecuritySettings.js.map +1 -1
  180. package/package.json +2 -2
  181. package/src/AdminRoot.tsx +43 -10
  182. package/src/__tests__/components/inspector-pane.test.tsx +64 -0
  183. package/src/__tests__/hooks/useIdleLogout.test.tsx +86 -0
  184. package/src/__tests__/lib/pages-tree.test.ts +197 -0
  185. package/src/__tests__/lib/post-types-service.test.ts +112 -0
  186. package/src/__tests__/views/collection-list-nav.render.test.tsx +51 -5
  187. package/src/__tests__/views/dashboard.test.tsx +7 -3
  188. package/src/__tests__/views/forms-list.render.test.tsx +34 -6
  189. package/src/__tests__/views/media-seo-audit.render.test.tsx +117 -0
  190. package/src/__tests__/views/onboarding-block.render.test.tsx +193 -0
  191. package/src/__tests__/views/page-builder-sections-panel.render.test.tsx +138 -0
  192. package/src/__tests__/views/page-templates.render.test.tsx +142 -0
  193. package/src/__tests__/views/pages-list-view.test.tsx +93 -1
  194. package/src/__tests__/views/post-type-editor.render.test.tsx +116 -0
  195. package/src/__tests__/views/security-settings.render.test.tsx +111 -4
  196. package/src/__tests__/views/seo-content-pane.render.test.tsx +142 -0
  197. package/src/components/collections/EntryDetailPane.tsx +182 -0
  198. package/src/components/forms/FieldsPanel.tsx +3 -1
  199. package/src/components/forms/FormSchemaPane.tsx +192 -0
  200. package/src/components/script-tags/ScriptTagEditorPane.tsx +474 -0
  201. package/src/components/seo/SeoEditorPane.tsx +533 -0
  202. package/src/components/ui/InspectorPane.tsx +129 -0
  203. package/src/components/ui/index.ts +10 -0
  204. package/src/hooks/useIdleLogout.ts +77 -0
  205. package/src/lib/api.ts +8 -2
  206. package/src/lib/page-editor-service.ts +16 -2
  207. package/src/lib/pages-tree.ts +145 -0
  208. package/src/lib/post-types-service.ts +129 -0
  209. package/src/views/CollectionList.tsx +158 -110
  210. package/src/views/Dashboard.tsx +238 -196
  211. package/src/views/Forms.tsx +154 -126
  212. package/src/views/MediaBrowser.tsx +641 -511
  213. package/src/views/MediaSeoAudit.tsx +320 -0
  214. package/src/views/Pages/PagesListView.tsx +352 -183
  215. package/src/views/Pages/PagesTreeTable.tsx +339 -0
  216. package/src/views/Posts/PostTypeEditor.tsx +568 -0
  217. package/src/views/Posts/PostTypesView.tsx +5 -4
  218. package/src/views/ScriptTags.tsx +204 -129
  219. package/src/views/dashboard/OnboardingBlock.tsx +233 -0
  220. package/src/views/page-builder/BuilderSectionsPanel.tsx +304 -0
  221. package/src/views/page-builder/PageBuilder.tsx +69 -2
  222. package/src/views/page-builder/PageTemplates.tsx +340 -57
  223. package/src/views/page-editor/PageSectionEditor.tsx +9 -2
  224. package/src/views/page-editor/PageSettingsModal.tsx +75 -2
  225. package/src/views/seo/ContentTab.tsx +113 -80
  226. package/src/views/settings/AccessProtectionCard.tsx +83 -53
  227. package/src/views/settings/SecurityTab.tsx +23 -2
  228. package/src/views/settings/SessionPolicyCard.tsx +45 -9
  229. package/src/views/settings/useSecuritySettings.ts +78 -22
  230. package/dist/components/forms/FormSchemaDrawer.d.ts +0 -9
  231. package/dist/components/forms/FormSchemaDrawer.d.ts.map +0 -1
  232. package/dist/components/forms/FormSchemaDrawer.js +0 -99
  233. package/dist/components/forms/FormSchemaDrawer.js.map +0 -1
  234. package/dist/components/seo/SeoEditorDrawer.d.ts +0 -8
  235. package/dist/components/seo/SeoEditorDrawer.d.ts.map +0 -1
  236. package/dist/components/seo/SeoEditorDrawer.js +0 -172
  237. package/dist/components/seo/SeoEditorDrawer.js.map +0 -1
  238. package/dist/views/ScriptTagEditor.d.ts +0 -6
  239. package/dist/views/ScriptTagEditor.d.ts.map +0 -1
  240. package/dist/views/ScriptTagEditor.js +0 -111
  241. package/dist/views/ScriptTagEditor.js.map +0 -1
  242. package/src/components/forms/FormSchemaDrawer.tsx +0 -192
  243. package/src/components/seo/SeoEditorDrawer.tsx +0 -529
  244. package/src/views/ScriptTagEditor.tsx +0 -353
@@ -15,6 +15,8 @@ import { toast } from 'sonner'
15
15
  import { cmsApi } from '../lib/api.js'
16
16
  import { useApiData } from '../lib/useApiData.js'
17
17
  import { editPathForDoc, newPathForCollection } from '../lib/collection-routes.js'
18
+ import { InspectorPane, SplitPaneLayout, SplitPaneList } from '../components/ui/InspectorPane.js'
19
+ import { EntryDetailPane } from '../components/collections/EntryDetailPane.js'
18
20
 
19
21
  export interface CollectionListProps {
20
22
  collectionSlug: string
@@ -164,6 +166,8 @@ export function CollectionList({ collectionSlug, config, onNavigate }: Collectio
164
166
  const [sort, setSort] = useState<SortField | null>(null)
165
167
  const [order, setOrder] = useState<SortOrder>('asc')
166
168
  const [selected, setSelected] = useState<Set<string>>(new Set())
169
+ // Row selected into the inline detail pane (design Entries split-pane).
170
+ const [detailId, setDetailId] = useState<string | null>(null)
167
171
  const [filters, setFilters] = useState<Record<string, string>>({})
168
172
  // In-use values per `values`-sourced facet, fetched once per collection.
169
173
  const [facetValues, setFacetValues] = useState<Record<string, string[]>>({})
@@ -196,6 +200,7 @@ export function CollectionList({ collectionSlug, config, onNavigate }: Collectio
196
200
  useEffect(() => {
197
201
  setPage(1)
198
202
  setSelected(new Set())
203
+ setDetailId(null)
199
204
  setSearch('')
200
205
  setFilters({})
201
206
  setFacetValues({})
@@ -242,6 +247,12 @@ export function CollectionList({ collectionSlug, config, onNavigate }: Collectio
242
247
  })
243
248
  }, [])
244
249
 
250
+ const detailDoc = useMemo(
251
+ () => (detailId ? (docs.find((d: any) => String(d.id) === detailId) ?? null) : null),
252
+ [docs, detailId],
253
+ )
254
+ const toggleDetail = (id: string) => setDetailId((prev) => (prev === id ? null : id))
255
+
245
256
  const toggleSelect = (id: string) =>
246
257
  setSelected((prev) => {
247
258
  const s = new Set(prev)
@@ -454,120 +465,157 @@ export function CollectionList({ collectionSlug, config, onNavigate }: Collectio
454
465
  </button>
455
466
  </div>
456
467
  ) : (
457
- <div
458
- className="flex-1 overflow-auto rounded-lg border"
459
- style={{ borderColor: 'var(--actuate-border, #d1d5db)' }}
460
- >
461
- <table className="w-full text-sm">
462
- <thead
463
- className="sticky top-0"
464
- style={{
465
- background: 'var(--actuate-surface-alt, #f9fafb)',
466
- borderBottom: '1px solid var(--actuate-border, #d1d5db)',
467
- }}
468
+ <SplitPaneLayout>
469
+ <SplitPaneList>
470
+ <div
471
+ className="h-full overflow-auto rounded-lg border"
472
+ style={{ borderColor: 'var(--actuate-border, #d1d5db)' }}
468
473
  >
469
- <tr>
470
- <th className="w-10 px-3 py-2 text-left">
471
- <input
472
- type="checkbox"
473
- checked={selected.size === docs.length && docs.length > 0}
474
- onChange={(e) => toggleAll(e.target.checked)}
475
- className="rounded"
476
- />
477
- </th>
478
- <th className="px-3 py-2 text-left">
479
- <SortCol field="title">Title</SortCol>
480
- </th>
481
- {facets.map((facet) => (
482
- <th
483
- key={facet.name}
484
- className="px-3 py-2 text-left text-xs font-medium"
485
- style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
486
- >
487
- {facet.label}
488
- </th>
489
- ))}
490
- <th className="px-3 py-2 text-left">
491
- <SortCol field="status">Status</SortCol>
492
- </th>
493
- <th className="px-3 py-2 text-left">
494
- <SortCol field="updatedAt">Updated</SortCol>
495
- </th>
496
- <th
497
- className="px-3 py-2 text-left text-xs font-medium"
498
- style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
474
+ <table className="w-full text-sm">
475
+ <thead
476
+ className="sticky top-0"
477
+ style={{
478
+ background: 'var(--actuate-surface-alt, #f9fafb)',
479
+ borderBottom: '1px solid var(--actuate-border, #d1d5db)',
480
+ }}
499
481
  >
500
- Actions
501
- </th>
502
- </tr>
503
- </thead>
504
- <tbody>
505
- {docs.map((doc: any) => (
506
- <tr
507
- key={doc.id}
508
- className="transition-colors hover:opacity-95"
509
- style={{ borderBottom: '1px solid var(--actuate-border, #e5e7eb)' }}
510
- >
511
- <td className="px-3 py-2">
512
- <input
513
- type="checkbox"
514
- checked={selected.has(String(doc.id))}
515
- onChange={() => toggleSelect(String(doc.id))}
516
- className="rounded"
517
- />
518
- </td>
519
- <td className="px-3 py-2">
520
- <button
521
- type="button"
522
- onClick={() => onNavigate(editPath(doc.id))}
523
- className="text-left font-medium hover:underline"
524
- style={{ color: 'var(--actuate-text, #111827)' }}
525
- >
526
- {doc.title || doc.name || `#${doc.id}`}
527
- </button>
528
- </td>
529
- {facets.map((facet) => (
530
- <td
531
- key={facet.name}
532
- className="max-w-[200px] truncate px-3 py-2"
482
+ <tr>
483
+ <th className="w-10 px-3 py-2 text-left">
484
+ <input
485
+ type="checkbox"
486
+ checked={selected.size === docs.length && docs.length > 0}
487
+ onChange={(e) => toggleAll(e.target.checked)}
488
+ className="rounded"
489
+ />
490
+ </th>
491
+ <th className="px-3 py-2 text-left">
492
+ <SortCol field="title">Title</SortCol>
493
+ </th>
494
+ {facets.map((facet) => (
495
+ <th
496
+ key={facet.name}
497
+ className="px-3 py-2 text-left text-xs font-medium"
498
+ style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
499
+ >
500
+ {facet.label}
501
+ </th>
502
+ ))}
503
+ <th className="px-3 py-2 text-left">
504
+ <SortCol field="status">Status</SortCol>
505
+ </th>
506
+ <th className="px-3 py-2 text-left">
507
+ <SortCol field="updatedAt">Updated</SortCol>
508
+ </th>
509
+ <th
510
+ className="px-3 py-2 text-left text-xs font-medium"
533
511
  style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
534
- title={facetCellValue(doc, facet) || undefined}
535
- >
536
- {facetCellValue(doc, facet) || '—'}
537
- </td>
538
- ))}
539
- <td className="px-3 py-2">
540
- <span
541
- className="inline-block rounded-full px-2 py-0.5 text-xs font-medium"
542
- style={{ background: statusColor(doc.status), color: statusText(doc.status) }}
543
512
  >
544
- {doc.status ?? 'DRAFT'}
545
- </span>
546
- </td>
547
- <td
548
- className="px-3 py-2"
549
- style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
550
- >
551
- {formatDate(doc.updatedAt)}
552
- </td>
553
- <td className="px-3 py-2">
554
- <button
555
- type="button"
556
- onClick={() => onNavigate(editPath(doc.id))}
557
- className="rounded p-1.5 transition-opacity hover:opacity-75"
558
- title="Edit"
559
- >
560
- <MoreHorizontal
561
- className="h-4 w-4"
562
- style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
563
- />
564
- </button>
565
- </td>
566
- </tr>
567
- ))}
568
- </tbody>
569
- </table>
570
- </div>
513
+ Actions
514
+ </th>
515
+ </tr>
516
+ </thead>
517
+ <tbody>
518
+ {docs.map((doc: any) => {
519
+ const isDetail = detailId === String(doc.id)
520
+ return (
521
+ <tr
522
+ key={doc.id}
523
+ className={`cursor-pointer transition-colors ${isDetail ? 'bg-[var(--acc-l)]' : 'hover:opacity-95'}`}
524
+ style={{ borderBottom: '1px solid var(--actuate-border, #e5e7eb)' }}
525
+ onClick={() => toggleDetail(String(doc.id))}
526
+ onDoubleClick={() => onNavigate(editPath(doc.id))}
527
+ >
528
+ <td className="px-3 py-2" onClick={(e) => e.stopPropagation()}>
529
+ <input
530
+ type="checkbox"
531
+ checked={selected.has(String(doc.id))}
532
+ onChange={() => toggleSelect(String(doc.id))}
533
+ className="rounded"
534
+ />
535
+ </td>
536
+ <td className="px-3 py-2">
537
+ <button
538
+ type="button"
539
+ onClick={(e) => {
540
+ e.stopPropagation()
541
+ toggleDetail(String(doc.id))
542
+ }}
543
+ aria-expanded={isDetail}
544
+ className="text-left font-medium hover:underline"
545
+ style={{ color: 'var(--actuate-text, #111827)' }}
546
+ >
547
+ {doc.title || doc.name || `#${doc.id}`}
548
+ </button>
549
+ </td>
550
+ {facets.map((facet) => (
551
+ <td
552
+ key={facet.name}
553
+ className="max-w-[200px] truncate px-3 py-2"
554
+ style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
555
+ title={facetCellValue(doc, facet) || undefined}
556
+ >
557
+ {facetCellValue(doc, facet) || '—'}
558
+ </td>
559
+ ))}
560
+ <td className="px-3 py-2">
561
+ <span
562
+ className="inline-block rounded-full px-2 py-0.5 text-xs font-medium"
563
+ style={{
564
+ background: statusColor(doc.status),
565
+ color: statusText(doc.status),
566
+ }}
567
+ >
568
+ {doc.status ?? 'DRAFT'}
569
+ </span>
570
+ </td>
571
+ <td
572
+ className="px-3 py-2"
573
+ style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
574
+ >
575
+ {formatDate(doc.updatedAt)}
576
+ </td>
577
+ <td className="px-3 py-2">
578
+ <button
579
+ type="button"
580
+ onClick={(e) => {
581
+ e.stopPropagation()
582
+ onNavigate(editPath(doc.id))
583
+ }}
584
+ className="rounded p-1.5 transition-opacity hover:opacity-75"
585
+ title="Edit"
586
+ aria-label={`Edit ${doc.title || doc.name || `#${doc.id}`}`}
587
+ >
588
+ <MoreHorizontal
589
+ className="h-4 w-4"
590
+ style={{ color: 'var(--actuate-text-secondary, #6b7280)' }}
591
+ />
592
+ </button>
593
+ </td>
594
+ </tr>
595
+ )
596
+ })}
597
+ </tbody>
598
+ </table>
599
+ </div>
600
+ </SplitPaneList>
601
+
602
+ <InspectorPane
603
+ open={detailDoc !== null}
604
+ width={400}
605
+ aria-label={`${labels.singular} details`}
606
+ >
607
+ {detailDoc && (
608
+ <EntryDetailPane
609
+ key={String(detailDoc.id)}
610
+ doc={detailDoc}
611
+ collection={collectionDef}
612
+ singularLabel={labels.singular}
613
+ onClose={() => setDetailId(null)}
614
+ onOpenEditor={() => onNavigate(editPath(detailDoc.id))}
615
+ />
616
+ )}
617
+ </InspectorPane>
618
+ </SplitPaneLayout>
571
619
  )}
572
620
 
573
621
  {/* Pagination */}