@jmruthers/pace-core 0.4.1 → 0.5.1

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 (601) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +231 -229
  3. package/dist/{DataTable-2LB6HI6V.js → DataTable-GX3XERFJ.js} +14 -17
  4. package/dist/{DataTable-BDBqkU-i.d.ts → DataTable-ltTFXHS3.d.ts} +25 -51
  5. package/dist/{Table-CIm9IWqk.d.ts → PublicLoadingSpinner-DztrzuJr.d.ts} +635 -122
  6. package/dist/UnifiedAuthProvider-w66zSCUf.d.ts +160 -0
  7. package/dist/{api-AIJ3IJX3.js → api-ETQ6YJ3C.js} +6 -4
  8. package/dist/{appConfig-fB1pP_v3.d.ts → appConfig-BVGyuvI7.d.ts} +1 -1
  9. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  10. package/dist/{audit-PD5L5ZSC.js → audit-BUW3LMJB.js} +3 -3
  11. package/dist/chunk-5EL3KHOQ.js +388 -0
  12. package/dist/chunk-5EL3KHOQ.js.map +1 -0
  13. package/dist/{chunk-4MCJAK7J.js → chunk-6CR3MRZN.js} +1827 -4886
  14. package/dist/chunk-6CR3MRZN.js.map +1 -0
  15. package/dist/{chunk-YNU5QJ4S.js → chunk-7BNPOCLL.js} +22 -5
  16. package/dist/chunk-7BNPOCLL.js.map +1 -0
  17. package/dist/chunk-AUE24LVR.js +268 -0
  18. package/dist/chunk-AUE24LVR.js.map +1 -0
  19. package/dist/chunk-C5G2A4PO.js +1349 -0
  20. package/dist/chunk-C5G2A4PO.js.map +1 -0
  21. package/dist/{chunk-4ZTIEYU2.js → chunk-CDQ3PX7L.js} +1 -1
  22. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  23. package/dist/chunk-COBPIXXQ.js +379 -0
  24. package/dist/chunk-COBPIXXQ.js.map +1 -0
  25. package/dist/chunk-GSNM5D6H.js +5441 -0
  26. package/dist/chunk-GSNM5D6H.js.map +1 -0
  27. package/dist/chunk-MZBUOP4P.js +119 -0
  28. package/dist/chunk-MZBUOP4P.js.map +1 -0
  29. package/dist/chunk-N2EUGZRW.js +98 -0
  30. package/dist/chunk-N2EUGZRW.js.map +1 -0
  31. package/dist/chunk-NQ4TOOO6.js +20 -0
  32. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  33. package/dist/{chunk-KK6WIDK6.js → chunk-OEGRKULD.js} +12 -2
  34. package/dist/{chunk-KK6WIDK6.js.map → chunk-OEGRKULD.js.map} +1 -1
  35. package/dist/chunk-OYRY44Q2.js +62 -0
  36. package/dist/chunk-OYRY44Q2.js.map +1 -0
  37. package/dist/{chunk-DC5AMYBS.js → chunk-PLDDJCW6.js} +15 -5
  38. package/dist/chunk-PLDDJCW6.js.map +1 -0
  39. package/dist/{chunk-WHLSWC6W.js → chunk-SS3E6QLB.js} +16 -61
  40. package/dist/chunk-SS3E6QLB.js.map +1 -0
  41. package/dist/chunk-T3XIA4AJ.js +3295 -0
  42. package/dist/chunk-T3XIA4AJ.js.map +1 -0
  43. package/dist/{chunk-H4PZ4B3Y.js → chunk-TGDCLPP2.js} +129 -28
  44. package/dist/chunk-TGDCLPP2.js.map +1 -0
  45. package/dist/{chunk-IOX76PSM.js → chunk-U6JDHVC2.js} +273 -29
  46. package/dist/chunk-U6JDHVC2.js.map +1 -0
  47. package/dist/{chunk-JUUNUW3O.js → chunk-XJK2J4N6.js} +17 -6
  48. package/dist/chunk-XJK2J4N6.js.map +1 -0
  49. package/dist/chunk-YDJW5XTN.js +84 -0
  50. package/dist/chunk-YDJW5XTN.js.map +1 -0
  51. package/dist/components.d.ts +906 -10
  52. package/dist/components.js +3263 -84
  53. package/dist/components.js.map +1 -1
  54. package/dist/{database-CAMsquLm.d.ts → database-C3Szpi5J.d.ts} +28 -11
  55. package/dist/hooks.d.ts +7 -6
  56. package/dist/hooks.js +35 -11
  57. package/dist/hooks.js.map +1 -1
  58. package/dist/index.d.ts +245 -111
  59. package/dist/index.js +195 -185
  60. package/dist/index.js.map +1 -1
  61. package/dist/{organisation-DLNNQhPB.d.ts → organisation-CO3Sh3_D.d.ts} +1 -1
  62. package/dist/providers.d.ts +4 -4
  63. package/dist/providers.js +21 -6
  64. package/dist/rbac/index.d.ts +862 -806
  65. package/dist/rbac/index.js +953 -1032
  66. package/dist/rbac/index.js.map +1 -1
  67. package/dist/styles/core.css +422 -0
  68. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  69. package/dist/styles/fonts/georama.woff2 +0 -0
  70. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  71. package/dist/styles/fonts/open-sans.woff2 +0 -0
  72. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  73. package/dist/styles/index.d.ts +36 -0
  74. package/dist/styles/index.js +24 -0
  75. package/dist/styles/index.js.map +1 -0
  76. package/dist/theming/runtime.d.ts +73 -0
  77. package/dist/theming/runtime.js +16 -0
  78. package/dist/theming/runtime.js.map +1 -0
  79. package/dist/{types-Bavn44NW.d.ts → types-BRDU7N6w.d.ts} +79 -33
  80. package/dist/types.d.ts +5 -5
  81. package/dist/types.js +7 -2
  82. package/dist/types.js.map +1 -1
  83. package/dist/{unified-BtRpPbmp.d.ts → unified-CM7T0aTK.d.ts} +1 -2
  84. package/dist/usePublicRouteParams-B6i0KtXW.d.ts +477 -0
  85. package/dist/utils.d.ts +83 -60
  86. package/dist/utils.js +301 -55657
  87. package/dist/utils.js.map +1 -1
  88. package/dist/validation.d.ts +1 -1
  89. package/dist/validation.js +1 -1
  90. package/docs/INDEX.md +192 -0
  91. package/docs/README.md +46 -32
  92. package/docs/api/README.md +231 -229
  93. package/docs/api/classes/ErrorBoundary.md +1 -1
  94. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  95. package/docs/api/interfaces/AggregateConfig.md +4 -4
  96. package/docs/api/interfaces/ButtonProps.md +2 -2
  97. package/docs/api/interfaces/CardProps.md +2 -2
  98. package/docs/api/interfaces/ColorPalette.md +1 -1
  99. package/docs/api/interfaces/ColorShade.md +1 -1
  100. package/docs/api/interfaces/DataTableAction.md +98 -7
  101. package/docs/api/interfaces/DataTableColumn.md +131 -12
  102. package/docs/api/interfaces/DataTableProps.md +77 -274
  103. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  104. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  105. package/docs/api/interfaces/EventContextType.md +7 -7
  106. package/docs/api/interfaces/EventLogoProps.md +152 -0
  107. package/docs/api/interfaces/EventProviderProps.md +2 -2
  108. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  109. package/docs/api/interfaces/FileUploadProps.md +154 -0
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  112. package/docs/api/interfaces/InputProps.md +2 -2
  113. package/docs/api/interfaces/LabelProps.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationItem.md +1 -1
  116. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  117. package/docs/api/interfaces/Organisation.md +1 -1
  118. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  119. package/docs/api/interfaces/OrganisationMembership.md +2 -2
  120. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  121. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  122. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -26
  123. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  124. package/docs/api/interfaces/PaletteData.md +1 -1
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  128. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  131. package/docs/api/interfaces/StorageConfig.md +41 -0
  132. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  133. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  134. package/docs/api/interfaces/StorageListOptions.md +86 -0
  135. package/docs/api/interfaces/StorageListResult.md +41 -0
  136. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  137. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  138. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  139. package/docs/api/interfaces/StyleImport.md +2 -2
  140. package/docs/api/interfaces/ToastActionElement.md +1 -1
  141. package/docs/api/interfaces/ToastProps.md +1 -1
  142. package/docs/api/interfaces/UnifiedAuthContextType.md +447 -46
  143. package/docs/api/interfaces/UnifiedAuthProviderProps.md +95 -9
  144. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  145. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  146. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  147. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  148. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  149. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  150. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  151. package/docs/api/interfaces/UserEventAccess.md +14 -14
  152. package/docs/api/interfaces/UserMenuProps.md +6 -6
  153. package/docs/api/interfaces/UserProfile.md +1 -1
  154. package/docs/api/modules.md +1626 -768
  155. package/docs/api-reference/components.md +761 -43
  156. package/docs/api-reference/hooks.md +126 -0
  157. package/docs/api-reference/providers.md +141 -65
  158. package/docs/api-reference/types.md +66 -36
  159. package/docs/api-reference/utilities.md +1 -1
  160. package/docs/architecture/README.md +1 -2
  161. package/docs/best-practices/README.md +400 -0
  162. package/docs/consuming-app-example.md +42 -96
  163. package/docs/consuming-app-vite-config.md +233 -0
  164. package/docs/core-concepts/events.md +3 -3
  165. package/docs/core-concepts/organisations.md +0 -1
  166. package/docs/core-concepts/rbac-system.md +23 -10
  167. package/docs/documentation-style-checklist.md +8 -2
  168. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  169. package/docs/getting-started/examples/README.md +15 -1
  170. package/docs/getting-started/examples/basic-auth-app.md +444 -119
  171. package/docs/getting-started/examples/full-featured-app.md +6 -6
  172. package/docs/getting-started/installation.md +231 -52
  173. package/docs/getting-started/quick-start.md +121 -24
  174. package/docs/implementation-guides/app-layout.md +133 -108
  175. package/docs/implementation-guides/data-tables.md +1011 -29
  176. package/docs/implementation-guides/forms.md +3 -3
  177. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  178. package/docs/implementation-guides/large-datasets.md +2 -2
  179. package/docs/implementation-guides/navigation.md +1 -1
  180. package/docs/implementation-guides/permission-enforcement.md +4 -4
  181. package/docs/implementation-guides/public-pages.md +752 -0
  182. package/docs/migration/README.md +18 -8
  183. package/docs/migration/quick-migration-guide.md +320 -0
  184. package/docs/migration/rbac-migration.md +50 -0
  185. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  186. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  187. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  188. package/docs/migration-guide.md +51 -104
  189. package/docs/performance/README.md +1 -4
  190. package/docs/print-components/README.md +258 -0
  191. package/docs/print-components/api-reference.md +636 -0
  192. package/docs/print-components/examples/README.md +204 -0
  193. package/docs/print-components/examples/basic-report.tsx +92 -0
  194. package/docs/print-components/examples/card-catalog.tsx +149 -0
  195. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  196. package/docs/print-components/quick-start.md +363 -0
  197. package/docs/quick-reference.md +53 -36
  198. package/docs/rbac/README.md +136 -69
  199. package/docs/rbac/api-reference.md +39 -8
  200. package/docs/rbac/examples.md +237 -66
  201. package/docs/rbac/getting-started.md +131 -16
  202. package/docs/rbac/quick-start.md +499 -323
  203. package/docs/rbac/troubleshooting.md +240 -262
  204. package/docs/security/README.md +50 -1
  205. package/docs/styles/README.md +143 -117
  206. package/docs/testing/README.md +6 -10
  207. package/docs/troubleshooting/README.md +497 -0
  208. package/docs/troubleshooting/common-issues.md +604 -14
  209. package/docs/troubleshooting/styling-issues.md +219 -0
  210. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  211. package/docs/usage.md +28 -90
  212. package/docs/visual-testing.md +0 -7
  213. package/package.json +46 -24
  214. package/src/__mocks__/lucide-react.ts +181 -0
  215. package/src/__tests__/REBUILD_PLAN.md +223 -0
  216. package/src/__tests__/TESTING_GUIDELINES.md +341 -0
  217. package/src/__tests__/fixtures/mocks.ts +93 -0
  218. package/src/__tests__/helpers/component-test-utils.tsx +145 -0
  219. package/src/__tests__/helpers/test-utils.tsx +117 -0
  220. package/src/__tests__/integration/UserProfile.test.tsx +128 -0
  221. package/src/__tests__/setup.ts +71 -0
  222. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  223. package/src/__tests__/templates/component.test.template.tsx +144 -0
  224. package/src/__tests__/templates/hook.test.template.ts +173 -0
  225. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  226. package/src/__tests__/types/test.types.ts +106 -0
  227. package/src/components/Alert/Alert.test.tsx +496 -0
  228. package/src/components/Alert/Alert.tsx +134 -0
  229. package/src/components/Alert/index.ts +2 -0
  230. package/src/components/Avatar/Avatar.test.tsx +484 -0
  231. package/src/components/Avatar/Avatar.tsx +84 -0
  232. package/src/components/Avatar/index.ts +2 -0
  233. package/src/components/Button/Button.test.tsx +662 -0
  234. package/src/components/Button/Button.tsx +270 -0
  235. package/src/components/Button/index.ts +2 -0
  236. package/src/components/Card/Card.test.tsx +593 -0
  237. package/src/components/Card/Card.tsx +271 -0
  238. package/src/components/Card/index.ts +1 -0
  239. package/src/components/Checkbox/Checkbox.test.tsx +461 -0
  240. package/src/components/Checkbox/Checkbox.tsx +75 -0
  241. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  242. package/src/components/Checkbox/index.ts +2 -0
  243. package/src/components/DataTable/DataTable.tsx +446 -0
  244. package/src/components/DataTable/__tests__/README.md +145 -0
  245. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  246. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  247. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +381 -0
  248. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  249. package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
  250. package/src/components/DataTable/components/ActionButtons.tsx +194 -0
  251. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  252. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  253. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  254. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  255. package/src/components/DataTable/components/DataTableCore.tsx +1027 -0
  256. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  257. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  258. package/src/components/DataTable/components/DataTableToolbar.tsx +262 -0
  259. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  260. package/src/components/DataTable/components/EditableRow.tsx +159 -0
  261. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  262. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  263. package/src/components/DataTable/components/FilterRow.tsx +100 -0
  264. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  265. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  266. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  267. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  268. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  269. package/src/components/DataTable/components/UnifiedTableBody.tsx +742 -0
  270. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  271. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  272. package/src/components/DataTable/components/index.ts +16 -0
  273. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  274. package/src/components/DataTable/core/ActionManager.ts +235 -0
  275. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  276. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  277. package/src/components/DataTable/core/DataManager.ts +188 -0
  278. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  279. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  280. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  281. package/src/components/DataTable/core/StateManager.ts +311 -0
  282. package/src/components/DataTable/core/index.ts +8 -0
  283. package/src/components/DataTable/core/interfaces.ts +338 -0
  284. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +419 -0
  285. package/src/components/DataTable/examples/HierarchicalExample.tsx +475 -0
  286. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +176 -0
  287. package/src/components/DataTable/examples/PerformanceExample.tsx +505 -0
  288. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  289. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  290. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  291. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  292. package/src/components/DataTable/index.ts +68 -0
  293. package/src/components/DataTable/styles.ts +171 -0
  294. package/src/components/DataTable/types.ts +511 -0
  295. package/src/components/DataTable/utils/debugTools.ts +583 -0
  296. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  297. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  298. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  299. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  300. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  301. package/src/components/DataTable/utils/index.ts +1 -0
  302. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  303. package/src/components/Dialog/Dialog.test.tsx +1139 -0
  304. package/src/components/Dialog/Dialog.tsx +782 -0
  305. package/src/components/Dialog/README.md +804 -0
  306. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  307. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  308. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  309. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  310. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  311. package/src/components/Dialog/index.ts +12 -0
  312. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  313. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
  314. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  315. package/src/components/ErrorBoundary/index.ts +8 -0
  316. package/src/components/EventSelector/EventSelector.tsx +360 -0
  317. package/src/components/EventSelector/index.ts +3 -0
  318. package/src/components/EventSelector/types.ts +79 -0
  319. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  320. package/src/components/FileUpload/FileUpload.test.tsx +665 -0
  321. package/src/components/FileUpload/FileUpload.tsx +237 -0
  322. package/src/components/FileUpload/index.ts +6 -0
  323. package/src/components/Footer/Footer.tsx +197 -0
  324. package/src/components/Footer/index.ts +17 -0
  325. package/src/components/Form/Form.tsx +166 -0
  326. package/src/components/Form/FormErrorSummary.tsx +113 -0
  327. package/src/components/Form/FormField.tsx +249 -0
  328. package/src/components/Form/FormFieldset.tsx +127 -0
  329. package/src/components/Form/FormLiveRegion.tsx +198 -0
  330. package/src/components/Form/index.ts +26 -0
  331. package/src/components/Header/Header.tsx +301 -0
  332. package/src/components/Header/index.ts +4 -0
  333. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  334. package/src/components/InactivityWarningModal/index.ts +9 -0
  335. package/src/components/Input/Input.tsx +201 -0
  336. package/src/components/Input/__mocks__/Input.tsx +2 -0
  337. package/src/components/Input/index.ts +9 -0
  338. package/src/components/Label/Label.tsx +186 -0
  339. package/src/components/Label/index.ts +2 -0
  340. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  341. package/src/components/LoadingSpinner/index.ts +3 -0
  342. package/src/components/LoginForm/LoginForm.tsx +273 -0
  343. package/src/components/LoginForm/index.ts +3 -0
  344. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  345. package/src/components/NavigationMenu/index.ts +10 -0
  346. package/src/components/NavigationMenu/types.ts +85 -0
  347. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  348. package/src/components/OrganisationSelector/index.ts +9 -0
  349. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  350. package/src/components/PaceAppLayout/README.md +278 -0
  351. package/src/components/PaceAppLayout/index.ts +1 -0
  352. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  353. package/src/components/PaceLoginPage/index.ts +1 -0
  354. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  355. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  356. package/src/components/PasswordReset/index.ts +4 -0
  357. package/src/components/PrintButton/PrintButton.tsx +321 -0
  358. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  359. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  360. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  361. package/src/components/PrintButton/index.ts +33 -0
  362. package/src/components/PrintButton/types.ts +173 -0
  363. package/src/components/PrintCard/PrintCard.tsx +154 -0
  364. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  365. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  366. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  367. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  368. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  369. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  370. package/src/components/PrintCard/index.ts +34 -0
  371. package/src/components/PrintCard/types.ts +171 -0
  372. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  373. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  374. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  375. package/src/components/PrintDataTable/index.ts +25 -0
  376. package/src/components/PrintDataTable/types.ts +67 -0
  377. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  378. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  379. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  380. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  381. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  382. package/src/components/PrintFooter/index.ts +30 -0
  383. package/src/components/PrintFooter/types.ts +149 -0
  384. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  385. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  386. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  387. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  388. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  389. package/src/components/PrintGrid/index.ts +31 -0
  390. package/src/components/PrintGrid/types.ts +159 -0
  391. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  392. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  393. package/src/components/PrintHeader/index.ts +17 -0
  394. package/src/components/PrintHeader/types.ts +42 -0
  395. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  396. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  397. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  398. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  399. package/src/components/PrintLayout/index.ts +19 -0
  400. package/src/components/PrintLayout/types.ts +37 -0
  401. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  402. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  403. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  404. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  405. package/src/components/PrintPageBreak/index.ts +23 -0
  406. package/src/components/PrintPageBreak/types.ts +94 -0
  407. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  408. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  409. package/src/components/PrintSection/PrintSection.tsx +129 -0
  410. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  411. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  412. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  413. package/src/components/PrintSection/index.ts +33 -0
  414. package/src/components/PrintSection/types.ts +155 -0
  415. package/src/components/PrintText/PrintText.tsx +116 -0
  416. package/src/components/PrintText/index.ts +16 -0
  417. package/src/components/PrintText/types.ts +24 -0
  418. package/src/components/Progress/Progress.tsx +116 -0
  419. package/src/components/Progress/index.ts +3 -0
  420. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  421. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  422. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  423. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  424. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  425. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  426. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  427. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  428. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  429. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  430. package/src/components/PublicLayout/index.ts +51 -0
  431. package/src/components/RBAC/PagePermissionGuard.tsx +287 -0
  432. package/src/components/RBAC/RBACGuard.tsx +143 -0
  433. package/src/components/RBAC/RBACProvider.tsx +186 -0
  434. package/src/components/RBAC/RoleBasedContent.tsx +129 -0
  435. package/src/components/RBAC/index.ts +23 -0
  436. package/src/components/Select/Select.tsx +660 -0
  437. package/src/components/Select/index.ts +1 -0
  438. package/src/components/SuperAdminGuard.tsx +116 -0
  439. package/src/components/Table/Table.tsx +222 -0
  440. package/src/components/Table/index.ts +11 -0
  441. package/src/components/Toast/Toast.tsx +339 -0
  442. package/src/components/Toast/index.ts +14 -0
  443. package/src/components/Tooltip/Tooltip.tsx +167 -0
  444. package/src/components/Tooltip/index.ts +7 -0
  445. package/src/components/UserMenu/UserMenu.tsx +243 -0
  446. package/src/components/UserMenu/index.ts +3 -0
  447. package/src/components/examples/PermissionExample.tsx +150 -0
  448. package/src/components/index.ts +434 -0
  449. package/src/components.ts +19 -0
  450. package/src/constants/performance.ts +14 -0
  451. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  452. package/src/examples/PublicEventPage.tsx +274 -0
  453. package/src/examples/PublicPageApp.tsx +308 -0
  454. package/src/examples/PublicPageUsageExample.tsx +216 -0
  455. package/src/hooks/index.ts +56 -0
  456. package/src/hooks/public/index.ts +34 -0
  457. package/src/hooks/public/usePublicEvent.ts +261 -0
  458. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  459. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  460. package/src/hooks/useAppConfig.ts +94 -0
  461. package/src/hooks/useComponentPerformance.ts +39 -0
  462. package/src/hooks/useCounter.test.ts +135 -0
  463. package/src/hooks/useDataTablePerformance.ts +387 -0
  464. package/src/hooks/useDataTableState.ts +110 -0
  465. package/src/hooks/useDebounce.ts +18 -0
  466. package/src/hooks/useFocusManagement.ts +161 -0
  467. package/src/hooks/useFocusTrap.ts +155 -0
  468. package/src/hooks/useInactivityTracker.ts +372 -0
  469. package/src/hooks/useIsMobile.ts +42 -0
  470. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  471. package/src/hooks/useOrganisationPermissions.ts +208 -0
  472. package/src/hooks/useOrganisationSecurity.ts +262 -0
  473. package/src/hooks/usePerformanceMonitor.ts +128 -0
  474. package/src/hooks/usePermissionCache.ts +455 -0
  475. package/src/hooks/useRBAC.ts +262 -0
  476. package/src/hooks/useSecureDataAccess.ts +586 -0
  477. package/src/hooks/useStorage.ts +274 -0
  478. package/src/hooks/useToast.ts +242 -0
  479. package/src/hooks/useZodForm.ts +28 -0
  480. package/src/index.ts +200 -0
  481. package/src/providers/AuthProvider.tsx +369 -0
  482. package/src/providers/EventProvider.tsx +324 -0
  483. package/src/providers/InactivityProvider.tsx +238 -0
  484. package/src/providers/OrganisationProvider.tsx +588 -0
  485. package/src/providers/RBACProvider.tsx +634 -0
  486. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  487. package/src/providers/index.ts +15 -0
  488. package/src/rbac/README.md +885 -0
  489. package/src/rbac/adapters.tsx +726 -0
  490. package/src/rbac/api.ts +339 -0
  491. package/src/rbac/audit-enhanced.ts +339 -0
  492. package/src/rbac/audit.ts +338 -0
  493. package/src/rbac/cache.ts +215 -0
  494. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  495. package/src/rbac/components/NavigationGuard.tsx +294 -0
  496. package/src/rbac/components/NavigationProvider.tsx +314 -0
  497. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  498. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  499. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  500. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  501. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  502. package/src/rbac/components/index.ts +64 -0
  503. package/src/rbac/config.ts +133 -0
  504. package/src/rbac/docs/event-based-apps.md +285 -0
  505. package/src/rbac/engine.ts +1026 -0
  506. package/src/rbac/eslint-rules.js +285 -0
  507. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  508. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  509. package/src/rbac/hooks.ts +570 -0
  510. package/src/rbac/index.ts +114 -0
  511. package/src/rbac/permissions.ts +293 -0
  512. package/src/rbac/secureClient.ts +244 -0
  513. package/src/rbac/security.ts +346 -0
  514. package/src/rbac/testing/index.tsx +340 -0
  515. package/src/rbac/types.ts +343 -0
  516. package/src/rbac/utils/eventContext.ts +83 -0
  517. package/src/styles/core.css +422 -0
  518. package/src/styles/index.ts +51 -0
  519. package/src/theming/runtime.ts +187 -0
  520. package/src/types/database.ts +472 -0
  521. package/src/types/guards.ts +30 -0
  522. package/src/types/index.ts +25 -0
  523. package/src/types/organisation.ts +184 -0
  524. package/src/types/security.ts +70 -0
  525. package/src/types/supabase.ts +166 -0
  526. package/src/types/theme.ts +6 -0
  527. package/src/types/unified.ts +262 -0
  528. package/src/types/validation.ts +164 -0
  529. package/src/types/vitest-globals.d.ts +43 -0
  530. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  531. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  532. package/src/utils/appConfig.ts +47 -0
  533. package/src/utils/appIdResolver.ts +130 -0
  534. package/src/utils/appNameResolver.ts +190 -0
  535. package/src/utils/audit.ts +127 -0
  536. package/src/utils/auth-utils.ts +96 -0
  537. package/src/utils/bundleAnalysis.ts +129 -0
  538. package/src/utils/cn.ts +7 -0
  539. package/src/utils/debugLogger.ts +46 -0
  540. package/src/utils/deviceFingerprint.ts +215 -0
  541. package/src/utils/dynamicUtils.ts +105 -0
  542. package/src/utils/formatting.ts +77 -0
  543. package/src/utils/index.ts +145 -0
  544. package/src/utils/lazyLoad.tsx +44 -0
  545. package/src/utils/organisationContext.ts +135 -0
  546. package/src/utils/performanceBenchmark.ts +64 -0
  547. package/src/utils/performanceBudgets.ts +111 -0
  548. package/src/utils/permissionTypes.ts +37 -0
  549. package/src/utils/permissionUtils.ts +31 -0
  550. package/src/utils/print/PrintDataProcessor.ts +390 -0
  551. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  552. package/src/utils/print/index.ts +29 -0
  553. package/src/utils/print/types.ts +196 -0
  554. package/src/utils/print/usePrintOptimization.ts +272 -0
  555. package/src/utils/sanitization.ts +264 -0
  556. package/src/utils/schemaUtils.ts +37 -0
  557. package/src/utils/secureDataAccess.ts +361 -0
  558. package/src/utils/secureErrors.ts +79 -0
  559. package/src/utils/secureStorage.ts +244 -0
  560. package/src/utils/security.ts +156 -0
  561. package/src/utils/securityMonitor.ts +45 -0
  562. package/src/utils/sessionTracking.ts +170 -0
  563. package/src/utils/storage/README.md +348 -0
  564. package/src/utils/storage/config.ts +100 -0
  565. package/src/utils/storage/helpers.ts +359 -0
  566. package/src/utils/storage/index.ts +36 -0
  567. package/src/utils/storage/types.ts +90 -0
  568. package/src/utils/validation.ts +111 -0
  569. package/src/utils/validationUtils.ts +120 -0
  570. package/src/validation/common.ts +53 -0
  571. package/src/validation/csrf.ts +214 -0
  572. package/src/validation/index.ts +43 -0
  573. package/src/validation/passwordSchema.ts +125 -0
  574. package/src/validation/sanitization.ts +96 -0
  575. package/src/validation/schemaUtils.ts +42 -0
  576. package/src/validation/sqlInjectionProtection.ts +242 -0
  577. package/src/validation/user.ts +34 -0
  578. package/dist/UnifiedAuthProvider-V7y63NjT.d.ts +0 -88
  579. package/dist/chunk-4MCJAK7J.js.map +0 -1
  580. package/dist/chunk-4ZTIEYU2.js.map +0 -1
  581. package/dist/chunk-H4PZ4B3Y.js.map +0 -1
  582. package/dist/chunk-IOX76PSM.js.map +0 -1
  583. package/dist/chunk-JUUNUW3O.js.map +0 -1
  584. package/dist/chunk-U7DY5T33.js +0 -11
  585. package/dist/chunk-U7DY5T33.js.map +0 -1
  586. package/dist/chunk-WHLSWC6W.js.map +0 -1
  587. package/dist/chunk-XI7QFSSC.js +0 -790
  588. package/dist/chunk-XI7QFSSC.js.map +0 -1
  589. package/dist/chunk-XIJMMBDD.js +0 -73
  590. package/dist/chunk-XIJMMBDD.js.map +0 -1
  591. package/dist/chunk-YNU5QJ4S.js.map +0 -1
  592. package/dist/chunk-YWYCNGWH.js +0 -2070
  593. package/dist/chunk-YWYCNGWH.js.map +0 -1
  594. package/dist/chunk-ZJ3UKPIW.js +0 -952
  595. package/dist/chunk-ZJ3UKPIW.js.map +0 -1
  596. package/dist/useAppConfig-CZNJJsT_.d.ts +0 -148
  597. package/dist/{DataTable-2LB6HI6V.js.map → DataTable-GX3XERFJ.js.map} +0 -0
  598. package/dist/{api-AIJ3IJX3.js.map → api-ETQ6YJ3C.js.map} +0 -0
  599. package/dist/{audit-PD5L5ZSC.js.map → appNameResolver-7GHF5ED2.js.map} +0 -0
  600. package/dist/{chunk-DC5AMYBS.js.map → audit-BUW3LMJB.js.map} +0 -0
  601. package/dist/{validation-D2-NNCCE.d.ts → validation-PM_iOaTI.d.ts} +6 -6
