@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,237 @@
1
+ /**
2
+ * @file formatDate Utility Tests
3
+ * @description Comprehensive tests for the formatDate utility function
4
+ */
5
+
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { formatDate } from './formatting';
8
+
9
+ describe('formatDate Utility', () => {
10
+ let originalLocale: string;
11
+ let originalTimezone: string;
12
+
13
+ beforeEach(() => {
14
+ // Store original values
15
+ originalLocale = Intl.DateTimeFormat().resolvedOptions().locale;
16
+ originalTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
17
+ });
18
+
19
+ describe('Date Object Input', () => {
20
+ it('formats a Date object correctly', () => {
21
+ const date = new Date('2024-01-15T10:30:00.000Z');
22
+ const result = formatDate(date);
23
+
24
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
25
+ });
26
+
27
+ it('formats different Date objects', () => {
28
+ const dates = [
29
+ new Date('2023-12-25T00:00:00.000Z'),
30
+ new Date('2024-06-15T12:00:00.000Z'),
31
+ new Date('2024-12-31T23:59:59.999Z')
32
+ ];
33
+
34
+ dates.forEach(date => {
35
+ const result = formatDate(date);
36
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
37
+ });
38
+ });
39
+ });
40
+
41
+ describe('String Input', () => {
42
+ it('formats ISO date strings correctly', () => {
43
+ const result = formatDate('2024-01-15T10:30:00.000Z');
44
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
45
+ });
46
+
47
+ it('formats date-only strings correctly', () => {
48
+ const result = formatDate('2024-01-15');
49
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
50
+ });
51
+
52
+ it('formats various date string formats', () => {
53
+ const dateStrings = [
54
+ '2024-01-15',
55
+ '2024-01-15T10:30:00Z',
56
+ '2024-01-15T10:30:00.000Z',
57
+ '2024-01-15T10:30:00+00:00'
58
+ ];
59
+
60
+ dateStrings.forEach(dateString => {
61
+ const result = formatDate(dateString);
62
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
63
+ });
64
+ });
65
+ });
66
+
67
+ describe('Number Input', () => {
68
+ it('formats timestamp numbers correctly', () => {
69
+ const timestamp = new Date('2024-01-15T10:30:00.000Z').getTime();
70
+ const result = formatDate(timestamp);
71
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
72
+ });
73
+
74
+ it('formats Unix timestamps correctly', () => {
75
+ const unixTimestamp = Math.floor(new Date('2024-01-15T10:30:00.000Z').getTime() / 1000);
76
+ const result = formatDate(unixTimestamp * 1000); // Convert back to milliseconds
77
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
78
+ });
79
+ });
80
+
81
+ describe('Edge Cases', () => {
82
+ it('handles invalid date strings gracefully', () => {
83
+ const invalidDates = [
84
+ 'invalid-date',
85
+ 'not-a-date',
86
+ '2024-13-45', // Invalid month and day
87
+ '2024-02-30' // Invalid day for February
88
+ ];
89
+
90
+ invalidDates.forEach(invalidDate => {
91
+ const result = formatDate(invalidDate);
92
+ // Should return a string even for invalid dates (may be "Invalid Date")
93
+ expect(typeof result).toBe('string');
94
+ expect(result.length).toBeGreaterThan(0);
95
+ });
96
+ });
97
+
98
+ it('handles empty string input', () => {
99
+ const result = formatDate('');
100
+ expect(typeof result).toBe('string');
101
+ });
102
+
103
+ it('handles null and undefined input', () => {
104
+ // @ts-expect-error - Testing runtime behavior with invalid types
105
+ expect(() => formatDate(null)).toThrow();
106
+ // @ts-expect-error - Testing runtime behavior with invalid types
107
+ expect(() => formatDate(undefined)).toThrow();
108
+ });
109
+
110
+ it('handles very large numbers', () => {
111
+ const largeNumber = Number.MAX_SAFE_INTEGER;
112
+ const result = formatDate(largeNumber);
113
+ expect(typeof result).toBe('string');
114
+ });
115
+
116
+ it('handles negative numbers', () => {
117
+ const negativeNumber = -1000000;
118
+ const result = formatDate(negativeNumber);
119
+ expect(typeof result).toBe('string');
120
+ });
121
+
122
+ it('handles zero', () => {
123
+ const result = formatDate(0);
124
+ expect(typeof result).toBe('string');
125
+ });
126
+ });
127
+
128
+ describe('Format Consistency', () => {
129
+ it('returns consistent format for same date', () => {
130
+ const date = new Date('2024-01-15T10:30:00.000Z');
131
+ const result1 = formatDate(date);
132
+ const result2 = formatDate(date);
133
+
134
+ expect(result1).toBe(result2);
135
+ });
136
+
137
+ it('returns consistent format across different input types for same date', () => {
138
+ const date = new Date('2024-01-15T10:30:00.000Z');
139
+ const dateString = '2024-01-15T10:30:00.000Z';
140
+ const timestamp = date.getTime();
141
+
142
+ const result1 = formatDate(date);
143
+ const result2 = formatDate(dateString);
144
+ const result3 = formatDate(timestamp);
145
+
146
+ expect(result1).toBe(result2);
147
+ expect(result2).toBe(result3);
148
+ });
149
+ });
150
+
151
+ describe('Locale Handling', () => {
152
+ it('uses default locale when no locale is specified', () => {
153
+ const date = new Date('2024-01-15T10:30:00.000Z');
154
+ const result = formatDate(date);
155
+
156
+ // Should use the default locale format
157
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
158
+ });
159
+
160
+ it('handles different locales correctly', () => {
161
+ const date = new Date('2024-01-15T10:30:00.000Z');
162
+
163
+ const result = formatDate(date);
164
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
165
+ });
166
+ });
167
+
168
+ describe('Time Zone Handling', () => {
169
+ it('handles different time zones correctly', () => {
170
+ const date = new Date('2024-01-15T10:30:00.000Z');
171
+ const result = formatDate(date);
172
+
173
+ // Should format consistently regardless of timezone
174
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
175
+ });
176
+ });
177
+
178
+ describe('Performance', () => {
179
+ it('handles large number of calls efficiently', () => {
180
+ const date = new Date('2024-01-15T10:30:00.000Z');
181
+ const startTime = performance.now();
182
+
183
+ // Call formatDate many times
184
+ for (let i = 0; i < 1000; i++) {
185
+ formatDate(date);
186
+ }
187
+
188
+ const endTime = performance.now();
189
+ const duration = endTime - startTime;
190
+
191
+ // Should complete in reasonable time (less than 200ms for 1000 calls)
192
+ expect(duration).toBeLessThan(200);
193
+ });
194
+ });
195
+
196
+ describe('Type Safety', () => {
197
+ it('accepts valid Date types', () => {
198
+ const date = new Date();
199
+ expect(() => formatDate(date)).not.toThrow();
200
+ });
201
+
202
+ it('accepts valid string types', () => {
203
+ const dateString = '2024-01-15';
204
+ expect(() => formatDate(dateString)).not.toThrow();
205
+ });
206
+
207
+ it('accepts valid number types', () => {
208
+ const timestamp = Date.now();
209
+ expect(() => formatDate(timestamp)).not.toThrow();
210
+ });
211
+ });
212
+
213
+ describe('Return Value', () => {
214
+ it('returns a string', () => {
215
+ const date = new Date('2024-01-15T10:30:00.000Z');
216
+ const result = formatDate(date);
217
+
218
+ expect(typeof result).toBe('string');
219
+ });
220
+
221
+ it('returns non-empty string for valid dates', () => {
222
+ const date = new Date('2024-01-15T10:30:00.000Z');
223
+ const result = formatDate(date);
224
+
225
+ expect(result).toBeTruthy();
226
+ expect(result.length).toBeGreaterThan(0);
227
+ });
228
+
229
+ it('returns expected format pattern', () => {
230
+ const date = new Date('2024-01-15T10:30:00.000Z');
231
+ const result = formatDate(date);
232
+
233
+ // Should match pattern: "MMM DD, YYYY"
234
+ expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
235
+ });
236
+ });
237
+ });
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Utility functions for formatting data in the application
3
+ */
4
+
5
+ /**
6
+ * Format a date as a readable string in "dd mmm yyyy" format (e.g., "15 Jun 2024")
7
+ */
8
+ export function formatDate(date: Date | string | number): string {
9
+ const dateObj = typeof date === 'string' || typeof date === 'number'
10
+ ? new Date(date)
11
+ : date;
12
+
13
+ // Use 'en-GB' locale to ensure "dd mmm yyyy" format (e.g., "15 Jun 2024")
14
+ return dateObj.toLocaleDateString('en-GB', {
15
+ year: 'numeric',
16
+ month: 'short',
17
+ day: 'numeric'
18
+ });
19
+ }
20
+
21
+ /**
22
+ * Format a number as a currency
23
+ */
24
+ export function formatCurrency(value: number, currencyCode = 'USD', locale = 'en-US'): string {
25
+ return new Intl.NumberFormat(locale, {
26
+ style: 'currency',
27
+ currency: currencyCode,
28
+ }).format(value);
29
+ }
30
+
31
+ /**
32
+ * Format a number with custom options
33
+ */
34
+ export function formatNumber(
35
+ value: number,
36
+ options: Intl.NumberFormatOptions = {},
37
+ locale = 'en-US'
38
+ ): string {
39
+ return new Intl.NumberFormat(locale, options).format(value);
40
+ }
41
+
42
+ /**
43
+ * Format a number as a percentage.
44
+ *
45
+ * The third parameter can be either:
46
+ * - A number for fixed decimal places (backward compatible): `formatPercent(0.81, 'en-US', 2)`
47
+ * - An options object with:
48
+ * - `decimals`: Fixed number of decimal places (default: 1)
49
+ * - `preserveDecimals`: Auto-detect and preserve decimal places from the input value
50
+ * - `maxDecimals`: Maximum decimal places when preserving (default: 10)
51
+ *
52
+ * @param value - The percentage value as a decimal (e.g., 0.81 for 0.81%)
53
+ * @param locale - The locale string (default: 'en-US')
54
+ * @param decimalsOrOptions - Either a number for fixed decimals, or an options object with:
55
+ * - `decimals` - Fixed number of decimal places (default: 1)
56
+ * - `preserveDecimals` - Auto-detect and preserve decimal places from the input value
57
+ * - `maxDecimals` - Maximum decimal places when preserving (default: 10)
58
+ * @returns Formatted percentage string (e.g., "0.81%", "81%")
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * // Fixed decimals (default behavior)
63
+ * formatPercent(0.5) // '0.5%'
64
+ * formatPercent(0.81, 'en-US', 1) // '0.8%' (loses precision)
65
+ *
66
+ * // Preserve decimal places dynamically
67
+ * formatPercent(0.81, 'en-US', { preserveDecimals: true }) // '0.81%'
68
+ * formatPercent(0.8123, 'en-US', { preserveDecimals: true, maxDecimals: 2 }) // '0.81%'
69
+ * ```
70
+ */
71
+ export function formatPercent(
72
+ value: number,
73
+ locale: string = 'en-US',
74
+ decimalsOrOptions?: number | {
75
+ decimals?: number;
76
+ preserveDecimals?: boolean;
77
+ maxDecimals?: number;
78
+ }
79
+ ): string {
80
+ let decimals: number;
81
+
82
+ // Backward compatibility: if decimalsOrOptions is a number, use it directly
83
+ if (typeof decimalsOrOptions === 'number') {
84
+ decimals = decimalsOrOptions;
85
+ } else if (decimalsOrOptions && typeof decimalsOrOptions === 'object') {
86
+ // New options object: check if we should preserve decimals
87
+ if (decimalsOrOptions.preserveDecimals) {
88
+ const valueStr = value.toString();
89
+ const decimalIndex = valueStr.indexOf('.');
90
+
91
+ if (decimalIndex !== -1) {
92
+ const detectedDecimals = valueStr.length - decimalIndex - 1;
93
+ const maxDecimals = decimalsOrOptions.maxDecimals ?? 10;
94
+ decimals = Math.min(detectedDecimals, maxDecimals);
95
+ } else {
96
+ decimals = 0;
97
+ }
98
+ } else {
99
+ decimals = decimalsOrOptions.decimals ?? 1;
100
+ }
101
+ } else {
102
+ decimals = 1;
103
+ }
104
+
105
+ return new Intl.NumberFormat(locale, {
106
+ style: 'percent',
107
+ minimumFractionDigits: decimals,
108
+ maximumFractionDigits: decimals,
109
+ }).format(value / 100);
110
+ }
111
+
112
+ /**
113
+ * Format a large number with abbreviations (K, M, B)
114
+ */
115
+ export function formatCompactNumber(value: number, locale = 'en-US'): string {
116
+ return new Intl.NumberFormat(locale, {
117
+ notation: 'compact',
118
+ compactDisplay: 'short'
119
+ }).format(value);
120
+ }
121
+
122
+ /**
123
+ * Format a file size in bytes to a human-readable string
124
+ */
125
+ export function formatFileSize(bytes: number): string {
126
+ if (bytes === 0) return '0 Bytes';
127
+
128
+ const k = 1024;
129
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
130
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
131
+
132
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
133
+ }
@@ -6,39 +6,57 @@
6
6
  */
