@jmruthers/pace-core 0.5.134 → 0.5.136

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 (522) hide show
  1. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  2. package/dist/{DataTable-A36PJG6N.js → DataTable-CYOHOX3O.js} +25 -13
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-801uofbR.d.ts} +51 -135
  4. package/dist/UnifiedAuthProvider-5E5TUNMS.js +17 -0
  5. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  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-CTJRBUX2.js → chunk-2TWNJ46Y.js} +2 -2
  9. package/dist/{chunk-UJI6WSMD.js → chunk-444EZN6N.js} +3 -3
  10. package/dist/chunk-444EZN6N.js.map +1 -0
  11. package/dist/{chunk-3CG5L6RN.js → chunk-4MT5BGGL.js} +90 -73
  12. package/dist/chunk-4MT5BGGL.js.map +1 -0
  13. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  14. package/dist/chunk-56XJ3TU6.js.map +1 -0
  15. package/dist/chunk-5DPZ5EAT.js +60 -0
  16. package/dist/chunk-5DPZ5EAT.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-APIBCTL2.js +670 -0
  20. package/dist/chunk-APIBCTL2.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-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  24. package/dist/chunk-BVYWGZVV.js.map +1 -0
  25. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  26. package/dist/chunk-ERISIBYU.js.map +1 -0
  27. package/dist/{chunk-CQZU6TFE.js → chunk-FHWWBIHA.js} +100 -62
  28. package/dist/chunk-FHWWBIHA.js.map +1 -0
  29. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  30. package/dist/chunk-FMUCXFII.js.map +1 -0
  31. package/dist/{chunk-GVDR7WNV.js → chunk-HJGGOMQ6.js} +194 -518
  32. package/dist/chunk-HJGGOMQ6.js.map +1 -0
  33. package/dist/{chunk-BDZUMRBD.js → chunk-K2WWTH7O.js} +13 -6
  34. package/dist/chunk-K2WWTH7O.js.map +1 -0
  35. package/dist/{chunk-BYXRHAIF.js → chunk-L6PGMCMD.js} +23 -14
  36. package/dist/chunk-L6PGMCMD.js.map +1 -0
  37. package/dist/chunk-LMC26NLJ.js +84 -0
  38. package/dist/chunk-LMC26NLJ.js.map +1 -0
  39. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  40. package/dist/chunk-LS353YLY.js.map +1 -0
  41. package/dist/{chunk-ZYZCRSBD.js → chunk-LTV3XIJJ.js} +16 -11
  42. package/dist/chunk-LTV3XIJJ.js.map +1 -0
  43. package/dist/{chunk-HMNOSGVA.js → chunk-NOHEVYVX.js} +377 -666
  44. package/dist/chunk-NOHEVYVX.js.map +1 -0
  45. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  46. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  47. package/dist/chunk-S5OFRT4M.js +94 -0
  48. package/dist/chunk-S5OFRT4M.js.map +1 -0
  49. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  50. package/dist/chunk-SBVILCCA.js.map +1 -0
  51. package/dist/{chunk-TGIY2AR2.js → chunk-SL2YQDR6.js} +4 -3
  52. package/dist/{chunk-TGIY2AR2.js.map → chunk-SL2YQDR6.js.map} +1 -1
  53. package/dist/{chunk-VZ5OR6HD.js → chunk-TVYPTYOY.js} +55 -179
  54. package/dist/chunk-TVYPTYOY.js.map +1 -0
  55. package/dist/{chunk-ZV77RZMU.js → chunk-XARJS7CD.js} +2 -2
  56. package/dist/chunk-XDNLUEXI.js +138 -0
  57. package/dist/chunk-XDNLUEXI.js.map +1 -0
  58. package/dist/{chunk-F64FFPOZ.js → chunk-YLKIDTUK.js} +26 -20
  59. package/dist/chunk-YLKIDTUK.js.map +1 -0
  60. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  61. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  62. package/dist/components.d.ts +7 -287
  63. package/dist/components.js +26 -157
  64. package/dist/components.js.map +1 -1
  65. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  66. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  67. package/dist/hooks.d.ts +3 -3
  68. package/dist/hooks.js +22 -16
  69. package/dist/hooks.js.map +1 -1
  70. package/dist/index.d.ts +219 -9
  71. package/dist/index.js +49 -31
  72. package/dist/index.js.map +1 -1
  73. package/dist/providers.d.ts +1 -1
  74. package/dist/providers.js +5 -4
  75. package/dist/rbac/index.js +13 -12
  76. package/dist/styles/index.js +2 -1
  77. package/dist/theming/runtime.d.ts +2 -19
  78. package/dist/theming/runtime.js +2 -1
  79. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  80. package/dist/types.d.ts +2 -2
  81. package/dist/types.js +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 +195 -232
  85. package/dist/utils.js +173 -331
  86. package/dist/utils.js.map +1 -1
  87. package/dist/{validation-DnhrNMju.d.ts → validation-8npbysjg.d.ts} +26 -8
  88. package/dist/validation.d.ts +261 -10
  89. package/dist/validation.js +82 -440
  90. package/dist/validation.js.map +1 -1
  91. package/docs/api/classes/ColumnFactory.md +1 -1
  92. package/docs/api/classes/ErrorBoundary.md +6 -6
  93. package/docs/api/classes/InvalidScopeError.md +1 -1
  94. package/docs/api/classes/MissingUserContextError.md +1 -1
  95. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  96. package/docs/api/classes/PermissionDeniedError.md +1 -1
  97. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  98. package/docs/api/classes/RBACAuditManager.md +6 -6
  99. package/docs/api/classes/RBACCache.md +1 -1
  100. package/docs/api/classes/RBACEngine.md +7 -7
  101. package/docs/api/classes/RBACError.md +1 -1
  102. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  103. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  104. package/docs/api/classes/StorageUtils.md +1 -1
  105. package/docs/api/enums/FileCategory.md +1 -1
  106. package/docs/api/interfaces/AggregateConfig.md +4 -4
  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 +3 -3
  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 +90 -0
  122. package/docs/api/interfaces/ExportOptions.md +126 -0
  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 +648 -212
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -2
  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/examples/README.md +30 -14
  205. package/examples/STRUCTURE.md +125 -0
  206. package/examples/components/DataTable/HierarchicalActionsExample.tsx +421 -0
  207. package/examples/components/DataTable/HierarchicalExample.tsx +475 -0
  208. package/examples/components/DataTable/InitialPageSizeExample.tsx +177 -0
  209. package/examples/components/DataTable/PerformanceExample.tsx +506 -0
  210. package/examples/components/DataTable/index.ts +13 -0
  211. package/examples/components/Dialog/BasicHtmlTest.tsx +55 -0
  212. package/examples/components/Dialog/DebugHtmlExample.tsx +68 -0
  213. package/examples/components/Dialog/HtmlDialogExample.tsx +202 -0
  214. package/examples/components/Dialog/ScrollableDialogExample.tsx +290 -0
  215. package/examples/components/Dialog/SimpleHtmlTest.tsx +61 -0
  216. package/examples/components/Dialog/SmartDialogExample.tsx +322 -0
  217. package/examples/components/Dialog/index.ts +15 -0
  218. package/examples/components/index.ts +11 -0
  219. package/examples/features/index.ts +12 -0
  220. package/examples/{public-pages → features/public-pages}/CorrectPublicPageImplementation.tsx +1 -1
  221. package/examples/{public-pages → features/public-pages}/PublicEventPage.tsx +1 -1
  222. package/examples/{public-pages → features/public-pages}/PublicPageApp.tsx +1 -1
  223. package/examples/{public-pages → features/public-pages}/PublicPageUsageExample.tsx +1 -1
  224. package/examples/index.ts +11 -3
  225. package/package.json +30 -10
  226. package/src/components/Alert/Alert.tsx +1 -1
  227. package/src/components/Avatar/Avatar.tsx +1 -1
  228. package/src/components/Button/Button.tsx +1 -1
  229. package/src/components/Card/Card.tsx +1 -1
  230. package/src/components/Checkbox/Checkbox.tsx +1 -1
  231. package/src/components/DataTable/DataTable.test.tsx +1 -1
  232. package/src/components/DataTable/DataTable.tsx +1 -30
  233. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  234. package/src/components/DataTable/__tests__/styles.test.ts +2 -2
  235. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  236. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  237. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  238. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  239. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  240. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  241. package/src/components/DataTable/components/PaginationControls.tsx +1 -1
  242. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  243. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  244. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  245. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  246. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  247. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  248. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  249. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  250. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  251. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  252. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  253. package/src/components/DataTable/index.ts +4 -0
  254. package/src/components/DataTable/styles.ts +1 -1
  255. package/src/components/DataTable/types.ts +13 -0
  256. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  257. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  258. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  259. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  260. package/src/components/DataTable/utils/index.ts +1 -0
  261. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  262. package/src/components/Dialog/Dialog.tsx +2 -2
  263. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  264. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  265. package/src/components/EventSelector/EventSelector.tsx +3 -2
  266. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  267. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  268. package/src/components/FileUpload/FileUpload.tsx +2 -2
  269. package/src/components/Footer/Footer.tsx +1 -1
  270. package/src/components/Form/Form.test.tsx +4 -509
  271. package/src/components/Form/Form.tsx +1 -1
  272. package/src/components/Form/FormField.tsx +1 -1
  273. package/src/components/Form/index.ts +0 -12
  274. package/src/components/Header/Header.tsx +1 -1
  275. package/src/components/Input/Input.tsx +1 -1
  276. package/src/components/Label/Label.tsx +1 -1
  277. package/src/components/LoginForm/LoginForm.tsx +1 -1
  278. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  279. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  280. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  281. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  282. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  283. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  284. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  285. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  286. package/src/components/PaceLoginPage/PaceLoginPage.tsx +13 -12
  287. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  288. package/src/components/PasswordReset/index.ts +0 -2
  289. package/src/components/Progress/Progress.tsx +1 -1
  290. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  291. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  292. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  293. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  294. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  295. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  296. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  297. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  298. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  299. package/src/components/PublicLayout/index.ts +4 -2
  300. package/src/components/Select/Select.tsx +1 -1
  301. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  302. package/src/components/SessionRestorationLoader/index.ts +3 -0
  303. package/src/components/Switch/Switch.tsx +1 -1
  304. package/src/components/Table/Table.tsx +1 -1
  305. package/src/components/Toast/Toast.tsx +1 -1
  306. package/src/components/Tooltip/Tooltip.tsx +1 -1
  307. package/src/components/index.ts +4 -10
  308. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  309. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  310. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  311. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  312. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  313. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  314. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  315. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  316. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  317. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  318. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  319. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  320. package/src/hooks/public/usePublicEvent.ts +7 -6
  321. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  322. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  323. package/src/hooks/useComponentPerformance.ts +4 -1
  324. package/src/hooks/useDataTablePerformance.ts +4 -3
  325. package/src/hooks/useEventTheme.test.ts +18 -5
  326. package/src/hooks/useEventTheme.ts +4 -1
  327. package/src/hooks/useEvents.ts +2 -0
  328. package/src/hooks/useFileDisplay.ts +9 -8
  329. package/src/hooks/useFileReference.ts +4 -1
  330. package/src/hooks/useFileUrl.ts +4 -1
  331. package/src/hooks/useInactivityTracker.ts +5 -4
  332. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  333. package/src/hooks/useOrganisationSecurity.ts +8 -7
  334. package/src/hooks/usePerformanceMonitor.ts +6 -3
  335. package/src/hooks/usePermissionCache.ts +13 -6
  336. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  337. package/src/hooks/useSecureDataAccess.ts +9 -8
  338. package/src/hooks/useSessionRestoration.ts +4 -1
  339. package/src/hooks/useStorage.ts +4 -1
  340. package/src/index.ts +25 -8
  341. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  342. package/src/providers/services/EventServiceProvider.tsx +2 -1
  343. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  344. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  345. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  346. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  347. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  348. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  349. package/src/rbac/api.ts +5 -2
  350. package/src/rbac/audit-enhanced.ts +6 -6
  351. package/src/rbac/audit.test.ts +60 -38
  352. package/src/rbac/audit.ts +8 -8
  353. package/src/rbac/cache-invalidation.ts +7 -4
  354. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  355. package/src/rbac/components/NavigationGuard.tsx +7 -3
  356. package/src/rbac/components/NavigationProvider.tsx +6 -3
  357. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  358. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  359. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  360. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  361. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  362. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  363. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  364. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  365. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  366. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  367. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  368. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  369. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  370. package/src/rbac/engine.ts +15 -7
  371. package/src/rbac/hooks/usePermissions.ts +7 -3
  372. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  373. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  374. package/src/rbac/permissions.ts +5 -2
  375. package/src/rbac/security.test.ts +27 -16
  376. package/src/rbac/security.ts +5 -4
  377. package/src/services/AuthService.ts +22 -21
  378. package/src/services/EventService.ts +12 -12
  379. package/src/services/InactivityService.ts +5 -4
  380. package/src/services/OrganisationService.ts +26 -25
  381. package/src/services/__tests__/AuthService.test.ts +51 -19
  382. package/src/services/__tests__/EventService.test.ts +37 -5
  383. package/src/services/__tests__/InactivityService.test.ts +38 -4
  384. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  385. package/src/services/base/BaseService.ts +3 -1
  386. package/src/theming/__tests__/runtime.test.ts +21 -12
  387. package/src/theming/parseEventColours.ts +5 -19
  388. package/src/theming/runtime.ts +8 -4
  389. package/src/types/validation.ts +2 -29
  390. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  391. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  392. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  393. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  394. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  395. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  396. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  397. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  398. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  399. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  400. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  401. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  402. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  403. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  404. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  405. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  406. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  407. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  408. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  409. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  410. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  411. package/src/utils/__tests__/security.unit.test.ts +40 -18
  412. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  413. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  414. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  415. package/src/utils/{appIdResolver.test.ts → app/appIdResolver.test.ts} +28 -30
  416. package/src/utils/{appIdResolver.ts → app/appIdResolver.ts} +8 -5
  417. package/src/utils/{appNameResolver.test.ts → app/appNameResolver.test.ts} +1 -1
  418. package/src/utils/{appNameResolver.ts → app/appNameResolver.ts} +5 -1
  419. package/src/utils/{organisationContext.ts → context/organisationContext.ts} +6 -3
  420. package/src/utils/{sessionTracking.ts → context/sessionTracking.ts} +11 -12
  421. package/src/utils/{logger.ts → core/logger.ts} +4 -2
  422. package/src/utils/{deviceFingerprint.ts → device/deviceFingerprint.ts} +1 -1
  423. package/src/utils/{lazyLoad.tsx → dynamic/lazyLoad.tsx} +2 -2
  424. package/src/utils/{file-reference.test.ts → file-reference/__tests__/file-reference.test.ts} +5 -5
  425. package/src/utils/{file-reference.ts → file-reference/index.ts} +20 -38
  426. package/src/utils/index.ts +32 -54
  427. package/src/utils/{secureErrors.ts → security/secureErrors.ts} +6 -3
  428. package/src/utils/{security.ts → security/security.ts} +5 -2
  429. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  430. package/src/utils/storage/helpers.ts +15 -8
  431. package/src/{components/Dialog/utils/__tests__/safeHtml.unit.test.ts → utils/validation/__tests__/htmlSanitization.unit.test.ts} +9 -15
  432. package/src/{validation → utils/validation}/csrf.ts +1 -1
  433. package/src/{components/Dialog/utils/safeHtml.ts → utils/validation/htmlSanitization.ts} +9 -10
  434. package/src/utils/validation/index.ts +79 -0
  435. package/src/utils/{sanitization.ts → validation/sanitization.ts} +71 -2
  436. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  437. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  438. package/src/utils/{validationUtils.ts → validation/validationUtils.ts} +4 -1
  439. package/src/validation/index.ts +3 -34
  440. package/dist/UnifiedAuthProvider-CQDZRJIS.js +0 -16
  441. package/dist/chunk-24MKLB7U.js +0 -81
  442. package/dist/chunk-24MKLB7U.js.map +0 -1
  443. package/dist/chunk-3CG5L6RN.js.map +0 -1
  444. package/dist/chunk-3DBFLLLU.js.map +0 -1
  445. package/dist/chunk-5F3NDPJV.js.map +0 -1
  446. package/dist/chunk-66C4BSAY.js.map +0 -1
  447. package/dist/chunk-BDZUMRBD.js.map +0 -1
  448. package/dist/chunk-BYXRHAIF.js.map +0 -1
  449. package/dist/chunk-CDQ3PX7L.js +0 -18
  450. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  451. package/dist/chunk-CQZU6TFE.js.map +0 -1
  452. package/dist/chunk-F64FFPOZ.js.map +0 -1
  453. package/dist/chunk-GEVIB2UB.js.map +0 -1
  454. package/dist/chunk-GKHF54DI.js.map +0 -1
  455. package/dist/chunk-GVDR7WNV.js.map +0 -1
  456. package/dist/chunk-HMNOSGVA.js.map +0 -1
  457. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  458. package/dist/chunk-M6DDYFUD.js.map +0 -1
  459. package/dist/chunk-O3NWNXDY.js.map +0 -1
  460. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  461. package/dist/chunk-UJI6WSMD.js.map +0 -1
  462. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  463. package/dist/chunk-WP5I5GLN.js.map +0 -1
  464. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  465. package/src/components/Dialog/README.md +0 -804
  466. package/src/components/Form/FormErrorSummary.tsx +0 -113
  467. package/src/components/Form/FormFieldset.tsx +0 -127
  468. package/src/components/Form/FormLiveRegion.tsx +0 -198
  469. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  470. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  471. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  472. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  473. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  474. package/src/examples/CorrectPublicPageImplementation.tsx +0 -304
  475. package/src/examples/PublicEventPage.tsx +0 -287
  476. package/src/examples/PublicPageApp.tsx +0 -321
  477. package/src/examples/PublicPageUsageExample.tsx +0 -218
  478. package/src/utils/schemaUtils.ts +0 -37
  479. package/src/validation/__tests__/common.unit.test.ts +0 -101
  480. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  481. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  482. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  483. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  484. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  485. package/src/validation/__tests__/user.unit.test.ts +0 -440
  486. package/src/validation/sanitization.ts +0 -96
  487. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-CYOHOX3O.js.map} +0 -0
  488. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-5E5TUNMS.js.map} +0 -0
  489. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  490. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  491. /package/dist/{chunk-CTJRBUX2.js.map → chunk-2TWNJ46Y.js.map} +0 -0
  492. /package/dist/{chunk-ZV77RZMU.js.map → chunk-XARJS7CD.js.map} +0 -0
  493. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  494. /package/examples/{public-pages → features/public-pages}/index.ts +0 -0
  495. /package/examples/{RBAC → features/rbac}/CompleteRBACExample.tsx +0 -0
  496. /package/examples/{RBAC → features/rbac}/EventBasedApp.tsx +0 -0
  497. /package/examples/{RBAC → features/rbac}/PermissionExample.tsx +0 -0
  498. /package/examples/{RBAC → features/rbac}/index.ts +0 -0
  499. /package/src/utils/{appConfig.ts → app/appConfig.ts} +0 -0
  500. /package/src/utils/{appNameResolver.simple.test.ts → app/appNameResolver.simple.test.ts} +0 -0
  501. /package/src/utils/{audit.ts → audit/audit.ts} +0 -0
  502. /package/src/utils/{organisationContext.test.ts → context/organisationContext.test.ts} +0 -0
  503. /package/src/utils/{cn.ts → core/cn.ts} +0 -0
  504. /package/src/utils/{debugLogger.ts → core/debugLogger.ts} +0 -0
  505. /package/src/utils/{dynamicUtils.ts → dynamic/dynamicUtils.ts} +0 -0
  506. /package/src/utils/{formatDate.test.ts → formatting/formatDate.test.ts} +0 -0
  507. /package/src/utils/{formatting.ts → formatting/formatting.ts} +0 -0
  508. /package/src/utils/{bundleAnalysis.ts → performance/bundleAnalysis.ts} +0 -0
  509. /package/src/utils/{performanceBenchmark.ts → performance/performanceBenchmark.ts} +0 -0
  510. /package/src/utils/{performanceBudgets.ts → performance/performanceBudgets.ts} +0 -0
  511. /package/src/utils/{permissionTypes.ts → permissions/permissionTypes.ts} +0 -0
  512. /package/src/utils/{permissionUtils.test.ts → permissions/permissionUtils.test.ts} +0 -0
  513. /package/src/utils/{permissionUtils.ts → permissions/permissionUtils.ts} +0 -0
  514. /package/src/utils/{auth-utils.ts → security/auth-utils.ts} +0 -0
  515. /package/src/utils/{secureDataAccess.test.ts → security/secureDataAccess.test.ts} +0 -0
  516. /package/src/utils/{secureDataAccess.ts → security/secureDataAccess.ts} +0 -0
  517. /package/src/utils/{secureStorage.ts → security/secureStorage.ts} +0 -0
  518. /package/src/utils/{securityMonitor.ts → security/securityMonitor.ts} +0 -0
  519. /package/src/{validation → utils/validation}/common.ts +0 -0
  520. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  521. /package/src/{validation → utils/validation}/user.ts +0 -0
  522. /package/src/utils/{validation.ts → validation/validation.ts} +0 -0