@@ -8,9 +8,11 @@ The PACE Core DataTable is an enterprise-grade data table component built on Tan
8
8
 
9
9
  - **🚀 Performance Optimized** - Virtual scrolling, intelligent chunking, and automatic mode detection
10
10
  - **📊 Data Management** - Sorting, filtering, pagination, search, export/import
11
+ - **🌳 Hierarchical Rows** - Parent/child row relationships with expand/collapse all and smart sorting ([Detailed Guide](./hierarchical-datatable.md))
11
12
  - **✏️ Inline Editing** - Row editing, creation, and deletion
12
13
  - **🎯 Actions** - Custom row actions and toolbar buttons
13
14
  - **📈 Grouping** - Data grouping with aggregation functions
15
+ - **📏 Auto Column Sizing** - Automatic column width adjustment based on content
14
16
  - **🎨 Customizable** - Column visibility, responsive design, accessibility
15
17
  - **🔧 TypeScript** - Full TypeScript support with strict typing
16
18
 
@@ -55,8 +57,8 @@ const columns: DataTableColumn<User>[] = [
55
57
  cell: ({ row }) => (
56
58
  <span className={`px-2 py-1 rounded text-xs ${
57
59
  row.original.status === 'active'
58
- ? 'bg-green-100 text-green-800'
59
- : 'bg-red-100 text-red-800'
60
+ ? 'bg-main-100 text-main-800'
61
+ : 'bg-acc-100 text-acc-800'
60
62
  }`}>
61
63
  {row.original.status}
62
64
  </span>
@@ -82,6 +84,7 @@ function UserTable() {
82
84
  sorting: true,
83
85
  filtering: true,
84
86
  }}
87
+ columnOrder={['name', 'email', 'role', 'status']} // Control column order
85
88
  // Performance and other settings can be configured via performance prop
86
89
  />
87
90
  );
