@jmruthers/pace-core 0.5.75 → 0.5.77

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 (507) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-SBHZQtCH.d.ts} +5 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/DataTable-QCNCV6IK.js +157 -0
  5. package/dist/{PublicLoadingSpinner-BKNBT6b6.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +33 -19
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-Z2FWNW7O.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-2DFZ432F.js → chunk-7PX43UYN.js} +197 -629
  11. package/dist/chunk-7PX43UYN.js.map +1 -0
  12. package/dist/{chunk-DAXLNIDY.js → chunk-C4RQ3GQA.js} +108 -32
  13. package/dist/chunk-C4RQ3GQA.js.map +1 -0
  14. package/dist/{chunk-LW7MMEAQ.js → chunk-CRKP3HXI.js} +2 -2
  15. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  16. package/dist/chunk-CVMVPYAL.js.map +1 -0
  17. package/dist/{chunk-CY3AHGO4.js → chunk-DDPG7FCX.js} +3395 -3254
  18. package/dist/chunk-DDPG7FCX.js.map +1 -0
  19. package/dist/{chunk-URUTVZ7N.js → chunk-DVHZ5L55.js} +2 -2
  20. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  21. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  22. package/dist/{chunk-WN6XJWOS.js → chunk-JDQ7T3QB.js} +256 -743
  23. package/dist/chunk-JDQ7T3QB.js.map +1 -0
  24. package/dist/{chunk-ZTT2AXMX.js → chunk-LMYTEMUH.js} +153 -132
  25. package/dist/chunk-LMYTEMUH.js.map +1 -0
  26. package/dist/{chunk-33PHABLB.js → chunk-NKT2DLZI.js} +13 -130
  27. package/dist/chunk-NKT2DLZI.js.map +1 -0
  28. package/dist/chunk-PUKTJMRT.js +732 -0
  29. package/dist/chunk-PUKTJMRT.js.map +1 -0
  30. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  31. package/dist/chunk-Q7APDV6H.js.map +1 -0
  32. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  33. package/dist/chunk-S63MFSY6.js.map +1 -0
  34. package/dist/{chunk-NTNILOBC.js → chunk-TLD5BEU6.js} +4 -4
  35. package/dist/chunk-WUXCWRL6.js +20 -0
  36. package/dist/chunk-WUXCWRL6.js.map +1 -0
  37. package/dist/{chunk-YNUBMSMV.js → chunk-YCKPEMJA.js} +186 -263
  38. package/dist/chunk-YCKPEMJA.js.map +1 -0
  39. package/dist/{chunk-A4FUBC7B.js → chunk-Z3T6RK3K.js} +2 -4
  40. package/dist/{chunk-A4FUBC7B.js.map → chunk-Z3T6RK3K.js.map} +1 -1
  41. package/dist/components.d.ts +6 -6
  42. package/dist/components.js +17 -20
  43. package/dist/components.js.map +1 -1
  44. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  45. package/dist/hooks.d.ts +21 -44
  46. package/dist/hooks.js +12 -13
  47. package/dist/hooks.js.map +1 -1
  48. package/dist/index.d.ts +19 -27
  49. package/dist/index.js +27 -33
  50. package/dist/index.js.map +1 -1
  51. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  52. package/dist/providers.d.ts +7 -21
  53. package/dist/providers.js +3 -10
  54. package/dist/rbac/index.d.ts +118 -215
  55. package/dist/rbac/index.js +18 -18
  56. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  57. package/dist/types.d.ts +3 -3
  58. package/dist/types.js +61 -18
  59. package/dist/types.js.map +1 -1
  60. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  61. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  62. package/dist/utils.d.ts +2 -2
  63. package/dist/utils.js +52 -9
  64. package/dist/utils.js.map +1 -1
  65. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  66. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  67. package/docs/README.md +142 -147
  68. package/docs/STYLE_GUIDE.md +37 -0
  69. package/docs/api/classes/ColumnFactory.md +17 -17
  70. package/docs/api/classes/ErrorBoundary.md +1 -1
  71. package/docs/api/classes/InvalidScopeError.md +4 -4
  72. package/docs/api/classes/MissingUserContextError.md +4 -4
  73. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  74. package/docs/api/classes/PermissionDeniedError.md +5 -5
  75. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  76. package/docs/api/classes/RBACAuditManager.md +8 -8
  77. package/docs/api/classes/RBACCache.md +35 -5
  78. package/docs/api/classes/RBACEngine.md +49 -20
  79. package/docs/api/classes/RBACError.md +4 -4
  80. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  81. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  82. package/docs/api/classes/StorageUtils.md +1 -1
  83. package/docs/api/enums/FileCategory.md +1 -1
  84. package/docs/api/interfaces/AggregateConfig.md +4 -4
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CardProps.md +1 -1
  87. package/docs/api/interfaces/ColorPalette.md +1 -1
  88. package/docs/api/interfaces/ColorShade.md +1 -1
  89. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  90. package/docs/api/interfaces/DataRecord.md +11 -0
  91. package/docs/api/interfaces/DataTableAction.md +65 -29
  92. package/docs/api/interfaces/DataTableColumn.md +36 -23
  93. package/docs/api/interfaces/DataTableProps.md +80 -38
  94. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  95. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  96. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  97. package/docs/api/interfaces/EventLogoProps.md +1 -1
  98. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  99. package/docs/api/interfaces/FileMetadata.md +1 -1
  100. package/docs/api/interfaces/FileReference.md +1 -1
  101. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  102. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  103. package/docs/api/interfaces/FileUploadProps.md +1 -1
  104. package/docs/api/interfaces/FooterProps.md +1 -1
  105. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  106. package/docs/api/interfaces/InputProps.md +1 -1
  107. package/docs/api/interfaces/LabelProps.md +1 -1
  108. package/docs/api/interfaces/LoginFormProps.md +1 -1
  109. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  110. package/docs/api/interfaces/NavigationContextType.md +9 -9
  111. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  112. package/docs/api/interfaces/NavigationItem.md +1 -1
  113. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  114. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  115. package/docs/api/interfaces/Organisation.md +1 -1
  116. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  117. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  118. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  119. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  120. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  121. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  122. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  123. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  124. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  125. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  126. package/docs/api/interfaces/PaletteData.md +1 -1
  127. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  128. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  129. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  130. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  131. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  132. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  133. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  134. package/docs/api/interfaces/RBACConfig.md +1 -1
  135. package/docs/api/interfaces/RBACLogger.md +1 -1
  136. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  137. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  138. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  139. package/docs/api/interfaces/RouteConfig.md +2 -2
  140. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  141. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  142. package/docs/api/interfaces/StorageConfig.md +1 -1
  143. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  144. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  145. package/docs/api/interfaces/StorageListOptions.md +1 -1
  146. package/docs/api/interfaces/StorageListResult.md +1 -1
  147. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  148. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  149. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  150. package/docs/api/interfaces/StyleImport.md +1 -1
  151. package/docs/api/interfaces/SwitchProps.md +1 -1
  152. package/docs/api/interfaces/ToastActionElement.md +1 -1
  153. package/docs/api/interfaces/ToastProps.md +1 -1
  154. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  155. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  156. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  157. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  159. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  160. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  161. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  162. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  163. package/docs/api/interfaces/UseResolvedScopeOptions.md +47 -0
  164. package/docs/api/interfaces/UseResolvedScopeReturn.md +47 -0
  165. package/docs/api/interfaces/UserEventAccess.md +11 -11
  166. package/docs/api/interfaces/UserMenuProps.md +1 -1
  167. package/docs/api/interfaces/UserProfile.md +1 -1
  168. package/docs/api/modules.md +303 -275
  169. package/docs/api-reference/components.md +193 -0
  170. package/docs/api-reference/hooks.md +265 -0
  171. package/docs/api-reference/providers.md +32 -7
  172. package/docs/api-reference/types.md +6 -0
  173. package/docs/api-reference/utilities.md +207 -0
  174. package/docs/architecture/README.md +6 -0
  175. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  176. package/docs/architecture/rbac-security-architecture.md +258 -0
  177. package/docs/architecture/services.md +9 -1
  178. package/docs/best-practices/README.md +26 -0
  179. package/docs/best-practices/accessibility.md +572 -0
  180. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  181. package/docs/best-practices/deployment.md +6 -0
  182. package/docs/best-practices/performance.md +475 -2
  183. package/docs/best-practices/security.md +6 -0
  184. package/docs/best-practices/testing.md +6 -0
  185. package/docs/core-concepts/authentication.md +21 -7
  186. package/docs/core-concepts/events.md +6 -0
  187. package/docs/core-concepts/organisations.md +6 -0
  188. package/docs/core-concepts/permissions.md +6 -0
  189. package/docs/core-concepts/rbac-system.md +6 -0
  190. package/docs/documentation-index.md +121 -182
  191. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  192. package/docs/getting-started/documentation-index.md +40 -0
  193. package/docs/getting-started/examples/README.md +878 -35
  194. package/docs/{faq.md → getting-started/faq.md} +7 -1
  195. package/docs/getting-started/installation-guide.md +6 -0
  196. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  197. package/docs/implementation-guides/app-layout.md +6 -0
  198. package/docs/implementation-guides/authentication.md +1021 -0
  199. package/docs/implementation-guides/component-styling.md +416 -0
  200. package/docs/implementation-guides/data-tables.md +1264 -2076
  201. package/docs/implementation-guides/dynamic-colors.md +6 -0
  202. package/docs/implementation-guides/event-theming-summary.md +6 -0
  203. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  204. package/docs/implementation-guides/file-upload-storage.md +6 -0
  205. package/docs/implementation-guides/forms.md +6 -0
  206. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  207. package/docs/implementation-guides/navigation.md +6 -0
  208. package/docs/implementation-guides/organisation-security.md +6 -0
  209. package/docs/implementation-guides/permission-enforcement.md +6 -0
  210. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  211. package/docs/implementation-guides/public-pages.md +6 -0
  212. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  213. package/docs/migration/README.md +7 -1
  214. package/docs/migration/organisation-context-timing-fix.md +6 -0
  215. package/docs/migration/rbac-migration.md +44 -1
  216. package/docs/migration/service-architecture.md +6 -0
  217. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  218. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  219. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  220. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  221. package/docs/rbac/README.md +6 -0
  222. package/docs/rbac/advanced-patterns.md +6 -0
  223. package/docs/rbac/api-reference.md +7 -1
  224. package/docs/rbac/breaking-changes-v3.md +222 -0
  225. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  226. package/docs/rbac/examples.md +6 -0
  227. package/docs/rbac/getting-started.md +6 -0
  228. package/docs/rbac/migration-guide.md +260 -0
  229. package/docs/rbac/quick-start.md +6 -0
  230. package/docs/rbac/rbac-rls-integration.md +6 -0
  231. package/docs/rbac/super-admin-guide.md +6 -0
  232. package/docs/rbac/troubleshooting.md +6 -0
  233. package/docs/security/README.md +6 -0
  234. package/docs/security/checklist.md +6 -0
  235. package/docs/styles/README.md +7 -1
  236. package/docs/{usage.md → styles/usage.md} +6 -0
  237. package/docs/testing/README.md +6 -0
  238. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  239. package/docs/troubleshooting/README.md +387 -5
  240. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  241. package/docs/troubleshooting/common-issues.md +6 -0
  242. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  243. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  244. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  245. package/docs/troubleshooting/styling-issues.md +6 -0
  246. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  247. package/package.json +1 -1
  248. package/src/__tests__/TEST_GUIDE_CURSOR.md +290 -0
  249. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  250. package/src/__tests__/helpers/supabaseMock.ts +48 -2
  251. package/src/__tests__/helpers/test-providers.tsx +3 -53
  252. package/src/components/DataTable/DataTable.test.tsx +319 -0
  253. package/src/components/DataTable/DataTable.tsx +32 -11
  254. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  255. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +17 -6
  256. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  257. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +96 -10
  258. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  259. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  260. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  261. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  262. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  263. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  264. package/src/components/DataTable/components/DataTableCore.tsx +442 -665
  265. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  266. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  267. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  268. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  269. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  270. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  271. package/src/components/DataTable/components/UnifiedTableBody.tsx +222 -278
  272. package/src/components/DataTable/components/index.ts +1 -2
  273. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  274. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +208 -275
  275. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  276. package/src/components/DataTable/core/index.ts +1 -8
  277. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  278. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  279. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  280. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  281. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +521 -0
  282. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +570 -0
  283. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  284. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +214 -0
  285. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +224 -0
  286. package/src/components/DataTable/hooks/index.ts +13 -0
  287. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  288. package/src/components/DataTable/hooks/useColumnReordering.ts +1 -0
  289. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  290. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  291. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  292. package/src/components/DataTable/hooks/useDataTablePermissions.ts +193 -0
  293. package/src/components/DataTable/hooks/useDataTableState.ts +51 -17
  294. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  295. package/src/components/DataTable/hooks/useHierarchicalState.ts +41 -9
  296. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  297. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  298. package/src/components/DataTable/hooks/useTableColumns.ts +156 -0
  299. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  300. package/src/components/DataTable/index.ts +13 -12
  301. package/src/components/DataTable/types.ts +129 -9
  302. package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +89 -0
  303. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +162 -28
  304. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +573 -0
  305. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +247 -0
  306. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +8 -6
  307. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +466 -0
  308. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +251 -0
  309. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  310. package/src/components/DataTable/utils/debugTools.ts +47 -21
  311. package/src/components/DataTable/utils/errorHandling.ts +52 -460
  312. package/src/components/DataTable/utils/exportUtils.ts +157 -28
  313. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  314. package/src/components/DataTable/utils/hierarchicalSorting.ts +50 -3
  315. package/src/components/DataTable/utils/hierarchicalUtils.ts +167 -34
  316. package/src/components/DataTable/utils/index.ts +7 -0
  317. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  318. package/src/components/DataTable/utils/rowUtils.ts +69 -0
  319. package/src/components/EventSelector/EventSelector.test.tsx +672 -0
  320. package/src/components/Label/__tests__/Label.test.tsx +434 -0
  321. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  322. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  323. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  324. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  325. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  326. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +190 -0
  327. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +185 -0
  328. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  329. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +313 -0
  330. package/src/components/Select/Select.test.tsx +143 -120
  331. package/src/components/Select/Select.tsx +48 -212
  332. package/src/components/Select/hooks.ts +36 -1
  333. package/src/components/Select/index.ts +2 -1
  334. package/src/components/examples/PermissionExample.tsx +173 -0
  335. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  336. package/src/examples/PublicEventPage.tsx +274 -0
  337. package/src/examples/PublicPageApp.tsx +308 -0
  338. package/src/examples/PublicPageUsageExample.tsx +216 -0
  339. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  340. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  341. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  342. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  343. package/src/hooks/useOrganisationPermissions.ts +12 -6
  344. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  345. package/src/hooks/useOrganisationSecurity.ts +41 -10
  346. package/src/hooks/useSecureDataAccess.test.ts +32 -29
  347. package/src/index.ts +0 -1
  348. package/src/providers/AuthProvider.simplified.tsx +880 -0
  349. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  350. package/src/providers/__tests__/ProviderLifecycle.test.tsx +341 -0
  351. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  352. package/src/providers/index.ts +0 -1
  353. package/src/providers/services/EventServiceProvider.tsx +19 -15
  354. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  355. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  356. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  357. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  358. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  359. package/src/rbac/README.md +1 -1
  360. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  361. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  362. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  363. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  364. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  365. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  366. package/src/rbac/adapters.tsx +26 -69
  367. package/src/rbac/api.test.ts +90 -27
  368. package/src/rbac/api.ts +61 -10
  369. package/src/rbac/audit.test.ts +33 -38
  370. package/src/rbac/audit.ts +21 -6
  371. package/src/rbac/cache.ts +33 -1
  372. package/src/rbac/components/NavigationGuard.tsx +11 -11
  373. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  374. package/src/rbac/components/NavigationProvider.tsx +37 -13
  375. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  376. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  377. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  378. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  379. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  380. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  381. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  382. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  383. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  384. package/src/rbac/engine.test.simple.ts +19 -13
  385. package/src/rbac/engine.test.ts +1 -0
  386. package/src/rbac/engine.ts +330 -766
  387. package/src/rbac/errors.ts +156 -0
  388. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +437 -0
  389. package/src/rbac/hooks/index.ts +2 -0
  390. package/src/rbac/hooks/usePermissions.ts +32 -10
  391. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  392. package/src/rbac/hooks/useRBAC.ts +147 -193
  393. package/src/rbac/hooks/useResolvedScope.ts +244 -0
  394. package/src/rbac/index.ts +7 -4
  395. package/src/rbac/security.ts +109 -18
  396. package/src/rbac/types.ts +12 -1
  397. package/src/services/AuthService.ts +2 -15
  398. package/src/services/EventService.ts +26 -46
  399. package/src/services/OrganisationService.ts +51 -31
  400. package/src/services/__tests__/AuthService.test.ts +1 -1
  401. package/src/services/__tests__/EventService.test.ts +1 -1
  402. package/src/services/__tests__/InactivityService.lifecycle.test.ts +411 -0
  403. package/src/services/__tests__/OrganisationService.pagination.test.ts +375 -0
  404. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  405. package/src/styles/base.css +208 -0
  406. package/src/styles/semantic.css +24 -0
  407. package/src/types/__tests__/README.md +114 -0
  408. package/src/types/__tests__/validation.test.ts +731 -0
  409. package/src/types/database.generated.ts +7347 -0
  410. package/src/types/database.ts +20 -0
  411. package/src/utils/__tests__/file-reference.test.ts +383 -0
  412. package/src/utils/__tests__/performanceBenchmark.test.ts +175 -0
  413. package/src/utils/appNameResolver.test.ts +54 -0
  414. package/src/utils/logger.ts +179 -0
  415. package/src/utils/organisationContext.ts +11 -4
  416. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  417. package/src/validation/__tests__/csrf.unit.test.ts +63 -0
  418. package/src/validation/__tests__/passwordSchema.unit.test.ts +105 -0
  419. package/dist/DataTable-HWZQGASI.js +0 -102
  420. package/dist/appNameResolver-UURKN7NF.js +0 -22
  421. package/dist/audit-6TOCAMKO.js.map +0 -1
  422. package/dist/chunk-2CHATWBF.js +0 -523
  423. package/dist/chunk-2CHATWBF.js.map +0 -1
  424. package/dist/chunk-2DFZ432F.js.map +0 -1
  425. package/dist/chunk-33PHABLB.js.map +0 -1
  426. package/dist/chunk-B2WTCLCV.js.map +0 -1
  427. package/dist/chunk-CY3AHGO4.js.map +0 -1
  428. package/dist/chunk-DAXLNIDY.js.map +0 -1
  429. package/dist/chunk-FGMFQSHX.js.map +0 -1
  430. package/dist/chunk-TYHR5X4W.js +0 -33
  431. package/dist/chunk-TYHR5X4W.js.map +0 -1
  432. package/dist/chunk-ULBI5JGB.js +0 -109
  433. package/dist/chunk-ULBI5JGB.js.map +0 -1
  434. package/dist/chunk-WN6XJWOS.js.map +0 -1
  435. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  436. package/dist/chunk-YNUBMSMV.js.map +0 -1
  437. package/dist/chunk-ZTT2AXMX.js.map +0 -1
  438. package/dist/eventContext-BBA42P6G.js +0 -14
  439. package/dist/eventContext-BBA42P6G.js.map +0 -1
  440. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  441. package/docs/api/interfaces/RBACContextType.md +0 -468
  442. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  443. package/docs/breaking-changes.md +0 -179
  444. package/docs/consuming-app-example.md +0 -290
  445. package/docs/documentation-style-checklist.md +0 -294
  446. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  447. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  448. package/docs/getting-started/examples/full-featured-app.md +0 -616
  449. package/docs/getting-started/quick-start.md +0 -426
  450. package/docs/implementation-guides/datatable-filtering.md +0 -313
  451. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  452. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  453. package/docs/implementation-guides/large-datasets.md +0 -281
  454. package/docs/implementation-guides/performance.md +0 -403
  455. package/docs/migration/quick-migration-guide.md +0 -320
  456. package/docs/migration-guide.md +0 -193
  457. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  458. package/docs/performance/README.md +0 -551
  459. package/docs/style-guide.md +0 -925
  460. package/docs/troubleshooting/authentication-issues.md +0 -334
  461. package/docs/troubleshooting/debugging.md +0 -1117
  462. package/docs/troubleshooting/migration.md +0 -918
  463. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  464. package/src/components/DataTable/components/DataTableBody.tsx +0 -488
  465. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -144
  466. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -515
  467. package/src/components/DataTable/core/ActionManager.ts +0 -235
  468. package/src/components/DataTable/core/ColumnManager.ts +0 -215
  469. package/src/components/DataTable/core/DataManager.ts +0 -188
  470. package/src/components/DataTable/core/DataTableContext.tsx +0 -181
  471. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -264
  472. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  473. package/src/components/DataTable/core/StateManager.ts +0 -311
  474. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -634
  475. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -193
  476. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -519
  477. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -714
  478. package/src/components/DataTable/core/interfaces.ts +0 -338
  479. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  480. package/src/components/Select/Select.bug-test.tsx +0 -69
  481. package/src/components/Select/Select.refactored.tsx +0 -497
  482. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  483. package/src/hooks/services/usePermissions.ts +0 -70
  484. package/src/hooks/services/useRBACService.ts +0 -30
  485. package/src/hooks/usePermissionCheck.ts +0 -150
  486. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  487. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  488. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  489. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  490. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  491. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  492. package/src/rbac/providers/RBACProvider.tsx +0 -645
  493. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  494. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  495. package/src/rbac/providers/index.ts +0 -11
  496. package/src/services/RBACService.ts +0 -522
  497. package/src/services/__tests__/RBACService.test.ts +0 -492
  498. package/src/services/interfaces/IRBACService.ts +0 -62
  499. package/src/utils/appNameResolver.test 2.ts +0 -494
  500. /package/dist/{DataTable-HWZQGASI.js.map → DataTable-QCNCV6IK.js.map} +0 -0
  501. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-Z2FWNW7O.js.map} +0 -0
  502. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  503. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  504. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-CRKP3HXI.js.map} +0 -0
  505. /package/dist/{chunk-URUTVZ7N.js.map → chunk-DVHZ5L55.js.map} +0 -0
  506. /package/dist/{chunk-NTNILOBC.js.map → chunk-TLD5BEU6.js.map} +0 -0
  507. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -9,8 +9,8 @@