7
7
 
8
8
  // Core utilities
9
- export { cn } from './cn';
10
- export { DebugLogger } from './debugLogger';
9
+ export { cn } from './core/cn';
10
+ export { DebugLogger } from './core/debugLogger';
11
+ export { Logger, logger, createLogger, LogLevel } from './core/logger';
12
+ export type { LoggerConfig } from './core/logger';
11
13
 
12
14
  // App configuration utilities
13
- export * from './appNameResolver';
14
- export * from './appConfig';
15
+ export * from './app/appNameResolver';
16
+ export { setAppConfig, getAppConfig, getCurrentAppId } from './app/appConfig';
17
+ export * from './app/appIdResolver';
15
18
 
16
19
  // Validation and sanitization
17
20
  export * from './validation';
18
- export * from './validationUtils';
19
- export * from './sanitization';
21
+ // Explicitly re-export commonly used validation utilities to ensure they're available
22
+ // Import from source modules to avoid re-export issues
23
+ export { validateUserInput, usernameSchema } from './validation/validationUtils';
24
+ export { sanitizeUserInput, sanitizeFormData } from './validation/sanitization';
25
+ export { emailSchema, nameSchema, phoneSchema, urlSchema } from './validation/common';
26
+ export { passwordSchema } from './validation/passwordSchema';
27
+ export { pickSchema, combineSchemas } from './validation/schema';
20
28
 