@@ -141,19 +144,22 @@ The DataTable component has a comprehensive prop interface. Here are the key pro
141
144
  - `description?: string` - Table description
142
145
  - `variant?: 'default' | 'compact' | 'spacious'` - Visual variant
143
146
  - `className?: string` - Additional CSS classes
147
+ - `columnOrder?: string[]` - **Column ordering** - Array of column IDs in desired order
144
148
 
145
149
  ### Event Handlers
146
150
  - `onEditRow?: (row: TData, data: Partial<TData>) => void` - Row edit handler
147
- - `onDeleteRow?: (row: TData) => void` - Row deletion handler
151
+ - `onDeleteRow?: (row: TData) => void` - Row deletion handler (also used as fallback for bulk delete)
148
152
  - `onCreateRow?: (data: Partial<TData>) => void` - Row creation handler
149
153
  - `onImport?: (data: TData[]) => void | Promise<void>` - Import handler
150
- - `onDeleteSelected?: (selectedRows: Record<string, boolean>) => void` - Bulk delete handler
154
+ - `onRowSelectionChange?: (selection: Record<string, boolean>) => void` - Row selection change handler
155
+ - `onDeleteSelected?: (selectedRows: Record<string, boolean>) => void` - **Bulk delete handler** - Called when delete selected button is clicked
151
156
 
