@marktiderman/genesis-ui 1.3.0 → 2.1.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 (297) hide show
  1. package/LICENSE +21 -0
  2. package/dist/AppShell-sQT0UbXg.d.ts +198 -0
  3. package/dist/{chunk-NJMO3VPA.js → chunk-22XB3Q6H.js} +8 -8
  4. package/dist/chunk-22XB3Q6H.js.map +1 -0
  5. package/dist/{chunk-2MXMWBDV.js → chunk-27ELYTGE.js} +6 -6
  6. package/dist/chunk-27ELYTGE.js.map +1 -0
  7. package/dist/chunk-46TZGMFW.js +159 -0
  8. package/dist/chunk-46TZGMFW.js.map +1 -0
  9. package/dist/chunk-4CQHPWJD.js +117 -0
  10. package/dist/chunk-4CQHPWJD.js.map +1 -0
  11. package/dist/{chunk-ZDAT5JDH.js → chunk-65SPT7EA.js} +24 -6
  12. package/dist/chunk-65SPT7EA.js.map +1 -0
  13. package/dist/chunk-6KHY647C.js +67 -0
  14. package/dist/chunk-6KHY647C.js.map +1 -0
  15. package/dist/chunk-6M4NHHKG.js +51 -0
  16. package/dist/chunk-6M4NHHKG.js.map +1 -0
  17. package/dist/chunk-6Q6CLLJ4.js +9 -0
  18. package/dist/chunk-6Q6CLLJ4.js.map +1 -0
  19. package/dist/{chunk-UGHQFQOE.js → chunk-6TVMQH6M.js} +28 -28
  20. package/dist/chunk-6TVMQH6M.js.map +1 -0
  21. package/dist/{chunk-6VVVGYKS.js → chunk-6XPMU65K.js} +5 -5
  22. package/dist/{chunk-6VVVGYKS.js.map → chunk-6XPMU65K.js.map} +1 -1
  23. package/dist/{chunk-YZEA5TGK.js → chunk-7XMZVISM.js} +16 -16
  24. package/dist/chunk-7XMZVISM.js.map +1 -0
  25. package/dist/chunk-A7AHVDG7.js +52 -0
  26. package/dist/chunk-A7AHVDG7.js.map +1 -0
  27. package/dist/chunk-AFZ76Q26.js +84 -0
  28. package/dist/chunk-AFZ76Q26.js.map +1 -0
  29. package/dist/{chunk-4V4H2ZM7.js → chunk-AL5TMEZQ.js} +31 -31
  30. package/dist/chunk-AL5TMEZQ.js.map +1 -0
  31. package/dist/{chunk-AUECDWP2.js → chunk-AOZGQM6W.js} +3 -3
  32. package/dist/chunk-AOZGQM6W.js.map +1 -0
  33. package/dist/chunk-ARJI2JUV.js +122 -0
  34. package/dist/chunk-ARJI2JUV.js.map +1 -0
  35. package/dist/chunk-AVFZ4P4B.js +25 -0
  36. package/dist/chunk-AVFZ4P4B.js.map +1 -0
  37. package/dist/chunk-B2GIBUQD.js +11 -0
  38. package/dist/chunk-B2GIBUQD.js.map +1 -0
  39. package/dist/{chunk-JXI2MYL3.js → chunk-C46ITXE4.js} +5 -5
  40. package/dist/chunk-C46ITXE4.js.map +1 -0
  41. package/dist/{chunk-A2OXCNNY.js → chunk-CNTWQSUT.js} +3 -3
  42. package/dist/{chunk-A2OXCNNY.js.map → chunk-CNTWQSUT.js.map} +1 -1
  43. package/dist/chunk-D2LIXA2Y.js +65 -0
  44. package/dist/chunk-D2LIXA2Y.js.map +1 -0
  45. package/dist/{chunk-T5VX5DYO.js → chunk-F47U5KNW.js} +5 -5
  46. package/dist/chunk-F47U5KNW.js.map +1 -0
  47. package/dist/chunk-FEJAZFP3.js +1100 -0
  48. package/dist/chunk-FEJAZFP3.js.map +1 -0
  49. package/dist/{chunk-2B3MFHBQ.js → chunk-FK42ZGGV.js} +21 -21
  50. package/dist/chunk-FK42ZGGV.js.map +1 -0
  51. package/dist/{chunk-XISSLIMH.js → chunk-FTTNGGLA.js} +2 -2
  52. package/dist/{chunk-XISSLIMH.js.map → chunk-FTTNGGLA.js.map} +1 -1
  53. package/dist/chunk-G5YKBPBF.js +74 -0
  54. package/dist/chunk-G5YKBPBF.js.map +1 -0
  55. package/dist/{chunk-QLCDAFS7.js → chunk-GDFNAHI4.js} +10 -6
  56. package/dist/chunk-GDFNAHI4.js.map +1 -0
  57. package/dist/{chunk-KB5T5LWM.js → chunk-IJCT5IJD.js} +3 -3
  58. package/dist/{chunk-KB5T5LWM.js.map → chunk-IJCT5IJD.js.map} +1 -1
  59. package/dist/{chunk-44TULYGG.js → chunk-J6FBA7PH.js} +3 -3
  60. package/dist/{chunk-44TULYGG.js.map → chunk-J6FBA7PH.js.map} +1 -1
  61. package/dist/chunk-JAMLFMDS.js +12 -0
  62. package/dist/chunk-JAMLFMDS.js.map +1 -0
  63. package/dist/{chunk-C6H7AMO4.js → chunk-LNFF2RBD.js} +9 -9
  64. package/dist/chunk-LNFF2RBD.js.map +1 -0
  65. package/dist/{chunk-QBZMY2AF.js → chunk-M62CHO3N.js} +18 -18
  66. package/dist/chunk-M62CHO3N.js.map +1 -0
  67. package/dist/{chunk-5Q4FABZQ.js → chunk-NUXW6NPP.js} +8 -8
  68. package/dist/chunk-NUXW6NPP.js.map +1 -0
  69. package/dist/{chunk-ZJFSZFPI.js → chunk-NWSCYLPT.js} +77 -18
  70. package/dist/chunk-NWSCYLPT.js.map +1 -0
  71. package/dist/{chunk-63FW5ZUA.js → chunk-P3ZL6FGR.js} +7 -7
  72. package/dist/chunk-P3ZL6FGR.js.map +1 -0
  73. package/dist/chunk-P64MFQXZ.js +191 -0
  74. package/dist/chunk-P64MFQXZ.js.map +1 -0
  75. package/dist/chunk-PLIYF6KI.js +52 -0
  76. package/dist/chunk-PLIYF6KI.js.map +1 -0
  77. package/dist/chunk-PSR47JRA.js +26 -0
  78. package/dist/chunk-PSR47JRA.js.map +1 -0
  79. package/dist/{chunk-SBJV3K4G.js → chunk-QJ6P2DW6.js} +28 -28
  80. package/dist/chunk-QJ6P2DW6.js.map +1 -0
  81. package/dist/{chunk-IP6TMT3D.js → chunk-R7QFP6EL.js} +3 -3
  82. package/dist/chunk-R7QFP6EL.js.map +1 -0
  83. package/dist/{chunk-WZWR2ELB.js → chunk-SEBU6JCK.js} +6 -6
  84. package/dist/chunk-SEBU6JCK.js.map +1 -0
  85. package/dist/{chunk-7OBL3H5P.js → chunk-SEFK4NZV.js} +3 -3
  86. package/dist/chunk-SEFK4NZV.js.map +1 -0
  87. package/dist/chunk-SRIT4NFQ.js +67 -0
  88. package/dist/chunk-SRIT4NFQ.js.map +1 -0
  89. package/dist/chunk-SY62XJFA.js +19 -0
  90. package/dist/chunk-SY62XJFA.js.map +1 -0
  91. package/dist/{chunk-SVXDWPLO.js → chunk-THD3YOOZ.js} +17 -17
  92. package/dist/chunk-THD3YOOZ.js.map +1 -0
  93. package/dist/chunk-VXFYETRK.js +58 -0
  94. package/dist/chunk-VXFYETRK.js.map +1 -0
  95. package/dist/chunk-XBX6QMR5.js +58 -0
  96. package/dist/chunk-XBX6QMR5.js.map +1 -0
  97. package/dist/{chunk-SCUT2ZCD.js → chunk-XCGZPFT7.js} +17 -17
  98. package/dist/chunk-XCGZPFT7.js.map +1 -0
  99. package/dist/chunk-XMK3T4TA.js +73 -0
  100. package/dist/chunk-XMK3T4TA.js.map +1 -0
  101. package/dist/chunk-YJ6MPS6U.js +226 -0
  102. package/dist/chunk-YJ6MPS6U.js.map +1 -0
  103. package/dist/chunk-YRYQXU3G.js +38 -0
  104. package/dist/chunk-YRYQXU3G.js.map +1 -0
  105. package/dist/{chunk-5J7BP5DI.js → chunk-YWFPMND7.js} +10 -10
  106. package/dist/chunk-YWFPMND7.js.map +1 -0
  107. package/dist/chunk-YYEGAFUE.js +94 -0
  108. package/dist/chunk-YYEGAFUE.js.map +1 -0
  109. package/dist/{chunk-TKA4LOMT.js → chunk-ZZ7H7VVX.js} +8 -8
  110. package/dist/chunk-ZZ7H7VVX.js.map +1 -0
  111. package/dist/components/data/index.d.ts +318 -228
  112. package/dist/components/data/index.js +591 -1394
  113. package/dist/components/data/index.js.map +1 -1
  114. package/dist/components/layout/dashboard-page.d.ts +4 -0
  115. package/dist/components/layout/dashboard-page.js +5 -0
  116. package/dist/components/layout/dashboard-page.js.map +1 -0
  117. package/dist/components/layout/detail-page.d.ts +91 -0
  118. package/dist/components/layout/detail-page.js +6 -0
  119. package/dist/components/layout/detail-page.js.map +1 -0
  120. package/dist/components/layout/form-page.d.ts +82 -0
  121. package/dist/components/layout/form-page.js +5 -0
  122. package/dist/components/layout/form-page.js.map +1 -0
  123. package/dist/components/layout/index.d.ts +14 -0
  124. package/dist/components/layout/index.js +21 -0
  125. package/dist/components/layout/index.js.map +1 -0
  126. package/dist/components/layout/settings-page.d.ts +114 -0
  127. package/dist/components/layout/settings-page.js +6 -0
  128. package/dist/components/layout/settings-page.js.map +1 -0
  129. package/dist/components/patterns/empty-state.d.ts +73 -0
  130. package/dist/components/{ui → patterns}/empty-state.js +2 -1
  131. package/dist/components/{ui → patterns}/form-field.d.ts +5 -6
  132. package/dist/components/{ui → patterns}/form-field.js +2 -2
  133. package/dist/components/patterns/index.d.ts +17 -0
  134. package/dist/components/patterns/index.js +18 -0
  135. package/dist/components/patterns/index.js.map +1 -0
  136. package/dist/components/patterns/page-loading.d.ts +25 -0
  137. package/dist/components/patterns/page-loading.js +5 -0
  138. package/dist/components/patterns/page-loading.js.map +1 -0
  139. package/dist/components/patterns/settings-row.d.ts +41 -0
  140. package/dist/components/patterns/settings-row.js +6 -0
  141. package/dist/components/patterns/settings-row.js.map +1 -0
  142. package/dist/components/patterns/status-badge.d.ts +37 -0
  143. package/dist/components/patterns/status-badge.js +4 -0
  144. package/dist/components/patterns/status-badge.js.map +1 -0
  145. package/dist/components/patterns/toggle-row.d.ts +35 -0
  146. package/dist/components/patterns/toggle-row.js +8 -0
  147. package/dist/components/patterns/toggle-row.js.map +1 -0
  148. package/dist/components/patterns/user-avatar.d.ts +34 -0
  149. package/dist/components/patterns/user-avatar.js +5 -0
  150. package/dist/components/patterns/user-avatar.js.map +1 -0
  151. package/dist/components/ui/accessible-icon.d.ts +47 -0
  152. package/dist/components/ui/accessible-icon.js +3 -0
  153. package/dist/components/ui/accessible-icon.js.map +1 -0
  154. package/dist/components/ui/accordion.d.ts +5 -5
  155. package/dist/components/ui/accordion.js +1 -1
  156. package/dist/components/ui/alert-dialog.d.ts +12 -13
  157. package/dist/components/ui/alert-dialog.js +1 -1
  158. package/dist/components/ui/aspect-ratio.d.ts +2 -2
  159. package/dist/components/ui/aspect-ratio.js +1 -1
  160. package/dist/components/ui/avatar.d.ts +4 -4
  161. package/dist/components/ui/avatar.js +1 -1
  162. package/dist/components/ui/badge.d.ts +1 -2
  163. package/dist/components/ui/breadcrumb.d.ts +2 -3
  164. package/dist/components/ui/button-group.d.ts +1 -2
  165. package/dist/components/ui/button.d.ts +73 -8
  166. package/dist/components/ui/button.js +1 -1
  167. package/dist/components/ui/calendar.d.ts +2 -3
  168. package/dist/components/ui/calendar.js +2 -2
  169. package/dist/components/ui/card.d.ts +6 -7
  170. package/dist/components/ui/carousel.d.ts +4 -4
  171. package/dist/components/ui/carousel.js +2 -2
  172. package/dist/components/ui/chart.d.ts +4 -5
  173. package/dist/components/ui/checkbox.d.ts +2 -2
  174. package/dist/components/ui/checkbox.js +1 -1
  175. package/dist/components/ui/collapsible.d.ts +4 -4
  176. package/dist/components/ui/collapsible.js +1 -1
  177. package/dist/components/ui/command-palette.d.ts +1 -2
  178. package/dist/components/ui/command-palette.js +3 -3
  179. package/dist/components/ui/command.d.ts +11 -12
  180. package/dist/components/ui/command.js +2 -2
  181. package/dist/components/ui/context-menu.d.ts +16 -17
  182. package/dist/components/ui/context-menu.js +1 -1
  183. package/dist/components/ui/date-picker.d.ts +2 -2
  184. package/dist/components/ui/date-picker.js +4 -4
  185. package/dist/components/ui/dialog.d.ts +11 -12
  186. package/dist/components/ui/dialog.js +1 -1
  187. package/dist/components/ui/drawer.d.ts +10 -11
  188. package/dist/components/ui/dropdown-menu.d.ts +16 -17
  189. package/dist/components/ui/dropdown-menu.js +1 -1
  190. package/dist/components/ui/hover-card.d.ts +4 -4
  191. package/dist/components/ui/hover-card.js +1 -1
  192. package/dist/components/ui/input-otp.d.ts +2 -2
  193. package/dist/components/ui/kbd.d.ts +1 -2
  194. package/dist/components/ui/label.d.ts +2 -2
  195. package/dist/components/ui/label.js +1 -1
  196. package/dist/components/ui/menubar.d.ts +17 -18
  197. package/dist/components/ui/menubar.js +1 -1
  198. package/dist/components/ui/navigation-menu.d.ts +9 -9
  199. package/dist/components/ui/navigation-menu.js +1 -1
  200. package/dist/components/ui/pagination.d.ts +5 -6
  201. package/dist/components/ui/pagination.js +2 -2
  202. package/dist/components/ui/password-toggle-field.d.ts +120 -0
  203. package/dist/components/ui/password-toggle-field.js +4 -0
  204. package/dist/components/ui/password-toggle-field.js.map +1 -0
  205. package/dist/components/ui/popover.d.ts +4 -4
  206. package/dist/components/ui/popover.js +1 -1
  207. package/dist/components/ui/progress.d.ts +1 -2
  208. package/dist/components/ui/radio-group.d.ts +3 -3
  209. package/dist/components/ui/radio-group.js +1 -1
  210. package/dist/components/ui/resizable.d.ts +3 -4
  211. package/dist/components/ui/scroll-area.d.ts +60 -3
  212. package/dist/components/ui/scroll-area.js +1 -1
  213. package/dist/components/ui/select.d.ts +9 -9
  214. package/dist/components/ui/select.js +1 -1
  215. package/dist/components/ui/separator.d.ts +1 -2
  216. package/dist/components/ui/sheet.d.ts +13 -12
  217. package/dist/components/ui/sheet.js +1 -1
  218. package/dist/components/ui/skeleton.d.ts +1 -2
  219. package/dist/components/ui/slider.d.ts +2 -2
  220. package/dist/components/ui/slider.js +1 -1
  221. package/dist/components/ui/sonner.d.ts +1 -2
  222. package/dist/components/ui/spinner.d.ts +1 -2
  223. package/dist/components/ui/switch.d.ts +2 -2
  224. package/dist/components/ui/switch.js +1 -1
  225. package/dist/components/ui/tabs.d.ts +29 -14
  226. package/dist/components/ui/tabs.js +1 -1
  227. package/dist/components/ui/toggle-group.d.ts +3 -3
  228. package/dist/components/ui/toggle-group.js +2 -2
  229. package/dist/components/ui/toggle.d.ts +2 -2
  230. package/dist/components/ui/toggle.js +1 -1
  231. package/dist/components/ui/toolbar.d.ts +104 -0
  232. package/dist/components/ui/toolbar.js +6 -0
  233. package/dist/components/ui/toolbar.js.map +1 -0
  234. package/dist/components/ui/tooltip.d.ts +46 -5
  235. package/dist/components/ui/tooltip.js +1 -1
  236. package/dist/components/ui/typography.d.ts +9 -10
  237. package/dist/components/ui/visually-hidden.d.ts +48 -0
  238. package/dist/components/ui/visually-hidden.js +4 -0
  239. package/dist/components/ui/visually-hidden.js.map +1 -0
  240. package/dist/dashboard-page-C0TihRl5.d.ts +107 -0
  241. package/dist/hooks/index.d.ts +2 -3
  242. package/dist/hooks/index.js +6 -6
  243. package/dist/hooks/use-keyboard-navigation.d.ts +58 -2
  244. package/dist/hooks/use-keyboard-navigation.js +1 -1
  245. package/dist/hooks/use-resource-page.d.ts +2 -3
  246. package/dist/hooks/use-resource-page.js +2 -2
  247. package/dist/hooks/use-view-preference.d.ts +2 -2
  248. package/dist/hooks/use-view-preference.js +1 -1
  249. package/dist/index.d.ts +22 -25
  250. package/dist/index.js +54 -38
  251. package/dist/spacing-BS6qECD4.d.ts +191 -0
  252. package/dist/split-Dk9f4Mi0.d.ts +57 -0
  253. package/dist/{use-resource-page-BXBv_Xah.d.ts → use-resource-page-DTQS011Q.d.ts} +18 -6
  254. package/dist/view-settings-kHKCHMjj.d.ts +12 -0
  255. package/dist/{ViewToggle-DDe_Luj2.d.ts → view-toggle-CahQ87PW.d.ts} +2 -2
  256. package/package.json +80 -39
  257. package/dist/chunk-2B3MFHBQ.js.map +0 -1
  258. package/dist/chunk-2MXMWBDV.js.map +0 -1
  259. package/dist/chunk-4V4H2ZM7.js.map +0 -1
  260. package/dist/chunk-5J7BP5DI.js.map +0 -1
  261. package/dist/chunk-5Q4FABZQ.js.map +0 -1
  262. package/dist/chunk-63FW5ZUA.js.map +0 -1
  263. package/dist/chunk-7OBL3H5P.js.map +0 -1
  264. package/dist/chunk-AUECDWP2.js.map +0 -1
  265. package/dist/chunk-C6H7AMO4.js.map +0 -1
  266. package/dist/chunk-EI5EGKHL.js +0 -32
  267. package/dist/chunk-EI5EGKHL.js.map +0 -1
  268. package/dist/chunk-IP6TMT3D.js.map +0 -1
  269. package/dist/chunk-JJ4NOMMI.js +0 -73
  270. package/dist/chunk-JJ4NOMMI.js.map +0 -1
  271. package/dist/chunk-JXI2MYL3.js.map +0 -1
  272. package/dist/chunk-KBS4BHME.js +0 -11
  273. package/dist/chunk-KBS4BHME.js.map +0 -1
  274. package/dist/chunk-LRXDZBV2.js +0 -26
  275. package/dist/chunk-LRXDZBV2.js.map +0 -1
  276. package/dist/chunk-NJMO3VPA.js.map +0 -1
  277. package/dist/chunk-OCTV3S4I.js +0 -29
  278. package/dist/chunk-OCTV3S4I.js.map +0 -1
  279. package/dist/chunk-QBZMY2AF.js.map +0 -1
  280. package/dist/chunk-QLCDAFS7.js.map +0 -1
  281. package/dist/chunk-SBJV3K4G.js.map +0 -1
  282. package/dist/chunk-SCUT2ZCD.js.map +0 -1
  283. package/dist/chunk-SVXDWPLO.js.map +0 -1
  284. package/dist/chunk-T465NJRL.js +0 -134
  285. package/dist/chunk-T465NJRL.js.map +0 -1
  286. package/dist/chunk-T5VX5DYO.js.map +0 -1
  287. package/dist/chunk-TKA4LOMT.js.map +0 -1
  288. package/dist/chunk-UGHQFQOE.js.map +0 -1
  289. package/dist/chunk-WALXVR6V.js +0 -9
  290. package/dist/chunk-WALXVR6V.js.map +0 -1
  291. package/dist/chunk-WZWR2ELB.js.map +0 -1
  292. package/dist/chunk-YZEA5TGK.js.map +0 -1
  293. package/dist/chunk-ZDAT5JDH.js.map +0 -1
  294. package/dist/chunk-ZJFSZFPI.js.map +0 -1
  295. package/dist/components/ui/empty-state.d.ts +0 -22
  296. /package/dist/components/{ui → patterns}/empty-state.js.map +0 -0
  297. /package/dist/components/{ui → patterns}/form-field.js.map +0 -0
