@jmruthers/pace-core 0.5.189 → 0.5.190

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 (420) hide show
  1. package/core-usage-manifest.json +0 -4
  2. package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
  3. package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
  4. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
  5. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  6. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
  7. package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
  8. package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
  9. package/dist/chunk-4QYC5L4K.js.map +1 -0
  10. package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
  11. package/dist/chunk-73HSNNOQ.js.map +1 -0
  12. package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
  13. package/dist/chunk-DZWK57KZ.js.map +1 -0
  14. package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
  15. package/dist/chunk-HQVPB5MZ.js.map +1 -0
  16. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  17. package/dist/chunk-HW3OVDUF.js.map +1 -0
  18. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  19. package/dist/chunk-I7PSE6JW.js.map +1 -0
  20. package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
  21. package/dist/chunk-J2XXC7R5.js.map +1 -0
  22. package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
  23. package/dist/chunk-NIU6J6OX.js.map +1 -0
  24. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  25. package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
  26. package/dist/chunk-RUYZKXOD.js.map +1 -0
  27. package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
  28. package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
  29. package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
  30. package/dist/chunk-STYK4OH2.js.map +1 -0
  31. package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
  32. package/dist/chunk-VVBAW5A5.js.map +1 -0
  33. package/dist/chunk-Y4BUBBHD.js +614 -0
  34. package/dist/chunk-Y4BUBBHD.js.map +1 -0
  35. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  36. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  37. package/dist/components.d.ts +3 -4
  38. package/dist/components.js +19 -19
  39. package/dist/components.js.map +1 -1
  40. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  41. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  42. package/dist/hooks.d.ts +10 -5
  43. package/dist/hooks.js +14 -8
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +13 -11
  46. package/dist/index.js +79 -69
  47. package/dist/index.js.map +1 -1
  48. package/dist/providers.d.ts +3 -3
  49. package/dist/providers.js +3 -1
  50. package/dist/rbac/index.d.ts +76 -12
  51. package/dist/rbac/index.js +12 -9
  52. package/dist/types.d.ts +1 -1
  53. package/dist/types.js +1 -1
  54. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
  55. package/dist/utils.js +16 -16
  56. package/docs/README.md +2 -2
  57. package/docs/api/classes/ColumnFactory.md +1 -1
  58. package/docs/api/classes/ErrorBoundary.md +1 -1
  59. package/docs/api/classes/InvalidScopeError.md +2 -2
  60. package/docs/api/classes/Logger.md +1 -1
  61. package/docs/api/classes/MissingUserContextError.md +2 -2
  62. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  63. package/docs/api/classes/PermissionDeniedError.md +1 -1
  64. package/docs/api/classes/RBACAuditManager.md +1 -1
  65. package/docs/api/classes/RBACCache.md +1 -1
  66. package/docs/api/classes/RBACEngine.md +4 -4
  67. package/docs/api/classes/RBACError.md +1 -1
  68. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  69. package/docs/api/classes/SecureSupabaseClient.md +21 -16
  70. package/docs/api/classes/StorageUtils.md +7 -4
  71. package/docs/api/enums/FileCategory.md +1 -1
  72. package/docs/api/enums/LogLevel.md +1 -1
  73. package/docs/api/enums/RBACErrorCode.md +1 -1
  74. package/docs/api/enums/RPCFunction.md +1 -1
  75. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  76. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  77. package/docs/api/interfaces/AggregateConfig.md +1 -1
  78. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  79. package/docs/api/interfaces/AvatarProps.md +1 -1
  80. package/docs/api/interfaces/BadgeProps.md +1 -1
  81. package/docs/api/interfaces/ButtonProps.md +1 -1
  82. package/docs/api/interfaces/CalendarProps.md +20 -6
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/ComplianceResult.md +1 -1
  87. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  88. package/docs/api/interfaces/DataRecord.md +1 -1
  89. package/docs/api/interfaces/DataTableAction.md +1 -1
  90. package/docs/api/interfaces/DataTableColumn.md +1 -1
  91. package/docs/api/interfaces/DataTableProps.md +1 -1
  92. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  93. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  94. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  95. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  96. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  97. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  98. package/docs/api/interfaces/ExportColumn.md +1 -1
  99. package/docs/api/interfaces/ExportOptions.md +1 -1
  100. package/docs/api/interfaces/FileDisplayProps.md +62 -16
  101. package/docs/api/interfaces/FileMetadata.md +1 -1
  102. package/docs/api/interfaces/FileReference.md +2 -2
  103. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  104. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  105. package/docs/api/interfaces/FileUploadProps.md +30 -19
  106. package/docs/api/interfaces/FooterProps.md +1 -1
  107. package/docs/api/interfaces/FormFieldProps.md +1 -1
  108. package/docs/api/interfaces/FormProps.md +1 -1
  109. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  110. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  111. package/docs/api/interfaces/InputProps.md +1 -1
  112. package/docs/api/interfaces/LabelProps.md +1 -1
  113. package/docs/api/interfaces/LoggerConfig.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  116. package/docs/api/interfaces/NavigationContextType.md +9 -9
  117. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  118. package/docs/api/interfaces/NavigationItem.md +1 -1
  119. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  120. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  121. package/docs/api/interfaces/Organisation.md +1 -1
  122. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  123. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  124. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  125. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  126. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  127. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  128. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  129. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  130. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  131. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  132. package/docs/api/interfaces/PaletteData.md +1 -1
  133. package/docs/api/interfaces/ParsedAddress.md +1 -1
  134. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  135. package/docs/api/interfaces/ProgressProps.md +3 -11
  136. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  137. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  138. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  139. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  140. package/docs/api/interfaces/QuickFix.md +1 -1
  141. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  142. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  143. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  144. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  145. package/docs/api/interfaces/RBACConfig.md +1 -1
  146. package/docs/api/interfaces/RBACContext.md +1 -1
  147. package/docs/api/interfaces/RBACLogger.md +1 -1
  148. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  149. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  150. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  151. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  152. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  153. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  154. package/docs/api/interfaces/RBACResult.md +1 -1
  155. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  156. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  157. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  158. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  160. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  161. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  162. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  163. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  164. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  165. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  166. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  167. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  168. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  169. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  170. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  171. package/docs/api/interfaces/RouteConfig.md +10 -10
  172. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  173. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  174. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  175. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  176. package/docs/api/interfaces/SetupIssue.md +1 -1
  177. package/docs/api/interfaces/StorageConfig.md +4 -4
  178. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  179. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  180. package/docs/api/interfaces/StorageListOptions.md +22 -9
  181. package/docs/api/interfaces/StorageListResult.md +4 -4
  182. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  183. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  184. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  185. package/docs/api/interfaces/StyleImport.md +1 -1
  186. package/docs/api/interfaces/SwitchProps.md +1 -1
  187. package/docs/api/interfaces/TabsContentProps.md +1 -1
  188. package/docs/api/interfaces/TabsListProps.md +1 -1
  189. package/docs/api/interfaces/TabsProps.md +1 -1
  190. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  191. package/docs/api/interfaces/TextareaProps.md +1 -1
  192. package/docs/api/interfaces/ToastActionElement.md +1 -1
  193. package/docs/api/interfaces/ToastProps.md +1 -1
  194. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  195. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  196. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  197. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  198. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  199. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  200. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  201. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  202. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  203. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  205. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  207. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  208. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  209. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  210. package/docs/api/interfaces/UserEventAccess.md +11 -11
  211. package/docs/api/interfaces/UserMenuProps.md +1 -1
  212. package/docs/api/interfaces/UserProfile.md +1 -1
  213. package/docs/api/modules.md +151 -92
  214. package/docs/api-reference/components.md +15 -7
  215. package/docs/api-reference/providers.md +2 -2
  216. package/docs/api-reference/rpc-functions.md +1 -0
  217. package/docs/best-practices/README.md +1 -1
  218. package/docs/best-practices/deployment.md +8 -8
  219. package/docs/getting-started/examples/README.md +2 -2
  220. package/docs/getting-started/installation-guide.md +4 -4
  221. package/docs/getting-started/quick-start.md +3 -3
  222. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  223. package/docs/rbac/compliance/compliance-guide.md +2 -2
  224. package/docs/rbac/event-based-apps.md +2 -2
  225. package/docs/rbac/getting-started.md +2 -2
  226. package/docs/rbac/quick-start.md +2 -2
  227. package/docs/security/README.md +4 -4
  228. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  229. package/docs/troubleshooting/README.md +2 -2
  230. package/docs/troubleshooting/migration.md +3 -3
  231. package/package.json +1 -3
  232. package/scripts/check-pace-core-compliance.cjs +1 -1
  233. package/scripts/check-pace-core-compliance.js +1 -1
  234. package/src/__tests__/fixtures/supabase.ts +301 -0
  235. package/src/__tests__/public-recipe-view.test.ts +9 -9
  236. package/src/__tests__/rls-policies.test.ts +197 -61
  237. package/src/components/AddressField/AddressField.test.tsx +42 -0
  238. package/src/components/AddressField/AddressField.tsx +71 -60
  239. package/src/components/AddressField/README.md +1 -0
  240. package/src/components/Alert/Alert.test.tsx +50 -10
  241. package/src/components/Alert/Alert.tsx +5 -3
  242. package/src/components/Avatar/Avatar.test.tsx +95 -43
  243. package/src/components/Avatar/Avatar.tsx +16 -16
  244. package/src/components/Button/Button.test.tsx +2 -1
  245. package/src/components/Button/Button.tsx +3 -3
  246. package/src/components/Calendar/Calendar.test.tsx +53 -37
  247. package/src/components/Calendar/Calendar.tsx +409 -82
  248. package/src/components/Card/Card.test.tsx +7 -4
  249. package/src/components/Card/Card.tsx +3 -6
  250. package/src/components/Checkbox/Checkbox.tsx +2 -2
  251. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  252. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  253. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  254. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  255. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  256. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  257. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  258. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  259. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  260. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  261. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  262. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  264. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  265. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  266. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  267. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  268. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  269. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  270. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  271. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  272. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  273. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  274. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  275. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  276. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  277. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  278. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  280. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  281. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  282. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  283. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  284. package/src/components/Dialog/Dialog.tsx +2 -2
  285. package/src/components/EventSelector/EventSelector.tsx +7 -7
  286. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  287. package/src/components/FileUpload/FileUpload.tsx +7 -4
  288. package/src/components/Header/Header.test.tsx +28 -0
  289. package/src/components/Header/Header.tsx +22 -9
  290. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  291. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  292. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  293. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  294. package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
  295. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  296. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  297. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  298. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  299. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  300. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  301. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  302. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  303. package/src/components/Progress/Progress.test.tsx +18 -19
  304. package/src/components/Progress/Progress.tsx +31 -32
  305. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  306. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  307. package/src/components/Select/Select.tsx +5 -5
  308. package/src/components/Switch/Switch.test.tsx +2 -1
  309. package/src/components/Switch/Switch.tsx +1 -1
  310. package/src/components/Toast/Toast.tsx +1 -1
  311. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  312. package/src/components/UserMenu/UserMenu.tsx +3 -3
  313. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  314. package/src/eslint-rules/pace-core-compliance.js +0 -2
  315. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  316. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  317. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  318. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  319. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  320. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  321. package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
  322. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  323. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
  324. package/src/hooks/index.ts +1 -1
  325. package/src/hooks/public/usePublicEvent.ts +2 -2
  326. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  327. package/src/hooks/useAppConfig.ts +24 -5
  328. package/src/hooks/useFileDisplay.ts +297 -34
  329. package/src/hooks/useFileReference.ts +56 -11
  330. package/src/hooks/useFileUrl.ts +1 -1
  331. package/src/hooks/useInactivityTracker.ts +16 -7
  332. package/src/hooks/usePermissionCache.test.ts +85 -8
  333. package/src/hooks/useQueryCache.ts +21 -0
  334. package/src/hooks/useSecureDataAccess.test.ts +80 -35
  335. package/src/hooks/useSecureDataAccess.ts +80 -37
  336. package/src/providers/services/EventServiceProvider.tsx +37 -17
  337. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  338. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  339. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  340. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  341. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  342. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  343. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  344. package/src/rbac/api.ts +240 -36
  345. package/src/rbac/cache-invalidation.ts +21 -7
  346. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  347. package/src/rbac/components/NavigationGuard.tsx +23 -63
  348. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  349. package/src/rbac/components/NavigationProvider.tsx +13 -11
  350. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  351. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  352. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  353. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  354. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  355. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  356. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  357. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  358. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  359. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  360. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  361. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  362. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  363. package/src/rbac/engine.ts +4 -2
  364. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  365. package/src/rbac/hooks/index.ts +3 -0
  366. package/src/rbac/hooks/useCan.test.ts +101 -53
  367. package/src/rbac/hooks/usePermissions.ts +108 -41
  368. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  369. package/src/rbac/hooks/useRBAC.ts +83 -40
  370. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  371. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  372. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  373. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  374. package/src/rbac/request-deduplication.ts +1 -1
  375. package/src/rbac/secureClient.ts +72 -12
  376. package/src/rbac/security.ts +29 -23
  377. package/src/rbac/types.ts +10 -0
  378. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  379. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  380. package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
  381. package/src/rbac/utils/contextValidator.ts +288 -0
  382. package/src/rbac/utils/eventContext.ts +48 -2
  383. package/src/services/EventService.ts +165 -21
  384. package/src/services/OrganisationService.ts +37 -2
  385. package/src/services/__tests__/EventService.test.ts +26 -21
  386. package/src/types/file-reference.ts +13 -10
  387. package/src/utils/app/appNameResolver.test.ts +346 -73
  388. package/src/utils/context/superAdminOverride.ts +58 -0
  389. package/src/utils/file-reference/index.ts +61 -33
  390. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  391. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  392. package/src/utils/storage/helpers.test.ts +1 -1
  393. package/src/utils/storage/helpers.ts +38 -19
  394. package/src/utils/storage/types.ts +15 -8
  395. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  396. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  397. package/src/vite-env.d.ts +2 -2
  398. package/dist/chunk-3GOZZZYH.js.map +0 -1
  399. package/dist/chunk-DDM4CCYT.js.map +0 -1
  400. package/dist/chunk-E7UAOUMY.js +0 -75
  401. package/dist/chunk-E7UAOUMY.js.map +0 -1
  402. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  403. package/dist/chunk-HEHYGYOX.js.map +0 -1
  404. package/dist/chunk-IM4QE42D.js.map +0 -1
  405. package/dist/chunk-MX64ZF6I.js.map +0 -1
  406. package/dist/chunk-SAUPYVLF.js.map +0 -1
  407. package/dist/chunk-THRPYOFK.js.map +0 -1
  408. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  409. package/dist/chunk-VGZZXKBR.js.map +0 -1
  410. package/dist/chunk-YGPFYGA6.js.map +0 -1
  411. package/dist/chunk-YHCN776L.js.map +0 -1
  412. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  413. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  414. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
  415. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  416. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
  417. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
  418. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
  419. /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
  420. /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
package/dist/index.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  withAccessLevelGuard,
41
41
  withPermissionGuard,
42
42
  withRoleGuard