152
157
  ### Performance Props
153
158
  - `performance?: PerformanceConfig` - Performance optimization settings
154
159
  - `serverSide?: ServerSideConfig<TData>` - Server-side data fetching
155
160
  - `virtualHeight?: number` - Virtual scrolling height (default: 600)
156
161
  - `showPerformanceMetrics?: boolean` - Show performance metrics
162
+ - `initialPageSize?: number` - Initial page size for pagination (default: 10)
157
163
 
158
164
  ### Feature-Specific Configuration
159
165
  - `bulkOperationsConfig?: BulkOperationsConfig` - Bulk operations config
@@ -165,6 +171,30 @@ The DataTable component has a comprehensive prop interface. Here are the key pro
165
171
 
166
172
  The DataTable component uses a unified `features` prop to control all table functionality. This provides a consistent and intuitive way to enable or disable features.
167
173
 
174
+ ### DataTableFeatureConfig Properties
175
+
176
+ | Property | Type | Default | Description |
177
+ |----------|------|---------|-------------|
178
+ | **Core Features** |
179
+ | `search` | `boolean` | `false` | Enable global search functionality |
180
+ | `pagination` | `boolean` | `false` | Enable pagination controls |
181
+ | `sorting` | `boolean` | `false` | Enable column sorting |
182
+ | `filtering` | `boolean` | `false` | Enable column filtering |
183
+ | **Data Management** |
184
+ | `import` | `boolean` | `false` | Enable data import functionality |
185
+ | `export` | `boolean` | `false` | Enable data export functionality |
186
+ | **Row Operations** |
187
+ | `selection` | `boolean` | `false` | Enable row selection for bulk operations |
188
+ | `creation` | `boolean` | `false` | Enable row creation |
189
+ | `editing` | `boolean` | `false` | Enable row editing |
190
+ | `deletion` | `boolean` | `false` | Enable row deletion |
191
+ | `deleteSelected` | `boolean` | `false` | Enable bulk deletion of selected rows |
192
+ | **Table Customization** |
193
+ | `grouping` | `boolean` | `false` | Enable data grouping |
194
+ | `columnVisibility` | `boolean` | `false` | Enable column visibility controls |
195
+ | `columnReordering` | `boolean` | `false` | Enable column reordering |
196
+ | `autoColumnSizing` | `boolean` | `false` | Enable automatic column width adjustment based on content |
197
+
168
198
  ### Basic Feature Configuration
169
199
 
170
200
  ```tsx
@@ -183,25 +213,17 @@ The DataTable component uses a unified `features` prop to control all table func
183
213
  export: true,
184
214
 
185
215
  // Row Operations
186
- selection: true,
216
+ selection: true, // Required for row selection
187
217
  creation: true,
188
218
  editing: true,
189
- deletion: true,
190
- deleteSelected: true,
219
+ deletion: true, // Required for delete functionality
220
+ deleteSelected: true, // Required for delete selected button
191
221
 
192
222
  // Table Customization
193
223
  grouping: true,
194
224
  columnVisibility: true,
195
225
  columnReordering: true,
196
-
197
- // Performance
198
- virtualization: true,
199
- performanceMetrics: true,
200
-
201
- // Advanced Features
202
- inlineEditing: true,
203
- bulkOperations: true,
204
- rowActions: true,
226
+ autoColumnSizing: true, // Enable automatic column width adjustment
205
227
  }}
206
228
  />
207
229
  ```
@@ -239,17 +261,93 @@ For a full-featured data management table:
239
261
  creation: true,
240
262
  editing: true,
241
263
  deletion: true,
264
+ deleteSelected: true, // Enable delete selected functionality
242
265
  export: true,
243
266
  import: true,
244
267
  grouping: true,
245
268
  columnVisibility: true,
246
269
  bulkOperations: true,
247
270
  }}
271
+ columnOrder={['select', 'name', 'email', 'role', 'status', 'actions']} // Custom column order
248
272
  onEditRow={handleEdit}
249
273
  onDeleteRow={handleDelete}
250
274
  onCreateRow={handleCreate}
251
275
  onImport={handleImport}
276
+ onRowSelectionChange={handleSelectionChange}
252
277
  onDeleteSelected={handleBulkDelete}