9
9
  * while maintaining all features consistently.
10
10
  */
11
11
 
12
- import React, { useLayoutEffect, useState, useRef, useMemo } from 'react';
13
- import { type Table, flexRender } from '@tanstack/react-table';
12
+ import React, { useLayoutEffect, useState, useRef, useMemo, useEffect } from 'react';
13
+ import { type Table, flexRender, type Column, type Row } from '@tanstack/react-table';
14
14
  import { useVirtualizer } from '@tanstack/react-virtual';
15
15
  // Removed Table component imports - using native HTML elements
16
16
  import { Button } from '../../Button/Button';
@@ -18,12 +18,22 @@ import { ChevronUp, ChevronDown, ChevronRight } from 'lucide-react';
18
18
  import { EmptyState } from './EmptyState';
19
19
  import { FilterRow } from './FilterRow';
20
20
  import { ActionButtons } from './ActionButtons';
21
- import { DraggableColumnHeader } from './DraggableColumnHeader';
21
+ 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';
36
+ import { getRowIdSafe } from '../utils/rowUtils';
27
37
 
28
38
  // Performance thresholds
29
39
  const VIRTUALIZATION_THRESHOLD = 1000;
@@ -33,15 +43,15 @@ const MEMORY_OPTIMIZATION_THRESHOLD = 100000;
33
43
  /**
34
44
  * Props for the unified table body component
35
45
  */