43
- } from "./chunk-IM4QE42D.js";
43
+ } from "./chunk-73HSNNOQ.js";
44
44
  import {
45
45
  AddressField,
46
46
  Avatar,
@@ -92,7 +92,7 @@ import {
92
92
  useFileReferenceById,
93
93
  useFileReferenceForRecord,
94
94
  useFilesByCategory
95
- } from "./chunk-YGPFYGA6.js";
95
+ } from "./chunk-VVBAW5A5.js";
96
96
  import {
97
97
  Alert,
98
98
  AlertDescription,
@@ -142,7 +142,7 @@ import {
142
142
  max,
143
143
  min,
144
144
  sum
145
- } from "./chunk-2UUZZJFT.js";
145
+ } from "./chunk-SDMHPX3X.js";
146
146
  import {
147
147
  SecureSupabaseClient,
148
148
  createSecureClient,
@@ -155,50 +155,10 @@ import {
155
155
  useMultiplePermissions,
156
156
  usePermissions,
157
157
  useRBAC,
158
- useResolvedScope,
159
158
  useResourcePermissions,
160
159
  useRoleManagement,
161
160
  useSecureSupabase
162
- } from "./chunk-3GOZZZYH.js";
163
- import {
164
- CACHE_PATTERNS,
165
- RBACCache,
166
- RBACEngine,
167
- clearInFlightRequests,
168
- createRBACConfig,
169
- createRBACEngine,
170
- disablePerformanceMonitoring,
171
- enablePerformanceMonitoring,
172
- getAccessLevel,
173
- getInFlightRequestCount,
174
- getPerformanceMetrics,
175
- getPerformanceSummary,
176
- getPermissionMap,
177
- getRBACConfig,
178
- getRBACLogger,
179
- getRoleContext,
180
- hasAllPermissions,
181
- hasAnyPermission,
182
- hasPermission,
183
- isDebugMode,
184
- isDevelopmentMode,
185
- isPerformanceMonitoringEnabled,
186
- isPermitted,
187
- isPermittedCached,
188
- rbacCache,
189
- recordAuditEvent,
190
- recordPermissionCheck,
191
- resetPerformanceMetrics,
192
- resolveAppContext,
193
- setupRBAC
194
- } from "./chunk-HEHYGYOX.js";
195
- import {
196
- RBACAuditManager,
197
- createAuditManager,
198
- emitAuditEvent,
199
- getGlobalAuditManager,
200
- setGlobalAuditManager
201
- } from "./chunk-63FOKYGO.js";
161
+ } from "./chunk-HQVPB5MZ.js";
202
162
  import {
203
163
  StorageUtils,
204
164
  clearPublicEventCache,
@@ -215,14 +175,12 @@ import {
215
175
  usePublicEventLogo,
216
176
  usePublicRouteParams,
217
177
  useZodForm
218
- } from "./chunk-MX64ZF6I.js";
219
- import "./chunk-DDM4CCYT.js";
178
+ } from "./chunk-STYK4OH2.js";
179
+ import "./chunk-4QYC5L4K.js";
220
180
  import {
221
181
  APP_PATH_MAPPING,
222
182
  DEFAULT_FILE_SIZE_LIMIT,
223
- ErrorBoundary,
224
183
  FILE_SIZE_LIMITS,
225
- PublicPageProvider,
226
184
  STORAGE_CONFIG,
227
185
  archiveFile,
228
186
  clearPublicFileDisplayCache,
@@ -239,20 +197,23 @@ import {
239
197
  getSignedUrl,
240
198
  listFiles,
241
199
  uploadFile,
242
- useAppConfig,
243
200
  useEventTheme,
244
- useIsPublicPage,
245
201
  usePublicFileDisplay,
246
- usePublicPageContext,
247
202
  validateFileSize
248
- } from "./chunk-UCQSRW7Z.js";
203
+ } from "./chunk-NIU6J6OX.js";
249
204
  import {
250
205
  useToast
251
206
  } from "./chunk-6C4YBBJM.js";
252
207
  import {
208
+ ErrorBoundary,
209
+ PublicPageProvider,
210
+ useAppConfig,
253
211
  useEvents,
254
- useOrganisations
255
- } from "./chunk-E7UAOUMY.js";
212
+ useIsPublicPage,
213
+ usePublicPageContext,
214
+ useResolvedScope,
215
+ useSuperAdminBypass
216
+ } from "./chunk-Y4BUBBHD.js";
256
217
  import "./chunk-KQCRWDSA.js";
257
218
  import {
258
219
  EventServiceProvider,
@@ -263,12 +224,52 @@ import {
263
224
  useEventService,
264
225
  useInactivityService,
265
226
  useOrganisationService,
227
+ useOrganisations,
266
228
  useSessionRestoration,
267
229
  useUnifiedAuth
268
- } from "./chunk-VGZZXKBR.js";
230
+ } from "./chunk-J2XXC7R5.js";
231
+ import {
232
+ CACHE_PATTERNS,
233
+ RBACCache,
234
+ RBACEngine,
235
+ clearInFlightRequests,
236
+ createRBACConfig,
237
+ createRBACEngine,
238
+ disablePerformanceMonitoring,
239
+ enablePerformanceMonitoring,
240
+ getAccessLevel,
241
+ getInFlightRequestCount,
242
+ getPerformanceMetrics,
243
+ getPerformanceSummary,
244
+ getPermissionMap,
245
+ getRBACConfig,
246
+ getRBACLogger,
247
+ getRoleContext,
248
+ hasAllPermissions,
249
+ hasAnyPermission,
250
+ hasPermission,
251
+ isDebugMode,
252
+ isDevelopmentMode,
253
+ isPerformanceMonitoringEnabled,
254
+ isPermitted,
255
+ isPermittedCached,
256
+ rbacCache,
257
+ recordAuditEvent,
258
+ recordPermissionCheck,
259
+ resetPerformanceMetrics,
260
+ resolveAppContext,
261
+ setupRBAC
262
+ } from "./chunk-RUYZKXOD.js";
263
+ import {
264
+ RBACAuditManager,
265
+ createAuditManager,
266
+ emitAuditEvent,
267
+ getGlobalAuditManager,
268
+ setGlobalAuditManager
269
+ } from "./chunk-63FOKYGO.js";
269
270
  import {
270
271
  FileCategory
271
- } from "./chunk-SAUPYVLF.js";
272
+ } from "./chunk-ZSAAAMVR.js";
272
273
  import "./chunk-QXHPKYJV.js";
273
274
  import {
274
275
  emailSchema,
@@ -289,7 +290,7 @@ import {
289
290
  setAppConfig,
290
291
  urlSchema,
291
292
  useSessionTracking
292
- } from "./chunk-HESYZWZW.js";
293
+ } from "./chunk-QWWZ5CAQ.js";
293
294
  import {
294
295
  LoadingSpinner,
295
296
  formatInTimeZone,
@@ -300,12 +301,12 @@ import {
300
301
  getUserTimeZone,
301
302
  roundToNearestMinutes,
302
303
  toZonedTime
303
- } from "./chunk-THRPYOFK.js";
304
+ } from "./chunk-HW3OVDUF.js";
304
305
  import {
305
306
  cn
306
307
  } from "./chunk-R77UEZ4E.js";
307
- import "./chunk-F2IMUDXZ.js";
308
- import "./chunk-YHCN776L.js";
308
+ import "./chunk-DZWK57KZ.js";
309
+ import "./chunk-I7PSE6JW.js";
309
310
  import "./chunk-VBXEHIUJ.js";
310
311
  import {
311
312
  getAllStylePaths,
@@ -386,7 +387,7 @@ function InactivityWarningModal({
386
387
  children: [
387
388
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
388
389
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
389
- /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx2(AlertTriangle, { className: "h-6 w-6 text-acc-600" }) }),
390
+ /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx2(AlertTriangle, { className: "size-6 text-acc-600" }) }),
390
391
  /* @__PURE__ */ jsx2("div", { children: /* @__PURE__ */ jsx2(DialogTitle, { className: "text-lg font-semibold text-main-900", children: title }) })
391
392
  ] }),
392
393
  /* @__PURE__ */ jsx2(DialogDescription, { className: "text-main-700 mt-2", children: description })
@@ -394,7 +395,7 @@ function InactivityWarningModal({
394
395
  /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
395
396
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
396
397
  /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 px-4 py-3 bg-acc-50 border border-acc-200 rounded-lg", children: [
397
- /* @__PURE__ */ jsx2(Clock, { className: "h-5 w-5 text-acc-600" }),
398
+ /* @__PURE__ */ jsx2(Clock, { className: "size-5 text-acc-600" }),
398
399
  /* @__PURE__ */ jsx2("span", { className: "text-2xl font-mono font-bold text-acc-700", children: formatTime2(displayTime) })
399
400
  ] }),
400
401
  /* @__PURE__ */ jsx2("p", { className: "text-sm text-main-600 mt-2", children: "Time remaining before automatic logout" })
