@jmruthers/pace-core 0.5.54 → 0.5.55

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 (396) hide show
  1. package/README.md +0 -4
  2. package/dist/{DataTable-7FMFXA7A.js → DataTable-4T627QFJ.js} +11 -11
  3. package/dist/{PublicLoadingSpinner-Bq_-BeK-.d.ts → PublicLoadingSpinner-SL8WaQN7.d.ts} +2 -21
  4. package/dist/{api-H5A3H4IR.js → api-LUNF5O6M.js} +3 -3
  5. package/dist/{appConfig-BVGyuvI7.d.ts → appConfig-DjpeG6P-.d.ts} +9 -1
  6. package/dist/{appNameResolver-7GHF5ED2.js → appNameResolver-UURKN7NF.js} +2 -2
  7. package/dist/{audit-BUW3LMJB.js → audit-6TOCAMKO.js} +2 -2
  8. package/dist/{chunk-MZBUOP4P.js → chunk-5BSLGBYI.js} +4 -3
  9. package/dist/chunk-5BSLGBYI.js.map +1 -0
  10. package/dist/{chunk-I5Z3QH5X.js → chunk-66C4BSAY.js} +2 -2
  11. package/dist/{chunk-I5Z3QH5X.js.map → chunk-66C4BSAY.js.map} +1 -1
  12. package/dist/{chunk-MYP2EGHX.js → chunk-AJ2KMES7.js} +21 -14
  13. package/dist/chunk-AJ2KMES7.js.map +1 -0
  14. package/dist/{chunk-EL2O4IUX.js → chunk-AQFRLC7K.js} +16 -24
  15. package/dist/{chunk-EL2O4IUX.js.map → chunk-AQFRLC7K.js.map} +1 -1
  16. package/dist/{chunk-7BNPOCLL.js → chunk-B2WTCLCV.js} +6 -2
  17. package/dist/chunk-B2WTCLCV.js.map +1 -0
  18. package/dist/{chunk-WJARTBCT.js → chunk-D7ARGIA3.js} +16 -7
  19. package/dist/chunk-D7ARGIA3.js.map +1 -0
  20. package/dist/{chunk-NRK4AIHQ.js → chunk-KBRACSJI.js} +3 -3
  21. package/dist/{chunk-NYUJ4FJR.js → chunk-KJDPSM64.js} +7 -7
  22. package/dist/chunk-KJDPSM64.js.map +1 -0
  23. package/dist/{chunk-GWSBHC4J.js → chunk-KLPVOPRI.js} +261 -38
  24. package/dist/chunk-KLPVOPRI.js.map +1 -0
  25. package/dist/{chunk-TRIZ7IB7.js → chunk-MPQDF75X.js} +148 -288
  26. package/dist/chunk-MPQDF75X.js.map +1 -0
  27. package/dist/{chunk-MSFACPQQ.js → chunk-PAEM3OWN.js} +11 -11
  28. package/dist/{chunk-MSFACPQQ.js.map → chunk-PAEM3OWN.js.map} +1 -1
  29. package/dist/{chunk-GIO7BFE7.js → chunk-RQD3D2CO.js} +66 -169
  30. package/dist/{chunk-GIO7BFE7.js.map → chunk-RQD3D2CO.js.map} +1 -1
  31. package/dist/{chunk-YDJW5XTN.js → chunk-STT7INZR.js} +25 -1
  32. package/dist/chunk-STT7INZR.js.map +1 -0
  33. package/dist/{chunk-6MTY77WU.js → chunk-TNMXZLDR.js} +3 -3
  34. package/dist/{chunk-BC3S53OZ.js → chunk-UQE2Y64H.js} +30 -14
  35. package/dist/chunk-UQE2Y64H.js.map +1 -0
  36. package/dist/{chunk-22KLBHPS.js → chunk-W66AZIOH.js} +2 -2
  37. package/dist/chunk-W66AZIOH.js.map +1 -0
  38. package/dist/{chunk-SS3E6QLB.js → chunk-YNUBMSMV.js} +2 -2
  39. package/dist/chunk-YNUBMSMV.js.map +1 -0
  40. package/dist/{chunk-NZ655MWE.js → chunk-ZOD2ZY6X.js} +5 -4
  41. package/dist/chunk-ZOD2ZY6X.js.map +1 -0
  42. package/dist/{chunk-74C6SNEC.js → chunk-ZPK5656W.js} +3 -3
  43. package/dist/{chunk-74C6SNEC.js.map → chunk-ZPK5656W.js.map} +1 -1
  44. package/dist/components.d.ts +22 -899
  45. package/dist/components.js +436 -3118
  46. package/dist/components.js.map +1 -1
  47. package/dist/file-reference-9xUOnwyt.d.ts +70 -0
  48. package/dist/hooks.d.ts +2 -2
  49. package/dist/hooks.js +10 -10
  50. package/dist/hooks.js.map +1 -1
  51. package/dist/index.d.ts +49 -9
  52. package/dist/index.js +190 -25
  53. package/dist/index.js.map +1 -1
  54. package/dist/{organisation-CO3Sh3_D.d.ts → organisation-t-vvQC3g.d.ts} +1 -8
  55. package/dist/providers.d.ts +2 -2
  56. package/dist/providers.js +5 -5
  57. package/dist/rbac/index.d.ts +65 -46
  58. package/dist/rbac/index.js +10 -12
  59. package/dist/styles/core.css +0 -125
  60. package/dist/types.d.ts +2 -1
  61. package/dist/types.js +3 -1
  62. package/dist/types.js.map +1 -1
  63. package/dist/{usePublicRouteParams-B2OcAsur.d.ts → usePublicRouteParams-CdoFxnJK.d.ts} +1 -1
  64. package/dist/utils.d.ts +3 -4
  65. package/dist/utils.js +44 -13
  66. package/dist/utils.js.map +1 -1
  67. package/docs/FILE_REFERENCE_SYSTEM.md +440 -0
  68. package/docs/INDEX.md +7 -5
  69. package/docs/README.md +0 -1
  70. package/docs/api/README.md +0 -4
  71. package/docs/api/classes/ErrorBoundary.md +1 -1
  72. package/docs/api/classes/InvalidScopeError.md +1 -1
  73. package/docs/api/classes/MissingUserContextError.md +1 -1
  74. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  75. package/docs/api/classes/PermissionDeniedError.md +2 -2
  76. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  77. package/docs/api/classes/RBACAuditManager.md +12 -12
  78. package/docs/api/classes/RBACCache.md +1 -1
  79. package/docs/api/classes/RBACEngine.md +6 -6
  80. package/docs/api/classes/RBACError.md +1 -1
  81. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  82. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  83. package/docs/api/classes/StorageUtils.md +281 -0
  84. package/docs/api/interfaces/AggregateConfig.md +1 -1
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CardProps.md +1 -1
  87. package/docs/api/interfaces/ColorPalette.md +1 -1
  88. package/docs/api/interfaces/ColorShade.md +1 -1
  89. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  90. package/docs/api/interfaces/DataTableAction.md +1 -1
  91. package/docs/api/interfaces/DataTableColumn.md +1 -1
  92. package/docs/api/interfaces/DataTableProps.md +1 -1
  93. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  94. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  95. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  96. package/docs/api/interfaces/EventContextType.md +1 -1
  97. package/docs/api/interfaces/EventLogoProps.md +1 -1
  98. package/docs/api/interfaces/EventProviderProps.md +1 -1
  99. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
  107. package/docs/api/interfaces/NavigationContextType.md +1 -1
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACContextType.md +1 -1
  133. package/docs/api/interfaces/RBACLogger.md +1 -1
  134. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  135. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  136. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  137. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  138. package/docs/api/interfaces/RouteConfig.md +2 -2
  139. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  140. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  141. package/docs/api/interfaces/StorageConfig.md +1 -1
  142. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  143. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  144. package/docs/api/interfaces/StorageListOptions.md +1 -1
  145. package/docs/api/interfaces/StorageListResult.md +1 -1
  146. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  147. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  148. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  149. package/docs/api/interfaces/StyleImport.md +1 -1
  150. package/docs/api/interfaces/ToastActionElement.md +1 -1
  151. package/docs/api/interfaces/ToastProps.md +1 -1
  152. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  153. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  155. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  159. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  160. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  161. package/docs/api/interfaces/UserEventAccess.md +1 -1
  162. package/docs/api/interfaces/UserMenuProps.md +1 -1
  163. package/docs/api/interfaces/UserProfile.md +1 -1
  164. package/docs/api/modules.md +204 -200
  165. package/docs/api-reference/components.md +141 -163
  166. package/docs/api-reference/hooks.md +347 -0
  167. package/docs/core-concepts/rbac-system.md +69 -16
  168. package/docs/getting-started/examples/basic-auth-app.md +0 -1
  169. package/docs/implementation-guides/datatable-rbac-usage.md +12 -11
  170. package/docs/implementation-guides/file-upload-storage.md +733 -0
  171. package/docs/implementation-guides/inactivity-tracking.md +779 -0
  172. package/docs/implementation-guides/organisation-security.md +748 -0
  173. package/docs/implementation-guides/public-pages-advanced.md +1022 -0
  174. package/docs/migration/MIGRATION_GUIDE.md +684 -0
  175. package/docs/migration/README.md +13 -2
  176. package/docs/migration/rbac-migration.md +73 -0
  177. package/docs/rbac/examples/rbac-rls-integration-example.md +11 -13
  178. package/docs/style-guide.md +269 -1
  179. package/package.json +1 -1
  180. package/src/__tests__/TESTING_GUIDELINES.md +331 -18
  181. package/src/__tests__/helpers/supabaseMock.ts +99 -0
  182. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -7
  183. package/src/__tests__/shared.ts +6 -0
  184. package/src/components/DataTable/components/ActionButtons.tsx +2 -2
  185. package/src/components/DataTable/components/DataTableCore.tsx +2 -2
  186. package/src/components/DataTable/components/UnifiedTableBody.tsx +1 -1
  187. package/src/components/DataTable/utils/debugTools.ts +2 -2
  188. package/src/components/Dialog/Dialog.test.tsx +12 -2
  189. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +6 -6
  190. package/src/components/ErrorBoundary/ErrorBoundary.tsx +2 -2
  191. package/src/components/FileDisplay.tsx +233 -0
  192. package/src/components/FileUpload.tsx +176 -0
  193. package/src/components/Footer/Footer.test.tsx +7 -7
  194. package/src/components/NavigationMenu/NavigationMenu.test.tsx +13 -6
  195. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +30 -3
  196. package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
  197. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +558 -0
  198. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  199. package/src/components/PublicLayout/PublicPageDebugger.tsx +2 -2
  200. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +2 -2
  201. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -2
  202. package/src/components/Select/Select.test.tsx +50 -15
  203. package/src/components/SuperAdminGuard.tsx +2 -2
  204. package/src/components/__tests__/SuperAdminGuard.test.tsx +559 -0
  205. package/src/components/index.ts +0 -183
  206. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
  207. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +1 -1
  208. package/src/hooks/__tests__/useRBAC.unit.test.ts +191 -138
  209. package/src/hooks/public/usePublicEvent.ts +2 -2
  210. package/src/hooks/useAppConfig.ts +3 -3
  211. package/src/hooks/useComponentPerformance.ts +1 -1
  212. package/src/hooks/useDataTablePerformance.ts +1 -1
  213. package/src/hooks/useFileReference.ts +232 -0
  214. package/src/hooks/useOrganisationPermissions.test.ts +254 -344
  215. package/src/hooks/useOrganisationPermissions.ts +15 -7
  216. package/src/hooks/useOrganisationSecurity.test.ts +390 -402
  217. package/src/hooks/usePerformanceMonitor.ts +1 -1
  218. package/src/hooks/usePermissionCache.test.ts +264 -395
  219. package/src/hooks/usePermissionCache.ts +34 -4
  220. package/src/hooks/useSecureDataAccess.test.ts +486 -0
  221. package/src/hooks/useSecureDataAccess.ts +4 -1
  222. package/src/providers/InactivityProvider.tsx +2 -2
  223. package/src/providers/OrganisationProvider.test.simple.tsx +168 -0
  224. package/src/providers/OrganisationProvider.test.tsx +168 -0
  225. package/src/providers/OrganisationProvider.tsx +18 -31
  226. package/src/providers/UnifiedAuthProvider.test.simple.tsx +205 -0
  227. package/src/providers/UnifiedAuthProvider.test.tsx +128 -0
  228. package/src/providers/__tests__/InactivityProvider.test.tsx +3 -4
  229. package/src/providers/__tests__/OrganisationProvider.test.tsx +19 -14
  230. package/src/rbac/__tests__/integration.authflow.test.tsx +123 -0
  231. package/src/rbac/__tests__/integration.navigation.test.tsx +72 -0
  232. package/src/rbac/__tests__/integration.securedata.test.tsx +92 -0
  233. package/src/rbac/__tests__/integration.smoke.test.tsx +73 -0
  234. package/src/rbac/__tests__/rbac-core.test.tsx +26 -22
  235. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +411 -0
  236. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +285 -0
  237. package/src/rbac/__tests__/rbac-functions.test.ts +655 -0
  238. package/src/rbac/__tests__/rbac-integration.test.ts +532 -0
  239. package/src/rbac/__tests__/scenarios.user-role.test.tsx +196 -0
  240. package/src/rbac/api.test.ts +6 -6
  241. package/src/rbac/api.ts +2 -2
  242. package/src/rbac/audit.test.ts +485 -0
  243. package/src/rbac/audit.ts +7 -1
  244. package/src/rbac/cache-invalidation.ts +318 -0
  245. package/src/rbac/cache.test.ts +286 -0
  246. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +559 -0
  247. package/src/rbac/components/EnhancedNavigationMenu.tsx +29 -23
  248. package/src/rbac/components/NavigationProvider.test.tsx +449 -0
  249. package/src/rbac/components/PagePermissionGuard.tsx +4 -4
  250. package/src/rbac/components/PagePermissionProvider.test.tsx +479 -0
  251. package/src/rbac/components/SecureDataProvider.test.tsx +511 -0
  252. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +159 -430
  253. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +4 -5
  254. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +112 -118
  255. package/src/rbac/config.test.ts +410 -0
  256. package/src/rbac/engine.test.simple.ts +237 -0
  257. package/src/rbac/engine.test.ts +233 -0
  258. package/src/rbac/engine.ts +37 -41
  259. package/src/rbac/examples/CompleteRBACExample.tsx +3 -3
  260. package/src/rbac/examples/EventBasedApp.tsx +4 -4
  261. package/src/rbac/hooks/useRBAC.simple.test.ts +16 -0
  262. package/src/rbac/hooks/useRBAC.test.ts +207 -455
  263. package/src/rbac/hooks/useRBAC.ts +30 -22
  264. package/src/rbac/permissions.test.ts +128 -0
  265. package/src/rbac/permissions.ts +56 -141
  266. package/src/rbac/providers/RBACProvider.tsx +1 -1
  267. package/src/rbac/secureClient.test.ts +444 -0
  268. package/src/rbac/security.test.ts +390 -0
  269. package/src/rbac/security.ts +1 -1
  270. package/src/rbac/types.test.ts +382 -0
  271. package/src/rbac/types.ts +2 -2
  272. package/src/styles/core.css +0 -125
  273. package/src/types/file-reference.ts +77 -0
  274. package/src/types/rbac-functions.ts +290 -0
  275. package/src/types/supabase.ts +10 -28
  276. package/src/types/unified.ts +4 -1
  277. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +81 -55
  278. package/src/utils/__tests__/lazyLoad.unit.test.tsx +21 -12
  279. package/src/utils/__tests__/organisationContext.unit.test.ts +13 -7
  280. package/src/utils/__tests__/performanceBudgets.unit.test.ts +3 -3
  281. package/src/utils/__tests__/sessionTracking.unit.test.ts +32 -12
  282. package/src/utils/appConfig.ts +1 -1
  283. package/src/utils/appIdResolver.test.ts +503 -0
  284. package/src/utils/appIdResolver.ts +1 -1
  285. package/src/utils/appNameResolver.test.ts +494 -0
  286. package/src/utils/appNameResolver.ts +3 -2
  287. package/src/utils/bundleAnalysis.ts +3 -3
  288. package/src/utils/debugLogger.ts +1 -1
  289. package/src/utils/file-reference.ts +263 -0
  290. package/src/utils/formatDate.test.ts +2 -2
  291. package/src/utils/organisationContext.test.ts +340 -0
  292. package/src/utils/organisationContext.ts +19 -6
  293. package/src/utils/performanceBudgets.ts +2 -2
  294. package/src/utils/permissionUtils.test.ts +393 -0
  295. package/src/utils/permissionUtils.ts +5 -2
  296. package/src/utils/secureDataAccess.test.ts +715 -0
  297. package/src/utils/secureDataAccess.ts +21 -5
  298. package/src/utils/sessionTracking.ts +34 -4
  299. package/src/utils/storage/__tests__/helpers.unit.test.ts +328 -0
  300. package/src/utils/storage/__tests__/index.unit.test.ts +16 -0
  301. package/src/utils/storage/helpers.ts +20 -25
  302. package/src/utils/storage/index.ts +29 -1
  303. package/src/vite-env.d.ts +17 -0
  304. package/dist/chunk-22KLBHPS.js.map +0 -1
  305. package/dist/chunk-7BNPOCLL.js.map +0 -1
  306. package/dist/chunk-BC3S53OZ.js.map +0 -1
  307. package/dist/chunk-GWSBHC4J.js.map +0 -1
  308. package/dist/chunk-MYP2EGHX.js.map +0 -1
  309. package/dist/chunk-MZBUOP4P.js.map +0 -1
  310. package/dist/chunk-NYUJ4FJR.js.map +0 -1
  311. package/dist/chunk-NZ655MWE.js.map +0 -1
  312. package/dist/chunk-SS3E6QLB.js.map +0 -1
  313. package/dist/chunk-TRIZ7IB7.js.map +0 -1
  314. package/dist/chunk-WJARTBCT.js.map +0 -1
  315. package/dist/chunk-YDJW5XTN.js.map +0 -1
  316. package/docs/print-components/README.md +0 -258
  317. package/docs/print-components/api-reference.md +0 -636
  318. package/docs/print-components/examples/README.md +0 -204
  319. package/docs/print-components/examples/basic-report.tsx +0 -92
  320. package/docs/print-components/examples/card-catalog.tsx +0 -149
  321. package/docs/print-components/examples/cover-page-report.tsx +0 -163
  322. package/docs/print-components/quick-start.md +0 -363
  323. package/src/components/PrintButton/PrintButton.tsx +0 -321
  324. package/src/components/PrintButton/PrintButtonGroup.tsx +0 -84
  325. package/src/components/PrintButton/PrintToolbar.tsx +0 -94
  326. package/src/components/PrintButton/__tests__/PrintButton.test.tsx +0 -271
  327. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +0 -438
  328. package/src/components/PrintButton/index.ts +0 -33
  329. package/src/components/PrintButton/types.ts +0 -173
  330. package/src/components/PrintCard/PrintCard.tsx +0 -154
  331. package/src/components/PrintCard/PrintCardContent.tsx +0 -57
  332. package/src/components/PrintCard/PrintCardFooter.tsx +0 -60
  333. package/src/components/PrintCard/PrintCardGrid.tsx +0 -91
  334. package/src/components/PrintCard/PrintCardHeader.tsx +0 -78
  335. package/src/components/PrintCard/PrintCardImage.tsx +0 -81
  336. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +0 -239
  337. package/src/components/PrintCard/index.ts +0 -34
  338. package/src/components/PrintCard/types.ts +0 -171
  339. package/src/components/PrintDataTable/PrintDataTable.tsx +0 -215
  340. package/src/components/PrintDataTable/PrintTableGroup.tsx +0 -90
  341. package/src/components/PrintDataTable/PrintTableRow.tsx +0 -76
  342. package/src/components/PrintDataTable/index.ts +0 -25
  343. package/src/components/PrintDataTable/types.ts +0 -67
  344. package/src/components/PrintFooter/PrintFooter.tsx +0 -183
  345. package/src/components/PrintFooter/PrintFooterContent.tsx +0 -71
  346. package/src/components/PrintFooter/PrintFooterInfo.tsx +0 -86
  347. package/src/components/PrintFooter/PrintPageNumber.tsx +0 -90
  348. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +0 -390
  349. package/src/components/PrintFooter/index.ts +0 -30
  350. package/src/components/PrintFooter/types.ts +0 -149
  351. package/src/components/PrintGrid/PrintGrid.tsx +0 -180
  352. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +0 -109
  353. package/src/components/PrintGrid/PrintGridContainer.tsx +0 -128
  354. package/src/components/PrintGrid/PrintGridItem.tsx +0 -220
  355. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +0 -359
  356. package/src/components/PrintGrid/index.ts +0 -31
  357. package/src/components/PrintGrid/types.ts +0 -159
  358. package/src/components/PrintHeader/PrintCoverHeader.tsx +0 -230
  359. package/src/components/PrintHeader/PrintHeader.tsx +0 -150
  360. package/src/components/PrintHeader/index.ts +0 -17
  361. package/src/components/PrintHeader/types.ts +0 -42
  362. package/src/components/PrintLayout/PrintLayout.tsx +0 -122
  363. package/src/components/PrintLayout/PrintLayoutContext.tsx +0 -66
  364. package/src/components/PrintLayout/PrintPageBreak.tsx +0 -52
  365. package/src/components/PrintLayout/examples/PrintShowcase.tsx +0 -230
  366. package/src/components/PrintLayout/index.ts +0 -19
  367. package/src/components/PrintLayout/types.ts +0 -37
  368. package/src/components/PrintPageBreak/PrintPageBreak.tsx +0 -120
  369. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +0 -90
  370. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +0 -112
  371. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +0 -279
  372. package/src/components/PrintPageBreak/index.ts +0 -23
  373. package/src/components/PrintPageBreak/types.ts +0 -94
  374. package/src/components/PrintSection/PrintColumn.tsx +0 -104
  375. package/src/components/PrintSection/PrintDivider.tsx +0 -101
  376. package/src/components/PrintSection/PrintSection.tsx +0 -129
  377. package/src/components/PrintSection/PrintSectionContent.tsx +0 -75
  378. package/src/components/PrintSection/PrintSectionHeader.tsx +0 -97
  379. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +0 -258
  380. package/src/components/PrintSection/index.ts +0 -33
  381. package/src/components/PrintSection/types.ts +0 -155
  382. package/src/components/PrintText/PrintText.tsx +0 -116
  383. package/src/components/PrintText/index.ts +0 -16
  384. package/src/components/PrintText/types.ts +0 -24
  385. package/src/rbac/__tests__/integration.test.tsx +0 -218
  386. package/src/utils/print/PrintDataProcessor.ts +0 -390
  387. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +0 -397
  388. package/src/utils/print/index.ts +0 -29
  389. package/src/utils/print/types.ts +0 -196
  390. package/src/utils/print/usePrintOptimization.ts +0 -272
  391. /package/dist/{DataTable-7FMFXA7A.js.map → DataTable-4T627QFJ.js.map} +0 -0
  392. /package/dist/{api-H5A3H4IR.js.map → api-LUNF5O6M.js.map} +0 -0
  393. /package/dist/{appNameResolver-7GHF5ED2.js.map → appNameResolver-UURKN7NF.js.map} +0 -0
  394. /package/dist/{audit-BUW3LMJB.js.map → audit-6TOCAMKO.js.map} +0 -0
  395. /package/dist/{chunk-NRK4AIHQ.js.map → chunk-KBRACSJI.js.map} +0 -0
  396. /package/dist/{chunk-6MTY77WU.js.map → chunk-TNMXZLDR.js.map} +0 -0
