@prenta/admin 1.17.0 → 1.17.2

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 (327) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/__tests__/lib/seo-service-errors.test.js +2 -6
  3. package/dist/__tests__/lib/seo-service-errors.test.js.map +1 -1
  4. package/dist/__tests__/views/ai-settings.render.test.js +67 -1
  5. package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
  6. package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
  7. package/dist/components/CoauthorResultPopover.js +4 -1
  8. package/dist/components/CoauthorResultPopover.js.map +1 -1
  9. package/dist/components/CommentSidePanel.d.ts +0 -7
  10. package/dist/components/CommentSidePanel.d.ts.map +1 -1
  11. package/dist/components/CommentSidePanel.js +0 -2
  12. package/dist/components/CommentSidePanel.js.map +1 -1
  13. package/dist/components/EditorRail.d.ts +2 -1
  14. package/dist/components/EditorRail.d.ts.map +1 -1
  15. package/dist/components/MediaPickerModal.d.ts +2 -1
  16. package/dist/components/MediaPickerModal.d.ts.map +1 -1
  17. package/dist/components/TipTapEditor.d.ts +3 -2
  18. package/dist/components/TipTapEditor.d.ts.map +1 -1
  19. package/dist/components/forms/EntriesTable.d.ts +0 -1
  20. package/dist/components/forms/EntriesTable.d.ts.map +1 -1
  21. package/dist/components/forms/EntriesTable.js +1 -1
  22. package/dist/components/forms/EntriesTable.js.map +1 -1
  23. package/dist/components/pages/tag-badges.d.ts +2 -2
  24. package/dist/components/pages/tag-badges.d.ts.map +1 -1
  25. package/dist/components/pages/tag-badges.js.map +1 -1
  26. package/dist/components/seo/FaqProposalPreview.d.ts +2 -3
  27. package/dist/components/seo/FaqProposalPreview.d.ts.map +1 -1
  28. package/dist/components/seo/FaqProposalPreview.js +1 -1
  29. package/dist/components/seo/FaqProposalPreview.js.map +1 -1
  30. package/dist/components/seo/SeoCopilotDrawer.js +1 -1
  31. package/dist/components/seo/SeoCopilotDrawer.js.map +1 -1
  32. package/dist/components/seo/SeoEditorPane.d.ts.map +1 -1
  33. package/dist/components/seo/SeoEditorPane.js +4 -1
  34. package/dist/components/seo/SeoEditorPane.js.map +1 -1
  35. package/dist/components/ui/Badge.d.ts +3 -9
  36. package/dist/components/ui/Badge.d.ts.map +1 -1
  37. package/dist/components/ui/Badge.js +2 -3
  38. package/dist/components/ui/Badge.js.map +1 -1
  39. package/dist/components/ui/Button.d.ts +2 -2
  40. package/dist/components/ui/Button.d.ts.map +1 -1
  41. package/dist/components/ui/Button.js +0 -1
  42. package/dist/components/ui/Button.js.map +1 -1
  43. package/dist/components/ui/Card.d.ts +2 -3
  44. package/dist/components/ui/Card.d.ts.map +1 -1
  45. package/dist/components/ui/Card.js +0 -4
  46. package/dist/components/ui/Card.js.map +1 -1
  47. package/dist/components/ui/Input.d.ts +6 -8
  48. package/dist/components/ui/Input.d.ts.map +1 -1
  49. package/dist/components/ui/Input.js +6 -6
  50. package/dist/components/ui/Input.js.map +1 -1
  51. package/dist/components/ui/Modal.d.ts +1 -1
  52. package/dist/components/ui/Modal.d.ts.map +1 -1
  53. package/dist/components/ui/ResizableAside.d.ts +0 -13
  54. package/dist/components/ui/ResizableAside.d.ts.map +1 -1
  55. package/dist/components/ui/ResizableAside.js +5 -5
  56. package/dist/components/ui/ResizableAside.js.map +1 -1
  57. package/dist/components/ui/StatusBadge.d.ts +2 -2
  58. package/dist/components/ui/StatusBadge.d.ts.map +1 -1
  59. package/dist/components/ui/StatusBadge.js +0 -1
  60. package/dist/components/ui/StatusBadge.js.map +1 -1
  61. package/dist/components/ui/Toggle.d.ts +2 -8
  62. package/dist/components/ui/Toggle.d.ts.map +1 -1
  63. package/dist/components/ui/Toggle.js +0 -1
  64. package/dist/components/ui/Toggle.js.map +1 -1
  65. package/dist/fields/FieldRenderer.d.ts +2 -1
  66. package/dist/fields/FieldRenderer.d.ts.map +1 -1
  67. package/dist/fields/index.d.ts +0 -17
  68. package/dist/fields/index.d.ts.map +1 -1
  69. package/dist/fields/index.js +0 -15
  70. package/dist/fields/index.js.map +1 -1
  71. package/dist/layout/primitives/tokens.d.ts +0 -2
  72. package/dist/layout/primitives/tokens.d.ts.map +1 -1
  73. package/dist/layout/primitives/tokens.js +0 -6
  74. package/dist/layout/primitives/tokens.js.map +1 -1
  75. package/dist/lib/brand-voice-client.d.ts +14 -1
  76. package/dist/lib/brand-voice-client.d.ts.map +1 -1
  77. package/dist/lib/brand-voice-client.js +7 -0
  78. package/dist/lib/brand-voice-client.js.map +1 -1
  79. package/dist/lib/coauthor-client.d.ts +2 -1
  80. package/dist/lib/coauthor-client.d.ts.map +1 -1
  81. package/dist/lib/collection-schema.d.ts +0 -9
  82. package/dist/lib/collection-schema.d.ts.map +1 -1
  83. package/dist/lib/collection-schema.js +2 -2
  84. package/dist/lib/collection-schema.js.map +1 -1
  85. package/dist/lib/editor-seo-content.d.ts +0 -10
  86. package/dist/lib/editor-seo-content.d.ts.map +1 -1
  87. package/dist/lib/editor-seo-content.js +0 -13
  88. package/dist/lib/editor-seo-content.js.map +1 -1
  89. package/dist/lib/forms-service.d.ts +3 -21
  90. package/dist/lib/forms-service.d.ts.map +1 -1
  91. package/dist/lib/forms-service.js +0 -25
  92. package/dist/lib/forms-service.js.map +1 -1
  93. package/dist/lib/notifications-client.d.ts +4 -3
  94. package/dist/lib/notifications-client.d.ts.map +1 -1
  95. package/dist/lib/page-audit-input.d.ts +0 -10
  96. package/dist/lib/page-audit-input.d.ts.map +1 -1
  97. package/dist/lib/page-audit-input.js +1 -1
  98. package/dist/lib/page-audit-input.js.map +1 -1
  99. package/dist/lib/page-editor-service.d.ts +2 -4
  100. package/dist/lib/page-editor-service.d.ts.map +1 -1
  101. package/dist/lib/page-editor-service.js +3 -3
  102. package/dist/lib/page-editor-service.js.map +1 -1
  103. package/dist/lib/pages-service.d.ts +2 -13
  104. package/dist/lib/pages-service.d.ts.map +1 -1
  105. package/dist/lib/pages-service.js +3 -24
  106. package/dist/lib/pages-service.js.map +1 -1
  107. package/dist/lib/plan.d.ts +2 -1
  108. package/dist/lib/plan.d.ts.map +1 -1
  109. package/dist/lib/post-editor-service.d.ts +3 -13
  110. package/dist/lib/post-editor-service.d.ts.map +1 -1
  111. package/dist/lib/post-editor-service.js +5 -6
  112. package/dist/lib/post-editor-service.js.map +1 -1
  113. package/dist/lib/post-types-service.d.ts +2 -3
  114. package/dist/lib/post-types-service.d.ts.map +1 -1
  115. package/dist/lib/post-types-service.js +1 -1
  116. package/dist/lib/post-types-service.js.map +1 -1
  117. package/dist/lib/posts-service.d.ts +2 -1
  118. package/dist/lib/posts-service.d.ts.map +1 -1
  119. package/dist/lib/preview-link.d.ts +0 -9
  120. package/dist/lib/preview-link.d.ts.map +1 -1
  121. package/dist/lib/preview-link.js +0 -15
  122. package/dist/lib/preview-link.js.map +1 -1
  123. package/dist/lib/rail-width.d.ts +0 -1
  124. package/dist/lib/rail-width.d.ts.map +1 -1
  125. package/dist/lib/rail-width.js +1 -1
  126. package/dist/lib/rail-width.js.map +1 -1
  127. package/dist/lib/reflow-probe.d.ts +0 -67
  128. package/dist/lib/reflow-probe.d.ts.map +1 -1
  129. package/dist/lib/reflow-probe.js +4 -4
  130. package/dist/lib/reflow-probe.js.map +1 -1
  131. package/dist/lib/seo-service.d.ts +14 -37
  132. package/dist/lib/seo-service.d.ts.map +1 -1
  133. package/dist/lib/seo-service.js +7 -37
  134. package/dist/lib/seo-service.js.map +1 -1
  135. package/dist/lib/theme-chrome.d.ts +0 -1
  136. package/dist/lib/theme-chrome.d.ts.map +1 -1
  137. package/dist/lib/theme-chrome.js +1 -1
  138. package/dist/lib/theme-chrome.js.map +1 -1
  139. package/dist/lib/version-history.d.ts +2 -2
  140. package/dist/lib/version-history.d.ts.map +1 -1
  141. package/dist/lib/workflow-chrome.d.ts +0 -3
  142. package/dist/lib/workflow-chrome.d.ts.map +1 -1
  143. package/dist/lib/workflow-chrome.js +3 -3
  144. package/dist/lib/workflow-chrome.js.map +1 -1
  145. package/dist/prenta-admin.css +1 -1
  146. package/dist/views/Login.d.ts +2 -1
  147. package/dist/views/Login.d.ts.map +1 -1
  148. package/dist/views/MediaBrowser.d.ts.map +1 -1
  149. package/dist/views/MediaBrowser.js +3 -2
  150. package/dist/views/MediaBrowser.js.map +1 -1
  151. package/dist/views/PageEditor.d.ts +2 -1
  152. package/dist/views/PageEditor.d.ts.map +1 -1
  153. package/dist/views/Pages/PagesListView.d.ts +0 -1
  154. package/dist/views/Pages/PagesListView.d.ts.map +1 -1
  155. package/dist/views/Pages/PagesListView.js +1 -1
  156. package/dist/views/Pages/PagesListView.js.map +1 -1
  157. package/dist/views/Pages.d.ts +2 -1
  158. package/dist/views/Pages.d.ts.map +1 -1
  159. package/dist/views/Redirects.d.ts +2 -1
  160. package/dist/views/Redirects.d.ts.map +1 -1
  161. package/dist/views/page-editor/section-types.d.ts +2 -2
  162. package/dist/views/page-editor/section-types.d.ts.map +1 -1
  163. package/dist/views/page-editor/section-types.js +1 -1
  164. package/dist/views/page-editor/section-types.js.map +1 -1
  165. package/dist/views/page-editor/sections/admin-renderers.d.ts +2 -1
  166. package/dist/views/page-editor/sections/admin-renderers.d.ts.map +1 -1
  167. package/dist/views/page-editor/theme-chrome/index.d.ts +1 -6
  168. package/dist/views/page-editor/theme-chrome/index.d.ts.map +1 -1
  169. package/dist/views/page-editor/theme-chrome/index.js +1 -3
  170. package/dist/views/page-editor/theme-chrome/index.js.map +1 -1
  171. package/dist/views/page-editor/viewports.d.ts +1 -1
  172. package/dist/views/page-editor/viewports.d.ts.map +1 -1
  173. package/dist/views/page-editor/viewports.js +1 -1
  174. package/dist/views/page-editor/viewports.js.map +1 -1
  175. package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
  176. package/dist/views/settings/AISettingsTab.js +13 -3
  177. package/dist/views/settings/AISettingsTab.js.map +1 -1
  178. package/dist/views/settings/BrandVoiceCard.d.ts +3 -0
  179. package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
  180. package/dist/views/settings/BrandVoiceCard.js +2 -2
  181. package/dist/views/settings/BrandVoiceCard.js.map +1 -1
  182. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts.map +1 -1
  183. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js +4 -1
  184. package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js.map +1 -1
  185. package/dist/views/settings/featureModel.d.ts +0 -3
  186. package/dist/views/settings/featureModel.d.ts.map +1 -1
  187. package/dist/views/settings/featureModel.js +2 -2
  188. package/dist/views/settings/featureModel.js.map +1 -1
  189. package/dist/views/settings/useAiSettings.d.ts +2 -2
  190. package/dist/views/settings/useAiSettings.d.ts.map +1 -1
  191. package/dist/views/settings/useAiSettings.js +6 -2
  192. package/dist/views/settings/useAiSettings.js.map +1 -1
  193. package/dist/views/settings/useAppearanceSettings.d.ts +5 -6
  194. package/dist/views/settings/useAppearanceSettings.d.ts.map +1 -1
  195. package/dist/views/settings/useAppearanceSettings.js +1 -1
  196. package/dist/views/settings/useAppearanceSettings.js.map +1 -1
  197. package/dist/views/settings/useEmailSettings.d.ts +3 -2
  198. package/dist/views/settings/useEmailSettings.d.ts.map +1 -1
  199. package/dist/views/settings/useGeneralSettings.d.ts +2 -11
  200. package/dist/views/settings/useGeneralSettings.d.ts.map +1 -1
  201. package/dist/views/settings/useGeneralSettings.js +3 -3
  202. package/dist/views/settings/useGeneralSettings.js.map +1 -1
  203. package/dist/views/settings/useSeoSettings.d.ts +1 -1
  204. package/dist/views/settings/useSeoSettings.d.ts.map +1 -1
  205. package/dist/views/settings/useUpdates.d.ts +1 -3
  206. package/dist/views/settings/useUpdates.d.ts.map +1 -1
  207. package/dist/views/settings/useUpdates.js +1 -1
  208. package/dist/views/settings/useUpdates.js.map +1 -1
  209. package/package.json +5 -5
  210. package/src/__tests__/lib/seo-service-errors.test.ts +1 -9
  211. package/src/__tests__/views/ai-settings.render.test.tsx +86 -2
  212. package/src/components/CoauthorResultPopover.tsx +3 -1
  213. package/src/components/CommentSidePanel.tsx +0 -1
  214. package/src/components/EditorRail.tsx +1 -1
  215. package/src/components/MediaPickerModal.tsx +1 -1
  216. package/src/components/TipTapEditor.tsx +2 -2
  217. package/src/components/forms/EntriesTable.tsx +1 -1
  218. package/src/components/pages/tag-badges.tsx +1 -1
  219. package/src/components/seo/FaqProposalPreview.tsx +2 -2
  220. package/src/components/seo/SeoCopilotDrawer.tsx +1 -1
  221. package/src/components/seo/SeoEditorPane.tsx +3 -1
  222. package/src/components/ui/Badge.tsx +4 -6
  223. package/src/components/ui/Button.tsx +1 -3
  224. package/src/components/ui/Card.tsx +1 -14
  225. package/src/components/ui/Input.tsx +7 -15
  226. package/src/components/ui/Modal.tsx +1 -1
  227. package/src/components/ui/ResizableAside.tsx +5 -5
  228. package/src/components/ui/StatusBadge.tsx +1 -3
  229. package/src/components/ui/Toggle.tsx +1 -3
  230. package/src/fields/FieldRenderer.tsx +1 -1
  231. package/src/fields/index.ts +0 -17
  232. package/src/layout/primitives/tokens.ts +0 -7
  233. package/src/lib/brand-voice-client.ts +18 -1
  234. package/src/lib/coauthor-client.ts +1 -1
  235. package/src/lib/collection-schema.ts +2 -2
  236. package/src/lib/editor-seo-content.ts +0 -22
  237. package/src/lib/forms-service.ts +2 -42
  238. package/src/lib/notifications-client.ts +3 -3
  239. package/src/lib/page-audit-input.ts +1 -1
  240. package/src/lib/page-editor-service.ts +1 -3
  241. package/src/lib/pages-service.ts +4 -29
  242. package/src/lib/plan.ts +1 -1
  243. package/src/lib/post-editor-service.ts +4 -10
  244. package/src/lib/post-types-service.ts +2 -2
  245. package/src/lib/posts-service.ts +1 -1
  246. package/src/lib/preview-link.ts +0 -14
  247. package/src/lib/rail-width.ts +1 -1
  248. package/src/lib/reflow-probe.ts +4 -4
  249. package/src/lib/seo-service.ts +20 -74
  250. package/src/lib/theme-chrome.ts +1 -1
  251. package/src/lib/version-history.ts +2 -2
  252. package/src/lib/workflow-chrome.ts +3 -3
  253. package/src/views/Login.tsx +1 -1
  254. package/src/views/MediaBrowser.tsx +3 -2
  255. package/src/views/PageEditor.tsx +1 -1
  256. package/src/views/Pages/PagesListView.tsx +1 -1
  257. package/src/views/Pages.tsx +1 -1
  258. package/src/views/Redirects.tsx +1 -1
  259. package/src/views/page-editor/section-types.ts +0 -9
  260. package/src/views/page-editor/sections/admin-renderers.tsx +1 -1
  261. package/src/views/page-editor/theme-chrome/index.ts +2 -10
  262. package/src/views/page-editor/viewports.ts +0 -3
  263. package/src/views/settings/AISettingsTab.tsx +15 -3
  264. package/src/views/settings/BrandVoiceCard.tsx +11 -1
  265. package/src/views/settings/brand-voice/BrandVoiceAlignmentPanel.tsx +3 -1
  266. package/src/views/settings/featureModel.ts +2 -2
  267. package/src/views/settings/useAiSettings.ts +8 -3
  268. package/src/views/settings/useAppearanceSettings.ts +4 -6
  269. package/src/views/settings/useEmailSettings.ts +2 -2
  270. package/src/views/settings/useGeneralSettings.ts +5 -10
  271. package/src/views/settings/useSeoSettings.ts +1 -1
  272. package/src/views/settings/useUpdates.ts +2 -2
  273. package/dist/components/ContentOverviewChart.d.ts +0 -8
  274. package/dist/components/ContentOverviewChart.d.ts.map +0 -1
  275. package/dist/components/ContentOverviewChart.js +0 -20
  276. package/dist/components/ContentOverviewChart.js.map +0 -1
  277. package/dist/components/SEOPerformance.d.ts +0 -5
  278. package/dist/components/SEOPerformance.d.ts.map +0 -1
  279. package/dist/components/SEOPerformance.js +0 -29
  280. package/dist/components/SEOPerformance.js.map +0 -1
  281. package/dist/components/ui/Avatar.d.ts +0 -9
  282. package/dist/components/ui/Avatar.d.ts.map +0 -1
  283. package/dist/components/ui/Avatar.js +0 -21
  284. package/dist/components/ui/Avatar.js.map +0 -1
  285. package/dist/components/ui/CommandPalette.d.ts +0 -14
  286. package/dist/components/ui/CommandPalette.d.ts.map +0 -1
  287. package/dist/components/ui/CommandPalette.js +0 -58
  288. package/dist/components/ui/CommandPalette.js.map +0 -1
  289. package/dist/components/ui/DataTable.d.ts +0 -30
  290. package/dist/components/ui/DataTable.d.ts.map +0 -1
  291. package/dist/components/ui/DataTable.js +0 -44
  292. package/dist/components/ui/DataTable.js.map +0 -1
  293. package/dist/components/ui/Pagination.d.ts +0 -9
  294. package/dist/components/ui/Pagination.d.ts.map +0 -1
  295. package/dist/components/ui/Pagination.js +0 -26
  296. package/dist/components/ui/Pagination.js.map +0 -1
  297. package/dist/components/ui/Select.d.ts +0 -16
  298. package/dist/components/ui/Select.d.ts.map +0 -1
  299. package/dist/components/ui/Select.js +0 -24
  300. package/dist/components/ui/Select.js.map +0 -1
  301. package/dist/components/ui/Toast.d.ts +0 -18
  302. package/dist/components/ui/Toast.d.ts.map +0 -1
  303. package/dist/components/ui/Toast.js +0 -29
  304. package/dist/components/ui/Toast.js.map +0 -1
  305. package/dist/components/ui/index.d.ts +0 -46
  306. package/dist/components/ui/index.d.ts.map +0 -1
  307. package/dist/components/ui/index.js +0 -24
  308. package/dist/components/ui/index.js.map +0 -1
  309. package/dist/hooks/useContentLock.d.ts +0 -12
  310. package/dist/hooks/useContentLock.d.ts.map +0 -1
  311. package/dist/hooks/useContentLock.js +0 -38
  312. package/dist/hooks/useContentLock.js.map +0 -1
  313. package/dist/hooks/useDebounce.d.ts +0 -2
  314. package/dist/hooks/useDebounce.d.ts.map +0 -1
  315. package/dist/hooks/useDebounce.js +0 -11
  316. package/dist/hooks/useDebounce.js.map +0 -1
  317. package/src/components/ContentOverviewChart.tsx +0 -75
  318. package/src/components/SEOPerformance.tsx +0 -163
  319. package/src/components/ui/Avatar.tsx +0 -42
  320. package/src/components/ui/CommandPalette.tsx +0 -133
  321. package/src/components/ui/DataTable.tsx +0 -204
  322. package/src/components/ui/Pagination.tsx +0 -94
  323. package/src/components/ui/Select.tsx +0 -53
  324. package/src/components/ui/Toast.tsx +0 -72
  325. package/src/components/ui/index.ts +0 -61
  326. package/src/hooks/useContentLock.ts +0 -55
  327. package/src/hooks/useDebounce.ts +0 -14