@@ -1,84 +1,25 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
1
  import * as React from 'react';
3
2
  import { ReactNode, RefObject } from 'react';
3
+ import { c as PageHeaderOptions, A as AppShell$1, P as PageHeader$1 } from '../../AppShell-sQT0UbXg.js';
4
+ export { a as AppShellOptions, b as AppShellProps, N as NavItem, d as PageHeaderProps } from '../../AppShell-sQT0UbXg.js';
5
+ import { V as ViewMode } from '../../view-toggle-CahQ87PW.js';
6
+ export { a as ViewToggle } from '../../view-toggle-CahQ87PW.js';
4
7
  import { LucideIcon } from 'lucide-react';
5
- import { V as ViewMode } from '../../ViewToggle-DDe_Luj2.js';
6
- export { a as ViewToggle } from '../../ViewToggle-DDe_Luj2.js';
7
8
  import { Density } from '../../hooks/use-view-settings.js';
8
- import { a as ResourceColumnDef } from '../../use-resource-page-BXBv_Xah.js';
9
- export { D as DataTable, c as DataTableColumn, d as DataTableProps, L as LinkCell, R as ResourceActions, T as ThumbnailCell } from '../../use-resource-page-BXBv_Xah.js';
9
+ import { R as ResourceActions, a as ResourceColumnDef } from '../../use-resource-page-DTQS011Q.js';
10
+ export { D as DataTable, c as DataTableColumn, d as DataTableProps, L as LinkCell, T as ThumbnailCell } from '../../use-resource-page-DTQS011Q.js';
11
+ export { EmptyState } from '../patterns/empty-state.js';
12
+ export { V as ViewSettings } from '../../view-settings-kHKCHMjj.js';
10
13
  import { L as LinkComponent, N as NavigateFn } from '../../navigation-CpOEyUSb.js';
