@jmruthers/pace-core 0.5.76 → 0.5.78

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 (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -13,6 +13,7 @@ import {
13
13
  } from 'lucide-react';
14
14
  import { cn } from '../../../utils/cn';
15
15
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
16
+ import { getPaginationBinding, getPageSizeOptions } from '../utils/paginationUtils';
16
17
  import type { PaginationMode, ServerSideResponse, DataRecord } from '../types';
17
18
 
18
19
  interface PaginationControlsProps<TData extends DataRecord> {
@@ -39,30 +40,15 @@ export function PaginationControls<TData extends DataRecord>({
39
40
  totalCount
40
41
  }: PaginationControlsProps<TData>) {
41
42
 
42
- // Get pagination state based on mode
43
- const getPaginationState = () => {
44
- if (paginationMode === 'server' && serverData) {
45
- return {
46
- currentPageSize: serverData.pageSize,
47
- currentPageIndex: serverData.pageIndex,
48
- pageCount: serverData.pageCount,
49
- totalRows: serverData.totalCount,
50
- canPreviousPage: serverData.hasPreviousPage,
51
- canNextPage: serverData.hasNextPage,
52
- };
53
- }
54
-
55
- // Client or hybrid mode
56
- const state = table.getState().pagination;
57
- return {
58
- currentPageSize: state.pageSize,
59
- currentPageIndex: state.pageIndex,
60
- pageCount: table.getPageCount(),
61
- totalRows: totalCount ?? table.getRowCount(),
62
- canPreviousPage: table.getCanPreviousPage(),
63
- canNextPage: table.getCanNextPage(),
64
- };
65
- };
43
+ // Use unified pagination binding for consistent behavior across modes
44
+ const pagination = getPaginationBinding({
45
+ mode: paginationMode,
46
+ table,
47
+ serverData,
48
+ totalCount,
49
+ onPageChange,
50
+ onPageSizeChange,
51
+ });
66
52
 
67
53
  const {
68
54
  currentPageSize,
@@ -71,67 +57,20 @@ export function PaginationControls<TData extends DataRecord>({
71
57
  totalRows,
72
58
  canPreviousPage,
73
59
  canNextPage,
74
- } = getPaginationState();
75
-
76
- // Handle page size changes
77
- const handlePageSizeChange = (newPageSize: number) => {
78
- if (paginationMode === 'server') {
79
- onPageSizeChange?.(newPageSize);
80
- } else {
81
- table.setPageSize(newPageSize);
82
- }
83
- };
84
-
85
- // Handle page navigation
86
- const handleFirstPage = () => {
87
- if (paginationMode === 'server') {
88
- onPageChange?.(0);
89
- } else {
90
- table.setPageIndex(0);
91
- }
92
- };
93
-
94
- const handlePreviousPage = () => {
95
- if (paginationMode === 'server') {
96
- onPageChange?.(Math.max(0, currentPageIndex - 1));
97
- } else {
98
- table.previousPage();
99
- }
100
- };
101
-
102
- const handleNextPage = () => {
103
- if (paginationMode === 'server') {
104
- onPageChange?.(Math.min(pageCount - 1, currentPageIndex + 1));
105
- } else {
106
- table.nextPage();
107
- }
108
- };
60
+ startRow,
61
+ endRow,
62
+ } = pagination.state;
109
63
 
110
- const handleLastPage = () => {
111
- if (paginationMode === 'server') {
112
- onPageChange?.(pageCount - 1);
113
- } else {
114
- table.setPageIndex(pageCount - 1);
115
- }
116
- };
117
-
118
- // Calculate display range
119
- const startRow = currentPageIndex * currentPageSize + 1;
120
- const endRow = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
64
+ const {
65
+ goToFirstPage,
66
+ goToPreviousPage,
67
+ goToNextPage,
68
+ goToLastPage,
69
+ setPageSize,
70
+ } = pagination.actions;
121
71
 
122
72
  // Get mode-specific page size options
123
- const getPageSizeOptions = () => {
124
- switch (paginationMode) {
125
- case 'server':
126
- return pageSizeOptions.filter(size => size <= 250); // Limit server-side page sizes
127
- case 'hybrid':
128
- return pageSizeOptions.filter(size => size >= 50); // Hybrid mode prefers larger pages
129
- default:
130
- return pageSizeOptions;
131
- }
132
- };
133
-
134
- const availablePageSizes = getPageSizeOptions();
73
+ const availablePageSizes = getPageSizeOptions(paginationMode, pageSizeOptions);
135
74
 
136
75
  // Performance mode indicator
137
76
  const getModeIcon = () => {
@@ -168,7 +107,7 @@ export function PaginationControls<TData extends DataRecord>({
168
107
  <Select
169
108
  value={currentPageSize?.toString() || '10'}
170
109
  selectedText={currentPageSize?.toString() || '10'}
171
- onValueChange={(value) => handlePageSizeChange(Number(value))}
110
+ onValueChange={(value) => setPageSize(Number(value))}
172
111
  disabled={isLoading}
173
112
  className="w-36 h-8"
174
113
  >
@@ -182,7 +121,7 @@ export function PaginationControls<TData extends DataRecord>({
182
121
  <SelectValue />
183
122
  </SelectTrigger>
184
123
  <SelectContent>
185
- {pageSizeOptions.map((pageSize) => (
124
+ {availablePageSizes.map((pageSize) => (
186
125
  <SelectItem key={pageSize} value={pageSize?.toString() || '10'}>
187
126
  {pageSize}
188
127
  </SelectItem>
@@ -217,7 +156,7 @@ export function PaginationControls<TData extends DataRecord>({
217
156
  variant="outline"
218
157
  size="sm"
219
158
  className="h-8 w-8 p-0"
220
- onClick={handleFirstPage}
159
+ onClick={goToFirstPage}
221
160
  disabled={!canPreviousPage || isLoading}
222
161
  aria-label="Go to first page"
223
162
  tabIndex={0}
@@ -229,7 +168,7 @@ export function PaginationControls<TData extends DataRecord>({
229
168
  variant="outline"
230
169
  size="sm"
231
170
  className="h-8 w-8 p-0"
232
- onClick={handlePreviousPage}
171
+ onClick={goToPreviousPage}
233
172
  disabled={!canPreviousPage || isLoading}
234
173
  aria-label="Go to previous page"
235
174
  tabIndex={0}
@@ -241,7 +180,7 @@ export function PaginationControls<TData extends DataRecord>({
241
180
  variant="outline"
242
181
  size="sm"
243
182
  className="h-8 w-8 p-0"
244
- onClick={handleNextPage}
183
+ onClick={goToNextPage}
245
184
  disabled={!canNextPage || isLoading}
246
185
  aria-label="Go to next page"
247
186
  tabIndex={0}
@@ -253,7 +192,7 @@ export function PaginationControls<TData extends DataRecord>({
253
192
  variant="outline"
254
193
  size="sm"
255
194
  className="h-8 w-8 p-0"
256
- onClick={handleLastPage}
195
+ onClick={goToLastPage}
257
196
  disabled={!canNextPage || isLoading}
258
197
  aria-label="Go to last page"
259
198
  tabIndex={0}
@@ -279,25 +218,26 @@ export function EnhancedPaginationControls<TData extends DataRecord>({
279
218
  }: EnhancedPaginationControlsProps<TData>) {
280
219
  const [jumpToPage, setJumpToPage] = React.useState('');
281
220
 
282
- const { table, paginationMode = 'client', serverData, onPageChange } = props;
221
+ const { table, paginationMode = 'client', serverData, onPageChange, totalCount } = props;
283
222
 
284
- const { pageCount } = (() => {
285
- if (paginationMode === 'server' && serverData) {
286
- return { pageCount: serverData.pageCount };
287
- }
288
- return { pageCount: table.getPageCount() };
289
- })();
223
+ // Use unified pagination binding for consistent behavior
224
+ const pagination = getPaginationBinding({
225
+ mode: paginationMode,
226
+ table,
227
+ serverData,
228
+ totalCount,
229
+ onPageChange,
230
+ onPageSizeChange: props.onPageSizeChange,
231
+ });
232
+
233
+ const { pageCount } = pagination.state;
290
234
 
291
235
  const handleJumpToPage = (e: React.FormEvent) => {
292
236
  e.preventDefault();
293
237
  const pageNumber = parseInt(jumpToPage, 10);
294
238
  if (pageNumber >= 1 && pageNumber <= pageCount) {
295
239
  const pageIndex = pageNumber - 1;
296
- if (paginationMode === 'server') {
297
- onPageChange?.(pageIndex);
298
- } else {
299
- table.setPageIndex(pageIndex);
300
- }
240
+ pagination.actions.goToPage(pageIndex);
301
241
  setJumpToPage('');
302
242
  }
303
243
  };
@@ -22,7 +22,16 @@ import { EditableRow } from './EditableRow';
22
22
  import { getTableCellClasses, getTableHeadClasses, getTableRowClasses } from '../styles';
23
23
  import { Input } from '../../Input/Input';
24
24
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
25
- import type { AggregateConfig, HierarchicalConfig, HierarchicalDataRow } from '../types';
25
+ import type {
26
+ AggregateConfig,
27
+ DataRecord,
28
+ DataTableAction,
29
+ EditableColumnDef,
30
+ EmptyStateConfig,
31
+ HierarchicalConfig,
32
+ HierarchicalDataRow,
33
+ CellValue
34
+ } from '../types';
26
35
  import { calculateIndentation } from '../utils/hierarchicalUtils';
27
36
  import { getRowIdSafe } from '../utils/rowUtils';
28
37
 
@@ -34,15 +43,15 @@ const MEMORY_OPTIMIZATION_THRESHOLD = 100000;
34
43
  /**
35
44
  * Props for the unified table body component
36
45
  */
37
- interface UnifiedTableBodyProps<TData extends Record<string, any>> {
46
+ interface UnifiedTableBodyProps<TData extends DataRecord> {
38
47
  /** TanStack table instance */
39
48
  table: Table<TData>;
40
49
  /** Whether a new row is being created */
41
50
  isCreating: boolean;
42
51
  /** Data for the row being created */
43
- creationData: Record<string, any>;
52
+ creationData: Record<string, CellValue>;
44
53
  /** Callback when creation data changes */
45
- onCreationDataChange: (data: Record<string, any>) => void;
54
+ onCreationDataChange: (data: Record<string, CellValue>) => void;
46
55
  /** Callback to save the new row */
47
56
  onSaveCreation: () => void;
48
57
  /** Callback to cancel row creation */
@@ -50,9 +59,9 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
50
59
  /** ID of the row currently being edited */
51
60
  editingRowId: string | null;
52
61
  /** Data for the row being edited */
53
- editingData: Record<string, any>;
62
+ editingData: Record<string, CellValue>;
54
63
  /** Callback when editing data changes */
55
- onEditingDataChange: (data: Record<string, any>) => void;
64
+ onEditingDataChange: (data: Record<string, CellValue>) => void;
56
65
  /** Callback to save the edited row */
57
66
  onSaveEditing?: () => void;
58
67
  /** Callback to cancel row editing */
@@ -64,15 +73,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
64
73
  /** Function to get unique row ID */
65
74
  getRowId?: (row: TData, index: number) => string;
66
75
  /** Custom empty state configuration */
67
- emptyState?: {
68
- title?: string;
69
- description?: string;
70
- icon?: React.ComponentType<{ className?: string }>;
71
- action?: {
72
- label: string;
73
- onClick: () => void;
74
- };
75
- };
76
+ emptyState?: EmptyStateConfig;
76
77
  /** Whether the table is currently filtered */
77
78
  isFiltered?: boolean;
78
79
  /** Callback to clear all filters */
@@ -103,25 +104,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
103
104
  hasAnyChildren?: boolean;
104
105
  };
105
106
  /** Actions for action buttons */
106
- actions?: Array<{
107
- label: string;
108
- onClick: (row: any) => void;
109
- icon?: any;
110
- variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';
111
- disabled?: boolean | ((row?: any) => boolean);
112
- visible?: boolean | ((row?: any) => boolean);
113
- testId?: string;
114
- showInEditMode?: boolean;
115
- hideInViewMode?: boolean;
116
- showInViewMode?: boolean;
117
- hidden?: boolean;
118
- showForParent?: boolean;
119
- showForChild?: boolean;
120
- parentIcon?: any;
121
- childIcon?: any;
122
- parentLabel?: string;
123
- childLabel?: string;
124
- }>;
107
+ actions?: DataTableAction<TData>[];
125
108
  // MANDATORY RBAC
126
109
  rbac?: {
127
110
  pageId?: string;
@@ -138,38 +121,37 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
138
121
  }
139
122
 
140
123
  // Helper function to render the appropriate input type based on column configuration
141
- const renderEditField = <TData extends Record<string, any>>(
124
+ const renderEditField = <TData extends DataRecord>(
142
125
  column: Column<TData, unknown>,
143
- value: unknown,
144
- onChange: (value: unknown) => void,
145
- editingData: Record<string, unknown> = {},
126
+ value: CellValue,
127
+ onChange: (value: CellValue | Record<string, CellValue>) => void,
128
+ editingData: Record<string, CellValue> = {},
146
129
  placeholder?: string
147
130
  ) => {
148
- // Cast to DataTableColumn to access extended properties
149
- const columnDef = column.columnDef as any;
150
-
131
+ const columnDef = column.columnDef as EditableColumnDef<TData>;
132
+
151
133
  // Check if column is editable (default: true)
152
134
  if (columnDef.editable === false) {
153
135
  // Return the original value as text if column is not editable
154
- return <span className="text-sm text-gray-600">{String(value || '')}</span>;
136
+ return <span className="text-sm text-gray-600">{String(value ?? '')}</span>;
155
137
  }
156
-
138
+
157
139
  // Check for custom field type
158
140
  if (columnDef.fieldType === 'select' && columnDef.fieldOptions) {
159
141
  // Use editAccessorKey if specified, otherwise use the column id
160
142
  const accessorKey = columnDef.editAccessorKey || column.id;
161
- const currentValue = editingData[accessorKey] || value || '';
162
-
143
+ const currentValue = editingData[accessorKey] ?? value ?? '';
144
+
163
145
  return (
164
146
  <Select
165
147
  value={String(currentValue)}
166
- onValueChange={(newValue) => onChange({ [accessorKey]: newValue })}
148
+ onValueChange={(newValue) => onChange({ [accessorKey]: newValue as CellValue })}
167
149
  >
168
150
  <SelectTrigger className="h-8">
169
151
  <SelectValue placeholder={placeholder || `Select ${columnDef.header || column.id}...`} />
170
152
  </SelectTrigger>
171
153
  <SelectContent>
172
- {columnDef.fieldOptions.map((option: any) => (
154
+ {columnDef.fieldOptions.map(option => (
173
155
  <SelectItem key={option.value} value={String(option.value)}>
174
156
  {option.label}
175
157
  </SelectItem>
@@ -184,32 +166,32 @@ const renderEditField = <TData extends Record<string, any>>(
184
166
  return (
185
167
  <Input
186
168
  type="number"
187
- value={String(value || '')}
188
- onChange={(e) => onChange(e.target.value)}
169
+ value={String(value ?? '')}
170
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
189
171
  placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
190
172
  className="h-8"
191
173
  />
192
174
  );
193
175
  }
194
-
176
+
195
177
  // Check for date type
196
178
  if (columnDef.fieldType === 'date') {
197
179
  return (
198
180
  <Input
199
181
  type="date"
200
- value={String(value || '')}
201
- onChange={(e) => onChange(e.target.value)}
182
+ value={String(value ?? '')}
183
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
202
184
  className="h-8"
203
185
  />
204
186
  );
205
187
  }
206
-
188
+
207
189
  // Default to text input
208
190
  return (
209
191
  <Input
210
192
  type="text"
211
- value={String(value || '')}
212
- onChange={(e) => onChange(e.target.value)}
193
+ value={String(value ?? '')}
194
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
213
195
  placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
214
196
  className="h-8"
215
197
  />
@@ -378,52 +360,12 @@ const RowComponent = React.memo(({
378
360
  key={cell.id}
379
361
  className={getTableCellClasses({
380
362
  isCompact: true,
381
- className: "px-3 py-2 pl-8 whitespace-normal break-words"
363
+ className: `px-3 py-2 pl-8 ${cell.column.id === 'actions' ? 'whitespace-nowrap' : 'whitespace-normal break-words'} ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`
382
364
  })}
383
365
  >
384
- <div className={`${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
385
- {isSubRowEditing && cell.column.id !== 'actions' ? (
386
- // Check if column has a custom cell renderer - if so, use it in edit mode
387
- cell.column.columnDef.cell ? (
388
- flexRender(cell.column.columnDef.cell, {
389
- ...cell.getContext(),
390
- hierarchical: hierarchical,
391
- isParent: false,
392
- isChild: true,
393
- isHierarchical: false,
394
- rowId: subRowId,
395
- isExpanded: false,
396
- hasChildren: false,
397
- getIsEditing: () => true, // Always true in edit mode
398
- setValue: (value: any) => {
399
- if (typeof value === 'object' && value !== null) {
400
- onEditingDataChange?.({ ...editingData, ...value });
401
- } else {
402
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
403
- }
404
- }
405
- })
406
- ) : (
407
- // Fall back to default edit field rendering when no custom cell renderer
408
- renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
409
- if (typeof value === 'object' && value !== null) {
410
- onEditingDataChange?.({ ...editingData, ...value });
411
- } else {
412
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
413
- }
414
- }, editingData)
415
- )
416
- ) : cell.column.id === 'actions' ? (
417
- <ActionButtons
418
- row={row}
419
- actions={actions}
420
- isEditing={isEditing}
421
- isParent={isParent}
422
- hierarchical={!!hierarchical}
423
- rbac={rbac}
424
- permissions={permissions}
425
- />
426
- ) : (
366
+ {isSubRowEditing && cell.column.id !== 'actions' ? (
367
+ // Check if column has a custom cell renderer - if so, use it in edit mode
368
+ cell.column.columnDef.cell ? (
427
369
  flexRender(cell.column.columnDef.cell, {
428
370
  ...cell.getContext(),
429
371
  hierarchical: hierarchical,
@@ -432,10 +374,48 @@ const RowComponent = React.memo(({
432
374
  isHierarchical: false,
433
375
  rowId: subRowId,
434
376
  isExpanded: false,
435
- hasChildren: false
377
+ hasChildren: false,
378
+ getIsEditing: () => true, // Always true in edit mode
379
+ setValue: (value: any) => {
380
+ if (typeof value === 'object' && value !== null) {
381
+ onEditingDataChange?.({ ...editingData, ...value });
382
+ } else {
383
+ onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
384
+ }
385
+ }
436
386
  })
437
- )}
438
- </div>
387
+ ) : (
388
+ // Fall back to default edit field rendering when no custom cell renderer
389
+ renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
390
+ if (typeof value === 'object' && value !== null) {
391
+ onEditingDataChange?.({ ...editingData, ...value });
392
+ } else {
393
+ onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
394
+ }
395
+ }, editingData)
396
+ )
397
+ ) : cell.column.id === 'actions' ? (
398
+ <ActionButtons
399
+ row={row}
400
+ actions={actions}
401
+ isEditing={isEditing}
402
+ isParent={isParent}
403
+ hierarchical={!!hierarchical}
404
+ rbac={rbac}
405
+ permissions={permissions}
406
+ />
407
+ ) : (
408
+ flexRender(cell.column.columnDef.cell, {
409
+ ...cell.getContext(),
410
+ hierarchical: hierarchical,
411
+ isParent: false,
412
+ isChild: true,
413
+ isHierarchical: false,
414
+ rowId: subRowId,
415
+ isExpanded: false,
416
+ hasChildren: false
417
+ })
418
+ )}
439
419
  </td>
440
420
  ))}
441
421
  </tr>
@@ -459,7 +439,7 @@ const RowComponent = React.memo(({
459
439
  onEditingDataChange={onEditingDataChange}
460
440
  onSave={onSaveEditing}
461
441
  onCancel={onCancelEditing}
462
- actions={((actions || []) as any[]).filter((a: any) => !a.disabled) as any}
442
+ actions={actions ?? []}
463
443
  getRowId={getRowId}
464
444
  isParent={isParent}
465
445
  hierarchical={!!hierarchical}
@@ -487,11 +467,13 @@ const RowComponent = React.memo(({
487
467
  <tr
488
468
  ref={rowRef}
489
469
  key={row.id}
470
+ role="row"
490
471
  style={{
491
472
  ...style,
492
473
  ...(isChild && indentation > 0 ? { paddingLeft: `${indentation}px` } : {})
493
474
  }}
494
475
  className={rowClassName}
476
+ aria-selected={typeof row.getIsSelected === 'function' ? (row.getIsSelected() ? 'true' : 'false') : 'false'}
495
477
  >
496
478
  {visibleCells.map((cell: any, cellIndex: number) => {
497
479
  const isFirstCell = cellIndex === 0;
@@ -504,52 +486,47 @@ const RowComponent = React.memo(({
504
486
  key={cell.id}
505
487
  className={getTableCellClasses({
506
488
  isCompact: true,
507
- className: "px-3 py-2 whitespace-normal break-words"
489
+ className: `px-3 py-2 ${cell.column.id === 'actions' ? 'whitespace-nowrap' : 'whitespace-normal break-words'} ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`
508
490
  })}
509
491
  >
510
- <div className="flex items-center gap-2">
511
- {shouldShowExpansionButton && hasChildren && (
512
- <Button
513
- variant="ghost"
514
- size="sm"
515
- onClick={() => hierarchical?.state?.toggleRow(rowId)}
516
- className="h-6 w-6 p-0 flex-shrink-0"
517
- aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
518
- title={isExpanded ? 'Collapse row' : 'Expand row'}
519
- >
520
- {isExpanded ? (
521
- <ChevronDown className="h-4 w-4" />
522
- ) : (
523
- <ChevronRight className="h-4 w-4" />
524
- )}
525
- </Button>
526
- )}
527
-
528
- <div className={`flex-1 ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
529
- {cell.column.id === 'actions' ? (
530
- <ActionButtons
531
- row={row}
532
- actions={actions}
533
- isEditing={isEditing}
534
- isParent={isParent}
535
- hierarchical={!!hierarchical}
536
- rbac={rbac}
537
- permissions={permissions}
538
- />
492
+ {shouldShowExpansionButton && hasChildren && (
493
+ <Button
494
+ variant="ghost"
495
+ size="sm"
496
+ onClick={() => hierarchical?.state?.toggleRow(rowId)}
497
+ className="h-6 w-6 p-0 flex-shrink-0"
498
+ aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
499
+ title={isExpanded ? 'Collapse row' : 'Expand row'}
500
+ >
501
+ {isExpanded ? (
502
+ <ChevronDown className="h-4 w-4" />
539
503
  ) : (
540
- flexRender(cell.column.columnDef.cell, {
541
- ...cell.getContext(),
542
- hierarchical: hierarchical,
543
- isParent: isParent,
544
- isChild: isChild,
545
- isHierarchical: isHierarchical,
546
- rowId: rowId,
547
- isExpanded: isExpanded,
548
- hasChildren: hasChildren,
549
- })
504
+ <ChevronRight className="h-4 w-4" />
550
505
  )}
551
- </div>
552
- </div>
506
+ </Button>
507
+ )}
508
+ {cell.column.id === 'actions' ? (
509
+ <ActionButtons
510
+ row={row}
511
+ actions={actions}
512
+ isEditing={isEditing}
513
+ isParent={isParent}
514
+ hierarchical={!!hierarchical}
515
+ rbac={rbac}
516
+ permissions={permissions}
517
+ />
518
+ ) : (
519
+ flexRender(cell.column.columnDef.cell, {
520
+ ...cell.getContext(),
521
+ hierarchical: hierarchical,
522
+ isParent: isParent,
523
+ isChild: isChild,
524
+ isHierarchical: isHierarchical,
525
+ rowId: rowId,
526
+ isExpanded: isExpanded,
527
+ hasChildren: hasChildren,
528
+ })
529
+ )}
553
530
  </td>
554
531
  );
555
532
  })}
@@ -728,10 +705,10 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
728
705
  })}
729
706
  >
730
707
  {renderEditField(header.column, creationData[header.column.id], (value) => {
731
- if (typeof value === 'object' && value !== null) {
732
- onCreationDataChange({ ...creationData, ...value });
708
+ if (typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
709
+ onCreationDataChange({ ...creationData, ...(value as Record<string, CellValue>) });
733
710
  } else {
734
- onCreationDataChange({ ...creationData, [header.column.id]: value });
711
+ onCreationDataChange({ ...creationData, [header.column.id]: value as CellValue });
735
712
  }
736
713
  }, creationData)}
737
714
  </td>
@@ -31,7 +31,7 @@ export interface DataTableContextValue<TData extends DataRecord> {
31
31
  // CONTEXT CREATION
32
32
  // ============================================================================
33
33
 
34
- const DataTableContext = createContext<DataTableContextValue<any> | null>(null);
34
+ const DataTableContext = createContext<DataTableContextValue<DataRecord> | null>(null);
35
35
 
36
36
  // ============================================================================
37
37
  // PROVIDER COMPONENT
@@ -45,6 +45,10 @@ export interface ActionColumnOptions {
45
45
  size?: number;
46
46
  minSize?: number;
47
47
  maxSize?: number;
48
+ meta?: {
49
+ align?: 'left' | 'right' | 'center';
50
+ [key: string]: any;
51
+ };
48
52
  }
49
53
 
50
54
  export interface CustomColumnOptions<TData extends DataRecord> {
@@ -220,6 +224,7 @@ export class ColumnFactory<TData extends DataRecord = DataRecord> {
220
224
  size: options.size || 150,
221
225
  minSize: options.minSize || 100,
222
226
  maxSize: options.maxSize || 200,
227
+ meta: options.meta,
223
228
  } as ColumnDef<TData>;
224
229
  }
225
230