278
+ getRowId={(row) => row.id} // Important: Required for selection and delete operations
279
+ />
280
+ ```
281
+
282
+ ## Auto Column Sizing
283
+
284
+ The DataTable component includes automatic column width adjustment based on content, which helps optimize space usage and improve readability.
285
+
286
+ ### How Auto-Sizing Works
287
+
288
+ When `autoColumnSizing: true` is enabled:
289
+
290
+ 1. **Content Analysis**: Analyzes both header text and data content to determine optimal widths
291
+ 2. **Smart Calculation**: Uses character count estimation (8px per character + padding)
292
+ 3. **Constraints**: Respects min-width (80px) and max-width (400px) limits
293
+ 4. **Performance**: Only samples first 100 rows for large datasets
294
+ 5. **Table Layout**: Switches from `tableLayout: 'fixed'` to `tableLayout: 'auto'`
295
+
296
+ ### Benefits
297
+
298
+ - **Better Space Utilization**: Columns automatically adjust to content width
299
+ - **Improved Readability**: Long text gets more space, short text takes less space
300
+ - **No Text Wrapping**: Prevents unnecessary text wrapping in narrow columns
301
+ - **Consistent Layout**: Maintains proper spacing and alignment
302
+
303
+ ### Enabling Auto-Sizing
304
+
305
+ ```tsx
306
+ <DataTable
307
+ data={data}
308
+ columns={columns}
309
+ features={{
310
+ search: true,
311
+ pagination: true,
312
+ sorting: true,
313
+ autoColumnSizing: true, // Enable automatic column width adjustment
314
+ }}
315
+ />
316
+ ```
317
+
318
+ ### Auto-Sizing vs Fixed Widths
319
+
320
+ **With Auto-Sizing (Recommended):**
321
+ - Columns automatically adjust to content width
322
+ - Long text gets more space, short text takes less space
323
+ - Better space utilization
324
+ - Improved readability
325
+
326
+ **Without Auto-Sizing:**
327
+ - All columns have equal width
328
+ - Long text may wrap unnecessarily
329
+ - Short columns have wasted space
330
+ - Consistent but potentially inefficient layout
331
+
332
+ ### Example: Content-Based Sizing
333
+
334
+ ```tsx
335
+ const data = [
336
+ { id: '1', name: 'John', description: 'A short description' },
337
+ { id: '2', name: 'Jane', description: 'A very long description that should make this column wider' },
338
+ { id: '3', name: 'Bob', description: 'Medium length description' }
339
+ ];
340
+
341
+ const columns = [
342
+ { accessorKey: 'name', header: 'Name' },
343
+ { accessorKey: 'description', header: 'Description' }
344
+ ];
345
+
346
+ // With auto-sizing: Description column will be wider than Name column
347
+ <DataTable
348
+ data={data}
349
+ columns={columns}
350
+ features={{ autoColumnSizing: true }}
253
351
  />
254
352
  ```
255
353
 
@@ -361,6 +459,275 @@ const columns: DataTableColumn<User>[] = [
361
459
  ];
362
460
  ```
363
461
 
462
+ ## Column Ordering
463
+
464
+ The DataTable component supports custom column ordering through the `columnOrder` prop, allowing you to control the exact position of columns including selection and actions columns.
465
+
466
+ ### Basic Column Ordering
467
+
468
+ ```tsx
469
+ <DataTable
470
+ data={data}
471
+ columns={columns}
472
+ features={{
473
+ selection: true,
474
+ sorting: true,
475
+ filtering: true,
476
+ }}
477
+ columnOrder={['select', 'name', 'email', 'role', 'status']}
478
+ />
479
+ ```
480
+
481
+ ### Column Order Behavior
482
+
483
+ #### When `columnOrder` is provided:
484
+ - **Exact positioning**: Columns appear in the exact order specified
485
+ - **Selection column**: Include `'select'` in the array to position the selection column
486
+ - **Actions column**: Include `'actions'` in the array to position the actions column
487
+ - **Data columns**: Use the column's `accessorKey` or `id` to reference data columns
488
+
489
+ #### When `columnOrder` is not provided:
490
+ - **Default behavior**: Selection column first (if enabled), then data columns, then actions column
491
+ - **Automatic ordering**: Columns appear in the order they're defined in the `columns` array
492
+
493
+ ### Selection Column Positioning
494
+
495
+ The selection column can be positioned anywhere in the column order:
496
+
497
+ ```tsx
498
+ // Selection column first (default when not in columnOrder)
499
+ <DataTable
500
+ data={data}
501
+ columns={columns}
502
+ features={{ selection: true }}
503
+ columnOrder={['select', 'name', 'email', 'role']}
504
+ />
505
+
506
+ // Selection column in the middle
507
+ <DataTable
508
+ data={data}
509
+ columns={columns}
510
+ features={{ selection: true }}
511
+ columnOrder={['name', 'select', 'email', 'role']}
512
+ />
513
+
514
+ // Selection column last
515
+ <DataTable
516
+ data={data}
517
+ columns={columns}
518
+ features={{ selection: true }}
519
+ columnOrder={['name', 'email', 'role', 'select']}
520
+ />
521
+
522
+ // Selection column not in columnOrder - defaults to first position
523
+ <DataTable
524
+ data={data}
525
+ columns={columns}
526
+ features={{ selection: true }}
527
+ columnOrder={['name', 'email', 'role']} // selection will be first
528
+ />
529
+ ```
530
+
531
+ ### Actions Column Positioning
532
+
533
+ The actions column can also be positioned anywhere:
534
+
535
+ ```tsx
536
+ // Actions column last (default when not in columnOrder)
537
+ <DataTable
538
+ data={data}
539
+ columns={columns}
540
+ features={{ editing: true, deletion: true }}
541
+ columnOrder={['name', 'email', 'role', 'actions']}
542
+ />
543
+
544
+ // Actions column first
545
+ <DataTable
546
+ data={data}
547
+ columns={columns}
548
+ features={{ editing: true, deletion: true }}
549
+ columnOrder={['actions', 'name', 'email', 'role']}
550
+ />
551
+
552
+ // Actions column in the middle
553
+ <DataTable
554
+ data={data}
555
+ columns={columns}
556
+ features={{ editing: true, deletion: true }}
557
+ columnOrder={['name', 'actions', 'email', 'role']}
558
+ />
559
+ ```
560
+
561
+ ### Complete Column Ordering Example
562
+
563
+ ```tsx
564
+ interface User {
565
+ id: string;
566
+ name: string;
567
+ email: string;
568
+ role: string;
569
+ status: 'active' | 'inactive';
570
+ createdAt: Date;
571
+ }
572
+
573
+ const columns: DataTableColumn<User>[] = [
574
+ {
575
+ accessorKey: 'name',
576
+ header: 'Name',
577
+ sortable: true,
578
+ },
579
+ {
580
+ accessorKey: 'email',
581
+ header: 'Email',
582
+ sortable: true,
583
+ },
584
+ {
585
+ accessorKey: 'role',
586
+ header: 'Role',
587
+ sortable: true,
588
+ enableGrouping: true,
589
+ },
590
+ {
591
+ accessorKey: 'status',
592
+ header: 'Status',
593
+ sortable: true,
594
+ },
595
+ {
596
+ accessorKey: 'createdAt',
597
+ header: 'Created',
598
+ sortable: true,
599
+ },
600
+ ];
601
+
602
+ function UserTable() {
603
+ return (
604
+ <DataTable
605
+ data={users}
606
+ columns={columns}
607
+ title="User Management"
608
+ features={{
609
+ selection: true,
610
+ sorting: true,
611
+ filtering: true,
612
+ editing: true,
613
+ deletion: true,
614
+ }}
615
+ // Custom column order: selection first, then name, email, role, status, actions, created last
616
+ columnOrder={['select', 'name', 'email', 'role', 'status', 'actions', 'createdAt']}
617
+ onEditRow={handleEdit}
618
+ onDeleteRow={handleDelete}
619
+ />
620
+ );
621
+ }
622
+ ```
623
+
624
+ ### Column Ordering with Hierarchical Data
625
+
626
+ When using hierarchical data, column ordering works the same way:
627
+
628
+ ```tsx
629
+ <DataTable
630
+ data={hierarchicalData}
631
+ columns={columns}
632
+ features={{
633
+ hierarchical: true,
634
+ selection: true,
635
+ editing: true,
636
+ deletion: true,
637
+ }}
638
+ hierarchical={{
639
+ enabled: true,
640
+ defaultExpanded: false,
641
+ }}
642
+ // Custom order for hierarchical table
643
+ columnOrder={['select', 'name', 'ingredient', 'quantity', 'actions']}
644
+ />
645
+ ```
646
+
647
+ ### Dynamic Column Ordering
648
+
649
+ You can dynamically change column order based on user preferences or application state:
650
+
651
+ ```tsx
652
+ function DynamicUserTable() {
653
+ const [columnOrder, setColumnOrder] = useState(['select', 'name', 'email', 'role', 'status']);
654
+
655
+ const handleColumnReorder = (newOrder: string[]) => {
656
+ setColumnOrder(newOrder);
657
+ // Save to localStorage or user preferences
658
+ localStorage.setItem('userTableColumnOrder', JSON.stringify(newOrder));
659
+ };
660
+
661
+ return (
662
+ <DataTable
663
+ data={users}
664
+ columns={columns}
665
+ features={{
666
+ selection: true,
667
+ sorting: true,
668
+ columnReordering: true, // Enable drag-and-drop reordering
669
+ }}
670
+ columnOrder={columnOrder}
671
+ onColumnOrderChange={handleColumnReorder}
672
+ />
673
+ );
674
+ }
675
+ ```
676
+
677
+ ### Column Ordering Best Practices
678
+
679
+ #### 1. **Consistent Ordering**
680
+ ```tsx
681
+ // ✅ Good - Consistent ordering across similar tables
682
+ const userTableOrder = ['select', 'name', 'email', 'role', 'status', 'actions'];
683
+ const productTableOrder = ['select', 'name', 'sku', 'price', 'status', 'actions'];
684
+
685
+ // ❌ Avoid - Inconsistent ordering
686
+ const userTableOrder = ['select', 'name', 'email', 'role', 'status', 'actions'];
687
+ const productTableOrder = ['name', 'select', 'sku', 'actions', 'price', 'status'];
688
+ ```
689
+
690
+ #### 2. **Logical Grouping**
691
+ ```tsx
692
+ // ✅ Good - Logical grouping of related columns
693
+ columnOrder={[
694
+ 'select', // Selection controls
695
+ 'name', 'email', // Identity information
696
+ 'role', 'status', // Access and state
697
+ 'createdAt', // Metadata
698
+ 'actions' // Actions
699
+ ]}
700
+
701
+ // ❌ Avoid - Random column order
702
+ columnOrder={['email', 'actions', 'name', 'select', 'status', 'role', 'createdAt']}
703
+ ```
704
+
705
+ #### 3. **User Experience Considerations**
706
+ ```tsx
707
+ // ✅ Good - Most important columns first
708
+ columnOrder={['select', 'name', 'email', 'role', 'status', 'actions']}
709
+
710
+ // ✅ Good - Actions column last (standard pattern)
711
+ columnOrder={['select', 'name', 'email', 'role', 'status', 'actions']}
712
+
713
+ // ❌ Avoid - Actions column in the middle (confusing)
714
+ columnOrder={['select', 'name', 'actions', 'email', 'role', 'status']}
715
+ ```
716
+
717
+ #### 4. **Responsive Considerations**
718
+ ```tsx
719
+ // For mobile-first design, put most important columns first
720
+ const mobileColumnOrder = ['select', 'name', 'status', 'actions'];
721
+ const desktopColumnOrder = ['select', 'name', 'email', 'role', 'status', 'createdAt', 'actions'];
722
+
723
+ <DataTable
724
+ data={users}
725
+ columns={columns}
726
+ features={{ selection: true, sorting: true }}
727
+ columnOrder={isMobile ? mobileColumnOrder : desktopColumnOrder}
728
+ />
729
+ ```
730
+
364
731
  ## Data Management