21
29
  // Security utilities
22
30
  export {
23
31
  getSecurityHeaders,
24
32
  validateSecurityHeaders
25
- } from './security';
33
+ } from './security/security';
34
+ export type { SecurityEvent } from './security/security';
26
35
 
27
- // Note: Accessibility testing utilities are only available in test environments
28
- // They are not exported in production builds to avoid including test dependencies
36
+ // Security monitoring utilities
37
+ export {
38
+ securityMonitor
39
+ } from './security/securityMonitor';
40
+ export type { SecureDataAccess } from './security/secureDataAccess';
29
41
 
30
42
  // Performance utilities
31
43
  export { useComponentPerformance } from '../hooks/useComponentPerformance';
32
44
  export { PERFORMANCE_THRESHOLDS } from '../constants/performance';
33
- export { createPerformanceBenchmark, measureRenderPerformance } from './performanceBenchmark';
34
- export type { PerformanceMetrics } from './performanceBenchmark';
45
+ export { createPerformanceBenchmark, measureRenderPerformance } from './performance/performanceBenchmark';
46
+ export type { PerformanceMetrics } from './performance/performanceBenchmark';
35
47
 
36
48
  // Bundle analysis utilities
37
49
  export {
38
50
  bundleAnalyzer,
39
51
  validateImportPattern,
40
52
  trackDynamicImport
41
- } from './bundleAnalysis';
53
+ } from './performance/bundleAnalysis';
54
+
55
+ // Performance budget utilities
56
+ export {
57
+ performanceBudgetMonitor,
58
+ PERFORMANCE_BUDGETS
59
+ } from './performance/performanceBudgets';
42
60
 