@@ -1,321 +0,0 @@
1
- /**
2
- * @file Public Page App Example
3
- * @package @jmruthers/pace-core
4
- * @module Examples/PublicPages
5
- * @since 1.0.0
6
- *
7
- * A complete example showing how to properly implement public pages
8
- * that are completely isolated from the authentication context.
9
- *
10
- * This example demonstrates the correct architecture for public pages:
11
- * 1. Separate routing structure outside authentication context
12
- * 2. PublicPageProvider for environment variables
13
- * 3. No authentication context initialization
14
- * 4. Proper error handling and loading states
15
- *
16
- * @example
17
- * ```tsx
18
- * import { PublicPageApp } from '@jmruthers/pace-core/examples';
19
- *
20
- * // In your main App.tsx, use this for public routes
21
- * function App() {
22
- * return (
23
- * <BrowserRouter>
24
- * <Routes>
25
- * <Route path="/public/*" element={<PublicPageApp />} />
26
- * <Route path="/*" element={<AuthenticatedApp />} />
27
- * </Routes>
28
- * </BrowserRouter>
29
- * );
30
- * }
31
- * ```
32
- */
33
-
34
- import React from 'react';
35
- import { Routes, Route } from 'react-router-dom';
36
- import {
37
- PublicPageProvider,
38
- PublicPageLayout,
39
- PublicPageHeader,
40
- PublicPageFooter,
41
- FileDisplay,
42
- usePublicEvent,
43
- usePublicRouteParams,
44
- PublicLoadingSpinner,
45
- PublicErrorBoundary
46
- } from '../index';
47
- import { FileCategory } from '../types/file-reference';
48
-
49
- /**
50
- * Complete public page application that works independently
51
- * of the main application's authentication context.
52
- *
53
- * This component should be used for all public routes that don't
54
- * require authentication, such as:
55
- * - Event pages: /events/:eventCode/recipe-grid-report
56
- * - Public reports: /reports/:reportId
57
- * - Public information: /info/:pageId
58
- */
59
- export function PublicPageApp() {
60
- return (
61
- <PublicPageProvider>
62
- <Routes>
63
- {/* Public event pages */}
64
- <Route path="/events/:eventCode/recipe-grid-report" element={<PublicRecipeGridReportPage />} />
65
- <Route path="/events/:eventCode" element={<PublicEventPage />} />
66
-
67
- {/* Add more public routes as needed */}
68
- <Route path="/info/:pageId" element={<PublicInfoPage />} />
69
- <Route path="/reports/:reportId" element={<PublicReportPage />} />
70
- </Routes>
71
- </PublicPageProvider>
72
- );
73
- }
74
-
75
- /**
76
- * Public recipe grid report page
77
- *
78
- * This is the specific page mentioned in the bug report.
79
- * It demonstrates the correct usage pattern for public pages.
80
- */
81
- function PublicRecipeGridReportPage() {
82
- // Step 1: Extract event code from URL (no auth context triggered)
83
- const { eventCode } = usePublicRouteParams({ fetchEventData: false });
84
-
85
- // Step 2: Fetch event data using the event code
86
- const { event, isLoading, error, refetch } = usePublicEvent(eventCode || '');
87
-
88
- // Step 3: Handle loading state
89
- if (isLoading) {
90
- return (
91
- <PublicLoadingSpinner
92
- message="Loading recipe grid report..."
93
- />
94
- );
95
- }
96
-
97
- // Step 4: Handle error state
98
- if (error) {
99
- return (
100
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
101
- <div className="max-w-md mx-auto text-center px-4">
102
- <div className="mb-6">
103
- <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-acc-100 mb-4">
104
- <svg className="h-6 w-6 text-acc-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
105
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
106
- </svg>
107
- </div>
108
- <h1 className="text-2xl font-bold text-sec-900 mb-2">
109
- Recipe Grid Report Not Found
110
- </h1>
111
- <p className="text-sec-600 mb-6">
112
- The event code "{eventCode}" is invalid or the recipe grid report is not available for public viewing.
113
- </p>
114
- <button
115
- onClick={refetch}
116
- className="px-4 py-2 bg-main-600 text-main-50 rounded-md hover:bg-main-700 transition-colors"
117
- >
118
- Try Again
119
- </button>
120
- </div>
121
- </div>
122
- </div>
123
- );
124
- }
125
-
126
- // Step 5: Handle missing event
127
- if (!event) {
128
- return (
129
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
130
- <div className="max-w-md mx-auto text-center px-4">
131
- <h1 className="text-2xl font-bold text-sec-900 mb-4">
132
- Recipe Grid Report Not Available
133
- </h1>
134
- <p className="text-sec-600 mb-6">
135
- This recipe grid report is not available for public viewing.
136
- </p>
137
- <button
138
- onClick={refetch}
139
- className="px-4 py-2 bg-main-600 text-main-50 rounded-md hover:bg-main-700 transition-colors"
140
- >
141
- Try Again
142
- </button>
143
- </div>
144
- </div>
145
- );
146
- }
147
-
148
- // Step 6: Render the public page with event data
149
- return (
150
- <PublicPageLayout eventCode={eventCode || ''} event={event}>
151
- <PublicPageHeader
152
- event={event}
153
- eventCode={eventCode || ''}
154
- title="Recipe Grid Report"
155
- description="Public recipe grid report for this event"
156
- />
157
-
158
- <main className="max-w-6xl mx-auto px-4 py-8">
159
- {/* Recipe Grid Report Content */}
160
- <div className="mb-12">
161
- <div className="bg-main-50 border border-main-200 rounded-lg p-6">
162
- <h3 className="font-semibold text-main-900 mb-2">Recipe Grid Report</h3>
163
- <p className="text-main-800">
164
- This is where your recipe grid report content would go.
165
- The public page is now working correctly without authentication context conflicts.
166
- </p>
167
- <div className="mt-4 text-sm text-main-700">
168
- <p><strong>Event Code:</strong> {eventCode}</p>
169
- <p><strong>Event ID:</strong> {event.event_id}</p>
170
- <p><strong>Event Name:</strong> {event.event_name}</p>
171
- </div>
172
- </div>
173
- </div>
174
-
175
- {/* Event Information */}
176
- <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-12">
177
- <div className="lg:col-span-2 space-y-6">
178
- <div>
179
- <h2 className="text-2xl font-bold text-sec-900 mb-4">Event Information</h2>
180
- <div className="bg-sec-50 rounded-lg p-6 space-y-4">
181
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
182
- <div>
183
- <h3 className="font-semibold text-sec-700">Date</h3>
184
- <p className="text-sec-900">
185
- {event.event_date ? new Date(event.event_date).toLocaleDateString('en-AU', {
186
- weekday: 'long',
187
- year: 'numeric',
188
- month: 'long',
189
- day: 'numeric'
190
- }) : 'TBA'}
191
- </p>
192
- </div>
193
- <div>
194
- <h3 className="font-semibold text-sec-700">Venue</h3>
195
- <p className="text-sec-900">{event.event_venue || 'TBA'}</p>
196
- </div>
197
- <div>
198
- <h3 className="font-semibold text-sec-700">Participants</h3>
199
- <p className="text-sec-900">{event.event_participants || 'TBA'}</p>
200
- </div>
201
- <div>
202
- <h3 className="font-semibold text-sec-700">Event Code</h3>
203
- <p className="text-sec-900 font-mono">{event.event_code}</p>
204
- </div>
205
- </div>
206
- </div>
207
- </div>
208
- </div>
209
-
210
- {/* Event Logo */}
211
- <div className="flex justify-center lg:justify-start">
212
- <div className="text-center">
213
- <FileDisplay
214
- table_name="event"
215
- record_id={event.event_id}
216
- organisation_id={event.organisation_id}
217
- category={FileCategory.EVENT_LOGOS}
218
- showDelete={false}
219
- className="rounded-lg shadow-lg [&_img]:h-20 [&_img]:w-20 [&_img]:object-contain"
220
- />
221
- <p className="mt-4 text-sm text-sec-600">Event Logo</p>
222
- </div>
223
- </div>
224
- </div>
225
- </main>
226
-
227
- <PublicPageFooter event={event} />
228
- </PublicPageLayout>
229
- );
230
- }
231
-
232
- /**
233
- * Generic public event page
234
- */
235
- function PublicEventPage() {
236
- const { eventCode } = usePublicRouteParams({ fetchEventData: false });
237
- const { event, isLoading, error, refetch } = usePublicEvent(eventCode || '');
238
-
239
- if (isLoading) return <PublicLoadingSpinner message="Loading event..." />;
240
- if (error || !event) return <div>Event not found</div>;
241
-
242
- return (
243
- <PublicPageLayout eventCode={eventCode || ''} event={event}>
244
- <PublicPageHeader
245
- event={event}
246
- eventCode={eventCode || ''}
247
- title="Event Details"
248
- description="Public information about this event"
249
- />
250
-
251
- <main className="max-w-4xl mx-auto px-4 py-6">
252
- <div className="text-center mb-6">
253
- <FileDisplay
254
- table_name="event"
255
- record_id={event.event_id}
256
- organisation_id={event.organisation_id}
257
- category={FileCategory.EVENT_LOGOS}
258
- displayOnly={true}
259
- showFallback={true}
260
- fallbackSize="xl"
261
- className="h-24 w-24 mx-auto mb-4 object-contain rounded"
262
- generateFallbackText={(fileName) => {
263
- if (!event.event_name) return 'EV';
264
- return event.event_name
265
- .split(/[\s\-_]+/)
266
- .map(word => word.charAt(0).toUpperCase())
267
- .join('')
268
- .substring(0, 3);
269
- }}
270
- />
271
- <h1 className="text-2xl font-bold text-sec-900">{event.event_name}</h1>
272
- {event.event_date && (
273
- <p className="text-sec-600 mt-2">
274
- {new Date(event.event_date).toLocaleDateString('en-AU')}
275
- </p>
276
- )}
277
- </div>
278
- </main>
279
-
280
- <PublicPageFooter event={event} />
281
- </PublicPageLayout>
282
- );
283
- }
284
-
285
- /**
286
- * Generic public info page
287
- */
288
- function PublicInfoPage() {
289
- return (
290
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
291
- <div className="max-w-md mx-auto text-center px-4">
292
- <h1 className="text-2xl font-bold text-sec-900 mb-4">
293
- Public Information Page
294
- </h1>
295
- <p className="text-sec-600">
296
- This is a public information page that doesn't require authentication.
297
- </p>
298
- </div>
299
- </div>
300
- );
301
- }
302
-
303
- /**
304
- * Generic public report page
305
- */
306
- function PublicReportPage() {
307
- return (
308
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
309
- <div className="max-w-md mx-auto text-center px-4">
310
- <h1 className="text-2xl font-bold text-sec-900 mb-4">
311
- Public Report Page
312
- </h1>
313
- <p className="text-sec-600">
314
- This is a public report page that doesn't require authentication.
315
- </p>
316
- </div>
317
- </div>
318
- );
319
- }
320
-
321
- export default PublicPageApp;
@@ -1,218 +0,0 @@
1
- /**
2
- * @file Public Page Usage Example
3
- * @package @jmruthers/pace-core
4
- * @module Examples/PublicPages
5
- * @since 1.0.0
6
- *
7
- * A complete example showing the correct usage pattern for public pages.
8
- * This example demonstrates how to properly implement public pages without
9
- * authentication context conflicts.
10
- *
11
- * @example
12
- * ```tsx
13
- * import { PublicPageUsageExample } from '@jmruthers/pace-core/examples';
14
- *
15
- * function App() {
16
- * return (
17
- * <BrowserRouter>
18
- * <Routes>
19
- * <Route path="/events/:eventCode/recipe-grid-report" element={<PublicPageUsageExample />} />
20
- * </Routes>
21
- * </BrowserRouter>
22
- * );
23
- * }
24
- * ```
25
- */
26
-
27
- import React from 'react';
28
- import {
29
- PublicPageLayout,
30
- PublicPageHeader,
31
- PublicPageFooter,
32
- FileDisplay,
33
- usePublicEvent,
34
- usePublicRouteParams,
35
- PublicLoadingSpinner,
36
- PublicErrorBoundary
37
- } from '../index';
38
- import { FileCategory } from '../types/file-reference';
39
-
40
- /**
41
- * Correct usage pattern for public pages
42
- *
43
- * This component demonstrates the proper way to implement public pages:
44
- * 1. Use usePublicRouteParams to get the eventCode from URL
45
- * 2. Use usePublicEvent to fetch event data
46
- * 3. Pass event data to PublicPageLayout
47
- * 4. No authentication context is triggered
48
- */
49
- export function PublicPageUsageExample() {
50
- // Step 1: Extract event code from URL parameters
51
- const { eventCode } = usePublicRouteParams({ fetchEventData: false });
52
-
53
- // Step 2: Fetch event data using the event code
54
- const { event, isLoading, error, refetch } = usePublicEvent(eventCode || '');
55
-
56
- // Step 3: Handle loading state
57
- if (isLoading) {
58
- return (
59
- <PublicLoadingSpinner
60
- message="Loading event details..."
61
- />
62
- );
63
- }
64
-
65
- // Step 4: Handle error state
66
- if (error) {
67
- return (
68
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
69
- <div className="max-w-md mx-auto text-center px-4">
70
- <div className="mb-6">
71
- <div className="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-acc-100 mb-4">
72
- <svg className="h-6 w-6 text-acc-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
73
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
74
- </svg>
75
- </div>
76
- <h1 className="text-2xl font-bold text-sec-900 mb-2">
77
- Event Not Found
78
- </h1>
79
- <p className="text-sec-600 mb-6">
80
- The event code "{eventCode}" is invalid or the event is not available for public viewing.
81
- </p>
82
- <button
83
- onClick={refetch}
84
- className="px-4 py-2 bg-main-600 text-main-50 rounded-md hover:bg-main-700 transition-colors"
85
- >
86
- Try Again
87
- </button>
88
- </div>
89
- </div>
90
- </div>
91
- );
92
- }
93
-
94
- // Step 5: Handle missing event
95
- if (!event) {
96
- return (
97
- <div className="min-h-screen bg-main-50 flex items-center justify-center">
98
- <div className="max-w-md mx-auto text-center px-4">
99
- <h1 className="text-2xl font-bold text-sec-900 mb-4">
100
- Event Not Available
101
- </h1>
102
- <p className="text-sec-600 mb-6">
103
- This event is not available for public viewing.
104
- </p>
105
- <button
106
- onClick={refetch}
107
- className="px-4 py-2 bg-main-600 text-main-50 rounded-md hover:bg-main-700 transition-colors"
108
- >
109
- Try Again
110
- </button>
111
- </div>
112
- </div>
113
- );
114
- }
115
-
116
- // Step 6: Render the public page with event data
117
- return (
118
- <PublicErrorBoundary>
119
- <PublicPageLayout eventCode={eventCode || ''} event={event}>
120
- <PublicPageHeader
121
- event={event}
122
- eventCode={eventCode || ''}
123
- title="Recipe Grid Report"
124
- description="Public recipe grid report for this event"
125
- />
126
-
127
- <main className="max-w-6xl mx-auto px-4 py-8">
128
- {/* Event Overview */}
129
- <div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-12">
130
- {/* Event Information */}
131
- <div className="lg:col-span-2 space-y-6">
132
- <div>
133
- <h2 className="text-2xl font-bold text-sec-900 mb-4">Event Information</h2>
134
- <div className="bg-sec-50 rounded-lg p-6 space-y-4">
135
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
136
- <div>
137
- <h3 className="font-semibold text-sec-700">Date</h3>
138
- <p className="text-sec-900">
139
- {event.event_date ? new Date(event.event_date).toLocaleDateString('en-AU', {
140
- weekday: 'long',
141
- year: 'numeric',
142
- month: 'long',
143
- day: 'numeric'
144
- }) : 'TBA'}
145
- </p>
146
- </div>
147
- <div>
148
- <h3 className="font-semibold text-sec-700">Venue</h3>
149
- <p className="text-sec-900">{event.event_venue || 'TBA'}</p>
150
- </div>
151
- <div>
152
- <h3 className="font-semibold text-sec-700">Participants</h3>
153
- <p className="text-sec-900">{event.event_participants || 'TBA'}</p>
154
- </div>
155
- <div>
156
- <h3 className="font-semibold text-sec-700">Event Code</h3>
157
- <p className="text-sec-900 font-mono">{event.event_code}</p>
158
- </div>
159
- </div>
160
-
161
- {event.event_news && (
162
- <div>
163
- <h3 className="font-semibold text-sec-700 mb-2">Event News</h3>
164
- <p className="text-sec-900">{event.event_news}</p>
165
- </div>
166
- )}
167
- </div>
168
- </div>
169
- </div>
170
-
171
- {/* Event Logo */}
172
- <div className="flex justify-center lg:justify-start">
173
- <div className="text-center">
174
- <FileDisplay
175
- table_name="event"
176
- record_id={event.event_id}
177
- organisation_id={event.organisation_id}
178
- category={FileCategory.EVENT_LOGOS}
179
- showDelete={false}
180
- className="rounded-lg shadow-lg [&_img]:h-20 [&_img]:w-20 [&_img]:object-contain"
181
- />
182
- <p className="mt-4 text-sm text-sec-600">Event Logo</p>
183
- </div>
184
- </div>
185
- </div>
186
-
187
- {/* Recipe Grid Report Content */}
188
- <div className="mb-12">
189
- <div className="bg-main-50 border border-main-200 rounded-lg p-6">
190
- <h3 className="font-semibold text-main-900 mb-2">Recipe Grid Report</h3>
191
- <p className="text-main-800">
192
- This is where your recipe grid report content would go.
193
- The public page is now working correctly without authentication context conflicts.
194
- </p>
195
- <div className="mt-4 text-sm text-main-700">
196
- <p><strong>Event Code:</strong> {eventCode}</p>
197
- <p><strong>Event ID:</strong> {event.event_id}</p>
198
- <p><strong>Event Name:</strong> {event.event_name}</p>
199
- </div>
200
- </div>
201
- </div>
202
-
203
- {/* Event Footer Information */}
204
- {event.event_footer && (
205
- <div className="bg-sec-50 rounded-lg p-6">
206
- <h3 className="font-semibold text-sec-900 mb-2">Additional Information</h3>
207
- <p className="text-sec-700">{event.event_footer}</p>
208
- </div>
209
- )}
210
- </main>
211
-
212
- <PublicPageFooter event={event} />
213
- </PublicPageLayout>
214
- </PublicErrorBoundary>
215
- );
216
- }
217
-
218
- export default PublicPageUsageExample;
@@ -1,37 +0,0 @@
1
- import { z } from 'zod';
2
-
3
- /**
4
- * Creates a subset schema from a larger schema
5
- *
6
- * @param schema - Original Zod schema
7
- * @param keys - Array of keys to pick from the schema
8
- * @returns New schema with only the selected fields
9
- */
10
- export function pickSchema<T extends z.ZodObject<any, any, any>, K extends keyof z.infer<T>>(
11
- schema: T,
12
- keys: K[]
13
- ): z.ZodObject<any> {
14
- const shape = Object.entries(schema.shape)
15
- .filter(([key]) => keys.includes(key as K))
16
- .reduce((acc, [key, value]) => {
17
- acc[key] = value as z.ZodTypeAny;
18
- return acc;
19
- }, {} as Record<string, z.ZodTypeAny>);
20
-
21
- return z.object(shape);
22
- }
23
-
24
- /**
25
- * Combines multiple Zod schemas into one
26
- *
27
- * @param schemas - Array of Zod schemas to combine
28
- * @returns Combined schema
29
- */
30
- export function combineSchemas<T extends z.ZodObject<any, any, any>[]>(
31
- schemas: T
32
- ): z.ZodObject<any> {
33
- return schemas.reduce(
34
- (merged, schema) => merged.merge(schema),
35
- z.object({})
36
- );
37
- }
@@ -1,101 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- emailSchema,
4
- nameSchema,
5
- phoneSchema,
6
- urlSchema,
7
- dateSchema
8
- } from '../common';
9
-
10
- describe('Common Validation Schemas', () => {
11
- describe('emailSchema', () => {
12
- it('should validate correct email addresses', () => {
13
- expect(emailSchema.safeParse('test@example.com').success).toBe(true);
14
- expect(emailSchema.safeParse('user.name+tag@domain.co.uk').success).toBe(true);
15
- expect(emailSchema.safeParse('123@domain.org').success).toBe(true);
16
- });
17
-
18
- it('should reject invalid email addresses', () => {
19
- expect(emailSchema.safeParse('invalid-email').success).toBe(false);
20
- expect(emailSchema.safeParse('@domain.com').success).toBe(false);
21
- expect(emailSchema.safeParse('user@').success).toBe(false);
22
- expect(emailSchema.safeParse('').success).toBe(false);
23
- });
24
-
25
- it('should reject emails that are too long', () => {
26
- const longEmail = 'a'.repeat(255) + '@example.com';
27
- expect(emailSchema.safeParse(longEmail).success).toBe(false);
28
- });
29
- });
30
-
31
- describe('nameSchema', () => {
32
- it('should validate correct names', () => {
33
- expect(nameSchema.safeParse('John Doe').success).toBe(true);
34
- expect(nameSchema.safeParse('Mary-Jane').success).toBe(true);
35
- expect(nameSchema.safeParse("O'Connor").success).toBe(true);
36
- });
37
-
38
- it('should reject invalid names', () => {
39
- expect(nameSchema.safeParse('').success).toBe(false);
40
- expect(nameSchema.safeParse('John123').success).toBe(false);
41
- expect(nameSchema.safeParse('John@Doe').success).toBe(false);
42
- });
43
-
44
- it('should reject names that are too long', () => {
45
- const longName = 'A'.repeat(101);
46
- expect(nameSchema.safeParse(longName).success).toBe(false);
47
- });
48
- });
49
-
50
- describe('phoneSchema', () => {
51
- it('should validate correct phone numbers', () => {
52
- expect(phoneSchema.safeParse('+1-555-123-4567').success).toBe(true);
53
- expect(phoneSchema.safeParse('555-123-4567').success).toBe(true);
54
- expect(phoneSchema.safeParse('(555) 123-4567').success).toBe(true);
55
- });
56
-
57
- it('should reject invalid phone numbers', () => {
58
- expect(phoneSchema.safeParse('123').success).toBe(false);
59
- expect(phoneSchema.safeParse('not-a-number').success).toBe(false);
60
- expect(phoneSchema.safeParse('').success).toBe(false);
61
- });
62
-
63
- it('should reject phone numbers that are too short or long', () => {
64
- expect(phoneSchema.safeParse('123').success).toBe(false);
65
- expect(phoneSchema.safeParse('1'.repeat(21)).success).toBe(false);
66
- });
67
- });
68
-
69
- describe('urlSchema', () => {
70
- it('should validate correct URLs', () => {
71
- expect(urlSchema.safeParse('https://example.com').success).toBe(true);
72
- expect(urlSchema.safeParse('http://sub.domain.co.uk/path').success).toBe(true);
73
- expect(urlSchema.safeParse('https://example.com?param=value').success).toBe(true);
74
- });
75
-
76
- it('should reject invalid URLs', () => {
77
- expect(urlSchema.safeParse('not-a-url').success).toBe(false);
78
- expect(urlSchema.safeParse('').success).toBe(false);
79
- });
80
-
81
- it('should reject URLs that are too long', () => {
82
- const longUrl = 'https://example.com/' + 'a'.repeat(2048);
83
- expect(urlSchema.safeParse(longUrl).success).toBe(false);
84
- });
85
- });
86
-
87
- describe('dateSchema', () => {
88
- it('should validate correct dates', () => {
89
- expect(dateSchema.safeParse('2023-12-25').success).toBe(true);
90
- expect(dateSchema.safeParse('2023-01-01').success).toBe(true);
91
- });
92
-
93
- it('should reject invalid dates', () => {
94
- expect(dateSchema.safeParse('invalid-date').success).toBe(false);
95
- expect(dateSchema.safeParse('2023/12/25').success).toBe(false);
96
- expect(dateSchema.safeParse('12/25/2023').success).toBe(false);
97
- expect(dateSchema.safeParse('2023-13-45').success).toBe(false);
98
- expect(dateSchema.safeParse('').success).toBe(false);
99
- });
100
- });
101
- });