11
14
  export { D as DefaultLink, G as GenesisLinkProps, d as defaultNavigate, i as isPathActive } from '../../navigation-CpOEyUSb.js';
12
15
  import { UseFormReturn, Control, FieldErrors } from 'react-hook-form';
13
16
  import { WizardStep, UseResourceOptions } from '@marktiderman/genesis-core/hooks';
14
- import { FilterParam } from '@marktiderman/genesis-core/provider';
17
+ import { FilterParam, SortParam, BaseRecord, Identifier } from '@marktiderman/genesis-core/provider';
15
18
  import { ResourceFormFieldDef } from '@marktiderman/genesis-core';
16
19
  export { FieldType, ResourceFormFieldDef, SelectOption } from '@marktiderman/genesis-core';
17
20
  export { CommandPalette, CommandPaletteItem, CommandPaletteProps, useCommandPaletteHotkey } from '../ui/command-palette.js';
18
21
  export { UseSavedViewsReturn, useSavedViews } from '../../hooks/use-saved-views.js';
19
22
 
20
- /**
21
- * Declarative chrome for PageHeader — developer defaults + optional
22
- * in-header user toggles (Notion/Linear “customize view” pattern).
23
- *
24
- * @stability Beta
25
- */
26
- interface PageHeaderOptions {
27
- showIcon?: boolean;
28
- showSubtitle?: boolean;
29
- showCount?: boolean;
30
- showViewToggle?: boolean;
31
- showViewSettings?: boolean;
32
- showCreate?: boolean;
33
- /** Ghost ListFilter control in the actions cluster */
34
- showDetailsToggle?: boolean;
35
- /** Quiet hint beside actions while details are collapsed */
36
- showDetailsHint?: boolean;
37
- /** Move subtitle into the details panel (default true when details exist) */
38
- subtitleInDetails?: boolean;
39
- defaultDetailsOpen?: boolean;
40
- detailsLabel?: string;
41
- /**
42
- * Show the in-header Header options popover so users can customize chrome.
43
- * Default true when the header has more than one chrome affordance.
44
- */
45
- configurable?: boolean;
46
- }
47
- interface PageHeaderProps {
48
- title: string;
49
- subtitle?: string;
50
- icon?: LucideIcon;
51
- /**
52
- * Header chrome config (developer defaults). Merged under user picks from
53
- * the in-header options menu when `options.configurable` / storage is on.
54
- */
55
- options?: PageHeaderOptions;
56
- /** Persist user header-option overrides (localStorage) */
57
- optionsStorageKey?: string;
58
- /** Extra trailing actions (after create); prefer first-class slots below */
59
- actions?: ReactNode;
60
- /** Collapsible details region below the title row */
61
- details?: ReactNode;
62
- detailsOpen?: boolean;
63
- onDetailsOpenChange?: (open: boolean) => void;
64
- detailsActive?: boolean;
65
- detailsHint?: ReactNode;
66
- /** Count badge */
67
- count?: number;
68
- totalCount?: number;
69
- /** Singular entity for “N rows” copy when unfiltered */
70
- entityName?: string;
71
- countActive?: boolean;
72
- viewMode?: ViewMode;
73
- onViewModeChange?: (mode: ViewMode) => void;
74
- pageSize?: number;
75
- onPageSizeChange?: (size: number) => void;
76
- density?: Density;
77
- onDensityChange?: (density: Density) => void;
78
- createAction?: ReactNode;
79
- }
80
- declare function PageHeader({ title, subtitle, icon: Icon, options: optionsProp, optionsStorageKey, actions, details, detailsOpen, onDetailsOpenChange, detailsActive, detailsHint, count, totalCount, entityName, countActive, viewMode, onViewModeChange, pageSize, onPageSizeChange, density, onDensityChange, createAction, }: PageHeaderProps): react_jsx_runtime.JSX.Element;
81
-
82
23
  interface DataPageShellProps {
83
24
  /** Display title for the page */
84
25
  title: string;
@@ -132,7 +73,7 @@ interface DataPageShellProps {
132
73
  headerOptionsStorageKey?: string;
133
74
  children: ReactNode;
134
75
  }
135
- declare function DataPageShell({ title, icon, entityName, subtitle, createAction, isLoading, isEmpty, emptyIcon, emptyMessage, emptyAction, hasError, errorMessage, onRetry, count, totalCount, viewMode, onViewModeChange, pageSize, onPageSizeChange, density, onDensityChange, filters, hasActiveFilters, onClearFilters, filtersCollapsible, defaultFiltersOpen, filtersOpen, onFiltersOpenChange, filtersLabel, filtersHint, headerOptions, headerOptionsStorageKey, children, }: DataPageShellProps): react_jsx_runtime.JSX.Element;
76
+ declare function DataPageShell({ title, icon, entityName, subtitle, createAction, isLoading, isEmpty, emptyIcon, emptyMessage, emptyAction, hasError, errorMessage, onRetry, count, totalCount, viewMode, onViewModeChange, pageSize, onPageSizeChange, density, onDensityChange, filters, hasActiveFilters, onClearFilters, filtersCollapsible, defaultFiltersOpen, filtersOpen, onFiltersOpenChange, filtersLabel, filtersHint, headerOptions, headerOptionsStorageKey, children, }: DataPageShellProps): React.JSX.Element;
136
77
 
137
78
  interface FilterOption {
138
79
  value: string;
@@ -150,7 +91,7 @@ interface FilterComboboxProps {
150
91
  /** Optional map of value -> display label */
151
92
  labelMap?: Record<string, string>;
152
93
  }
153
- declare function FilterCombobox({ label, icon: Icon, options, selected, onChange, searchPlaceholder, allLabel, labelMap, }: FilterComboboxProps): react_jsx_runtime.JSX.Element;
94
+ declare function FilterCombobox({ label, icon: Icon, options, selected, onChange, searchPlaceholder, allLabel, labelMap, }: FilterComboboxProps): React.JSX.Element;
154
95
 
155
96
  interface DataFilterConfig {
156
97
  key: string;
@@ -200,7 +141,7 @@ interface DataFiltersProps {
200
141
  /** Expose the search input ref for keyboard nav "/" shortcut */
201
142
  searchInputRef?: React.RefObject<HTMLInputElement | null>;
202
143
  }
203
- declare function DataFilters({ search, onSearchChange, searchPlaceholder, sort, onSortChange, sortOptions, filters, statusChips, savedViews, onLoadView, onSaveView, onDeleteView, canSaveViews, onViewSaved, onClearAll, searchInputRef, }: DataFiltersProps): react_jsx_runtime.JSX.Element;
144
+ declare function DataFilters({ search, onSearchChange, searchPlaceholder, sort, onSortChange, sortOptions, filters, statusChips, savedViews, onLoadView, onSaveView, onDeleteView, canSaveViews, onViewSaved, onClearAll, searchInputRef, }: DataFiltersProps): React.JSX.Element;
204
145
 
205
146
  interface DataGridProps<T> {
206
147
  items: T[];
@@ -224,7 +165,7 @@ interface DataGridProps<T> {
224
165
  /** Keyboard navigation: container ref for scroll management */
225
166
  keyboardContainerRef?: RefObject<HTMLDivElement | null>;
226
167
  }
227
- declare function DataGrid<T>({ items, viewMode, batchSize, gridCols, renderCard, renderTable, renderListItem, staggerAnimation, getKey, focusedIndex, keyboardContainerRef, }: DataGridProps<T>): react_jsx_runtime.JSX.Element;
168
+ declare function DataGrid<T>({ items, viewMode, batchSize, gridCols, renderCard, renderTable, renderListItem, staggerAnimation, getKey, focusedIndex, keyboardContainerRef, }: DataGridProps<T>): React.JSX.Element;
228
169
 
229
170
  interface BulkAction {
230
171
  label: string;
@@ -239,7 +180,7 @@ interface DataBulkBarProps {
239
180
  onClearSelection: () => void;
240
181
  actions: BulkAction[];
241
182
  }
242
- declare function DataBulkBar({ selected, totalCount, onToggleAll, onClearSelection, actions, }: DataBulkBarProps): react_jsx_runtime.JSX.Element | null;
183
+ declare function DataBulkBar({ selected, totalCount, onToggleAll, onClearSelection, actions, }: DataBulkBarProps): React.JSX.Element | null;
243
184
 
244
185
  /**
245
186
  * DateCell -- shows relative date by default, formatted date otherwise.
@@ -260,25 +201,7 @@ declare function CurrencyCell(currency?: string, locale?: string): (_item: unkno
260
201
  /**
261
202
  * BadgeCell -- status badge with configurable color map.
262
203
  */
263
- declare function BadgeCell(colorMap?: Record<string, "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "info" | "muted">): (_item: unknown, value: unknown) => react_jsx_runtime.JSX.Element | "—";
264
-
265
- interface EmptyStateProps {
266
- icon?: LucideIcon;
267
- message?: string;
268
- action?: ReactNode;
269
- /** If true, shows a "no results" message with clear button */
270
- hasFilters?: boolean;
271
- onClearFilters?: () => void;
272
- }
273
- declare function EmptyState({ icon: Icon, message, action, hasFilters, onClearFilters, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
274
-
275
- interface ViewSettingsProps {
276
- pageSize: number;
277
- onPageSizeChange: (size: number) => void;
278
- density: Density;
279
- onDensityChange: (density: Density) => void;
280
- }
281
- declare function ViewSettings({ pageSize, onPageSizeChange, density, onDensityChange, }: ViewSettingsProps): react_jsx_runtime.JSX.Element;
204
+ declare function BadgeCell(colorMap?: Record<string, "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "info" | "muted">): (_item: unknown, value: unknown) => React.JSX.Element | "—";
282
205
 
283
206
  type StatCardColor = "primary" | "success" | "warning" | "info" | "destructive" | "muted";
284
207
  interface StatCardProps {
@@ -300,7 +223,7 @@ interface StatCardProps {
300
223
  };
301
224
  className?: string;
302
225
  }
303
- declare function StatCard({ label, value, icon: Icon, color, href, linkComponent: Link, trend, className, }: StatCardProps): react_jsx_runtime.JSX.Element;
226
+ declare function StatCard({ label, value, icon: Icon, color, href, linkComponent: Link, trend, className, }: StatCardProps): React.JSX.Element;
304
227
 
305
228
  type ColumnStatus = "neutral" | "warning" | "success" | "info" | "destructive" | "primary";
306
229
  interface KanbanColumn<T> {
@@ -320,7 +243,7 @@ interface KanbanBoardProps<T> {
320
243
  emptyMessage?: string;
321
244
  className?: string;
322
245
  }
323
- declare function KanbanBoard<T>({ columns, renderCard, emptyMessage, className, }: KanbanBoardProps<T>): react_jsx_runtime.JSX.Element;
246
+ declare function KanbanBoard<T>({ columns, renderCard, emptyMessage, className, }: KanbanBoardProps<T>): React.JSX.Element;
324
247
 
325
248
  interface DataListProps<T> {
326
249
  items: T[];
@@ -328,8 +251,15 @@ interface DataListProps<T> {
328
251
  emptyMessage?: string;
329
252
  className?: string;
330
253
  }
331
- declare function DataList<T>({ items, renderItem, emptyMessage, className, }: DataListProps<T>): react_jsx_runtime.JSX.Element;
254
+ declare function DataList<T>({ items, renderItem, emptyMessage, className, }: DataListProps<T>): React.JSX.Element;
332
255
 
256
+ /**
257
+ * Props for {@link DetailPanel} — a shell-agnostic record detail view.
258
+ * `layout` selects only the surrounding shell (inline / dialog / sheet);
259
+ * the header and content below it render identically across all three.
260
+ *
261
+ * @stability Beta
262
+ */
333
263
  interface DetailPanelProps<T> {
334
264
  /** The record to display */
335
265
  item: T | null;
@@ -353,17 +283,93 @@ interface DetailPanelProps<T> {
353
283
  label: string;
354
284
  render?: (value: unknown, item: T) => ReactNode;
355
285
  }>;
356
- /** Panel width */
286
+ /**
287
+ * Panel width. For `"sheet"` / `"inline"` this is a fixed pixel width
288
+ * (matching this component's original, pre-`layout` sizing exactly). For
289
+ * `"dialog"` it maps to Tailwind's modal max-width scale instead, since a
290
+ * centered modal has a different sizing idiom than an edge-anchored panel.
291
+ */
357
292
  width?: "sm" | "md" | "lg";
293
+ /**
294
+ * Rendering shell for the header + content below.
295
+ * - `"sheet"` (default): fixed, right-anchored slide-in panel, composed
296
+ * from the shared `Sheet` primitive. Matches this component's original
297
+ * (pre-`layout`-prop) behavior — existing consumers that don't pass
298
+ * `layout` see no change, other than an overlay now present at all
299
+ * breakpoints (previously mobile-only) since it's a real `Sheet`.
300
+ * - `"dialog"`: centered modal overlay, composed from the shared `Dialog`
301
+ * primitive.
302
+ * - `"inline"`: plain in-flow panel — no overlay, backdrop, or fixed
303
+ * positioning — for master-detail / split-pane layouts.
304
+ */
305
+ layout?: "inline" | "dialog" | "sheet";
358
306
  }
359
- declare function DetailPanel<T extends Record<string, unknown>>({ item, open, onClose, title, subtitle, onEdit, onDelete, children, fields, width, }: DetailPanelProps<T>): react_jsx_runtime.JSX.Element | null;
307
+ declare function DetailPanel<T extends Record<string, unknown>>({ item, open, onClose, title, subtitle, onEdit, onDelete, children, fields, width, layout, }: DetailPanelProps<T>): React.JSX.Element | null;
360
308
 
309
+ /**
310
+ * Row-bound actions handed to `renderCard`, on top of the resource-wide
311
+ * `ResourceActions`. `open` is per-row, which is why it lives here rather
312
+ * than on `ResourceActions` — that object is built once and shared by every
313
+ * row and column, so it cannot carry a row-specific callback.
314
+ *
315
+ * @stability Beta
316
+ */
317
+ interface ResourceCardActions<T> extends ResourceActions<T> {
318
+ /**
319
+ * Activate this row — opens the configured detail panel / modal / route,
320
+ * exactly as clicking the built-in card does. Wire it to your card's
321
+ * `onClick` (and call `stopPropagation` on any nested control that should
322
+ * not also activate the row).
323
+ */
324
+ open: () => void;
325
+ }
326
+ /**
327
+ * Config-driven resource page: wires data-fetching (or a pre-fetched `data`
328
+ * array), search/filter/sort, table/grid/list views, and a detail
329
+ * panel/modal/route around a `DataProvider` resource — the CRUD page most
330
+ * apps hand-roll, expressed as one component tree. `renderCard` lets a
331
+ * consumer fully own item presentation while ResourcePage keeps handling
332
+ * data-fetching, filtering, and layout; see also the built-in
333
+ * `useKeyboardNavigation` wiring (`keyboardNavigation` prop) and `gridCols`.
334
+ *
335
+ * Three levels of control, and each option is available at all three:
336
+ *
337
+ * 1. **The primitive offers it** — table / grid / list views, search, sort,
338
+ * status chips, column visibility and resizing, density, page size,
339
+ * detail panel / modal / route, built-in create and edit forms.
340
+ * 2. **The instance turns it on or off** — every one of those is a prop, so
341
+ * a given page decides which affordances it offers at all.
342
+ * 3. **The end user picks their own, and it sticks** — for the options left
343
+ * on at level 2, the user's choice persists to their own storage:
344
+ * `viewSettingsKey` for page size and density, `columnVisibilityKey` and
345
+ * `resizeKey` for column layout, `savedViews` (pair with `useSavedViews`)
346
+ * for named filter sets. Persistence needs a key; without one the choice
347
+ * lasts only for the session.
348
+ *
349
+ * A server-paginated list drives the same component through the controlled
350
+ * props (`page`, `perPage`, `onPageChange`, `onSortChange`, `onSearchChange`
351
+ * and friends) — supplying any of them stops ResourcePage from searching,
352
+ * sorting or paging the `data` a second time. See that block in
353
+ * {@link ResourcePageProps}.
354
+ *
355
+ * @stability Beta
356
+ */
361
357
  interface ResourcePageProps<T extends Record<string, unknown> = Record<string, unknown>> {
362
358
  /** Client-side mode: resource name passed to useResource / DataProvider. */
363
359
  resource?: string;
364
360
  /** Server-data mode: pre-fetched data array. */
365
361
  data?: T[];
366
- /** Server-data mode: total record count (before client-side filtering). */
362
+ /**
363
+ * Server-data mode: total record count (before client-side filtering).
364
+ *
365
+ * Required whenever `onPageChange` is supplied. It cannot be derived from
366
+ * `data`, which holds only the current page. Omitted, `displayTotal` falls
367
+ * back to `0`, so the range span reads "No records" and `Next` stays
368
+ * disabled while the rows render directly below it. Rather than show a
369
+ * pager that contradicts the list, the component refuses to render the
370
+ * pager and shows an error instead. See {@link perPage} and
371
+ * {@link onPageChange}.
372
+ */
367
373
  total?: number;
368
374
  title: string;
369
375
  /** Page subtitle shown below the title. */
@@ -381,6 +387,16 @@ interface ResourcePageProps<T extends Record<string, unknown> = Record<string, u
381
387
  label: string;
382
388
  render?: (value: unknown, item: T) => ReactNode;
383
389
  }>;
390
+ /**
391
+ * Adds a status-chip filter. There is no dedicated status-change
392
+ * callback: chip clicks update the same filter state that already
393
+ * reports through `onFiltersChange`, whether or not the page is in
394
+ * server-controlled mode. A caller combining `statusFilter` with server
395
+ * pagination (`onPageChange` et al.) must supply `onFiltersChange` — see
396
+ * that prop — or status changes will update the chip UI without ever
397
+ * reaching the server. In server-controlled mode a status change also
398
+ * resets to page 1 via `onPageChange(1)` — see {@link onPageChange}.
399
+ */
384
400
  statusFilter?: string | {
385
401
  field: string;
386
402
  options?: string[];
@@ -389,6 +405,74 @@ interface ResourcePageProps<T extends Record<string, unknown> = Record<string, u
389
405
  searchPlaceholder?: string;
390
406
  initialFilters?: FilterParam[];
391
407
  onFiltersChange?: (filters: FilterParam[]) => void;
408
+ /** Current page, 1-based. Server-controlled mode only. */
409
+ page?: number;
410
+ /**
411
+ * Rows per page the server was asked for. Required whenever
412
+ * `onPageChange` is supplied: pager math (total pages, range start, Next)
413
+ * cannot be inferred from `data.length`, because a short final page is
414
+ * smaller than the real page size. Wins over the per-user page size
415
+ * persisted by `viewSettingsKey` — an explicit prop always beats a stored
416
+ * preference.
417
+ *
418
+ * Required whenever `onPageChange` is supplied. A short final page (the
419
+ * server's last page returning fewer rows than its page size) is
420
+ * indistinguishable from a small page size — there is no correct way to
421
+ * infer the divisor from the rows handed back. Rather than guess and
422
+ * render a wrong range or a stuck Next button, the component refuses to
423
+ * render the pager and shows an error instead when `onPageChange` is
424
+ * present without `perPage`.
425
+ *
426
+ * `total` is required on the same terms — see {@link total}. The error
427
+ * names every missing prop, not just the first.
428
+ */
429
+ perPage?: number;
430
+ /**
431
+ * Called with the next 1-based page number. The pager only renders when
432
+ * this is supplied AND both `perPage` and `total` are supplied — see
433
+ * {@link perPage} and {@link total}. Supplying this without either one
434
+ * renders an error naming the missing props instead of a pager.
435
+ *
436
+ * Status changes reach the server through `onFiltersChange` — not a
437
+ * dedicated callback here — because `statusFilter` state is tracked by
438
+ * the same filter machinery that already calls `onFiltersChange`
439
+ * regardless of controlled mode (see {@link statusFilter}). In
440
+ * server-controlled mode a status change also calls `onPageChange(1)`
441
+ * directly, since the previous page number is meaningless against a new
442
+ * filtered result set.
443
+ */
444
+ onPageChange?: (page: number) => void;
445
+ /** Called when the user picks a different page size in the header's view settings. */
446
+ onPerPageChange?: (perPage: number) => void;
447
+ /** Called when the user changes the sort, with `null` when the sort is cleared. */
448
+ onSortChange?: (sort: SortParam | null) => void;
449
+ /** Called when the user changes the search text (including clearing it). */
450
+ onSearchChange?: (search: string) => void;
451
+ /** Saved filter views to offer. Pair with `useSavedViews` for per-user storage. */
452
+ savedViews?: SavedViewItem[];
453
+ onLoadView?: (filters: Record<string, unknown>) => void;
454
+ onSaveView?: (name: string) => void;
455
+ onDeleteView?: (id: string) => void;
456
+ /** Show the "save current view" affordance. */
457
+ canSaveViews?: boolean;
458
+ /** Show the column-visibility dropdown. DataTable's default is `true`. */
459
+ columnVisibility?: boolean;
460
+ /** Persist key for the user's column-visibility picks. */
461
+ columnVisibilityKey?: string;
462
+ /** Allow drag-resizing columns. DataTable's default is `true`. */
463
+ resizableColumns?: boolean;
464
+ /** Persist key for the user's column widths. */
465
+ resizeKey?: string;
466
+ /** Keep the table header visible while scrolling. DataTable's default is `true`. */
467
+ stickyHeader?: boolean;
468
+ /** Keep the first column visible while scrolling horizontally. */
469
+ stickyFirstColumn?: boolean;
470
+ /**
471
+ * Page-size choices offered by `DataTable`'s own pager. Client-side mode
472
+ * only — server-controlled mode switches that pager off. (The header's
473
+ * view-settings popover has its own fixed 10/25/50/100 list.)
474
+ */
475
+ pageSizeOptions?: number[];
392
476
  onCreate?: () => void;
393
477
  onEdit?: (item: T) => void;
394
478
  onDelete?: (item: T) => void;
@@ -413,6 +497,46 @@ interface ResourcePageProps<T extends Record<string, unknown> = Record<string, u
413
497
  variant?: "default" | "destructive";
414
498
  onAction: (ids: string[]) => void | Promise<void>;
415
499
  }>;
500
+ /**
501
+ * Override the default card renderer used for grid view (and, absent a
502
+ * dedicated list layout, list view too — DataGrid falls back to the same
503
+ * renderer there). ResourcePage still owns data-fetching, filtering,
504
+ * sorting, and layout (grid columns, infinite-scroll batching, stagger
505
+ * animation) — this only swaps what's rendered inside each item slot.
506
+ *
507
+ * Receives `ResourceCardActions`: the row's `update`/`remove`/`refetch`
508
+ * plus `open()` to activate the row (opening the configured detail
509
+ * panel/modal/route). Row activation is *not* applied automatically to a
510
+ * custom card — wrapping it would double-fire against cards that bring
511
+ * their own click handling and would hijack clicks on nested buttons — so
512
+ * call `actions.open()` from wherever your card should activate.
513
+ */
514
+ renderCard?: (item: T, index: number, actions: ResourceCardActions<T>) => ReactNode;
515
+ /**
516
+ * Tailwind grid-column classes for the card grid, passed through to
517
+ * `DataGrid`'s `gridCols` — e.g. `"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3"`.
518
+ * Defaults to DataGrid's own responsive 1/2/3/4-column ramp.
519
+ */
520
+ gridCols?: string;
521
+ /**
522
+ * Built-in list keyboard navigation via `useKeyboardNavigation`: j/k (or
523
+ * Arrow Up/Down) move a focus cursor, Enter opens the focused item,
524
+ * Backspace (⌫) closes an open detail view, and x toggles the focused
525
+ * item's selection when `bulkActions` are configured. Set to `false` to
526
+ * opt out.
527
+ *
528
+ * Default-on, and scoped so that being on by default stays safe:
529
+ * - Only while the grid or list view is showing. Table view keeps its own
530
+ * independent sort/pagination, so a flat focus index can't reliably map
531
+ * onto its visible rows.
532
+ * - Cursor keys suspend while a detail panel/modal or the built-in form
533
+ * is open, so they can't drive the list behind the overlay; ⌫ stays
534
+ * live there so it can close it.
535
+ * - Backspace is only intercepted while there's an open detail to close.
536
+ * - Modified chords (Ctrl/Cmd/Alt) are never captured, so an app's
537
+ * Cmd+K-style shortcuts keep working.
538
+ */
539
+ keyboardNavigation?: boolean;
416
540
  toolbar?: ReactNode;
417
541
  emptyState?: ReactNode;
418
542
  /**
@@ -430,7 +554,86 @@ interface ResourcePageProps<T extends Record<string, unknown> = Record<string, u
430
554
  */
431
555
  viewSettingsKey?: string;
432
556
  }
433
- declare function ResourcePage<T extends Record<string, unknown> = Record<string, unknown>>(props: ResourcePageProps<T>): react_jsx_runtime.JSX.Element;
557
+ declare function ResourcePage<T extends Record<string, unknown> = Record<string, unknown>>(props: ResourcePageProps<T>): React.JSX.Element;
558
+
559
+ interface ResourceDetailPageProps<T extends BaseRecord = BaseRecord> {
560
+ /** Resource name, resolved through the mounted `DataProvider`. */
561
+ resource: string;
562
+ /**
563
+ * Record id. Nullish means "not resolved yet" — no request goes out and the
564
+ * page shows its loading state, which is what a route param that hasn't
565
+ * arrived should look like. It is deliberately NOT the not-found state:
566
+ * nothing has been asked, so nothing is missing.
567
+ */
568
+ id: Identifier | undefined | null;
569
+ /**
570
+ * Field used as the page title. Defaults to `name`, then `title`, then the
571
+ * id — the same fallback chain `ResourcePage` uses for a row's label.
572
+ */
573
+ titleField?: string;
574
+ /** Field used as the line under the title. */
575
+ subtitleField?: string;
576
+ /** Provider select/join syntax, e.g. `"*, owner:profiles(name)"`. */
577
+ select?: string;
578
+ /** Slot above the title: a `Breadcrumb`, a back link, a `StatusBadge`. */
579
+ breadcrumb?: ReactNode;
580
+ /** Record-scoped controls, built from the loaded record. */
581
+ actions?: (record: T) => ReactNode;
582
+ /** Metadata column, built from the loaded record. */
583
+ sidebar?: (record: T) => ReactNode;
584
+ /** The primary content region. */
585
+ children: (record: T) => ReactNode;
586
+ className?: string;
587
+ /** Stable test/automation selector (emitted as `data-testid`). */
588
+ testID?: string;
589
+ }
590
+ /**
591
+ * ResourceDetailPage — `DetailPage` with a record bound to it: fetches one
592
+ * record by id through the mounted `DataProvider` and hands it to the title,
593
+ * the actions, the sidebar and the content.
594
+ *
595
+ * ```tsx
596
+ * <ResourceDetailPage
597
+ * resource="people"
598
+ * id={params.id}
599
+ * subtitleField="role"
600
+ * actions={(person) => <Button testID="edit">Edit {person.name}</Button>}
601
+ * sidebar={(person) => <StatCard label="Sessions" value={person.session_count} />}
602
+ * >
603
+ * {(person) => <Section title="Timeline"><Timeline personId={person.id} /></Section>}
604
+ * </ResourceDetailPage>
605
+ * ```
606
+ *
607
+ * This is the detail-route counterpart to `ResourcePage`, which is the list
608
+ * one. Both are **data-bound**, not layouts: they need a resource contract
609
+ * to be useful, which is the layers table's admission test for this tier.
610
+ * The structure they render is a layout and lives one layer down —
611
+ * `DetailPage` in `@marktiderman/genesis-ui/layout` — so an app with its own
612
+ * fetching keeps the page shape without inheriting the provider. That
613
+ * layout/data-bound pairing is the same one `AppShell` and `ResourcePage`
614
+ * already have.
615
+ *
616
+ * The three non-record states are rendered here rather than left to the
617
+ * caller, because a per-app "loading…" is exactly the hand-written code a
618
+ * template exists to remove:
619
+ * - loading, or no id yet -> `PageLoading`
620
+ * - absent -> `EmptyState` saying so, distinct from the error state, since a
621
+ * deleted record and a broken query need different words. Every provider
622
+ * Genesis ships signals "no such row" by throwing rather than by resolving
623
+ * empty, so this state is reached by classifying the error (see
624
+ * `isNotFoundError`) as well as by a falsy `data`
625
+ * - any other failure -> `EmptyState` carrying the provider's message, which
626
+ * is kept verbatim: an error state that hides what went wrong is the one
627
+ * nobody can act on
628
+ *
629
+ * `titleField` is exact: name a field and you get that field, empty string
630
+ * included. The `name` -> `title` -> id chain is the DEFAULT, not a fallback
631
+ * layered under an explicit choice — a page silently titled by a different
632
+ * column than the one asked for is worse than a blank one.
633
+ *
634
+ * @stability Beta
635
+ */
636
+ declare function ResourceDetailPage<T extends BaseRecord = BaseRecord>({ resource, id, titleField, subtitleField, select, breadcrumb, actions, sidebar, children, className, testID, }: ResourceDetailPageProps<T>): React.JSX.Element;
434
637
 
435
638
  interface ResourceFormProps {
436
639
  resource: string;
@@ -454,7 +657,7 @@ interface ResourceFormProps {
454
657
  /** Number of columns for the form layout. Default 1. */
455
658
  columns?: 1 | 2;
456
659
  }
457
- declare function ResourceForm(props: ResourceFormProps): react_jsx_runtime.JSX.Element | null;
660
+ declare function ResourceForm(props: ResourceFormProps): React.JSX.Element | null;
458
661
 
459
662
  interface RelationFieldProps {
460
663
  field: ResourceFormFieldDef;
@@ -462,7 +665,7 @@ interface RelationFieldProps {
462
665
  onChange: (value: string) => void;
463
666
  disabled?: boolean;
464
667
  }
465
- declare function RelationField({ field, value, onChange, disabled, }: RelationFieldProps): react_jsx_runtime.JSX.Element;
668
+ declare function RelationField({ field, value, onChange, disabled, }: RelationFieldProps): React.JSX.Element;
466
669
 
467
670
  interface FileUploadFieldProps {
468
671
  field: ResourceFormFieldDef;
@@ -470,14 +673,14 @@ interface FileUploadFieldProps {
470
673
  onChange: (value: File | File[] | null) => void;
471
674
  disabled?: boolean;
472
675
  }
473
- declare function FileUploadField({ field, value, onChange, disabled, }: FileUploadFieldProps): react_jsx_runtime.JSX.Element;
676
+ declare function FileUploadField({ field, value, onChange, disabled, }: FileUploadFieldProps): React.JSX.Element;
474
677
 
475
678
  declare function FieldArrayRenderer({ field, control, action, watchedValues, }: {
476
679
  field: ResourceFormFieldDef;
477
680
  control: Control<Record<string, unknown>>;
478
681
  action: "create" | "edit";
479
682
  watchedValues?: Record<string, unknown>;
480
- }): react_jsx_runtime.JSX.Element;
683
+ }): React.JSX.Element;
481
684
 
482
685
  interface WizardFormProps {
483
686
  steps: WizardStep[];
@@ -489,134 +692,21 @@ interface WizardFormProps {
489
692
  action: "create" | "edit";
490
693
  onInvalid?: (errors: FieldErrors) => void;
491
694
  }
492
- declare function WizardForm({ steps, form, fields, onSubmit, isSaving, renderField, action, onInvalid, }: WizardFormProps): react_jsx_runtime.JSX.Element;
695
+ declare function WizardForm({ steps, form, fields, onSubmit, isSaving, renderField, action, onInvalid, }: WizardFormProps): React.JSX.Element;
493
696
 
494
- interface NavItem {
495
- to: string;
496
- icon: LucideIcon;
497
- label: string;
498
- /** Nested items — rendered as a collapsible group when the rail is expanded */
499
- children?: NavItem[];
500
- badge?: string | number;
501
- disabled?: boolean;
502
- /** Exact-match active state (e.g. overview `/`) */
503
- end?: boolean;
504
- }
505
697
  /**
506
- * Declarative chrome for AppShell — developer defaults + optional
507
- * in-sidebar user toggles (Notion/Linear “customize chrome” pattern).
508
- *
509
- * @stability Beta
698
+ * @deprecated Import `AppShell` from `@marktiderman/genesis-ui/layout` instead.
699
+ * `AppShell` is a layout, not a data-bound component. This `/data` alias is
700
+ * removed in the next major — see docs/FRAMEWORK.md rule 5.
701
+ * @stability Deprecated
510
702
  */
511
- interface AppShellOptions {
512
- showLogo?: boolean;
513
- showAppName?: boolean;
514
- showThemeToggle?: boolean;
515
- /** Desktop rail collapse control */
516
- showCollapse?: boolean;
517
- showUserSlot?: boolean;
518
- showFooter?: boolean;
519
- showSecondaryNav?: boolean;
520
- /** Mobile fixed bottom tab bar */
521
- showMobileBottomNav?: boolean;
522
- defaultCollapsed?: boolean;
523
- /**
524
- * Show the in-sidebar Sidebar options popover so users can customize chrome.
525
- * Default true when collapse / secondary / theme / slots are available.
526
- */
527
- configurable?: boolean;
528
- /**
529
- * Toggle keys the developer has decided on and users may not override —
530
- * e.g. hiding `showThemeToggle` for a brand that manages theme elsewhere.
531
- * Locked keys are dropped from the options popover and any stored user
532
- * override for them is ignored on resolve.
533
- */
534
- lockedOptions?: (keyof AppShellOptions)[];
535
- /** Comfortable (default) vs compact row padding */
536
- density?: "comfortable" | "compact";
537
- /** Expanded rail width in rem-ish tokens: narrow ≈ 13rem, wide ≈ 16rem */
538
- railWidth?: "narrow" | "wide";
539
- /**
540
- * Where page content scrolls.
541
- * - `container` (default): main panel scrolls — classic app-shell chrome.
542
- * - `window`: document/window scrolls with a sticky rail so React Router
543
- * `ScrollRestoration` keeps working (dashboard dogfood).
544
- */
545
- scrollRoot?: "container" | "window";
546
- }
703
+ declare const AppShell: typeof AppShell$1;
547
704
  /**
548
- * @stability Beta
705
+ * @deprecated Import `PageHeader` from `@marktiderman/genesis-ui/layout`
706
+ * instead. `PageHeader` is a layout, not a data-bound component. This `/data`
707
+ * alias is removed in the next major — see docs/FRAMEWORK.md rule 5.
708
+ * @stability Deprecated
549
709
  */
550
- interface AppShellProps {
551
- /** App name shown in sidebar header */
552
- appName: string;
553
- /** App logo letter or short text (ignored when `logo` is set) */
554
- appLogo?: string;
555
- /** Custom logo node — preferred over `appLogo` letter tile */
556
- logo?: ReactNode;
557
- /** Primary navigation items */
558
- navItems: NavItem[];
559
- /** Secondary nav (e.g. “More”) — rendered below a divider when shown */
560
- secondaryNavItems?: NavItem[];
561
- /** Label above secondary nav (default “More”) */
562
- secondaryNavLabel?: string;
563
- /**
564
- * Items for the mobile bottom tab bar. Defaults to top-level `navItems`
565
- * (no children). Pass a short list for apps with large sidebars; pass `[]`
566
- * and set `options.showMobileBottomNav: false` to hide.
567
- */
568
- mobileNavItems?: NavItem[];
569
- /** Slot below the logo row (product switcher, workspace picker, …) */
570
- headerSlot?: ReactNode;
571
- /**
572
- * Compact slot shown in the **collapsed** desktop rail, where `headerSlot`
573
- * is hidden for space. Use it to keep a core affordance reachable without
574
- * expanding — e.g. an icon-only product switcher. Omit to hide the header
575
- * region entirely while collapsed.
576
- */
577
- collapsedHeaderSlot?: ReactNode;
578
- /** Footer region above the user slot (version, links) */
579
- footer?: ReactNode;
580
- /**
581
- * User / account block at the bottom of the sidebar. When the rail is
582
- * collapsed, AppShell hides any descendant carrying the
583
- * `data-shell-user-detail` attribute (e.g. name/email text) so only a
584
- * compact element (avatar, initial) remains — tag the detail wrapper you
585
- * want hidden in the collapsed rail with that attribute.
586
- */
587
- userSlot?: ReactNode;
588
- /** Page content */
589
- children: ReactNode;
590
- /**
591
- * @deprecated Prefer `options.showThemeToggle`. Kept for sample-app
592
- * back-compat; merges into resolved options when `options` omits it.
593
- */
594
- showThemeToggle?: boolean;
595
- /** Chrome config (developer defaults + optional in-sidebar menu) */
596
- options?: AppShellOptions;
597
- /** Persist user sidebar-option overrides + collapse state (localStorage) */
598
- optionsStorageKey?: string;
599
- /** Controlled collapse (desktop rail) */
600
- collapsed?: boolean;
601
- onCollapsedChange?: (collapsed: boolean) => void;
602
- /**
603
- * Injectable link component. Defaults to a plain `<a>` (no router). Pass a
604
- * router adapter — e.g. React Router `({ href, ...p }) => <Link to={href} {...p} />`
605
- * or Next.js `next/link` — to get client-side navigation.
606
- */
607
- linkComponent?: LinkComponent;
608
- /**
609
- * Current path used to highlight the active nav item. Router consumers pass
610
- * `useLocation().pathname` (RR) or `usePathname()` (Next). Omit to disable
611
- * active highlighting.
612
- */
613
- activePath?: string;
614
- /**
615
- * Optional custom active-state matcher. Defaults to a prefix match (with `/`
616
- * treated as exact), mirroring React Router `NavLink`.
617
- */
618
- isActive?: (to: string, activePath?: string) => boolean;
619
- }
620
- declare function AppShell({ appName, appLogo, logo, navItems, secondaryNavItems, secondaryNavLabel, mobileNavItems, headerSlot, collapsedHeaderSlot, footer, userSlot, children, showThemeToggle: showThemeToggleProp, options: optionsProp, optionsStorageKey, collapsed: collapsedProp, onCollapsedChange, linkComponent, activePath, isActive, }: AppShellProps): react_jsx_runtime.JSX.Element;
710
+ declare const PageHeader: typeof PageHeader$1;
621
711
 
622
- export { AppShell, type AppShellOptions, type AppShellProps, BadgeCell, type BulkAction, type ColumnStatus, CurrencyCell, DataBulkBar, type DataFilterConfig, DataFilters, DataGrid, DataList, type DataListProps, DataPageShell, type DataPageShellProps, DateCell, Density, DetailPanel, type DetailPanelProps, EmptyState, FieldArrayRenderer, FileUploadField, FilterCombobox, type FilterOption, KanbanBoard, type KanbanBoardProps, type KanbanColumn, LinkComponent, type NavItem, NavigateFn, NumberCell, PageHeader, type PageHeaderOptions, type PageHeaderProps, RelationField, ResourceColumnDef, ResourceForm, type ResourceFormProps, ResourcePage, type ResourcePageProps, type SavedViewItem, StatCard, type StatCardColor, type StatCardProps, ViewMode, ViewSettings, WizardForm };
712
+ export { AppShell, BadgeCell, type BulkAction, type ColumnStatus, CurrencyCell, DataBulkBar, type DataFilterConfig, DataFilters, DataGrid, DataList, type DataListProps, DataPageShell, type DataPageShellProps, DateCell, Density, DetailPanel, type DetailPanelProps, FieldArrayRenderer, FileUploadField, FilterCombobox, type FilterOption, KanbanBoard, type KanbanBoardProps, type KanbanColumn, LinkComponent, NavigateFn, NumberCell, PageHeader, PageHeaderOptions, RelationField, ResourceActions, type ResourceCardActions, ResourceColumnDef, ResourceDetailPage, type ResourceDetailPageProps, ResourceForm, type ResourceFormProps, ResourcePage, type ResourcePageProps, type SavedViewItem, StatCard, type StatCardColor, type StatCardProps, ViewMode, WizardForm };