43
61
  // Dynamic utility loaders
44
62
  export {
@@ -53,25 +71,10 @@ export {
53
71
  lazyChartUtils,
54
72
  lazyFormUtils,
55
73
  lazyCSVUtils
56
- } from './dynamicUtils';
57
-
58
- // Performance budget utilities
59
- export {
60
- performanceBudgetMonitor,
61
- PERFORMANCE_BUDGETS
62
- } from './performanceBudgets';
74
+ } from './dynamic/dynamicUtils';
63
75
 
64
76
  // Lazy loading utilities
65
- export { createLazyComponent, LazyDataTable } from './lazyLoad';
66
-
67
- // App configuration utilities
68
- export {
69
- setAppConfig,
70
- getAppConfig,
71
- getCurrentAppName,
72
- getCurrentAppId
73
- } from './appConfig';
74
- export type { AppConfig } from './appConfig';
77
+ export { createLazyComponent, LazyDataTable } from './dynamic/lazyLoad';
75
78
 
76
79
  // Permission utilities
77
80
  export {
@@ -79,30 +82,18 @@ export {
79
82
  hasPermission,
80
83
  hasAnyPermission,
81
84
  hasAllPermissions
82
- } from './permissionUtils';
85
+ } from './permissions/permissionUtils';
83
86
 