36
- interface UnifiedTableBodyProps<TData extends Record<string, any>> {
46
+ interface UnifiedTableBodyProps<TData extends DataRecord> {
37
47
  /** TanStack table instance */
38
48
  table: Table<TData>;
39
49
  /** Whether a new row is being created */
40
50
  isCreating: boolean;
41
51
  /** Data for the row being created */
42
- creationData: Record<string, any>;
52
+ creationData: Record<string, CellValue>;
43
53
  /** Callback when creation data changes */
44
- onCreationDataChange: (data: Record<string, any>) => void;
54
+ onCreationDataChange: (data: Record<string, CellValue>) => void;
45
55
  /** Callback to save the new row */
46
56
  onSaveCreation: () => void;
47
57
  /** Callback to cancel row creation */
@@ -49,9 +59,9 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
49
59
  /** ID of the row currently being edited */
50
60
  editingRowId: string | null;
51
61
  /** Data for the row being edited */
52
- editingData: Record<string, any>;
62
+ editingData: Record<string, CellValue>;
53
63
  /** Callback when editing data changes */
54
- onEditingDataChange: (data: Record<string, any>) => void;
64
+ onEditingDataChange: (data: Record<string, CellValue>) => void;
55
65
  /** Callback to save the edited row */
56
66
  onSaveEditing?: () => void;
57
67
  /** Callback to cancel row editing */
@@ -63,15 +73,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
63
73
  /** Function to get unique row ID */
64
74
  getRowId?: (row: TData, index: number) => string;
65
75
  /** Custom empty state configuration */
66
- emptyState?: {
67
- title?: string;
68
- description?: string;
69
- icon?: React.ComponentType<{ className?: string }>;
70
- action?: {
71
- label: string;
72
- onClick: () => void;
73
- };
74
- };
76
+ emptyState?: EmptyStateConfig;
75
77
  /** Whether the table is currently filtered */
76
78
  isFiltered?: boolean;
77
79
  /** Callback to clear all filters */
@@ -80,16 +82,6 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
80
82
  enableFiltering?: boolean;
81
83
  /** Whether the filter row should be visible */
82
84
  showFilterRow?: boolean;
83
- /** Whether column reordering is enabled */
84
- enableColumnReordering?: boolean;
85
- /** Callback when column order changes */
86
- onColumnOrderChange?: (columnOrder: string[]) => void;
87
- /** Callback when a column is dropped on another column */
88
- onColumnDrop?: (draggedColumnId: string, targetColumnId: string) => void;
89
- /** Saved column order from persistence */
90
- savedColumnOrder?: string[];
91
- /** Whether persistence is enabled */
92
- enablePersistence?: boolean;
93
85
  /** Table ID for persistence */
94
86
  tableId?: string;
95
87
  /** Data length for virtualization decision */
@@ -112,25 +104,7 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
112
104
  hasAnyChildren?: boolean;
113
105
  };
114
106
  /** Actions for action buttons */
115
- actions?: Array<{
116
- label: string;
117
- onClick: (row: any) => void;
118
- icon?: any;
119
- variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost';
120
- disabled?: boolean | ((row?: any) => boolean);
121
- visible?: boolean | ((row?: any) => boolean);
122
- testId?: string;
123
- showInEditMode?: boolean;
124
- hideInViewMode?: boolean;
125
- showInViewMode?: boolean;
126
- hidden?: boolean;
127
- showForParent?: boolean;
128
- showForChild?: boolean;
129
- parentIcon?: any;
130
- childIcon?: any;
131
- parentLabel?: string;
132
- childLabel?: string;
133
- }>;
107
+ actions?: DataTableAction<TData>[];
134
108
  // MANDATORY RBAC
135
109
  rbac?: {
136
110
  pageId?: string;
@@ -147,38 +121,38 @@ interface UnifiedTableBodyProps<TData extends Record<string, any>> {
147
121
  }
148
122
 
149
123
  // Helper function to render the appropriate input type based on column configuration
150
- const renderEditField = (
151
- column: any,
152
- value: any,
153
- onChange: (value: any) => void,
154
- editingData: Record<string, any> = {},
124
+ const renderEditField = <TData extends DataRecord>(
125
+ column: Column<TData, unknown>,
126
+ value: CellValue,
127
+ onChange: (value: CellValue | Record<string, CellValue>) => void,
128
+ editingData: Record<string, CellValue> = {},
155
129
  placeholder?: string
156
130
  ) => {
157
- const columnDef = column.columnDef;
158
-
131
+ const columnDef = column.columnDef as EditableColumnDef<TData>;
132
+
159
133
  // Check if column is editable (default: true)
160
134
  if (columnDef.editable === false) {
161
135
  // Return the original value as text if column is not editable
162
- return <span className="text-sm text-gray-600">{value || ''}</span>;
136
+ return <span className="text-sm text-gray-600">{String(value ?? '')}</span>;
163
137
  }
164
-
138
+
165
139
  // Check for custom field type
166
140
  if (columnDef.fieldType === 'select' && columnDef.fieldOptions) {
167
141
  // Use editAccessorKey if specified, otherwise use the column id
168
142
  const accessorKey = columnDef.editAccessorKey || column.id;
169
- const currentValue = editingData[accessorKey] || value || '';
170
-
143
+ const currentValue = editingData[accessorKey] ?? value ?? '';
144
+
171
145
  return (
172
146
  <Select
173
- value={currentValue}
174
- onValueChange={(newValue) => onChange({ [accessorKey]: newValue })}
147
+ value={String(currentValue)}
148
+ onValueChange={(newValue) => onChange({ [accessorKey]: newValue as CellValue })}
175
149
  >
176
150
  <SelectTrigger className="h-8">
177
151
  <SelectValue placeholder={placeholder || `Select ${columnDef.header || column.id}...`} />
178
152
  </SelectTrigger>
179
153
  <SelectContent>
180
- {columnDef.fieldOptions.map((option: any) => (
181
- <SelectItem key={option.value} value={option.value}>
154
+ {columnDef.fieldOptions.map(option => (
155
+ <SelectItem key={option.value} value={String(option.value)}>
182
156
  {option.label}
183
157
  </SelectItem>
184
158
  ))}
@@ -192,55 +166,40 @@ const renderEditField = (
192
166
  return (
193
167
  <Input
194
168
  type="number"
195
- value={value || ''}
196
- onChange={(e) => onChange(e.target.value)}
169
+ value={String(value ?? '')}
170
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
197
171
  placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
198
172
  className="h-8"
199
173
  />
200
174
  );
201
175
  }
202
-
176
+
203
177
  // Check for date type
204
178
  if (columnDef.fieldType === 'date') {
205
179
  return (
206
180
  <Input
207
181
  type="date"
208
- value={value || ''}
209
- onChange={(e) => onChange(e.target.value)}
182
+ value={String(value ?? '')}
183
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
210
184
  className="h-8"
211
185
  />
212
186
  );
213
187
  }
214
-
188
+
215
189
  // Default to text input
216
190
  return (
217
191
  <Input
218
192
  type="text"
219
- value={value || ''}
220
- onChange={(e) => onChange(e.target.value)}
193
+ value={String(value ?? '')}
194
+ onChange={(e) => onChange(e.target.value as unknown as CellValue)}
221
195
  placeholder={placeholder || `Enter ${columnDef.header || column.id}...`}
222
196
  className="h-8"
223
197
  />
224
198
  );
225
199
  };
226
200
 
227
- // Row component without memoization to ensure column visibility works
228
- const MemoizedRow = ({
229
- row,
230
- style,
231
- isEditing,
232
- editingData,
233
- onEditingDataChange,
234
- onSaveEditing,
235
- onCancelEditing,
236
- getRowId,
237
- grouping,
238
- editingRowId,
239
- hierarchical,
240
- actions,
241
- rbac,
242
- permissions
243
- }: {
201
+ // Row component props interface
202
+ interface RowProps {
244
203
  row: any;
245
204
  style?: React.CSSProperties;
246
205
  isEditing?: boolean;
@@ -290,8 +249,29 @@ const MemoizedRow = ({
290
249
  canExport: { can: boolean; isLoading: boolean };
291
250
  canImport: { can: boolean; isLoading: boolean };
292
251
  };
293
- }) => {
294
- const rowId = getRowId ? getRowId(row.original, row.index) : String(row.index);
252
+ }
253
+
254
+ // Row component with proper memoization
255
+ const RowComponent = React.memo(({
256
+ row,
257
+ style,
258
+ isEditing,
259
+ editingData,
260
+ onEditingDataChange,
261
+ onSaveEditing,
262
+ onCancelEditing,
263
+ getRowId,
264
+ grouping,
265
+ editingRowId,
266
+ hierarchical,
267
+ actions,
268
+ rbac,
269
+ permissions
270
+ }: RowProps) => {
271
+ const rowRef = useRef<HTMLTableRowElement>(null);
272
+ const firstInputRef = useRef<HTMLInputElement>(null);
273
+
274
+ const rowId = getRowIdSafe(row.original, row.index, getRowId);
295
275
 
296
276
  // Hierarchical row styling - moved to top to avoid hoisting issues
297
277
  const hierarchicalRow = row.original as HierarchicalDataRow;
@@ -299,6 +279,40 @@ const MemoizedRow = ({
299
279
  const isParent = isHierarchical && hierarchicalRow.isParent;
300
280
  const isChild = isHierarchical && !hierarchicalRow.isParent;
301
281
 
282
+ // Auto-focus first editable field when entering edit mode
283
+ useEffect(() => {
284
+ if (isEditing && firstInputRef.current) {
285
+ firstInputRef.current.focus();
286
+ firstInputRef.current.select();
287
+ }
288
+ }, [isEditing]);
289
+
290
+ // Keyboard navigation (Enter to save, Escape to cancel)
291
+ useEffect(() => {
292
+ if (!isEditing) return;
293
+
294
+ const handleKeyDown = (event: KeyboardEvent) => {
295
+ const target = event.target as HTMLElement;
296
+ if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
297
+ if (event.key === 'Enter' && !event.shiftKey && target.tagName === 'INPUT') {
298
+ event.preventDefault();
299
+ onSaveEditing?.();
300
+ } else if (event.key === 'Escape') {
301
+ event.preventDefault();
302
+ onCancelEditing?.();
303
+ }
304
+ }
305
+ };
306
+
307
+ const currentRow = rowRef.current;
308
+ if (currentRow) {
309
+ currentRow.addEventListener('keydown', handleKeyDown);
310
+ return () => {
311
+ currentRow.removeEventListener('keydown', handleKeyDown);
312
+ };
313
+ }
314
+ }, [isEditing, onSaveEditing, onCancelEditing]);
315
+
302
316
  // Handle grouped rows
303
317
  if (row.getIsGrouped && row.getIsGrouped()) {
304
318
  const groupValue = row.getValue(grouping[0]);
@@ -346,52 +360,12 @@ const MemoizedRow = ({
346
360
  key={cell.id}
347
361
  className={getTableCellClasses({
348
362
  isCompact: true,
349
- 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' : ''}`
350
364
  })}
351
365
  >
352
- <div className={`${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
353
- {isSubRowEditing && cell.column.id !== 'actions' ? (
354
- // Check if column has a custom cell renderer - if so, use it in edit mode
355
- cell.column.columnDef.cell ? (
356
- flexRender(cell.column.columnDef.cell, {
357
- ...cell.getContext(),
358
- hierarchical: hierarchical,
359
- isParent: false,
360
- isChild: true,
361
- isHierarchical: false,
362
- rowId: subRowId,
363
- isExpanded: false,
364
- hasChildren: false,
365
- getIsEditing: () => true, // Always true in edit mode
366
- setValue: (value: any) => {
367
- if (typeof value === 'object' && value !== null) {
368
- onEditingDataChange?.({ ...editingData, ...value });
369
- } else {
370
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
371
- }
372
- }
373
- })
374
- ) : (
375
- // Fall back to default edit field rendering when no custom cell renderer
376
- renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
377
- if (typeof value === 'object' && value !== null) {
378
- onEditingDataChange?.({ ...editingData, ...value });
379
- } else {
380
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
381
- }
382
- }, editingData)
383
- )
384
- ) : cell.column.id === 'actions' ? (
385
- <ActionButtons
386
- row={row}
387
- actions={actions}
388
- isEditing={isEditing}
389
- isParent={isParent}
390
- hierarchical={!!hierarchical}
391
- rbac={rbac}
392
- permissions={permissions}
393
- />
394
- ) : (
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 ? (
395
369
  flexRender(cell.column.columnDef.cell, {
396
370
  ...cell.getContext(),
397
371
  hierarchical: hierarchical,
@@ -400,10 +374,48 @@ const MemoizedRow = ({
400
374
  isHierarchical: false,
401
375
  rowId: subRowId,
402
376
  isExpanded: false,
403
- 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
+ }
404
386
  })
405
- )}
406
- </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
+ )}
407
419
  </td>
408
420
  ))}
409
421
  </tr>
@@ -418,7 +430,24 @@ const MemoizedRow = ({
418
430
  return null;
419
431
  }
420
432
 
421
- // Regular row
433
+ // If we're in edit mode, use EditableRow for better UX (auto-focus, keyboard shortcuts)
434
+ if (isEditing && editingData && onEditingDataChange && onSaveEditing && onCancelEditing) {
435
+ return (
436
+ <EditableRow
437
+ row={row}
438
+ editingData={editingData}
439
+ onEditingDataChange={onEditingDataChange}
440
+ onSave={onSaveEditing}
441
+ onCancel={onCancelEditing}
442
+ actions={actions ?? []}
443
+ getRowId={getRowId}
444
+ isParent={isParent}
445
+ hierarchical={!!hierarchical}
446
+ />
447
+ );
448
+ }
449
+
450
+ // Regular row (not in edit mode)
422
451
  const visibleCells = row.getVisibleCells();
423
452
  const allCells = row.getAllCells ? row.getAllCells() : [];
424
453
 
@@ -436,158 +465,79 @@ const MemoizedRow = ({
436
465
 
437
466
  return (
438
467
  <tr
468
+ ref={rowRef}
439
469
  key={row.id}
470
+ role="row"
440
471
  style={{
441
472
  ...style,
442
473
  ...(isChild && indentation > 0 ? { paddingLeft: `${indentation}px` } : {})
443
474
  }}
444
475
  className={rowClassName}
476
+ aria-selected={typeof row.getIsSelected === 'function' ? (row.getIsSelected() ? 'true' : 'false') : 'false'}
445
477
  >
446
478
  {visibleCells.map((cell: any, cellIndex: number) => {
447
- // For hierarchical parent rows, add expansion button to the first cell
448
479
  const isFirstCell = cellIndex === 0;
449
480
  const shouldShowExpansionButton = isHierarchical && isParent && isFirstCell && hierarchical?.state;
450
481
  const isExpanded = shouldShowExpansionButton ? hierarchical?.state?.isExpanded(rowId) : false;
451
482
  const hasChildren = shouldShowExpansionButton ? hierarchical?.state?.hasChildren(rowId) : false;
452
483
 
453
- // Debug logging for expander button conditions (development only)
454
- if (import.meta.env.MODE === 'development' && isParent && isFirstCell) {
455
- console.log('🔍 Expander Button Debug:', {
456
- rowId,
457
- isHierarchical,
458
- isParent,
459
- isFirstCell,
460
- hasHierarchicalState: !!hierarchical?.state,
461
- shouldShowExpansionButton,
462
- hasChildren,
463
- isExpanded
464
- });
465
- }
466
-
467
-
468
484
  return (
469
485
  <td
470
486
  key={cell.id}
471
487
  className={getTableCellClasses({
472
488
  isCompact: true,
473
- 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' : ''}`
474
490
  })}
475
491
  >
476
- <div className="flex items-center gap-2">
477
- {/* Individual expansion button for hierarchical parent rows */}
478
- {shouldShowExpansionButton && hasChildren && (
479
- <Button
480
- variant="ghost"
481
- size="sm"
482
- onClick={() => hierarchical?.state?.toggleRow(rowId)}
483
- className="h-6 w-6 p-0 flex-shrink-0"
484
- aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
485
- title={isExpanded ? 'Collapse row' : 'Expand row'}
486
- >
487
- {isExpanded ? (
488
- <ChevronDown className="h-4 w-4" />
489
- ) : (
490
- <ChevronRight className="h-4 w-4" />
491
- )}
492
- </Button>
493
- )}
494
-
495
- {/* Cell content */}
496
- <div className={`flex-1 ${cell.column.columnDef.meta?.align === 'right' ? 'text-right' : ''}`}>
497
- {(() => {
498
- const columnDef = cell.column.columnDef as any;
499
- const isColumnEditable = columnDef.editable !== false;
500
- const shouldRenderEditField = isEditing && cell.column.id !== 'actions' && isColumnEditable;
501
-
502
- if (shouldRenderEditField) {
503
- // Render edit input fields for editable columns in edit mode
504
- return cell.column.columnDef.cell ? (
505
- flexRender(cell.column.columnDef.cell, {
506
- ...cell.getContext(),
507
- hierarchical: hierarchical,
508
- isParent: isParent,
509
- isChild: isChild,
510
- isHierarchical: isHierarchical,
511
- rowId: rowId,
512
- isExpanded: isExpanded,
513
- hasChildren: hasChildren,
514
- getIsEditing: () => true, // Always true in edit mode
515
- setValue: (value: any) => {
516
- if (typeof value === 'object' && value !== null) {
517
- onEditingDataChange?.({ ...editingData, ...value });
518
- } else {
519
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
520
- }
521
- }
522
- })
523
- ) : (
524
- renderEditField(cell.column, editingData?.[cell.column.id], (value) => {
525
- if (typeof value === 'object' && value !== null) {
526
- onEditingDataChange?.({ ...editingData, ...value });
527
- } else {
528
- onEditingDataChange?.({ ...editingData, [cell.column.id]: value });
529
- }
530
- }, editingData)
531
- );
532
- }
533
-
534
- // Render normal cell (not in edit mode, or column not editable, or is actions column)
535
- if (cell.column.id === 'actions') {
536
- return isEditing ? (
537
- <div className="flex gap-1">
538
- <button
539
- onClick={onSaveEditing}
540
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
541
- title="Save changes"
542
- >
543
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
544
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
545
- </svg>
546
- </button>
547
- <button
548
- onClick={onCancelEditing}
549
- className="h-8 w-8 p-0 hover:bg-muted/50 flex items-center justify-center"
550
- title="Cancel changes"
551
- >
552
- <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
553
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
554
- </svg>
555
- </button>
556
- </div>
557
- ) : (
558
- <ActionButtons
559
- row={row}
560
- actions={actions}
561
- isEditing={isEditing}
562
- isParent={isParent}
563
- hierarchical={!!hierarchical}
564
- rbac={rbac}
565
- permissions={permissions}
566
- />
567
- );
568
- }
569
-
570
- return flexRender(cell.column.columnDef.cell, {
571
- ...cell.getContext(),
572
- hierarchical: hierarchical,
573
- isParent: isParent,
574
- isChild: isChild,
575
- isHierarchical: isHierarchical,
576
- rowId: rowId,
577
- isExpanded: isExpanded,
578
- hasChildren: hasChildren,
579
- });
580
- })()}
581
- </div>
582
- </div>
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" />
503
+ ) : (
504
+ <ChevronRight className="h-4 w-4" />
505
+ )}
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
+ )}
583
530
  </td>
584
531
  );
585
532
  })}
586
533
  </tr>
587
534
  );
588
- };
535
+ });
536
+
537
+ RowComponent.displayName = 'RowComponent';
589
538
 
590
- MemoizedRow.displayName = 'MemoizedRow';
539
+ // Use the already memoized RowComponent
540
+ const MemoizedRow = RowComponent;
591
541
 
592
542
  /**
593
543
  * Unified table body component with intelligent virtualization
@@ -612,12 +562,6 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
612
562
  onClearFilters,
613
563
  enableFiltering = false,
614
564
  showFilterRow = false,
615
- enableColumnReordering = false,
616
- onColumnOrderChange,
617
- onColumnDrop,
618
- savedColumnOrder,
619
- enablePersistence = false,
620
- tableId,
621
565
  dataLength,
622
566
  virtualHeight = 600,
623
567
  forceVirtualization = false,
@@ -639,16 +583,16 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
639
583
  const rows = table.getRowModel().rows;
640
584
  const headerGroups = table.getHeaderGroups();
641
585
 
642
- // Virtual scrolling setup
586
+ // Virtual scrolling setup - only create virtualizer when needed
643
587
  const virtualizer = useVirtualizer({
644
- count: rows.length,
588
+ count: shouldVirtualize ? rows.length : 0,
645
589
  getScrollElement: () => parentRef.current,
646
590
  estimateSize: () => 40,
647
591
  overscan: 5,
648
592
  });
649
593
 
650
- const virtualRows = virtualizer.getVirtualItems();
651
- const totalSize = virtualizer.getTotalSize();
594
+ const virtualRows = shouldVirtualize ? virtualizer.getVirtualItems() : [];
595
+ const totalSize = shouldVirtualize ? virtualizer.getTotalSize() : 0;
652
596
 
653
597
 
654
598
  // Render table content
@@ -680,7 +624,7 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
680
624
  const row = rows[virtualRow.index];
681
625
  if (!row) return null;
682
626
 
683
- const rowId = getRowId ? getRowId(row.original, row.index) : String(row.index);
627
+ const rowId = getRowIdSafe(row.original, row.index, getRowId);
684
628
  const isEditing = editingRowId === rowId;
685
629
 
686
630
  return (
@@ -713,7 +657,7 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
713
657
  } else {
714
658
  // Standard rendering
715
659
  return rows.map((row) => {
716
- const rowId = getRowId ? getRowId(row.original, row.index) : String(row.index);
660
+ const rowId = getRowIdSafe(row.original, row.index, getRowId);
717
661
  const isEditing = editingRowId === rowId;
718
662
 
719
663
  return (
@@ -761,10 +705,10 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
761
705
  })}
762
706
  >
763
707
  {renderEditField(header.column, creationData[header.column.id], (value) => {
764
- if (typeof value === 'object' && value !== null) {
765
- onCreationDataChange({ ...creationData, ...value });
708
+ if (typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date)) {
709
+ onCreationDataChange({ ...creationData, ...(value as Record<string, CellValue>) });
766
710
  } else {
767
- onCreationDataChange({ ...creationData, [header.column.id]: value });
711
+ onCreationDataChange({ ...creationData, [header.column.id]: value as CellValue });
768
712
  }
769
713
  }, creationData)}
770
714
  </td>