@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
@@ -98,7 +98,21 @@ describe('ProtectedRoute Component', () => {
98
98
  isLoading: false,
99
99
  };
100
100
 
101
+ let originalMode: string | undefined;
102
+
101
103
  beforeEach(() => {
104
+ // Ensure logger is enabled by setting MODE to development
105
+ originalMode = import.meta.env.MODE;
106
+ (import.meta.env as any).MODE = 'development';
107
+
108
+ import('../../utils/core/logger').then(({ Logger, LogLevel }) => {
109
+ Logger.configure({
110
+ level: LogLevel.DEBUG,
111
+ includeTimestamp: false,
112
+ includeComponent: true,
113
+ });
114
+ });
115
+
102
116
  vi.clearAllMocks();
103
117
  console.debug = vi.fn();
104
118
  console.warn = vi.fn();
@@ -112,6 +126,11 @@ describe('ProtectedRoute Component', () => {
112
126
  afterEach(() => {
113
127
  console.debug = originalConsoleDebug;
114
128
  console.warn = originalConsoleWarn;
129
+
130
+ // Restore original mode
131
+ if (originalMode !== undefined) {
132
+ (import.meta.env as any).MODE = originalMode;
133
+ }
115
134
  });
116
135
 
117
136
  describe('Rendering', () => {
@@ -124,6 +143,8 @@ describe('ProtectedRoute Component', () => {
124
143
  });
125
144
 
126
145
  it('renders outlet when events exist but none selected (allows event selector visibility)', () => {
146
+ const consoleDebugSpy = vi.spyOn(console, 'debug').mockImplementation(() => {});
147
+
127
148
  mockUseEvents.mockReturnValue({
128
149
  selectedEvent: null,
129
150
  events: [{ id: 'event-1', name: 'Test Event' }],
@@ -133,8 +154,8 @@ describe('ProtectedRoute Component', () => {
133
154
  renderWithProviders(<ProtectedRoute />);
134
155
 
135
156
  expect(screen.getByTestId('outlet')).toBeInTheDocument();
136
- expect(console.debug).toHaveBeenCalledWith(
137
- '[ProtectedRoute] Events available but none selected - allowing render so selector is visible'
157
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
158
+ expect.stringContaining('[DEBUG] [ProtectedRoute] Events available but none selected - allowing render so selector is visible')
138
159
  );
139
160
  });
140
161
 
@@ -222,6 +243,8 @@ describe('ProtectedRoute Component', () => {
222
243
  });
223
244
 
224
245
  it('warns when redirecting due to session restoration timeout', () => {
246
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
247
+
225
248
  mockUseUnifiedAuth.mockReturnValue({
226
249
  isAuthenticated: false,
227
250
  authLoading: false,
@@ -236,8 +259,8 @@ describe('ProtectedRoute Component', () => {
236
259
 
237
260
  renderWithProviders(<ProtectedRoute />);
238
261
 
239
- expect(console.warn).toHaveBeenCalledWith(
240
- '[ProtectedRoute] Session restoration failed, redirecting to login',
262
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
263
+ expect.stringContaining('[WARN] [ProtectedRoute] Session restoration failed, redirecting to login'),
241
264
  expect.objectContaining({
242
265
  timedOut: true,
243
266
  })
@@ -259,10 +282,12 @@ describe('ProtectedRoute Component', () => {
259
282
  hasTimedOut: false,
260
283
  });
261
284
 
285
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
286
+
262
287
  renderWithProviders(<ProtectedRoute />);
263
288
 
264
- expect(console.warn).toHaveBeenCalledWith(
265
- '[ProtectedRoute] Session restoration failed, redirecting to login',
289
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
290
+ expect.stringContaining('[WARN] [ProtectedRoute] Session restoration failed, redirecting to login'),
266
291
  expect.objectContaining({
267
292
  error: 'Session restoration failed',
268
293
  timedOut: false,
@@ -408,11 +433,13 @@ describe('ProtectedRoute Component', () => {
408
433
  isLoading: false,
409
434
  });
410
435
 
436
+ const consoleDebugSpy = vi.spyOn(console, 'debug').mockImplementation(() => {});
437
+
411
438
  renderWithProviders(<ProtectedRoute requireEvent={true} />);
412
439
 
413
440
  expect(screen.getByTestId('outlet')).toBeInTheDocument();
414
- expect(console.debug).toHaveBeenCalledWith(
415
- '[ProtectedRoute] Events available but none selected - allowing render so selector is visible'
441
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
442
+ expect.stringContaining('[DEBUG] [ProtectedRoute] Events available but none selected - allowing render so selector is visible')
416
443
  );
417
444
  });
418
445
 
@@ -76,6 +76,7 @@ import { useEvents } from '../../hooks/useEvents';
76
76
  import { LoadingSpinner } from '../LoadingSpinner/LoadingSpinner';
77
77
  import { SessionRestorationLoader } from '../SessionRestorationLoader';
78
78
  import { Alert, AlertDescription, AlertTitle } from '../Alert/Alert';
79
+ import { logger } from '../../utils/core/logger';
79
80
 
80
81
  export interface ProtectedRouteProps {
81
82
  /**
@@ -175,7 +176,7 @@ export function ProtectedRoute({
175
176
  // Redirect to login if not authenticated
176
177
  if (!isAuthenticated) {
177
178
  if (sessionRestoration.hasTimedOut || sessionRestoration.restorationError) {
178
- console.warn('[ProtectedRoute] Session restoration failed, redirecting to login', {
179
+ logger.warn('ProtectedRoute', 'Session restoration failed, redirecting to login', {
179
180
  timedOut: sessionRestoration.hasTimedOut,
180
181
  error: sessionRestoration.restorationError?.message
181
182
  });
@@ -217,7 +218,7 @@ export function ProtectedRoute({
217
218
  // The event selector will be visible and user can select, or auto-selection will kick in
218
219
  if (!selectedEvent) {
219
220
  // Log for debugging - this is expected behavior, not an error
220
- console.debug('[ProtectedRoute] Events available but none selected - allowing render so selector is visible');
221
+ logger.debug('ProtectedRoute', 'Events available but none selected - allowing render so selector is visible');
221
222
  return <Outlet />;
222
223
  }
223
224
 
@@ -40,7 +40,7 @@
40
40
  */
41
41
 
42
42
  import React, { Component, ErrorInfo, ReactNode } from 'react';
43
- import { cn } from '../../utils/cn';
43
+ import { cn } from '../../utils/core/cn';
44
44
 
45
45
  export interface PublicErrorBoundaryProps {
46
46
  /** Child components to wrap */
@@ -37,7 +37,7 @@
37
37
  */
38
38
 
39
39
  import React from 'react';
40
- import { cn } from '../../utils/cn';
40
+ import { cn } from '../../utils/core/cn';
41
41
 
42
42
  export interface PublicLoadingSpinnerProps {
43
43
  /** Loading message to display */
@@ -10,6 +10,7 @@
10
10
 
11
11
  import React, { useEffect } from 'react';
12
12
  import { usePublicPageContext } from './PublicPageProvider';
13
+ import { logger } from '../../utils/core/logger';
13
14
 
14
15
  export interface PublicPageContextCheckerProps {
15
16
  /** Whether to enable checking */
@@ -23,88 +24,88 @@ export interface PublicPageContextCheckerProps {
23
24
  *
24
25
  * This component will immediately log to console if authentication context
25
26
  * is being triggered in a public page.
27
+ *
28
+ * Only enabled in development mode when VITE_ENABLE_DEBUG_LOGS is 'true'
26
29
  */
27
30
  export function PublicPageContextChecker({ enabled = true, label = 'PublicPage' }: PublicPageContextCheckerProps) {
31
+ // Check if debug logging is enabled
32
+ // Allow in development mode with VITE_ENABLE_DEBUG_LOGS, or in test mode
33
+ // Also check for VITEST environment variable which is set by Vitest
34
+ const isDebugEnabled =
35
+ (import.meta.env.MODE === 'development' && import.meta.env.VITE_ENABLE_DEBUG_LOGS === 'true') ||
36
+ import.meta.env.MODE === 'test' ||
37
+ import.meta.env.VITEST === true ||
38
+ (typeof process !== 'undefined' && process.env.NODE_ENV === 'test');
39
+
40
+ // Early return if not in debug mode
41
+ if (!isDebugEnabled || !enabled) {
42
+ return null;
43
+ }
44
+
28
45
  useEffect(() => {
29
- if (!enabled) return;
30
46
 
31
- console.group(`🚨 [${label}] PUBLIC PAGE CONTEXT CHECK`);
47
+ logger.debug('PublicPageContextChecker', `🚨 [${label}] PUBLIC PAGE CONTEXT CHECK`);
32
48
 
33
49
  // Check for authentication context
34
50
  try {
35
51
  // This will throw if we're not in UnifiedAuthProvider
36
52
  const { isAuthenticated } = require('../../providers/UnifiedAuthProvider').useUnifiedAuth();
37
- console.error(`❌ [${label}] AUTHENTICATION CONTEXT DETECTED!`);
38
- console.error(`❌ [${label}] isAuthenticated:`, isAuthenticated);
39
- console.error(`❌ [${label}] This public page is inside UnifiedAuthProvider - THIS IS WRONG!`);
40
- console.error(`❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
53
+ logger.error('PublicPageContextChecker', `❌ [${label}] AUTHENTICATION CONTEXT DETECTED!`);
54
+ logger.error('PublicPageContextChecker', `❌ [${label}] isAuthenticated:`, isAuthenticated);
55
+ logger.error('PublicPageContextChecker', `❌ [${label}] This public page is inside UnifiedAuthProvider - THIS IS WRONG!`);
56
+ logger.error('PublicPageContextChecker', `❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
41
57
  } catch (error) {
42
- console.log(`✅ [${label}] No authentication context detected (GOOD!)`);
58
+ logger.debug('PublicPageContextChecker', `✅ [${label}] No authentication context detected (GOOD!)`);
43
59
  }
44
60
 
45
61
  // Check for organisation context
46
62
  try {
47
63
  // This will throw if we're not in OrganisationProvider
48
64
  const { selectedOrganisation } = require('../../providers/OrganisationProvider').useOrganisations();
49
- console.error(`❌ [${label}] ORGANISATION CONTEXT DETECTED!`);
50
- console.error(`❌ [${label}] selectedOrganisation:`, selectedOrganisation);
51
- console.error(`❌ [${label}] This public page is inside OrganisationProvider - THIS IS WRONG!`);
52
- console.error(`❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
65
+ logger.error('PublicPageContextChecker', `❌ [${label}] ORGANISATION CONTEXT DETECTED!`);
66
+ logger.error('PublicPageContextChecker', `❌ [${label}] selectedOrganisation:`, selectedOrganisation);
67
+ logger.error('PublicPageContextChecker', `❌ [${label}] This public page is inside OrganisationProvider - THIS IS WRONG!`);
68
+ logger.error('PublicPageContextChecker', `❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
53
69
  } catch (error) {
54
- console.log(`✅ [${label}] No organisation context detected (GOOD!)`);
70
+ logger.debug('PublicPageContextChecker', `✅ [${label}] No organisation context detected (GOOD!)`);
55
71
  }
56
72
 
57
73
  // Check for event context
58
74
  try {
59
75
  // This will throw if we're not in EventProvider
60
76
  const { events } = require('../../providers/EventProvider').useEvents();
61
- console.error(`❌ [${label}] EVENT CONTEXT DETECTED!`);
62
- console.error(`❌ [${label}] events:`, events);
63
- console.error(`❌ [${label}] This public page is inside EventProvider - THIS IS WRONG!`);
64
- console.error(`❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
77
+ logger.error('PublicPageContextChecker', `❌ [${label}] EVENT CONTEXT DETECTED!`);
78
+ logger.error('PublicPageContextChecker', `❌ [${label}] events:`, events);
79
+ logger.error('PublicPageContextChecker', `❌ [${label}] This public page is inside EventProvider - THIS IS WRONG!`);
80
+ logger.error('PublicPageContextChecker', `❌ [${label}] SOLUTION: Move public routes outside of authentication providers`);
65
81
  } catch (error) {
66
- console.log(`✅ [${label}] No event context detected (GOOD!)`);
82
+ logger.debug('PublicPageContextChecker', `✅ [${label}] No event context detected (GOOD!)`);
67
83
  }
68
84
 
69
85
  // Check for PublicPageProvider context
70
86
  try {
71
87
  const { isPublicPage } = usePublicPageContext();
72
88
  if (isPublicPage) {
73
- console.log(`✅ [${label}] Public page context detected (GOOD!)`);
89
+ logger.debug('PublicPageContextChecker', `✅ [${label}] Public page context detected (GOOD!)`);
74
90
  } else {
75
- console.warn(`⚠️ [${label}] Not in PublicPageProvider context`);
76
- console.warn(`⚠️ [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
91
+ logger.warn('PublicPageContextChecker', `⚠️ [${label}] Not in PublicPageProvider context`);
92
+ logger.warn('PublicPageContextChecker', `⚠️ [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
77
93
  }
78
94
  } catch (error) {
79
- console.warn(`⚠️ [${label}] Not in PublicPageProvider context`);
80
- console.warn(`⚠️ [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
95
+ logger.warn('PublicPageContextChecker', `⚠️ [${label}] Not in PublicPageProvider context`);
96
+ logger.warn('PublicPageContextChecker', `⚠️ [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
81
97
  }
82
98
 
83
- console.groupEnd();
84
-
85
99
  // Provide immediate guidance
86
- console.group(`📖 [${label}] IMMEDIATE ACTION REQUIRED`);
87
- console.log(`If you see any ❌ errors above, your public page is inside authentication context.`);
88
- console.log(`This will cause infinite loading loops and authentication errors.`);
89
- console.log(``);
90
- console.log(`🔧 SOLUTION:`);
91
- console.log(`1. Check your main App.tsx file`);
92
- console.log(`2. Make sure public routes are completely separate from authentication providers`);
93
- console.log(`3. Follow the architecture in: packages/core/docs/public-pages-guide.md`);
94
- console.log(``);
95
- console.log(`✅ CORRECT ARCHITECTURE:`);
96
- console.log(`<BrowserRouter>`);
97
- console.log(` <Routes>`);
98
- console.log(` <Route path="/events/*" element={<PublicPageApp />} />`);
99
- console.log(` <Route path="/*" element={<AuthenticatedApp />} />`);
100
- console.log(` </Routes>`);
101
- console.log(`</BrowserRouter>`);
102
- console.groupEnd();
100
+ logger.debug('PublicPageContextChecker', `📖 [${label}] IMMEDIATE ACTION REQUIRED`);
101
+ logger.debug('PublicPageContextChecker', `If you see any ❌ errors above, your public page is inside authentication context.`);
102
+ logger.debug('PublicPageContextChecker', `This will cause infinite loading loops and authentication errors.`);
103
+ logger.debug('PublicPageContextChecker', `🔧 SOLUTION: Check your main App.tsx file`);
104
+ logger.debug('PublicPageContextChecker', `Make sure public routes are completely separate from authentication providers`);
105
+ logger.debug('PublicPageContextChecker', `Follow the architecture in: packages/core/docs/public-pages-guide.md`);
103
106
 
104
107
  }, [enabled, label]);
105
108
 
106
- if (!enabled) return null;
107
-
108
109
  return (
109
110
  <div style={{
110
111
  position: 'fixed',
@@ -42,7 +42,7 @@
42
42
  */
43
43
 
44
44
  import React from 'react';
45
- import { cn } from '../../utils/cn';
45
+ import { cn } from '../../utils/core/cn';
46
46
  import type { Event } from '../../types/unified';
47
47
 
48
48
  export interface PublicPageFooterProps {
@@ -55,7 +55,7 @@ import type { Event } from '../../types/unified';
55
55
  import { FileDisplay } from '../FileDisplay/FileDisplay';
56
56
  import { FileCategory } from '../../types/file-reference';
57
57
  import { useAppConfig } from '../../hooks/useAppConfig';
58
- import { cn } from '../../utils/cn';
58
+ import { cn } from '../../utils/core/cn';
59
59
 
60
60
  export interface PublicPageHeaderProps {
61
61
  /** The event data for this public page */
@@ -145,20 +145,6 @@ export function PublicPageHeader({
145
145
  <>
146
146
  {customEventLogo || (
147
147
  <>
148
- {/* Log organisation_id derivation chain for debugging */}
149
- {(() => {
150
- console.log('[PublicPageHeader] Organisation ID Derivation Chain:', {
151
- eventCode: eventCode,
152
- eventId: event.event_id,
153
- eventName: event.event_name,
154
- organisationId: event.organisation_id,
155
- organisationIdType: typeof event.organisation_id,
156
- organisationIdValid: !!event.organisation_id && event.organisation_id !== '',
157
- derivation: 'URL → eventCode → usePublicEvent → event.organisation_id → FileDisplay',
158
- note: 'Organisation ID is derived from event data fetched using event code from URL'
159
- });
160
- return null;
161
- })()}
162
148
  <FileDisplay
163
149
  table_name="event"
164
150
  record_id={event.event_id}
@@ -38,6 +38,7 @@ import React, { createContext, useContext, ReactNode, useMemo } from 'react';
38
38
  import { createClient } from '@supabase/supabase-js';
39
39
  import type { Database } from '../../types/database';
40
40
  import { PublicErrorBoundary } from './PublicErrorBoundary';
41
+ import { logger } from '../../utils/core/logger';
41
42
 
42
43
  interface PublicPageContextType {
43
44
  isPublicPage: true;
@@ -93,11 +94,11 @@ export function PublicPageProvider({ children, appName }: PublicPageProviderProp
93
94
  // Create Supabase client if environment variables are available
94
95
  const supabase = useMemo(() => {
95
96
  if (!supabaseUrl || !supabaseKey) {
96
- console.warn('[PublicPageProvider] Missing Supabase environment variables. Please ensure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in your environment.');
97
+ logger.warn('PublicPageProvider', 'Missing Supabase environment variables. Please ensure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in your environment.');
97
98
  return null;
98
99
  }
99
100
  const client = createClient<Database>(supabaseUrl, supabaseKey);
100
- console.log('[PublicPageProvider] Supabase client created successfully for public pages');
101
+ logger.info('PublicPageProvider', 'Supabase client created successfully for public pages');
101
102
  return client;
102
103
  }, [supabaseUrl, supabaseKey]);
103
104
 
@@ -20,6 +20,8 @@ describe('PublicPageContextChecker', () => {
20
20
  const consoleErrorSpy = vi.spyOn(console, 'error');
21
21
 
22
22
  beforeEach(() => {
23
+ // Component now automatically detects test mode via process.env.NODE_ENV === 'test'
24
+ // No need to manually set environment variables
23
25
  vi.clearAllMocks();
24
26
  consoleGroupSpy.mockImplementation(() => {});
25
27
  consoleGroupEndSpy.mockImplementation(() => {});
@@ -12,7 +12,7 @@ import { PublicPageFooter } from '../PublicPageFooter';
12
12
  import type { Event } from '../../../types/unified';
13
13
 
14
14
  // Mock the cn utility
15
- vi.mock('../../../utils/cn', () => ({
15
+ vi.mock('../../../utils/core/cn', () => ({
16
16
  cn: vi.fn((...classes) => classes.filter(Boolean).join(' '))
17
17
  }));
18
18
 
@@ -21,8 +21,6 @@ export { PublicPageLayout, usePublicPageContext } from './PublicPageLayout';
21
21
  export { PublicPageHeader } from './PublicPageHeader';
22
22
  export { PublicPageProvider, usePublicPageContext as usePublicPageProviderContext, useIsPublicPage } from './PublicPageProvider';
23
23
  export { PublicPageFooter } from './PublicPageFooter';
24
- export { PublicPageDebugger } from './PublicPageDebugger';
25
- export { PublicPageDiagnostic } from './PublicPageDiagnostic';
26
24
  export { PublicPageContextChecker } from './PublicPageContextChecker';
27
25
 
28
26
 
@@ -40,6 +38,10 @@ export {
40
38
  PublicLoadingSkeleton
41
39
  } from './PublicLoadingSpinner';
42
40
 
41
+ // === EVENT LOGO COMPONENT ===
42
+ export { EventLogo, EventLogoCompact, EventLogoLarge } from './EventLogo';
43
+ export type { EventLogoProps } from './EventLogo';
44
+
43
45
  // === TYPES ===
44
46
  export type { PublicPageLayoutProps } from './PublicPageLayout';
45
47
  export type { PublicPageHeaderProps } from './PublicPageHeader';
@@ -42,7 +42,7 @@ vi.mock('../Button/Button', () => ({
42
42
  }));
43
43
 
44
44
  // Mock cn utility
45
- vi.mock('../../utils/cn', () => ({
45
+ vi.mock('../../utils/core/cn', () => ({
46
46
  cn: (...classes: any[]) => classes.filter(Boolean).join(' '),
47
47
  }));
48
48
 
@@ -15,7 +15,7 @@
15
15
  import * as React from "react";
16
16
  import { Search, X, ChevronDown, Check } from "lucide-react";
17
17
  import { Button, type ButtonProps } from "../Button/Button";
18
- import { cn } from "../../utils/cn";
18
+ import { cn } from "../../utils/core/cn";
19
19
  import {
20
20
  useSelectState,
21
21
  useSelectEvents,
@@ -33,11 +33,13 @@ export interface SelectContextValue extends SelectState {
33
33
  actions: SelectActions;
34
34
  registerItem?: (value: string, text: string) => void;
35
35
  unregisterItem?: (value: string) => void;
36
+ direction?: 'up' | 'down';
36
37
  }
37
38
 
38
39
  export interface SelectProps extends Omit<React.HTMLAttributes<HTMLFormElement>, 'onChange' | 'onKeyDown' | 'onFocus' | 'onBlur'> {
39
40
  children: React.ReactNode;
40
41
  className?: string;
42
+ direction?: 'up' | 'down';
41
43
  // State props are in UseSelectStateProps (via & intersection)
42
44
  }
43
45
 
@@ -168,6 +170,7 @@ export const Select = React.forwardRef<HTMLFormElement, SelectProps & UseSelectS
168
170
  ({
169
171
  children,
170
172
  className,
173
+ direction = 'down',
171
174
  ...selectProps
172
175
  }, ref) => {
173
176
  const internalRef = React.useRef<HTMLFormElement>(null);
@@ -317,7 +320,8 @@ export const Select = React.forwardRef<HTMLFormElement, SelectProps & UseSelectS
317
320
  actions,
318
321
  registerItem,
319
322
  unregisterItem,
320
- }), [state, actions, registerItem, unregisterItem]);
323
+ direction,
324
+ }), [state, actions, registerItem, unregisterItem, direction]);
321
325
 
322
326
  return (
323
327
  <form
@@ -341,7 +345,8 @@ Select.displayName = "Select";
341
345
 
342
346
  export const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
343
347
  ({ children, className, variant = "outline", size = "default", asChild = false, ...props }, ref) => {
344
- const { open, disabled, value, actions } = useSelectContext();
348
+ const { open, disabled, value, actions, direction = 'down' } = useSelectContext();
349
+ const opensUpward = direction === 'up';
345
350
 
346
351
  const handleClick = () => {
347
352
  actions.setOpen(!open);
@@ -377,7 +382,8 @@ export const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerPr
377
382
  className: cn(
378
383
  "!justify-between relative w-full",
379
384
  "[&_svg]:pointer-events-none",
380
- open && "!rounded-b-none !border-b-0",
385
+ open && !opensUpward && "!rounded-b-none !border-b-0",
386
+ open && opensUpward && "!rounded-t-none !border-t-0",
381
387
  className
382
388
  ),
383
389
  style: {
@@ -438,7 +444,8 @@ export const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerPr
438
444
  className={cn(
439
445
  "!justify-between relative w-full",
440
446
  "[&_svg]:pointer-events-none",
441
- open && "!rounded-b-none !border-b-0",
447
+ open && !opensUpward && "!rounded-b-none !border-b-0",
448
+ open && opensUpward && "!rounded-t-none !border-t-0",
442
449
  className
443
450
  )}
444
451
  style={{
@@ -493,10 +500,10 @@ export const SelectContent = React.forwardRef<HTMLUListElement, SelectContentPro
493
500
  className,
494
501
  searchable = false,
495
502
  searchPlaceholder = "Search...",
496
- maxHeight = "20rem",
503
+ maxHeight = "max(20rem, 50vh)",
497
504
  style
498
505
  }, ref) => {
499
- const { open, actions } = useSelectContext();
506
+ const { open, actions, direction = 'down' } = useSelectContext();
500
507
  const { searchTerm, setSearchTerm, filteredChildren, searchInputRef } = useSelectSearch({
501
508
  children,
502
509
  searchable,
@@ -525,16 +532,21 @@ export const SelectContent = React.forwardRef<HTMLUListElement, SelectContentPro
525
532
  );
526
533
  }
527
534
 
535
+ const opensUpward = direction === 'up';
536
+
528
537
  return (
529
538
  <ul
530
539
  ref={ref}
531
540
  className={cn(
532
- "absolute z-[99999] w-full overflow-y-auto rounded-b-md border border-t-0 border-main-300 bg-main-50 shadow-lg",
541
+ "absolute z-[99999] w-full overflow-y-auto border border-main-300 bg-main-50 shadow-lg",
533
542
  "list-none p-0 m-0",
543
+ opensUpward
544
+ ? "rounded-t-md border-b-0"
545
+ : "rounded-b-md border-t-0",
534
546
  className
535
547
  )}
536
548
  style={{
537
- top: '100%',
549
+ [opensUpward ? 'bottom' : 'top']: '100%',
538
550
  left: 0,
539
551
  right: 0,
540
552
  maxHeight,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file SessionRestorationLoader Component
3
3
  * @package @jmruthers/pace-core
4
- * @module Components
4
+ * @module Components/SessionRestorationLoader
5
5
  * @since 0.1.0
6
6
  *
7
7
  * Displays a consistent loading state while the authentication service
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import React from 'react';
12
- import { LoadingSpinner } from './LoadingSpinner/LoadingSpinner';
12
+ import { LoadingSpinner } from '../LoadingSpinner/LoadingSpinner';
13
13
 
14
14
  export interface SessionRestorationLoaderProps {
15
15
  /** Customise the status message displayed under the spinner */
@@ -46,3 +46,4 @@ export const SessionRestorationLoader: React.FC<SessionRestorationLoaderProps> =
46
46
  </div>
47
47
  );
48
48
  };
49
+
@@ -0,0 +1,3 @@
1
+ export { SessionRestorationLoader } from './SessionRestorationLoader';
2
+ export type { SessionRestorationLoaderProps } from './SessionRestorationLoader';
3
+
@@ -69,7 +69,7 @@
69
69
 
70
70
  import * as React from "react";
71
71
  import * as SwitchPrimitive from "@radix-ui/react-switch";
72
- import { cn } from "../../utils/cn";
72
+ import { cn } from "../../utils/core/cn";
73
73
 
74
74
  /**
75
75
  * Switch component props
@@ -91,7 +91,7 @@
91
91
 
92
92
  import * as React from "react"
93
93
 
94
- import { cn } from "../../utils/cn"
94
+ import { cn } from "../../utils/core/cn"
95
95
 
96
96
  /**
97
97
  * Table component
@@ -20,7 +20,7 @@ import {
20
20
  } from '../Table';
21
21
 
22
22
  // Mock the cn utility
23
- vi.mock('../../../utils/cn', () => ({
23
+ vi.mock('../../../utils/core/cn', () => ({
24
24
  cn: vi.fn((...classes) => classes.filter(Boolean).join(' '))
25
25
  }));
26
26
 
@@ -88,7 +88,7 @@
88
88
  import * as React from "react"
89
89
  import * as ToastPrimitives from "@radix-ui/react-toast"
90
90
  import { X } from "lucide-react"
91
- import { cn } from "../../utils/cn"
91
+ import { cn } from "../../utils/core/cn"
92
92
  import { useToast } from "../../hooks/useToast"
93
93
 
94
94
  const ToastProvider = ToastPrimitives.Provider
@@ -73,7 +73,7 @@
73
73
 
74
74
  import * as React from "react";
75
75
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
76
- import { cn } from "../../utils/cn";
76
+ import { cn } from "../../utils/core/cn";
77
77
 
78
78
  const TooltipProvider = TooltipPrimitive.Provider;
79
79
 
@@ -49,6 +49,9 @@ export type { LabelProps } from './Label';
49
49
  export { Alert, AlertTitle, AlertDescription } from './Alert';
50
50
  export { Avatar, AvatarImage, AvatarFallback } from './Avatar';
51
51
 
52
+ export { Badge } from './Badge';
53
+ export type { BadgeProps, BadgeVariant } from './Badge';
54
+
52
55
  export { Checkbox } from './Checkbox';
53
56
  export { Switch } from './Switch';
54
57
  export type { SwitchProps } from './Switch';
@@ -151,17 +154,11 @@ export type { DataRecord } from './DataTable/types';
151
154
 
152
155
  export {
153
156
  Form,
154
- FormField,
155
- FormErrorSummary,
156
- FormLiveRegion,
157
- FormFieldset
157
+ FormField
158
158
  } from './Form';
159
159
  export type {
160
160
  FormProps,
161
- FormFieldProps,
162
- FormErrorSummaryProps,
163
- FormLiveRegionProps,
164
- FormFieldsetProps
161
+ FormFieldProps
165
162
  } from './Form';
166
163
 
167
164
  // LoginForm - ensure it's exported
@@ -212,6 +209,7 @@ export { ErrorBoundary } from './ErrorBoundary';
212
209
  export type { ErrorBoundaryProps, ErrorBoundaryState } from './ErrorBoundary';
213
210
  export { LoadingSpinner } from './LoadingSpinner';
214
211
  export { SessionRestorationLoader } from './SessionRestorationLoader';
212
+ export type { SessionRestorationLoaderProps } from './SessionRestorationLoader';
215
213
 
216
214
  // ============================================================================
217
215
  // EVENT MANAGEMENT
@@ -223,8 +221,7 @@ export { EventSelector } from './EventSelector';
223
221
  // AUTHENTICATION FORMS
224
222
  // ============================================================================
225
223
 
226
- // Password Component exports
227
- export { PasswordResetForm } from './PasswordReset';
224
+ // Password Component exports (PasswordResetForm removed - unused)
228
225
 
229
226
  // ============================================================================
230
227
  // STORAGE COMPONENTS