@@ -486,6 +487,14 @@ function useInactivityTracker({
486
487
  const lastActivityRef = useRef(Date.now());
487
488
  const channelRef = useRef(null);
488
489
  const throttledResetActivityRef = useRef(null);
490
+ const onIdleRef = useRef(onIdle);
491
+ const onWarningRef = useRef(onWarning);
492
+ const onActivityRef = useRef(onActivity);
493
+ useEffect2(() => {
494
+ onIdleRef.current = onIdle;
495
+ onWarningRef.current = onWarning;
496
+ onActivityRef.current = onActivity;
497
+ }, [onIdle, onWarning, onActivity]);
489
498
  const clearTimers = useCallback2(() => {
490
499
  if (timeoutRef.current) {
491
500
  clearTimeout(timeoutRef.current);
@@ -509,18 +518,18 @@ function useInactivityTracker({
509
518
  setShowWarning(false);
510
519
  setTimeRemaining(idleTimeoutMs);
511
520
  if (!skipActivityCallback) {
512
- onActivity?.();
521
+ onActivityRef.current?.();
513
522
  }
514
523
  const warningTime = idleTimeoutMs - warnBeforeMs;
515
524
  if (warningTime > 0) {
516
525
  warningTimeoutRef.current = setTimeout(() => {
517
526
  setShowWarning(true);
518
- onWarning?.();
527
+ onWarningRef.current?.();
519
528
  }, warningTime);
520
529
  }
521
530
  timeoutRef.current = setTimeout(() => {
522
531
  setIsIdle(true);
523
- onIdle?.();
532
+ onIdleRef.current?.();
524
533
  }, idleTimeoutMs);
525
534
  countdownIntervalRef.current = setInterval(() => {
526
535
  const elapsed = Date.now() - lastActivityRef.current;
@@ -542,7 +551,7 @@ function useInactivityTracker({
542
551
  } catch (error) {
543
552
  logger.warn("useInactivityTracker", "Failed to broadcast activity:", error);
544
553
  }
545
- }, [enabled, idleTimeoutMs, warnBeforeMs, onIdle, onWarning, onActivity, storageKey, clearTimers]);
554
+ }, [enabled, idleTimeoutMs, warnBeforeMs, storageKey, clearTimers]);
546
555
  const startTracking = useCallback2(() => {
547
556
  if (!enabled) return;
548
557
  setIsTracking(false);
@@ -575,11 +584,11 @@ function useInactivityTracker({
575
584
  setTimeRemaining(remaining);
576
585
  if (remaining <= warnBeforeMs) {
577
586
  setShowWarning(true);
578
- onWarning?.();
587
+ onWarningRef.current?.();
579
588
  }
580
589
  if (remaining <= 0) {
581
590
  setIsIdle(true);
582
- onIdle?.();
591
+ onIdleRef.current?.();
583
592
  return;
584
593
  }
585
594
  }
@@ -612,7 +621,7 @@ function useInactivityTracker({
612
621
  channelRef.current = null;
613
622
  }
614
623
  };
615
- }, [enabled, isTracking, channelName, storageKey, idleTimeoutMs, warnBeforeMs, onIdle, onWarning, onActivity, resetActivity]);
624
+ }, [enabled, channelName, storageKey, idleTimeoutMs, warnBeforeMs, resetActivity, clearTimers]);
616
625
  const stopTracking = useCallback2(() => {
617
626
  setIsTracking(false);
618
627
  clearTimers();
@@ -1162,6 +1171,7 @@ export {
1162
1171
  useSecureSupabase,
1163
1172
  useSessionRestoration,
1164
1173
  useSessionTracking,
1174
+ useSuperAdminBypass,
1165
1175
  useToast,
1166
1176
  useUnifiedAuth,
1167
1177
  useZodForm,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/providers/OrganisationProvider.tsx","../src/components/InactivityWarningModal/InactivityWarningModal.tsx","../src/hooks/useInactivityTracker.ts","../src/index.ts","../src/utils/security/secureDataAccess.ts"],"sourcesContent":["/**\n * @file Organisation Provider\n * @package @jmruthers/pace-core\n * @module Providers\n * @since 0.1.0\n *\n * React provider for organisation context.\n * This is a convenience wrapper around OrganisationServiceProvider that\n * automatically gets auth context from UnifiedAuthProvider.\n * \n * Note: If you're using UnifiedAuthProvider, it already includes\n * OrganisationServiceProvider internally, so this component is mainly\n * for backward compatibility or standalone usage.\n */\n\nimport React from 'react';\nimport { useUnifiedAuth } from '../providers/services/UnifiedAuthProvider';\nimport { OrganisationServiceProvider } from './services/OrganisationServiceProvider';\nimport type { OrganisationProviderProps as BaseOrganisationProviderProps } from '../types/organisation';\n\nexport interface OrganisationProviderProps extends BaseOrganisationProviderProps {\n children: React.ReactNode;\n requireOrganisationContext?: boolean;\n autoSelectPrimaryOrganisation?: boolean;\n onOrganisationChange?: (organisation: any) => void;\n}\n\n/**\n * OrganisationProvider component\n * \n * Wraps OrganisationServiceProvider and automatically gets auth context.\n * \n * @example\n * ```tsx\n * <UnifiedAuthProvider supabaseClient={supabase} appName=\"my-app\">\n * <OrganisationProvider>\n * <App />\n * </OrganisationProvider>\n * </UnifiedAuthProvider>\n * ```\n */\nexport function OrganisationProvider({ \n children,\n requireOrganisationContext,\n autoSelectPrimaryOrganisation,\n onOrganisationChange\n}: OrganisationProviderProps) {\n // Get auth context from UnifiedAuthProvider\n const authContext = useUnifiedAuth();\n \n // If we're inside UnifiedAuthProvider, it already includes OrganisationServiceProvider\n // So we can just pass through the children\n // However, if the auth context is not available, we need to handle that\n if (!authContext) {\n // If no auth context, we can't provide organisation service\n // This might happen if used outside UnifiedAuthProvider\n // In that case, we should probably throw an error or show a message\n console.warn('OrganisationProvider: No auth context available. Make sure OrganisationProvider is used inside UnifiedAuthProvider.');\n return <>{children}</>;\n }\n\n const { supabase, user, session } = authContext;\n\n // Wrap with OrganisationServiceProvider\n // Note: The props like requireOrganisationContext, autoSelectPrimaryOrganisation\n // are handled by the OrganisationService internally, not by the provider\n // Note: supabase is mapped to supabaseClient for OrganisationServiceProvider\n if (!supabase) {\n console.warn('OrganisationProvider: No supabase client available.');\n return <>{children}</>;\n }\n\n return (\n <OrganisationServiceProvider\n supabaseClient={supabase}\n user={user}\n session={session}\n >\n {children}\n </OrganisationServiceProvider>\n );\n}\n\n","/**\n * @file Inactivity Warning Modal\n * @package @jmruthers/pace-core\n * @module Components/InactivityWarningModal\n * @since 0.1.0\n *\n * A modal dialog that warns users about impending auto-logout due to inactivity.\n * Provides a countdown timer and action buttons to either stay signed in or sign out immediately.\n *\n * Features:\n * - Accessible modal dialog with focus management\n * - Live countdown timer with 1-second updates\n * - Clear action buttons (Stay Signed In / Sign Out Now)\n * - Keyboard navigation support (Escape to stay signed in)\n * - Cross-tab awareness and synchronization\n * - Tailwind v4 styling with pace-core theme tokens\n * - Production-safe with no arbitrary bracket classes\n *\n * @example\n * ```tsx\n * <InactivityWarningModal\n * isOpen={showWarning}\n * timeRemaining={45}\n * onStaySignedIn={() => setShowWarning(false)}\n * onSignOutNow={() => signOut()}\n * />\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Focus trap within modal content\n * - Screen reader announcements for countdown changes\n * - Keyboard navigation support\n * - Clear visual hierarchy and contrast\n * - Escape key to stay signed in (safe default)\n *\n * @performance\n * - Efficient countdown updates (1-second intervals)\n * - Minimal re-renders with stable references\n * - Memory leak prevention with cleanup\n * - Optimized timer management\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - Dialog components - Modal functionality\n * - Tailwind CSS v4 - Styling\n */\n\nimport React, { useEffect, useState, useCallback } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '../Dialog/Dialog';\nimport { Button } from '../Button/Button';\nimport { Clock, AlertTriangle } from 'lucide-react';\nimport { cn } from '../../utils/core/cn';\n\nexport interface InactivityWarningModalProps {\n /** Whether the modal is open */\n isOpen: boolean;\n /** Time remaining in seconds before auto-logout */\n timeRemaining: number;\n /** Callback when user chooses to stay signed in */\n onStaySignedIn: () => void;\n /** Callback when user chooses to sign out immediately */\n onSignOutNow: () => void;\n /** Optional custom title */\n title?: string;\n /** Optional custom description */\n description?: string;\n /** Optional custom className */\n className?: string;\n}\n\nexport function InactivityWarningModal({\n isOpen,\n timeRemaining,\n onStaySignedIn,\n onSignOutNow,\n title = \"Session Timeout Warning\",\n description = \"You've been inactive for a while. Your session will expire soon for security reasons.\",\n className\n}: InactivityWarningModalProps) {\n const [displayTime, setDisplayTime] = useState(timeRemaining);\n\n // Update display time when timeRemaining prop changes\n useEffect(() => {\n setDisplayTime(timeRemaining);\n }, [timeRemaining]);\n\n // Format time for display (MM:SS)\n const formatTime = useCallback((seconds: number) => {\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }, []);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onStaySignedIn()}>\n <DialogContent \n className={cn(\"sm:max-w-md\", className)}\n preventCloseOnEscape={false}\n preventCloseOnOutsideClick={true}\n data-testid=\"inactivity-warning-modal\"\n >\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-shrink-0\">\n <AlertTriangle className=\"h-6 w-6 text-acc-600\" />\n </div>\n <div>\n <DialogTitle className=\"text-lg font-semibold text-main-900\">\n {title}\n </DialogTitle>\n </div>\n </div>\n <DialogDescription className=\"text-main-700 mt-2\">\n {description}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-6\">\n {/* Countdown Timer */}\n <div className=\"text-center\">\n <div className=\"inline-flex items-center gap-2 px-4 py-3 bg-acc-50 border border-acc-200 rounded-lg\">\n <Clock className=\"h-5 w-5 text-acc-600\" />\n <span className=\"text-2xl font-mono font-bold text-acc-700\">\n {formatTime(displayTime)}\n </span>\n </div>\n <p className=\"text-sm text-main-600 mt-2\">\n Time remaining before automatic logout\n </p>\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <Button\n onClick={onStaySignedIn}\n className=\"flex-1 bg-main-600 hover:bg-main-700 text-main-50\"\n size=\"lg\"\n >\n Stay Signed In\n </Button>\n <Button\n onClick={onSignOutNow}\n variant=\"outline\"\n className=\"flex-1 border-acc-300 text-acc-700 hover:bg-acc-50\"\n size=\"lg\"\n >\n Sign Out Now\n </Button>\n </div>\n\n {/* Additional Info */}\n <div className=\"text-xs text-main-500 text-center\">\n <p>\n For security reasons, you'll be automatically signed out after 30 minutes of inactivity.\n </p>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n","/**\n * @file Inactivity Tracker Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useInactivityTracker\n * @since 0.1.0\n *\n * A custom hook that tracks user inactivity and provides cross-tab synchronization.\n * Monitors various user interactions and manages inactivity timers with persistence.\n *\n * Features:\n * - Cross-tab synchronization using BroadcastChannel and localStorage\n * - Monitors keyboard, mouse, touch, scroll, and focus events\n * - Throttled event handling for performance\n * - Persistence of last activity time across page reloads\n * - SSR-safe implementation with proper cleanup\n * - Configurable timeout and warning thresholds\n * - Production-safe with dev-only escape hatches\n *\n * @example\n * ```tsx\n * const {\n * isIdle,\n * timeRemaining,\n * showWarning,\n * resetActivity,\n * startTracking,\n * stopTracking\n * } = useInactivityTracker({\n * idleTimeoutMs: 30 * 60 * 1000, // 30 minutes\n * warnBeforeMs: 60 * 1000, // 1 minute\n * onIdle: () => console.log('User is idle'),\n * onWarning: () => console.log('Warning should show'),\n * onActivity: () => console.log('User is active')\n * });\n * ```\n *\n * @accessibility\n * - No direct accessibility concerns (utility hook)\n * - Enables accessible inactivity warnings\n * - Supports screen reader friendly countdowns\n * - Maintains focus management during warnings\n *\n * @performance\n * - Throttled event handling (100ms intervals)\n * - Efficient timer management with cleanup\n * - Minimal re-renders with stable references\n * - Memory leak prevention\n * - Cross-tab optimization\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - Browser APIs - BroadcastChannel, localStorage, timers\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { logger } from '../utils/core/logger';\n\nexport interface UseInactivityTrackerOptions {\n /** Timeout in milliseconds before user is considered idle (default: 30 minutes) */\n idleTimeoutMs?: number;\n /** Time in milliseconds before idle timeout to show warning (default: 60 seconds) */\n warnBeforeMs?: number;\n /** Callback when user becomes idle */\n onIdle?: () => void;\n /** Callback when warning should be shown */\n onWarning?: () => void;\n /** Callback when user becomes active again */\n onActivity?: () => void;\n /** Whether tracking is enabled (default: true) */\n enabled?: boolean;\n /** Storage key for persistence (default: 'pace-core-inactivity') */\n storageKey?: string;\n /** Broadcast channel name for cross-tab sync (default: 'pace-core-inactivity') */\n channelName?: string;\n}\n\nexport interface UseInactivityTrackerReturn {\n /** Whether the user is currently idle */\n isIdle: boolean;\n /** Time remaining in milliseconds before idle timeout */\n timeRemaining: number;\n /** Whether warning should be shown */\n showWarning: boolean;\n /** Reset the activity timer */\n resetActivity: () => void;\n /** Start tracking inactivity */\n startTracking: () => void;\n /** Stop tracking inactivity */\n stopTracking: () => void;\n /** Whether tracking is currently active */\n isTracking: boolean;\n}\n\n// Events that indicate user activity\nconst ACTIVITY_EVENTS = [\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'click',\n 'scroll',\n 'wheel',\n 'touchstart',\n 'touchmove',\n 'touchend',\n 'keydown',\n 'keyup',\n 'keypress',\n 'focus',\n 'blur',\n 'visibilitychange'\n] as const;\n\n// Throttle function to limit event handler frequency\nfunction throttle<T extends (...args: any[]) => void>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle: boolean;\n return function (this: any, ...args: Parameters<T>) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\nexport function useInactivityTracker({\n idleTimeoutMs = 30 * 60 * 1000, // 30 minutes\n warnBeforeMs = 60 * 1000, // 1 minute\n onIdle,\n onWarning,\n onActivity,\n enabled = true,\n storageKey = 'pace-core-inactivity',\n channelName = 'pace-core-inactivity'\n}: UseInactivityTrackerOptions = {}): UseInactivityTrackerReturn {\n const [isIdle, setIsIdle] = useState(false);\n const [timeRemaining, setTimeRemaining] = useState(idleTimeoutMs);\n const [showWarning, setShowWarning] = useState(false);\n const [isTracking, setIsTracking] = useState(false);\n\n // Reset tracking state when enabled changes\n useEffect(() => {\n if (!enabled) {\n setIsTracking(false);\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n }\n }, [enabled, idleTimeoutMs]);\n\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const warningTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const countdownIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const lastActivityRef = useRef<number>(Date.now());\n const channelRef = useRef<BroadcastChannel | null>(null);\n const throttledResetActivityRef = useRef<((event: Event) => void) | null>(null);\n\n // Clear all timers\n const clearTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (warningTimeoutRef.current) {\n clearTimeout(warningTimeoutRef.current);\n warningTimeoutRef.current = null;\n }\n if (countdownIntervalRef.current) {\n clearInterval(countdownIntervalRef.current);\n countdownIntervalRef.current = null;\n }\n }, []);\n\n // Reset activity and restart timers\n const resetActivity = useCallback((skipActivityCallback = false) => {\n if (!enabled) return;\n\n const now = Date.now();\n lastActivityRef.current = now;\n\n // Clear existing timers\n clearTimers();\n\n // Reset state\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n\n // Notify activity callback (unless skipped for initial setup)\n if (!skipActivityCallback) {\n onActivity?.();\n }\n\n // Set up warning timer\n const warningTime = idleTimeoutMs - warnBeforeMs;\n if (warningTime > 0) {\n warningTimeoutRef.current = setTimeout(() => {\n setShowWarning(true);\n onWarning?.();\n }, warningTime);\n }\n\n // Set up idle timeout\n timeoutRef.current = setTimeout(() => {\n setIsIdle(true);\n onIdle?.();\n }, idleTimeoutMs);\n\n // Start countdown interval for time remaining\n countdownIntervalRef.current = setInterval(() => {\n const elapsed = Date.now() - lastActivityRef.current;\n const remaining = Math.max(0, idleTimeoutMs - elapsed);\n setTimeRemaining(remaining);\n\n if (remaining === 0) {\n clearTimers();\n }\n }, 1000);\n\n // Persist activity time\n try {\n localStorage.setItem(storageKey, now.toString());\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to persist activity time:', error);\n }\n\n // Broadcast activity to other tabs\n try {\n if (channelRef.current) {\n channelRef.current.postMessage({ type: 'activity', timestamp: now });\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to broadcast activity:', error);\n }\n }, [enabled, idleTimeoutMs, warnBeforeMs, onIdle, onWarning, onActivity, storageKey, clearTimers]);\n\n // Start tracking\n const startTracking = useCallback(() => {\n if (!enabled) return;\n\n // Always reset state and start fresh\n setIsTracking(false);\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n \n // Clear any existing timers\n clearTimers();\n \n setIsTracking(true);\n\n // Set up cross-tab communication\n try {\n if (typeof BroadcastChannel !== 'undefined') {\n channelRef.current = new BroadcastChannel(channelName);\n channelRef.current.onmessage = (event) => {\n if (event.data.type === 'activity') {\n lastActivityRef.current = event.data.timestamp;\n resetActivity();\n }\n };\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to set up cross-tab communication:', error);\n }\n\n // Check for persisted activity time\n try {\n const persistedTime = localStorage.getItem(storageKey);\n if (persistedTime) {\n const persistedTimestamp = parseInt(persistedTime, 10);\n const elapsed = Date.now() - persistedTimestamp;\n \n if (elapsed < idleTimeoutMs) {\n // User was active recently, continue from where we left off\n lastActivityRef.current = persistedTimestamp;\n const remaining = idleTimeoutMs - elapsed;\n setTimeRemaining(remaining);\n \n if (remaining <= warnBeforeMs) {\n setShowWarning(true);\n onWarning?.();\n }\n \n if (remaining <= 0) {\n setIsIdle(true);\n onIdle?.();\n return;\n }\n }\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to check persisted activity time:', error);\n }\n\n // Clean up any existing throttled handler and event listeners first\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n }\n\n // Set up throttled activity handler - store in ref for proper cleanup\n throttledResetActivityRef.current = throttle((event) => {\n resetActivity();\n }, 100);\n\n // Add event listeners\n ACTIVITY_EVENTS.forEach(event => {\n document.addEventListener(event, throttledResetActivityRef.current!, { passive: true });\n });\n\n // Start the timer (skip activity callback for initial setup)\n resetActivity(true);\n\n // Cleanup function\n return () => {\n // Remove event listeners using the stored ref\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n throttledResetActivityRef.current = null;\n }\n clearTimers();\n if (channelRef.current) {\n channelRef.current.close();\n channelRef.current = null;\n }\n };\n }, [enabled, isTracking, channelName, storageKey, idleTimeoutMs, warnBeforeMs, onIdle, onWarning, onActivity, resetActivity]);\n\n // Stop tracking\n const stopTracking = useCallback(() => {\n setIsTracking(false);\n clearTimers();\n \n // Remove event listeners\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n throttledResetActivityRef.current = null;\n }\n \n if (channelRef.current) {\n channelRef.current.close();\n channelRef.current = null;\n }\n }, [clearTimers]);\n\n // Effect to start/stop tracking based on enabled state\n useEffect(() => {\n if (enabled) {\n const cleanup = startTracking();\n return cleanup;\n } else {\n stopTracking();\n return undefined;\n }\n }, [enabled, idleTimeoutMs, warnBeforeMs, startTracking, stopTracking]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n clearTimers();\n if (channelRef.current) {\n channelRef.current.close();\n }\n };\n }, [clearTimers]);\n\n return {\n isIdle,\n timeRemaining,\n showWarning,\n resetActivity,\n startTracking,\n stopTracking,\n isTracking\n };\n}\n","/**\n * @file Complete Component Library Export\n * @package @jmruthers/pace-core\n * @module Core\n * @since 0.1.0\n * \n * This file exports the primary components, hooks, and utilities from the PACE Core library.\n * It is the main entry point for developers using the library.\n * \n * @example\n * // Import common components\n * import { Button, Card, useUnifiedAuth } from '@jmruthers/pace-core';\n * \n * // For specialized components, use the complete library import:\n * import { Dialog, NavigationMenu } from '@jmruthers/pace-core/components';\n */\n\n// AUTHENTICATION & AUTHORIZATION\n// Note: Providers are now service-based architecture for better testability and maintainability\nexport { UnifiedAuthProvider, useUnifiedAuth } from './providers/services/UnifiedAuthProvider';\nexport type { UnifiedAuthProviderProps, UnifiedAuthContextType, UserEventAccess } from './providers/services/UnifiedAuthProvider';\n\n// Session tracking utility (for manual use if needed)\nexport { useSessionTracking } from './utils/context/sessionTracking';\n\n// Provider components (using service architecture)\nexport { EventServiceProvider } from './providers/services/EventServiceProvider';\nexport { OrganisationServiceProvider } from './providers/services/OrganisationServiceProvider';\nexport { InactivityServiceProvider } from './providers/services/InactivityServiceProvider';\n\n// Convenience provider wrapper (backward compatibility)\nexport { OrganisationProvider } from './providers/OrganisationProvider';\nexport type { OrganisationProviderProps } from './providers/OrganisationProvider';\n\n// Convenience hooks\nexport { useEvents } from './hooks/useEvents';\nexport { useOrganisations } from './hooks/useOrganisations';\n\n// Service hooks for advanced usage (better performance)\nexport { useEventService } from './hooks/services/useEventService';\nexport { useOrganisationService } from './hooks/services/useOrganisationService';\nexport { useAuthService } from './hooks/services/useAuthService';\nexport { useInactivityService } from './hooks/services/useInactivityService';\nexport { useSessionRestoration } from './hooks/useSessionRestoration';\n\nexport type { \n Organisation, \n OrganisationMembership, \n OrganisationContextType, \n OrganisationSecurityError \n} from './types/organisation';\n\n// INACTIVITY TRACKING\nexport { InactivityWarningModal } from './components/InactivityWarningModal/InactivityWarningModal';\nexport type { InactivityWarningModalProps } from './components/InactivityWarningModal/InactivityWarningModal';\nexport { useInactivityTracker } from './hooks/useInactivityTracker';\nexport type { UseInactivityTrackerOptions, UseInactivityTrackerReturn } from './hooks/useInactivityTracker';\n\n// RBAC SYSTEM - Consolidated RBAC module\nexport * from './rbac';\n\n// BASIC UI COMPONENTS\nexport { Button } from './components/Button/Button';\nexport type { ButtonProps } from './components/Button/Button';\n\nexport { \n Card, \n CardHeader, \n CardFooter, \n CardTitle, \n CardDescription, \n CardContent,\n CardActions\n} from './components/Card/Card';\nexport type { CardProps } from './components/Card/Card';\n\nexport { Input } from './components/Input/Input';\nexport type { InputProps } from './components/Input/Input';\nexport { AddressField } from './components/AddressField';\nexport type { AddressFieldProps, AddressFieldRef, ParsedAddress, AutocompleteOptions } from './components/AddressField';\nexport { Label } from './components/Label/Label';\nexport type { LabelProps } from './components/Label/Label';\n\nexport { Textarea } from './components/Textarea/Textarea';\nexport type { TextareaProps } from './components/Textarea/Textarea';\n\nexport { Alert, AlertTitle, AlertDescription } from './components/Alert/Alert';\nexport { Avatar } from './components/Avatar/Avatar';\nexport type { AvatarProps } from './components/Avatar/Avatar';\n\nexport { Badge } from './components/Badge/Badge';\nexport type { BadgeProps, BadgeVariant } from './components/Badge/Badge';\n\nexport { Checkbox } from './components/Checkbox/Checkbox';\nexport { Switch } from './components/Switch/Switch';\nexport type { SwitchProps } from './components/Switch/Switch';\nexport { Progress } from './components/Progress';\nexport type { ProgressProps } from './components/Progress';\n\n// ADVANCED UI COMPONENTS\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogBody,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n} from './components/Dialog/Dialog';\n\n// Dropdown Menu exports\n// DropdownMenu components have been merged into Select components\n\n// Select exports\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n} from './components/Select';\n\n// Tabs exports\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/Tabs/Tabs';\nexport type { TabsProps, TabsListProps, TabsTriggerProps, TabsContentProps } from './components/Tabs/Tabs';\n\n// Calendar exports\nexport { Calendar } from './components/Calendar/Calendar';\nexport type { CalendarProps } from './components/Calendar/Calendar';\n\n// Modal functionality is provided by Dialog components\n\nexport {\n Toast,\n Toaster,\n ToastAction,\n ToastProvider,\n ToastViewport,\n ToastTitle,\n ToastDescription,\n ToastClose,\n} from './components/Toast/Toast';\nexport { useToast } from './hooks/useToast';\nexport type { ToastActionElement, ToastProps } from './components/Toast/Toast';\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TooltipRoot } from './components/Tooltip/Tooltip';\n\n// DATA DISPLAY COMPONENTS\nexport {\n DataTable,\n type DataTableProps,\n type DataTableColumn,\n type DataTableAction,\n type DataTableToolbarButton,\n type AggregateConfig,\n type EmptyStateConfig,\n type GetRowId,\n type DataTableFeatureConfig,\n ColumnFactory\n} from './components/DataTable';\n\n// Re-export types from DataTable types\nexport type { DataRecord, ExportOptions } from './components/DataTable/types';\n\n// Export DataTable utility functions\nexport {\n exportToCSV,\n exportToCSVWithTableRows,\n generateCSVContent,\n type ExportColumn\n} from './components/DataTable/utils/exportUtils';\n\n// Export DataTable aggregation utilities\nexport {\n sum,\n average,\n count,\n min,\n max\n} from './components/DataTable/utils/aggregationUtils';\n\n// FORM COMPONENTS\nexport { Form, FormField } from './components/Form/Form';\nexport type { FormProps, FormFieldProps } from './components/Form/Form';\nexport { LoginForm } from './components/LoginForm';\nexport type { LoginFormProps } from './components/LoginForm';\n\n// FORM HOOKS\nexport { useZodForm } from './hooks/useZodForm';\nexport { useFormDialog } from './hooks/useFormDialog';\nexport type { UseFormDialogOptions, UseFormDialogReturn } from './hooks/useFormDialog';\n\n// VALIDATION - Re-export zod for schema creation\nexport { z } from 'zod';\n// Common validation schemas\nexport { emailSchema, nameSchema, phoneSchema, urlSchema } from './utils/validation/common';\nexport { passwordSchema } from './utils/validation/passwordSchema';\n\n// LAYOUT COMPONENTS\nexport { Header } from './components/Header/Header';\nexport { Footer } from './components/Footer/Footer';\nexport type { FooterProps } from './components/Footer/Footer';\n\n// NAVIGATION COMPONENTS\nexport { NavigationMenu } from './components/NavigationMenu/NavigationMenu';\nexport type { NavigationMenuProps, NavigationItem, NavigationMode } from './components/NavigationMenu/NavigationMenu';\nexport { UserMenu } from './components/UserMenu/UserMenu';\nexport type { UserMenuProps } from './components/UserMenu/UserMenu';\n\n// Reusable Page/Layout Components\nexport { PaceAppLayout } from './components/PaceAppLayout/PaceAppLayout';\nexport type { PaceAppLayoutProps } from './components/PaceAppLayout/PaceAppLayout';\nexport { PaceLoginPage } from './components/PaceLoginPage/PaceLoginPage';\nexport type { PaceLoginPageProps } from './components/PaceLoginPage/PaceLoginPage';\n\nexport { ProtectedRoute } from './components/ProtectedRoute/ProtectedRoute';\nexport type { ProtectedRouteProps } from './components/ProtectedRoute/ProtectedRoute';\n\n// UTILITY COMPONENTS\nexport { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary';\nexport { LoadingSpinner } from './components/LoadingSpinner/LoadingSpinner';\nexport { SessionRestorationLoader } from './components/SessionRestorationLoader/SessionRestorationLoader';\nexport type { SessionRestorationLoaderProps } from './components/SessionRestorationLoader/SessionRestorationLoader';\n\n// EVENT MANAGEMENT\nexport { EventSelector } from './components/EventSelector/EventSelector';\n\n// ORGANISATION MANAGEMENT\nexport { OrganisationSelector } from './components/OrganisationSelector/OrganisationSelector';\nexport { useOrganisationPermissions } from './hooks/useOrganisationPermissions';\nexport { useOrganisationSecurity } from './hooks/useOrganisationSecurity';\nexport { createSecureDataAccess } from './utils/security/secureDataAccess';\n\n// TYPES\nexport type { UserProfile } from './types/organisation';\n\n// AUTHENTICATION FORMS\nexport { PasswordChangeForm } from './components/PasswordChange/PasswordChangeForm';\n\n// UTILS & HOOKS\nexport { useAppConfig } from './hooks/useAppConfig';\nexport { useEventTheme } from './hooks/useEventTheme';\nexport { cn } from './utils/core/cn';\nexport { setAppConfig, getAppConfig, getCurrentAppName, getCurrentAppId } from './utils/app/appConfig';\n\n// LOGGING UTILITIES\nexport { Logger, logger, createLogger, LogLevel } from './utils/core/logger';\nexport type { LoggerConfig } from './utils/core/logger';\n\n// FORMATTING UTILITIES\nexport { \n formatDate,\n formatTime,\n formatDateTime,\n formatCurrency, \n formatNumber,\n formatPercent,\n formatCompactNumber,\n formatFileSize\n} from './utils/formatting/formatting';\n\n// TIMEZONE UTILITIES\nexport {\n formatInTimeZone,\n getTimezoneAbbreviation,\n formatTimeInTimeZone,\n getUserTimeZone,\n toZonedTime,\n fromZonedTime,\n roundToNearestMinutes,\n getTimeZoneDifference\n} from './utils/timezone';\n\n// STORAGE UTILITIES\nexport { FileUpload } from './components/FileUpload';\nexport type { FileUploadProps } from './components/FileUpload';\nexport { FileDisplay } from './components/FileDisplay';\nexport type { FileDisplayProps } from './components/FileDisplay';\nexport { FileCategory } from './types/file-reference';\nexport type { FileReference, FileMetadata, FileUploadOptions } from './types/file-reference';\nexport { \n useFileReference, \n useFileReferenceForRecord,\n useFileReferenceById,\n useFilesByCategory\n} from './hooks/useFileReference';\nexport type { \n UseFileReferenceOptions, \n UseFileReferenceReturn, \n UseFileReferenceForRecordReturn \n} from './hooks/useFileReference';\nexport * from './utils/storage';\n\n// Table components\nexport {\n Table,\n TableHeader,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableRow,\n} from './components/Table/Table';\n\n// STYLES & THEMING\nexport * from './styles';\n// Direct export of theming utilities for convenience\nexport { parseAndNormalizeEventColours } from './theming/parseEventColours';\nexport { applyPalette, clearPalette } from './theming/runtime';\nexport type { PaletteData, ColorPalette, ColorShade } from './theming/runtime';\n\n// PUBLIC PAGES\nexport * from './hooks/public';\nexport * from './components/PublicLayout';\n","/**\n * @file Secure Data Access Utility\n * @package @jmruthers/pace-core\n * @module Utils/SecureDataAccess\n * @since 0.4.0\n *\n * Secure data access utilities that enforce organisation context for all database operations.\n * Prevents data leakage between organisations and ensures proper access validation.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\n\n// Generic database record type\nexport interface DatabaseRecord {\n id: string;\n organisation_id: string;\n [key: string]: unknown;\n}\n\n// Generic data for insert/update operations\nexport interface DatabaseData {\n [key: string]: unknown;\n}\n\n// Generic filters for queries\nexport interface DatabaseFilters {\n [key: string]: unknown;\n}\n\n// Secure query options\nexport interface SecureQueryOptions {\n table: string;\n select: string;\n organisationId: string;\n filters?: DatabaseFilters;\n orderBy?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface SecureDataAccess {\n // Secure query methods\n secureQuery: <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions) => Promise<T[]>;\n secureSingleQuery: <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions) => Promise<T | null>;\n \n // Secure mutation methods\n secureInsert: <T extends DatabaseRecord = DatabaseRecord>(table: string, data: DatabaseData, organisationId: string) => Promise<T | null>;\n secureUpdate: <T extends DatabaseRecord = DatabaseRecord>(table: string, data: DatabaseData, filters: DatabaseFilters, organisationId: string) => Promise<T | null>;\n secureDelete: (table: string, filters: DatabaseFilters, organisationId: string) => Promise<boolean>;\n \n // Organisation-scoped queries\n queryByOrganisation: <T extends DatabaseRecord = DatabaseRecord>(table: string, select: string, organisationId: string, filters?: DatabaseFilters) => Promise<T[]>;\n \n // Validation helpers\n validateOrganisationContext: (organisationId: string) => void;\n ensureOrganisationColumn: (table: string) => boolean;\n}\n\nexport interface SecureQueryBuilder {\n table: string;\n select: string;\n organisationId: string;\n filters?: DatabaseFilters;\n orderBy?: string;\n limit?: number;\n offset?: number;\n}\n\n/**\n * Create a secure data access instance\n * @param supabase - Supabase client instance\n * @param organisationId - Current organisation context\n * @param isSuperAdmin - Whether user has super admin privileges\n * @returns Secure data access utilities\n */\nexport const createSecureDataAccess = (\n supabase: SupabaseClient,\n organisationId: string,\n isSuperAdmin: boolean = false\n): SecureDataAccess => {\n \n // Validate organisation context\n const validateOrganisationContext = (orgId: string): void => {\n if (!orgId) {\n throw new Error('Organisation context is required for secure data access');\n }\n \n if (!isSuperAdmin && !orgId) {\n throw new Error('Organisation context is mandatory for non-super admin users');\n }\n };\n\n // Check if table has organisation_id column\n const ensureOrganisationColumn = (table: string): boolean => {\n // This is a simplified check - in production you might want to cache this\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n return tablesWithOrganisation.includes(table);\n };\n\n // Build secure query with organisation context\n const buildSecureQuery = (options: SecureQueryBuilder) => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n validateOrganisationContext(orgId);\n \n let query = supabase\n .from(table)\n .select(select);\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', orgId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n // Handle qualified column names (e.g., 'users.role')\n const columnName = key.includes('.') ? key.split('.').pop()! : key;\n query = query.eq(columnName, value);\n }\n });\n }\n \n // Add ordering\n if (orderBy) {\n // Only use the column name, not a qualified name\n const orderByColumn = orderBy.split('.').pop();\n if (orderByColumn) {\n query = query.order(orderByColumn);\n }\n }\n \n // Add pagination\n if (limit) {\n query = query.limit(limit);\n }\n \n if (offset) {\n query = query.range(offset, offset + (limit || 10) - 1);\n }\n \n return query;\n };\n\n // Secure query for multiple results\n const secureQuery = async <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions): Promise<T[]> => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n try {\n const query = buildSecureQuery({\n table,\n select,\n organisationId: orgId,\n filters,\n orderBy,\n limit,\n offset\n });\n \n const { data, error } = await query;\n \n if (error) {\n throw error;\n }\n \n // Ensure data is an array and not an error type\n if (Array.isArray(data)) {\n return data as unknown as T[];\n }\n \n return [];\n } catch (error) {\n throw error;\n }\n };\n\n // Secure query for single result\n const secureSingleQuery = async <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions): Promise<T | null> => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n try {\n const query = buildSecureQuery({\n table,\n select,\n organisationId: orgId,\n filters,\n orderBy,\n limit,\n offset\n });\n \n const { data, error } = await query.single();\n \n if (error) {\n if (error.code === 'PGRST116') {\n // No rows returned\n return null;\n }\n throw error;\n }\n \n // Ensure data is not an error type\n if (data && typeof data === 'object' && !('code' in data)) {\n return data as unknown as T;\n }\n \n return null;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure insert with organisation context\n const secureInsert = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n data: DatabaseData, \n organisationId: string\n ): Promise<T | null> => {\n validateOrganisationContext(organisationId);\n \n try {\n const insertData = {\n ...data,\n organisation_id: organisationId\n };\n \n const { data: result, error } = await supabase\n .from(table)\n .insert(insertData)\n .select()\n .single();\n \n if (error) {\n throw error;\n }\n \n return result;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure update with organisation context\n const secureUpdate = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n data: DatabaseData, \n filters: DatabaseFilters, \n organisationId: string\n ): Promise<T | null> => {\n validateOrganisationContext(organisationId);\n \n try {\n let query = supabase\n .from(table)\n .update(data);\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n }\n \n const { data: result, error } = await query.select().single();\n \n if (error) {\n throw error;\n }\n \n return result;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure delete with organisation context\n const secureDelete = async (\n table: string, \n filters: DatabaseFilters, \n organisationId: string\n ): Promise<boolean> => {\n validateOrganisationContext(organisationId);\n \n try {\n let query = supabase\n .from(table)\n .delete();\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n }\n \n const { error } = await query;\n \n if (error) {\n throw error;\n }\n \n return true;\n } catch (error) {\n throw error;\n }\n };\n\n // Organisation-scoped query helper\n const queryByOrganisation = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n select: string, \n organisationId: string, \n filters?: DatabaseFilters\n ): Promise<T[]> => {\n return secureQuery<T>({\n table,\n select,\n organisationId,\n filters\n });\n };\n\n return {\n secureQuery,\n secureSingleQuery,\n secureInsert,\n secureUpdate,\n secureDelete,\n queryByOrganisation,\n validateOrganisationContext,\n ensureOrganisationColumn\n };\n};\n\n/**\n * Hook for secure data access\n * @returns Secure data access utilities\n */\nexport const useSecureDataAccess = (): SecureDataAccess => {\n // This would typically get the context from providers\n // For now, we'll create a placeholder that can be used with explicit parameters\n throw new Error('useSecureDataAccess must be used with explicit parameters. Use createSecureDataAccess instead.');\n}; "],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DW;AAjBJ,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAE5B,QAAM,cAAc,eAAe;AAKnC,MAAI,CAAC,aAAa;AAIhB,YAAQ,KAAK,qHAAqH;AAClI,WAAO,gCAAG,UAAS;AAAA,EACrB;AAEA,QAAM,EAAE,UAAU,MAAM,QAAQ,IAAI;AAMpC,MAAI,CAAC,UAAU;AACb,YAAQ,KAAK,qDAAqD;AAClE,WAAO,gCAAG,UAAS;AAAA,EACrB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;ACjCA,SAAgB,WAAW,UAAU,mBAAmB;AAGxD,SAAS,OAAO,qBAAqB;AAoD3B,SAEI,OAAAA,MAFJ;AAhCH,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AACF,GAAgC;AAC9B,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,aAAa;AAG5D,YAAU,MAAM;AACd,mBAAe,aAAa;AAAA,EAC9B,GAAG,CAAC,aAAa,CAAC;AAGlB,QAAMC,cAAa,YAAY,CAAC,YAAoB;AAClD,UAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,UAAM,OAAO,UAAU;AACvB,WAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EAChF,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAD,KAAC,UAAO,MAAM,QAAQ,cAAc,CAAC,SAAS,CAAC,QAAQ,eAAe,GACpE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,eAAe,SAAS;AAAA,MACtC,sBAAsB;AAAA,MACtB,4BAA4B;AAAA,MAC5B,eAAY;AAAA,MAEZ;AAAA,6BAAC,gBACC;AAAA,+BAAC,SAAI,WAAU,2BACb;AAAA,4BAAAA,KAAC,SAAI,WAAU,iBACb,0BAAAA,KAAC,iBAAc,WAAU,wBAAuB,GAClD;AAAA,YACA,gBAAAA,KAAC,SACC,0BAAAA,KAAC,eAAY,WAAU,uCACpB,iBACH,GACF;AAAA,aACF;AAAA,UACA,gBAAAA,KAAC,qBAAkB,WAAU,sBAC1B,uBACH;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,aAEb;AAAA,+BAAC,SAAI,WAAU,eACb;AAAA,iCAAC,SAAI,WAAU,uFACb;AAAA,8BAAAA,KAAC,SAAM,WAAU,wBAAuB;AAAA,cACxC,gBAAAA,KAAC,UAAK,WAAU,6CACb,UAAAC,YAAW,WAAW,GACzB;AAAA,eACF;AAAA,YACA,gBAAAD,KAAC,OAAE,WAAU,8BAA6B,oDAE1C;AAAA,aACF;AAAA,UAGA,qBAAC,SAAI,WAAU,mCACb;AAAA,4BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBACV,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,SAAQ;AAAA,gBACR,WAAU;AAAA,gBACV,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,aACF;AAAA,UAGA,gBAAAA,KAAC,SAAI,WAAU,qCACb,0BAAAA,KAAC,OAAE,sGAEH,GACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;;;AC3GA,SAAS,YAAAE,WAAU,aAAAC,YAAW,eAAAC,cAAa,cAAc;AAwCzD,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,SACP,MACA,OACkC;AAClC,MAAI;AACJ,SAAO,YAAwB,MAAqB;AAClD,QAAI,CAAC,YAAY;AACf,WAAK,MAAM,MAAM,IAAI;AACrB,mBAAa;AACb,iBAAW,MAAO,aAAa,OAAQ,KAAK;AAAA,IAC9C;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB;AAAA,EACnC,gBAAgB,KAAK,KAAK;AAAA;AAAA,EAC1B,eAAe,KAAK;AAAA;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,aAAa;AAAA,EACb,cAAc;AAChB,IAAiC,CAAC,GAA+B;AAC/D,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAAS,aAAa;AAChE,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAGlD,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,oBAAc,KAAK;AACnB,gBAAU,KAAK;AACf,qBAAe,KAAK;AACpB,uBAAiB,aAAa;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,QAAM,aAAa,OAA8B,IAAI;AACrD,QAAM,oBAAoB,OAA8B,IAAI;AAC5D,QAAM,uBAAuB,OAA8B,IAAI;AAC/D,QAAM,kBAAkB,OAAe,KAAK,IAAI,CAAC;AACjD,QAAM,aAAa,OAAgC,IAAI;AACvD,QAAM,4BAA4B,OAAwC,IAAI;AAG9E,QAAM,cAAcC,aAAY,MAAM;AACpC,QAAI,WAAW,SAAS;AACtB,mBAAa,WAAW,OAAO;AAC/B,iBAAW,UAAU;AAAA,IACvB;AACA,QAAI,kBAAkB,SAAS;AAC7B,mBAAa,kBAAkB,OAAO;AACtC,wBAAkB,UAAU;AAAA,IAC9B;AACA,QAAI,qBAAqB,SAAS;AAChC,oBAAc,qBAAqB,OAAO;AAC1C,2BAAqB,UAAU;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,gBAAgBA,aAAY,CAAC,uBAAuB,UAAU;AAClE,QAAI,CAAC,QAAS;AAEd,UAAM,MAAM,KAAK,IAAI;AACrB,oBAAgB,UAAU;AAG1B,gBAAY;AAGZ,cAAU,KAAK;AACf,mBAAe,KAAK;AACpB,qBAAiB,aAAa;AAG9B,QAAI,CAAC,sBAAsB;AACzB,mBAAa;AAAA,IACf;AAGA,UAAM,cAAc,gBAAgB;AACpC,QAAI,cAAc,GAAG;AACnB,wBAAkB,UAAU,WAAW,MAAM;AAC3C,uBAAe,IAAI;AACnB,oBAAY;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAGA,eAAW,UAAU,WAAW,MAAM;AACpC,gBAAU,IAAI;AACd,eAAS;AAAA,IACX,GAAG,aAAa;AAGhB,yBAAqB,UAAU,YAAY,MAAM;AAC/C,YAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB;AAC7C,YAAM,YAAY,KAAK,IAAI,GAAG,gBAAgB,OAAO;AACrD,uBAAiB,SAAS;AAE1B,UAAI,cAAc,GAAG;AACnB,oBAAY;AAAA,MACd;AAAA,IACF,GAAG,GAAI;AAGP,QAAI;AACF,mBAAa,QAAQ,YAAY,IAAI,SAAS,CAAC;AAAA,IACjD,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,oCAAoC,KAAK;AAAA,IAC/E;AAGA,QAAI;AACF,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,YAAY,EAAE,MAAM,YAAY,WAAW,IAAI,CAAC;AAAA,MACrE;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,iCAAiC,KAAK;AAAA,IAC5E;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,cAAc,QAAQ,WAAW,YAAY,YAAY,WAAW,CAAC;AAGjG,QAAM,gBAAgBA,aAAY,MAAM;AACtC,QAAI,CAAC,QAAS;AAGd,kBAAc,KAAK;AACnB,cAAU,KAAK;AACf,mBAAe,KAAK;AACpB,qBAAiB,aAAa;AAG9B,gBAAY;AAEZ,kBAAc,IAAI;AAGlB,QAAI;AACF,UAAI,OAAO,qBAAqB,aAAa;AAC3C,mBAAW,UAAU,IAAI,iBAAiB,WAAW;AACrD,mBAAW,QAAQ,YAAY,CAAC,UAAU;AACxC,cAAI,MAAM,KAAK,SAAS,YAAY;AAClC,4BAAgB,UAAU,MAAM,KAAK;AACrC,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,6CAA6C,KAAK;AAAA,IACxF;AAGA,QAAI;AACF,YAAM,gBAAgB,aAAa,QAAQ,UAAU;AACrD,UAAI,eAAe;AACjB,cAAM,qBAAqB,SAAS,eAAe,EAAE;AACrD,cAAM,UAAU,KAAK,IAAI,IAAI;AAE7B,YAAI,UAAU,eAAe;AAE3B,0BAAgB,UAAU;AAC1B,gBAAM,YAAY,gBAAgB;AAClC,2BAAiB,SAAS;AAE1B,cAAI,aAAa,cAAc;AAC7B,2BAAe,IAAI;AACnB,wBAAY;AAAA,UACd;AAEA,cAAI,aAAa,GAAG;AAClB,sBAAU,IAAI;AACd,qBAAS;AACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,4CAA4C,KAAK;AAAA,IACvF;AAGA,QAAI,0BAA0B,SAAS;AACrC,sBAAgB,QAAQ,WAAS;AAC/B,iBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,MACxE,CAAC;AAAA,IACH;AAGA,8BAA0B,UAAU,SAAS,CAAC,UAAU;AACtD,oBAAc;AAAA,IAChB,GAAG,GAAG;AAGN,oBAAgB,QAAQ,WAAS;AAC/B,eAAS,iBAAiB,OAAO,0BAA0B,SAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxF,CAAC;AAGD,kBAAc,IAAI;AAGlB,WAAO,MAAM;AAEX,UAAI,0BAA0B,SAAS;AACrC,wBAAgB,QAAQ,WAAS;AAC/B,mBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,QACxE,CAAC;AACD,kCAA0B,UAAU;AAAA,MACtC;AACA,kBAAY;AACZ,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,MAAM;AACzB,mBAAW,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,YAAY,aAAa,YAAY,eAAe,cAAc,QAAQ,WAAW,YAAY,aAAa,CAAC;AAG5H,QAAM,eAAeA,aAAY,MAAM;AACrC,kBAAc,KAAK;AACnB,gBAAY;AAGZ,QAAI,0BAA0B,SAAS;AACrC,sBAAgB,QAAQ,WAAS;AAC/B,iBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,MACxE,CAAC;AACD,gCAA0B,UAAU;AAAA,IACtC;AAEA,QAAI,WAAW,SAAS;AACtB,iBAAW,QAAQ,MAAM;AACzB,iBAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAGhB,EAAAD,WAAU,MAAM;AACd,QAAI,SAAS;AACX,YAAM,UAAU,cAAc;AAC9B,aAAO;AAAA,IACT,OAAO;AACL,mBAAa;AACb,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,cAAc,eAAe,YAAY,CAAC;AAGtE,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACvLA,SAAS,SAAS;;;AC7HX,IAAM,yBAAyB,CACpC,UACA,gBACA,eAAwB,UACH;AAGrB,QAAM,8BAA8B,CAAC,UAAwB;AAC3D,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AAEA,QAAI,CAAC,gBAAgB,CAAC,OAAO;AAC3B,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AAAA,EACF;AAGA,QAAM,2BAA2B,CAAC,UAA2B;AAE3D,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MAAU;AAAA,MACV;AAAA,MAAwB;AAAA;AAAA,MAExB;AAAA,MAA0B;AAAA,MAA4B;AAAA;AAAA,MAEtD;AAAA,MAAa;AAAA,MAAiB;AAAA,MAAe;AAAA;AAAA,MAE7C;AAAA,MAAgB;AAAA,MAAkB;AAAA,MAAa;AAAA,MAAoB;AAAA,MACnE;AAAA,MAAgB;AAAA,MAAgB;AAAA,MAAuB;AAAA,MAA4B;AAAA,MACnF;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,MAE1C;AAAA,MAAW;AAAA,MAAa;AAAA,MAAkB;AAAA,MAC1C;AAAA,MAAiB;AAAA,MAAqB;AAAA,MACtC;AAAA,MAAiB;AAAA,MAAiB;AAAA,MAAc;AAAA,MAAa;AAAA,MAC7D;AAAA,MAAkB;AAAA,MAAiB;AAAA,MAAgB;AAAA,MAAe;AAAA,MAClE;AAAA,MAAe;AAAA,MAAa;AAAA,MAAoB;AAAA,MAAoB;AAAA,IACtE;AAEA,WAAO,uBAAuB,SAAS,KAAK;AAAA,EAC9C;AAGA,QAAM,mBAAmB,CAAC,YAAgC;AACxD,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,gCAA4B,KAAK;AAEjC,QAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,MAAM;AAGhB,QAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,cAAQ,MAAM,GAAG,mBAAmB,KAAK;AAAA,IAC3C;AAGA,QAAI,SAAS;AACX,aAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,YAAI,UAAU,UAAa,UAAU,MAAM;AAEzC,gBAAM,aAAa,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,IAAK;AAC/D,kBAAQ,MAAM,GAAG,YAAY,KAAK;AAAA,QACpC;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,SAAS;AAEX,YAAM,gBAAgB,QAAQ,MAAM,GAAG,EAAE,IAAI;AAC7C,UAAI,eAAe;AACjB,gBAAQ,MAAM,MAAM,aAAa;AAAA,MACnC;AAAA,IACF;AAGA,QAAI,OAAO;AACT,cAAQ,MAAM,MAAM,KAAK;AAAA,IAC3B;AAEA,QAAI,QAAQ;AACV,cAAQ,MAAM,MAAM,QAAQ,UAAU,SAAS,MAAM,CAAC;AAAA,IACxD;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,OAAkD,YAA8C;AAClH,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,QAAI;AACF,YAAM,QAAQ,iBAAiB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM;AAE9B,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAGA,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,eAAO;AAAA,MACT;AAEA,aAAO,CAAC;AAAA,IACV,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,oBAAoB,OAAkD,YAAmD;AAC7H,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,QAAI;AACF,YAAM,QAAQ,iBAAiB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,MAAM,OAAO;AAE3C,UAAI,OAAO;AACT,YAAI,MAAM,SAAS,YAAY;AAE7B,iBAAO;AAAA,QACT;AACA,cAAM;AAAA,MACR;AAGA,UAAI,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,OAAO;AACzD,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,MACAE,oBACsB;AACtB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,YAAM,aAAa;AAAA,QACjB,GAAG;AAAA,QACH,iBAAiBA;AAAA,MACnB;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,SACnC,KAAK,KAAK,EACV,OAAO,UAAU,EACjB,OAAO,EACP,OAAO;AAEV,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,MACA,SACAA,oBACsB;AACtB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,UAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,IAAI;AAGd,UAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,gBAAQ,MAAM,GAAG,mBAAmBA,eAAc;AAAA,MACpD;AAGA,UAAI,SAAS;AACX,eAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,cAAI,UAAU,UAAa,UAAU,MAAM;AACzC,oBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,OAAO,EAAE,OAAO;AAE5D,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,SACAA,oBACqB;AACrB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,UAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO;AAGV,UAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,gBAAQ,MAAM,GAAG,mBAAmBA,eAAc;AAAA,MACpD;AAGA,UAAI,SAAS;AACX,eAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,cAAI,UAAU,UAAa,UAAU,MAAM;AACzC,oBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,EAAE,MAAM,IAAI,MAAM;AAExB,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,sBAAsB,OAC1B,OACA,QACAA,iBACA,YACiB;AACjB,WAAO,YAAe;AAAA,MACpB;AAAA,MACA;AAAA,MACA,gBAAAA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["jsx","formatTime","useState","useEffect","useCallback","useState","useEffect","useCallback","organisationId"]}
1
+ {"version":3,"sources":["../src/providers/OrganisationProvider.tsx","../src/components/InactivityWarningModal/InactivityWarningModal.tsx","../src/hooks/useInactivityTracker.ts","../src/index.ts","../src/utils/security/secureDataAccess.ts"],"sourcesContent":["/**\n * @file Organisation Provider\n * @package @jmruthers/pace-core\n * @module Providers\n * @since 0.1.0\n *\n * React provider for organisation context.\n * This is a convenience wrapper around OrganisationServiceProvider that\n * automatically gets auth context from UnifiedAuthProvider.\n * \n * Note: If you're using UnifiedAuthProvider, it already includes\n * OrganisationServiceProvider internally, so this component is mainly\n * for backward compatibility or standalone usage.\n */\n\nimport React from 'react';\nimport { useUnifiedAuth } from '../providers/services/UnifiedAuthProvider';\nimport { OrganisationServiceProvider } from './services/OrganisationServiceProvider';\nimport type { OrganisationProviderProps as BaseOrganisationProviderProps } from '../types/organisation';\n\nexport interface OrganisationProviderProps extends BaseOrganisationProviderProps {\n children: React.ReactNode;\n requireOrganisationContext?: boolean;\n autoSelectPrimaryOrganisation?: boolean;\n onOrganisationChange?: (organisation: any) => void;\n}\n\n/**\n * OrganisationProvider component\n * \n * Wraps OrganisationServiceProvider and automatically gets auth context.\n * \n * @example\n * ```tsx\n * <UnifiedAuthProvider supabaseClient={supabase} appName=\"my-app\">\n * <OrganisationProvider>\n * <App />\n * </OrganisationProvider>\n * </UnifiedAuthProvider>\n * ```\n */\nexport function OrganisationProvider({ \n children,\n requireOrganisationContext,\n autoSelectPrimaryOrganisation,\n onOrganisationChange\n}: OrganisationProviderProps) {\n // Get auth context from UnifiedAuthProvider\n const authContext = useUnifiedAuth();\n \n // If we're inside UnifiedAuthProvider, it already includes OrganisationServiceProvider\n // So we can just pass through the children\n // However, if the auth context is not available, we need to handle that\n if (!authContext) {\n // If no auth context, we can't provide organisation service\n // This might happen if used outside UnifiedAuthProvider\n // In that case, we should probably throw an error or show a message\n console.warn('OrganisationProvider: No auth context available. Make sure OrganisationProvider is used inside UnifiedAuthProvider.');\n return <>{children}</>;\n }\n\n const { supabase, user, session } = authContext;\n\n // Wrap with OrganisationServiceProvider\n // Note: The props like requireOrganisationContext, autoSelectPrimaryOrganisation\n // are handled by the OrganisationService internally, not by the provider\n // Note: supabase is mapped to supabaseClient for OrganisationServiceProvider\n if (!supabase) {\n console.warn('OrganisationProvider: No supabase client available.');\n return <>{children}</>;\n }\n\n return (\n <OrganisationServiceProvider\n supabaseClient={supabase}\n user={user}\n session={session}\n >\n {children}\n </OrganisationServiceProvider>\n );\n}\n\n","/**\n * @file Inactivity Warning Modal\n * @package @jmruthers/pace-core\n * @module Components/InactivityWarningModal\n * @since 0.1.0\n *\n * A modal dialog that warns users about impending auto-logout due to inactivity.\n * Provides a countdown timer and action buttons to either stay signed in or sign out immediately.\n *\n * Features:\n * - Accessible modal dialog with focus management\n * - Live countdown timer with 1-second updates\n * - Clear action buttons (Stay Signed In / Sign Out Now)\n * - Keyboard navigation support (Escape to stay signed in)\n * - Cross-tab awareness and synchronization\n * - Tailwind v4 styling with pace-core theme tokens\n * - Production-safe with no arbitrary bracket classes\n *\n * @example\n * ```tsx\n * <InactivityWarningModal\n * isOpen={showWarning}\n * timeRemaining={45}\n * onStaySignedIn={() => setShowWarning(false)}\n * onSignOutNow={() => signOut()}\n * />\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Focus trap within modal content\n * - Screen reader announcements for countdown changes\n * - Keyboard navigation support\n * - Clear visual hierarchy and contrast\n * - Escape key to stay signed in (safe default)\n *\n * @performance\n * - Efficient countdown updates (1-second intervals)\n * - Minimal re-renders with stable references\n * - Memory leak prevention with cleanup\n * - Optimized timer management\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - Dialog components - Modal functionality\n * - Tailwind CSS v4 - Styling\n */\n\nimport React, { useEffect, useState, useCallback } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '../Dialog/Dialog';\nimport { Button } from '../Button/Button';\nimport { Clock, AlertTriangle } from 'lucide-react';\nimport { cn } from '../../utils/core/cn';\n\nexport interface InactivityWarningModalProps {\n /** Whether the modal is open */\n isOpen: boolean;\n /** Time remaining in seconds before auto-logout */\n timeRemaining: number;\n /** Callback when user chooses to stay signed in */\n onStaySignedIn: () => void;\n /** Callback when user chooses to sign out immediately */\n onSignOutNow: () => void;\n /** Optional custom title */\n title?: string;\n /** Optional custom description */\n description?: string;\n /** Optional custom className */\n className?: string;\n}\n\nexport function InactivityWarningModal({\n isOpen,\n timeRemaining,\n onStaySignedIn,\n onSignOutNow,\n title = \"Session Timeout Warning\",\n description = \"You've been inactive for a while. Your session will expire soon for security reasons.\",\n className\n}: InactivityWarningModalProps) {\n const [displayTime, setDisplayTime] = useState(timeRemaining);\n\n // Update display time when timeRemaining prop changes\n useEffect(() => {\n setDisplayTime(timeRemaining);\n }, [timeRemaining]);\n\n // Format time for display (MM:SS)\n const formatTime = useCallback((seconds: number) => {\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }, []);\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onStaySignedIn()}>\n <DialogContent \n className={cn(\"sm:max-w-md\", className)}\n preventCloseOnEscape={false}\n preventCloseOnOutsideClick={true}\n data-testid=\"inactivity-warning-modal\"\n >\n <DialogHeader>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-shrink-0\">\n <AlertTriangle className=\"size-6 text-acc-600\" />\n </div>\n <div>\n <DialogTitle className=\"text-lg font-semibold text-main-900\">\n {title}\n </DialogTitle>\n </div>\n </div>\n <DialogDescription className=\"text-main-700 mt-2\">\n {description}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-6\">\n {/* Countdown Timer */}\n <div className=\"text-center\">\n <div className=\"inline-flex items-center gap-2 px-4 py-3 bg-acc-50 border border-acc-200 rounded-lg\">\n <Clock className=\"size-5 text-acc-600\" />\n <span className=\"text-2xl font-mono font-bold text-acc-700\">\n {formatTime(displayTime)}\n </span>\n </div>\n <p className=\"text-sm text-main-600 mt-2\">\n Time remaining before automatic logout\n </p>\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex flex-col sm:flex-row gap-3\">\n <Button\n onClick={onStaySignedIn}\n className=\"flex-1 bg-main-600 hover:bg-main-700 text-main-50\"\n size=\"lg\"\n >\n Stay Signed In\n </Button>\n <Button\n onClick={onSignOutNow}\n variant=\"outline\"\n className=\"flex-1 border-acc-300 text-acc-700 hover:bg-acc-50\"\n size=\"lg\"\n >\n Sign Out Now\n </Button>\n </div>\n\n {/* Additional Info */}\n <div className=\"text-xs text-main-500 text-center\">\n <p>\n For security reasons, you'll be automatically signed out after 30 minutes of inactivity.\n </p>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n","/**\n * @file Inactivity Tracker Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useInactivityTracker\n * @since 0.1.0\n *\n * A custom hook that tracks user inactivity and provides cross-tab synchronization.\n * Monitors various user interactions and manages inactivity timers with persistence.\n *\n * Features:\n * - Cross-tab synchronization using BroadcastChannel and localStorage\n * - Monitors keyboard, mouse, touch, scroll, and focus events\n * - Throttled event handling for performance\n * - Persistence of last activity time across page reloads\n * - SSR-safe implementation with proper cleanup\n * - Configurable timeout and warning thresholds\n * - Production-safe with dev-only escape hatches\n *\n * @example\n * ```tsx\n * const {\n * isIdle,\n * timeRemaining,\n * showWarning,\n * resetActivity,\n * startTracking,\n * stopTracking\n * } = useInactivityTracker({\n * idleTimeoutMs: 30 * 60 * 1000, // 30 minutes\n * warnBeforeMs: 60 * 1000, // 1 minute\n * onIdle: () => console.log('User is idle'),\n * onWarning: () => console.log('Warning should show'),\n * onActivity: () => console.log('User is active')\n * });\n * ```\n *\n * @accessibility\n * - No direct accessibility concerns (utility hook)\n * - Enables accessible inactivity warnings\n * - Supports screen reader friendly countdowns\n * - Maintains focus management during warnings\n *\n * @performance\n * - Throttled event handling (100ms intervals)\n * - Efficient timer management with cleanup\n * - Minimal re-renders with stable references\n * - Memory leak prevention\n * - Cross-tab optimization\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - Browser APIs - BroadcastChannel, localStorage, timers\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { logger } from '../utils/core/logger';\n\nexport interface UseInactivityTrackerOptions {\n /** Timeout in milliseconds before user is considered idle (default: 30 minutes) */\n idleTimeoutMs?: number;\n /** Time in milliseconds before idle timeout to show warning (default: 60 seconds) */\n warnBeforeMs?: number;\n /** Callback when user becomes idle */\n onIdle?: () => void;\n /** Callback when warning should be shown */\n onWarning?: () => void;\n /** Callback when user becomes active again */\n onActivity?: () => void;\n /** Whether tracking is enabled (default: true) */\n enabled?: boolean;\n /** Storage key for persistence (default: 'pace-core-inactivity') */\n storageKey?: string;\n /** Broadcast channel name for cross-tab sync (default: 'pace-core-inactivity') */\n channelName?: string;\n}\n\nexport interface UseInactivityTrackerReturn {\n /** Whether the user is currently idle */\n isIdle: boolean;\n /** Time remaining in milliseconds before idle timeout */\n timeRemaining: number;\n /** Whether warning should be shown */\n showWarning: boolean;\n /** Reset the activity timer */\n resetActivity: () => void;\n /** Start tracking inactivity */\n startTracking: () => void;\n /** Stop tracking inactivity */\n stopTracking: () => void;\n /** Whether tracking is currently active */\n isTracking: boolean;\n}\n\n// Events that indicate user activity\nconst ACTIVITY_EVENTS = [\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'click',\n 'scroll',\n 'wheel',\n 'touchstart',\n 'touchmove',\n 'touchend',\n 'keydown',\n 'keyup',\n 'keypress',\n 'focus',\n 'blur',\n 'visibilitychange'\n] as const;\n\n// Throttle function to limit event handler frequency\nfunction throttle<T extends (...args: any[]) => void>(\n func: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let inThrottle: boolean;\n return function (this: any, ...args: Parameters<T>) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => (inThrottle = false), limit);\n }\n };\n}\n\nexport function useInactivityTracker({\n idleTimeoutMs = 30 * 60 * 1000, // 30 minutes\n warnBeforeMs = 60 * 1000, // 1 minute\n onIdle,\n onWarning,\n onActivity,\n enabled = true,\n storageKey = 'pace-core-inactivity',\n channelName = 'pace-core-inactivity'\n}: UseInactivityTrackerOptions = {}): UseInactivityTrackerReturn {\n const [isIdle, setIsIdle] = useState(false);\n const [timeRemaining, setTimeRemaining] = useState(idleTimeoutMs);\n const [showWarning, setShowWarning] = useState(false);\n const [isTracking, setIsTracking] = useState(false);\n\n // Reset tracking state when enabled changes\n useEffect(() => {\n if (!enabled) {\n setIsTracking(false);\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n }\n }, [enabled, idleTimeoutMs]);\n\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const warningTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const countdownIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const lastActivityRef = useRef<number>(Date.now());\n const channelRef = useRef<BroadcastChannel | null>(null);\n const throttledResetActivityRef = useRef<((event: Event) => void) | null>(null);\n const onIdleRef = useRef(onIdle);\n const onWarningRef = useRef(onWarning);\n const onActivityRef = useRef(onActivity);\n\n useEffect(() => {\n onIdleRef.current = onIdle;\n onWarningRef.current = onWarning;\n onActivityRef.current = onActivity;\n }, [onIdle, onWarning, onActivity]);\n\n // Clear all timers\n const clearTimers = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (warningTimeoutRef.current) {\n clearTimeout(warningTimeoutRef.current);\n warningTimeoutRef.current = null;\n }\n if (countdownIntervalRef.current) {\n clearInterval(countdownIntervalRef.current);\n countdownIntervalRef.current = null;\n }\n }, []);\n\n // Reset activity and restart timers\n const resetActivity = useCallback((skipActivityCallback = false) => {\n if (!enabled) return;\n\n const now = Date.now();\n lastActivityRef.current = now;\n\n // Clear existing timers\n clearTimers();\n\n // Reset state\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n\n // Notify activity callback (unless skipped for initial setup)\n if (!skipActivityCallback) {\n onActivityRef.current?.();\n }\n\n // Set up warning timer\n const warningTime = idleTimeoutMs - warnBeforeMs;\n if (warningTime > 0) {\n warningTimeoutRef.current = setTimeout(() => {\n setShowWarning(true);\n onWarningRef.current?.();\n }, warningTime);\n }\n\n // Set up idle timeout\n timeoutRef.current = setTimeout(() => {\n setIsIdle(true);\n onIdleRef.current?.();\n }, idleTimeoutMs);\n\n // Start countdown interval for time remaining\n countdownIntervalRef.current = setInterval(() => {\n const elapsed = Date.now() - lastActivityRef.current;\n const remaining = Math.max(0, idleTimeoutMs - elapsed);\n setTimeRemaining(remaining);\n\n if (remaining === 0) {\n clearTimers();\n }\n }, 1000);\n\n // Persist activity time\n try {\n localStorage.setItem(storageKey, now.toString());\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to persist activity time:', error);\n }\n\n // Broadcast activity to other tabs\n try {\n if (channelRef.current) {\n channelRef.current.postMessage({ type: 'activity', timestamp: now });\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to broadcast activity:', error);\n }\n }, [enabled, idleTimeoutMs, warnBeforeMs, storageKey, clearTimers]);\n\n // Start tracking\n const startTracking = useCallback(() => {\n if (!enabled) return;\n\n // Always reset state and start fresh\n setIsTracking(false);\n setIsIdle(false);\n setShowWarning(false);\n setTimeRemaining(idleTimeoutMs);\n \n // Clear any existing timers\n clearTimers();\n \n setIsTracking(true);\n\n // Set up cross-tab communication\n try {\n if (typeof BroadcastChannel !== 'undefined') {\n channelRef.current = new BroadcastChannel(channelName);\n channelRef.current.onmessage = (event) => {\n if (event.data.type === 'activity') {\n lastActivityRef.current = event.data.timestamp;\n resetActivity();\n }\n };\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to set up cross-tab communication:', error);\n }\n\n // Check for persisted activity time\n try {\n const persistedTime = localStorage.getItem(storageKey);\n if (persistedTime) {\n const persistedTimestamp = parseInt(persistedTime, 10);\n const elapsed = Date.now() - persistedTimestamp;\n \n if (elapsed < idleTimeoutMs) {\n // User was active recently, continue from where we left off\n lastActivityRef.current = persistedTimestamp;\n const remaining = idleTimeoutMs - elapsed;\n setTimeRemaining(remaining);\n \n if (remaining <= warnBeforeMs) {\n setShowWarning(true);\n onWarningRef.current?.();\n }\n \n if (remaining <= 0) {\n setIsIdle(true);\n onIdleRef.current?.();\n return;\n }\n }\n }\n } catch (error) {\n logger.warn('useInactivityTracker', 'Failed to check persisted activity time:', error);\n }\n\n // Clean up any existing throttled handler and event listeners first\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n }\n\n // Set up throttled activity handler - store in ref for proper cleanup\n throttledResetActivityRef.current = throttle((event) => {\n resetActivity();\n }, 100);\n\n // Add event listeners\n ACTIVITY_EVENTS.forEach(event => {\n document.addEventListener(event, throttledResetActivityRef.current!, { passive: true });\n });\n\n // Start the timer (skip activity callback for initial setup)\n resetActivity(true);\n\n // Cleanup function\n return () => {\n // Remove event listeners using the stored ref\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n throttledResetActivityRef.current = null;\n }\n clearTimers();\n if (channelRef.current) {\n channelRef.current.close();\n channelRef.current = null;\n }\n };\n }, [enabled, channelName, storageKey, idleTimeoutMs, warnBeforeMs, resetActivity, clearTimers]);\n\n // Stop tracking\n const stopTracking = useCallback(() => {\n setIsTracking(false);\n clearTimers();\n \n // Remove event listeners\n if (throttledResetActivityRef.current) {\n ACTIVITY_EVENTS.forEach(event => {\n document.removeEventListener(event, throttledResetActivityRef.current!);\n });\n throttledResetActivityRef.current = null;\n }\n \n if (channelRef.current) {\n channelRef.current.close();\n channelRef.current = null;\n }\n }, [clearTimers]);\n\n // Effect to start/stop tracking based on enabled state\n useEffect(() => {\n if (enabled) {\n const cleanup = startTracking();\n return cleanup;\n } else {\n stopTracking();\n return undefined;\n }\n }, [enabled, idleTimeoutMs, warnBeforeMs, startTracking, stopTracking]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n clearTimers();\n if (channelRef.current) {\n channelRef.current.close();\n }\n };\n }, [clearTimers]);\n\n return {\n isIdle,\n timeRemaining,\n showWarning,\n resetActivity,\n startTracking,\n stopTracking,\n isTracking\n };\n}\n","/**\n * @file Complete Component Library Export\n * @package @jmruthers/pace-core\n * @module Core\n * @since 0.1.0\n * \n * This file exports the primary components, hooks, and utilities from the PACE Core library.\n * It is the main entry point for developers using the library.\n * \n * @example\n * // Import common components\n * import { Button, Card, useUnifiedAuth } from '@jmruthers/pace-core';\n * \n * // For specialized components, use the complete library import:\n * import { Dialog, NavigationMenu } from '@jmruthers/pace-core/components';\n */\n\n// AUTHENTICATION & AUTHORIZATION\n// Note: Providers are now service-based architecture for better testability and maintainability\nexport { UnifiedAuthProvider, useUnifiedAuth } from './providers/services/UnifiedAuthProvider';\nexport type { UnifiedAuthProviderProps, UnifiedAuthContextType, UserEventAccess } from './providers/services/UnifiedAuthProvider';\n\n// Session tracking utility (for manual use if needed)\nexport { useSessionTracking } from './utils/context/sessionTracking';\n\n// Provider components (using service architecture)\nexport { EventServiceProvider } from './providers/services/EventServiceProvider';\nexport { OrganisationServiceProvider } from './providers/services/OrganisationServiceProvider';\nexport { InactivityServiceProvider } from './providers/services/InactivityServiceProvider';\n\n// Convenience provider wrapper (backward compatibility)\nexport { OrganisationProvider } from './providers/OrganisationProvider';\nexport type { OrganisationProviderProps } from './providers/OrganisationProvider';\n\n// Convenience hooks\nexport { useEvents } from './hooks/useEvents';\nexport { useOrganisations } from './hooks/useOrganisations';\n\n// Service hooks for advanced usage (better performance)\nexport { useEventService } from './hooks/services/useEventService';\nexport { useOrganisationService } from './hooks/services/useOrganisationService';\nexport { useAuthService } from './hooks/services/useAuthService';\nexport { useInactivityService } from './hooks/services/useInactivityService';\nexport { useSessionRestoration } from './hooks/useSessionRestoration';\n\nexport type { \n Organisation, \n OrganisationMembership, \n OrganisationContextType, \n OrganisationSecurityError \n} from './types/organisation';\n\n// INACTIVITY TRACKING\nexport { InactivityWarningModal } from './components/InactivityWarningModal/InactivityWarningModal';\nexport type { InactivityWarningModalProps } from './components/InactivityWarningModal/InactivityWarningModal';\nexport { useInactivityTracker } from './hooks/useInactivityTracker';\nexport type { UseInactivityTrackerOptions, UseInactivityTrackerReturn } from './hooks/useInactivityTracker';\n\n// RBAC SYSTEM - Consolidated RBAC module\nexport * from './rbac';\n\n// BASIC UI COMPONENTS\nexport { Button } from './components/Button/Button';\nexport type { ButtonProps } from './components/Button/Button';\n\nexport { \n Card, \n CardHeader, \n CardFooter, \n CardTitle, \n CardDescription, \n CardContent,\n CardActions\n} from './components/Card/Card';\nexport type { CardProps } from './components/Card/Card';\n\nexport { Input } from './components/Input/Input';\nexport type { InputProps } from './components/Input/Input';\nexport { AddressField } from './components/AddressField';\nexport type { AddressFieldProps, AddressFieldRef, ParsedAddress, AutocompleteOptions } from './components/AddressField';\nexport { Label } from './components/Label/Label';\nexport type { LabelProps } from './components/Label/Label';\n\nexport { Textarea } from './components/Textarea/Textarea';\nexport type { TextareaProps } from './components/Textarea/Textarea';\n\nexport { Alert, AlertTitle, AlertDescription } from './components/Alert/Alert';\nexport { Avatar } from './components/Avatar/Avatar';\nexport type { AvatarProps } from './components/Avatar/Avatar';\n\nexport { Badge } from './components/Badge/Badge';\nexport type { BadgeProps, BadgeVariant } from './components/Badge/Badge';\n\nexport { Checkbox } from './components/Checkbox/Checkbox';\nexport { Switch } from './components/Switch/Switch';\nexport type { SwitchProps } from './components/Switch/Switch';\nexport { Progress } from './components/Progress';\nexport type { ProgressProps } from './components/Progress';\n\n// ADVANCED UI COMPONENTS\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogBody,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n} from './components/Dialog/Dialog';\n\n// Dropdown Menu exports\n// DropdownMenu components have been merged into Select components\n\n// Select exports\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n} from './components/Select';\n\n// Tabs exports\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './components/Tabs/Tabs';\nexport type { TabsProps, TabsListProps, TabsTriggerProps, TabsContentProps } from './components/Tabs/Tabs';\n\n// Calendar exports\nexport { Calendar } from './components/Calendar/Calendar';\nexport type { CalendarProps } from './components/Calendar/Calendar';\n\n// Modal functionality is provided by Dialog components\n\nexport {\n Toast,\n Toaster,\n ToastAction,\n ToastProvider,\n ToastViewport,\n ToastTitle,\n ToastDescription,\n ToastClose,\n} from './components/Toast/Toast';\nexport { useToast } from './hooks/useToast';\nexport type { ToastActionElement, ToastProps } from './components/Toast/Toast';\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TooltipRoot } from './components/Tooltip/Tooltip';\n\n// DATA DISPLAY COMPONENTS\nexport {\n DataTable,\n type DataTableProps,\n type DataTableColumn,\n type DataTableAction,\n type DataTableToolbarButton,\n type AggregateConfig,\n type EmptyStateConfig,\n type GetRowId,\n type DataTableFeatureConfig,\n ColumnFactory\n} from './components/DataTable';\n\n// Re-export types from DataTable types\nexport type { DataRecord, ExportOptions } from './components/DataTable/types';\n\n// Export DataTable utility functions\nexport {\n exportToCSV,\n exportToCSVWithTableRows,\n generateCSVContent,\n type ExportColumn\n} from './components/DataTable/utils/exportUtils';\n\n// Export DataTable aggregation utilities\nexport {\n sum,\n average,\n count,\n min,\n max\n} from './components/DataTable/utils/aggregationUtils';\n\n// FORM COMPONENTS\nexport { Form, FormField } from './components/Form/Form';\nexport type { FormProps, FormFieldProps } from './components/Form/Form';\nexport { LoginForm } from './components/LoginForm';\nexport type { LoginFormProps } from './components/LoginForm';\n\n// FORM HOOKS\nexport { useZodForm } from './hooks/useZodForm';\nexport { useFormDialog } from './hooks/useFormDialog';\nexport type { UseFormDialogOptions, UseFormDialogReturn } from './hooks/useFormDialog';\n\n// VALIDATION - Re-export zod for schema creation\nexport { z } from 'zod';\n// Common validation schemas\nexport { emailSchema, nameSchema, phoneSchema, urlSchema } from './utils/validation/common';\nexport { passwordSchema } from './utils/validation/passwordSchema';\n\n// LAYOUT COMPONENTS\nexport { Header } from './components/Header/Header';\nexport { Footer } from './components/Footer/Footer';\nexport type { FooterProps } from './components/Footer/Footer';\n\n// NAVIGATION COMPONENTS\nexport { NavigationMenu } from './components/NavigationMenu/NavigationMenu';\nexport type { NavigationMenuProps, NavigationItem, NavigationMode } from './components/NavigationMenu/NavigationMenu';\nexport { UserMenu } from './components/UserMenu/UserMenu';\nexport type { UserMenuProps } from './components/UserMenu/UserMenu';\n\n// Reusable Page/Layout Components\nexport { PaceAppLayout } from './components/PaceAppLayout/PaceAppLayout';\nexport type { PaceAppLayoutProps } from './components/PaceAppLayout/PaceAppLayout';\nexport { PaceLoginPage } from './components/PaceLoginPage/PaceLoginPage';\nexport type { PaceLoginPageProps } from './components/PaceLoginPage/PaceLoginPage';\n\nexport { ProtectedRoute } from './components/ProtectedRoute/ProtectedRoute';\nexport type { ProtectedRouteProps } from './components/ProtectedRoute/ProtectedRoute';\n\n// UTILITY COMPONENTS\nexport { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary';\nexport { LoadingSpinner } from './components/LoadingSpinner/LoadingSpinner';\nexport { SessionRestorationLoader } from './components/SessionRestorationLoader/SessionRestorationLoader';\nexport type { SessionRestorationLoaderProps } from './components/SessionRestorationLoader/SessionRestorationLoader';\n\n// EVENT MANAGEMENT\nexport { EventSelector } from './components/EventSelector/EventSelector';\n\n// ORGANISATION MANAGEMENT\nexport { OrganisationSelector } from './components/OrganisationSelector/OrganisationSelector';\nexport { useOrganisationPermissions } from './hooks/useOrganisationPermissions';\nexport { useOrganisationSecurity } from './hooks/useOrganisationSecurity';\nexport { createSecureDataAccess } from './utils/security/secureDataAccess';\n\n// TYPES\nexport type { UserProfile } from './types/organisation';\n\n// AUTHENTICATION FORMS\nexport { PasswordChangeForm } from './components/PasswordChange/PasswordChangeForm';\n\n// UTILS & HOOKS\nexport { useAppConfig } from './hooks/useAppConfig';\nexport { useEventTheme } from './hooks/useEventTheme';\nexport { cn } from './utils/core/cn';\nexport { setAppConfig, getAppConfig, getCurrentAppName, getCurrentAppId } from './utils/app/appConfig';\n\n// LOGGING UTILITIES\nexport { Logger, logger, createLogger, LogLevel } from './utils/core/logger';\nexport type { LoggerConfig } from './utils/core/logger';\n\n// FORMATTING UTILITIES\nexport { \n formatDate,\n formatTime,\n formatDateTime,\n formatCurrency, \n formatNumber,\n formatPercent,\n formatCompactNumber,\n formatFileSize\n} from './utils/formatting/formatting';\n\n// TIMEZONE UTILITIES\nexport {\n formatInTimeZone,\n getTimezoneAbbreviation,\n formatTimeInTimeZone,\n getUserTimeZone,\n toZonedTime,\n fromZonedTime,\n roundToNearestMinutes,\n getTimeZoneDifference\n} from './utils/timezone';\n\n// STORAGE UTILITIES\nexport { FileUpload } from './components/FileUpload';\nexport type { FileUploadProps } from './components/FileUpload';\nexport { FileDisplay } from './components/FileDisplay';\nexport type { FileDisplayProps } from './components/FileDisplay';\nexport { FileCategory } from './types/file-reference';\nexport type { FileReference, FileMetadata, FileUploadOptions } from './types/file-reference';\nexport { \n useFileReference, \n useFileReferenceForRecord,\n useFileReferenceById,\n useFilesByCategory\n} from './hooks/useFileReference';\nexport type { \n UseFileReferenceOptions, \n UseFileReferenceReturn, \n UseFileReferenceForRecordReturn \n} from './hooks/useFileReference';\nexport * from './utils/storage';\n\n// Table components\nexport {\n Table,\n TableHeader,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableRow,\n} from './components/Table/Table';\n\n// STYLES & THEMING\nexport * from './styles';\n// Direct export of theming utilities for convenience\nexport { parseAndNormalizeEventColours } from './theming/parseEventColours';\nexport { applyPalette, clearPalette } from './theming/runtime';\nexport type { PaletteData, ColorPalette, ColorShade } from './theming/runtime';\n\n// PUBLIC PAGES\nexport * from './hooks/public';\nexport * from './components/PublicLayout';\n","/**\n * @file Secure Data Access Utility\n * @package @jmruthers/pace-core\n * @module Utils/SecureDataAccess\n * @since 0.4.0\n *\n * Secure data access utilities that enforce organisation context for all database operations.\n * Prevents data leakage between organisations and ensures proper access validation.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\n\n// Generic database record type\nexport interface DatabaseRecord {\n id: string;\n organisation_id: string;\n [key: string]: unknown;\n}\n\n// Generic data for insert/update operations\nexport interface DatabaseData {\n [key: string]: unknown;\n}\n\n// Generic filters for queries\nexport interface DatabaseFilters {\n [key: string]: unknown;\n}\n\n// Secure query options\nexport interface SecureQueryOptions {\n table: string;\n select: string;\n organisationId: string;\n filters?: DatabaseFilters;\n orderBy?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface SecureDataAccess {\n // Secure query methods\n secureQuery: <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions) => Promise<T[]>;\n secureSingleQuery: <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions) => Promise<T | null>;\n \n // Secure mutation methods\n secureInsert: <T extends DatabaseRecord = DatabaseRecord>(table: string, data: DatabaseData, organisationId: string) => Promise<T | null>;\n secureUpdate: <T extends DatabaseRecord = DatabaseRecord>(table: string, data: DatabaseData, filters: DatabaseFilters, organisationId: string) => Promise<T | null>;\n secureDelete: (table: string, filters: DatabaseFilters, organisationId: string) => Promise<boolean>;\n \n // Organisation-scoped queries\n queryByOrganisation: <T extends DatabaseRecord = DatabaseRecord>(table: string, select: string, organisationId: string, filters?: DatabaseFilters) => Promise<T[]>;\n \n // Validation helpers\n validateOrganisationContext: (organisationId: string) => void;\n ensureOrganisationColumn: (table: string) => boolean;\n}\n\nexport interface SecureQueryBuilder {\n table: string;\n select: string;\n organisationId: string;\n filters?: DatabaseFilters;\n orderBy?: string;\n limit?: number;\n offset?: number;\n}\n\n/**\n * Create a secure data access instance\n * @param supabase - Supabase client instance\n * @param organisationId - Current organisation context\n * @param isSuperAdmin - Whether user has super admin privileges\n * @returns Secure data access utilities\n */\nexport const createSecureDataAccess = (\n supabase: SupabaseClient,\n organisationId: string,\n isSuperAdmin: boolean = false\n): SecureDataAccess => {\n \n // Validate organisation context\n const validateOrganisationContext = (orgId: string): void => {\n if (!orgId) {\n throw new Error('Organisation context is required for secure data access');\n }\n \n if (!isSuperAdmin && !orgId) {\n throw new Error('Organisation context is mandatory for non-super admin users');\n }\n };\n\n // Check if table has organisation_id column\n const ensureOrganisationColumn = (table: string): boolean => {\n // This is a simplified check - in production you might want to cache this\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n return tablesWithOrganisation.includes(table);\n };\n\n // Build secure query with organisation context\n const buildSecureQuery = (options: SecureQueryBuilder) => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n validateOrganisationContext(orgId);\n \n let query = supabase\n .from(table)\n .select(select);\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', orgId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n // Handle qualified column names (e.g., 'users.role')\n const columnName = key.includes('.') ? key.split('.').pop()! : key;\n query = query.eq(columnName, value);\n }\n });\n }\n \n // Add ordering\n if (orderBy) {\n // Only use the column name, not a qualified name\n const orderByColumn = orderBy.split('.').pop();\n if (orderByColumn) {\n query = query.order(orderByColumn);\n }\n }\n \n // Add pagination\n if (limit) {\n query = query.limit(limit);\n }\n \n if (offset) {\n query = query.range(offset, offset + (limit || 10) - 1);\n }\n \n return query;\n };\n\n // Secure query for multiple results\n const secureQuery = async <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions): Promise<T[]> => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n try {\n const query = buildSecureQuery({\n table,\n select,\n organisationId: orgId,\n filters,\n orderBy,\n limit,\n offset\n });\n \n const { data, error } = await query;\n \n if (error) {\n throw error;\n }\n \n // Ensure data is an array and not an error type\n if (Array.isArray(data)) {\n return data as unknown as T[];\n }\n \n return [];\n } catch (error) {\n throw error;\n }\n };\n\n // Secure query for single result\n const secureSingleQuery = async <T extends DatabaseRecord = DatabaseRecord>(options: SecureQueryOptions): Promise<T | null> => {\n const { table, select, organisationId: orgId, filters, orderBy, limit, offset } = options;\n \n try {\n const query = buildSecureQuery({\n table,\n select,\n organisationId: orgId,\n filters,\n orderBy,\n limit,\n offset\n });\n \n const { data, error } = await query.single();\n \n if (error) {\n if (error.code === 'PGRST116') {\n // No rows returned\n return null;\n }\n throw error;\n }\n \n // Ensure data is not an error type\n if (data && typeof data === 'object' && !('code' in data)) {\n return data as unknown as T;\n }\n \n return null;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure insert with organisation context\n const secureInsert = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n data: DatabaseData, \n organisationId: string\n ): Promise<T | null> => {\n validateOrganisationContext(organisationId);\n \n try {\n const insertData = {\n ...data,\n organisation_id: organisationId\n };\n \n const { data: result, error } = await supabase\n .from(table)\n .insert(insertData)\n .select()\n .single();\n \n if (error) {\n throw error;\n }\n \n return result;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure update with organisation context\n const secureUpdate = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n data: DatabaseData, \n filters: DatabaseFilters, \n organisationId: string\n ): Promise<T | null> => {\n validateOrganisationContext(organisationId);\n \n try {\n let query = supabase\n .from(table)\n .update(data);\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n }\n \n const { data: result, error } = await query.select().single();\n \n if (error) {\n throw error;\n }\n \n return result;\n } catch (error) {\n throw error;\n }\n };\n\n // Secure delete with organisation context\n const secureDelete = async (\n table: string, \n filters: DatabaseFilters, \n organisationId: string\n ): Promise<boolean> => {\n validateOrganisationContext(organisationId);\n \n try {\n let query = supabase\n .from(table)\n .delete();\n \n // Add organisation filter (unless super admin)\n if (!isSuperAdmin && ensureOrganisationColumn(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n \n // Add additional filters\n if (filters) {\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n }\n \n const { error } = await query;\n \n if (error) {\n throw error;\n }\n \n return true;\n } catch (error) {\n throw error;\n }\n };\n\n // Organisation-scoped query helper\n const queryByOrganisation = async <T extends DatabaseRecord = DatabaseRecord>(\n table: string, \n select: string, \n organisationId: string, \n filters?: DatabaseFilters\n ): Promise<T[]> => {\n return secureQuery<T>({\n table,\n select,\n organisationId,\n filters\n });\n };\n\n return {\n secureQuery,\n secureSingleQuery,\n secureInsert,\n secureUpdate,\n secureDelete,\n queryByOrganisation,\n validateOrganisationContext,\n ensureOrganisationColumn\n };\n};\n\n/**\n * Hook for secure data access\n * @returns Secure data access utilities\n */\nexport const useSecureDataAccess = (): SecureDataAccess => {\n // This would typically get the context from providers\n // For now, we'll create a placeholder that can be used with explicit parameters\n throw new Error('useSecureDataAccess must be used with explicit parameters. Use createSecureDataAccess instead.');\n}; "],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DW;AAjBJ,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAE5B,QAAM,cAAc,eAAe;AAKnC,MAAI,CAAC,aAAa;AAIhB,YAAQ,KAAK,qHAAqH;AAClI,WAAO,gCAAG,UAAS;AAAA,EACrB;AAEA,QAAM,EAAE,UAAU,MAAM,QAAQ,IAAI;AAMpC,MAAI,CAAC,UAAU;AACb,YAAQ,KAAK,qDAAqD;AAClE,WAAO,gCAAG,UAAS;AAAA,EACrB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;ACjCA,SAAgB,WAAW,UAAU,mBAAmB;AAGxD,SAAS,OAAO,qBAAqB;AAoD3B,SAEI,OAAAA,MAFJ;AAhCH,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd;AACF,GAAgC;AAC9B,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,aAAa;AAG5D,YAAU,MAAM;AACd,mBAAe,aAAa;AAAA,EAC9B,GAAG,CAAC,aAAa,CAAC;AAGlB,QAAMC,cAAa,YAAY,CAAC,YAAoB;AAClD,UAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,UAAM,OAAO,UAAU;AACvB,WAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EAChF,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAD,KAAC,UAAO,MAAM,QAAQ,cAAc,CAAC,SAAS,CAAC,QAAQ,eAAe,GACpE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,eAAe,SAAS;AAAA,MACtC,sBAAsB;AAAA,MACtB,4BAA4B;AAAA,MAC5B,eAAY;AAAA,MAEZ;AAAA,6BAAC,gBACC;AAAA,+BAAC,SAAI,WAAU,2BACb;AAAA,4BAAAA,KAAC,SAAI,WAAU,iBACb,0BAAAA,KAAC,iBAAc,WAAU,uBAAsB,GACjD;AAAA,YACA,gBAAAA,KAAC,SACC,0BAAAA,KAAC,eAAY,WAAU,uCACpB,iBACH,GACF;AAAA,aACF;AAAA,UACA,gBAAAA,KAAC,qBAAkB,WAAU,sBAC1B,uBACH;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,aAEb;AAAA,+BAAC,SAAI,WAAU,eACb;AAAA,iCAAC,SAAI,WAAU,uFACb;AAAA,8BAAAA,KAAC,SAAM,WAAU,uBAAsB;AAAA,cACvC,gBAAAA,KAAC,UAAK,WAAU,6CACb,UAAAC,YAAW,WAAW,GACzB;AAAA,eACF;AAAA,YACA,gBAAAD,KAAC,OAAE,WAAU,8BAA6B,oDAE1C;AAAA,aACF;AAAA,UAGA,qBAAC,SAAI,WAAU,mCACb;AAAA,4BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,WAAU;AAAA,gBACV,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,SAAQ;AAAA,gBACR,WAAU;AAAA,gBACV,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,aACF;AAAA,UAGA,gBAAAA,KAAC,SAAI,WAAU,qCACb,0BAAAA,KAAC,OAAE,sGAEH,GACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;;;AC3GA,SAAS,YAAAE,WAAU,aAAAC,YAAW,eAAAC,cAAa,cAAc;AAwCzD,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,SACP,MACA,OACkC;AAClC,MAAI;AACJ,SAAO,YAAwB,MAAqB;AAClD,QAAI,CAAC,YAAY;AACf,WAAK,MAAM,MAAM,IAAI;AACrB,mBAAa;AACb,iBAAW,MAAO,aAAa,OAAQ,KAAK;AAAA,IAC9C;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB;AAAA,EACnC,gBAAgB,KAAK,KAAK;AAAA;AAAA,EAC1B,eAAe,KAAK;AAAA;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,aAAa;AAAA,EACb,cAAc;AAChB,IAAiC,CAAC,GAA+B;AAC/D,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAAS,aAAa;AAChE,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAGlD,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,oBAAc,KAAK;AACnB,gBAAU,KAAK;AACf,qBAAe,KAAK;AACpB,uBAAiB,aAAa;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,QAAM,aAAa,OAA8B,IAAI;AACrD,QAAM,oBAAoB,OAA8B,IAAI;AAC5D,QAAM,uBAAuB,OAA8B,IAAI;AAC/D,QAAM,kBAAkB,OAAe,KAAK,IAAI,CAAC;AACjD,QAAM,aAAa,OAAgC,IAAI;AACvD,QAAM,4BAA4B,OAAwC,IAAI;AAC9E,QAAM,YAAY,OAAO,MAAM;AAC/B,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,gBAAgB,OAAO,UAAU;AAEvC,EAAAA,WAAU,MAAM;AACd,cAAU,UAAU;AACpB,iBAAa,UAAU;AACvB,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,QAAQ,WAAW,UAAU,CAAC;AAGlC,QAAM,cAAcC,aAAY,MAAM;AACpC,QAAI,WAAW,SAAS;AACtB,mBAAa,WAAW,OAAO;AAC/B,iBAAW,UAAU;AAAA,IACvB;AACA,QAAI,kBAAkB,SAAS;AAC7B,mBAAa,kBAAkB,OAAO;AACtC,wBAAkB,UAAU;AAAA,IAC9B;AACA,QAAI,qBAAqB,SAAS;AAChC,oBAAc,qBAAqB,OAAO;AAC1C,2BAAqB,UAAU;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,gBAAgBA,aAAY,CAAC,uBAAuB,UAAU;AAClE,QAAI,CAAC,QAAS;AAEd,UAAM,MAAM,KAAK,IAAI;AACrB,oBAAgB,UAAU;AAG1B,gBAAY;AAGZ,cAAU,KAAK;AACf,mBAAe,KAAK;AACpB,qBAAiB,aAAa;AAG9B,QAAI,CAAC,sBAAsB;AACzB,oBAAc,UAAU;AAAA,IAC1B;AAGA,UAAM,cAAc,gBAAgB;AACpC,QAAI,cAAc,GAAG;AACnB,wBAAkB,UAAU,WAAW,MAAM;AAC3C,uBAAe,IAAI;AACnB,qBAAa,UAAU;AAAA,MACzB,GAAG,WAAW;AAAA,IAChB;AAGA,eAAW,UAAU,WAAW,MAAM;AACpC,gBAAU,IAAI;AACd,gBAAU,UAAU;AAAA,IACtB,GAAG,aAAa;AAGhB,yBAAqB,UAAU,YAAY,MAAM;AAC/C,YAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB;AAC7C,YAAM,YAAY,KAAK,IAAI,GAAG,gBAAgB,OAAO;AACrD,uBAAiB,SAAS;AAE1B,UAAI,cAAc,GAAG;AACnB,oBAAY;AAAA,MACd;AAAA,IACF,GAAG,GAAI;AAGP,QAAI;AACF,mBAAa,QAAQ,YAAY,IAAI,SAAS,CAAC;AAAA,IACjD,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,oCAAoC,KAAK;AAAA,IAC/E;AAGA,QAAI;AACF,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,YAAY,EAAE,MAAM,YAAY,WAAW,IAAI,CAAC;AAAA,MACrE;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,iCAAiC,KAAK;AAAA,IAC5E;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,cAAc,YAAY,WAAW,CAAC;AAGlE,QAAM,gBAAgBA,aAAY,MAAM;AACtC,QAAI,CAAC,QAAS;AAGd,kBAAc,KAAK;AACnB,cAAU,KAAK;AACf,mBAAe,KAAK;AACpB,qBAAiB,aAAa;AAG9B,gBAAY;AAEZ,kBAAc,IAAI;AAGlB,QAAI;AACF,UAAI,OAAO,qBAAqB,aAAa;AAC3C,mBAAW,UAAU,IAAI,iBAAiB,WAAW;AACrD,mBAAW,QAAQ,YAAY,CAAC,UAAU;AACxC,cAAI,MAAM,KAAK,SAAS,YAAY;AAClC,4BAAgB,UAAU,MAAM,KAAK;AACrC,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,6CAA6C,KAAK;AAAA,IACxF;AAGA,QAAI;AACF,YAAM,gBAAgB,aAAa,QAAQ,UAAU;AACrD,UAAI,eAAe;AACjB,cAAM,qBAAqB,SAAS,eAAe,EAAE;AACrD,cAAM,UAAU,KAAK,IAAI,IAAI;AAE7B,YAAI,UAAU,eAAe;AAE3B,0BAAgB,UAAU;AAC1B,gBAAM,YAAY,gBAAgB;AAClC,2BAAiB,SAAS;AAE1B,cAAI,aAAa,cAAc;AAC7B,2BAAe,IAAI;AACnB,yBAAa,UAAU;AAAA,UACzB;AAEA,cAAI,aAAa,GAAG;AAClB,sBAAU,IAAI;AACd,sBAAU,UAAU;AACpB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,wBAAwB,4CAA4C,KAAK;AAAA,IACvF;AAGA,QAAI,0BAA0B,SAAS;AACrC,sBAAgB,QAAQ,WAAS;AAC/B,iBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,MACxE,CAAC;AAAA,IACH;AAGA,8BAA0B,UAAU,SAAS,CAAC,UAAU;AACtD,oBAAc;AAAA,IAChB,GAAG,GAAG;AAGN,oBAAgB,QAAQ,WAAS;AAC/B,eAAS,iBAAiB,OAAO,0BAA0B,SAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxF,CAAC;AAGD,kBAAc,IAAI;AAGlB,WAAO,MAAM;AAEX,UAAI,0BAA0B,SAAS;AACrC,wBAAgB,QAAQ,WAAS;AAC/B,mBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,QACxE,CAAC;AACD,kCAA0B,UAAU;AAAA,MACtC;AACA,kBAAY;AACZ,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,MAAM;AACzB,mBAAW,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,YAAY,eAAe,cAAc,eAAe,WAAW,CAAC;AAG9F,QAAM,eAAeA,aAAY,MAAM;AACrC,kBAAc,KAAK;AACnB,gBAAY;AAGZ,QAAI,0BAA0B,SAAS;AACrC,sBAAgB,QAAQ,WAAS;AAC/B,iBAAS,oBAAoB,OAAO,0BAA0B,OAAQ;AAAA,MACxE,CAAC;AACD,gCAA0B,UAAU;AAAA,IACtC;AAEA,QAAI,WAAW,SAAS;AACtB,iBAAW,QAAQ,MAAM;AACzB,iBAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAGhB,EAAAD,WAAU,MAAM;AACd,QAAI,SAAS;AACX,YAAM,UAAU,cAAc;AAC9B,aAAO;AAAA,IACT,OAAO;AACL,mBAAa;AACb,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,cAAc,eAAe,YAAY,CAAC;AAGtE,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,kBAAY;AACZ,UAAI,WAAW,SAAS;AACtB,mBAAW,QAAQ,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChMA,SAAS,SAAS;;;AC7HX,IAAM,yBAAyB,CACpC,UACA,gBACA,eAAwB,UACH;AAGrB,QAAM,8BAA8B,CAAC,UAAwB;AAC3D,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AAEA,QAAI,CAAC,gBAAgB,CAAC,OAAO;AAC3B,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AAAA,EACF;AAGA,QAAM,2BAA2B,CAAC,UAA2B;AAE3D,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MAAU;AAAA,MACV;AAAA,MAAwB;AAAA;AAAA,MAExB;AAAA,MAA0B;AAAA,MAA4B;AAAA;AAAA,MAEtD;AAAA,MAAa;AAAA,MAAiB;AAAA,MAAe;AAAA;AAAA,MAE7C;AAAA,MAAgB;AAAA,MAAkB;AAAA,MAAa;AAAA,MAAoB;AAAA,MACnE;AAAA,MAAgB;AAAA,MAAgB;AAAA,MAAuB;AAAA,MAA4B;AAAA,MACnF;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,MAE1C;AAAA,MAAW;AAAA,MAAa;AAAA,MAAkB;AAAA,MAC1C;AAAA,MAAiB;AAAA,MAAqB;AAAA,MACtC;AAAA,MAAiB;AAAA,MAAiB;AAAA,MAAc;AAAA,MAAa;AAAA,MAC7D;AAAA,MAAkB;AAAA,MAAiB;AAAA,MAAgB;AAAA,MAAe;AAAA,MAClE;AAAA,MAAe;AAAA,MAAa;AAAA,MAAoB;AAAA,MAAoB;AAAA,IACtE;AAEA,WAAO,uBAAuB,SAAS,KAAK;AAAA,EAC9C;AAGA,QAAM,mBAAmB,CAAC,YAAgC;AACxD,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,gCAA4B,KAAK;AAEjC,QAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,MAAM;AAGhB,QAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,cAAQ,MAAM,GAAG,mBAAmB,KAAK;AAAA,IAC3C;AAGA,QAAI,SAAS;AACX,aAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,YAAI,UAAU,UAAa,UAAU,MAAM;AAEzC,gBAAM,aAAa,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,IAAK;AAC/D,kBAAQ,MAAM,GAAG,YAAY,KAAK;AAAA,QACpC;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,SAAS;AAEX,YAAM,gBAAgB,QAAQ,MAAM,GAAG,EAAE,IAAI;AAC7C,UAAI,eAAe;AACjB,gBAAQ,MAAM,MAAM,aAAa;AAAA,MACnC;AAAA,IACF;AAGA,QAAI,OAAO;AACT,cAAQ,MAAM,MAAM,KAAK;AAAA,IAC3B;AAEA,QAAI,QAAQ;AACV,cAAQ,MAAM,MAAM,QAAQ,UAAU,SAAS,MAAM,CAAC;AAAA,IACxD;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,OAAkD,YAA8C;AAClH,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,QAAI;AACF,YAAM,QAAQ,iBAAiB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM;AAE9B,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAGA,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,eAAO;AAAA,MACT;AAEA,aAAO,CAAC;AAAA,IACV,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,oBAAoB,OAAkD,YAAmD;AAC7H,UAAM,EAAE,OAAO,QAAQ,gBAAgB,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAElF,QAAI;AACF,YAAM,QAAQ,iBAAiB;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,MAAM,OAAO;AAE3C,UAAI,OAAO;AACT,YAAI,MAAM,SAAS,YAAY;AAE7B,iBAAO;AAAA,QACT;AACA,cAAM;AAAA,MACR;AAGA,UAAI,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,OAAO;AACzD,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,MACAE,oBACsB;AACtB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,YAAM,aAAa;AAAA,QACjB,GAAG;AAAA,QACH,iBAAiBA;AAAA,MACnB;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,SACnC,KAAK,KAAK,EACV,OAAO,UAAU,EACjB,OAAO,EACP,OAAO;AAEV,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,MACA,SACAA,oBACsB;AACtB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,UAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,IAAI;AAGd,UAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,gBAAQ,MAAM,GAAG,mBAAmBA,eAAc;AAAA,MACpD;AAGA,UAAI,SAAS;AACX,eAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,cAAI,UAAU,UAAa,UAAU,MAAM;AACzC,oBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,OAAO,EAAE,OAAO;AAE5D,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,eAAe,OACnB,OACA,SACAA,oBACqB;AACrB,gCAA4BA,eAAc;AAE1C,QAAI;AACF,UAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO;AAGV,UAAI,CAAC,gBAAgB,yBAAyB,KAAK,GAAG;AACpD,gBAAQ,MAAM,GAAG,mBAAmBA,eAAc;AAAA,MACpD;AAGA,UAAI,SAAS;AACX,eAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,cAAI,UAAU,UAAa,UAAU,MAAM;AACzC,oBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,EAAE,MAAM,IAAI,MAAM;AAExB,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,sBAAsB,OAC1B,OACA,QACAA,iBACA,YACiB;AACjB,WAAO,YAAe;AAAA,MACpB;AAAA,MACA;AAAA,MACA,gBAAAA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["jsx","formatTime","useState","useEffect","useCallback","useState","useEffect","useCallback","organisationId"]}
@@ -1,6 +1,6 @@
1
- export { b as UnifiedAuthContext, a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, U as UserEventAccess, u as useUnifiedAuth } from './UnifiedAuthProvider-BG0AL5eE.js';
2
- import { A as AuthService } from './AuthService-B-cd2MA4.js';
3
- export { a as EventServiceContext, E as EventServiceContextType, c as EventServiceProvider, b as EventServiceProviderProps, g as InactivityServiceContext, I as InactivityServiceContextType, i as InactivityServiceProvider, h as InactivityServiceProviderProps, d as OrganisationServiceContext, O as OrganisationServiceContextType, f as OrganisationServiceProvider, e as OrganisationServiceProviderProps } from './AuthService-B-cd2MA4.js';
1
+ export { b as UnifiedAuthContext, a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, U as UserEventAccess, u as useUnifiedAuth } from './UnifiedAuthProvider-BYA9qB-o.js';
2
+ import { A as AuthService } from './AuthService-CbP_utw2.js';
3
+ export { a as EventServiceContext, E as EventServiceContextType, c as EventServiceProvider, b as EventServiceProviderProps, g as InactivityServiceContext, I as InactivityServiceContextType, i as InactivityServiceProvider, h as InactivityServiceProviderProps, d as OrganisationServiceContext, O as OrganisationServiceContextType, f as OrganisationServiceProvider, e as OrganisationServiceProviderProps } from './AuthService-CbP_utw2.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import React__default from 'react';
6
6
  import { SupabaseClient } from '@supabase/supabase-js';
package/dist/providers.js CHANGED
@@ -11,7 +11,9 @@ import {
11
11
  UnifiedAuthContext,
12
12
  UnifiedAuthProvider,
13
13
  useUnifiedAuth
14
- } from "./chunk-VGZZXKBR.js";
14
+ } from "./chunk-J2XXC7R5.js";
15
+ import "./chunk-RUYZKXOD.js";
16
+ import "./chunk-63FOKYGO.js";
15
17
  import "./chunk-QXHPKYJV.js";
16
18
  import "./chunk-VBXEHIUJ.js";
17
19
  import "./chunk-PWLANIRT.js";