@jmruthers/pace-core 0.5.135 → 0.5.137

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 (544) hide show
  1. package/dist/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
  2. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
  4. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  5. package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
  6. package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
  7. package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
  8. package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
  9. package/dist/chunk-22WKWKRX.js.map +1 -0
  10. package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
  11. package/dist/chunk-4C7EXCAR.js.map +1 -0
  12. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  13. package/dist/chunk-56XJ3TU6.js.map +1 -0
  14. package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
  15. package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
  16. package/dist/chunk-7QCC6MCP.js.map +1 -0
  17. package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
  18. package/dist/chunk-ANBQRTPX.js.map +1 -0
  19. package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
  20. package/dist/chunk-BCIBECNB.js.map +1 -0
  21. package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
  22. package/dist/chunk-BESYRHQM.js.map +1 -0
  23. package/dist/chunk-BJPBT3CU.js +21 -0
  24. package/dist/chunk-BJPBT3CU.js.map +1 -0
  25. package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
  26. package/dist/chunk-BLCXZEYF.js.map +1 -0
  27. package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  28. package/dist/chunk-BVYWGZVV.js.map +1 -0
  29. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  30. package/dist/chunk-ERISIBYU.js.map +1 -0
  31. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  32. package/dist/chunk-FMUCXFII.js.map +1 -0
  33. package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
  34. package/dist/chunk-HAWZXGR2.js.map +1 -0
  35. package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
  36. package/dist/chunk-JISYG63F.js +70 -0
  37. package/dist/chunk-JISYG63F.js.map +1 -0
  38. package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
  39. package/dist/chunk-KYRHUBIU.js.map +1 -0
  40. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  41. package/dist/chunk-LS353YLY.js.map +1 -0
  42. package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
  43. package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
  44. package/dist/chunk-OWAG3GSU.js +58 -0
  45. package/dist/chunk-OWAG3GSU.js.map +1 -0
  46. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  47. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  48. package/dist/chunk-S5OFRT4M.js +94 -0
  49. package/dist/chunk-S5OFRT4M.js.map +1 -0
  50. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  51. package/dist/chunk-SBVILCCA.js.map +1 -0
  52. package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
  53. package/dist/chunk-T6JN6LH6.js.map +1 -0
  54. package/dist/chunk-XDNLUEXI.js +138 -0
  55. package/dist/chunk-XDNLUEXI.js.map +1 -0
  56. package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
  57. package/dist/chunk-YCWDTTUK.js.map +1 -0
  58. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  59. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  60. package/dist/components.d.ts +7 -287
  61. package/dist/components.js +27 -157
  62. package/dist/components.js.map +1 -1
  63. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  64. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  65. package/dist/hooks.d.ts +3 -3
  66. package/dist/hooks.js +21 -16
  67. package/dist/hooks.js.map +1 -1
  68. package/dist/index.d.ts +101 -9
  69. package/dist/index.js +44 -31
  70. package/dist/index.js.map +1 -1
  71. package/dist/providers.d.ts +1 -1
  72. package/dist/providers.js +4 -4
  73. package/dist/rbac/index.js +12 -12
  74. package/dist/schema-DTDZQe2u.d.ts +28 -0
  75. package/dist/styles/index.js +2 -1
  76. package/dist/theming/runtime.d.ts +2 -19
  77. package/dist/theming/runtime.js +2 -1
  78. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  79. package/dist/types.d.ts +153 -4
  80. package/dist/types.js +51 -16
  81. package/dist/types.js.map +1 -1
  82. package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
  83. package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
  84. package/dist/utils.d.ts +221 -173
  85. package/dist/utils.js +185 -225
  86. package/dist/utils.js.map +1 -1
  87. package/dist/validation.d.ts +24 -115
  88. package/dist/validation.js +19 -474
  89. package/dist/validation.js.map +1 -1
  90. package/docs/api/classes/ColumnFactory.md +1 -1
  91. package/docs/api/classes/ErrorBoundary.md +6 -6
  92. package/docs/api/classes/InvalidScopeError.md +1 -1
  93. package/docs/api/classes/MissingUserContextError.md +1 -1
  94. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  95. package/docs/api/classes/PermissionDeniedError.md +1 -1
  96. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  97. package/docs/api/classes/RBACAuditManager.md +6 -6
  98. package/docs/api/classes/RBACCache.md +1 -1
  99. package/docs/api/classes/RBACEngine.md +7 -7
  100. package/docs/api/classes/RBACError.md +1 -1
  101. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  102. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  103. package/docs/api/classes/StorageUtils.md +1 -1
  104. package/docs/api/enums/FileCategory.md +1 -1
  105. package/docs/api/interfaces/AggregateConfig.md +4 -4
  106. package/docs/api/interfaces/BadgeProps.md +27 -0
  107. package/docs/api/interfaces/ButtonProps.md +1 -1
  108. package/docs/api/interfaces/CardProps.md +1 -1
  109. package/docs/api/interfaces/ColorPalette.md +1 -1
  110. package/docs/api/interfaces/ColorShade.md +29 -4
  111. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  112. package/docs/api/interfaces/DataRecord.md +1 -1
  113. package/docs/api/interfaces/DataTableAction.md +18 -18
  114. package/docs/api/interfaces/DataTableColumn.md +61 -1
  115. package/docs/api/interfaces/DataTableProps.md +1 -1
  116. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  117. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  118. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
  119. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  120. package/docs/api/interfaces/EventLogoProps.md +152 -0
  121. package/docs/api/interfaces/ExportColumn.md +1 -1
  122. package/docs/api/interfaces/ExportOptions.md +8 -8
  123. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  124. package/docs/api/interfaces/FileMetadata.md +1 -1
  125. package/docs/api/interfaces/FileReference.md +1 -1
  126. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  127. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  128. package/docs/api/interfaces/FileUploadProps.md +1 -1
  129. package/docs/api/interfaces/FooterProps.md +1 -1
  130. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  131. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  132. package/docs/api/interfaces/InputProps.md +1 -1
  133. package/docs/api/interfaces/LabelProps.md +1 -1
  134. package/docs/api/interfaces/LoginFormProps.md +1 -1
  135. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  136. package/docs/api/interfaces/NavigationContextType.md +9 -9
  137. package/docs/api/interfaces/NavigationGuardProps.md +10 -10
  138. package/docs/api/interfaces/NavigationItem.md +1 -1
  139. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  140. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  141. package/docs/api/interfaces/Organisation.md +1 -1
  142. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  143. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  144. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  145. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  146. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  147. package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
  148. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  149. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  150. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  151. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  152. package/docs/api/interfaces/PaletteData.md +4 -4
  153. package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
  154. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  155. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  156. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  157. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  158. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  159. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  160. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  161. package/docs/api/interfaces/RBACConfig.md +1 -1
  162. package/docs/api/interfaces/RBACLogger.md +1 -1
  163. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  164. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  165. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  166. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  167. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  168. package/docs/api/interfaces/RouteConfig.md +10 -10
  169. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  170. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  171. package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
  172. package/docs/api/interfaces/StorageConfig.md +1 -1
  173. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  174. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  175. package/docs/api/interfaces/StorageListOptions.md +1 -1
  176. package/docs/api/interfaces/StorageListResult.md +1 -1
  177. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  178. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  179. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  180. package/docs/api/interfaces/StyleImport.md +1 -1
  181. package/docs/api/interfaces/SwitchProps.md +1 -1
  182. package/docs/api/interfaces/ToastActionElement.md +1 -1
  183. package/docs/api/interfaces/ToastProps.md +1 -1
  184. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  185. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  186. package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
  187. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  188. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  189. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  190. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  191. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
  192. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  193. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  194. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  195. package/docs/api/interfaces/UserEventAccess.md +11 -11
  196. package/docs/api/interfaces/UserMenuProps.md +1 -1
  197. package/docs/api/interfaces/UserProfile.md +1 -1
  198. package/docs/api/modules.md +591 -220
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -3
  201. package/docs/implementation-guides/data-tables.md +277 -13
  202. package/docs/implementation-guides/forms.md +1 -16
  203. package/docs/implementation-guides/permission-enforcement.md +8 -2
  204. package/docs/styles/README.md +0 -2
  205. package/examples/README.md +30 -14
  206. package/examples/STRUCTURE.md +125 -0
  207. package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
  208. package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
  209. package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
  210. package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
  211. package/examples/components 2/DataTable/index.ts +13 -0
  212. package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
  213. package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
  214. package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
  215. package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
  216. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
  217. package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
  218. package/examples/components 2/Dialog/index.ts +15 -0
  219. package/examples/components 2/index.ts +11 -0
  220. package/examples/features/index.ts +12 -0
  221. package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
  222. package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
  223. package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
  224. package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
  225. package/examples/features/public-pages/index.ts +14 -0
  226. package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
  227. package/examples/features/rbac/EventBasedApp.tsx +239 -0
  228. package/examples/features/rbac/PermissionExample.tsx +151 -0
  229. package/examples/features/rbac/index.ts +13 -0
  230. package/examples/index.ts +11 -3
  231. package/package.json +30 -19
  232. package/src/__tests__/TEST_STANDARD.md +92 -0
  233. package/src/components/Alert/Alert.tsx +1 -1
  234. package/src/components/Avatar/Avatar.tsx +1 -1
  235. package/src/components/Badge/Badge.test.tsx +314 -0
  236. package/src/components/Badge/Badge.tsx +304 -0
  237. package/src/components/Badge/index.ts +3 -0
  238. package/src/components/Button/Button.tsx +1 -1
  239. package/src/components/Card/Card.tsx +1 -1
  240. package/src/components/Checkbox/Checkbox.tsx +1 -1
  241. package/src/components/DataTable/DataTable.test.tsx +1 -1
  242. package/src/components/DataTable/DataTable.tsx +1 -30
  243. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  244. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
  245. package/src/components/DataTable/__tests__/styles.test.ts +3 -3
  246. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  247. package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
  248. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  249. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  250. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  252. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  253. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  254. package/src/components/DataTable/components/FilterRow.tsx +9 -3
  255. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  256. package/src/components/DataTable/components/PaginationControls.tsx +2 -1
  257. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  258. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  259. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
  260. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  261. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
  262. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  263. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  264. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
  265. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  266. package/src/components/DataTable/core/ActionManager.ts +235 -0
  267. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  268. package/src/components/DataTable/core/DataManager.ts +188 -0
  269. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  270. package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
  271. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  272. package/src/components/DataTable/core/StateManager.ts +311 -0
  273. package/src/components/DataTable/core/interfaces.ts +338 -0
  274. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  275. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  276. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  277. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  278. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  280. package/src/components/DataTable/index.ts +4 -0
  281. package/src/components/DataTable/styles.ts +28 -7
  282. package/src/components/DataTable/types.ts +13 -0
  283. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
  284. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  285. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  286. package/src/components/DataTable/utils/columnUtils.ts +40 -0
  287. package/src/components/DataTable/utils/debugTools.ts +609 -0
  288. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  289. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  290. package/src/components/DataTable/utils/index.ts +2 -0
  291. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  292. package/src/components/Dialog/Dialog.tsx +2 -2
  293. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
  294. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  295. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  296. package/src/components/EventSelector/EventSelector.tsx +3 -2
  297. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  298. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  299. package/src/components/FileUpload/FileUpload.tsx +2 -2
  300. package/src/components/Footer/Footer.test.tsx +1 -1
  301. package/src/components/Footer/Footer.tsx +1 -1
  302. package/src/components/Form/Form.test.tsx +5 -510
  303. package/src/components/Form/Form.tsx +1 -1
  304. package/src/components/Form/FormField.tsx +1 -1
  305. package/src/components/Form/index.ts +0 -12
  306. package/src/components/Header/Header.tsx +1 -1
  307. package/src/components/Input/Input.tsx +1 -1
  308. package/src/components/Label/Label.tsx +1 -1
  309. package/src/components/LoginForm/LoginForm.test.tsx +1 -1
  310. package/src/components/LoginForm/LoginForm.tsx +1 -1
  311. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  312. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  313. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  314. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  315. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  316. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
  317. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  318. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  319. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  320. package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
  321. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  322. package/src/components/PasswordReset/index.ts +0 -2
  323. package/src/components/Progress/Progress.tsx +1 -1
  324. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  325. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  326. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  327. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  328. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  329. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  330. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  331. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  332. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  333. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
  334. package/src/components/PublicLayout/index.ts +4 -2
  335. package/src/components/Select/Select.test.tsx +1 -1
  336. package/src/components/Select/Select.tsx +21 -9
  337. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  338. package/src/components/SessionRestorationLoader/index.ts +3 -0
  339. package/src/components/Switch/Switch.tsx +1 -1
  340. package/src/components/Table/Table.tsx +1 -1
  341. package/src/components/Table/__tests__/Table.test.tsx +1 -1
  342. package/src/components/Toast/Toast.tsx +1 -1
  343. package/src/components/Tooltip/Tooltip.tsx +1 -1
  344. package/src/components/index.ts +7 -10
  345. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  346. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  347. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  348. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  349. package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
  350. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  351. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  352. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  353. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  354. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  355. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  356. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  357. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  358. package/src/hooks/public/usePublicEvent.ts +7 -6
  359. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  360. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  361. package/src/hooks/useComponentPerformance.ts +4 -1
  362. package/src/hooks/useDataTablePerformance.ts +4 -3
  363. package/src/hooks/useEventTheme.test.ts +18 -5
  364. package/src/hooks/useEventTheme.ts +4 -1
  365. package/src/hooks/useEvents.ts +2 -0
  366. package/src/hooks/useFileDisplay.ts +9 -8
  367. package/src/hooks/useFileReference.ts +4 -1
  368. package/src/hooks/useFileUrl.ts +4 -1
  369. package/src/hooks/useInactivityTracker.ts +5 -4
  370. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  371. package/src/hooks/useOrganisationSecurity.ts +8 -7
  372. package/src/hooks/usePerformanceMonitor.ts +6 -3
  373. package/src/hooks/usePermissionCache.ts +13 -6
  374. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  375. package/src/hooks/useSecureDataAccess.ts +9 -8
  376. package/src/hooks/useSessionRestoration.ts +4 -1
  377. package/src/hooks/useStorage.ts +4 -1
  378. package/src/index.ts +20 -7
  379. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  380. package/src/providers/services/EventServiceProvider.tsx +2 -1
  381. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  382. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  383. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  384. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  385. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  386. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  387. package/src/rbac/api.ts +5 -2
  388. package/src/rbac/audit-enhanced.ts +6 -6
  389. package/src/rbac/audit.test.ts +60 -38
  390. package/src/rbac/audit.ts +8 -8
  391. package/src/rbac/cache-invalidation.ts +7 -4
  392. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  393. package/src/rbac/components/NavigationGuard.tsx +7 -3
  394. package/src/rbac/components/NavigationProvider.tsx +6 -3
  395. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  396. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  397. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  398. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  399. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  400. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  401. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  402. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  403. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  404. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  405. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  406. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  407. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  408. package/src/rbac/engine.ts +15 -7
  409. package/src/rbac/hooks/usePermissions.ts +7 -3
  410. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  411. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  412. package/src/rbac/permissions.ts +5 -2
  413. package/src/rbac/security.test.ts +27 -16
  414. package/src/rbac/security.ts +5 -4
  415. package/src/services/AuthService.ts +22 -21
  416. package/src/services/EventService.ts +12 -12
  417. package/src/services/InactivityService.ts +5 -4
  418. package/src/services/OrganisationService.ts +26 -25
  419. package/src/services/__tests__/AuthService.test.ts +51 -19
  420. package/src/services/__tests__/EventService.test.ts +37 -5
  421. package/src/services/__tests__/InactivityService.test.ts +38 -4
  422. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  423. package/src/services/base/BaseService.ts +3 -1
  424. package/src/styles/core.css +3 -0
  425. package/src/theming/__tests__/runtime.test.ts +21 -12
  426. package/src/theming/parseEventColours.ts +5 -19
  427. package/src/theming/runtime.ts +8 -4
  428. package/src/types/validation.ts +2 -29
  429. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  430. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  431. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  432. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  433. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  434. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  435. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  436. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  437. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  438. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  439. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  440. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  441. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  442. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  443. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  444. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  445. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  446. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  447. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  448. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  449. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  450. package/src/utils/__tests__/security.unit.test.ts +40 -18
  451. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  452. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  453. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  454. package/src/utils/app/appConfig.ts +47 -0
  455. package/src/utils/app/appIdResolver.test.ts +497 -0
  456. package/src/utils/app/appIdResolver.ts +133 -0
  457. package/src/utils/app/appNameResolver.simple.test.ts +212 -0
  458. package/src/utils/app/appNameResolver.test.ts +121 -0
  459. package/src/utils/app/appNameResolver.ts +195 -0
  460. package/src/utils/audit/audit.ts +127 -0
  461. package/src/utils/context/organisationContext.test.ts +322 -0
  462. package/src/utils/context/organisationContext.ts +156 -0
  463. package/src/utils/context/sessionTracking.ts +125 -0
  464. package/src/utils/core/cn.ts +7 -0
  465. package/src/utils/core/debugLogger.ts +67 -0
  466. package/src/utils/core/logger.ts +181 -0
  467. package/src/utils/device/deviceFingerprint.ts +215 -0
  468. package/src/utils/dynamic/dynamicUtils.ts +105 -0
  469. package/src/utils/dynamic/lazyLoad.tsx +44 -0
  470. package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
  471. package/src/utils/file-reference/index.ts +501 -0
  472. package/src/utils/formatting/formatDate.test.ts +237 -0
  473. package/src/utils/formatting/formatting.ts +133 -0
  474. package/src/utils/index.ts +39 -54
  475. package/src/utils/performance/bundleAnalysis.ts +129 -0
  476. package/src/utils/performance/performanceBenchmark.ts +64 -0
  477. package/src/utils/performance/performanceBudgets.ts +110 -0
  478. package/src/utils/permissions/permissionTypes.ts +37 -0
  479. package/src/utils/permissions/permissionUtils.test.ts +393 -0
  480. package/src/utils/permissions/permissionUtils.ts +34 -0
  481. package/src/utils/security/auth-utils.ts +96 -0
  482. package/src/utils/security/secureDataAccess.test.ts +711 -0
  483. package/src/utils/security/secureDataAccess.ts +377 -0
  484. package/src/utils/security/secureErrors.ts +82 -0
  485. package/src/utils/security/secureStorage.ts +244 -0
  486. package/src/utils/security/security.ts +159 -0
  487. package/src/utils/security/securityMonitor.ts +45 -0
  488. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  489. package/src/utils/storage/helpers.ts +15 -8
  490. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
  491. package/src/{validation → utils/validation}/csrf.ts +1 -1
  492. package/src/utils/validation/htmlSanitization.ts +184 -0
  493. package/src/utils/validation/index.ts +79 -0
  494. package/src/utils/validation/sanitization.ts +333 -0
  495. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  496. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  497. package/src/utils/validation/validation.ts +111 -0
  498. package/src/utils/validation/validationUtils.ts +123 -0
  499. package/src/validation/index.ts +3 -34
  500. package/dist/chunk-24MKLB7U.js +0 -81
  501. package/dist/chunk-24MKLB7U.js.map +0 -1
  502. package/dist/chunk-3CG5L6RN.js.map +0 -1
  503. package/dist/chunk-3DBFLLLU.js.map +0 -1
  504. package/dist/chunk-5F3NDPJV.js.map +0 -1
  505. package/dist/chunk-66C4BSAY.js.map +0 -1
  506. package/dist/chunk-BDZUMRBD.js +0 -87
  507. package/dist/chunk-BDZUMRBD.js.map +0 -1
  508. package/dist/chunk-BYXRHAIF.js.map +0 -1
  509. package/dist/chunk-CDQ3PX7L.js +0 -18
  510. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  511. package/dist/chunk-CQZU6TFE.js.map +0 -1
  512. package/dist/chunk-F64FFPOZ.js.map +0 -1
  513. package/dist/chunk-GEVIB2UB.js.map +0 -1
  514. package/dist/chunk-GKHF54DI.js.map +0 -1
  515. package/dist/chunk-GVDR7WNV.js.map +0 -1
  516. package/dist/chunk-HMNOSGVA.js.map +0 -1
  517. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  518. package/dist/chunk-M6DDYFUD.js.map +0 -1
  519. package/dist/chunk-O3NWNXDY.js.map +0 -1
  520. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  521. package/dist/chunk-UJI6WSMD.js.map +0 -1
  522. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  523. package/dist/chunk-WP5I5GLN.js.map +0 -1
  524. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  525. package/dist/validation-DnhrNMju.d.ts +0 -159
  526. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  527. package/src/validation/__tests__/common.unit.test.ts +0 -101
  528. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  529. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  530. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  531. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  532. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  533. package/src/validation/__tests__/user.unit.test.ts +0 -440
  534. package/src/validation/sanitization.ts +0 -96
  535. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
  536. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
  537. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  538. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  539. /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
  540. /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
  541. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  542. /package/src/{validation → utils/validation}/common.ts +0 -0
  543. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  544. /package/src/{validation → utils/validation}/user.ts +0 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @file Production-Safe Logger Utility