@@ -1,204 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useRef, useEffect } from 'react'
4
-
5
- interface Column {
6
- key: string
7
- label: string
8
- sortable?: boolean
9
- }
10
-
11
- interface Row {
12
- id: string
13
- [key: string]: any
14
- }
15
-
16
- export interface RowAction {
17
- key: string
18
- label: string
19
- icon?: React.ReactNode
20
- destructive?: boolean
21
- onClick: (row: Row) => void
22
- }
23
-
24
- export interface DataTableProps {
25
- columns: Column[]
26
- rows: Row[]
27
- selectedIds: string[]
28
- onSelectionChange: (ids: string[]) => void
29
- sortField?: string
30
- sortDir?: 'asc' | 'desc'
31
- onSort?: (field: string) => void
32
- rowActions?: RowAction[]
33
- onRowClick?: (row: Row) => void
34
- }
35
-
36
- export function DataTable({
37
- columns,
38
- rows,
39
- selectedIds,
40
- onSelectionChange,
41
- sortField,
42
- sortDir,
43
- onSort,
44
- rowActions,
45
- onRowClick,
46
- }: DataTableProps) {
47
- const allSelected = rows.length > 0 && selectedIds.length === rows.length
48
-
49
- function toggleAll() {
50
- onSelectionChange(allSelected ? [] : rows.map((r) => r.id))
51
- }
52
-
53
- function toggleRow(id: string) {
54
- onSelectionChange(
55
- selectedIds.includes(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id],
56
- )
57
- }
58
-
59
- return (
60
- <div className="overflow-x-auto rounded-lg border border-[var(--border)]">
61
- <table className="w-full text-left text-sm">
62
- <thead className="bg-muted border-b border-[var(--border)]">
63
- <tr>
64
- <th className="w-10 px-4 py-3">
65
- <input
66
- type="checkbox"
67
- checked={allSelected}
68
- onChange={toggleAll}
69
- className="rounded border-[var(--border)]"
70
- />
71
- </th>
72
- {columns.map((col) => (
73
- <th
74
- key={col.key}
75
- className="px-4 py-3 font-medium"
76
- aria-sort={
77
- col.sortable && onSort
78
- ? sortField === col.key
79
- ? sortDir === 'asc'
80
- ? 'ascending'
81
- : 'descending'
82
- : 'none'
83
- : undefined
84
- }
85
- >
86
- {col.sortable && onSort ? (
87
- <button
88
- onClick={() => onSort(col.key)}
89
- className="inline-flex items-center gap-1 hover:text-[var(--foreground)]"
90
- >
91
- {col.label}
92
- {sortField === col.key && (
93
- <span className="text-xs">{sortDir === 'asc' ? '↑' : '↓'}</span>
94
- )}
95
- </button>
96
- ) : (
97
- col.label
98
- )}
99
- </th>
100
- ))}
101
- {rowActions && rowActions.length > 0 && <th className="w-20 px-4 py-3" />}
102
- </tr>
103
- </thead>
104
- <tbody className="divide-y divide-[var(--border)]">
105
- {rows.map((row) => (
106
- <tr
107
- key={row.id}
108
- className={`hover:bg-[var(--accent)] ${selectedIds.includes(row.id) ? 'bg-[var(--accent)]' : ''}`}
109
- onClick={() => onRowClick?.(row)}
110
- style={onRowClick ? { cursor: 'pointer' } : undefined}
111
- >
112
- <td className="px-4 py-3" onClick={(e) => e.stopPropagation()}>
113
- <input
114
- type="checkbox"
115
- checked={selectedIds.includes(row.id)}
116
- onChange={() => toggleRow(row.id)}
117
- className="rounded border-[var(--border)]"
118
- />
119
- </td>
120
- {columns.map((col) => (
121
- <td key={col.key} className="px-4 py-3">
122
- {row[col.key]}
123
- </td>
124
- ))}
125
- {rowActions && rowActions.length > 0 && (
126
- <td className="px-4 py-3" onClick={(e) => e.stopPropagation()}>
127
- <RowActionsMenu actions={rowActions} row={row} />
128
- </td>
129
- )}
130
- </tr>
131
- ))}
132
- </tbody>
133
- </table>
134
- </div>
135
- )
136
- }
137
-
138
- function RowActionsMenu({ actions, row }: { actions: RowAction[]; row: Row }) {
139
- const [open, setOpen] = useState(false)
140
- const ref = useRef<HTMLDivElement>(null)
141
-
142
- useEffect(() => {
143
- if (!open) return
144
- function handleClickOutside(e: MouseEvent) {
145
- if (ref.current && !ref.current.contains(e.target as Node)) {
146
- setOpen(false)
147
- }
148
- }
149
- document.addEventListener('mousedown', handleClickOutside)
150
- return () => document.removeEventListener('mousedown', handleClickOutside)
151
- }, [open])
152
-
153
- return (
154
- <div className="relative flex items-center justify-end gap-1" ref={ref}>
155
- {actions
156
- .filter((a) => a.icon)
157
- .map((action) => (
158
- <button
159
- key={action.key}
160
- onClick={() => action.onClick(row)}
161
- className="hover:bg-muted rounded p-1 text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
162
- aria-label={action.label}
163
- title={action.label}
164
- >
165
- {action.icon}
166
- </button>
167
- ))}
168
- <button
169
- onClick={() => setOpen((o) => !o)}
170
- className="hover:bg-muted rounded p-1"
171
- aria-label="More actions"
172
- >
173
- <MoreVerticalIcon />
174
- </button>
175
- {open && (
176
- <div className="absolute top-full right-0 z-50 mt-1 w-40 rounded-md border border-[var(--border)] bg-[var(--popover)] py-1 shadow-lg">
177
- {actions.map((action) => (
178
- <button
179
- key={action.key}
180
- className={`flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-[var(--accent)] ${
181
- action.destructive ? 'text-[var(--destructive)]' : ''
182
- }`}
183
- onClick={() => {
184
- action.onClick(row)
185
- setOpen(false)
186
- }}
187
- >
188
- {action.icon && <span className="h-4 w-4">{action.icon}</span>}
189
- {action.label}
190
- </button>
191
- ))}
192
- </div>
193
- )}
194
- </div>
195
- )
196
- }
197
-
198
- function MoreVerticalIcon() {
199
- return (
200
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
201
- <path strokeLinecap="round" strokeLinejoin="round" d="M12 5v.01M12 12v.01M12 19v.01" />
202
- </svg>
203
- )
204
- }
@@ -1,94 +0,0 @@
1
- 'use client'
2
-
3
- export interface PaginationProps {
4
- page: number
5
- perPage: number
6
- total: number
7
- onPageChange: (page: number) => void
8
- onPerPageChange: (perPage: number) => void
9
- }
10
-
11
- export function Pagination({
12
- page,
13
- perPage,
14
- total,
15
- onPageChange,
16
- onPerPageChange,
17
- }: PaginationProps) {
18
- const totalPages = Math.max(1, Math.ceil(total / perPage))
19
- const start = (page - 1) * perPage + 1
20
- const end = Math.min(page * perPage, total)
21
-
22
- function pageNumbers(): (number | 'ellipsis')[] {
23
- const pages: (number | 'ellipsis')[] = []
24
- for (let i = 1; i <= totalPages; i++) {
25
- if (i === 1 || i === totalPages || Math.abs(i - page) <= 1) {
26
- pages.push(i)
27
- } else if (pages[pages.length - 1] !== 'ellipsis') {
28
- pages.push('ellipsis')
29
- }
30
- }
31
- return pages
32
- }
33
-
34
- return (
35
- <div className="flex items-center justify-between text-sm">
36
- <span className="text-[var(--muted-foreground)]">
37
- {start}–{end} of {total} results
38
- </span>
39
-
40
- <div className="flex items-center gap-2">
41
- <select
42
- value={perPage}
43
- onChange={(e) => {
44
- onPerPageChange(Number(e.target.value))
45
- onPageChange(1)
46
- }}
47
- className="rounded-md border border-[var(--border)] bg-[var(--input-background)] px-2 py-1 text-sm"
48
- >
49
- {[10, 25, 50, 100].map((n) => (
50
- <option key={n} value={n}>
51
- {n} / page
52
- </option>
53
- ))}
54
- </select>
55
-
56
- <nav className="flex items-center gap-1">
57
- <button
58
- onClick={() => onPageChange(page - 1)}
59
- disabled={page <= 1}
60
- className="rounded-md px-2 py-1 hover:bg-[var(--accent)] disabled:opacity-50"
61
- >
62
- Prev
63
- </button>
64
- {pageNumbers().map((p, i) =>
65
- p === 'ellipsis' ? (
66
- <span key={`e${i}`} className="px-1 text-[var(--muted-foreground)]">
67
- …
68
- </span>
69
- ) : (
70
- <button
71
- key={p}
72
- onClick={() => onPageChange(p)}
73
- className={`min-w-[2rem] rounded-md px-2 py-1 ${
74
- p === page
75
- ? 'bg-[var(--primary)] text-[var(--primary-foreground)]'
76
- : 'hover:bg-[var(--accent)]'
77
- }`}
78
- >
79
- {p}
80
- </button>
81
- ),
82
- )}
83
- <button
84
- onClick={() => onPageChange(page + 1)}
85
- disabled={page >= totalPages}
86
- className="rounded-md px-2 py-1 hover:bg-[var(--accent)] disabled:opacity-50"
87
- >
88
- Next
89
- </button>
90
- </nav>
91
- </div>
92
- </div>
93
- )
94
- }
@@ -1,53 +0,0 @@
1
- import { forwardRef, type SelectHTMLAttributes, type ReactNode } from 'react'
2
- import { cv, type VariantProps } from '../../lib/cv.js'
3
- import { formControlBase, formControlState } from './form-control.js'
4
-
5
- const select = cv(`${formControlBase} appearance-none pr-8`, {
6
- variants: {
7
- size: {
8
- sm: 'py-1.5 pr-7 pl-3 text-[length:var(--fs-sub)]',
9
- md: '',
10
- lg: 'py-2.5 pr-9 pl-3',
11
- },
12
- state: {
13
- default: formControlState.default,
14
- invalid: formControlState.invalid,
15
- valid: formControlState.valid,
16
- },
17
- },
18
- defaultVariants: { size: 'md', state: 'default' },
19
- })
20
-
21
- export type SelectVariants = VariantProps<typeof select>
22
-
23
- export interface SelectProps
24
- extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'>, SelectVariants {
25
- children?: ReactNode
26
- }
27
-
28
- export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(
29
- { size, state, className, children, ...rest },
30
- ref,
31
- ) {
32
- return (
33
- <div className="relative">
34
- <select ref={ref} className={select({ size, state, class: className })} {...rest}>
35
- {children}
36
- </select>
37
- <svg
38
- aria-hidden
39
- className="pointer-events-none absolute top-1/2 right-2 h-4 w-4 -translate-y-1/2 text-[var(--muted)]"
40
- viewBox="0 0 20 20"
41
- fill="currentColor"
42
- >
43
- <path
44
- fillRule="evenodd"
45
- d="M5.23 7.21a.75.75 0 011.06.02L10 11.06l3.71-3.83a.75.75 0 111.08 1.04l-4.25 4.39a.75.75 0 01-1.08 0L5.21 8.27a.75.75 0 01.02-1.06z"
46
- clipRule="evenodd"
47
- />
48
- </svg>
49
- </div>
50
- )
51
- })
52
-
53
- export { select as selectVariants }
@@ -1,72 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useCallback } from 'react'
4
-
5
- type ToastType = 'success' | 'error' | 'warning' | 'info'
6
-
7
- interface Toast {
8
- id: string
9
- type: ToastType
10
- message: string
11
- }
12
-
13
- const typeClasses: Record<ToastType, string> = {
14
- success: 'border-success bg-success/10 text-success',
15
- error: 'border-destructive bg-destructive/10 text-destructive',
16
- warning: 'border-warning bg-warning/10 text-warning',
17
- info: 'border-info bg-info/10 text-info',
18
- }
19
-
20
- export function useToast() {
21
- const [toasts, setToasts] = useState<Toast[]>([])
22
-
23
- const addToast = useCallback((type: ToastType, message: string) => {
24
- const id = crypto.randomUUID()
25
- setToasts((prev) => [...prev, { id, type, message }])
26
- setTimeout(() => {
27
- setToasts((prev) => prev.filter((t) => t.id !== id))
28
- }, 5000)
29
- }, [])
30
-
31
- const dismissToast = useCallback((id: string) => {
32
- setToasts((prev) => prev.filter((t) => t.id !== id))
33
- }, [])
34
-
35
- return { toasts, addToast, dismissToast }
36
- }
37
-
38
- export interface ToastContainerProps {
39
- toasts: Toast[]
40
- onDismiss: (id: string) => void
41
- }
42
-
43
- export function ToastContainer({ toasts, onDismiss }: ToastContainerProps) {
44
- if (toasts.length === 0) return null
45
-
46
- return (
47
- <div className="fixed right-4 bottom-4 z-[100] flex flex-col gap-2">
48
- {toasts.map((toast) => (
49
- <div
50
- key={toast.id}
51
- className={`flex items-center gap-3 rounded-md border-l-4 px-4 py-3 shadow-lg ${typeClasses[toast.type]}`}
52
- >
53
- <p className="flex-1 text-sm">{toast.message}</p>
54
- <button
55
- onClick={() => onDismiss(toast.id)}
56
- className="shrink-0 opacity-60 hover:opacity-100"
57
- >
58
- <svg
59
- className="h-4 w-4"
60
- fill="none"
61
- viewBox="0 0 24 24"
62
- stroke="currentColor"
63
- strokeWidth={2}
64
- >
65
- <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
66
- </svg>
67
- </button>
68
- </div>
69
- ))}
70
- </div>
71
- )
72
- }
@@ -1,61 +0,0 @@
1
- export { Button, buttonVariants } from './Button.js'
2
- export type { ButtonProps, ButtonVariants } from './Button.js'
3
- export { Badge, badgeVariants, STATUS_TONE, STATUS_LABEL } from './Badge.js'
4
- export type { BadgeProps, BadgeVariants, DocumentStatus } from './Badge.js'
5
- export {
6
- Card,
7
- CardHeader,
8
- CardTitle,
9
- CardDescription,
10
- CardContent,
11
- CardFooter,
12
- cardVariants,
13
- } from './Card.js'
14
- export type { CardProps, CardVariants } from './Card.js'
15
- export { Input, inputVariants } from './Input.js'
16
- export type { InputProps, InputVariants } from './Input.js'
17
- export { Select, selectVariants } from './Select.js'
18
- export type { SelectProps, SelectVariants } from './Select.js'
19
- export { Avatar } from './Avatar.js'
20
- export type { AvatarProps } from './Avatar.js'
21
- export { EmptyState } from './EmptyState.js'
22
- export type { EmptyStateProps } from './EmptyState.js'
23
- export { Skeleton } from './Skeleton.js'
24
- export type { SkeletonProps } from './Skeleton.js'
25
- export { useToast, ToastContainer } from './Toast.js'
26
- export type { ToastContainerProps } from './Toast.js'
27
- export { Modal } from './Modal.js'
28
- export type { ModalProps } from './Modal.js'
29
- export { ConfirmDialog } from './ConfirmDialog.js'
30
- export type { ConfirmDialogProps } from './ConfirmDialog.js'
31
- export { ReauthDialog } from './ReauthDialog.js'
32
- export type { ReauthDialogProps } from './ReauthDialog.js'
33
- export { DataTable } from './DataTable.js'
34
- export type { DataTableProps } from './DataTable.js'
35
- export { Pagination } from './Pagination.js'
36
- export type { PaginationProps } from './Pagination.js'
37
- export { SearchInput } from './SearchInput.js'
38
- export type { SearchInputProps } from './SearchInput.js'
39
- export { Toggle, toggleTrackVariants, toggleThumbVariants } from './Toggle.js'
40
- export type { ToggleProps, ToggleVariants } from './Toggle.js'
41
- export { StatusBadge, statusBadgeVariants } from './StatusBadge.js'
42
- export type { StatusBadgeProps, StatusBadgeVariants, StatusBadgeTone } from './StatusBadge.js'
43
- export { FilterPill } from './FilterPill.js'
44
- export type { FilterPillProps } from './FilterPill.js'
45
- export { StatPill } from './StatPill.js'
46
- export type { StatPillProps } from './StatPill.js'
47
- export { RowActions, RowActionButton } from './RowActions.js'
48
- export type { RowActionButtonProps } from './RowActions.js'
49
- export {
50
- SplitPaneLayout,
51
- SplitPaneList,
52
- InspectorPane,
53
- InspectorPaneHeader,
54
- InspectorPaneBody,
55
- InspectorPaneSection,
56
- InspectorPaneFooter,
57
- } from './InspectorPane.js'
58
- export type { InspectorPaneProps } from './InspectorPane.js'
59
- export { formControlBase, formControlState } from './form-control.js'
60
- export { CommandPalette } from './CommandPalette.js'
61
- export type { CommandPaletteProps } from './CommandPalette.js'
@@ -1,55 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useEffect, useCallback } from 'react'
4
-
5
- interface ContentLock {
6
- lockedBy: string | null
7
- lockedAt: Date | null
8
- isLocked: boolean
9
- isLockedByMe: boolean
10
- }
11
-
12
- export function useContentLock(
13
- documentId: string | undefined,
14
- userId: string,
15
- ): ContentLock & {
16
- acquireLock: () => Promise<boolean>
17
- releaseLock: () => Promise<void>
18
- } {
19
- const [lock, setLock] = useState<ContentLock>({
20
- lockedBy: null,
21
- lockedAt: null,
22
- isLocked: false,
23
- isLockedByMe: false,
24
- })
25
-
26
- const acquireLock = useCallback(async () => {
27
- if (!documentId) return false
28
- setLock({
29
- lockedBy: userId,
30
- lockedAt: new Date(),
31
- isLocked: true,
32
- isLockedByMe: true,
33
- })
34
- return true
35
- }, [documentId, userId])
36
-
37
- const releaseLock = useCallback(async () => {
38
- setLock({
39
- lockedBy: null,
40
- lockedAt: null,
41
- isLocked: false,
42
- isLockedByMe: false,
43
- })
44
- }, [])
45
-
46
- useEffect(() => {
47
- return () => {
48
- if (lock.isLockedByMe) {
49
- releaseLock()
50
- }
51
- }
52
- }, [lock.isLockedByMe, releaseLock])
53
-
54
- return { ...lock, acquireLock, releaseLock }
55
- }
@@ -1,14 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useEffect } from 'react'
4
-
5
- export function useDebounce<T>(value: T, delayMs: number): T {
6
- const [debouncedValue, setDebouncedValue] = useState(value)
7
-
8
- useEffect(() => {
9
- const timer = setTimeout(() => setDebouncedValue(value), delayMs)
10
- return () => clearTimeout(timer)
11
- }, [value, delayMs])
12
-
13
- return debouncedValue
14
- }