84
87
  // Permission types
85
88
  export {
86
89
  PermissionType,
87
90
  parsePermission
88
- } from './permissionTypes';
89
-
90
- // Schema utilities
91
- export {
92
- pickSchema,
93
- combineSchemas
94
- } from './schemaUtils';
95
-
96
- // Security monitoring utilities
97
- export {
98
- securityMonitor
99
- } from './securityMonitor';
100
- export type { SecureDataAccess } from './secureDataAccess';
91
+ } from './permissions/permissionTypes';
101
92
 
102
93
  // Session tracking utilities
103
94
  export {
104
95
  useSessionTracking
105
- } from './sessionTracking';
96
+ } from './context/sessionTracking';
106
97
 
107
98
  // Audit utilities
108
99
  export {
@@ -112,14 +103,13 @@ export {
112
103
  logPermissionEvent,
113
104
  logSecurityEvent,
114
105
  logAuditEvent
115
- } from './audit';
106
+ } from './audit/audit';
116
107
 
117
108
  // Device fingerprinting utilities
118
109
  export {
119
110
  generateDeviceFingerprint,
120
111
  validateDeviceFingerprint
121
- } from './deviceFingerprint';
122
-
112
+ } from './device/deviceFingerprint';
123
113
 
124
114
  // Formatting utilities
125
115
  export {
@@ -129,7 +119,7 @@ export {
129
119
  formatPercent,
130
120
  formatCompactNumber,
131
121
  formatFileSize
132
- } from './formatting';
122
+ } from './formatting/formatting';
133
123
 
134
124
  // Organisation context utilities