365
732
 
366
733
  ### Sorting
@@ -402,6 +769,35 @@ const columns: DataTableColumn<User>[] = [
402
769
  />
403
770
  ```
404
771
 
772
+ #### Custom Initial Page Size
773
+
774
+ ```tsx
775
+ <DataTable
776
+ data={data}
777
+ columns={columns}
778
+ features={{ pagination: true }}
779
+ initialPageSize={25} // Start with 25 items per page instead of default 10
780
+ />
781
+ ```
782
+
783
+ #### Page Size Validation
784
+
785
+ The DataTable automatically validates the `initialPageSize` against available page size options:
786
+
787
+ ```tsx
788
+ <DataTable
789
+ data={data}
790
+ columns={columns}
791
+ features={{ pagination: true }}
792
+ initialPageSize={15} // Will fallback to closest valid option (10) with console warning
793
+ />
794
+ ```
795
+
796
+ **Available page size options by mode:**
797
+ - **Client mode**: `[10, 25, 50]` or `[10, 25, 50, 100]` (depending on data size)
798
+ - **Hybrid mode**: `[50, 100, 250, 500]`
799
+ - **Server mode**: `[25, 50, 100, 250]`
800
+
405
801
  ### Search
406
802
 
407
803
  ```tsx
@@ -439,6 +835,24 @@ Row actions are handled through the `actions` prop, which provides full flexibil
439
835
  icon: EyeIcon,
440
836
  variant: 'default',
441
837
  },
