@jmruthers/pace-core 0.6.1 → 0.6.3

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 (549) hide show
  1. package/CHANGELOG.md +88 -10
  2. package/cursor-rules/00-pace-core-compliance.mdc +46 -87
  3. package/cursor-rules/01-standards-compliance.mdc +16 -47
  4. package/cursor-rules/02-project-structure.mdc +4 -4
  5. package/cursor-rules/03-solid-principles.mdc +45 -164
  6. package/cursor-rules/04-testing-standards.mdc +22 -69
  7. package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
  8. package/cursor-rules/06-code-quality.mdc +42 -125
  9. package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
  10. package/cursor-rules/08-markup-quality.mdc +452 -0
  11. package/cursor-rules/CHANGELOG.md +18 -0
  12. package/cursor-rules/README.md +2 -1
  13. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-Cb34EQs3.d.ts} +63 -1
  14. package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
  15. package/dist/{DataTable-DQ7RSOHE.js → DataTable-THFPBKTP.js} +12 -10
  16. package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DEMpysFR.d.ts} +394 -171
  17. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CKvHP1MK.d.ts} +30 -8
  18. package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-KAGUYQ4J.js} +5 -4
  19. package/dist/{api-N774RPUA.js → api-IAGWF3ZG.js} +10 -10
  20. package/dist/{audit-B5P6FFIR.js → audit-V53FV5AG.js} +2 -2
  21. package/dist/{chunk-JBKQ3SAO.js → chunk-2T2IG7T7.js} +107 -57
  22. package/dist/chunk-2T2IG7T7.js.map +1 -0
  23. package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
  24. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  25. package/dist/{chunk-3XTALGJF.js → chunk-6Z7LTB3D.js} +69 -240
  26. package/dist/chunk-6Z7LTB3D.js.map +1 -0
  27. package/dist/{chunk-4ZC4GX36.js → chunk-CNCQDFLN.js} +199 -46
  28. package/dist/chunk-CNCQDFLN.js.map +1 -0
  29. package/dist/chunk-DGUM43GV.js +11 -0
  30. package/dist/{chunk-BYFSK72L.js → chunk-DWUBLJJM.js} +361 -187
  31. package/dist/chunk-DWUBLJJM.js.map +1 -0
  32. package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
  33. package/dist/chunk-FFQEQTNW.js.map +1 -0
  34. package/dist/chunk-FMUCXFII.js +76 -0
  35. package/dist/chunk-FMUCXFII.js.map +1 -0
  36. package/dist/{chunk-4N5C5XZU.js → chunk-HFZBI76P.js} +4 -4
  37. package/dist/chunk-HFZBI76P.js.map +1 -0
  38. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  39. package/dist/chunk-L4OXEN46.js.map +1 -0
  40. package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
  41. package/dist/chunk-M43Y4SSO.js.map +1 -0
  42. package/dist/{chunk-I7PSE6JW.js → chunk-M7MPQISP.js} +3 -76
  43. package/dist/chunk-M7MPQISP.js.map +1 -0
  44. package/dist/chunk-PQBSKX33.js +7793 -0
  45. package/dist/chunk-PQBSKX33.js.map +1 -0
  46. package/dist/chunk-QRPVRXYT.js +226 -0
  47. package/dist/chunk-QRPVRXYT.js.map +1 -0
  48. package/dist/{chunk-KNC55RTG.js → chunk-RWEBCB47.js} +194 -416
  49. package/dist/chunk-RWEBCB47.js.map +1 -0
  50. package/dist/{chunk-XM25TVIE.js → chunk-YDQHOZNA.js} +843 -388
  51. package/dist/chunk-YDQHOZNA.js.map +1 -0
  52. package/dist/{chunk-GLK6VM3F.js → chunk-ZNIWI3UC.js} +739 -737
  53. package/dist/chunk-ZNIWI3UC.js.map +1 -0
  54. package/dist/components.d.ts +5 -5
  55. package/dist/components.js +18 -16
  56. package/dist/components.js.map +1 -1
  57. package/dist/contextValidator-3JNZKUTX.js +9 -0
  58. package/dist/contextValidator-3JNZKUTX.js.map +1 -0
  59. package/dist/eslint-rules/pace-core-compliance.cjs +106 -0
  60. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  61. package/dist/hooks.d.ts +55 -122
  62. package/dist/hooks.js +10 -13
  63. package/dist/hooks.js.map +1 -1
  64. package/dist/index.d.ts +60 -13
  65. package/dist/index.js +30 -25
  66. package/dist/index.js.map +1 -1
  67. package/dist/providers.d.ts +21 -3
  68. package/dist/providers.js +4 -3
  69. package/dist/rbac/index.d.ts +210 -139
  70. package/dist/rbac/index.js +17 -13
  71. package/dist/styles/index.js +1 -1
  72. package/dist/theming/runtime.d.ts +1 -13
  73. package/dist/theming/runtime.js +2 -2
  74. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  75. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  76. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  77. package/dist/types.d.ts +2 -2
  78. package/dist/types.js +1 -1
  79. package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-i3qtoBgg.d.ts} +38 -17
  80. package/dist/utils.d.ts +4 -5
  81. package/dist/utils.js +17 -19
  82. package/dist/utils.js.map +1 -1
  83. package/docs/api/README.md +21 -17
  84. package/docs/api/modules.md +4191 -2967
  85. package/docs/architecture/database-schema-requirements.md +161 -0
  86. package/docs/components/context-selector.md +126 -0
  87. package/docs/core-concepts/rbac-system.md +3 -3
  88. package/docs/documentation-index.md +2 -4
  89. package/docs/getting-started/cursor-rules.md +2 -1
  90. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  91. package/docs/migration/MIGRATION_GUIDE.md +2 -24
  92. package/docs/migration/RBAC_SCOPE_MIGRATION.md +385 -0
  93. package/docs/migration/README.md +52 -6
  94. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  95. package/docs/migration/database-changes-december-2025.md +3 -3
  96. package/docs/pace-mint-fix-auto-selection.md +218 -0
  97. package/docs/pace-mint-rbac-setup.md +391 -0
  98. package/docs/rbac/event-based-apps.md +1 -1
  99. package/docs/rbac/getting-started.md +1 -1
  100. package/docs/rbac/quick-start.md +1 -1
  101. package/docs/rbac/secure-client-protection.md +330 -0
  102. package/docs/standards/README.md +1 -0
  103. package/package.json +4 -3
  104. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  105. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  106. package/scripts/audit/core/checks/bundle.cjs +142 -0
  107. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +784 -685
  108. package/scripts/audit/core/checks/config.cjs +54 -0
  109. package/scripts/audit/core/checks/coverage.cjs +84 -0
  110. package/scripts/audit/core/checks/dependencies.cjs +985 -0
  111. package/scripts/audit/core/checks/documentation.cjs +268 -0
  112. package/scripts/audit/core/checks/environment.cjs +116 -0
  113. package/scripts/audit/core/checks/error-handling.cjs +340 -0
  114. package/scripts/audit/core/checks/forms.cjs +172 -0
  115. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  116. package/scripts/audit/core/checks/hooks.cjs +334 -0
  117. package/scripts/audit/core/checks/imports.cjs +244 -0
  118. package/scripts/audit/core/checks/performance.cjs +325 -0
  119. package/scripts/audit/core/checks/routes.cjs +117 -0
  120. package/scripts/audit/core/checks/state.cjs +130 -0
  121. package/scripts/audit/core/checks/structure.cjs +65 -0
  122. package/scripts/audit/core/checks/style.cjs +584 -0
  123. package/scripts/audit/core/checks/testing.cjs +122 -0
  124. package/scripts/audit/core/checks/typescript.cjs +61 -0
  125. package/scripts/audit/core/scanner.cjs +199 -0
  126. package/scripts/audit/core/utils.cjs +137 -0
  127. package/scripts/audit/index.cjs +223 -0
  128. package/scripts/audit/reporters/console.cjs +151 -0
  129. package/scripts/audit/reporters/json.cjs +54 -0
  130. package/scripts/audit/reporters/markdown.cjs +124 -0
  131. package/scripts/audit-consuming-app.cjs +61 -936
  132. package/scripts/build-docs/build-decision.js +240 -0
  133. package/scripts/build-docs/cache-utils.js +105 -0
  134. package/scripts/build-docs/content-normalization.js +150 -0
  135. package/scripts/build-docs/file-utils.js +105 -0
  136. package/scripts/build-docs/git-utils.js +86 -0
  137. package/scripts/build-docs/hash-utils.js +116 -0
  138. package/scripts/build-docs/typedoc-runner.js +220 -0
  139. package/scripts/build-docs-incremental.js +77 -913
  140. package/scripts/utils/command-runner.js +16 -11
  141. package/scripts/validate-formats.js +61 -56
  142. package/scripts/validate-master.js +74 -69
  143. package/scripts/validate-pre-publish.js +70 -65
  144. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  145. package/src/components/Alert/Alert.test.tsx +12 -18
  146. package/src/components/Alert/Alert.tsx +5 -7
  147. package/src/components/Avatar/Avatar.test.tsx +4 -4
  148. package/src/components/Badge/Badge.tsx +14 -0
  149. package/src/components/Button/Button.tsx +22 -0
  150. package/src/components/Calendar/Calendar.tsx +8 -2
  151. package/src/components/Card/Card.tsx +4 -0
  152. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  153. package/src/components/Checkbox/Checkbox.tsx +2 -2
  154. package/src/components/ContextSelector/ContextSelector.tsx +384 -0
  155. package/src/components/ContextSelector/index.ts +3 -0
  156. package/src/components/DataTable/DataTable.tsx +38 -4
  157. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  158. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
  159. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  160. package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
  161. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  162. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  163. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  164. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  165. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  166. package/src/components/DataTable/components/DataTableCore.tsx +196 -554
  167. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  168. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  169. package/src/components/DataTable/components/DataTableModals.tsx +8 -0
  170. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  171. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  172. package/src/components/DataTable/components/EditFields.tsx +307 -0
  173. package/src/components/DataTable/components/EditableRow.tsx +8 -0
  174. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  175. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  176. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  177. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  178. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  179. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  180. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  181. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  182. package/src/components/DataTable/components/UnifiedTableBody.tsx +63 -851
  183. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  184. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  185. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  186. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  187. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  188. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  189. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  190. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  191. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  192. package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
  193. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  194. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  195. package/src/components/DataTable/hooks/useDataTablePermissions.ts +127 -33
  196. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  197. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  198. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  199. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  200. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  201. package/src/components/DataTable/styles.ts +6 -6
  202. package/src/components/DataTable/types.ts +6 -10
  203. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  204. package/src/components/DataTable/utils/debugTools.ts +18 -113
  205. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  206. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  207. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  208. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  209. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  210. package/src/components/Dialog/Dialog.tsx +31 -3
  211. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  212. package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
  213. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  214. package/src/components/ErrorBoundary/index.ts +27 -2
  215. package/src/components/FileDisplay/FileDisplay.tsx +74 -28
  216. package/src/components/FileUpload/FileUpload.tsx +22 -2
  217. package/src/components/Footer/Footer.test.tsx +16 -16
  218. package/src/components/Footer/Footer.tsx +14 -11
  219. package/src/components/Form/Form.tsx +1 -0
  220. package/src/components/Header/Header.test.tsx +43 -73
  221. package/src/components/Header/Header.tsx +59 -49
  222. package/src/components/Input/Input.test.tsx +2 -2
  223. package/src/components/Input/Input.tsx +8 -4
  224. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  225. package/src/components/LoginForm/LoginForm.tsx +4 -0
  226. package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
  227. package/src/components/NavigationMenu/types.ts +56 -0
  228. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  229. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +10 -19
  230. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +2 -2
  231. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +5 -5
  232. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +13 -11
  233. package/src/components/PaceAppLayout/PaceAppLayout.tsx +167 -44
  234. package/src/components/PaceAppLayout/README.md +14 -17
  235. package/src/components/PaceAppLayout/test-setup.tsx +3 -4
  236. package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
  237. package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
  238. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  239. package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
  240. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  241. package/src/components/Select/Select.tsx +80 -434
  242. package/src/components/Select/context.ts +23 -0
  243. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  244. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  245. package/src/components/Select/hooks/useSelectState.ts +104 -0
  246. package/src/components/Select/index.ts +9 -1
  247. package/src/components/Select/types.ts +123 -0
  248. package/src/components/Select/utils/text.ts +26 -0
  249. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
  250. package/src/components/Switch/Switch.tsx +4 -4
  251. package/src/components/Tabs/Tabs.tsx +1 -1
  252. package/src/components/Toast/Toast.tsx +4 -0
  253. package/src/components/Tooltip/Tooltip.tsx +2 -2
  254. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  255. package/src/components/UserMenu/UserMenu.tsx +21 -18
  256. package/src/components/index.ts +7 -7
  257. package/src/eslint-rules/pace-core-compliance.cjs +106 -0
  258. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  259. package/src/hooks/__tests__/useAppConfig.unit.test.ts +4 -98
  260. package/src/hooks/index.ts +1 -2
  261. package/src/hooks/public/usePublicEvent.ts +4 -0
  262. package/src/hooks/public/usePublicEventLogo.ts +4 -0
  263. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  264. package/src/hooks/public/usePublicRouteParams.ts +4 -0
  265. package/src/hooks/services/useAuth.ts +32 -0
  266. package/src/hooks/services/useCurrentEvent.ts +6 -0
  267. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  268. package/src/hooks/useAppConfig.ts +15 -30
  269. package/src/hooks/useDebounce.ts +9 -0
  270. package/src/hooks/useEventTheme.ts +6 -0
  271. package/src/hooks/useFileDisplay.ts +81 -50
  272. package/src/hooks/useFileReference.ts +25 -7
  273. package/src/hooks/useFileUrl.ts +11 -1
  274. package/src/hooks/useFocusManagement.ts +14 -0
  275. package/src/hooks/useFocusTrap.ts +3 -0
  276. package/src/hooks/useInactivityTracker.ts +3 -0
  277. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  278. package/src/hooks/useOrganisationPermissions.ts +4 -0
  279. package/src/hooks/useOrganisationSecurity.ts +4 -0
  280. package/src/hooks/usePerformanceMonitor.ts +4 -0
  281. package/src/hooks/usePermissionCache.ts +7 -0
  282. package/src/hooks/useQueryCache.ts +12 -1
  283. package/src/hooks/useSessionRestoration.ts +4 -0
  284. package/src/hooks/useStorage.ts +4 -0
  285. package/src/hooks/useToast.ts +1 -1
  286. package/src/index.ts +6 -6
  287. package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
  288. package/src/providers/services/AuthServiceProvider.tsx +35 -7
  289. package/src/providers/services/EventServiceProvider.tsx +51 -5
  290. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  291. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +126 -134
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
  294. package/src/rbac/README.md +1 -1
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +1 -1
  296. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  297. package/src/rbac/adapters.tsx +12 -3
  298. package/src/rbac/api.test.ts +59 -51
  299. package/src/rbac/api.ts +246 -167
  300. package/src/rbac/components/NavigationProvider.tsx +4 -1
  301. package/src/rbac/components/PagePermissionGuard.tsx +185 -17
  302. package/src/rbac/components/RoleBasedRouter.tsx +5 -1
  303. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  304. package/src/rbac/components/SecureDataProvider.tsx +20 -5
  305. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  306. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  307. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  308. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  309. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  310. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  311. package/src/rbac/engine.ts +38 -14
  312. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +32 -21
  313. package/src/rbac/hooks/permissions/index.ts +7 -0
  314. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  315. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  316. package/src/rbac/hooks/permissions/useCan.ts +377 -0
  317. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  318. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  319. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  320. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  321. package/src/rbac/hooks/useCan.test.ts +64 -66
  322. package/src/rbac/hooks/usePermissions.ts +14 -995
  323. package/src/rbac/hooks/useRBAC.test.ts +1 -5
  324. package/src/rbac/hooks/useRBAC.ts +36 -37
  325. package/src/rbac/hooks/useResolvedScope.test.ts +120 -35
  326. package/src/rbac/hooks/useResolvedScope.ts +35 -40
  327. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  328. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  329. package/src/rbac/hooks/useSecureSupabase.ts +27 -7
  330. package/src/rbac/index.ts +7 -0
  331. package/src/rbac/permissions.ts +0 -30
  332. package/src/rbac/secureClient.test.ts +22 -18
  333. package/src/rbac/secureClient.ts +294 -68
  334. package/src/rbac/security.ts +0 -17
  335. package/src/rbac/types.ts +9 -0
  336. package/src/rbac/utils/__tests__/contextValidator.test.ts +64 -86
  337. package/src/rbac/utils/clientSecurity.ts +93 -0
  338. package/src/rbac/utils/contextValidator.ts +77 -168
  339. package/src/services/AuthService.ts +39 -7
  340. package/src/services/EventService.ts +186 -54
  341. package/src/services/OrganisationService.ts +81 -14
  342. package/src/services/__tests__/EventService.test.ts +1 -2
  343. package/src/services/base/BaseService.ts +3 -0
  344. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  345. package/src/theming/parseEventColours.ts +5 -19
  346. package/src/types/vitest-globals.d.ts +51 -26
  347. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  348. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  349. package/src/utils/__tests__/index.unit.test.ts +2 -2
  350. package/src/utils/audit/audit.ts +0 -3
  351. package/src/utils/core/cn.ts +1 -1
  352. package/src/utils/dynamic/dynamicUtils.ts +7 -4
  353. package/src/utils/file-reference/index.ts +53 -1
  354. package/src/utils/formatting/formatting.ts +8 -18
  355. package/src/utils/index.ts +0 -1
  356. package/dist/chunk-3QRJFVBR.js.map +0 -1
  357. package/dist/chunk-3XTALGJF.js.map +0 -1
  358. package/dist/chunk-4N5C5XZU.js.map +0 -1
  359. package/dist/chunk-4ZC4GX36.js.map +0 -1
  360. package/dist/chunk-7D4SUZUM.js +0 -38
  361. package/dist/chunk-BYFSK72L.js.map +0 -1
  362. package/dist/chunk-EXUD6RNJ.js +0 -451
  363. package/dist/chunk-EXUD6RNJ.js.map +0 -1
  364. package/dist/chunk-GLK6VM3F.js.map +0 -1
  365. package/dist/chunk-I7PSE6JW.js.map +0 -1
  366. package/dist/chunk-JBKQ3SAO.js.map +0 -1
  367. package/dist/chunk-KNC55RTG.js.map +0 -1
  368. package/dist/chunk-LXQLPRQ2.js.map +0 -1
  369. package/dist/chunk-R77UEZ4E.js.map +0 -1
  370. package/dist/chunk-SQGMNID3.js.map +0 -1
  371. package/dist/chunk-T33XF5ZC.js +0 -12922
  372. package/dist/chunk-T33XF5ZC.js.map +0 -1
  373. package/dist/chunk-XM25TVIE.js.map +0 -1
  374. package/docs/api/classes/ColumnFactory.md +0 -243
  375. package/docs/api/classes/ErrorBoundary.md +0 -144
  376. package/docs/api/classes/InvalidScopeError.md +0 -73
  377. package/docs/api/classes/Logger.md +0 -178
  378. package/docs/api/classes/MissingUserContextError.md +0 -66
  379. package/docs/api/classes/OrganisationContextRequiredError.md +0 -66
  380. package/docs/api/classes/PermissionDeniedError.md +0 -73
  381. package/docs/api/classes/RBACAuditManager.md +0 -297
  382. package/docs/api/classes/RBACCache.md +0 -322
  383. package/docs/api/classes/RBACEngine.md +0 -171
  384. package/docs/api/classes/RBACError.md +0 -76
  385. package/docs/api/classes/RBACNotInitializedError.md +0 -66
  386. package/docs/api/classes/SecureSupabaseClient.md +0 -160
  387. package/docs/api/classes/StorageUtils.md +0 -328
  388. package/docs/api/enums/FileCategory.md +0 -184
  389. package/docs/api/enums/LogLevel.md +0 -54
  390. package/docs/api/enums/RBACErrorCode.md +0 -228
  391. package/docs/api/enums/RPCFunction.md +0 -118
  392. package/docs/api/interfaces/AddressFieldProps.md +0 -241
  393. package/docs/api/interfaces/AddressFieldRef.md +0 -94
  394. package/docs/api/interfaces/AggregateConfig.md +0 -43
  395. package/docs/api/interfaces/AutocompleteOptions.md +0 -75
  396. package/docs/api/interfaces/AvatarProps.md +0 -128
  397. package/docs/api/interfaces/BadgeProps.md +0 -27
  398. package/docs/api/interfaces/ButtonProps.md +0 -53
  399. package/docs/api/interfaces/CalendarProps.md +0 -70
  400. package/docs/api/interfaces/CardProps.md +0 -66
  401. package/docs/api/interfaces/ColorPalette.md +0 -7
  402. package/docs/api/interfaces/ColorShade.md +0 -66
  403. package/docs/api/interfaces/ComplianceResult.md +0 -30
  404. package/docs/api/interfaces/DataAccessRecord.md +0 -96
  405. package/docs/api/interfaces/DataRecord.md +0 -11
  406. package/docs/api/interfaces/DataTableAction.md +0 -249
  407. package/docs/api/interfaces/DataTableColumn.md +0 -504
  408. package/docs/api/interfaces/DataTableProps.md +0 -625
  409. package/docs/api/interfaces/DataTableToolbarButton.md +0 -96
  410. package/docs/api/interfaces/DatabaseComplianceResult.md +0 -85
  411. package/docs/api/interfaces/DatabaseIssue.md +0 -41
  412. package/docs/api/interfaces/EmptyStateConfig.md +0 -61
  413. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +0 -235
  414. package/docs/api/interfaces/EventAppRoleData.md +0 -71
  415. package/docs/api/interfaces/ExportColumn.md +0 -90
  416. package/docs/api/interfaces/ExportOptions.md +0 -126
  417. package/docs/api/interfaces/FileDisplayProps.md +0 -249
  418. package/docs/api/interfaces/FileMetadata.md +0 -129
  419. package/docs/api/interfaces/FileReference.md +0 -118
  420. package/docs/api/interfaces/FileSizeLimits.md +0 -7
  421. package/docs/api/interfaces/FileUploadOptions.md +0 -139
  422. package/docs/api/interfaces/FileUploadProps.md +0 -293
  423. package/docs/api/interfaces/FooterProps.md +0 -105
  424. package/docs/api/interfaces/FormFieldProps.md +0 -166
  425. package/docs/api/interfaces/FormProps.md +0 -113
  426. package/docs/api/interfaces/GrantEventAppRoleParams.md +0 -122
  427. package/docs/api/interfaces/InactivityWarningModalProps.md +0 -115
  428. package/docs/api/interfaces/InputProps.md +0 -53
  429. package/docs/api/interfaces/LabelProps.md +0 -107
  430. package/docs/api/interfaces/LoggerConfig.md +0 -62
  431. package/docs/api/interfaces/LoginFormProps.md +0 -184
  432. package/docs/api/interfaces/NavigationAccessRecord.md +0 -107
  433. package/docs/api/interfaces/NavigationContextType.md +0 -164
  434. package/docs/api/interfaces/NavigationGuardProps.md +0 -139
  435. package/docs/api/interfaces/NavigationItem.md +0 -120
  436. package/docs/api/interfaces/NavigationMenuProps.md +0 -221
  437. package/docs/api/interfaces/NavigationProviderProps.md +0 -117
  438. package/docs/api/interfaces/Organisation.md +0 -140
  439. package/docs/api/interfaces/OrganisationContextType.md +0 -388
  440. package/docs/api/interfaces/OrganisationMembership.md +0 -140
  441. package/docs/api/interfaces/OrganisationProviderProps.md +0 -76
  442. package/docs/api/interfaces/OrganisationSecurityError.md +0 -62
  443. package/docs/api/interfaces/PaceAppLayoutProps.md +0 -406
  444. package/docs/api/interfaces/PaceLoginPageProps.md +0 -47
  445. package/docs/api/interfaces/PageAccessRecord.md +0 -85
  446. package/docs/api/interfaces/PagePermissionContextType.md +0 -140
  447. package/docs/api/interfaces/PagePermissionGuardProps.md +0 -153
  448. package/docs/api/interfaces/PagePermissionProviderProps.md +0 -119
  449. package/docs/api/interfaces/PaletteData.md +0 -41
  450. package/docs/api/interfaces/ParsedAddress.md +0 -120
  451. package/docs/api/interfaces/PermissionEnforcerProps.md +0 -153
  452. package/docs/api/interfaces/ProgressProps.md +0 -42
  453. package/docs/api/interfaces/ProtectedRouteProps.md +0 -97
  454. package/docs/api/interfaces/PublicPageFooterProps.md +0 -112
  455. package/docs/api/interfaces/PublicPageHeaderProps.md +0 -125
  456. package/docs/api/interfaces/PublicPageLayoutProps.md +0 -198
  457. package/docs/api/interfaces/QuickFix.md +0 -52
  458. package/docs/api/interfaces/RBACAccessValidateParams.md +0 -52
  459. package/docs/api/interfaces/RBACAccessValidateResult.md +0 -41
  460. package/docs/api/interfaces/RBACAuditLogParams.md +0 -85
  461. package/docs/api/interfaces/RBACAuditLogResult.md +0 -52
  462. package/docs/api/interfaces/RBACConfig.md +0 -133
  463. package/docs/api/interfaces/RBACContext.md +0 -52
  464. package/docs/api/interfaces/RBACLogger.md +0 -112
  465. package/docs/api/interfaces/RBACPageAccessCheckParams.md +0 -74
  466. package/docs/api/interfaces/RBACPerformanceMetrics.md +0 -138
  467. package/docs/api/interfaces/RBACPermissionCheckParams.md +0 -74
  468. package/docs/api/interfaces/RBACPermissionCheckResult.md +0 -52
  469. package/docs/api/interfaces/RBACPermissionsGetParams.md +0 -63
  470. package/docs/api/interfaces/RBACPermissionsGetResult.md +0 -63
  471. package/docs/api/interfaces/RBACResult.md +0 -58
  472. package/docs/api/interfaces/RBACRoleGrantParams.md +0 -63
  473. package/docs/api/interfaces/RBACRoleGrantResult.md +0 -52
  474. package/docs/api/interfaces/RBACRoleRevokeParams.md +0 -63
  475. package/docs/api/interfaces/RBACRoleRevokeResult.md +0 -52
  476. package/docs/api/interfaces/RBACRoleValidateParams.md +0 -52
  477. package/docs/api/interfaces/RBACRoleValidateResult.md +0 -63
  478. package/docs/api/interfaces/RBACRolesListParams.md +0 -52
  479. package/docs/api/interfaces/RBACRolesListResult.md +0 -74
  480. package/docs/api/interfaces/RBACSessionTrackParams.md +0 -74
  481. package/docs/api/interfaces/RBACSessionTrackResult.md +0 -52
  482. package/docs/api/interfaces/ResourcePermissions.md +0 -155
  483. package/docs/api/interfaces/RevokeEventAppRoleParams.md +0 -100
  484. package/docs/api/interfaces/RoleBasedRouterContextType.md +0 -151
  485. package/docs/api/interfaces/RoleBasedRouterProps.md +0 -156
  486. package/docs/api/interfaces/RoleManagementResult.md +0 -52
  487. package/docs/api/interfaces/RouteAccessRecord.md +0 -107
  488. package/docs/api/interfaces/RouteConfig.md +0 -134
  489. package/docs/api/interfaces/RuntimeComplianceResult.md +0 -55
  490. package/docs/api/interfaces/SecureDataContextType.md +0 -168
  491. package/docs/api/interfaces/SecureDataProviderProps.md +0 -132
  492. package/docs/api/interfaces/SessionRestorationLoaderProps.md +0 -34
  493. package/docs/api/interfaces/SetupIssue.md +0 -41
  494. package/docs/api/interfaces/StorageConfig.md +0 -41
  495. package/docs/api/interfaces/StorageFileInfo.md +0 -74
  496. package/docs/api/interfaces/StorageFileMetadata.md +0 -151
  497. package/docs/api/interfaces/StorageListOptions.md +0 -99
  498. package/docs/api/interfaces/StorageListResult.md +0 -41
  499. package/docs/api/interfaces/StorageUploadOptions.md +0 -101
  500. package/docs/api/interfaces/StorageUploadResult.md +0 -63
  501. package/docs/api/interfaces/StorageUrlOptions.md +0 -60
  502. package/docs/api/interfaces/StyleImport.md +0 -19
  503. package/docs/api/interfaces/SwitchProps.md +0 -34
  504. package/docs/api/interfaces/TabsContentProps.md +0 -9
  505. package/docs/api/interfaces/TabsListProps.md +0 -9
  506. package/docs/api/interfaces/TabsProps.md +0 -9
  507. package/docs/api/interfaces/TabsTriggerProps.md +0 -50
  508. package/docs/api/interfaces/TextareaProps.md +0 -53
  509. package/docs/api/interfaces/ToastActionElement.md +0 -9
  510. package/docs/api/interfaces/ToastProps.md +0 -9
  511. package/docs/api/interfaces/UnifiedAuthContextType.md +0 -820
  512. package/docs/api/interfaces/UnifiedAuthProviderProps.md +0 -171
  513. package/docs/api/interfaces/UseFormDialogOptions.md +0 -62
  514. package/docs/api/interfaces/UseFormDialogReturn.md +0 -117
  515. package/docs/api/interfaces/UseInactivityTrackerOptions.md +0 -136
  516. package/docs/api/interfaces/UseInactivityTrackerReturn.md +0 -123
  517. package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
  518. package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -81
  519. package/docs/api/interfaces/UsePublicEventOptions.md +0 -34
  520. package/docs/api/interfaces/UsePublicEventReturn.md +0 -68
  521. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +0 -47
  522. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +0 -120
  523. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +0 -94
  524. package/docs/api/interfaces/UseResolvedScopeOptions.md +0 -47
  525. package/docs/api/interfaces/UseResolvedScopeReturn.md +0 -47
  526. package/docs/api/interfaces/UseResourcePermissionsOptions.md +0 -34
  527. package/docs/api/interfaces/UserEventAccess.md +0 -118
  528. package/docs/api/interfaces/UserMenuProps.md +0 -86
  529. package/docs/api/interfaces/UserProfile.md +0 -63
  530. package/docs/migration/quick-migration-guide.md +0 -356
  531. package/docs/migration/service-architecture.md +0 -281
  532. package/src/components/EventSelector/EventSelector.test.tsx +0 -720
  533. package/src/components/EventSelector/EventSelector.tsx +0 -420
  534. package/src/components/EventSelector/index.ts +0 -3
  535. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +0 -784
  536. package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -324
  537. package/src/components/OrganisationSelector/index.ts +0 -9
  538. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  539. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  540. package/src/hooks/useSecureDataAccess.ts +0 -681
  541. /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-THFPBKTP.js.map} +0 -0
  542. /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-KAGUYQ4J.js.map} +0 -0
  543. /package/dist/{api-N774RPUA.js.map → api-IAGWF3ZG.js.map} +0 -0
  544. /package/dist/{audit-B5P6FFIR.js.map → audit-V53FV5AG.js.map} +0 -0
  545. /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
  546. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  547. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  548. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  549. /package/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