135
125
  export {
@@ -137,9 +127,4 @@ export {
137
127
  clearOrganisationContext,
138
128
  getOrganisationContext,
139
129
  isOrganisationContextAvailable
140
- } from './organisationContext';
141
-
142
- // Re-export types for convenience
143
- export type {
144
- SecurityEvent
145
- } from './security';
130
+ } from './context/organisationContext';
@@ -0,0 +1,129 @@
1
+
2
+ interface BundleStats {
3
+ totalSize: number;
4
+ gzippedSize: number;
5
+ chunks: ChunkInfo[];
6
+ treeshakingEffectiveness: number;
7
+ }
8
+
9
+ interface ChunkInfo {
10
+ name: string;
11
+ size: number;
12
+ modules: string[];
13
+ dynamicallyImported: boolean;
14
+ }
15
+
16
+ class BundleAnalyzer {
17
+ private enabled = import.meta.env.MODE === 'development';
18
+
19
+ analyzeBundle(): BundleStats | null {
20
+ if (!this.enabled) return null;
21
+
22
+ // In a real implementation, this would integrate with webpack-bundle-analyzer
23
+ // or similar tools. For now, we'll simulate analysis
24
+
25
+ // TODO: Replace with proper logging service integration
26
+ // For now, we'll log to console for testing purposes
27
+ console.log('Bundle analysis would run here in development');
28
+ console.log('To enable real bundle analysis:');
29
+ console.log('1. Install webpack-bundle-analyzer');
30
+ console.log('2. Add bundle analysis to build scripts');
31
+ console.log('3. Integrate with performance budgets');
32
+
33
+ return {
34
+ totalSize: 0,
35
+ gzippedSize: 0,
36
+ chunks: [],
37
+ treeshakingEffectiveness: 0
38
+ };
39
+ }
40
+
41
+ checkTreeshaking(): void {
42
+ if (!this.enabled) return;
43
+
44
+ const potentialIssues = [
45
+ 'Check for unused exports in index files',
46
+ 'Verify side-effect free modules in package.json',
47
+ 'Ensure proper ES module syntax',
48
+ 'Check for circular dependencies'
49
+ ];
50
+
51
+ // TODO: Replace with proper logging service integration
52
+ // For now, we'll log to console for testing purposes
53
+ console.group('Tree-shaking Analysis');
54
+ potentialIssues.forEach(issue => console.log('- ' + issue));
55
+ console.groupEnd();
56
+ }
57
+
58
+ validateExports(): void {
59
+ if (!this.enabled) return;
60
+
61
+ // TODO: Replace with proper logging service integration
62
+ // For now, we'll log to console for testing purposes
63
+ console.group('Export Validation');
64
+ console.log('Checking for optimal export patterns...');
65
+ console.log('- Prefer named exports over default exports');
66
+ console.log('- Avoid barrel exports for large modules');
67
+ console.log('- Use dynamic imports for large dependencies');
68
+ console.groupEnd();
69
+ }
70
+
71
+ generateReport(): string {
72
+ const report = `
73
+ # Bundle Analysis Report
74
+
75
+ ## Recommendations for @jmruthers/pace-core
76
+
77
+ ### 1. Code Splitting Opportunities
78
+ - ✅ DataTable virtualization is lazy-loaded
79
+ - ⚠️ Consider splitting auth providers by use case
80
+ - ⚠️ Lazy load heavy UI components (charts, complex forms)
81
+
82
+ ### 2. Tree-shaking Optimization
83
+ - ✅ Using ES modules throughout
84
+ - ✅ Proper sideEffects configuration
85
+ - ⚠️ Check for unused utility functions
86
+
87
+ ### 3. Bundle Size Targets
88
+ - Core components: < 50KB gzipped
89
+ - Auth module: < 30KB gzipped
90
+ - Utilities: < 20KB gzipped
91
+ - Total package: < 150KB gzipped
92
+
93
+ ### 4. Performance Monitoring
94
+ - Monitor component render times
95
+ - Track bundle size changes
96
+ - Validate tree-shaking effectiveness
97
+ `;
98
+
99
+ return report.trim();
100
+ }
101
+ }
102
+
103
+ export const bundleAnalyzer = new BundleAnalyzer();
104
+
105
+ // Helper to check if imports are optimized
106
+ export function validateImportPattern(moduleId: string, importedItems: string[]): void {
107
+ if (import.meta.env.MODE !== 'development') return;
108
+
109
+ const largeModules = ['lodash', 'moment', 'rxjs'];
110
+ const isLargeModule = largeModules.some(mod => moduleId.includes(mod));
111
+
112
+ if (isLargeModule && importedItems.length > 5) {
113
+ // TODO: Replace with proper logging service integration
114
+ // For now, we'll log to console for testing purposes
115
+ console.warn(
116
+ 'Large import detected: importing ' + importedItems.length + ' items from ' + moduleId + '. ' +
117
+ 'Consider splitting imports or using more specific imports.'
118
+ );
119
+ }
120
+ }
121
+
122
+ // Monitor dynamic imports
123
+ export function trackDynamicImport(moduleName: string): void {
124
+ if (import.meta.env.MODE !== 'development') return;
125
+
126
+ // TODO: Replace with proper logging service integration
127
+ // For now, we'll log to console for testing purposes
128
+ console.log('Dynamic import: ' + moduleName + ' - Good for code splitting!');
129
+ }