@@ -0,0 +1,779 @@
1
+ # Inactivity Tracking
2
+
3
+ > **⏰ User Session Management** | [← Back to Documentation](../README.md) | [↑ Table of Contents](#table-of-contents)
4
+
5
+ Complete guide to implementing user inactivity tracking with automatic warnings and session management.
6
+
7
+ ## Overview
8
+
9
+ PACE Core provides comprehensive inactivity tracking with:
10
+ - **Cross-tab Synchronization** - Activity tracked across all browser tabs
11
+ - **Configurable Timeouts** - Customizable idle and warning periods
12
+ - **Automatic Warnings** - User-friendly inactivity warnings
13
+ - **Session Management** - Integration with authentication systems
14
+ - **Accessibility Support** - Screen reader friendly warnings
15
+ - **Performance Optimized** - Throttled event handling
16
+
17
+ ## Architecture
18
+
19
+ ```mermaid
20
+ graph TD
21
+ A[User Activity] --> B[useInactivityTracker Hook]
22
+ B --> C[BroadcastChannel]
23
+ C --> D[Cross-tab Sync]
24
+ B --> E[Local Storage]
25
+ E --> F[Persistence]
26
+ B --> G[InactivityWarningModal]
27
+ G --> H[User Action]
28
+ H --> I[Reset Timer]
29
+ B --> J[onIdle Callback]
30
+ J --> K[Sign Out]
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ### 1. Basic Inactivity Tracking
36
+
37
+ ```tsx
38
+ import { useInactivityTracker, InactivityWarningModal } from '@jmruthers/pace-core';
39
+
40
+ function App() {
41
+ const { isIdle, timeRemaining, showWarning, resetActivity } = useInactivityTracker({
42
+ idleTimeoutMs: 30 * 60 * 1000, // 30 minutes
43
+ warnBeforeMs: 5 * 60 * 1000, // 5 minutes warning
44
+ onIdle: () => {
45
+ console.log('User is idle - signing out');
46
+ signOut();
47
+ },
48
+ onWarning: () => {
49
+ console.log('Showing inactivity warning');
50
+ }
51
+ });
52
+
53
+ return (
54
+ <div>
55
+ <h1>My App</h1>
56
+ <p>Idle: {isIdle ? 'Yes' : 'No'}</p>
57
+ <p>Time remaining: {Math.floor(timeRemaining / 1000)}s</p>
58
+
59
+ <InactivityWarningModal
60
+ isOpen={showWarning}
61
+ timeRemaining={timeRemaining}
62
+ onStayActive={resetActivity}
63
+ onSignOut={() => signOut()}
64
+ />
65
+ </div>
66
+ );
67
+ }
68
+ ```
69
+
70
+ ### 2. Integration with Authentication
71
+
72
+ ```tsx
73
+ import { useInactivityTracker, InactivityWarningModal } from '@jmruthers/pace-core';
74
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
75
+
76
+ function AuthenticatedApp() {
77
+ const { signOut } = useUnifiedAuth();
78
+
79
+ const {
80
+ isIdle,
81
+ timeRemaining,
82
+ showWarning,
83
+ resetActivity,
84
+ startTracking,
85
+ stopTracking
86
+ } = useInactivityTracker({
87
+ idleTimeoutMs: 15 * 60 * 1000, // 15 minutes
88
+ warnBeforeMs: 2 * 60 * 1000, // 2 minutes warning
89
+ onIdle: () => {
90
+ console.log('User inactive - signing out');
91
+ signOut();
92
+ },
93
+ onWarning: () => {
94
+ console.log('Inactivity warning triggered');
95
+ },
96
+ onActivity: () => {
97
+ console.log('User activity detected');
98
+ }
99
+ });
100
+
101
+ // Start tracking when component mounts
102
+ useEffect(() => {
103
+ startTracking();
104
+ return () => stopTracking();
105
+ }, [startTracking, stopTracking]);
106
+
107
+ return (
108
+ <div>
109
+ <h1>Dashboard</h1>
110
+ <p>Status: {isIdle ? 'Idle' : 'Active'}</p>
111
+
112
+ <InactivityWarningModal
113
+ isOpen={showWarning}
114
+ timeRemaining={timeRemaining}
115
+ onStayActive={resetActivity}
116
+ onSignOut={signOut}
117
+ title="Session Timeout Warning"
118
+ message="You will be signed out due to inactivity."
119
+ stayActiveText="Stay Active"
120
+ signOutText="Sign Out Now"
121
+ />
122
+ </div>
123
+ );
124
+ }
125
+ ```
126
+
127
+ ## Components
128
+
129
+ ### InactivityWarningModal
130
+
131
+ A modal component that displays inactivity warnings with countdown timer and action buttons.
132
+
133
+ #### Props
134
+
135
+ ```typescript
136
+ interface InactivityWarningModalProps {
137
+ isOpen: boolean;
138
+ timeRemaining: number;
139
+ onStayActive: () => void;
140
+ onSignOut: () => void;
141
+ title?: string;
142
+ message?: string;
143
+ stayActiveText?: string;
144
+ signOutText?: string;
145
+ className?: string;
146
+ }
147
+ ```
148
+
149
+ #### Usage Examples
150
+
151
+ **Basic Warning Modal:**
152
+ ```tsx
153
+ <InactivityWarningModal
154
+ isOpen={showWarning}
155
+ timeRemaining={timeRemaining}
156
+ onStayActive={resetActivity}
157
+ onSignOut={signOut}
158
+ />
159
+ ```
160
+
161
+ **Customized Warning Modal:**
162
+ ```tsx
163
+ <InactivityWarningModal
164
+ isOpen={showWarning}
165
+ timeRemaining={timeRemaining}
166
+ onStayActive={resetActivity}
167
+ onSignOut={signOut}
168
+ title="Session Expiring Soon"
169
+ message="Your session will expire in {time} seconds due to inactivity."
170
+ stayActiveText="Continue Working"
171
+ signOutText="End Session"
172
+ className="custom-warning-modal"
173
+ />
174
+ ```
175
+
176
+ **Custom Styling:**
177
+ ```tsx
178
+ <InactivityWarningModal
179
+ isOpen={showWarning}
180
+ timeRemaining={timeRemaining}
181
+ onStayActive={resetActivity}
182
+ onSignOut={signOut}
183
+ className="bg-main-50 border-main-300"
184
+ />
185
+ ```
186
+
187
+ ## Hooks
188
+
189
+ ### useInactivityTracker
190
+
191
+ Primary hook for tracking user inactivity with comprehensive configuration options.
192
+
193
+ #### Interface
194
+
195
+ ```typescript
196
+ interface UseInactivityTrackerOptions {
197
+ /** Timeout in milliseconds before user is considered idle (default: 30 minutes) */
198
+ idleTimeoutMs?: number;
199
+
200
+ /** Time in milliseconds before idle to show warning (default: 5 minutes) */
201
+ warnBeforeMs?: number;
202
+
203
+ /** Callback when user becomes idle */
204
+ onIdle?: () => void;
205
+
206
+ /** Callback when warning should be shown */
207
+ onWarning?: () => void;
208
+
209
+ /** Callback when user activity is detected */
210
+ onActivity?: () => void;
211
+
212
+ /** Events to track for activity (default: all) */
213
+ events?: string[];
214
+
215
+ /** Throttle interval for event handling (default: 100ms) */
216
+ throttleMs?: number;
217
+
218
+ /** Enable cross-tab synchronization (default: true) */
219
+ enableCrossTabSync?: boolean;
220
+
221
+ /** Storage key for persistence (default: 'pace-inactivity') */
222
+ storageKey?: string;
223
+
224
+ /** Enable debug logging (default: false) */
225
+ debug?: boolean;
226
+ }
227
+
228
+ interface UseInactivityTrackerReturn {
229
+ /** Whether user is currently idle */
230
+ isIdle: boolean;
231
+
232
+ /** Time remaining before idle (in milliseconds) */
233
+ timeRemaining: number;
234
+
235
+ /** Whether warning should be shown */
236
+ showWarning: boolean;
237
+
238
+ /** Reset the inactivity timer */
239
+ resetActivity: () => void;
240
+
241
+ /** Start tracking activity */
242
+ startTracking: () => void;
243
+
244
+ /** Stop tracking activity */
245
+ stopTracking: () => void;
246
+
247
+ /** Get current activity status */
248
+ getActivityStatus: () => {
249
+ isIdle: boolean;
250
+ timeRemaining: number;
251
+ lastActivity: number;
252
+ };
253
+ }
254
+ ```
255
+
256
+ #### Usage Examples
257
+
258
+ **Basic Configuration:**
259
+ ```tsx
260
+ import { useInactivityTracker } from '@jmruthers/pace-core';
261
+
262
+ function MyComponent() {
263
+ const { isIdle, timeRemaining, showWarning, resetActivity } = useInactivityTracker({
264
+ idleTimeoutMs: 20 * 60 * 1000, // 20 minutes
265
+ warnBeforeMs: 3 * 60 * 1000, // 3 minutes warning
266
+ onIdle: () => {
267
+ console.log('User is idle');
268
+ // Handle idle state
269
+ }
270
+ });
271
+
272
+ return (
273
+ <div>
274
+ <p>Idle: {isIdle ? 'Yes' : 'No'}</p>
275
+ <p>Time remaining: {Math.floor(timeRemaining / 1000)}s</p>
276
+ </div>
277
+ );
278
+ }
279
+ ```
280
+
281
+ **Advanced Configuration:**
282
+ ```tsx
283
+ import { useInactivityTracker } from '@jmruthers/pace-core';
284
+
285
+ function AdvancedComponent() {
286
+ const {
287
+ isIdle,
288
+ timeRemaining,
289
+ showWarning,
290
+ resetActivity,
291
+ startTracking,
292
+ stopTracking,
293
+ getActivityStatus
294
+ } = useInactivityTracker({
295
+ idleTimeoutMs: 45 * 60 * 1000, // 45 minutes
296
+ warnBeforeMs: 10 * 60 * 1000, // 10 minutes warning
297
+ events: ['mousedown', 'keydown', 'scroll', 'touchstart'], // Custom events
298
+ throttleMs: 200, // Throttle to 200ms
299
+ enableCrossTabSync: true,
300
+ storageKey: 'my-app-inactivity',
301
+ debug: process.env.NODE_ENV === 'development',
302
+ onIdle: () => {
303
+ console.log('User idle - performing cleanup');
304
+ // Save work, clear sensitive data, etc.
305
+ },
306
+ onWarning: () => {
307
+ console.log('Warning: User will be idle soon');
308
+ // Show notification, play sound, etc.
309
+ },
310
+ onActivity: () => {
311
+ console.log('User activity detected');
312
+ // Hide warnings, reset notifications, etc.
313
+ }
314
+ });
315
+
316
+ // Manual control
317
+ const handlePauseTracking = () => {
318
+ stopTracking();
319
+ };
320
+
321
+ const handleResumeTracking = () => {
322
+ startTracking();
323
+ };
324
+
325
+ const handleCheckStatus = () => {
326
+ const status = getActivityStatus();
327
+ console.log('Current status:', status);
328
+ };
329
+
330
+ return (
331
+ <div>
332
+ <div className="space-y-2">
333
+ <p>Status: {isIdle ? 'Idle' : 'Active'}</p>
334
+ <p>Time remaining: {Math.floor(timeRemaining / 1000)}s</p>
335
+ <p>Warning: {showWarning ? 'Yes' : 'No'}</p>
336
+ </div>
337
+
338
+ <div className="space-x-2">
339
+ <Button onClick={resetActivity}>Reset Timer</Button>
340
+ <Button onClick={handlePauseTracking}>Pause Tracking</Button>
341
+ <Button onClick={handleResumeTracking}>Resume Tracking</Button>
342
+ <Button onClick={handleCheckStatus}>Check Status</Button>
343
+ </div>
344
+ </div>
345
+ );
346
+ }
347
+ ```
348
+
349
+ ## Configuration Options
350
+
351
+ ### Timeout Configuration
352
+
353
+ ```tsx
354
+ // Short session (5 minutes idle, 1 minute warning)
355
+ const shortSession = useInactivityTracker({
356
+ idleTimeoutMs: 5 * 60 * 1000,
357
+ warnBeforeMs: 1 * 60 * 1000
358
+ });
359
+
360
+ // Long session (2 hours idle, 15 minutes warning)
361
+ const longSession = useInactivityTracker({
362
+ idleTimeoutMs: 2 * 60 * 60 * 1000,
363
+ warnBeforeMs: 15 * 60 * 1000
364
+ });
365
+
366
+ // No warning (immediate idle)
367
+ const immediateIdle = useInactivityTracker({
368
+ idleTimeoutMs: 10 * 60 * 1000,
369
+ warnBeforeMs: 0
370
+ });
371
+ ```
372
+
373
+ ### Event Tracking
374
+
375
+ ```tsx
376
+ // Track only mouse and keyboard events
377
+ const basicTracking = useInactivityTracker({
378
+ events: ['mousedown', 'keydown']
379
+ });
380
+
381
+ // Track all user interactions
382
+ const fullTracking = useInactivityTracker({
383
+ events: [
384
+ 'mousedown',
385
+ 'mousemove',
386
+ 'keydown',
387
+ 'keyup',
388
+ 'scroll',
389
+ 'touchstart',
390
+ 'touchmove',
391
+ 'focus',
392
+ 'blur'
393
+ ]
394
+ });
395
+
396
+ // Custom event tracking
397
+ const customTracking = useInactivityTracker({
398
+ events: ['click', 'input', 'change', 'submit']
399
+ });
400
+ ```
401
+
402
+ ### Cross-Tab Synchronization
403
+
404
+ ```tsx
405
+ // Enable cross-tab sync (default)
406
+ const syncedTracking = useInactivityTracker({
407
+ enableCrossTabSync: true
408
+ });
409
+
410
+ // Disable cross-tab sync
411
+ const localTracking = useInactivityTracker({
412
+ enableCrossTabSync: false
413
+ });
414
+ ```
415
+
416
+ ## Integration Patterns
417
+
418
+ ### Authentication Integration
419
+
420
+ ```tsx
421
+ import { useInactivityTracker, InactivityWarningModal } from '@jmruthers/pace-core';
422
+ import { useUnifiedAuth } from '@jmruthers/pace-core';
423
+
424
+ function AuthenticatedApp() {
425
+ const { user, signOut, loading } = useUnifiedAuth();
426
+
427
+ const {
428
+ isIdle,
429
+ timeRemaining,
430
+ showWarning,
431
+ resetActivity
432
+ } = useInactivityTracker({
433
+ idleTimeoutMs: 30 * 60 * 1000,
434
+ warnBeforeMs: 5 * 60 * 1000,
435
+ onIdle: () => {
436
+ console.log('User idle - signing out');
437
+ signOut();
438
+ },
439
+ onWarning: () => {
440
+ console.log('Inactivity warning');
441
+ }
442
+ });
443
+
444
+ // Don't track inactivity if not authenticated
445
+ if (loading || !user) {
446
+ return <div>Loading...</div>;
447
+ }
448
+
449
+ return (
450
+ <div>
451
+ <h1>Welcome, {user.email}</h1>
452
+
453
+ <InactivityWarningModal
454
+ isOpen={showWarning}
455
+ timeRemaining={timeRemaining}
456
+ onStayActive={resetActivity}
457
+ onSignOut={signOut}
458
+ />
459
+ </div>
460
+ );
461
+ }
462
+ ```
463
+
464
+ ### Form Integration
465
+
466
+ ```tsx
467
+ import { useInactivityTracker } from '@jmruthers/pace-core';
468
+ import { useForm } from 'react-hook-form';
469
+
470
+ function LongForm() {
471
+ const { formState: { isDirty } } = useForm();
472
+
473
+ const { isIdle, showWarning, resetActivity } = useInactivityTracker({
474
+ idleTimeoutMs: 10 * 60 * 1000, // 10 minutes
475
+ warnBeforeMs: 2 * 60 * 1000, // 2 minutes warning
476
+ onIdle: () => {
477
+ if (isDirty) {
478
+ // Save draft before signing out
479
+ saveDraft();
480
+ }
481
+ signOut();
482
+ }
483
+ });
484
+
485
+ return (
486
+ <form>
487
+ {/* Form fields */}
488
+
489
+ {showWarning && isDirty && (
490
+ <div className="bg-acc-100 border border-acc-300 rounded p-4">
491
+ <p>You have unsaved changes. Your session will expire soon.</p>
492
+ <Button onClick={resetActivity}>Continue Editing</Button>
493
+ </div>
494
+ )}
495
+ </form>
496
+ );
497
+ }
498
+ ```
499
+
500
+ ### Multi-Step Process Integration
501
+
502
+ ```tsx
503
+ import { useInactivityTracker } from '@jmruthers/pace-core';
504
+
505
+ function MultiStepProcess() {
506
+ const [currentStep, setCurrentStep] = useState(0);
507
+ const [formData, setFormData] = useState({});
508
+
509
+ const { isIdle, showWarning, resetActivity } = useInactivityTracker({
510
+ idleTimeoutMs: 15 * 60 * 1000,
511
+ warnBeforeMs: 3 * 60 * 1000,
512
+ onIdle: () => {
513
+ // Save progress before signing out
514
+ saveProgress(formData, currentStep);
515
+ signOut();
516
+ }
517
+ });
518
+
519
+ return (
520
+ <div>
521
+ <h2>Step {currentStep + 1} of 5</h2>
522
+
523
+ {/* Step content */}
524
+
525
+ {showWarning && (
526
+ <div className="fixed bottom-4 right-4 bg-main-600 text-main-50 p-4 rounded">
527
+ <p>Your session will expire soon. Save your progress?</p>
528
+ <Button onClick={resetActivity}>Continue</Button>
529
+ </div>
530
+ )}
531
+ </div>
532
+ );
533
+ }
534
+ ```
535
+
536
+ ## Accessibility
537
+
538
+ ### Screen Reader Support
539
+
540
+ The `InactivityWarningModal` includes proper ARIA attributes and announcements:
541
+
542
+ ```tsx
543
+ <InactivityWarningModal
544
+ isOpen={showWarning}
545
+ timeRemaining={timeRemaining}
546
+ onStayActive={resetActivity}
547
+ onSignOut={signOut}
548
+ // Automatically includes:
549
+ // - role="alertdialog"
550
+ // - aria-labelledby
551
+ // - aria-describedby
552
+ // - Live region for countdown updates
553
+ />
554
+ ```
555
+
556
+ ### Keyboard Navigation
557
+
558
+ The modal supports full keyboard navigation:
559
+ - **Tab** - Navigate between buttons
560
+ - **Enter/Space** - Activate focused button
561
+ - **Escape** - Close modal (if configured)
562
+
563
+ ### Focus Management
564
+
565
+ ```tsx
566
+ import { useInactivityTracker } from '@jmruthers/pace-core';
567
+
568
+ function AccessibleApp() {
569
+ const { showWarning, resetActivity } = useInactivityTracker({
570
+ // ... configuration
571
+ });
572
+
573
+ // Focus management for accessibility
574
+ useEffect(() => {
575
+ if (showWarning) {
576
+ // Focus will be automatically managed by the modal
577
+ // The modal will trap focus and return it when closed
578
+ }
579
+ }, [showWarning]);
580
+
581
+ return (
582
+ <div>
583
+ {/* App content */}
584
+
585
+ <InactivityWarningModal
586
+ isOpen={showWarning}
587
+ timeRemaining={timeRemaining}
588
+ onStayActive={resetActivity}
589
+ onSignOut={signOut}
590
+ // Focus management is handled automatically
591
+ />
592
+ </div>
593
+ );
594
+ }
595
+ ```
596
+
597
+ ## Performance Considerations
598
+
599
+ ### Throttling
600
+
601
+ The hook uses throttling to prevent excessive event handling:
602
+
603
+ ```tsx
604
+ // Default throttling (100ms)
605
+ const defaultThrottling = useInactivityTracker({
606
+ // Events are throttled to 100ms by default
607
+ });
608
+
609
+ // Custom throttling
610
+ const customThrottling = useInactivityTracker({
611
+ throttleMs: 500 // Throttle to 500ms
612
+ });
613
+
614
+ // No throttling (not recommended for performance)
615
+ const noThrottling = useInactivityTracker({
616
+ throttleMs: 0
617
+ });
618
+ ```
619
+
620
+ ### Memory Management
621
+
622
+ The hook automatically cleans up event listeners and timers:
623
+
624
+ ```tsx
625
+ function MyComponent() {
626
+ const inactivityTracker = useInactivityTracker({
627
+ // ... configuration
628
+ });
629
+
630
+ // Cleanup is automatic when component unmounts
631
+ // No manual cleanup required
632
+ }
633
+ ```
634
+
635
+ ### Cross-Tab Optimization
636
+
637
+ Cross-tab synchronization is optimized to minimize performance impact:
638
+
639
+ ```tsx
640
+ // Optimized cross-tab sync
641
+ const optimizedSync = useInactivityTracker({
642
+ enableCrossTabSync: true,
643
+ // Uses BroadcastChannel API for efficient communication
644
+ // Minimal memory footprint
645
+ // Automatic cleanup
646
+ });
647
+ ```
648
+
649
+ ## Troubleshooting
650
+
651
+ ### Common Issues
652
+
653
+ **Issue: Timer not resetting on activity**
654
+ - Check that events are being tracked correctly
655
+ - Verify throttle settings aren't too high
656
+ - Ensure event listeners are properly attached
657
+
658
+ **Issue: Cross-tab sync not working**
659
+ - Check browser support for BroadcastChannel API
660
+ - Verify storage permissions
661
+ - Check for conflicting storage keys
662
+
663
+ **Issue: Modal not showing**
664
+ - Verify `showWarning` state is true
665
+ - Check that `timeRemaining` is greater than 0
666
+ - Ensure modal is rendered in the component tree
667
+
668
+ ### Debug Mode
669
+
670
+ Enable debug logging to troubleshoot issues:
671
+
672
+ ```tsx
673
+ const { isIdle, timeRemaining, showWarning } = useInactivityTracker({
674
+ debug: true, // Enable debug logging
675
+ // ... other options
676
+ });
677
+
678
+ // Debug output will show:
679
+ // - Event tracking
680
+ // - Timer updates
681
+ // - Cross-tab communication
682
+ // - State changes
683
+ ```
684
+
685
+ ### Manual Testing
686
+
687
+ ```tsx
688
+ function DebugComponent() {
689
+ const {
690
+ isIdle,
691
+ timeRemaining,
692
+ showWarning,
693
+ resetActivity,
694
+ getActivityStatus
695
+ } = useInactivityTracker({
696
+ idleTimeoutMs: 10 * 1000, // 10 seconds for testing
697
+ warnBeforeMs: 5 * 1000, // 5 seconds warning
698
+ debug: true
699
+ });
700
+
701
+ const status = getActivityStatus();
702
+
703
+ return (
704
+ <div>
705
+ <h3>Debug Information</h3>
706
+ <p>Is Idle: {isIdle ? 'Yes' : 'No'}</p>
707
+ <p>Time Remaining: {timeRemaining}ms</p>
708
+ <p>Show Warning: {showWarning ? 'Yes' : 'No'}</p>
709
+ <p>Last Activity: {new Date(status.lastActivity).toLocaleTimeString()}</p>
710
+
711
+ <Button onClick={resetActivity}>Reset Timer</Button>
712
+ </div>
713
+ );
714
+ }
715
+ ```
716
+
717
+ ## Best Practices
718
+
719
+ ### 1. Appropriate Timeouts
720
+
721
+ ```tsx
722
+ // Short sessions (banking, admin)
723
+ const shortSession = useInactivityTracker({
724
+ idleTimeoutMs: 5 * 60 * 1000, // 5 minutes
725
+ warnBeforeMs: 1 * 60 * 1000 // 1 minute warning
726
+ });
727
+
728
+ // Medium sessions (general apps)
729
+ const mediumSession = useInactivityTracker({
730
+ idleTimeoutMs: 30 * 60 * 1000, // 30 minutes
731
+ warnBeforeMs: 5 * 60 * 1000 // 5 minutes warning
732
+ });
733
+
734
+ // Long sessions (content creation)
735
+ const longSession = useInactivityTracker({
736
+ idleTimeoutMs: 2 * 60 * 60 * 1000, // 2 hours
737
+ warnBeforeMs: 15 * 60 * 1000 // 15 minutes warning
738
+ });
739
+ ```
740
+
741
+ ### 2. User Experience
742
+
743
+ ```tsx
744
+ // Provide clear feedback
745
+ const userFriendly = useInactivityTracker({
746
+ onWarning: () => {
747
+ // Show toast notification
748
+ toast.info('Your session will expire soon');
749
+ },
750
+ onIdle: () => {
751
+ // Save work before signing out
752
+ saveUserWork();
753
+ signOut();
754
+ }
755
+ });
756
+ ```
757
+
758
+ ### 3. Security Considerations
759
+
760
+ ```tsx
761
+ // Clear sensitive data on idle
762
+ const secure = useInactivityTracker({
763
+ onIdle: () => {
764
+ // Clear sensitive data from memory
765
+ clearSensitiveData();
766
+ // Clear local storage
767
+ localStorage.removeItem('sensitive-data');
768
+ // Sign out
769
+ signOut();
770
+ }
771
+ });
772
+ ```
773
+
774
+ ## Next Steps
775
+
776
+ - **[Authentication Integration](./permission-enforcement.md)** - Security patterns
777
+ - **[Performance Optimization](./performance.md)** - Large application considerations
778
+ - **[Accessibility Guidelines](../best-practices/accessibility.md)** - Accessibility best practices
779
+ - **[Security Best Practices](../best-practices/security.md)** - Security considerations