@@ -34,7 +34,7 @@
34
34
  * ```
35
35
  */
36
36
 
37
- import { useState, useEffect, useCallback } from 'react';
37
+ import { useState, useEffect, useCallback, useRef } from 'react';
38
38
  import type { SupabaseClient } from '@supabase/supabase-js';
39
39
  import { FileReference, FileCategory } from '../types/file-reference';
40
40
  import { getPublicUrl, getSignedUrl, generateFileUrlsBatch } from '../utils/storage/helpers';
@@ -71,6 +71,10 @@ function cleanupCache() {
71
71
  }
72
72
  }
73
73
 
74
+ /**
75
+ * Return value of the useFileDisplay hook.
76
+ * Provides file URLs, references, loading state, error, and refetch function.
77
+ */
74
78
  export interface UseFileDisplayReturn {
75
79
  /** Single file URL if category is provided and file found, null otherwise */
76
80
  fileUrl: string | null;
@@ -134,14 +138,25 @@ export function useFileDisplay(
134
138
  const [isLoading, setIsLoading] = useState<boolean>(false);
135
139
  const [error, setError] = useState<Error | null>(null);
136
140
 
141
+ // Ref to track if component is mounted and effect is active
142
+ // This prevents state updates from stale async operations
143
+ const isMountedRef = useRef(true);
144
+
145
+ // Helper to safely set state only if component is still mounted
146
+ const safeSetState = <T,>(setter: (value: T) => void, value: T) => {
147
+ if (isMountedRef.current) {
148
+ setter(value);
149
+ }
150
+ };
151
+
137
152
  const fetchFiles = useCallback(async (): Promise<void> => {
138
153
  if (!table_name || !record_id || !supabase) {
139
- setFileUrl(null);
140
- setFileReference(null);
141
- setFileReferences([]);
142
- setFileUrls(new Map());
143
- setFileCount(0);
144
- setIsLoading(false);
154
+ safeSetState(setFileUrl, null);
155
+ safeSetState(setFileReference, null);
156
+ safeSetState(setFileReferences, []);
157
+ safeSetState(setFileUrls, new Map());
158
+ safeSetState(setFileCount, 0);
159
+ safeSetState(setIsLoading, false);
145
160
  return;
146
161
  }
147
162
 
@@ -173,13 +188,13 @@ export function useFileDisplay(
173
188
  expiresIn: 3600
174
189
  });
175
190
  const regeneratedUrl = signedUrlResult?.url || null;
176
- setFileUrl(regeneratedUrl);
177
- setFileReference(cachedData.fileReference);
178
- setFileReferences(cachedData.fileReferences || []);
179
- setFileUrls(cachedData.fileUrls || new Map());
180
- setFileCount(cachedData.fileCount || 0);
181
- setIsLoading(false);
182
- setError(null);
191
+ safeSetState(setFileUrl, regeneratedUrl);
192
+ safeSetState(setFileReference, cachedData.fileReference);
193
+ safeSetState(setFileReferences, cachedData.fileReferences || []);
194
+ safeSetState(setFileUrls, cachedData.fileUrls || new Map());
195
+ safeSetState(setFileCount, cachedData.fileCount || 0);
196
+ safeSetState(setIsLoading, false);
197
+ safeSetState(setError, null);
183
198
  return;
184
199
  } catch (err) {
185
200
  // If signed URL regeneration fails, fall through to normal fetch
@@ -188,20 +203,20 @@ export function useFileDisplay(
188
203
  }
189
204
 
190
205
  // Normal cache hit for public files or files with URLs
191
- setFileUrl(cachedData.fileUrl || null);
192
- setFileReference(cachedData.fileReference || null);
193
- setFileReferences(cachedData.fileReferences || []);
194
- setFileUrls(cachedData.fileUrls || new Map());
195
- setFileCount(cachedData.fileCount || 0);
196
- setIsLoading(false);
197
- setError(null);
206
+ safeSetState(setFileUrl, cachedData.fileUrl || null);
207
+ safeSetState(setFileReference, cachedData.fileReference || null);
208
+ safeSetState(setFileReferences, cachedData.fileReferences || []);
209
+ safeSetState(setFileUrls, cachedData.fileUrls || new Map());
210
+ safeSetState(setFileCount, cachedData.fileCount || 0);
211
+ safeSetState(setIsLoading, false);
212
+ safeSetState(setError, null);
198
213
  return;
199
214
  }
200
215
  }
201
216
 
202
217
  try {
203
- setIsLoading(true);
204
- setError(null);
218
+ safeSetState(setIsLoading, true);
219
+ safeSetState(setError, null);
205
220
 
206
221
  const service = createFileReferenceService(supabase);
207
222
  let files: FileReference[] = [];
@@ -481,11 +496,11 @@ export function useFileDisplay(
481
496
  }
482
497
 
483
498
  if (files.length === 0) {
484
- setFileUrl(null);
485
- setFileReference(null);
486
- setFileReferences([]);
487
- setFileUrls(new Map());
488
- setFileCount(0);
499
+ safeSetState(setFileUrl, null);
500
+ safeSetState(setFileReference, null);
501
+ safeSetState(setFileReferences, []);
502
+ safeSetState(setFileUrls, new Map());
503
+ safeSetState(setFileCount, 0);
489
504
 
490
505
  // Cache empty result
491
506
  if (enableCache) {
@@ -499,14 +514,14 @@ export function useFileDisplay(
499
514
  return;
500
515
  }
501
516
 
502
- setFileReferences(files);
503
- setFileCount(files.length);
517
+ safeSetState(setFileReferences, files);
518
+ safeSetState(setFileCount, files.length);
504
519
 
505
520
  if (category && files.length > 0) {
506
521
  // Single file mode - get first file
507
522
  const firstFile = files[0];
508
523
  // Removed verbose debug logs - only log on errors
509
- setFileReference(firstFile);
524
+ safeSetState(setFileReference, firstFile);
510
525
 
511
526
  // Generate URL based on file visibility
512
527
  let url: string | null = null;
@@ -529,7 +544,7 @@ export function useFileDisplay(
529
544
  });
530
545
  }
531
546
  }
532
- setFileUrl(url);
547
+ safeSetState(setFileUrl, url);
533
548
  } else {
534
549
  // Multiple files mode - generate URLs for all files in batch
535
550
  const urlMap = await generateFileUrlsBatch(supabase, files, {
@@ -538,9 +553,9 @@ export function useFileDisplay(
538
553
  userId: organisation_id ? undefined : record_id,
539
554
  expiresIn: 3600
540
555
  });
541
- setFileUrls(urlMap);
542
- setFileReference(null);
543
- setFileUrl(null);
556
+ safeSetState(setFileUrls, urlMap);
557
+ safeSetState(setFileReference, null);
558
+ safeSetState(setFileUrl, null);
544
559
  }
545
560
 
546
561
  // Cache the result
@@ -584,30 +599,46 @@ export function useFileDisplay(
584
599
  } catch (err) {
585
600
  logger.error('useFileDisplay', 'Error fetching files:', err);
586
601
  const error = err instanceof Error ? err : new Error('Unknown error occurred');
587
- setError(error);
588
- setFileUrl(null);
589
- setFileReference(null);
590
- setFileReferences([]);
591
- setFileUrls(new Map());
592
- setFileCount(0);
602
+ safeSetState(setError, error);
603
+ safeSetState(setFileUrl, null);
604
+ safeSetState(setFileReference, null);
605
+ safeSetState(setFileReferences, []);
606
+ safeSetState(setFileUrls, new Map());
607
+ safeSetState(setFileCount, 0);
593
608
  } finally {
594
- setIsLoading(false);
609
+ safeSetState(setIsLoading, false);
595
610
  }
596
611
  }, [table_name, record_id, organisation_id, category, supabase, cacheTtl, enableCache]);
597
612
 
598
613
  // Fetch files when parameters change
599
614
  useEffect(() => {
615
+ // Mark as mounted when effect runs
616
+ isMountedRef.current = true;
617
+
600
618
  if (table_name && record_id && supabase) {
601
- fetchFiles();
619
+ // Call fetchFiles - it will check isMountedRef before setting state
620
+ fetchFiles().catch((err) => {
621
+ // Only set error if component is still mounted
622
+ if (isMountedRef.current) {
623
+ safeSetState(setError, err instanceof Error ? err : new Error('Unknown error'));
624
+ }
625
+ });
602
626
  } else {
603
- setFileUrl(null);
604
- setFileReference(null);
605
- setFileReferences([]);
606
- setFileUrls(new Map());
607
- setFileCount(0);
608
- setIsLoading(false);
609
- setError(null);
627
+ // Only update state if component is still mounted
628
+ safeSetState(setFileUrl, null);
629
+ safeSetState(setFileReference, null);
630
+ safeSetState(setFileReferences, []);
631
+ safeSetState(setFileUrls, new Map());
632
+ safeSetState(setFileCount, 0);
633
+ safeSetState(setIsLoading, false);
634
+ safeSetState(setError, null);
610
635
  }
636
+
637
+ // Cleanup: mark as unmounted when dependencies change or component unmounts
638
+ // This prevents state updates from stale requests
639
+ return () => {
640
+ isMountedRef.current = false;
641
+ };
611
642
  // fetchFiles is memoized; we only need to re-run when parameters change
612
643
  // eslint-disable-next-line react-hooks/exhaustive-deps
613
644
  }, [table_name, record_id, organisation_id, supabase]);
@@ -59,6 +59,13 @@ const urlRefreshManager = {
59
59
  }
60
60
  };
61
61
 
62
+ /**
63
+ * Hook for managing file references.
64
+ * Provides file upload, retrieval, and URL generation functionality.
65
+ *
66
+ * @param supabase - Supabase client instance
67
+ * @returns File reference service with upload, get, and URL methods
68
+ */
62
69
  export function useFileReference(supabase: SupabaseClient) {
63
70
  const [isLoading, setIsLoading] = useState(false);
64
71
  const [error, setError] = useState<string | null>(null);
@@ -385,13 +392,18 @@ export function useFileReferenceById(
385
392
  }
386
393
 
387
394
  const loadUrl = async () => {
388
- const service = createFileReferenceService(supabase);
389
- const url = await service.getFileUrl(
390
- fileReference.table_name,
391
- fileReference.record_id,
392
- organisationId
393
- );
394
- setFileUrl(url);
395
+ try {
396
+ const service = createFileReferenceService(supabase);
397
+ const url = await service.getFileUrl(
398
+ fileReference.table_name,
399
+ fileReference.record_id,
400
+ organisationId
401
+ );
402
+ setFileUrl(url);
403
+ } catch (error) {
404
+ // Silently fail - component will handle missing URL
405
+ setFileUrl(null);
406
+ }
395
407
  };
396
408
 
397
409
  loadUrl();
@@ -478,6 +490,9 @@ export type UseFileReferenceOptions = {
478
490
  organisation_id: string;
479
491
  };
480
492
 
493
+ /**
494
+ * Return value of the useFileReference hook.
495
+ */
481
496
  export type UseFileReferenceReturn = {
482
497
  isLoading: boolean;
483
498
  error: string | null;
@@ -492,6 +507,9 @@ export type UseFileReferenceReturn = {
492
507
  clearError: () => void;
493
508
  };
494
509
 
510
+ /**
511
+ * Return value of the useFileReferenceForRecord hook.
512
+ */
495
513
  export type UseFileReferenceForRecordReturn = {
496
514
  isLoading: boolean;
497
515
  error: string | null;
@@ -15,11 +15,14 @@ import { createLogger } from '../utils/core/logger';
15
15
 
16
16
  const log = createLogger('useFileUrl');
17
17
 
18
+ /**
19
+ * Options for the useFileUrl hook.
20
+ */
18
21
  export interface UseFileUrlOptions {
19
22
  /** Organisation ID for signed URL generation */
20
23
  organisation_id: string | undefined;
21
24
  /** Supabase client instance */
22
- supabase: SupabaseClient;
25
+ supabase: SupabaseClient | null;
23
26
  /** Whether to auto-load URLs on mount */
24
27
  autoLoad?: boolean;
25
28
  }
@@ -63,6 +66,13 @@ export function useFileUrl(
63
66
  return;
64
67
  }
65
68
 
69
+ if (!supabase) {
70
+ setUrl(null);
71
+ setIsLoading(false);
72
+ setError(new Error('Supabase client is required for URL generation'));
73
+ return;
74
+ }
75
+
66
76
  // Skip if already loading or URL already exists for this file
67
77
  if (isLoading || (url && fileReferenceIdRef.current === fileReference.id)) {
68
78
  return;
@@ -1,6 +1,9 @@
1
1
 
2
2
  import { useRef, useCallback, useEffect } from 'react';
3
3
 
4
+ /**
5
+ * Options for the useFocusManagement hook.
6
+ */
4
7
  export interface FocusManagementOptions {
5
8
  trapFocus?: boolean;
6
9
  autoFocus?: boolean;
@@ -10,6 +13,10 @@ export interface FocusManagementOptions {
10
13
  onFocusLast?: () => void;
11
14
  }
12
15
 
16
+ /**
17
+ * Return value of the useFocusManagement hook.
18
+ * Provides focus management utilities for accessible components.
19
+ */
13
20
  export interface FocusManagementReturn {
14
21
  containerRef: React.RefObject<HTMLDivElement | null>;
15
22
  focusRef: React.RefObject<HTMLElement | null>;
@@ -22,6 +29,13 @@ export interface FocusManagementReturn {
22
29
  handleEscape: (callback: () => void) => () => void;
23
30
  }
24
31
 
32
+ /**
33
+ * Hook for managing focus in accessible components.
34
+ * Provides focus trapping, restoration, and navigation utilities.
35
+ *
36
+ * @param options - Focus management configuration
37
+ * @returns Focus management utilities and refs
38
+ */
25
39
  export function useFocusManagement(options: FocusManagementOptions = {}): FocusManagementReturn {
26
40
  const {
27
41
  trapFocus = false,
@@ -1,6 +1,9 @@
1
1
 
2
2
  import { useRef, useEffect, useCallback } from 'react';
3
3
 
4
+ /**
5
+ * Options for the useFocusTrap hook.
6
+ */
4
7
  export interface FocusTrapOptions {
5
8
  /** Whether the focus trap is active */
6
9
  isActive?: boolean;
@@ -55,6 +55,9 @@
55
55
  import { useState, useEffect, useCallback, useRef } from 'react';
56
56
  import { logger } from '../utils/core/logger';
57
57
 
58
+ /**
59
+ * Options for the useInactivityTracker hook.
60
+ */
58
61
  export interface UseInactivityTrackerOptions {
59
62
  /** Timeout in milliseconds before user is considered idle (default: 30 minutes) */
60
63
  idleTimeoutMs?: number;
@@ -1,5 +1,9 @@
1
1
  import { useEffect, useCallback } from 'react';
2
2
 
3
+ /**
4
+ * Keyboard shortcut definition.
5
+ * Defines a key combination and its handler function.
6
+ */
3
7
  export interface KeyboardShortcut {
4
8
  /** Key combination (e.g., 'Escape', 'Enter', 'ArrowDown', 'ctrl+s') */
5
9
  key: string;
@@ -50,6 +50,10 @@ import { useOrganisations } from './useOrganisations';
50
50
  import { useOrganisationSecurity } from './useOrganisationSecurity';
51
51
  import type { OrganisationRole, OrganisationPermission } from '../types/organisation';
52
52
 
53
+ /**
54
+ * Return value of the useOrganisationPermissions hook.
55
+ * Provides organisation-specific permissions and role information.
56
+ */
53
57
  export interface UseOrganisationPermissionsReturn {
54
58
  /** User's role in the organisation */
55
59
  userRole: OrganisationRole | 'no_access';
@@ -16,6 +16,10 @@ import type { OrganisationSecurityError, SuperAdminContext } from '../types/orga
16
16
  import type { Permission } from '../rbac/types';
17
17
  import { logger } from '../utils/core/logger';
18
18
 
19
+ /**
20
+ * Organisation security hook interface.
21
+ * Provides security utilities for organisation access validation and super admin functionality.
22
+ */
19
23
  export interface OrganisationSecurityHook {
20
24
  // Super admin context
21
25
  superAdminContext: SuperAdminContext;
@@ -5,6 +5,10 @@ import { createLogger } from '../utils/core/logger';
5
5
 
6
6
  const log = createLogger('usePerformanceMonitor');
7
7
 
8
+ /**
9
+ * Performance metrics interface.
10
+ * Represents performance measurement data for components or operations.
11
+ */
8
12
  export interface PerformanceMetrics {
9
13
  renderTime: number;
10
14
  componentName: string;
@@ -103,6 +103,13 @@ const DEFAULT_CONFIG: CacheConfig = {
103
103
  enableAuditTrail: true
104
104
  };
105
105
 
106
+ /**
107
+ * Hook for centralized permission caching.
108
+ * Provides intelligent caching with automatic invalidation for permission checks.
109
+ *
110
+ * @param config - Optional cache configuration
111
+ * @returns Permission cache utilities including check functions and debug info
112
+ */
106
113
  export function usePermissionCache(config: Partial<CacheConfig> = {}) {
107
114
  const mergedConfig = useMemo(() => ({ ...DEFAULT_CONFIG, ...config }), [config]);
108
115
 
@@ -127,6 +127,13 @@ export interface UseQueryCacheReturn {
127
127
  * );
128
128
  * ```