838
+ {
839
+ label: 'Edit',
840
+ onClick: (row) => editUser(row.original.id),
841
+ icon: EditIcon,
842
+ variant: 'outline',
843
+ },
844
+ {
845
+ label: 'Share',
846
+ onClick: (row) => shareUser(row.original.id),
847
+ icon: ShareIcon,
848
+ variant: 'secondary',
849
+ },
850
+ {
851
+ label: 'More Options',
852
+ onClick: (row) => showMoreOptions(row.original.id),
853
+ icon: MoreHorizontalIcon,
854
+ variant: 'ghost',
855
+ },
442
856
  {
443
857
  label: 'Archive',
444
858
  onClick: (row) => archiveUser(row.original.id),
@@ -464,6 +878,155 @@ Each action supports the following properties:
464
878
  - `showInEditMode?: boolean` - Show in edit mode (default: true)
465
879
  - `hideInViewMode?: boolean` - Hide in view mode (default: false)
466
880
 
881
+ #### Action Variants Guide
882
+
883
+ The DataTable supports 5 action variants, each designed for specific use cases:
884
+
885
+ ```tsx
886
+ const actions = [
887
+ // DEFAULT - Primary actions (most important)
888
+ {
889
+ label: 'View Details',
890
+ onClick: (row) => viewDetails(row.original.id),
891
+ icon: EyeIcon,
892
+ variant: 'default', // Solid background, primary color
893
+ },
894
+
895
+ // OUTLINE - Secondary actions (important but not primary)
896
+ {
897
+ label: 'Edit',
898
+ onClick: (row) => editItem(row.original.id),
899
+ icon: EditIcon,
900
+ variant: 'outline', // Bordered, transparent background
901
+ },
902
+
903
+ // SECONDARY - Supporting actions (less prominent)
904
+ {
905
+ label: 'Share',
906
+ onClick: (row) => shareItem(row.original.id),
907
+ icon: ShareIcon,
908
+ variant: 'secondary', // Muted background, subtle styling
909
+ },
910
+
911
+ // GHOST - Subtle actions (minimal visual impact)
912
+ {
913
+ label: 'More Options',
914
+ onClick: (row) => showMoreOptions(row.original.id),
915
+ icon: MoreHorizontalIcon,
916
+ variant: 'ghost', // No background, minimal styling
917
+ },
918
+
919
+ // DESTRUCTIVE - Dangerous actions (require caution)
920
+ {
921
+ label: 'Delete',
922
+ onClick: (row) => deleteItem(row.original.id),
923
+ icon: TrashIcon,
924
+ variant: 'destructive', // Red styling to indicate danger
925
+ disabled: (row) => row.original.status === 'locked',
926
+ },
927
+ ];
928
+ ```
929
+
930
+ **Variant Usage Guidelines:**
931
+
932
+ - **`default`**: Use for the most important action (e.g., "View Details", "Open")
933
+ - **`outline`**: Use for important secondary actions (e.g., "Edit", "Download")
934
+ - **`secondary`**: Use for supporting actions (e.g., "Share", "Copy", "Export")
935
+ - **`ghost`**: Use for subtle actions (e.g., "More Options", "Settings")
936
+ - **`destructive`**: Use for dangerous actions (e.g., "Delete", "Archive", "Remove")
937
+
938
+ #### Hierarchical Actions
939
+
940
+ When using hierarchical rows, you can define different action icons and labels for parent vs child rows:
941
+
942
+ ```tsx
943
+ <DataTable
944
+ data={hierarchicalData}
945
+ columns={columns}
946
+ features={{
947
+ hierarchical: true,
948
+ editing: true,
949
+ deletion: true,
950
+ }}
951
+ hierarchical={{
952
+ enabled: true,
953
+ defaultExpanded: false,
954
+ }}
955
+ actions={[
956
+ {
957
+ label: 'View Details',
958
+ icon: EyeIcon,
959
+ // Different icons for parent vs child rows
960
+ parentIcon: EyeIcon,
961
+ childIcon: InfoIcon,
962
+ // Different labels for parent vs child rows
963
+ parentLabel: 'View Recipe',
964
+ childLabel: 'View Ingredient',
965
+ onClick: (row) => {
966
+ console.log('Viewing:', row.isParent ? 'Recipe' : 'Ingredient', row.name);
967
+ },
968
+ variant: 'default',
969
+ },
970
+ {
971
+ label: 'Edit',
972
+ icon: PencilIcon,
973
+ parentIcon: SettingsIcon,
974
+ childIcon: PencilIcon,
975
+ parentLabel: 'Edit Recipe',
976
+ childLabel: 'Edit Ingredient',
977
+ onClick: (row) => {
978
+ console.log('Editing:', row.isParent ? 'Recipe' : 'Ingredient', row.name);
979
+ },
980
+ variant: 'default',
981
+ },
982
+ {
983
+ label: 'Copy Recipe',
984
+ icon: CopyIcon,
985
+ parentIcon: CopyIcon,
986
+ parentLabel: 'Duplicate Recipe',
987
+ onClick: (row) => {
988
+ console.log('Copying recipe:', row.name);
989
+ },
990
+ variant: 'outline',
991
+ // Only show for parent rows
992
+ showForParent: true,
993
+ },
994
+ {
995
+ label: 'Export',
996
+ icon: DownloadIcon,
997
+ childIcon: DownloadIcon,
998
+ childLabel: 'Export Ingredient',
999
+ onClick: (row) => {
1000
+ console.log('Exporting ingredient:', row.item);
1001
+ },
1002
+ variant: 'ghost',
1003
+ // Only show for child rows
1004
+ showForChild: true,
1005
+ },
1006
+ ]}
1007
+ />
1008
+ ```
1009
+
1010
+ ##### Hierarchical Action Properties
1011
+
1012
+ When using hierarchical rows, actions support additional properties:
1013
+
1014
+ - `showForParent?: boolean` - Only show this action for parent rows
1015
+ - `showForChild?: boolean` - Only show this action for child rows
1016
+ - `parentIcon?: ComponentType` - Icon to use for parent rows (overrides `icon`)
1017
+ - `childIcon?: ComponentType` - Icon to use for child rows (overrides `icon`)
1018
+ - `parentLabel?: string` - Label to use for parent rows (overrides `label`)
1019
+ - `childLabel?: string` - Label to use for child rows (overrides `label`)
1020
+
1021
+ ##### Action Visibility Logic
1022
+
1023
+ The action visibility is determined by the following logic:
1024
+
1025
+ 1. **Hierarchical filtering**: If `showForParent` is true, action only shows for parent rows
1026
+ 2. **Hierarchical filtering**: If `showForChild` is true, action only shows for child rows
1027
+ 3. **Standard filtering**: Uses `visible`, `showInEditMode`, `hideInViewMode` properties
1028
+ 4. **Disabled state**: Uses `disabled` function to determine if action is disabled
1029
+
467
1030
  ### Toolbar Actions
468
1031
 
469
1032
  Toolbar actions are automatically generated based on the enabled features. Custom toolbar buttons are not directly supported in the current interface, but you can implement them outside the DataTable component:
@@ -496,11 +1059,218 @@ Toolbar actions are automatically generated based on the enabled features. Custo
496
1059
  </div>
497
1060
  ```
498
1061
 
1062
+ ### Hierarchical Parent/Child Rows
1063
+
1064
+ The DataTable supports hierarchical parent/child row relationships with built-in expand/collapse functionality, expand/collapse all controls, and proper column rendering for different row types.
1065
+
1066
+ #### Data Structure
1067
+
1068
+ Your data must conform to the `HierarchicalDataRow` interface:
1069
+
1070
+ ```typescript
1071
+ interface HierarchicalDataRow extends DataRecord {
1072
+ /** Whether this row is a parent row */
1073
+ isParent: boolean;
1074
+ /** For child rows, references the parent row ID */
1075
+ parentId?: string;
1076
+ /** Unique identifier for this row */
1077
+ id: string;
1078
+ // ... your actual data properties
1079
+ }
1080
+ ```
1081
+
1082
+ #### Configuration
1083
+
1084
+ Enable hierarchical functionality through the `features` prop and configure it with the `hierarchical` prop:
1085
+
1086
+ ```tsx
1087
+ <DataTable
1088
+ data={hierarchicalData}
1089
+ columns={columns}
1090
+ features={{
1091
+ // ... other features
1092
+ hierarchical: true, // Enable hierarchical functionality
1093
+ }}
1094
+ hierarchical={{
1095
+ enabled: true,
1096
+ defaultExpanded: false, // true = all expanded, false = all collapsed, array = specific IDs
1097
+ onExpandedChange: (expandedIds) => console.log('Expanded:', expandedIds),
1098
+ expandButton: CustomExpandButton, // Optional custom expand button
1099
+ indentSize: 24, // Indentation for child rows in pixels
1100
+ parentRowClassName: 'bg-main-50 font-medium', // Custom styling for parent rows
1101
+ childRowClassName: 'bg-sec-25', // Custom styling for child rows
1102
+ }}
1103
+ ```
1104
+
1105
+ **Default Collapsed State:**
1106
+ To make parent rows collapsed by default (recommended for better UX), set `defaultExpanded: false`. This ensures users see only parent rows initially and must click to expand and view child rows.
1107
+
1108
+ #### Column Configuration
1109
+
1110
+ Configure how columns render for different row types:
1111
+
1112
+ ```tsx
1113
+ const columns: DataTableColumn<YourDataType>[] = [
1114
+ {
1115
+ accessorKey: 'code',
1116
+ header: 'Code',
1117
+ // Render differently for parent vs child rows
1118
+ renderForParent: (row) => (
1119
+ <div className="flex items-center gap-2">
1120
+ <strong>{row.code}</strong>
1121
+ </div>
1122
+ ),
1123
+ renderForChild: () => '', // Blank for child rows
1124
+ hideForChild: true, // Hide this column for child rows
1125
+ },
1126
+ {
1127
+ accessorKey: 'name',
1128
+ header: 'Name',
1129
+ renderForParent: (row) => <strong>{row.name}</strong>,
1130
+ renderForChild: () => '', // Blank for child rows
1131
+ hideForChild: true,
1132
+ },
1133
+ {
1134
+ accessorKey: 'ingredient',
1135
+ header: 'Ingredient',
1136
+ renderForParent: () => '', // Blank for parent rows
1137
+ renderForChild: (row) => <span className="ml-4">{row.ingredient}</span>,
1138
+ hideForParent: true, // Hide this column for parent rows
1139
+ },
1140
+ ];
1141
+ ```
1142
+
1143
+ #### Column Properties
1144
+
1145
+ - `renderForParent?: (row: TData) => React.ReactNode` - Custom renderer for parent rows
1146
+ - `renderForChild?: (row: TData) => React.ReactNode` - Custom renderer for child rows
1147
+ - `hideForParent?: boolean` - Hide this column for parent rows
1148
+ - `hideForChild?: boolean` - Hide this column for child rows
1149
+
1150
+ #### Expand/Collapse All Controls
1151
+
1152
+ The DataTable automatically adds an expand/collapse all button in the header when hierarchical mode is enabled:
1153
+
1154
+ **Features:**
1155
+ - **Expand All Button (▶️)**: Expands all parent rows to show their children
1156
+ - **Collapse All Button (🔽)**: Collapses all parent rows to hide their children
1157
+ - **Smart State Detection**: Button automatically updates based on current expansion state
1158
+ - **Accessibility**: Proper ARIA labels and keyboard navigation support
1159
+
1160
+ **Usage:**
1161
+ ```tsx
1162
+ <DataTable
1163
+ data={hierarchicalData}
1164
+ columns={columns}
1165
+ features={{ hierarchical: true }}
1166
+ hierarchical={{
1167
+ enabled: true,
1168
+ defaultExpanded: false, // Start with all collapsed
1169
+ onExpandedChange: (expandedIds) => {
1170
+ console.log('Expanded rows:', expandedIds);
1171
+ },
1172
+ }}
1173
+ />
1174
+ ```
1175
+
1176
+ **Button Behavior:**
1177
+ - Shows ▶️ when some or all parent rows are collapsed
1178
+ - Shows 🔽 when all parent rows are expanded
1179
+ - Only appears when there are parent rows with children
1180
+ - Positioned in the first column of the table header
1181
+
1182
+ #### Hierarchical Sorting
1183
+
1184
+ When hierarchical mode is enabled, sorting behavior is optimized to preserve the parent-child relationship structure:
1185
+
1186
+ **Parent Row Sorting:**
1187
+ - Parent rows maintain their original order and are not affected by sorting
1188
+ - Only child rows within each parent group are sorted
1189
+ - This prevents parent rows from being moved to unexpected positions
1190
+
1191
+ **Child Row Sorting:**
1192
+ - Child rows are sorted within their parent group only
1193
+ - Sorting by a child-specific column (e.g., "Diet", "Ingredient") will sort children within each parent
1194
+ - The parent row remains at the top of its group
1195
+
1196
+ **Example:**
1197
+ ```tsx
1198
+ // When sorting by "Diet" column:
1199
+ // ✅ Correct behavior:
1200
+ // Parent: Caesar Salad
1201
+ // ├─ Child: Dairy Free (Sour cream)
1202
+ // ├─ Child: Egg Free (Mayonnaise)
1203
+ // └─ Child: GF & Vegan (Lettuce)
1204
+ // Parent: Beef Stir Fry
1205
+ // ├─ Child: GF & Vegan (Vegetables)
1206
+ // └─ Child: Halal (Beef)
1207
+
1208
+ // ❌ Incorrect behavior (what we prevent):
1209
+ // Child: Dairy Free (Sour cream)
1210
+ // Child: Egg Free (Mayonnaise)
1211
+ // Child: GF & Vegan (Lettuce)
1212
+ // Child: GF & Vegan (Vegetables)
1213
+ // Child: Halal (Beef)
1214
+ // Parent: Caesar Salad (moved to end)
1215
+ // Parent: Beef Stir Fry (moved to end)
1216
+ ```
1217
+
1218
+ **Sorting Configuration:**
1219
+ - All existing sorting features work with hierarchical data
1220
+ - Multi-column sorting is supported
1221
+ - Server-side sorting is compatible
1222
+ - Column-specific sorting behavior is preserved
1223
+
1224
+ #### Example Use Case
1225
+
1226
+ ```tsx
1227
+ // Dishes and ingredients example
1228
+ const dishData = [
1229
+ // Parent rows (dishes)
1230
+ { id: 'dish-1', isParent: true, code: 'D001', name: 'Caesar Salad', type: 'Salad' },
1231
+ { id: 'dish-2', isParent: true, code: 'D002', name: 'Beef Stir Fry', type: 'Main Course' },
1232
+
1233
+ // Child rows (ingredients) for Caesar Salad
1234
+ { id: 'ing-1-1', isParent: false, parentId: 'dish-1', ingredient: 'Lettuce', quantity: '200g' },
1235
+ { id: 'ing-1-2', isParent: false, parentId: 'dish-1', ingredient: 'Chicken', quantity: '150g' },
1236
+
1237
+ // Child rows (ingredients) for Beef Stir Fry
1238
+ { id: 'ing-2-1', isParent: false, parentId: 'dish-2', ingredient: 'Beef Strips', quantity: '250g' },
1239
+ { id: 'ing-2-2', isParent: false, parentId: 'dish-2', ingredient: 'Mixed Vegetables', quantity: '200g' },
1240
+ ];
1241
+ ```
1242
+
499
1243
  ### Row Selection and Bulk Operations
500
1244
 
501
1245
  ```tsx
502
1246
  function SelectableUserTable() {
503
- const [selectedRows, setSelectedRows] = useState<RowSelectionState>({});
1247
+ const [selectedRows, setSelectedRows] = useState<Record<string, boolean>>({});
1248
+ const [data, setData] = useState<User[]>(initialData);
1249
+
1250
+ const handleBulkDelete = (selectedRows: Record<string, boolean>) => {
1251
+ // Get the selected row IDs
1252
+ const selectedRowIds = Object.keys(selectedRows).filter(id => selectedRows[id]);
1253
+
1254
+ // Get the actual data for selected rows
1255
+ const selectedData = data.filter(row => {
1256
+ const rowId = getRowId ? getRowId(row, data.indexOf(row)) : row.id;
1257
+ return selectedRowIds.includes(rowId);
1258
+ });
1259
+
1260
+ // Perform your deletion logic
1261
+ console.log('Deleting selected rows:', selectedData);
1262
+
1263
+ // Update your data state
1264
+ setData(prevData =>
1265
+ prevData.filter(row => {
1266
+ const rowId = getRowId ? getRowId(row, prevData.indexOf(row)) : row.id;
1267
+ return !selectedRowIds.includes(rowId);
1268
+ })
1269
+ );
1270
+
1271
+ // Clear selection after deletion
1272
+ setSelectedRows({});
1273
+ };
504
1274
 
505
1275
  return (
506
1276
  <DataTable
@@ -508,23 +1278,44 @@ function SelectableUserTable() {
508
1278
  columns={columns}
509
1279
  features={{
510
1280
  selection: true,
1281
+ deletion: true, // Required for delete functionality
1282
+ deleteSelected: true, // Enables the delete selected button
511
1283
  bulkOperations: true,
512
- deleteSelected: true,
513
1284
  }}
514
- rowSelection={selectedRows}
515
1285
  onRowSelectionChange={setSelectedRows}
516
1286
  onDeleteSelected={handleBulkDelete}
517
- bulkOperationsConfig={{
518
- enabled: true,
519
- operations: [
520
- {
521
- label: 'Delete Selected',
522
- action: 'delete',
523
- variant: 'destructive',
524
- requiresConfirmation: true,
525
- },
526
- ],
1287
+ getRowId={(row) => row.id} // Important: provide getRowId for proper row identification
1288
+ />
1289
+ );
1290
+ }
1291
+ ```
1292
+
1293
+ #### Alternative: Using Individual onDeleteRow (Fallback)
1294
+
1295
+ If you don't provide `onDeleteSelected`, the DataTable will automatically fall back to calling `onDeleteRow` for each selected row:
1296
+
1297
+ ```tsx
1298
+ function SelectableUserTable() {
1299
+ const [data, setData] = useState<User[]>(initialData);
1300
+
1301
+ const handleDeleteRow = (row: User) => {
1302
+ console.log('Deleting row:', row);
1303
+
1304
+ // Update your data state
1305
+ setData(prevData => prevData.filter(item => item.id !== row.id));
1306
+ };
1307
+
1308
+ return (
1309
+ <DataTable
1310
+ data={data}
1311
+ columns={columns}
1312
+ features={{
1313
+ selection: true,
1314
+ deletion: true,
1315
+ deleteSelected: true,
527
1316
  }}
1317
+ onDeleteRow={handleDeleteRow} // This will be called for each selected row
1318
+ getRowId={(row) => row.id}
528
1319
  />
529
1320
  );
530
1321
  }
@@ -680,8 +1471,191 @@ function SecureUserTable() {
680
1471
  }
681
1472
  ```
682
1473
 
1474
+ ## Practical Examples
1475
+
1476
+ ### Custom Page Size Configuration
1477
+
1478
+ Here's a complete example showing how to configure a DataTable with custom initial page size:
1479
+
1480
+ ```tsx
1481
+ import { DataTable, type DataTableColumn } from '@jmruthers/pace-core';
1482
+
1483
+ interface User {
1484
+ id: string;
1485
+ name: string;
1486
+ email: string;
1487
+ role: string;
1488
+ status: 'active' | 'inactive';
1489
+ }
1490
+
1491
+ const columns: DataTableColumn<User>[] = [
1492
+ {
1493
+ accessorKey: 'name',
1494
+ header: 'Name',
1495
+ sortable: true,
1496
+ searchable: true,
1497
+ },
1498
+ {
1499
+ accessorKey: 'email',
1500
+ header: 'Email',
1501
+ sortable: true,
1502
+ searchable: true,
1503
+ },
1504
+ {
1505
+ accessorKey: 'role',
1506
+ header: 'Role',
1507
+ sortable: true,
1508
+ enableGrouping: true,
1509
+ },
1510
+ {
1511
+ accessorKey: 'status',
1512
+ header: 'Status',
1513
+ sortable: true,
1514
+ cell: ({ row }) => (
1515
+ <span className={`px-2 py-1 rounded text-xs ${
1516
+ row.original.status === 'active'
1517
+ ? 'bg-main-100 text-main-800'
1518
+ : 'bg-acc-100 text-acc-800'
1519
+ }`}>
1520
+ {row.original.status}
1521
+ </span>
1522
+ ),
1523
+ },
1524
+ ];
1525
+
1526
+ function UserManagementTable() {
1527
+ const [users, setUsers] = useState<User[]>([]);
1528
+ const [loading, setLoading] = useState(true);
1529
+
1530
+ useEffect(() => {
1531
+ // Load users data
1532
+ loadUsers().then(setUsers).finally(() => setLoading(false));
1533
+ }, []);
1534
+
1535
+ return (
1536
+ <DataTable
1537
+ data={users}
1538
+ columns={columns}
1539
+ title="User Management"
1540
+ description="Manage system users with custom page size"
1541
+ features={{
1542
+ search: true,
1543
+ pagination: true,
1544
+ sorting: true,
1545
+ filtering: true,
1546
+ selection: true,
1547
+ creation: true,
1548
+ editing: true,
1549
+ deletion: true,
1550
+ deleteSelected: true,
1551
+ export: true,
1552
+ import: true,
1553
+ grouping: true,
1554
+ columnVisibility: true,
1555
+ columnReordering: true,
1556
+ autoColumnSizing: true,
1557
+ }}
1558
+ initialPageSize={25} // Start with 25 users per page
1559
+ isLoading={loading}
1560
+ onEditRow={(row, data) => {
1561
+ console.log('Editing user:', row.id, data);
1562
+ // Handle user edit
1563
+ }}
1564
+ onDeleteRow={(row) => {
1565
+ console.log('Deleting user:', row.id);
1566
+ // Handle user deletion
1567
+ }}
1568
+ onCreateRow={(data) => {
1569
+ console.log('Creating user:', data);
1570
+ // Handle user creation
1571
+ }}
1572
+ onImport={(data) => {
1573
+ console.log('Importing users:', data);
1574
+ // Handle user import
1575
+ }}
1576
+ onRowSelectionChange={(selection) => {
1577
+ console.log('Selection changed:', selection);
1578
+ // Handle selection changes
1579
+ }}
1580
+ onDeleteSelected={(selectedRows) => {
1581
+ console.log('Bulk deleting users:', selectedRows);
1582
+ // Handle bulk deletion
1583
+ }}
1584
+ />
1585
+ );
1586
+ }
1587
+ ```
1588
+
1589
+ ### Page Size Validation Example
1590
+
1591
+ ```tsx
1592
+ // This will show a console warning and use the closest valid option
1593
+ <DataTable
1594
+ data={largeDataset}
1595
+ columns={columns}
1596
+ features={{ pagination: true }}
1597
+ initialPageSize={15} // Invalid - will fallback to 10 with warning
1598
+ paginationMode="client" // Uses [10, 25, 50] options
1599
+ />
1600
+
1601
+ // This will work correctly
1602
+ <DataTable
1603
+ data={largeDataset}
1604
+ columns={columns}
1605
+ features={{ pagination: true }}
1606
+ initialPageSize={25} // Valid option
1607
+ paginationMode="client"
1608
+ />
1609
+ ```
1610
+
683
1611
  ## Best Practices
684
1612
 
1613
+ ### Data Processing Best Practices
1614
+ - **Stable Data References**: Ensure your data processing doesn't create new object references on every render
1615
+ - **Memoization**: Use `useMemo` with proper dependency arrays to prevent unnecessary re-computations
1616
+ - **Avoid Complex Transformations in useMemo**: Move complex data transformations to the backend or data fetching layer when possible
1617
+ - **Data Comparison**: Use shallow comparison to detect actual data changes before updating state
1618
+
1619
+ #### ✅ Good Data Processing Patterns
1620
+ ```tsx
1621
+ // Simple, stable data processing
1622
+ const processedData = useMemo(() => {
1623
+ if (!data || data.length === 0) return [];
1624
+ return data; // Direct usage, no transformations
1625
+ }, [data]);
1626
+
1627
+ // Complex processing with stable references
1628
+ const processedData = useMemo(() => {
1629
+ if (!data || data.length === 0) return [];
1630
+
1631
+ // Use stable references and avoid creating new objects unnecessarily
1632
+ return data.map(item => ({
1633
+ ...item,
1634
+ // Simple transformations only
1635
+ displayName: item.firstName + ' ' + item.lastName,
1636
+ }));
1637
+ }, [data]); // Single dependency
1638
+ ```
1639
+
1640
+ #### ❌ Avoid These Patterns
1641
+ ```tsx
1642
+ // This can cause infinite loops
1643
+ const processedData = useMemo(() => {
1644
+ return data.map(item => ({
1645
+ ...item,
1646
+ // Complex transformations that create new objects
1647
+ computed_field: relatedData?.find(rel => rel.id === item.relation_id)?.name || 'Unknown',
1648
+ formatted_date: item.date ? format(new Date(item.date), 'MMM dd, yyyy') : 'No date',
1649
+ }));
1650
+ }, [data, relatedData]); // Multiple dependencies with complex processing
1651
+ ```
1652
+
1653
+ #### 🔧 Recommended Solutions for Complex Data
1654
+ 1. **Backend Processing**: Move complex transformations to your API layer
1655
+ 2. **Supabase Relations**: Use database relations instead of client-side lookups
1656
+ 3. **Separate Hooks**: Create dedicated hooks for data processing
1657
+ 4. **Stable References**: Use `useCallback` and `useMemo` with proper dependencies
1658
+
685
1659
  ### 1. Use the Features Configuration Properly
686
1660
 
687
1661
  ```tsx
@@ -897,6 +1871,14 @@ const columns: DataTableColumn<User>[] = [
897
1871
  - Check that required event handlers are provided (e.g., `onEditRow` for editing)
898
1872
  - Verify that the feature configuration matches your use case
899
1873
 
1874
+ #### 7. Delete selected rows not working
1875
+ - **Check feature configuration**: Ensure `features={{ selection: true, deletion: true, deleteSelected: true }}`
1876
+ - **Provide onDeleteSelected callback**: Implement the callback to handle bulk deletion
1877
+ - **Verify getRowId function**: Ensure you provide a `getRowId` function that returns unique IDs
1878
+ - **Check button visibility**: The delete button only appears when all three features are enabled and rows are selected
1879
+ - **Debug selection state**: Add console logs to verify `onRowSelectionChange` is being called with correct data
1880
+ - **Fallback option**: If you don't provide `onDeleteSelected`, the table will fall back to calling `onDeleteRow` for each selected row
1881
+
900
1882
  ### Debug Mode
901
1883
 
902
1884
  Enable debug logging for DataTable issues: