@jmruthers/pace-core 0.5.193 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +299 -0
  4. package/cursor-rules/01-standards-compliance.mdc +244 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +222 -0
  7. package/cursor-rules/04-testing-standards.mdc +268 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +309 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
  11. package/cursor-rules/08-markup-quality.mdc +452 -0
  12. package/cursor-rules/CHANGELOG.md +119 -0
  13. package/cursor-rules/README.md +192 -0
  14. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
  15. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
  16. package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
  17. package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
  18. package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
  19. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
  20. package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
  21. package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
  22. package/dist/chunk-24UVZUZG.js.map +1 -0
  23. package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
  24. package/dist/chunk-2UOI2FG5.js.map +1 -0
  25. package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
  26. package/dist/chunk-3XC4CPTD.js.map +1 -0
  27. package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
  28. package/dist/chunk-6J4GEEJR.js.map +1 -0
  29. package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
  30. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  31. package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
  32. package/dist/chunk-EHMR7VYL.js.map +1 -0
  33. package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
  34. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  35. package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
  36. package/dist/chunk-FFQEQTNW.js.map +1 -0
  37. package/dist/chunk-FMUCXFII.js +76 -0
  38. package/dist/chunk-FMUCXFII.js.map +1 -0
  39. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  40. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  41. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  42. package/dist/chunk-L4OXEN46.js.map +1 -0
  43. package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
  44. package/dist/chunk-M43Y4SSO.js.map +1 -0
  45. package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
  46. package/dist/chunk-MMZ7JXPU.js.map +1 -0
  47. package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
  48. package/dist/chunk-NECFR5MM.js.map +1 -0
  49. package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
  50. package/dist/chunk-SFZUDBL5.js.map +1 -0
  51. package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
  52. package/dist/chunk-XWQCNGTQ.js.map +1 -0
  53. package/dist/components.d.ts +6 -6
  54. package/dist/components.js +15 -12
  55. package/dist/components.js.map +1 -1
  56. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  57. package/dist/hooks.d.ts +59 -126
  58. package/dist/hooks.js +19 -28
  59. package/dist/hooks.js.map +1 -1
  60. package/dist/index.d.ts +63 -16
  61. package/dist/index.js +23 -24
  62. package/dist/index.js.map +1 -1
  63. package/dist/providers.d.ts +21 -3
  64. package/dist/providers.js +2 -2
  65. package/dist/rbac/index.d.ts +146 -115
  66. package/dist/rbac/index.js +8 -11
  67. package/dist/theming/runtime.d.ts +1 -13
  68. package/dist/theming/runtime.js +1 -1
  69. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  70. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  71. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  72. package/dist/types.d.ts +2 -2
  73. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
  74. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  75. package/dist/utils.d.ts +4 -5
  76. package/dist/utils.js +15 -15
  77. package/dist/utils.js.map +1 -1
  78. package/docs/api/README.md +7 -1
  79. package/docs/api/classes/ColumnFactory.md +8 -8
  80. package/docs/api/classes/InvalidScopeError.md +4 -4
  81. package/docs/api/classes/Logger.md +1 -1
  82. package/docs/api/classes/MissingUserContextError.md +4 -4
  83. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  84. package/docs/api/classes/PermissionDeniedError.md +4 -4
  85. package/docs/api/classes/RBACAuditManager.md +1 -1
  86. package/docs/api/classes/RBACCache.md +1 -1
  87. package/docs/api/classes/RBACEngine.md +1 -1
  88. package/docs/api/classes/RBACError.md +4 -4
  89. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  90. package/docs/api/classes/SecureSupabaseClient.md +18 -15
  91. package/docs/api/classes/StorageUtils.md +1 -1
  92. package/docs/api/enums/FileCategory.md +1 -1
  93. package/docs/api/enums/LogLevel.md +1 -1
  94. package/docs/api/enums/RBACErrorCode.md +1 -1
  95. package/docs/api/enums/RPCFunction.md +1 -1
  96. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  97. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  98. package/docs/api/interfaces/AggregateConfig.md +4 -4
  99. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  100. package/docs/api/interfaces/AvatarProps.md +1 -1
  101. package/docs/api/interfaces/BadgeProps.md +9 -2
  102. package/docs/api/interfaces/ButtonProps.md +7 -4
  103. package/docs/api/interfaces/CalendarProps.md +8 -5
  104. package/docs/api/interfaces/CardProps.md +8 -5
  105. package/docs/api/interfaces/ColorPalette.md +1 -1
  106. package/docs/api/interfaces/ColorShade.md +1 -1
  107. package/docs/api/interfaces/ComplianceResult.md +1 -1
  108. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  109. package/docs/api/interfaces/DataRecord.md +1 -1
  110. package/docs/api/interfaces/DataTableAction.md +24 -21
  111. package/docs/api/interfaces/DataTableColumn.md +31 -31
  112. package/docs/api/interfaces/DataTableProps.md +1 -1
  113. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  114. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  115. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  116. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  117. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  118. package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
  119. package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
  120. package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
  121. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  122. package/docs/api/interfaces/ExportColumn.md +1 -1
  123. package/docs/api/interfaces/ExportOptions.md +8 -8
  124. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  125. package/docs/api/interfaces/FileMetadata.md +1 -1
  126. package/docs/api/interfaces/FileReference.md +1 -1
  127. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  128. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  129. package/docs/api/interfaces/FileUploadProps.md +26 -23
  130. package/docs/api/interfaces/FooterProps.md +10 -8
  131. package/docs/api/interfaces/FormFieldProps.md +10 -10
  132. package/docs/api/interfaces/FormProps.md +1 -1
  133. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  134. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  135. package/docs/api/interfaces/InputProps.md +7 -4
  136. package/docs/api/interfaces/LabelProps.md +1 -1
  137. package/docs/api/interfaces/LoggerConfig.md +1 -1
  138. package/docs/api/interfaces/LoginFormProps.md +14 -11
  139. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  140. package/docs/api/interfaces/NavigationContextType.md +1 -1
  141. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  142. package/docs/api/interfaces/NavigationItem.md +11 -11
  143. package/docs/api/interfaces/NavigationMenuProps.md +15 -15
  144. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  145. package/docs/api/interfaces/Organisation.md +1 -1
  146. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  147. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  148. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  149. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  150. package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
  151. package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
  152. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  153. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  154. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  155. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  156. package/docs/api/interfaces/PaletteData.md +1 -1
  157. package/docs/api/interfaces/ParsedAddress.md +1 -1
  158. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  159. package/docs/api/interfaces/ProgressProps.md +1 -1
  160. package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
  161. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  162. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  163. package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
  164. package/docs/api/interfaces/QuickFix.md +1 -1
  165. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  166. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  167. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  168. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  169. package/docs/api/interfaces/RBACConfig.md +1 -1
  170. package/docs/api/interfaces/RBACContext.md +1 -1
  171. package/docs/api/interfaces/RBACLogger.md +1 -1
  172. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  173. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  174. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  175. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  176. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  177. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  178. package/docs/api/interfaces/RBACResult.md +1 -1
  179. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  180. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  181. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  182. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  183. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  184. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  185. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  186. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  187. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  188. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  189. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  190. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  191. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  192. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  193. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  194. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  195. package/docs/api/interfaces/RouteConfig.md +1 -1
  196. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  197. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  198. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  199. package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
  200. package/docs/api/interfaces/SetupIssue.md +1 -1
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +3 -3
  215. package/docs/api/interfaces/TextareaProps.md +1 -1
  216. package/docs/api/interfaces/ToastActionElement.md +4 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
  220. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  221. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  222. package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
  223. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  224. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  225. package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
  226. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  227. package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
  228. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  229. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
  230. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
  231. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  232. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  233. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  234. package/docs/api/interfaces/UserEventAccess.md +14 -11
  235. package/docs/api/interfaces/UserMenuProps.md +8 -6
  236. package/docs/api/interfaces/UserProfile.md +1 -1
  237. package/docs/api/modules.md +575 -634
  238. package/docs/architecture/database-schema-requirements.md +161 -0
  239. package/docs/core-concepts/rbac-system.md +3 -3
  240. package/docs/documentation-index.md +2 -4
  241. package/docs/getting-started/cursor-rules.md +263 -0
  242. package/docs/getting-started/installation-guide.md +6 -1
  243. package/docs/getting-started/quick-start.md +6 -1
  244. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  245. package/docs/migration/MIGRATION_GUIDE.md +6 -28
  246. package/docs/migration/README.md +52 -6
  247. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  248. package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
  249. package/docs/migration/database-changes-december-2025.md +3 -3
  250. package/docs/rbac/event-based-apps.md +1 -1
  251. package/docs/rbac/getting-started.md +1 -1
  252. package/docs/rbac/quick-start.md +1 -1
  253. package/docs/standards/README.md +40 -0
  254. package/docs/troubleshooting/migration.md +4 -4
  255. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  256. package/package.json +12 -6
  257. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  258. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  259. package/scripts/audit/core/checks/bundle.cjs +142 -0
  260. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
  261. package/scripts/audit/core/checks/config.cjs +54 -0
  262. package/scripts/audit/core/checks/coverage.cjs +84 -0
  263. package/scripts/audit/core/checks/dependencies.cjs +454 -0
  264. package/scripts/audit/core/checks/documentation.cjs +203 -0
  265. package/scripts/audit/core/checks/environment.cjs +128 -0
  266. package/scripts/audit/core/checks/error-handling.cjs +299 -0
  267. package/scripts/audit/core/checks/forms.cjs +172 -0
  268. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  269. package/scripts/audit/core/checks/hooks.cjs +334 -0
  270. package/scripts/audit/core/checks/imports.cjs +244 -0
  271. package/scripts/audit/core/checks/performance.cjs +325 -0
  272. package/scripts/audit/core/checks/routes.cjs +117 -0
  273. package/scripts/audit/core/checks/state.cjs +130 -0
  274. package/scripts/audit/core/checks/structure.cjs +65 -0
  275. package/scripts/audit/core/checks/style.cjs +584 -0
  276. package/scripts/audit/core/checks/testing.cjs +122 -0
  277. package/scripts/audit/core/checks/typescript.cjs +61 -0
  278. package/scripts/audit/core/scanner.cjs +199 -0
  279. package/scripts/audit/core/utils.cjs +137 -0
  280. package/scripts/audit/index.cjs +223 -0
  281. package/scripts/audit/reporters/console.cjs +151 -0
  282. package/scripts/audit/reporters/json.cjs +54 -0
  283. package/scripts/audit/reporters/markdown.cjs +124 -0
  284. package/scripts/audit-consuming-app.cjs +86 -0
  285. package/scripts/build-docs/build-decision.js +240 -0
  286. package/scripts/build-docs/cache-utils.js +105 -0
  287. package/scripts/build-docs/content-normalization.js +150 -0
  288. package/scripts/build-docs/file-utils.js +105 -0
  289. package/scripts/build-docs/git-utils.js +86 -0
  290. package/scripts/build-docs/hash-utils.js +116 -0
  291. package/scripts/build-docs/typedoc-runner.js +220 -0
  292. package/scripts/build-docs-incremental.js +77 -913
  293. package/scripts/install-cursor-rules.cjs +236 -0
  294. package/scripts/utils/command-runner.js +16 -11
  295. package/scripts/validate-formats.js +61 -56
  296. package/scripts/validate-master.js +74 -69
  297. package/scripts/validate-pre-publish.js +70 -65
  298. package/src/__tests__/helpers/test-providers.tsx +1 -1
  299. package/src/__tests__/helpers/test-utils.tsx +1 -1
  300. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  301. package/src/components/Alert/Alert.test.tsx +12 -18
  302. package/src/components/Alert/Alert.tsx +5 -7
  303. package/src/components/Avatar/Avatar.test.tsx +4 -4
  304. package/src/components/Badge/Badge.tsx +16 -4
  305. package/src/components/Button/Button.tsx +27 -4
  306. package/src/components/Calendar/Calendar.tsx +9 -3
  307. package/src/components/Card/Card.tsx +4 -0
  308. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  309. package/src/components/Checkbox/Checkbox.tsx +2 -2
  310. package/src/components/DataTable/DataTable.test.tsx +57 -93
  311. package/src/components/DataTable/DataTable.tsx +40 -6
  312. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  313. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
  314. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  315. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  316. package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
  317. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  318. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  319. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  320. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  321. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  322. package/src/components/DataTable/components/DataTableCore.tsx +200 -561
  323. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  324. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  325. package/src/components/DataTable/components/DataTableModals.tsx +9 -1
  326. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  327. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  328. package/src/components/DataTable/components/EditFields.tsx +307 -0
  329. package/src/components/DataTable/components/EditableRow.tsx +9 -1
  330. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  331. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  332. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  333. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  334. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  335. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  336. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  337. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  338. package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
  339. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  340. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  341. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  342. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  343. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  344. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  345. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  346. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  347. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  348. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  349. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  350. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  351. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  352. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  353. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  354. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  355. package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
  356. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  357. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  358. package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
  359. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  360. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  361. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  362. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  363. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  364. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  365. package/src/components/DataTable/styles.ts +6 -6
  366. package/src/components/DataTable/types.ts +6 -10
  367. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  368. package/src/components/DataTable/utils/debugTools.ts +18 -113
  369. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  370. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  371. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  372. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  373. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  374. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  375. package/src/components/Dialog/Dialog.tsx +8 -7
  376. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  377. package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
  378. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  379. package/src/components/ErrorBoundary/index.ts +27 -2
  380. package/src/components/EventSelector/EventSelector.tsx +4 -1
  381. package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
  382. package/src/components/FileDisplay/FileDisplay.tsx +32 -18
  383. package/src/components/FileUpload/FileUpload.tsx +22 -2
  384. package/src/components/Footer/Footer.test.tsx +16 -16
  385. package/src/components/Footer/Footer.tsx +15 -12
  386. package/src/components/Form/Form.test.tsx +36 -15
  387. package/src/components/Form/Form.tsx +31 -26
  388. package/src/components/Header/Header.tsx +22 -11
  389. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  390. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  391. package/src/components/Input/Input.test.tsx +2 -2
  392. package/src/components/Input/Input.tsx +36 -34
  393. package/src/components/Label/Label.tsx +1 -1
  394. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  395. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  396. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  397. package/src/components/LoginForm/LoginForm.tsx +12 -8
  398. package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
  399. package/src/components/NavigationMenu/types.ts +56 -0
  400. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  401. package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
  402. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  403. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
  404. package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
  405. package/src/components/PaceAppLayout/README.md +1 -1
  406. package/src/components/PaceAppLayout/test-setup.tsx +1 -2
  407. package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
  408. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  409. package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
  410. package/src/components/Progress/Progress.tsx +1 -1
  411. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  412. package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
  413. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  414. package/src/components/Select/Select.tsx +95 -438
  415. package/src/components/Select/context.ts +23 -0
  416. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  417. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  418. package/src/components/Select/hooks/useSelectState.ts +104 -0
  419. package/src/components/Select/index.ts +9 -1
  420. package/src/components/Select/types.ts +123 -0
  421. package/src/components/Select/utils/text.ts +26 -0
  422. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
  423. package/src/components/Switch/Switch.tsx +4 -4
  424. package/src/components/Table/Table.tsx +1 -1
  425. package/src/components/Tabs/Tabs.tsx +1 -1
  426. package/src/components/Textarea/Textarea.tsx +27 -29
  427. package/src/components/Toast/Toast.tsx +5 -1
  428. package/src/components/Tooltip/Tooltip.tsx +3 -3
  429. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  430. package/src/components/UserMenu/UserMenu.tsx +22 -19
  431. package/src/components/index.ts +2 -2
  432. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  433. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  434. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  435. package/src/hooks/index.ts +1 -2
  436. package/src/hooks/public/usePublicEvent.ts +5 -1
  437. package/src/hooks/public/usePublicEventLogo.ts +5 -1
  438. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  439. package/src/hooks/public/usePublicRouteParams.ts +5 -1
  440. package/src/hooks/services/useAuth.ts +32 -0
  441. package/src/hooks/services/useCurrentEvent.ts +6 -0
  442. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  443. package/src/hooks/useDataTableState.ts +8 -18
  444. package/src/hooks/useDebounce.ts +9 -0
  445. package/src/hooks/useEventTheme.ts +6 -0
  446. package/src/hooks/useFileDisplay.ts +4 -0
  447. package/src/hooks/useFileReference.ts +25 -7
  448. package/src/hooks/useFileUrl.ts +11 -1
  449. package/src/hooks/useFocusManagement.ts +16 -2
  450. package/src/hooks/useFocusTrap.ts +7 -4
  451. package/src/hooks/useFormDialog.ts +8 -7
  452. package/src/hooks/useInactivityTracker.ts +4 -1
  453. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  454. package/src/hooks/useOrganisationPermissions.ts +4 -0
  455. package/src/hooks/useOrganisationSecurity.ts +4 -0
  456. package/src/hooks/usePerformanceMonitor.ts +4 -0
  457. package/src/hooks/usePermissionCache.ts +8 -1
  458. package/src/hooks/useQueryCache.ts +12 -1
  459. package/src/hooks/useSessionRestoration.ts +4 -0
  460. package/src/hooks/useStorage.ts +4 -0
  461. package/src/hooks/useToast.ts +3 -3
  462. package/src/index.ts +2 -1
  463. package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
  464. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  465. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  466. package/src/providers/services/AuthServiceProvider.tsx +18 -0
  467. package/src/providers/services/EventServiceProvider.tsx +18 -0
  468. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  469. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  470. package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
  471. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
  472. package/src/rbac/README.md +1 -1
  473. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
  474. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  475. package/src/rbac/adapters.tsx +14 -5
  476. package/src/rbac/api.ts +100 -67
  477. package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
  478. package/src/rbac/components/NavigationGuard.tsx +1 -1
  479. package/src/rbac/components/NavigationProvider.tsx +5 -2
  480. package/src/rbac/components/PagePermissionGuard.tsx +158 -18
  481. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  482. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  483. package/src/rbac/components/RoleBasedRouter.tsx +6 -2
  484. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  485. package/src/rbac/components/SecureDataProvider.tsx +21 -6
  486. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  487. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  488. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  489. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  490. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  491. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  492. package/src/rbac/engine.ts +38 -14
  493. package/src/rbac/hooks/permissions/index.ts +7 -0
  494. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  495. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  496. package/src/rbac/hooks/permissions/useCan.ts +347 -0
  497. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  498. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  499. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  500. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  501. package/src/rbac/hooks/useCan.test.ts +71 -64
  502. package/src/rbac/hooks/usePermissions.ts +14 -995
  503. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  504. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  505. package/src/rbac/hooks/useSecureSupabase.ts +33 -13
  506. package/src/rbac/permissions.ts +0 -30
  507. package/src/rbac/secureClient.ts +212 -61
  508. package/src/rbac/types.ts +8 -0
  509. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  510. package/src/theming/parseEventColours.ts +5 -19
  511. package/src/types/vitest-globals.d.ts +51 -26
  512. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  513. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  514. package/src/utils/__tests__/index.unit.test.ts +2 -2
  515. package/src/utils/audit/audit.ts +0 -3
  516. package/src/utils/core/cn.ts +1 -1
  517. package/src/utils/file-reference/index.ts +53 -1
  518. package/src/utils/formatting/formatting.ts +8 -18
  519. package/src/utils/index.ts +0 -1
  520. package/src/utils/security/secureDataAccess.test.ts +31 -20
  521. package/src/utils/security/secureDataAccess.ts +4 -3
  522. package/dist/chunk-6C4YBBJM.js +0 -628
  523. package/dist/chunk-6C4YBBJM.js.map +0 -1
  524. package/dist/chunk-7D4SUZUM.js 2.map +0 -1
  525. package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
  526. package/dist/chunk-7EQTDTTJ.js.map +0 -1
  527. package/dist/chunk-7FLMSG37.js 2.map +0 -1
  528. package/dist/chunk-7FLMSG37.js.map +0 -1
  529. package/dist/chunk-BC4IJKSL.js.map +0 -1
  530. package/dist/chunk-E3SPN4VZ.js +0 -12917
  531. package/dist/chunk-E3SPN4VZ.js.map +0 -1
  532. package/dist/chunk-E66EQZE6 5.js +0 -37
  533. package/dist/chunk-E66EQZE6.js 2.map +0 -1
  534. package/dist/chunk-HWIIPPNI.js.map +0 -1
  535. package/dist/chunk-I7PSE6JW 5.js +0 -191
  536. package/dist/chunk-I7PSE6JW.js 2.map +0 -1
  537. package/dist/chunk-I7PSE6JW.js.map +0 -1
  538. package/dist/chunk-IIELH4DL.js.map +0 -1
  539. package/dist/chunk-KNC55RTG.js 5.map +0 -1
  540. package/dist/chunk-KNC55RTG.js.map +0 -1
  541. package/dist/chunk-KQCRWDSA.js 5.map +0 -1
  542. package/dist/chunk-LFNCN2SP.js +0 -412
  543. package/dist/chunk-LFNCN2SP.js 2.map +0 -1
  544. package/dist/chunk-LFNCN2SP.js.map +0 -1
  545. package/dist/chunk-LMC26NLJ 2.js +0 -84
  546. package/dist/chunk-NOAYCWCX.js +0 -4993
  547. package/dist/chunk-NOAYCWCX.js.map +0 -1
  548. package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
  549. package/dist/chunk-QWWZ5CAQ.js.map +0 -1
  550. package/dist/chunk-QXHPKYJV 3.js +0 -113
  551. package/dist/chunk-R77UEZ4E.js +0 -68
  552. package/dist/chunk-R77UEZ4E.js.map +0 -1
  553. package/dist/chunk-SQGMNID3.js.map +0 -1
  554. package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
  555. package/dist/chunk-XNXXZ43G.js.map +0 -1
  556. package/dist/chunk-ZSAAAMVR 6.js +0 -25
  557. package/dist/components.js 5.map +0 -1
  558. package/dist/styles/index 2.js +0 -12
  559. package/dist/styles/index.js 5.map +0 -1
  560. package/dist/theming/runtime 5.js +0 -19
  561. package/dist/theming/runtime.js 5.map +0 -1
  562. package/docs/api/classes/ErrorBoundary.md +0 -144
  563. package/docs/migration/quick-migration-guide.md +0 -356
  564. package/docs/migration/service-architecture.md +0 -281
  565. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  566. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  567. package/src/hooks/useSecureDataAccess.ts +0 -666
  568. /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
  569. /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
  570. /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
  571. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  572. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  573. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  574. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  575. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  576. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  577. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -22,6 +22,10 @@ import {
22
22
  } from '../types';
23
23
  import type { Permission } from '../../../rbac/types';
24
24
 
25
+ /**
26
+ * Return value of the useDataTablePermissions hook.
27
+ * Contains permission checks and secure feature configuration.
28
+ */
25
29
  export interface UseDataTablePermissionsReturn {
26
30
  permissions: {
27
31
  canRead: ReturnType<typeof useCan>;
@@ -35,6 +39,15 @@ export interface UseDataTablePermissionsReturn {
35
39
  effectivePageId: string | undefined;
36
40
  }
37
41
 
42
+ /**
43
+ * Hook for managing RBAC permissions in DataTable components.
44
+ * Handles scope resolution, permission checks, and secure feature configuration.
45
+ *
46
+ * @template TData - The type of data records in the table
47
+ * @param rbac - RBAC configuration for the DataTable
48
+ * @param features - Feature configuration to secure
49
+ * @returns Permission checks and secure feature configuration
50
+ */
38
51
  export function useDataTablePermissions<TData extends DataRecord>(
39
52
  rbac: DataTableRBACConfig,
40
53
  features: DataTableFeatureConfig = {}
@@ -45,26 +58,69 @@ export function useDataTablePermissions<TData extends DataRecord>(
45
58
 
46
59
  // Super admin status - check if user has super admin privileges
47
60
  // Super admins bypass all permission checks (similar to PaceAppLayout)
48
- const [isSuperAdminUser, setIsSuperAdminUser] = useState<boolean>(false);
49
- const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState<boolean>(false);
61
+ // PERFORMANCE OPTIMIZATION: Check super admin once and share with all useCan hooks to avoid duplicate queries
62
+ // Use null to indicate "not checked yet" vs false which means "checked and not super admin"
63
+ const [isSuperAdminUser, setIsSuperAdminUser] = useState<boolean | null>(null);
64
+ const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState<boolean>(() => !!user?.id);
65
+ const lastCheckedUserIdRef = useRef<string | null>(null);
66
+ const isCheckingRef = useRef<boolean>(false);
50
67
 
51
68
  useEffect(() => {
69
+ // Skip if already checked for this user ID
70
+ if (lastCheckedUserIdRef.current === user?.id && isSuperAdminUser !== null) {
71
+ return;
72
+ }
73
+
74
+ // Skip if already checking
75
+ if (isCheckingRef.current) {
76
+ return;
77
+ }
78
+
52
79
  const checkSuperAdminStatus = async () => {
53
80
  if (!user?.id) {
54
- setIsSuperAdminUser(false);
81
+ setIsSuperAdminUser(false); // No user = not super admin
55
82
  setIsCheckingSuperAdmin(false);
83
+ lastCheckedUserIdRef.current = null;
56
84
  return;
57
85
  }
58
86
 
87
+ // Mark as checking and track user ID
88
+ isCheckingRef.current = true;
89
+ lastCheckedUserIdRef.current = user.id;
90
+
91
+ const startTime = Date.now();
59
92
  setIsCheckingSuperAdmin(true);
93
+
94
+ // Add timeout to prevent infinite hanging
95
+ const timeoutId = setTimeout(() => {
96
+ logger.warn('useDataTablePermissions', 'Super admin check taking longer than 5 seconds', {
97
+ userId: user?.id,
98
+ elapsedMs: Date.now() - startTime,
99
+ });
100
+ }, 5000);
101
+
60
102
  try {
103
+ logger.debug('useDataTablePermissions', 'Starting super admin check', { userId: user?.id });
61
104
  const superAdminStatus = await isSuperAdmin(user.id);
105
+ const elapsed = Date.now() - startTime;
106
+ logger.debug('useDataTablePermissions', 'Super admin check completed', {
107
+ userId: user?.id,
108
+ isSuperAdmin: superAdminStatus,
109
+ elapsedMs: elapsed,
110
+ });
62
111
  setIsSuperAdminUser(superAdminStatus);
63
112
  } catch (error) {
64
- logger.error('useDataTablePermissions', 'Error checking super admin status', { userId: user?.id, error });
65
- setIsSuperAdminUser(false);
113
+ const elapsed = Date.now() - startTime;
114
+ logger.error('useDataTablePermissions', 'Error checking super admin status', {
115
+ userId: user?.id,
116
+ error,
117
+ elapsedMs: elapsed,
118
+ });
119
+ setIsSuperAdminUser(false); // Error = assume not super admin for security
66
120
  } finally {
121
+ clearTimeout(timeoutId);
67
122
  setIsCheckingSuperAdmin(false);
123
+ isCheckingRef.current = false;
68
124
  }
69
125
  };
70
126
 
@@ -156,24 +212,36 @@ export function useDataTablePermissions<TData extends DataRecord>(
156
212
  * This allows permission checks for users without organisations (e.g., profile pages).
157
213
  * The database function rbac_check_permission_simplified can handle NULL organisation_id.
158
214
  *
159
- * IMPORTANT: When using pageName (not pageId), we MUST wait for appId to be resolved,
160
- * because the RPC function needs appId to resolve the pageName to a pageId UUID.
161
- * If we have a pageId (UUID), we can proceed even without appId.
215
+ * PERFORMANCE OPTIMIZATION: For page-level permissions with pageId (UUID), we don't need to wait
216
+ * for full scope resolution. The database function can handle page-level permissions without
217
+ * organisationId or appId. We only need to wait if:
218
+ * 1. We're using pageName (not UUID) and need appId to resolve it, OR
219
+ * 2. We need organisationId for resource-level permissions (but we're using page-level here)
162
220
  *
163
- * The key issue: When pageName is used without appId, the RPC function cannot resolve
164
- * the pageName to a pageId, which causes permission checks to fail initially, showing
165
- * "Access Denied" before the scope resolves and permissions are re-checked.
221
+ * This allows permission checks to proceed in parallel with scope resolution, reducing load time.
166
222
  */
167
223
  const isPageName = !pageId && !!pageName; // We're using pageName, not a UUID pageId
168
224
  const needsAppIdForResolution = isPageName; // Only need appId if we're resolving a pageName
169
225
 
170
- // Wait for scope resolution if:
171
- // 1. Scope is still loading, OR
172
- // 2. We're using pageName and don't have appId yet (needed to resolve pageName to pageId)
173
- // This prevents premature permission checks that would fail and show "Access Denied"
174
- const shouldWaitForScope = scopeLoading || (needsAppIdForResolution && !stableScope.appId);
226
+ // PERFORMANCE FIX: For page-level permissions with UUID pageId, we can proceed immediately
227
+ // The database function handles page-level permissions without requiring full scope
228
+ // Only wait if we're using pageName (which needs appId to resolve) or if scope is critical
229
+ // For page-level permissions, organisationId and appId are optional
230
+ const hasPageId = !!pageId && typeof pageId === 'string';
231
+ const canProceedWithoutFullScope = hasPageId && !isPageName; // UUID pageId doesn't need appId
232
+
233
+ // Wait for scope resolution only if:
234
+ // 1. We're using pageName and don't have appId yet (needed to resolve pageName to pageId), OR
235
+ // 2. Scope is loading AND we don't have a UUID pageId (can't proceed without scope)
236
+ // This allows permission checks to start earlier for UUID pageIds, reducing load time
237
+ const shouldWaitForScope = (needsAppIdForResolution && !stableScope.appId) ||
238
+ (scopeLoading && !canProceedWithoutFullScope);
175
239
 
176
- const effectiveScope = (!shouldWaitForScope) ? stableScope : null;
240
+ // Use available scope immediately if we can proceed, otherwise wait
241
+ // For page-level permissions, empty scope is acceptable (database handles it)
242
+ const effectiveScope = (!shouldWaitForScope && (stableScope.organisationId || stableScope.appId || stableScope.eventId || canProceedWithoutFullScope))
243
+ ? stableScope
244
+ : (canProceedWithoutFullScope ? { organisationId: undefined, eventId: undefined, appId: undefined } : null);
177
245
 
178
246
  // Always call hooks with consistent parameters to avoid React hooks order violations
179
247
  const userId = user?.id || '';
@@ -189,28 +257,39 @@ export function useDataTablePermissions<TData extends DataRecord>(
189
257
  const consistentScope = effectiveScope || { organisationId: undefined, eventId: undefined, appId: undefined };
190
258
 
191
259
  // Check permissions using useCan hooks
260
+ // PERFORMANCE OPTIMIZATION: Pass precomputed super admin status to avoid duplicate checks
261
+ // Each useCan hook would normally check super admin separately (6+ queries), but we check once here
262
+ // and share the result. Pass null if not checked yet (hooks will check), false/true if checked.
192
263
  // Note: The database function already handles super admin bypass, but we check here
193
264
  // as an additional safety layer to prevent unnecessary permission checks and ensure
194
265
  // super admins never see "Access Denied" even if useCan hasn't completed
195
- const canReadResult = useCan(userId, consistentScope, readPermission, effectivePageId, true);
196
- const canCreateResult = useCan(userId, consistentScope, createPermission, effectivePageId, true);
197
- const canUpdateResult = useCan(userId, consistentScope, updatePermission, effectivePageId, true);
198
- const canDeleteResult = useCan(userId, consistentScope, deletePermission, effectivePageId, true);
199
- const canExportResult = useCan(userId, consistentScope, readPermission, effectivePageId, true); // Use read permission for export
200
- const canImportResult = useCan(userId, consistentScope, createPermission, effectivePageId, true); // Use create permission for import
266
+ // Pass super admin status directly - null means not checked yet, false/true means checked
267
+ // This eliminates duplicate super admin checks across all 6 permission hooks
268
+ const canReadResult = useCan(userId, consistentScope, readPermission, effectivePageId, true, isSuperAdminUser);
269
+ const canCreateResult = useCan(userId, consistentScope, createPermission, effectivePageId, true, isSuperAdminUser);
270
+ const canUpdateResult = useCan(userId, consistentScope, updatePermission, effectivePageId, true, isSuperAdminUser);
271
+ const canDeleteResult = useCan(userId, consistentScope, deletePermission, effectivePageId, true, isSuperAdminUser);
272
+ const canExportResult = useCan(userId, consistentScope, readPermission, effectivePageId, true, isSuperAdminUser); // Use read permission for export
273
+ const canImportResult = useCan(userId, consistentScope, createPermission, effectivePageId, true, isSuperAdminUser); // Use create permission for import
201
274
 
202
275
  // Create permission wrappers that bypass checks for super admins
203
276
  // Super admins get can: true for all permissions, but we preserve isLoading and error states
204
277
  // to maintain consistent API with useCan return type
278
+ // React 19 fix: Read isLoading directly from result objects to ensure we get the latest state
279
+ // instead of relying on memoized object references which may not update properly in React 19
205
280
  const permissions = useMemo(() => {
206
281
  // Helper to create a permission result that bypasses for super admins
207
282
  // If super admin check is still loading, we show loading state to prevent premature "Access Denied"
208
283
  // Once super admin check completes, if user is super admin, all permissions are true
209
284
  // Otherwise, use the normal permission check results
210
285
  const createSuperAdminAwarePermission = (result: ReturnType<typeof useCan>) => ({
211
- can: isSuperAdminUser ? true : result.can,
212
- // Show loading if super admin check is in progress OR if the underlying permission check is loading
213
- isLoading: isCheckingSuperAdmin || result.isLoading,
286
+ // If super admin check completed and user is super admin, grant all permissions
287
+ // Otherwise use the normal permission check result
288
+ // Use === true to distinguish between null (not checked) and false (checked, not super admin)
289
+ can: isSuperAdminUser === true ? true : result.can,
290
+ // Show loading if super admin check is in progress (null and checking) OR if the underlying permission check is loading
291
+ // React 19 fix: Read isLoading directly from the result object to ensure we get the latest state
292
+ isLoading: (isSuperAdminUser === null && isCheckingSuperAdmin) || result.isLoading,
214
293
  error: result.error,
215
294
  refetch: result.refetch,
216
295
  });
@@ -226,12 +305,25 @@ export function useDataTablePermissions<TData extends DataRecord>(
226
305
  }, [
227
306
  isSuperAdminUser,
228
307
  isCheckingSuperAdmin,
229
- canReadResult,
230
- canCreateResult,
231
- canUpdateResult,
232
- canDeleteResult,
233
- canExportResult,
234
- canImportResult,
308
+ // React 19 fix: Include individual properties instead of entire objects to ensure proper dependency tracking
309
+ canReadResult.can,
310
+ canReadResult.isLoading,
311
+ canReadResult.error,
312
+ canCreateResult.can,
313
+ canCreateResult.isLoading,
314
+ canCreateResult.error,
315
+ canUpdateResult.can,
316
+ canUpdateResult.isLoading,
317
+ canUpdateResult.error,
318
+ canDeleteResult.can,
319
+ canDeleteResult.isLoading,
320
+ canDeleteResult.error,
321
+ canExportResult.can,
322
+ canExportResult.isLoading,
323
+ canExportResult.error,
324
+ canImportResult.can,
325
+ canImportResult.isLoading,
326
+ canImportResult.error,
235
327
  ]);
236
328
 
237
329
  // MANDATORY: Features are automatically filtered by permissions
@@ -26,6 +26,12 @@ export type { DataRecord, CellValue, RowId };
26
26
  // STATE INTERFACE
27
27
  // ============================================================================
28
28
 
29
+ /**
30
+ * DataTable state interface.
31
+ * Contains all state for table operations including sorting, filtering, pagination, and editing.
32
+ *
33
+ * @template TData - The type of data records in the table
34
+ */
29
35
  export interface DataTableState<TData extends DataRecord> {
30
36
  // Table state
31
37
  sorting: SortingState;
@@ -53,6 +59,12 @@ export interface DataTableState<TData extends DataRecord> {
53
59
  searchQuery: string;
54
60
  }
55
61
 
62
+ /**
63
+ * Actions interface for DataTable state management.
64
+ * Provides functions to update all aspects of table state.
65
+ *
66
+ * @template TData - The type of data records in the table
67
+ */
56
68
  export interface DataTableStateActions<TData extends DataRecord> {
57
69
  setSorting: (sorting: SortingState) => void;
58
70
  setColumnFilters: (filters: ColumnFiltersState) => void;
@@ -78,6 +90,19 @@ export interface DataTableStateActions<TData extends DataRecord> {
78
90
  initializeState: (partialState: Partial<DataTableState<TData>>) => void;
79
91
  }
80
92
 
93
+ /**
94
+ * Computed values interface for DataTable.
95
+ * Provides derived state values that are computed from the table state.
96
+ */
97
+ export interface DataTableComputed {
98
+ hasSelection: boolean;
99
+ selectedRowIds: string[];
100
+ isEditing: boolean;
101
+ isCreating: boolean;
102
+ hasFilters: boolean;
103
+ canClearFilters: boolean;
104
+ }
105
+
81
106
  // ============================================================================
82
107
  // ACTION TYPES
83
108
  // ============================================================================
@@ -108,6 +133,15 @@ export type DataTableAction<TData extends DataRecord> =
108
133
  // REDUCER
109
134
  // ============================================================================
110
135
 
136
+ /**
137
+ * Reducer function for DataTable state management.
138
+ * Handles all state updates for the DataTable component.
139
+ *
140
+ * @template TData - The type of data records in the table
141
+ * @param state - Current table state
142
+ * @param action - Action to perform
143
+ * @returns New table state
144
+ */
111
145
  export function dataTableReducer<TData extends DataRecord>(
112
146
  state: DataTableState<TData>,
113
147
  action: DataTableAction<TData>
@@ -330,7 +364,7 @@ export function useDataTableState<TData extends DataRecord>({
330
364
  // COMPUTED VALUES
331
365
  // ============================================================================
332
366
 
333
- const computed = useMemo(() => ({
367
+ const computed = useMemo<DataTableComputed>(() => ({
334
368
  hasSelection: Object.values(state.rowSelection).some(Boolean),
335
369
  selectedRowIds: Object.entries(state.rowSelection)
336
370
  .filter(([_, selected]) => selected)
@@ -2,12 +2,24 @@ import { useMemo } from 'react';
2
2
 
3
3
  import type { DataRecord, DataTableColumn } from '../types';
4
4
 
5
+ /**
6
+ * Options for the useEffectiveColumnOrder hook.
7
+ * @template TData - The type of data records in the table
8
+ */
5
9
  interface UseEffectiveColumnOrderOptions<TData extends DataRecord> {
6
10
  columns: DataTableColumn<TData>[];
7
11
  externalColumnOrder?: string[];
8
12
  selectionEnabled: boolean;
9
13
  }
10
14
 
15
+ /**
16
+ * Hook to compute effective column order.
17
+ * Handles external column order and ensures selection column is first when enabled.
18
+ *
19
+ * @template TData - The type of data records in the table
20
+ * @param options - Column order configuration
21
+ * @returns Effective column order array
22
+ */
11
23
  export function useEffectiveColumnOrder<TData extends DataRecord>({
12
24
  columns,
13
25
  externalColumnOrder,
@@ -23,7 +23,7 @@ export interface KeyboardNavigationOptions {
23
23
  /** Callback when focus moves to a new cell */
24
24
  onFocusChange?: (rowIndex: number, columnIndex: number) => void;
25
25
  /** Table ref for DOM queries */
26
- tableRef?: React.RefObject<HTMLTableElement>;
26
+ tableRef?: React.RefObject<HTMLTableElement | null>;
27
27
  }
28
28
 
29
29
  export interface KeyboardNavigationState {
@@ -105,7 +105,7 @@ export function useKeyboardNavigation(
105
105
  const internalTableRef = useRef<HTMLTableElement>(null);
106
106
  const tableRef = externalTableRef || internalTableRef;
107
107
  const storedFocusRef = useRef<{ rowIndex: number; columnIndex: number } | null>(null);
108
- const navigationTimeoutRef = useRef<NodeJS.Timeout>();
108
+ const navigationTimeoutRef = useRef<NodeJS.Timeout>(undefined);
109
109
 
110
110
  // Helper to get cell element
111
111
  const getCellElement = useCallback((rowIndex: number, columnIndex: number): HTMLElement | null => {
@@ -16,6 +16,10 @@ import type {
16
16
  PaginationState,
17
17
  } from '@tanstack/react-table';
18
18
 
19
+ /**
20
+ * Parameters for the useServerSideDataEffect hook.
21
+ * @template TData - The type of data records in the table
22
+ */
19
23
  export interface UseServerSideDataEffectParams<TData extends DataRecord> {
20
24
  finalPaginationMode: PaginationMode;
21
25
  serverSide?: ServerSideConfig<TData>;
@@ -29,6 +33,13 @@ export interface UseServerSideDataEffectParams<TData extends DataRecord> {
29
33
  cleanup?: () => void;
30
34
  }
31
35
 
36
+ /**
37
+ * Hook for coordinating server-side data fetching.
38
+ * Triggers data fetches when table state changes in server-side pagination mode.
39
+ *
40
+ * @template TData - The type of data records in the table
41
+ * @param params - Server-side data effect configuration
42
+ */
32
43
  export function useServerSideDataEffect<TData extends DataRecord>({
33
44
  finalPaginationMode,
34
45
  serverSide,
@@ -21,6 +21,10 @@ import type {
21
21
  import type { ColumnDef } from '@tanstack/react-table';
22
22
  import type { HeaderContext, CellContext } from '@tanstack/react-table';
23
23
 
24
+ /**
25
+ * Options for the useTableColumns hook.
26
+ * @template TData - The type of data records in the table
27
+ */
24
28
  export interface UseTableColumnsOptions<TData extends DataRecord> {
25
29
  columns: DataTableColumn<TData>[];
26
30
  features: NormalizedDataTableFeatureConfig;
@@ -28,6 +32,10 @@ export interface UseTableColumnsOptions<TData extends DataRecord> {
28
32
  columnOrder: string[];
29
33
  }
30
34
 
35
+ /**
36
+ * Return value of the useTableColumns hook.
37
+ * @template TData - The type of data records in the table
38
+ */
31
39
  export interface UseTableColumnsReturn<TData extends DataRecord> {
32
40
  enhancedColumns: ColumnDef<TData>[];
33
41
  }
@@ -14,11 +14,21 @@ import type {
14
14
  DataTableStateActions,
15
15
  } from './useDataTableState';
16
16
 
17
+ /**
18
+ * Table layout change interface.
19
+ * Represents changes to column order and visibility.
20
+ */
17
21
  export interface TableLayoutChange {
18
22
  columnOrder: string[];
19
23
  columnVisibility: VisibilityState;
20
24
  }
21
25
 
26
+ /**
27
+ * Snapshot of table state at a point in time.
28
+ * Used for state persistence and restoration.
29
+ *
30
+ * @template TData - The type of data records in the table
31
+ */
22
32
  export interface TableStateSnapshot<TData extends DataRecord> {
23
33
  sorting: SortingState;
24
34
  columnFilters: ColumnFiltersState;
@@ -31,6 +41,10 @@ export interface TableStateSnapshot<TData extends DataRecord> {
31
41
  columnOrder: string[];
32
42
  }
33
43
 
44
+ /**
45
+ * Table event handlers interface.
46
+ * Provides handlers for all table state changes.
47
+ */
34
48
  export interface TableHandlers {
35
49
  onSortingChange: (updaterOrValue: unknown) => void;
36
50
  onColumnFiltersChange: (updaterOrValue: unknown) => void;
@@ -64,7 +64,7 @@ export const getTableCellClasses = (options: {
64
64
  isCompact?: boolean;
65
65
  isSortable?: boolean;
66
66
  className?: string;
67
- } = {}) => {
67
+ } = {}): string => {
68
68
  const { isVirtualized = false, isCompact = false, isSortable = false, className } = options;
69
69
 
70
70
  if (isVirtualized) {
@@ -88,7 +88,7 @@ export const getTableCellClasses = (options: {
88
88
  export const getTableHeadClasses = (options: {
89
89
  isSortable?: boolean;
90
90
  className?: string;
91
- } = {}) => {
91
+ } = {}): string => {
92
92
  const { isSortable = false, className } = options;
93
93
 
94
94
  return cn(
@@ -105,7 +105,7 @@ export const getTableRowClasses = (options: {
105
105
  isSelected?: boolean;
106
106
  isVirtualized?: boolean;
107
107
  className?: string;
108
- } = {}) => {
108
+ } = {}): string => {
109
109
  const { isSelected = false, isVirtualized = false, className } = options;
110
110
 
111
111
  if (isVirtualized) {
@@ -129,7 +129,7 @@ export const getTableRowClasses = (options: {
129
129
  export const getTableContainerClasses = (options: {
130
130
  isVirtualized?: boolean;
131
131
  className?: string;
132
- } = {}) => {
132
+ } = {}): string => {
133
133
  const { isVirtualized = false, className } = options;
134
134
 
135
135
  return cn(
@@ -145,7 +145,7 @@ export const getTableClasses = (options: {
145
145
  isFixed?: boolean;
146
146
  variant?: 'default' | 'compact' | 'spacious';
147
147
  className?: string;
148
- } = {}) => {
148
+ } = {}): string => {
149
149
  const { isFixed = false, variant = 'default', className } = options;
150
150
 
151
151
  if (isFixed) {
@@ -182,7 +182,7 @@ export const getTableClasses = (options: {
182
182
  */
183
183
  export const getMainContainerClasses = (options: {
184
184
  className?: string;
185
- } = {}) => {
185
+ } = {}): string => {
186
186
  const { className } = options;
187
187
 
188
188
  return cn(
@@ -55,16 +55,6 @@ export type RowId = string;
55
55
  */
56
56
  export type GetRowId<TData extends DataRecord> = (row: TData, index: number) => RowId;
57
57
 
58
- /**
59
- * Generic type for partial data updates
60
- */
61
- export type PartialDataRecord<TData extends DataRecord> = Partial<TData>;
62
-
63
- /**
64
- * Generic type for complete data records
65
- */
66
- export type CompleteDataRecord<TData extends DataRecord> = TData;
67
-
68
58
  // ============================================================================
69
59
  // HIERARCHICAL DATA TYPES
70
60
  // ============================================================================
@@ -393,6 +383,12 @@ export interface SimpleColumn<TData extends DataRecord = DataRecord> {
393
383
  */
394
384
  export type ActionCondition<TData extends DataRecord> = boolean | ((row: TData) => boolean);
395
385
 
386
+ /**
387
+ * Action definition for DataTable rows.
388
+ * Defines custom actions that can be performed on table rows.
389
+ *
390
+ * @template TData - The type of data records in the table
391
+ */
396
392
  export interface DataTableAction<TData extends DataRecord> {
397
393
  /** Display label for the action */
398
394
  label: string;
@@ -211,6 +211,13 @@ export function announceBulkOperation(operation: string, count: number): void {
211
211
  * Get ARIA sort value for column headers
212
212
  * @param sortDirection - Current sort direction
213
213
  */
214
+ /**
215
+ * Converts TanStack Table sort direction to ARIA sort value.
216
+ * Maps table sort states to accessible ARIA attributes.
217
+ *
218
+ * @param sortDirection - Sort direction from TanStack Table
219
+ * @returns ARIA sort value for accessibility
220
+ */
214
221
  export function getAriaSortValue(sortDirection: 'asc' | 'desc' | false): 'ascending' | 'descending' | 'none' {
215
222
  if (sortDirection === 'asc') return 'ascending';
216
223
  if (sortDirection === 'desc') return 'descending';