129
129
  */
130
+ /**
131
+ * Hook for in-memory query result caching.
132
+ * Provides caching for frequently accessed data to eliminate duplicate queries.
133
+ *
134
+ * @param supabase - Optional Supabase client instance
135
+ * @returns Query cache utilities including get, invalidate, and clear functions
136
+ */
130
137
  export function useQueryCache(supabase?: SupabaseClient<Database>): UseQueryCacheReturn {
131
138
  const getCachedQuery = useCallback(async <T,>(
132
139
  table: string,
@@ -218,7 +225,11 @@ export function useQueryCache(supabase?: SupabaseClient<Database>): UseQueryCach
218
225
  /**
219
226
  * Pre-configured cache helpers for common queries
220
227
  */
221
- export const queryCacheHelpers = {
228
+ export const queryCacheHelpers: {
229
+ pacePersonByUserId: <T>(supabase: SupabaseClient<Database>, userId: string, fetchFn: () => Promise<T>) => Promise<T>;
230
+ paceMemberByPersonId: <T>(supabase: SupabaseClient<Database>, personId: string, fetchFn: () => Promise<T>) => Promise<T>;
231
+ rbacAppPagesByAppId: <T>(supabase: SupabaseClient<Database>, appId: string, fetchFn: () => Promise<T>) => Promise<T>;
232
+ } = {
222
233
  /**
223
234
  * Cache core_person queries by user_id
224
235
  * TTL: 5 minutes
@@ -18,6 +18,10 @@ const log = createLogger('useSessionRestoration');
18
18
 
19
19
  const SESSION_RESTORATION_TIMEOUT_MS = 5000;
20
20
 
21
+ /**
22
+ * Return value of the useSessionRestoration hook.
23
+ * Extends SessionRestorationState with timeout information.
24
+ */
21
25
  export interface UseSessionRestorationResult extends SessionRestorationState {
22
26
  /** Indicates whether the restoration process exceeded the timeout window */
23
27
  hasTimedOut: boolean;
@@ -27,6 +27,10 @@ export interface UseStorageOptions {
27
27
  orgId: string;
28
28
  }
29
29
 
30
+ /**
31
+ * Return value of the useStorage hook.
32
+ * Provides storage operations including upload, URL generation, file management, and listing.
33
+ */
30
34
  export interface UseStorageReturn {
31
35
  // Upload
32
36
  uploadFile: (file: File, options?: Partial<StorageUploadOptions>) => Promise<StorageUploadResult>;
@@ -71,7 +71,7 @@ const listeners: Array<(state: State) => void> = []
71
71
  /**
72
72
  * Reset the toast state and clear all timeouts
73
73
  */
74
- export function reset() {
74
+ export function reset(): void {
75
75
  memoryState = { toasts: [] }
76
76
  toastTimeouts.forEach((timeout) => clearTimeout(timeout))
77
77
  toastTimeouts.clear()
package/src/index.ts CHANGED
@@ -224,16 +224,16 @@ export { ProtectedRoute } from './components/ProtectedRoute/ProtectedRoute';
224
224
  export type { ProtectedRouteProps } from './components/ProtectedRoute/ProtectedRoute';
225
225
 
226
226
  // UTILITY COMPONENTS
227
- export { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary';
227
+ export { ErrorBoundary, ErrorBoundaryProvider } from './components/ErrorBoundary';
228
+ export type { ErrorBoundaryProps, ErrorBoundaryState, ErrorBoundaryProviderProps, GlobalErrorHandler } from './components/ErrorBoundary';
228
229
  export { LoadingSpinner } from './components/LoadingSpinner/LoadingSpinner';
229
230
  export { SessionRestorationLoader } from './components/SessionRestorationLoader/SessionRestorationLoader';
230
231
  export type { SessionRestorationLoaderProps } from './components/SessionRestorationLoader/SessionRestorationLoader';
231
232
 
232
- // EVENT MANAGEMENT
233
- export { EventSelector } from './components/EventSelector/EventSelector';
234
-
235
- // ORGANISATION MANAGEMENT
236
- export { OrganisationSelector } from './components/OrganisationSelector/OrganisationSelector';
233
+ // CONTEXT SELECTION
234
+ // Unified context selector (shows all accessible orgs and events)
235
+ export { ContextSelector } from './components/ContextSelector/ContextSelector';
236
+ export type { ContextSelectorProps } from './components/ContextSelector/ContextSelector';
237
237
  export { useOrganisationPermissions } from './hooks/useOrganisationPermissions';
238
238
  export { useOrganisationSecurity } from './hooks/useOrganisationSecurity';
239
239
  export { createSecureDataAccess } from './utils/security/secureDataAccess';