3
+ * @package @jmruthers/pace-core
4
+ * @module Utils/Logger
5
+ * @since 0.4.76
6
+ */
7
+
8
+ /**
9
+ * Logger levels for different types of messages
10
+ */
11
+ export enum LogLevel {
12
+ DEBUG = 0,
13
+ INFO = 1,
14
+ WARN = 2,
15
+ ERROR = 3,
16
+ }
17
+
18
+ /**
19
+ * Logger configuration interface
20
+ */
21
+ export interface LoggerConfig {
22
+ /** Minimum log level to output */
23
+ level: LogLevel;
24
+ /** Whether to include timestamps */
25
+ includeTimestamp: boolean;
26
+ /** Whether to include component names */
27
+ includeComponent: boolean;
28
+ /** Custom prefix for all log messages */
29
+ prefix?: string;
30
+ }
31
+
32
+ /**
33
+ * Production-safe logger that no-ops in production builds
34
+ * Only outputs logs in development mode to prevent production console spam
35
+ */
36
+ export class Logger {
37
+ private static config: LoggerConfig = {
38
+ level: LogLevel.DEBUG,
39
+ includeTimestamp: false,
40
+ includeComponent: true,
41
+ };
42
+
43
+ /**
44
+ * Check if we're in development or test mode
45
+ * Allows logging in both development and test environments
46
+ */
47
+ private static get isDevelopment(): boolean {
48
+ const mode = import.meta.env.MODE;
49
+ return mode === 'development' || mode === 'test';
50
+ }
51
+
52
+ /**
53
+ * Configure the logger
54
+ */
55
+ static configure(config: Partial<LoggerConfig>): void {
56
+ this.config = { ...this.config, ...config };
57
+ }
58
+
59
+ /**
60
+ * Format a log message with optional timestamp and component
61
+ */
62
+ private static formatMessage(
63
+ level: LogLevel,
64
+ component: string,
65
+ message: string
66
+ ): string {
67
+ const parts: string[] = [];
68
+
69
+ if (this.config.prefix) {
70
+ parts.push(`[${this.config.prefix}]`);
71
+ }
72
+
73
+ if (this.config.includeTimestamp) {
74
+ parts.push(`[${new Date().toISOString()}]`);
75
+ }
76
+
77
+ parts.push(`[${LogLevel[level]}]`);
78
+
79
+ if (this.config.includeComponent && component) {
80
+ parts.push(`[${component}]`);
81
+ }
82
+
83
+ parts.push(message);
84
+
85
+ return parts.join(' ');
86
+ }
87
+
88
+ /**
89
+ * Check if a log level should be output
90
+ */
91
+ private static shouldLog(level: LogLevel): boolean {
92
+ return this.isDevelopment && level >= this.config.level;
93
+ }
94
+
95
+ /**
96
+ * Log debug information (development only)
97
+ */
98
+ static debug(component: string, message: string, ...args: any[]): void {
99
+ if (this.shouldLog(LogLevel.DEBUG)) {
100
+ try {
101
+ console.debug(this.formatMessage(LogLevel.DEBUG, component, message), ...args);
102
+ } catch (e) {
103
+ // Gracefully handle console method errors
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Log info information (development only)
110
+ */
111
+ static info(component: string, message: string, ...args: any[]): void {
112
+ if (this.shouldLog(LogLevel.INFO)) {
113
+ try {
114
+ console.info(this.formatMessage(LogLevel.INFO, component, message), ...args);
115
+ } catch (e) {
116
+ // Gracefully handle console method errors
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Log warning information (development only)
123
+ */
124
+ static warn(component: string, message: string, ...args: any[]): void {
125
+ if (this.shouldLog(LogLevel.WARN)) {
126
+ try {
127
+ console.warn(this.formatMessage(LogLevel.WARN, component, message), ...args);
128
+ } catch (e) {
129
+ // Gracefully handle console method errors
130
+ }
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Log error information (development only)
136
+ */
137
+ static error(component: string, message: string, ...args: any[]): void {
138
+ if (this.shouldLog(LogLevel.ERROR)) {
139
+ try {
140
+ console.error(this.formatMessage(LogLevel.ERROR, component, message), ...args);
141
+ } catch (e) {
142
+ // Gracefully handle console method errors
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Create a scoped logger for a specific component
149
+ */
150
+ static createScopedLogger(component: string) {
151
+ return {
152
+ debug: (message: string, ...args: any[]) => this.debug(component, message, ...args),
153
+ info: (message: string, ...args: any[]) => this.info(component, message, ...args),
154
+ warn: (message: string, ...args: any[]) => this.warn(component, message, ...args),
155
+ error: (message: string, ...args: any[]) => this.error(component, message, ...args),
156
+ };
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Default logger instance for convenience
162
+ */
163
+ export const logger = {
164
+ debug: (component: string, message: string, ...args: any[]) =>
165
+ Logger.debug(component, message, ...args),
166
+ info: (component: string, message: string, ...args: any[]) =>
167
+ Logger.info(component, message, ...args),
168
+ warn: (component: string, message: string, ...args: any[]) =>
169
+ Logger.warn(component, message, ...args),
170
+ error: (component: string, message: string, ...args: any[]) =>
171
+ Logger.error(component, message, ...args),
172
+ createScopedLogger: (component: string) => Logger.createScopedLogger(component),
173
+ configure: (config: Partial<LoggerConfig>) => Logger.configure(config),
174
+ };
175
+
176
+ /**
177
+ * Convenience function to create a scoped logger
178
+ */
179
+ export function createLogger(component: string) {
180
+ return Logger.createScopedLogger(component);
181
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @file Secure Device Fingerprinting
3
+ * @description Enhanced device fingerprinting with encryption and security measures
4
+ */
5
+
6
+ import { secureStorage } from '../security/secureStorage';
7
+
8
+ export interface DeviceFingerprint {
9
+ hash: string;
10
+ timestamp: number;
11
+ components: {
12
+ userAgent: string;
13
+ language: string;
14
+ platform: string;
15
+ screen: string;
16
+ timezone: string;
17
+ canvas?: string;
18
+ webgl?: string;
19
+ };
20
+ entropy: number;
21
+ }
22
+
23
+ /**
24
+ * Generate a secure device fingerprint (synchronous)
25
+ */
26
+ export function generateDeviceFingerprint(): DeviceFingerprint {
27
+ try {
28
+ const components = {
29
+ userAgent: getHashedUserAgent(),
30
+ language: navigator.language || 'unknown',
31
+ platform: navigator.platform || 'unknown',
32
+ screen: `${screen.width}x${screen.height}x${screen.colorDepth}`,
33
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'unknown',
34
+ canvas: getCanvasFingerprint(),
35
+ webgl: getWebGLFingerprint(),
36
+ };
37
+
38
+ // Calculate entropy (uniqueness score)
39
+ const entropy = calculateEntropy(components);
40
+
41
+ // Create a hash from all components
42
+ const fingerprintData = JSON.stringify(components);
43
+ const hash = hashStringSync(fingerprintData);
44
+
45
+ const fingerprint: DeviceFingerprint = {
46
+ hash,
47
+ timestamp: Date.now(),
48
+ components,
49
+ entropy,
50
+ };
51
+
52
+ // Store fingerprint asynchronously
53
+ secureStorage.setItem('device_fingerprint', JSON.stringify(fingerprint));
54
+
55
+ return fingerprint;
56
+ } catch (error) {
57
+ return generateFallbackFingerprint();
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Validate device fingerprint with security checks
63
+ */
64
+ export function validateDeviceFingerprint(
65
+ storedFingerprint: DeviceFingerprint,
66
+ currentFingerprint: DeviceFingerprint
67
+ ): {
68
+ isValid: boolean;
69
+ confidence: number;
70
+ reasons: string[];
71
+ } {
72
+ const reasons: string[] = [];
73
+ let matchingComponents = 0;
74
+ const totalComponents = Object.keys(storedFingerprint.components).length;
75
+
76
+ // Check each component
77
+ Object.entries(storedFingerprint.components).forEach(([key, value]) => {
78
+ if (currentFingerprint.components[key as keyof typeof currentFingerprint.components] === value) {
79
+ matchingComponents++;
80
+ } else {
81
+ reasons.push(`Component mismatch: ${key}`);
82
+ }
83
+ });
84
+
85
+ // Calculate confidence score
86
+ const confidence = (matchingComponents / totalComponents) * 100;
87
+
88
+ // Security thresholds
89
+ const isValid = confidence >= 80; // Require 80% match
90
+
91
+ // Additional security checks
92
+ const timeDiff = currentFingerprint.timestamp - storedFingerprint.timestamp;
93
+ const maxAge = 30 * 24 * 60 * 60 * 1000; // 30 days
94
+
95
+ if (timeDiff > maxAge) {
96
+ reasons.push('Fingerprint too old');
97
+ return { isValid: false, confidence, reasons };
98
+ }
99
+
100
+ if (confidence < 60) {
101
+ reasons.push('Device signature changed significantly');
102
+ }
103
+
104
+ return { isValid, confidence, reasons };
105
+ }
106
+
107
+ /**
108
+ * Generate canvas fingerprint for enhanced uniqueness
109
+ */
110
+ function getCanvasFingerprint(): string {
111
+ try {
112
+ const canvas = document.createElement('canvas');
113
+ const ctx = canvas.getContext('2d');
114
+
115
+ if (!ctx) return 'canvas-unavailable';
116
+
117
+ // Draw complex pattern for fingerprinting
118
+ ctx.textBaseline = 'top';
119
+ ctx.font = '14px Arial';
120
+ ctx.fillStyle = '#f60';
121
+ ctx.fillRect(125, 1, 62, 20);
122
+ ctx.fillStyle = '#069';
123
+ ctx.fillText('Device fingerprint 🔒', 2, 15);
124
+ ctx.fillStyle = 'rgba(102, 204, 0, 0.2)';
125
+ ctx.fillText('Device fingerprint 🔒', 4, 17);
126
+
127
+ const dataURL = canvas.toDataURL();
128
+ return hashStringSync(dataURL);
129
+ } catch (error) {
130
+ return 'canvas-error';
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get WebGL fingerprint
136
+ */
137
+ function getWebGLFingerprint(): string {
138
+ try {
139
+ const canvas = document.createElement('canvas');
140
+ const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl') as WebGLRenderingContext | null;
141
+
142
+ if (!gl) return 'webgl-unavailable';
143
+
144
+ const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
145
+ if (!debugInfo) return 'webgl-no-debug';
146
+
147
+ const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
148
+ const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
149
+
150
+ return `${vendor}|${renderer}`;
151
+ } catch (error) {
152
+ return 'webgl-error';
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Hash user agent to prevent direct exposure
158
+ */
159
+ function getHashedUserAgent(): string {
160
+ const ua = navigator.userAgent;
161
+ return hashStringSync(ua).substring(0, 16); // Shorter hash for storage
162
+ }
163
+
164
+ /**
165
+ * Calculate entropy of fingerprint components
166
+ */
167
+ function calculateEntropy(components: Record<string, string>): number {
168
+ const values = Object.values(components).join('');
169
+ const charCounts = new Map<string, number>();
170
+
171
+ for (const char of values) {
172
+ charCounts.set(char, (charCounts.get(char) || 0) + 1);
173
+ }
174
+
175
+ let entropy = 0;
176
+ for (const count of charCounts.values()) {
177
+ const probability = count / values.length;
178
+ entropy -= probability * Math.log2(probability);
179
+ }
180
+
181
+ return entropy;
182
+ }
183
+
184
+ /**
185
+ * Synchronous hash function for device fingerprinting
186
+ */
187
+ function hashStringSync(str: string): string {
188
+ let hash = 0;
189
+ for (let i = 0; i < str.length; i++) {
190
+ const char = str.charCodeAt(i);
191
+ hash = ((hash << 5) - hash) + char;
192
+ hash = hash & hash;
193
+ }
194
+ return Math.abs(hash).toString(36);
195
+ }
196
+
197
+ /**
198
+ * Generate fallback fingerprint for error cases
199
+ */
200
+ function generateFallbackFingerprint(): DeviceFingerprint {
201
+ const components = {
202
+ userAgent: 'fallback',
203
+ language: 'unknown',
204
+ platform: 'unknown',
205
+ screen: 'unknown',
206
+ timezone: 'unknown',
207
+ };
208
+
209
+ return {
210
+ hash: `fallback_${Date.now()}_${Math.random().toString(36)}`,
211
+ timestamp: Date.now(),
212
+ components,
213
+ entropy: 1, // Low entropy for fallback
214
+ };
215
+ }
@@ -0,0 +1,105 @@
1
+
2
+ /**
3
+ * Dynamic utility loader to reduce initial bundle size
4
+ * Heavy utilities are loaded on-demand
5
+ */
6
+
7
+ // Type definitions for dynamic imports
8
+ type DebounceFunction = <T extends (...args: unknown[]) => unknown>(
9
+ func: T,
10
+ wait?: number,
11
+ options?: { leading?: boolean; maxWait?: number; trailing?: boolean }
12
+ ) => T & { cancel(): void; flush(): void };
13
+
14
+ type ThrottleFunction = <T extends (...args: unknown[]) => unknown>(
15
+ func: T,
16
+ wait?: number,
17
+ options?: { leading?: boolean; trailing?: boolean }
18
+ ) => T & { cancel(): void; flush(): void };
19
+
20
+ // Dynamic lodash utilities
21
+ export const loadLodash = async (): Promise<{
22
+ debounce: DebounceFunction;
23
+ throttle: ThrottleFunction;
24
+ }> => {
25
+ const [debounceModule, throttleModule] = await Promise.all([
26
+ import('lodash.debounce' as any),
27
+ import('lodash.throttle' as any)
28
+ ]);
29
+
30
+ return {
31
+ debounce: (debounceModule.default || debounceModule) as DebounceFunction,
32
+ throttle: (throttleModule.default || throttleModule) as ThrottleFunction
33
+ };
34
+ };
35
+
36
+ // Dynamic date utilities
37
+ export const loadDateUtils = async (): Promise<typeof import('date-fns')> => {
38
+ const dateFns = await import('date-fns');
39
+ return dateFns;
40
+ };
41
+
42
+ // Dynamic chart utilities - using unknown type to avoid Recharts type issues
43
+ export const loadChartUtils = async (): Promise<unknown> => {
44
+ const recharts = await import('recharts');
45
+ return recharts;
46
+ };
47
+
48
+ // Dynamic form utilities
49
+ export const loadFormUtils = async (): Promise<{
50
+ useForm: unknown;
51
+ useController: unknown;
52
+ Controller: unknown;
53
+ FormProvider: unknown;
54
+ useFormContext: unknown;
55
+ useWatch: unknown;
56
+ useFormState: unknown;
57
+ useFieldArray: unknown;
58
+ zodResolver: unknown;
59
+ }> => {
60
+ const [reactHookForm, zodResolvers] = await Promise.all([
61
+ import('react-hook-form'),
62
+ import('@hookform/resolvers/zod')
63
+ ]);
64
+
65
+ return {
66
+ ...reactHookForm,
67
+ zodResolver: zodResolvers.zodResolver
68
+ };
69
+ };
70
+
71
+ // Dynamic CSV utilities
72
+ export const loadCSVUtils = async (): Promise<unknown> => {
73
+ const papaparse = await import('papaparse');
74
+ return papaparse.default;
75
+ };
76
+
77
+ // Utility function to create lazy utility hooks
78
+ export function createLazyUtility<T>(loader: () => Promise<T>) {
79
+ let cached: T | null = null;
80
+ let loading: Promise<T> | null = null;
81
+
82
+ return {
83
+ load: async (): Promise<T> => {
84
+ if (cached) return cached;
85
+ if (loading) return loading;
86
+
87
+ loading = loader().then(result => {
88
+ cached = result;
89
+ loading = null;
90
+ return result;
91
+ });
92
+
93
+ return loading;
94
+ },
95
+ getCached: (): T | null => cached,
96
+ isLoaded: (): boolean => cached !== null
97
+ };
98
+ }
99
+
100
+ // Pre-configured lazy utilities with explicit types
101
+ export const lazyLodash: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadLodash>>>> = createLazyUtility(loadLodash);
102
+ export const lazyDateUtils: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadDateUtils>>>> = createLazyUtility(loadDateUtils);
103
+ export const lazyChartUtils: ReturnType<typeof createLazyUtility<unknown>> = createLazyUtility(loadChartUtils);
104
+ export const lazyFormUtils: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadFormUtils>>>> = createLazyUtility(loadFormUtils);
105
+ export const lazyCSVUtils: ReturnType<typeof createLazyUtility<unknown>> = createLazyUtility(loadCSVUtils);
@@ -0,0 +1,44 @@
1
+ import React, { Suspense, ComponentType, lazy } from 'react';
2
+ import { LoadingSpinner } from '../../components/LoadingSpinner/LoadingSpinner';
3
+
4
+ interface LazyLoadOptions {
5
+ fallback?: React.ReactNode;
6
+ errorBoundary?: ComponentType<{ children: React.ReactNode }>;
7
+ }
8
+
9
+ /**
10
+ * Create a lazy-loaded component with error boundary and loading fallback
11
+ */
12
+ export function createLazyComponent<T extends ComponentType<any>>(
13
+ importFn: () => Promise<{ default: T }>,
14
+ componentName: string,
15
+ options: LazyLoadOptions = {}
16
+ ): T {
17
+ const LazyComponent = lazy(importFn);
18
+
19
+ const WrappedComponent = (props: any) => {
20
+ const content = (
21
+ <Suspense fallback={options.fallback || <LoadingSpinner />}>
22
+ <LazyComponent {...props} />
23
+ </Suspense>
24
+ );
25
+
26
+ if (options.errorBoundary) {
27
+ const ErrorBoundary = options.errorBoundary;
28
+ return <ErrorBoundary>{content}</ErrorBoundary>;
29
+ }
30
+
31
+ return content;
32
+ };
33
+
34
+ WrappedComponent.displayName = `Lazy${componentName}`;
35
+ return WrappedComponent as T;
36
+ }
37
+
38
+ /**
39
+ * Lazy-loaded DataTable component
40
+ */
41
+ export const LazyDataTable = createLazyComponent(
42
+ () => import('../../components/DataTable').then(module => ({ default: module.DataTable })),
43
+ 'DataTable'
44
+ );