@jmruthers/pace-core 0.2.4

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 (1009) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/README.md +299 -0
  3. package/dist/DataTable-BHlzyKZP.d.ts +116 -0
  4. package/dist/DataTable-GEY5U7OI.js +100 -0
  5. package/dist/DataTable-GEY5U7OI.js.map +1 -0
  6. package/dist/PublicLoadingSpinner-DztrzuJr.d.ts +3430 -0
  7. package/dist/UnifiedAuthProvider-w66zSCUf.d.ts +160 -0
  8. package/dist/api-GZHIDA4X.js +41 -0
  9. package/dist/api-GZHIDA4X.js.map +1 -0
  10. package/dist/appConfig-BVGyuvI7.d.ts +71 -0
  11. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  12. package/dist/appNameResolver-7GHF5ED2.js.map +1 -0
  13. package/dist/audit-BUW3LMJB.js +16 -0
  14. package/dist/audit-BUW3LMJB.js.map +1 -0
  15. package/dist/chunk-22KLBHPS.js +29 -0
  16. package/dist/chunk-22KLBHPS.js.map +1 -0
  17. package/dist/chunk-24MKLB7U.js +81 -0
  18. package/dist/chunk-24MKLB7U.js.map +1 -0
  19. package/dist/chunk-2MKP6IYD.js +388 -0
  20. package/dist/chunk-2MKP6IYD.js.map +1 -0
  21. package/dist/chunk-2V3Y6YBC.js +114 -0
  22. package/dist/chunk-2V3Y6YBC.js.map +1 -0
  23. package/dist/chunk-5CDJCTOO.js +190 -0
  24. package/dist/chunk-5CDJCTOO.js.map +1 -0
  25. package/dist/chunk-6ZQVSHKL.js +1345 -0
  26. package/dist/chunk-6ZQVSHKL.js.map +1 -0
  27. package/dist/chunk-74C6SNEC.js +77 -0
  28. package/dist/chunk-74C6SNEC.js.map +1 -0
  29. package/dist/chunk-7BNPOCLL.js +178 -0
  30. package/dist/chunk-7BNPOCLL.js.map +1 -0
  31. package/dist/chunk-7JL3T7BO.js +3344 -0
  32. package/dist/chunk-7JL3T7BO.js.map +1 -0
  33. package/dist/chunk-CDQ3PX7L.js +18 -0
  34. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  35. package/dist/chunk-DY5E3AT7.js +1734 -0
  36. package/dist/chunk-DY5E3AT7.js.map +1 -0
  37. package/dist/chunk-ETEJVKYK.js +6032 -0
  38. package/dist/chunk-ETEJVKYK.js.map +1 -0
  39. package/dist/chunk-I5Z3QH5X.js +32 -0
  40. package/dist/chunk-I5Z3QH5X.js.map +1 -0
  41. package/dist/chunk-MZBUOP4P.js +119 -0
  42. package/dist/chunk-MZBUOP4P.js.map +1 -0
  43. package/dist/chunk-N2EUGZRW.js +98 -0
  44. package/dist/chunk-N2EUGZRW.js.map +1 -0
  45. package/dist/chunk-NQ4TOOO6.js +20 -0
  46. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  47. package/dist/chunk-OHXGNT3K.js +21 -0
  48. package/dist/chunk-OHXGNT3K.js.map +1 -0
  49. package/dist/chunk-OKXMUYIB.js +522 -0
  50. package/dist/chunk-OKXMUYIB.js.map +1 -0
  51. package/dist/chunk-PFRRIDYA.js +382 -0
  52. package/dist/chunk-PFRRIDYA.js.map +1 -0
  53. package/dist/chunk-PLDDJCW6.js +49 -0
  54. package/dist/chunk-PLDDJCW6.js.map +1 -0
  55. package/dist/chunk-SS3E6QLB.js +695 -0
  56. package/dist/chunk-SS3E6QLB.js.map +1 -0
  57. package/dist/chunk-TMRLB2LA.js +326 -0
  58. package/dist/chunk-TMRLB2LA.js.map +1 -0
  59. package/dist/chunk-WYB6MBZA.js +5533 -0
  60. package/dist/chunk-WYB6MBZA.js.map +1 -0
  61. package/dist/chunk-YDJW5XTN.js +84 -0
  62. package/dist/chunk-YDJW5XTN.js.map +1 -0
  63. package/dist/components.d.ts +1308 -0
  64. package/dist/components.js +3759 -0
  65. package/dist/components.js.map +1 -0
  66. package/dist/database-C3Szpi5J.d.ts +470 -0
  67. package/dist/hooks.d.ts +449 -0
  68. package/dist/hooks.js +612 -0
  69. package/dist/hooks.js.map +1 -0
  70. package/dist/index.d.ts +385 -0
  71. package/dist/index.js +569 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/organisation-CO3Sh3_D.d.ts +99 -0
  74. package/dist/providers.d.ts +45 -0
  75. package/dist/providers.js +36 -0
  76. package/dist/providers.js.map +1 -0
  77. package/dist/rbac/eslint-rules.d.ts +52 -0
  78. package/dist/rbac/eslint-rules.js +252 -0
  79. package/dist/rbac/eslint-rules.js.map +1 -0
  80. package/dist/rbac/index.d.ts +1918 -0
  81. package/dist/rbac/index.js +2212 -0
  82. package/dist/rbac/index.js.map +1 -0
  83. package/dist/styles/core.css +401 -0
  84. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  85. package/dist/styles/fonts/georama.woff2 +0 -0
  86. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  87. package/dist/styles/fonts/open-sans.woff2 +0 -0
  88. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  89. package/dist/styles/index.d.ts +36 -0
  90. package/dist/styles/index.js +24 -0
  91. package/dist/styles/index.js.map +1 -0
  92. package/dist/theming/runtime.d.ts +73 -0
  93. package/dist/theming/runtime.js +16 -0
  94. package/dist/theming/runtime.js.map +1 -0
  95. package/dist/types-CInEi-ng.d.ts +316 -0
  96. package/dist/types.d.ts +196 -0
  97. package/dist/types.js +83 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/unified-CM7T0aTK.d.ts +198 -0
  100. package/dist/useComponentPerformance-DE9l5RkL.d.ts +11 -0
  101. package/dist/usePublicRouteParams-B6i0KtXW.d.ts +477 -0
  102. package/dist/utils.d.ts +639 -0
  103. package/dist/utils.js +1103 -0
  104. package/dist/utils.js.map +1 -0
  105. package/dist/validation-PM_iOaTI.d.ts +159 -0
  106. package/dist/validation.d.ts +138 -0
  107. package/dist/validation.js +477 -0
  108. package/dist/validation.js.map +1 -0
  109. package/docs/INDEX.md +192 -0
  110. package/docs/README.md +165 -0
  111. package/docs/api/.nojekyll +1 -0
  112. package/docs/api/README.md +301 -0
  113. package/docs/api/classes/ErrorBoundary.md +144 -0
  114. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  115. package/docs/api/interfaces/AggregateConfig.md +43 -0
  116. package/docs/api/interfaces/ButtonProps.md +53 -0
  117. package/docs/api/interfaces/CardProps.md +40 -0
  118. package/docs/api/interfaces/ColorPalette.md +7 -0
  119. package/docs/api/interfaces/ColorShade.md +41 -0
  120. package/docs/api/interfaces/DataTableAction.md +200 -0
  121. package/docs/api/interfaces/DataTableColumn.md +300 -0
  122. package/docs/api/interfaces/DataTableProps.md +517 -0
  123. package/docs/api/interfaces/DataTableToolbarButton.md +96 -0
  124. package/docs/api/interfaces/EmptyStateConfig.md +61 -0
  125. package/docs/api/interfaces/EventContextType.md +96 -0
  126. package/docs/api/interfaces/EventLogoProps.md +152 -0
  127. package/docs/api/interfaces/EventProviderProps.md +19 -0
  128. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  129. package/docs/api/interfaces/FileUploadProps.md +154 -0
  130. package/docs/api/interfaces/FooterProps.md +105 -0
  131. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  132. package/docs/api/interfaces/InputProps.md +53 -0
  133. package/docs/api/interfaces/LabelProps.md +107 -0
  134. package/docs/api/interfaces/LoginFormProps.md +184 -0
  135. package/docs/api/interfaces/NavigationItem.md +176 -0
  136. package/docs/api/interfaces/NavigationMenuProps.md +236 -0
  137. package/docs/api/interfaces/Organisation.md +140 -0
  138. package/docs/api/interfaces/OrganisationContextType.md +377 -0
  139. package/docs/api/interfaces/OrganisationMembership.md +140 -0
  140. package/docs/api/interfaces/OrganisationProviderProps.md +19 -0
  141. package/docs/api/interfaces/OrganisationSecurityError.md +62 -0
  142. package/docs/api/interfaces/PaceAppLayoutProps.md +393 -0
  143. package/docs/api/interfaces/PaceLoginPageProps.md +34 -0
  144. package/docs/api/interfaces/PaletteData.md +41 -0
  145. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  146. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  147. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  148. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  149. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  150. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  151. package/docs/api/interfaces/StorageConfig.md +41 -0
  152. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  153. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  154. package/docs/api/interfaces/StorageListOptions.md +86 -0
  155. package/docs/api/interfaces/StorageListResult.md +41 -0
  156. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  157. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  158. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  159. package/docs/api/interfaces/StyleImport.md +19 -0
  160. package/docs/api/interfaces/ToastActionElement.md +9 -0
  161. package/docs/api/interfaces/ToastProps.md +9 -0
  162. package/docs/api/interfaces/UnifiedAuthContextType.md +1108 -0
  163. package/docs/api/interfaces/UnifiedAuthProviderProps.md +171 -0
  164. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  165. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  166. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  167. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  168. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  169. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  170. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  171. package/docs/api/interfaces/UserEventAccess.md +118 -0
  172. package/docs/api/interfaces/UserMenuProps.md +86 -0
  173. package/docs/api/interfaces/UserProfile.md +63 -0
  174. package/docs/api/modules.md +4153 -0
  175. package/docs/api-reference/components.md +1623 -0
  176. package/docs/api-reference/hooks.md +627 -0
  177. package/docs/api-reference/providers.md +487 -0
  178. package/docs/api-reference/types.md +1005 -0
  179. package/docs/api-reference/utilities.md +1104 -0
  180. package/docs/app.css.example +53 -0
  181. package/docs/architecture/README.md +577 -0
  182. package/docs/best-practices/README.md +400 -0
  183. package/docs/best-practices/deployment.md +1042 -0
  184. package/docs/best-practices/performance.md +789 -0
  185. package/docs/best-practices/security.md +881 -0
  186. package/docs/best-practices/testing.md +981 -0
  187. package/docs/consuming-app-example.md +290 -0
  188. package/docs/consuming-app-vite-config.md +233 -0
  189. package/docs/core-concepts/authentication.md +98 -0
  190. package/docs/core-concepts/events.md +756 -0
  191. package/docs/core-concepts/organisations.md +790 -0
  192. package/docs/core-concepts/permissions.md +729 -0
  193. package/docs/core-concepts/rbac-system.md +233 -0
  194. package/docs/database-schema-requirements.md +172 -0
  195. package/docs/documentation-style-checklist.md +294 -0
  196. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  197. package/docs/getting-started/examples/README.md +106 -0
  198. package/docs/getting-started/examples/basic-auth-app.md +521 -0
  199. package/docs/getting-started/examples/full-featured-app.md +616 -0
  200. package/docs/getting-started/installation.md +269 -0
  201. package/docs/getting-started/quick-start.md +401 -0
  202. package/docs/implementation-guides/app-layout.md +983 -0
  203. package/docs/implementation-guides/data-tables.md +1898 -0
  204. package/docs/implementation-guides/dynamic-colors.md +195 -0
  205. package/docs/implementation-guides/forms.md +578 -0
  206. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  207. package/docs/implementation-guides/large-datasets.md +281 -0
  208. package/docs/implementation-guides/navigation.md +844 -0
  209. package/docs/implementation-guides/performance.md +403 -0
  210. package/docs/implementation-guides/permission-enforcement.md +764 -0
  211. package/docs/implementation-guides/public-pages.md +752 -0
  212. package/docs/migration/README.md +493 -0
  213. package/docs/migration/organisation-context-timing-fix.md +217 -0
  214. package/docs/migration/quick-migration-guide.md +320 -0
  215. package/docs/migration/rbac-migration.md +571 -0
  216. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  217. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  218. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  219. package/docs/migration-guide.md +168 -0
  220. package/docs/performance/README.md +551 -0
  221. package/docs/print-components/README.md +258 -0
  222. package/docs/print-components/api-reference.md +636 -0
  223. package/docs/print-components/examples/README.md +204 -0
  224. package/docs/print-components/examples/basic-report.tsx +92 -0
  225. package/docs/print-components/examples/card-catalog.tsx +149 -0
  226. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  227. package/docs/print-components/quick-start.md +363 -0
  228. package/docs/quick-reference.md +576 -0
  229. package/docs/rbac/README.md +265 -0
  230. package/docs/rbac/advanced-patterns.md +776 -0
  231. package/docs/rbac/api-reference.md +1033 -0
  232. package/docs/rbac/examples.md +883 -0
  233. package/docs/rbac/getting-started.md +679 -0
  234. package/docs/rbac/quick-start.md +619 -0
  235. package/docs/rbac/super-admin-guide.md +592 -0
  236. package/docs/rbac/troubleshooting.md +316 -0
  237. package/docs/security/README.md +680 -0
  238. package/docs/security/checklist.md +343 -0
  239. package/docs/style-guide.md +522 -0
  240. package/docs/styles/README.md +319 -0
  241. package/docs/testing/README.md +874 -0
  242. package/docs/troubleshooting/README.md +497 -0
  243. package/docs/troubleshooting/common-issues.md +1563 -0
  244. package/docs/troubleshooting/database-view-compatibility.md +119 -0
  245. package/docs/troubleshooting/debugging.md +1117 -0
  246. package/docs/troubleshooting/migration.md +918 -0
  247. package/docs/troubleshooting/organisation-context-setup.md +277 -0
  248. package/docs/troubleshooting/react-hooks-issue-analysis.md +166 -0
  249. package/docs/troubleshooting/styling-issues.md +219 -0
  250. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  251. package/docs/usage.md +175 -0
  252. package/docs/visual-testing.md +114 -0
  253. package/package.json +211 -0
  254. package/src/__mocks__/lucide-react.ts +181 -0
  255. package/src/__tests__/README.md +404 -0
  256. package/src/__tests__/debug-provider.unit.test.tsx +67 -0
  257. package/src/__tests__/e2e/workflows.test.tsx +373 -0
  258. package/src/__tests__/hybridPermissions.unit.test.tsx +474 -0
  259. package/src/__tests__/index.integration.test.ts +491 -0
  260. package/src/__tests__/mocks/MockAuthProvider-standalone.tsx +47 -0
  261. package/src/__tests__/mocks/MockAuthProvider.tsx +63 -0
  262. package/src/__tests__/mocks/enhancedSupabaseMock.ts +252 -0
  263. package/src/__tests__/mocks/index.test.ts +23 -0
  264. package/src/__tests__/mocks/index.ts +16 -0
  265. package/src/__tests__/mocks/mockAuth.ts +155 -0
  266. package/src/__tests__/mocks/mockSupabase.ts +83 -0
  267. package/src/__tests__/mocks/mockSupabaseClient.ts +63 -0
  268. package/src/__tests__/mocks/providers.tsx +22 -0
  269. package/src/__tests__/patterns/__tests__/testPatterns.test.ts +394 -0
  270. package/src/__tests__/patterns/testPatterns.ts +124 -0
  271. package/src/__tests__/performance/componentPerformance.performance.test.ts +27 -0
  272. package/src/__tests__/performance/index.ts +24 -0
  273. package/src/__tests__/performance/performanceValidation.performance.test.ts +15 -0
  274. package/src/__tests__/security/security.unit.test.tsx +7 -0
  275. package/src/__tests__/security/securityValidation.security.test.tsx +153 -0
  276. package/src/__tests__/setup.ts +259 -0
  277. package/src/__tests__/setupTests.d.ts +1 -0
  278. package/src/__tests__/shared/componentTestUtils.tsx +475 -0
  279. package/src/__tests__/shared/errorHandlingTestUtils.ts +107 -0
  280. package/src/__tests__/shared/index.ts +81 -0
  281. package/src/__tests__/shared/integrationTestUtils.tsx +375 -0
  282. package/src/__tests__/shared/performanceTestUtils.tsx +476 -0
  283. package/src/__tests__/shared/testUtils.optimized.tsx +627 -0
  284. package/src/__tests__/simple.test.tsx +20 -0
  285. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  286. package/src/__tests__/templates/component.test.template.tsx +122 -0
  287. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  288. package/src/__tests__/test-utils/dataFactories.ts +60 -0
  289. package/src/__tests__/test-utils/index.ts +6 -0
  290. package/src/__tests__/typeSafety.unit.test.ts +65 -0
  291. package/src/__tests__/unifiedAuth.unit.test.tsx +151 -0
  292. package/src/__tests__/utils/accessibilityHelpers.ts +254 -0
  293. package/src/__tests__/utils/assertions.ts +50 -0
  294. package/src/__tests__/utils/deterministicHelpers.ts +31 -0
  295. package/src/__tests__/utils/edgeCaseConfig.test.ts +75 -0
  296. package/src/__tests__/utils/edgeCaseConfig.ts +98 -0
  297. package/src/__tests__/utils/mockHelpers.ts +149 -0
  298. package/src/__tests__/utils/mockLoader.ts +101 -0
  299. package/src/__tests__/utils/performanceHelpers.ts +55 -0
  300. package/src/__tests__/utils/performanceTestHelpers.ts +68 -0
  301. package/src/__tests__/utils/testDataFactories.ts +28 -0
  302. package/src/__tests__/utils/testIsolation.ts +67 -0
  303. package/src/__tests__/utils/visualTestHelpers.ts +20 -0
  304. package/src/__tests__/visual/__snapshots__/componentSnapshots.visual.test.tsx.snap +68 -0
  305. package/src/__tests__/visual/__snapshots__/componentVisuals.visual.test.tsx.snap +14 -0
  306. package/src/__tests__/visual/__snapshots__/visualRegression.test.tsx.snap +217 -0
  307. package/src/__tests__/visual/__snapshots__/visualRegression.visual.test.tsx.snap +24 -0
  308. package/src/__tests__/visual/componentSnapshots.visual.test.tsx +33 -0
  309. package/src/__tests__/visual/componentVisuals.visual.test.tsx +12 -0
  310. package/src/__tests__/visual/visualRegression.visual.test.tsx +20 -0
  311. package/src/components/Alert/Alert.tsx +134 -0
  312. package/src/components/Alert/__tests__/Alert.unit.test.tsx +381 -0
  313. package/src/components/Alert/index.ts +2 -0
  314. package/src/components/Avatar/Avatar.tsx +84 -0
  315. package/src/components/Avatar/__tests__/Avatar.unit.test.tsx +232 -0
  316. package/src/components/Avatar/index.ts +2 -0
  317. package/src/components/Button/Button.tsx +270 -0
  318. package/src/components/Button/__tests__/Button.accessibility.test.tsx +131 -0
  319. package/src/components/Button/__tests__/Button.comprehensive.test.tsx +721 -0
  320. package/src/components/Button/__tests__/Button.unit.test.tsx +189 -0
  321. package/src/components/Button/__tests__/EventSelector.integration.test.tsx +285 -0
  322. package/src/components/Button/index.ts +2 -0
  323. package/src/components/Card/Card.tsx +271 -0
  324. package/src/components/Card/__tests__/Card.accessibility.test.tsx +394 -0
  325. package/src/components/Card/__tests__/Card.comprehensive.test.tsx +599 -0
  326. package/src/components/Card/__tests__/Card.integration.test.tsx +673 -0
  327. package/src/components/Card/__tests__/Card.performance.test.tsx +546 -0
  328. package/src/components/Card/__tests__/Card.unit.test.tsx +330 -0
  329. package/src/components/Card/__tests__/Card.visual.test.tsx +599 -0
  330. package/src/components/Card/__tests__/README.md +211 -0
  331. package/src/components/Card/index.ts +1 -0
  332. package/src/components/Checkbox/Checkbox.tsx +75 -0
  333. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  334. package/src/components/Checkbox/__tests__/Checkbox.unit.test.tsx +520 -0
  335. package/src/components/Checkbox/index.ts +2 -0
  336. package/src/components/DataTable/DataTable.tsx +440 -0
  337. package/src/components/DataTable/__tests__/DataTable.autoSizing.test.tsx +526 -0
  338. package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +259 -0
  339. package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +675 -0
  340. package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +324 -0
  341. package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +724 -0
  342. package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +597 -0
  343. package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +306 -0
  344. package/src/components/DataTable/__tests__/DataTable.regressionFixes.test.tsx +546 -0
  345. package/src/components/DataTable/__tests__/DataTable.selection.controlled.test.tsx +386 -0
  346. package/src/components/DataTable/__tests__/DataTable.selection.test.tsx +338 -0
  347. package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +310 -0
  348. package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +489 -0
  349. package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +701 -0
  350. package/src/components/DataTable/__tests__/README.md +136 -0
  351. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  352. package/src/components/DataTable/__tests__/performance-regression.test.tsx +788 -0
  353. package/src/components/DataTable/__tests__/performance.test.tsx +365 -0
  354. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  355. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +382 -0
  356. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  357. package/src/components/DataTable/components/ActionButtons.tsx +177 -0
  358. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  359. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  360. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  361. package/src/components/DataTable/components/DataTableBody.tsx +462 -0
  362. package/src/components/DataTable/components/DataTableCore.tsx +869 -0
  363. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  364. package/src/components/DataTable/components/DataTableHeader.tsx +31 -0
  365. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  366. package/src/components/DataTable/components/DataTableToolbar.tsx +251 -0
  367. package/src/components/DataTable/components/DraggableColumnHeader.tsx +148 -0
  368. package/src/components/DataTable/components/EditableRow.tsx +160 -0
  369. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  370. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  371. package/src/components/DataTable/components/FilterRow.tsx +101 -0
  372. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  373. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  374. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  375. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  376. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  377. package/src/components/DataTable/components/UnifiedTableBody.tsx +911 -0
  378. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  379. package/src/components/DataTable/components/VirtualizedDataTable.tsx +593 -0
  380. package/src/components/DataTable/components/__tests__/ActionButtons.unit.test.tsx +150 -0
  381. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +224 -0
  382. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.unit.test.tsx +244 -0
  383. package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +523 -0
  384. package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +401 -0
  385. package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +161 -0
  386. package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +251 -0
  387. package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +172 -0
  388. package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +290 -0
  389. package/src/components/DataTable/components/__tests__/DataTableBody.unit.test.tsx +147 -0
  390. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.unit.test.tsx +182 -0
  391. package/src/components/DataTable/components/__tests__/DataTableHeader.unit.test.tsx +143 -0
  392. package/src/components/DataTable/components/__tests__/DataTableModals.unit.test.tsx +123 -0
  393. package/src/components/DataTable/components/__tests__/EditableRow.unit.test.tsx +660 -0
  394. package/src/components/DataTable/components/__tests__/EmptyState.unit.test.tsx +256 -0
  395. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +498 -0
  396. package/src/components/DataTable/components/__tests__/FilterRow.unit.test.tsx +112 -0
  397. package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +130 -0
  398. package/src/components/DataTable/components/__tests__/GroupHeader.unit.test.tsx +172 -0
  399. package/src/components/DataTable/components/__tests__/GroupingDropdown.unit.test.tsx +222 -0
  400. package/src/components/DataTable/components/__tests__/ImportModal.unit.test.tsx +780 -0
  401. package/src/components/DataTable/components/__tests__/LoadingState.unit.test.tsx +65 -0
  402. package/src/components/DataTable/components/__tests__/PaginationControls.unit.test.tsx +634 -0
  403. package/src/components/DataTable/components/__tests__/StateComponents.unit.test.tsx +48 -0
  404. package/src/components/DataTable/components/__tests__/UnifiedTableBody.hierarchical.test.tsx +541 -0
  405. package/src/components/DataTable/components/__tests__/ViewRowModal.unit.test.tsx +228 -0
  406. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.unit.test.tsx +568 -0
  407. package/src/components/DataTable/components/index.ts +17 -0
  408. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  409. package/src/components/DataTable/core/ActionManager.ts +235 -0
  410. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  411. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  412. package/src/components/DataTable/core/DataManager.ts +188 -0
  413. package/src/components/DataTable/core/DataTableContext.tsx +182 -0
  414. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  415. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  416. package/src/components/DataTable/core/StateManager.ts +311 -0
  417. package/src/components/DataTable/core/__tests__/ActionManager.unit.test.ts +405 -0
  418. package/src/components/DataTable/core/__tests__/ArchitectureIntegration.unit.test.tsx +445 -0
  419. package/src/components/DataTable/core/__tests__/ColumnFactory.unit.test.ts +288 -0
  420. package/src/components/DataTable/core/__tests__/ColumnManager.unit.test.ts +623 -0
  421. package/src/components/DataTable/core/__tests__/DataManager.unit.test.ts +431 -0
  422. package/src/components/DataTable/core/__tests__/DataTableContext.unit.test.tsx +433 -0
  423. package/src/components/DataTable/core/__tests__/LocalDataAdapter.unit.test.ts +422 -0
  424. package/src/components/DataTable/core/__tests__/PluginRegistry.unit.test.tsx +207 -0
  425. package/src/components/DataTable/core/__tests__/StateManager.unit.test.ts +278 -0
  426. package/src/components/DataTable/core/index.ts +8 -0
  427. package/src/components/DataTable/core/interfaces.ts +338 -0
  428. package/src/components/DataTable/examples/AutoSizingExample.tsx +180 -0
  429. package/src/components/DataTable/examples/ColumnSizingComparison.tsx +235 -0
  430. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +418 -0
  431. package/src/components/DataTable/examples/HierarchicalExample.tsx +472 -0
  432. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +173 -0
  433. package/src/components/DataTable/examples/PerformanceExample.tsx +502 -0
  434. package/src/components/DataTable/examples/__tests__/PerformanceExample.unit.test.tsx +281 -0
  435. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.unit.test.ts +407 -0
  436. package/src/components/DataTable/hooks/__tests__/useColumnReordering.unit.test.ts +679 -0
  437. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  438. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  439. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  440. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  441. package/src/components/DataTable/index.ts +70 -0
  442. package/src/components/DataTable/styles.ts +171 -0
  443. package/src/components/DataTable/types.ts +475 -0
  444. package/src/components/DataTable/utils/__tests__/columnSizing.test.ts +237 -0
  445. package/src/components/DataTable/utils/__tests__/debugTools.unit.test.ts +267 -0
  446. package/src/components/DataTable/utils/__tests__/errorHandling.unit.test.ts +467 -0
  447. package/src/components/DataTable/utils/__tests__/exportUtils.unit.test.ts +380 -0
  448. package/src/components/DataTable/utils/__tests__/flexibleImport.unit.test.ts +233 -0
  449. package/src/components/DataTable/utils/__tests__/performanceUtils.unit.test.ts +414 -0
  450. package/src/components/DataTable/utils/columnSizing.ts +125 -0
  451. package/src/components/DataTable/utils/debugTools.ts +583 -0
  452. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  453. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  454. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  455. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  456. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  457. package/src/components/DataTable/utils/index.ts +1 -0
  458. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  459. package/src/components/Dialog/Dialog.tsx +782 -0
  460. package/src/components/Dialog/README.md +804 -0
  461. package/src/components/Dialog/__tests__/Dialog.accessibility.test.tsx +521 -0
  462. package/src/components/Dialog/__tests__/Dialog.auto-size.example.tsx +157 -0
  463. package/src/components/Dialog/__tests__/Dialog.enhanced.test.tsx +538 -0
  464. package/src/components/Dialog/__tests__/Dialog.unit.test.tsx +1373 -0
  465. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  466. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  467. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  468. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  469. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  470. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +151 -0
  471. package/src/components/Dialog/index.ts +12 -0
  472. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +611 -0
  473. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  474. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  475. package/src/components/ErrorBoundary/__tests__/ErrorBoundary.accessibility.test.tsx +517 -0
  476. package/src/components/ErrorBoundary/__tests__/ErrorBoundary.integration.test.tsx +572 -0
  477. package/src/components/ErrorBoundary/__tests__/ErrorBoundary.unit.test.tsx +579 -0
  478. package/src/components/ErrorBoundary/index.ts +8 -0
  479. package/src/components/EventSelector/EventSelector.tsx +360 -0
  480. package/src/components/EventSelector/__tests__/EventSelector.test.tsx +528 -0
  481. package/src/components/EventSelector/index.ts +3 -0
  482. package/src/components/EventSelector/types.ts +79 -0
  483. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  484. package/src/components/FileUpload/FileUpload.tsx +237 -0
  485. package/src/components/FileUpload/__tests__/FileUpload.integration.test.tsx +992 -0
  486. package/src/components/FileUpload/__tests__/FileUpload.real.test.tsx +927 -0
  487. package/src/components/FileUpload/__tests__/FileUpload.test.tsx +855 -0
  488. package/src/components/FileUpload/__tests__/FileUpload.unit.test.tsx +1311 -0
  489. package/src/components/FileUpload/__tests__/FileUpload.unmocked.test.tsx +937 -0
  490. package/src/components/FileUpload/index.ts +6 -0
  491. package/src/components/Footer/Footer.tsx +197 -0
  492. package/src/components/Footer/__tests__/Footer.accessibility.test.tsx +359 -0
  493. package/src/components/Footer/__tests__/Footer.integration.test.tsx +353 -0
  494. package/src/components/Footer/__tests__/Footer.performance.test.tsx +309 -0
  495. package/src/components/Footer/__tests__/Footer.unit.test.tsx +309 -0
  496. package/src/components/Footer/__tests__/Footer.visual.test.tsx +335 -0
  497. package/src/components/Footer/index.ts +17 -0
  498. package/src/components/Form/Form.tsx +166 -0
  499. package/src/components/Form/FormErrorSummary.tsx +113 -0
  500. package/src/components/Form/FormField.tsx +249 -0
  501. package/src/components/Form/FormFieldset.tsx +127 -0
  502. package/src/components/Form/FormLiveRegion.tsx +198 -0
  503. package/src/components/Form/__tests__/Form.accessibility.test.tsx +820 -0
  504. package/src/components/Form/__tests__/Form.unit.test.tsx +305 -0
  505. package/src/components/Form/__tests__/FormErrorSummary.unit.test.tsx +285 -0
  506. package/src/components/Form/__tests__/FormFieldset.unit.test.tsx +241 -0
  507. package/src/components/Form/index.ts +26 -0
  508. package/src/components/Header/Header.tsx +301 -0
  509. package/src/components/Header/__tests__/Header.accessibility.test.tsx +382 -0
  510. package/src/components/Header/__tests__/Header.comprehensive.test.tsx +509 -0
  511. package/src/components/Header/__tests__/Header.unit.test.tsx +335 -0
  512. package/src/components/Header/index.ts +4 -0
  513. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +196 -0
  514. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  515. package/src/components/InactivityWarningModal/__tests__/InactivityWarningModal.unit.test.tsx +224 -0
  516. package/src/components/InactivityWarningModal/index.ts +9 -0
  517. package/src/components/Input/Input.tsx +201 -0
  518. package/src/components/Input/__mocks__/Input.tsx +2 -0
  519. package/src/components/Input/__tests__/Input.accessibility.test.tsx +632 -0
  520. package/src/components/Input/__tests__/Input.unit.test.tsx +1121 -0
  521. package/src/components/Input/index.ts +9 -0
  522. package/src/components/Label/Label.tsx +186 -0
  523. package/src/components/Label/__tests__/Label.accessibility.test.tsx +239 -0
  524. package/src/components/Label/__tests__/Label.unit.test.tsx +331 -0
  525. package/src/components/Label/index.ts +2 -0
  526. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  527. package/src/components/LoadingSpinner/__tests__/LoadingSpinner.accessibility.test.tsx +116 -0
  528. package/src/components/LoadingSpinner/__tests__/LoadingSpinner.unit.test.tsx +144 -0
  529. package/src/components/LoadingSpinner/index.ts +3 -0
  530. package/src/components/LoginForm/LoginForm.tsx +273 -0
  531. package/src/components/LoginForm/__tests__/LoginForm.accessibility.test.tsx +201 -0
  532. package/src/components/LoginForm/__tests__/LoginForm.unit.test.tsx +119 -0
  533. package/src/components/LoginForm/index.ts +3 -0
  534. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  535. package/src/components/NavigationMenu/__tests__/NavigationMenu.accessibility.test.tsx +378 -0
  536. package/src/components/NavigationMenu/__tests__/NavigationMenu.enhanced.test.tsx +768 -0
  537. package/src/components/NavigationMenu/__tests__/NavigationMenu.integration.test.tsx +576 -0
  538. package/src/components/NavigationMenu/__tests__/NavigationMenu.performance.test.tsx +585 -0
  539. package/src/components/NavigationMenu/__tests__/NavigationMenu.real.component.test.tsx +783 -0
  540. package/src/components/NavigationMenu/__tests__/NavigationMenu.security.enhanced.test.tsx +810 -0
  541. package/src/components/NavigationMenu/__tests__/NavigationMenu.security.test.tsx +494 -0
  542. package/src/components/NavigationMenu/__tests__/NavigationMenu.unit.test.tsx +331 -0
  543. package/src/components/NavigationMenu/__tests__/NavigationMenu.userWorkflows.test.tsx +347 -0
  544. package/src/components/NavigationMenu/__tests__/NavigationMenu.workflows.test.tsx +584 -0
  545. package/src/components/NavigationMenu/index.ts +10 -0
  546. package/src/components/NavigationMenu/types.ts +85 -0
  547. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  548. package/src/components/OrganisationSelector/__tests__/OrganisationSelector.unit.test.tsx +664 -0
  549. package/src/components/OrganisationSelector/index.ts +9 -0
  550. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  551. package/src/components/PaceAppLayout/README.md +278 -0
  552. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +288 -0
  553. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +889 -0
  554. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +629 -0
  555. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +782 -0
  556. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +904 -0
  557. package/src/components/PaceAppLayout/index.ts +1 -0
  558. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  559. package/src/components/PaceLoginPage/__tests__/PaceLoginPage.accessibility.test.tsx +463 -0
  560. package/src/components/PaceLoginPage/__tests__/PaceLoginPage.integration.test.tsx +586 -0
  561. package/src/components/PaceLoginPage/__tests__/PaceLoginPage.unit.test.tsx +533 -0
  562. package/src/components/PaceLoginPage/index.ts +1 -0
  563. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  564. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  565. package/src/components/PasswordReset/__tests__/PasswordChangeForm.accessibility.test.tsx +408 -0
  566. package/src/components/PasswordReset/__tests__/PasswordChangeForm.unit.test.tsx +561 -0
  567. package/src/components/PasswordReset/__tests__/PasswordReset.integration.test.tsx +304 -0
  568. package/src/components/PasswordReset/__tests__/PasswordResetForm.accessibility.test.tsx +20 -0
  569. package/src/components/PasswordReset/__tests__/PasswordResetForm.unit.test.tsx +523 -0
  570. package/src/components/PasswordReset/__tests__/__mocks__/UnifiedAuthProvider.ts +29 -0
  571. package/src/components/PasswordReset/index.ts +4 -0
  572. package/src/components/Print/__tests__/Print.comprehensive.test.tsx +331 -0
  573. package/src/components/PrintButton/PrintButton.tsx +321 -0
  574. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  575. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  576. package/src/components/PrintButton/__tests__/PrintButton.unit.test.tsx +429 -0
  577. package/src/components/PrintButton/__tests__/PrintButtonGroup.unit.test.tsx +277 -0
  578. package/src/components/PrintButton/__tests__/PrintToolbar.unit.test.tsx +264 -0
  579. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  580. package/src/components/PrintButton/index.ts +33 -0
  581. package/src/components/PrintButton/types.ts +173 -0
  582. package/src/components/PrintCard/PrintCard.tsx +154 -0
  583. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  584. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  585. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  586. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  587. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  588. package/src/components/PrintCard/__tests__/PrintCard.unit.test.tsx +233 -0
  589. package/src/components/PrintCard/__tests__/PrintCardContent.test.tsx +284 -0
  590. package/src/components/PrintCard/__tests__/PrintCardGrid.unit.test.tsx +214 -0
  591. package/src/components/PrintCard/__tests__/PrintCardImage.unit.test.tsx +264 -0
  592. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  593. package/src/components/PrintCard/index.ts +34 -0
  594. package/src/components/PrintCard/types.ts +171 -0
  595. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  596. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  597. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  598. package/src/components/PrintDataTable/__tests__/PrintDataTable.unit.test.tsx +361 -0
  599. package/src/components/PrintDataTable/__tests__/PrintTableGroup.unit.test.tsx +314 -0
  600. package/src/components/PrintDataTable/__tests__/PrintTableRow.unit.test.tsx +362 -0
  601. package/src/components/PrintDataTable/index.ts +25 -0
  602. package/src/components/PrintDataTable/types.ts +67 -0
  603. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  604. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  605. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  606. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  607. package/src/components/PrintFooter/__tests__/PrintFooter.unit.test.tsx +500 -0
  608. package/src/components/PrintFooter/__tests__/PrintFooterContent.unit.test.tsx +321 -0
  609. package/src/components/PrintFooter/__tests__/PrintFooterInfo.unit.test.tsx +335 -0
  610. package/src/components/PrintFooter/__tests__/PrintPageNumber.unit.test.tsx +340 -0
  611. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  612. package/src/components/PrintFooter/index.ts +30 -0
  613. package/src/components/PrintFooter/types.ts +149 -0
  614. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  615. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  616. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  617. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  618. package/src/components/PrintGrid/__tests__/PrintGrid.unit.test.tsx +340 -0
  619. package/src/components/PrintGrid/__tests__/PrintGridBreakpoint.unit.test.tsx +261 -0
  620. package/src/components/PrintGrid/__tests__/PrintGridContainer.unit.test.tsx +338 -0
  621. package/src/components/PrintGrid/__tests__/PrintGridItem.unit.test.tsx +338 -0
  622. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  623. package/src/components/PrintGrid/index.ts +31 -0
  624. package/src/components/PrintGrid/types.ts +159 -0
  625. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  626. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  627. package/src/components/PrintHeader/__tests__/PrintCoverHeader.unit.test.tsx +309 -0
  628. package/src/components/PrintHeader/__tests__/PrintHeader.unit.test.tsx +202 -0
  629. package/src/components/PrintHeader/index.ts +17 -0
  630. package/src/components/PrintHeader/types.ts +42 -0
  631. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  632. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  633. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  634. package/src/components/PrintLayout/__tests__/PrintLayout.unit.test.tsx +238 -0
  635. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  636. package/src/components/PrintLayout/index.ts +19 -0
  637. package/src/components/PrintLayout/types.ts +37 -0
  638. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  639. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  640. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  641. package/src/components/PrintPageBreak/__tests__/PrintPageBreak.unit.test.tsx +263 -0
  642. package/src/components/PrintPageBreak/__tests__/PrintPageBreakGroup.unit.test.tsx +239 -0
  643. package/src/components/PrintPageBreak/__tests__/PrintPageBreakIndicator.unit.test.tsx +235 -0
  644. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  645. package/src/components/PrintPageBreak/index.ts +23 -0
  646. package/src/components/PrintPageBreak/types.ts +94 -0
  647. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  648. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  649. package/src/components/PrintSection/PrintSection.tsx +129 -0
  650. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  651. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  652. package/src/components/PrintSection/__tests__/PrintColumn.unit.test.tsx +385 -0
  653. package/src/components/PrintSection/__tests__/PrintDivider.unit.test.tsx +373 -0
  654. package/src/components/PrintSection/__tests__/PrintSection.unit.test.tsx +390 -0
  655. package/src/components/PrintSection/__tests__/PrintSectionContent.unit.test.tsx +321 -0
  656. package/src/components/PrintSection/__tests__/PrintSectionHeader.unit.test.tsx +334 -0
  657. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  658. package/src/components/PrintSection/index.ts +33 -0
  659. package/src/components/PrintSection/types.ts +155 -0
  660. package/src/components/PrintText/PrintText.tsx +116 -0
  661. package/src/components/PrintText/__tests__/PrintText.unit.test.tsx +351 -0
  662. package/src/components/PrintText/index.ts +16 -0
  663. package/src/components/PrintText/types.ts +24 -0
  664. package/src/components/Progress/Progress.tsx +116 -0
  665. package/src/components/Progress/__tests__/Progress.accessibility.test.tsx +240 -0
  666. package/src/components/Progress/__tests__/Progress.unit.test.tsx +242 -0
  667. package/src/components/Progress/index.ts +3 -0
  668. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  669. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  670. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  671. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  672. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  673. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  674. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  675. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  676. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  677. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  678. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +761 -0
  679. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.simplified.test.tsx +228 -0
  680. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +228 -0
  681. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +459 -0
  682. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +362 -0
  683. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +522 -0
  684. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +599 -0
  685. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +513 -0
  686. package/src/components/PublicLayout/index.ts +51 -0
  687. package/src/components/RBAC/PagePermissionGuard.tsx +274 -0
  688. package/src/components/RBAC/RBACGuard.tsx +143 -0
  689. package/src/components/RBAC/RBACProvider.tsx +186 -0
  690. package/src/components/RBAC/RoleBasedContent.tsx +129 -0
  691. package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +674 -0
  692. package/src/components/RBAC/__tests__/RBAC.integration.test.tsx +573 -0
  693. package/src/components/RBAC/__tests__/RBACGuard.unit.test.tsx +467 -0
  694. package/src/components/RBAC/__tests__/RBACProvider.accessibility.test.tsx +475 -0
  695. package/src/components/RBAC/__tests__/RBACProvider.advanced.test.tsx +569 -0
  696. package/src/components/RBAC/__tests__/RBACProvider.integration.test.tsx +352 -0
  697. package/src/components/RBAC/__tests__/RBACProvider.unit.test.tsx +128 -0
  698. package/src/components/RBAC/__tests__/RoleBasedContent.unit.test.tsx +657 -0
  699. package/src/components/RBAC/index.ts +23 -0
  700. package/src/components/Select/Select.tsx +654 -0
  701. package/src/components/Select/__tests__/SearchableSelect.unit.test.tsx +437 -0
  702. package/src/components/Select/__tests__/Select.accessibility.test.tsx +1202 -0
  703. package/src/components/Select/__tests__/Select.actual.test.tsx +774 -0
  704. package/src/components/Select/__tests__/Select.comprehensive.test.tsx +837 -0
  705. package/src/components/Select/__tests__/Select.enhanced.test.tsx +1101 -0
  706. package/src/components/Select/__tests__/Select.integration.test.tsx +772 -0
  707. package/src/components/Select/__tests__/Select.performance.test.tsx +695 -0
  708. package/src/components/Select/__tests__/Select.real-world.test.tsx +1046 -0
  709. package/src/components/Select/__tests__/Select.search-algorithms.test.tsx +968 -0
  710. package/src/components/Select/__tests__/Select.unit.test.tsx +647 -0
  711. package/src/components/Select/__tests__/Select.utils.test.tsx +890 -0
  712. package/src/components/Select/index.ts +1 -0
  713. package/src/components/SuperAdminGuard.tsx +116 -0
  714. package/src/components/Table/Table.tsx +222 -0
  715. package/src/components/Table/__tests__/Table.accessibility.test.tsx +233 -0
  716. package/src/components/Table/__tests__/Table.unit.test.tsx +235 -0
  717. package/src/components/Table/index.ts +11 -0
  718. package/src/components/Toast/Toast.tsx +339 -0
  719. package/src/components/Toast/__tests__/Toast.accessibility.test.tsx +238 -0
  720. package/src/components/Toast/__tests__/Toast.integration.test.tsx +699 -0
  721. package/src/components/Toast/__tests__/Toast.unit.test.tsx +750 -0
  722. package/src/components/Toast/index.ts +14 -0
  723. package/src/components/Tooltip/Tooltip.tsx +167 -0
  724. package/src/components/Tooltip/__tests__/Tooltip.accessibility.test.tsx +121 -0
  725. package/src/components/Tooltip/__tests__/Tooltip.unit.test.tsx +185 -0
  726. package/src/components/Tooltip/index.ts +7 -0
  727. package/src/components/UserMenu/UserMenu.tsx +243 -0
  728. package/src/components/UserMenu/__tests__/UserMenu.accessibility.test.tsx +139 -0
  729. package/src/components/UserMenu/__tests__/UserMenu.integration.test.tsx +188 -0
  730. package/src/components/UserMenu/__tests__/UserMenu.unit.test.tsx +458 -0
  731. package/src/components/UserMenu/index.ts +3 -0
  732. package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +523 -0
  733. package/src/components/__tests__/ErrorTesting.enhanced.test.tsx +455 -0
  734. package/src/components/__tests__/SuperAdminGuard.test.tsx +456 -0
  735. package/src/components/__tests__/SuperAdminGuard.unit.test.tsx +456 -0
  736. package/src/components/examples/PermissionExample.tsx +150 -0
  737. package/src/components/examples/__tests__/PermissionExample.unit.test.tsx +360 -0
  738. package/src/components/index.ts +434 -0
  739. package/src/components.ts +19 -0
  740. package/src/constants/performance.ts +14 -0
  741. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  742. package/src/examples/PublicEventPage.tsx +274 -0
  743. package/src/examples/PublicPageApp.tsx +308 -0
  744. package/src/examples/PublicPageUsageExample.tsx +216 -0
  745. package/src/fonts/georama-italic.woff2 +0 -0
  746. package/src/fonts/georama.woff2 +0 -0
  747. package/src/fonts/open-sans-italic.woff2 +0 -0
  748. package/src/fonts/open-sans.woff2 +0 -0
  749. package/src/fonts/reddit-mono.woff2 +0 -0
  750. package/src/hooks/__tests__/hooks.integration.test.tsx +575 -0
  751. package/src/hooks/__tests__/useApiFetch.unit.test.ts +115 -0
  752. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +133 -0
  753. package/src/hooks/__tests__/useDebounce.unit.test.ts +82 -0
  754. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +293 -0
  755. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +385 -0
  756. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +286 -0
  757. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +838 -0
  758. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +627 -0
  759. package/src/hooks/__tests__/useRBAC.unit.test.ts +903 -0
  760. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +537 -0
  761. package/src/hooks/__tests__/useToast.unit.test.tsx +62 -0
  762. package/src/hooks/__tests__/useZodForm.unit.test.tsx +37 -0
  763. package/src/hooks/index.ts +56 -0
  764. package/src/hooks/public/__tests__/usePublicEvent.test.tsx +397 -0
  765. package/src/hooks/public/__tests__/usePublicEventLogo.test.tsx +690 -0
  766. package/src/hooks/public/__tests__/usePublicRouteParams.test.tsx +449 -0
  767. package/src/hooks/public/index.ts +34 -0
  768. package/src/hooks/public/usePublicEvent.ts +261 -0
  769. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  770. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  771. package/src/hooks/useAppConfig.ts +94 -0
  772. package/src/hooks/useComponentPerformance.ts +39 -0
  773. package/src/hooks/useDataTablePerformance.ts +387 -0
  774. package/src/hooks/useDataTableState.ts +110 -0
  775. package/src/hooks/useDebounce.ts +18 -0
  776. package/src/hooks/useFocusManagement.ts +161 -0
  777. package/src/hooks/useFocusTrap.ts +155 -0
  778. package/src/hooks/useInactivityTracker.ts +372 -0
  779. package/src/hooks/useIsMobile.ts +42 -0
  780. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  781. package/src/hooks/useOrganisationPermissions.ts +208 -0
  782. package/src/hooks/useOrganisationSecurity.ts +262 -0
  783. package/src/hooks/usePerformanceMonitor.ts +128 -0
  784. package/src/hooks/usePermissionCache.ts +455 -0
  785. package/src/hooks/useRBAC.ts +262 -0
  786. package/src/hooks/useSecureDataAccess.ts +586 -0
  787. package/src/hooks/useStorage.ts +274 -0
  788. package/src/hooks/useToast.ts +242 -0
  789. package/src/hooks/useZodForm.ts +28 -0
  790. package/src/index.ts +200 -0
  791. package/src/providers/AuthProvider.tsx +369 -0
  792. package/src/providers/EventProvider.tsx +324 -0
  793. package/src/providers/InactivityProvider.tsx +238 -0
  794. package/src/providers/OrganisationProvider.tsx +588 -0
  795. package/src/providers/RBACProvider.tsx +622 -0
  796. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  797. package/src/providers/__tests__/EventProvider.unit.test.tsx +768 -0
  798. package/src/providers/__tests__/OrganisationProvider.basic.test.tsx +116 -0
  799. package/src/providers/__tests__/OrganisationProvider.unit.test.tsx +1312 -0
  800. package/src/providers/__tests__/UnifiedAuthProvider.inactivity.test.tsx +601 -0
  801. package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +675 -0
  802. package/src/providers/__tests__/index.unit.test.ts +78 -0
  803. package/src/providers/index.ts +15 -0
  804. package/src/rbac/README.md +885 -0
  805. package/src/rbac/__tests__/PagePermissionGuard.test.tsx +673 -0
  806. package/src/rbac/__tests__/README.md +170 -0
  807. package/src/rbac/__tests__/RoleBasedRouter.test.tsx +709 -0
  808. package/src/rbac/__tests__/TestContext.tsx +72 -0
  809. package/src/rbac/__tests__/__mocks__/cache.ts +144 -0
  810. package/src/rbac/__tests__/__mocks__/supabase.ts +152 -0
  811. package/src/rbac/__tests__/adapters-hooks-comprehensive.test.tsx +782 -0
  812. package/src/rbac/__tests__/adapters-hooks.test.tsx +561 -0
  813. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +963 -0
  814. package/src/rbac/__tests__/adapters.test.tsx +444 -0
  815. package/src/rbac/__tests__/api.test.ts +620 -0
  816. package/src/rbac/__tests__/audit-observability-comprehensive.test.ts +792 -0
  817. package/src/rbac/__tests__/audit-observability.test.ts +549 -0
  818. package/src/rbac/__tests__/audit.test.ts +616 -0
  819. package/src/rbac/__tests__/build-contract-compliance-simple.test.ts +230 -0
  820. package/src/rbac/__tests__/cache-invalidation-comprehensive.test.ts +889 -0
  821. package/src/rbac/__tests__/cache-invalidation.test.ts +457 -0
  822. package/src/rbac/__tests__/cache.test.ts +458 -0
  823. package/src/rbac/__tests__/components-navigation-guard.enhanced.test.tsx +859 -0
  824. package/src/rbac/__tests__/components-navigation-guard.test.tsx +895 -0
  825. package/src/rbac/__tests__/components-navigation-provider.test.tsx +692 -0
  826. package/src/rbac/__tests__/components-page-permission-guard.test.tsx +673 -0
  827. package/src/rbac/__tests__/components-page-permission-provider.test.tsx +614 -0
  828. package/src/rbac/__tests__/components-permission-enforcer.enhanced.fixed.test.tsx +836 -0
  829. package/src/rbac/__tests__/components-permission-enforcer.enhanced.test.tsx +837 -0
  830. package/src/rbac/__tests__/components-permission-enforcer.test.tsx +825 -0
  831. package/src/rbac/__tests__/components-role-based-router.test.tsx +709 -0
  832. package/src/rbac/__tests__/components-secure-data-provider.test.tsx +607 -0
  833. package/src/rbac/__tests__/config.test.ts +583 -0
  834. package/src/rbac/__tests__/core-logic-unit.test.ts +190 -0
  835. package/src/rbac/__tests__/core-permission-logic-comprehensive.test.ts +1467 -0
  836. package/src/rbac/__tests__/core-permission-logic-fixed.test.ts +151 -0
  837. package/src/rbac/__tests__/core-permission-logic-simple.test.ts +968 -0
  838. package/src/rbac/__tests__/core-permission-logic.test.ts +966 -0
  839. package/src/rbac/__tests__/edge-cases-comprehensive.test.ts +988 -0
  840. package/src/rbac/__tests__/edge-cases.test.ts +654 -0
  841. package/src/rbac/__tests__/engine.test.ts +361 -0
  842. package/src/rbac/__tests__/engine.unit.test.ts +361 -0
  843. package/src/rbac/__tests__/hooks.enhanced.test.tsx +979 -0
  844. package/src/rbac/__tests__/hooks.fixed.test.tsx +475 -0
  845. package/src/rbac/__tests__/hooks.test.tsx +385 -0
  846. package/src/rbac/__tests__/index.test.ts +269 -0
  847. package/src/rbac/__tests__/integration.enhanced.test.tsx +824 -0
  848. package/src/rbac/__tests__/page-permission-guard-super-admin.test.tsx +261 -0
  849. package/src/rbac/__tests__/performance.enhanced.test.tsx +724 -0
  850. package/src/rbac/__tests__/permissions.test.ts +383 -0
  851. package/src/rbac/__tests__/requires-event.test.ts +330 -0
  852. package/src/rbac/__tests__/scope-isolation-comprehensive.test.ts +1349 -0
  853. package/src/rbac/__tests__/scope-isolation.test.ts +755 -0
  854. package/src/rbac/__tests__/secure-client-rls-comprehensive.test.ts +592 -0
  855. package/src/rbac/__tests__/secure-client-rls.test.ts +377 -0
  856. package/src/rbac/__tests__/security.test.ts +296 -0
  857. package/src/rbac/__tests__/setup.ts +228 -0
  858. package/src/rbac/__tests__/test-utils-enhanced.tsx +400 -0
  859. package/src/rbac/__tests__/types.test.ts +685 -0
  860. package/src/rbac/adapters.tsx +726 -0
  861. package/src/rbac/api.ts +337 -0
  862. package/src/rbac/audit-enhanced.ts +339 -0
  863. package/src/rbac/audit.ts +338 -0
  864. package/src/rbac/cache.ts +213 -0
  865. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  866. package/src/rbac/components/NavigationGuard.tsx +294 -0
  867. package/src/rbac/components/NavigationProvider.tsx +314 -0
  868. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  869. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  870. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  871. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  872. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  873. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +631 -0
  874. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +667 -0
  875. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +647 -0
  876. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +496 -0
  877. package/src/rbac/components/index.ts +64 -0
  878. package/src/rbac/config.ts +133 -0
  879. package/src/rbac/docs/event-based-apps.md +285 -0
  880. package/src/rbac/engine.ts +1026 -0
  881. package/src/rbac/eslint-rules.js +285 -0
  882. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  883. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  884. package/src/rbac/hooks.ts +555 -0
  885. package/src/rbac/index.ts +114 -0
  886. package/src/rbac/permissions.ts +293 -0
  887. package/src/rbac/secureClient.ts +244 -0
  888. package/src/rbac/security.ts +346 -0
  889. package/src/rbac/testing/__tests__/index.test.tsx +342 -0
  890. package/src/rbac/testing/index.tsx +340 -0
  891. package/src/rbac/types.ts +341 -0
  892. package/src/rbac/utils/__tests__/eventContext.test.ts +428 -0
  893. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +428 -0
  894. package/src/rbac/utils/eventContext.ts +83 -0
  895. package/src/styles/__tests__/styles.unit.test.ts +164 -0
  896. package/src/styles/core.css +401 -0
  897. package/src/styles/index.ts +51 -0
  898. package/src/test-dom-cleanup.test.tsx +38 -0
  899. package/src/theming/__tests__/README.md +335 -0
  900. package/src/theming/__tests__/runtime.accessibility.test.ts +474 -0
  901. package/src/theming/__tests__/runtime.error.test.ts +616 -0
  902. package/src/theming/__tests__/runtime.integration.test.ts +376 -0
  903. package/src/theming/__tests__/runtime.performance.test.ts +411 -0
  904. package/src/theming/__tests__/runtime.unit.test.ts +470 -0
  905. package/src/theming/runtime.ts +187 -0
  906. package/src/types/__tests__/database.unit.test.ts +489 -0
  907. package/src/types/__tests__/guards.unit.test.ts +146 -0
  908. package/src/types/__tests__/index.unit.test.ts +77 -0
  909. package/src/types/__tests__/organisation.unit.test.ts +713 -0
  910. package/src/types/__tests__/rbac.unit.test.ts +621 -0
  911. package/src/types/__tests__/security.unit.test.ts +347 -0
  912. package/src/types/__tests__/supabase.unit.test.ts +658 -0
  913. package/src/types/__tests__/theme.unit.test.ts +218 -0
  914. package/src/types/__tests__/unified.unit.test.ts +537 -0
  915. package/src/types/__tests__/validation.unit.test.ts +616 -0
  916. package/src/types/database.ts +472 -0
  917. package/src/types/guards.ts +30 -0
  918. package/src/types/index.ts +25 -0
  919. package/src/types/organisation.ts +184 -0
  920. package/src/types/security.ts +70 -0
  921. package/src/types/supabase.ts +166 -0
  922. package/src/types/theme.ts +6 -0
  923. package/src/types/unified.ts +262 -0
  924. package/src/types/validation.ts +164 -0
  925. package/src/types/vitest-globals.d.ts +43 -0
  926. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  927. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  928. package/src/utils/__tests__/appConfig.unit.test.ts +55 -0
  929. package/src/utils/__tests__/appNameResolver.unit.test.ts +137 -0
  930. package/src/utils/__tests__/audit.unit.test.ts +69 -0
  931. package/src/utils/__tests__/auth-utils.unit.test.ts +70 -0
  932. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +317 -0
  933. package/src/utils/__tests__/cn.unit.test.ts +34 -0
  934. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +480 -0
  935. package/src/utils/__tests__/dynamicUtils.unit.test.ts +322 -0
  936. package/src/utils/__tests__/formatDate.unit.test.ts +109 -0
  937. package/src/utils/__tests__/formatting.unit.test.ts +66 -0
  938. package/src/utils/__tests__/index.unit.test.ts +251 -0
  939. package/src/utils/__tests__/lazyLoad.unit.test.tsx +309 -0
  940. package/src/utils/__tests__/organisationContext.unit.test.ts +192 -0
  941. package/src/utils/__tests__/performanceBudgets.unit.test.ts +259 -0
  942. package/src/utils/__tests__/permissionTypes.unit.test.ts +250 -0
  943. package/src/utils/__tests__/permissionUtils.unit.test.ts +362 -0
  944. package/src/utils/__tests__/sanitization.unit.test.ts +346 -0
  945. package/src/utils/__tests__/schemaUtils.unit.test.ts +441 -0
  946. package/src/utils/__tests__/secureDataAccess.unit.test.ts +334 -0
  947. package/src/utils/__tests__/secureErrors.unit.test.ts +377 -0
  948. package/src/utils/__tests__/secureStorage.unit.test.ts +293 -0
  949. package/src/utils/__tests__/security.unit.test.ts +127 -0
  950. package/src/utils/__tests__/securityMonitor.unit.test.ts +280 -0
  951. package/src/utils/__tests__/sessionTracking.unit.test.ts +370 -0
  952. package/src/utils/__tests__/validation.unit.test.ts +84 -0
  953. package/src/utils/__tests__/validationUtils.unit.test.ts +571 -0
  954. package/src/utils/appConfig.ts +47 -0
  955. package/src/utils/appIdResolver.ts +130 -0
  956. package/src/utils/appNameResolver.ts +190 -0
  957. package/src/utils/audit.ts +127 -0
  958. package/src/utils/auth-utils.ts +96 -0
  959. package/src/utils/bundleAnalysis.ts +129 -0
  960. package/src/utils/cn.ts +7 -0
  961. package/src/utils/debugLogger.ts +46 -0
  962. package/src/utils/deviceFingerprint.ts +215 -0
  963. package/src/utils/dynamicUtils.ts +105 -0
  964. package/src/utils/formatting.ts +77 -0
  965. package/src/utils/index.ts +145 -0
  966. package/src/utils/lazyLoad.tsx +44 -0
  967. package/src/utils/organisationContext.ts +135 -0
  968. package/src/utils/performanceBenchmark.ts +64 -0
  969. package/src/utils/performanceBudgets.ts +111 -0
  970. package/src/utils/permissionTypes.ts +37 -0
  971. package/src/utils/permissionUtils.ts +31 -0
  972. package/src/utils/print/PrintDataProcessor.ts +390 -0
  973. package/src/utils/print/__tests__/PrintDataProcessor.unit.test.ts +219 -0
  974. package/src/utils/print/__tests__/usePrintOptimization.unit.test.tsx +353 -0
  975. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  976. package/src/utils/print/index.ts +29 -0
  977. package/src/utils/print/types.ts +196 -0
  978. package/src/utils/print/usePrintOptimization.ts +272 -0
  979. package/src/utils/sanitization.ts +264 -0
  980. package/src/utils/schemaUtils.ts +37 -0
  981. package/src/utils/secureDataAccess.ts +361 -0
  982. package/src/utils/secureErrors.ts +79 -0
  983. package/src/utils/secureStorage.ts +244 -0
  984. package/src/utils/security.ts +156 -0
  985. package/src/utils/securityMonitor.ts +45 -0
  986. package/src/utils/sessionTracking.ts +170 -0
  987. package/src/utils/storage/README.md +348 -0
  988. package/src/utils/storage/__tests__/config.unit.test.ts +206 -0
  989. package/src/utils/storage/__tests__/helpers.unit.test.ts +646 -0
  990. package/src/utils/storage/__tests__/index.unit.test.ts +167 -0
  991. package/src/utils/storage/__tests__/types.unit.test.ts +441 -0
  992. package/src/utils/storage/config.ts +100 -0
  993. package/src/utils/storage/helpers.ts +359 -0
  994. package/src/utils/storage/index.ts +36 -0
  995. package/src/utils/storage/types.ts +90 -0
  996. package/src/utils/validation.ts +111 -0
  997. package/src/utils/validationUtils.ts +120 -0
  998. package/src/validation/__tests__/common.unit.test.ts +101 -0
  999. package/src/validation/__tests__/csrf.unit.test.ts +302 -0
  1000. package/src/validation/__tests__/passwordSchema.unit.test.ts +98 -0
  1001. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +466 -0
  1002. package/src/validation/common.ts +53 -0
  1003. package/src/validation/csrf.ts +214 -0
  1004. package/src/validation/index.ts +43 -0
  1005. package/src/validation/passwordSchema.ts +125 -0
  1006. package/src/validation/sanitization.ts +96 -0
  1007. package/src/validation/schemaUtils.ts +42 -0
  1008. package/src/validation/sqlInjectionProtection.ts +242 -0
  1009. package/src/validation/user.ts +34 -0
@@ -0,0 +1,3344 @@
1
+ import {
2
+ Alert,
3
+ AlertDescription,
4
+ Input,
5
+ Select,
6
+ SelectContent,
7
+ SelectItem,
8
+ SelectLabel,
9
+ SelectSeparator,
10
+ SelectTrigger,
11
+ SelectValue
12
+ } from "./chunk-WYB6MBZA.js";
13
+ import {
14
+ isPermitted
15
+ } from "./chunk-6ZQVSHKL.js";
16
+ import {
17
+ EventProvider_exports,
18
+ init_EventProvider,
19
+ useEvents
20
+ } from "./chunk-TMRLB2LA.js";
21
+ import {
22
+ PublicErrorBoundary,
23
+ useAppConfig,
24
+ usePublicEventLogo,
25
+ usePublicPageContext
26
+ } from "./chunk-2MKP6IYD.js";
27
+ import {
28
+ OrganisationProvider_exports,
29
+ UnifiedAuthProvider_exports,
30
+ init_OrganisationProvider,
31
+ init_UnifiedAuthProvider,
32
+ useOrganisations,
33
+ useUnifiedAuth
34
+ } from "./chunk-DY5E3AT7.js";
35
+ import {
36
+ Button,
37
+ Dialog,
38
+ DialogContent,
39
+ DialogHeader,
40
+ DialogOverlay,
41
+ DialogTitle,
42
+ DialogTrigger,
43
+ init_Button
44
+ } from "./chunk-ETEJVKYK.js";
45
+ import {
46
+ LoadingSpinner
47
+ } from "./chunk-CDQ3PX7L.js";
48
+ import {
49
+ performanceBudgetMonitor
50
+ } from "./chunk-74C6SNEC.js";
51
+ import {
52
+ cn,
53
+ init_cn
54
+ } from "./chunk-OHXGNT3K.js";
55
+ import {
56
+ __require,
57
+ __toCommonJS
58
+ } from "./chunk-PLDDJCW6.js";
59
+
60
+ // src/components/Card/Card.tsx
61
+ init_cn();
62
+ import * as React from "react";
63
+ import { jsx } from "react/jsx-runtime";
64
+ function getCardClasses(variant = "default", size = "default") {
65
+ const baseClasses = "rounded-lg border bg-card text-card-foreground shadow-sm";
66
+ const variantClasses = {
67
+ default: "shadow-xl",
68
+ outline: "border-2",
69
+ ghost: "border-0 shadow-none"
70
+ };
71
+ const sizeClasses3 = {
72
+ default: "",
73
+ sm: "text-sm",
74
+ lg: "text-lg"
75
+ };
76
+ return `${baseClasses} ${variantClasses[variant]} ${sizeClasses3[size]}`;
77
+ }
78
+ var Card = React.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
79
+ "article",
80
+ {
81
+ ref,
82
+ className: cn(
83
+ "grid grid-rows-[auto_1fr_auto] min-w-0 overflow-visible",
84
+ getCardClasses(variant, size),
85
+ className
86
+ ),
87
+ ...props
88
+ }
89
+ ));
90
+ Card.displayName = "Card";
91
+ var CardHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
92
+ "header",
93
+ {
94
+ ref,
95
+ className: cn("flex flex-col space-y-1.5 p-6 min-w-0 w-full", className),
96
+ ...props
97
+ }
98
+ ));
99
+ CardHeader.displayName = "CardHeader";
100
+ var CardTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
101
+ "h3",
102
+ {
103
+ ref,
104
+ className: cn(
105
+ "text-2xl font-semibold leading-none tracking-tight",
106
+ className
107
+ ),
108
+ ...props
109
+ }
110
+ ));
111
+ CardTitle.displayName = "CardTitle";
112
+ var CardDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
113
+ "p",
114
+ {
115
+ ref,
116
+ className: cn(className),
117
+ ...props
118
+ }
119
+ ));
120
+ CardDescription.displayName = "CardDescription";
121
+ var CardContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
122
+ "main",
123
+ {
124
+ ref,
125
+ className: cn("p-6 pt-0 min-w-0 w-full", className),
126
+ ...props
127
+ }
128
+ ));
129
+ CardContent.displayName = "CardContent";
130
+ var CardFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
131
+ "footer",
132
+ {
133
+ ref,
134
+ className: cn("flex items-center p-6 pt-0 min-w-0 w-full", className),
135
+ ...props
136
+ }
137
+ ));
138
+ CardFooter.displayName = "CardFooter";
139
+ var CardActions = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
140
+ "nav",
141
+ {
142
+ ref,
143
+ className: cn("flex gap-2", className),
144
+ role: "group",
145
+ "aria-label": "Card actions",
146
+ ...props
147
+ }
148
+ ));
149
+ CardActions.displayName = "CardActions";
150
+ var HoverCard = React.forwardRef(({ children, className, ...props }, ref) => {
151
+ return /* @__PURE__ */ jsx(
152
+ "section",
153
+ {
154
+ ref,
155
+ className: cn("relative inline-block", className),
156
+ ...props,
157
+ children
158
+ }
159
+ );
160
+ });
161
+ HoverCard.displayName = "HoverCard";
162
+ var HoverCardTrigger = React.forwardRef(({ className, asChild, children, ...props }, ref) => {
163
+ if (asChild) {
164
+ return /* @__PURE__ */ jsx("span", { className: cn("cursor-pointer", className), children });
165
+ }
166
+ return /* @__PURE__ */ jsx(
167
+ "button",
168
+ {
169
+ ref,
170
+ type: "button",
171
+ className: cn(
172
+ "cursor-pointer bg-transparent border-0 p-0 m-0 font-inherit color-inherit text-left",
173
+ className
174
+ ),
175
+ ...props,
176
+ children
177
+ }
178
+ );
179
+ });
180
+ HoverCardTrigger.displayName = "HoverCardTrigger";
181
+ var HoverCardContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
182
+ "aside",
183
+ {
184
+ ref,
185
+ className: cn(
186
+ "absolute z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-4 text-popover-foreground shadow-md",
187
+ className
188
+ ),
189
+ role: "tooltip",
190
+ ...props
191
+ }
192
+ ));
193
+ HoverCardContent.displayName = "HoverCardContent";
194
+
195
+ // src/components/Label/Label.tsx
196
+ init_cn();
197
+ import * as React2 from "react";
198
+ import * as LabelPrimitive from "@radix-ui/react-label";
199
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
200
+ var getLabelClasses = () => {
201
+ return "font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70";
202
+ };
203
+ var Label = React2.forwardRef(({
204
+ className,
205
+ required = false,
206
+ requiredIndicator,
207
+ hideRequiredIndicator = false,
208
+ helperText,
209
+ helperTextClassName,
210
+ error,
211
+ errorClassName,
212
+ children,
213
+ htmlFor,
214
+ ...props
215
+ }, ref) => {
216
+ const hasError = !!error;
217
+ const showHelperText = helperText && !hasError;
218
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
219
+ /* @__PURE__ */ jsxs(
220
+ LabelPrimitive.Root,
221
+ {
222
+ ref,
223
+ className: cn(
224
+ getLabelClasses(),
225
+ hasError && "text-destructive",
226
+ className
227
+ ),
228
+ htmlFor,
229
+ ...props,
230
+ children: [
231
+ children,
232
+ required && /* @__PURE__ */ jsx2(
233
+ "label",
234
+ {
235
+ "aria-label": "required",
236
+ className: cn(
237
+ "text-destructive ml-1",
238
+ hideRequiredIndicator && "sr-only"
239
+ ),
240
+ children: requiredIndicator || "*"
241
+ }
242
+ )
243
+ ]
244
+ }
245
+ ),
246
+ showHelperText && /* @__PURE__ */ jsx2("p", { className: cn("text-muted-foreground", helperTextClassName), children: helperText }),
247
+ hasError && /* @__PURE__ */ jsx2(
248
+ "p",
249
+ {
250
+ role: "alert",
251
+ "aria-live": "polite",
252
+ className: cn("text-destructive", errorClassName),
253
+ children: error
254
+ }
255
+ )
256
+ ] });
257
+ });
258
+ Label.displayName = LabelPrimitive.Root.displayName;
259
+
260
+ // src/components/Avatar/Avatar.tsx
261
+ init_cn();
262
+ import * as React3 from "react";
263
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
264
+ import { jsx as jsx3 } from "react/jsx-runtime";
265
+ var Avatar = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
266
+ AvatarPrimitive.Root,
267
+ {
268
+ ref,
269
+ className: cn(
270
+ "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
271
+ className
272
+ ),
273
+ ...props
274
+ }
275
+ ));
276
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
277
+ var AvatarImage = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
278
+ AvatarPrimitive.Image,
279
+ {
280
+ ref,
281
+ className: cn("object-cover", className),
282
+ ...props
283
+ }
284
+ ));
285
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
286
+ var AvatarFallback = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
287
+ AvatarPrimitive.Fallback,
288
+ {
289
+ ref,
290
+ className: cn(
291
+ "flex h-full w-full items-center justify-center rounded-full text-sec-50 bg-sec-500",
292
+ className
293
+ ),
294
+ ...props
295
+ }
296
+ ));
297
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
298
+
299
+ // src/components/Progress/Progress.tsx
300
+ init_cn();
301
+ import * as React4 from "react";
302
+ import * as ProgressPrimitive from "@radix-ui/react-progress";
303
+ import { jsx as jsx4 } from "react/jsx-runtime";
304
+ var Progress = React4.forwardRef(({ className, value, max = 100, ...props }, ref) => /* @__PURE__ */ jsx4(
305
+ ProgressPrimitive.Root,
306
+ {
307
+ ref,
308
+ className: cn(
309
+ "relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
310
+ className
311
+ ),
312
+ ...props,
313
+ value,
314
+ max,
315
+ "aria-valuenow": value,
316
+ "aria-valuemax": max,
317
+ "aria-valuemin": 0,
318
+ children: /* @__PURE__ */ jsx4(
319
+ ProgressPrimitive.Indicator,
320
+ {
321
+ className: "h-full w-full flex-1 bg-primary transition-all",
322
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
323
+ }
324
+ )
325
+ }
326
+ ));
327
+ Progress.displayName = ProgressPrimitive.Root.displayName;
328
+
329
+ // src/components/Toast/Toast.tsx
330
+ init_cn();
331
+ import * as React5 from "react";
332
+ import * as ToastPrimitives from "@radix-ui/react-toast";
333
+ import { X } from "lucide-react";
334
+ import { jsx as jsx5 } from "react/jsx-runtime";
335
+ var ToastProvider = ToastPrimitives.Provider;
336
+ var ToastViewport = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
337
+ ToastPrimitives.Viewport,
338
+ {
339
+ ref,
340
+ "data-testid": "toast-viewport",
341
+ className: cn(
342
+ "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
343
+ className
344
+ ),
345
+ ...props
346
+ }
347
+ ));
348
+ ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
349
+ var Toast = React5.forwardRef(({ className, ...props }, ref) => {
350
+ return /* @__PURE__ */ jsx5(
351
+ ToastPrimitives.Root,
352
+ {
353
+ ref,
354
+ "data-testid": "toast-root",
355
+ className: cn(
356
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
357
+ className
358
+ ),
359
+ ...props
360
+ }
361
+ );
362
+ });
363
+ Toast.displayName = ToastPrimitives.Root.displayName;
364
+ var ToastAction = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
365
+ ToastPrimitives.Action,
366
+ {
367
+ ref,
368
+ "data-testid": "toast-action",
369
+ className: cn(
370
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
371
+ className
372
+ ),
373
+ ...props
374
+ }
375
+ ));
376
+ ToastAction.displayName = ToastPrimitives.Action.displayName;
377
+ var ToastClose = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
378
+ ToastPrimitives.Close,
379
+ {
380
+ ref,
381
+ "data-testid": "toast-close",
382
+ className: cn(
383
+ "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-acc-300 group-[.destructive]:hover:text-acc-50 group-[.destructive]:focus:ring-acc-400 group-[.destructive]:focus:ring-offset-acc-600",
384
+ className
385
+ ),
386
+ "toast-close": "",
387
+ ...props,
388
+ children: /* @__PURE__ */ jsx5(X, { className: "h-4 w-4" })
389
+ }
390
+ ));
391
+ ToastClose.displayName = ToastPrimitives.Close.displayName;
392
+ var ToastTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
393
+ ToastPrimitives.Title,
394
+ {
395
+ ref,
396
+ "data-testid": "toast-title",
397
+ className: cn("text-sm font-semibold", className),
398
+ ...props
399
+ }
400
+ ));
401
+ ToastTitle.displayName = ToastPrimitives.Title.displayName;
402
+ var ToastDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(
403
+ ToastPrimitives.Description,
404
+ {
405
+ ref,
406
+ "data-testid": "toast-description",
407
+ className: cn("text-sm opacity-90", className),
408
+ ...props
409
+ }
410
+ ));
411
+ ToastDescription.displayName = ToastPrimitives.Description.displayName;
412
+ function useToast() {
413
+ return {
414
+ toast: (props) => {
415
+ console.log("Toast:", props);
416
+ },
417
+ dismiss: () => {
418
+ console.log("Toast dismissed");
419
+ }
420
+ };
421
+ }
422
+ function Toaster() {
423
+ return /* @__PURE__ */ jsx5(ToastProvider, { "data-testid": "toast-provider", children: /* @__PURE__ */ jsx5(ToastViewport, {}) });
424
+ }
425
+
426
+ // src/components/Form/Form.tsx
427
+ init_cn();
428
+ import { useForm, FormProvider } from "react-hook-form";
429
+ import { zodResolver } from "@hookform/resolvers/zod";
430
+ import { jsx as jsx6 } from "react/jsx-runtime";
431
+ function Form({
432
+ schema,
433
+ defaultValues,
434
+ onSubmit,
435
+ onError,
436
+ mode = "onSubmit",
437
+ children,
438
+ className
439
+ }) {
440
+ const methods = useForm({
441
+ resolver: schema ? zodResolver(schema) : void 0,
442
+ defaultValues,
443
+ mode
444
+ });
445
+ const handleSubmit = methods.handleSubmit(onSubmit, onError);
446
+ return /* @__PURE__ */ jsx6(FormProvider, { ...methods, children: /* @__PURE__ */ jsx6("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: typeof children === "function" ? children(methods) : children }) });
447
+ }
448
+
449
+ // src/components/LoginForm/LoginForm.tsx
450
+ init_Button();
451
+ import React6, { useState, useCallback, useMemo } from "react";
452
+ init_cn();
453
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
454
+ var LoginForm = React6.memo(({
455
+ onSignIn,
456
+ onSuccess,
457
+ onError,
458
+ isLoading = false,
459
+ appName,
460
+ title,
461
+ subtitle,
462
+ showSignUp = false,
463
+ onSignUp,
464
+ className
465
+ }) => {
466
+ const [formData, setFormData] = useState({ email: "", password: "" });
467
+ const [error, setError] = useState(null);
468
+ const isFormValid = useMemo(() => {
469
+ return formData.email.length > 0 && formData.password.length > 0;
470
+ }, [formData.email, formData.password]);
471
+ const handleEmailChange = useCallback((e) => {
472
+ setFormData((prev) => ({ ...prev, email: e.target.value }));
473
+ }, []);
474
+ const handlePasswordChange = useCallback((e) => {
475
+ setFormData((prev) => ({ ...prev, password: e.target.value }));
476
+ }, []);
477
+ const handleSubmit = useCallback(async (e) => {
478
+ e.preventDefault();
479
+ setError(null);
480
+ if (!isFormValid || isLoading) return;
481
+ try {
482
+ await onSignIn(formData);
483
+ onSuccess?.();
484
+ } catch (err) {
485
+ const errorMessage = err instanceof Error ? err.message : "Sign in failed";
486
+ setError(errorMessage);
487
+ onError?.(err instanceof Error ? err : new Error(errorMessage));
488
+ }
489
+ }, [formData, isFormValid, isLoading, onSignIn, onSuccess, onError]);
490
+ const handleSignUpClick = useCallback(() => {
491
+ onSignUp?.();
492
+ }, [onSignUp]);
493
+ const displayTitle = useMemo(() => title || (appName ? `Sign in to ${appName}` : "Sign In"), [title, appName]);
494
+ const displaySubtitle = useMemo(() => subtitle || "Enter your credentials to continue.", [subtitle]);
495
+ return /* @__PURE__ */ jsx7(Card, { className: cn("w-full max-w-md mx-auto", className), children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, "data-testid": "login-form", children: [
496
+ /* @__PURE__ */ jsxs2(CardHeader, { className: "space-y-1", children: [
497
+ /* @__PURE__ */ jsx7(CardTitle, { className: "text-2xl text-center", children: displayTitle }),
498
+ /* @__PURE__ */ jsx7(CardDescription, { className: "text-center", children: displaySubtitle })
499
+ ] }),
500
+ /* @__PURE__ */ jsxs2(CardContent, { className: "space-y-4", children: [
501
+ error && /* @__PURE__ */ jsx7(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx7(AlertDescription, { children: error }) }),
502
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "email", children: "Email" }),
503
+ /* @__PURE__ */ jsx7(
504
+ Input,
505
+ {
506
+ id: "email",
507
+ type: "email",
508
+ placeholder: "Enter your email",
509
+ value: formData.email,
510
+ onChange: handleEmailChange,
511
+ required: true,
512
+ disabled: isLoading
513
+ }
514
+ ),
515
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "password", children: "Password" }),
516
+ /* @__PURE__ */ jsx7(
517
+ Input,
518
+ {
519
+ id: "password",
520
+ type: "password",
521
+ placeholder: "Enter your password",
522
+ value: formData.password,
523
+ onChange: handlePasswordChange,
524
+ required: true,
525
+ disabled: isLoading
526
+ }
527
+ )
528
+ ] }),
529
+ /* @__PURE__ */ jsxs2(CardFooter, { className: "flex flex-col space-y-4", children: [
530
+ /* @__PURE__ */ jsx7(
531
+ Button,
532
+ {
533
+ type: "submit",
534
+ className: "w-full",
535
+ disabled: isLoading || !isFormValid,
536
+ children: isLoading ? "Signing in..." : "Sign In"
537
+ }
538
+ ),
539
+ showSignUp && (onSignUp ? /* @__PURE__ */ jsx7("div", { className: "text-sm text-center text-muted-foreground", children: /* @__PURE__ */ jsx7(
540
+ "button",
541
+ {
542
+ type: "button",
543
+ onClick: handleSignUpClick,
544
+ className: "text-primary hover:underline",
545
+ children: "Don't have an account? Sign up"
546
+ }
547
+ ) }) : /* @__PURE__ */ jsxs2("p", { className: "text-center text-muted-foreground", children: [
548
+ "Don't have an account?",
549
+ " ",
550
+ /* @__PURE__ */ jsx7("a", { href: "/signup", className: "text-primary hover:underline", children: "Sign up" })
551
+ ] }))
552
+ ] })
553
+ ] }) });
554
+ });
555
+
556
+ // src/components/EventSelector/EventSelector.tsx
557
+ init_Button();
558
+ init_EventProvider();
559
+ import { RefreshCw, AlertCircle, Lock, Calendar, Star } from "lucide-react";
560
+ import { useEffect, useMemo as useMemo2 } from "react";
561
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
562
+ function EventSelector({
563
+ placeholder = "Select an event",
564
+ className,
565
+ onEventChange,
566
+ showNoEventsMessage = true,
567
+ showRetryButton = true,
568
+ showEventDetails = true,
569
+ showNextEventIndicator = true
570
+ }) {
571
+ const {
572
+ events,
573
+ selectedEvent,
574
+ isLoading,
575
+ error,
576
+ setSelectedEvent,
577
+ refreshEvents
578
+ } = useEvents();
579
+ const handleValueChange = (eventId) => {
580
+ const event = events.find((e) => (e.event_id || e.id) === eventId);
581
+ if (event) {
582
+ setSelectedEvent(event);
583
+ if (onEventChange) {
584
+ onEventChange(event);
585
+ }
586
+ }
587
+ };
588
+ const handleRetry = () => {
589
+ refreshEvents();
590
+ };
591
+ const isNextEvent = (event) => {
592
+ if (!event.event_date) return false;
593
+ const now = /* @__PURE__ */ new Date();
594
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
595
+ const eventDate = new Date(event.event_date);
596
+ return eventDate >= today;
597
+ };
598
+ const formatEventDate = (dateString) => {
599
+ const date = new Date(dateString);
600
+ const today = /* @__PURE__ */ new Date();
601
+ const tomorrow = new Date(today);
602
+ tomorrow.setDate(tomorrow.getDate() + 1);
603
+ const normalizeDate = (d) => {
604
+ const normalized = new Date(d);
605
+ normalized.setHours(0, 0, 0, 0);
606
+ return normalized;
607
+ };
608
+ const normalizedDate = normalizeDate(date);
609
+ const normalizedToday = normalizeDate(today);
610
+ const normalizedTomorrow = normalizeDate(tomorrow);
611
+ if (normalizedDate.getTime() === normalizedToday.getTime()) {
612
+ return "Today";
613
+ } else if (normalizedDate.getTime() === normalizedTomorrow.getTime()) {
614
+ return "Tomorrow";
615
+ } else {
616
+ return date.toLocaleDateString();
617
+ }
618
+ };
619
+ const sortedEvents = useMemo2(() => {
620
+ const getTime = (e) => e.event_date ? new Date(e.event_date).getTime() : Number.NEGATIVE_INFINITY;
621
+ return [...events].sort((a, b) => getTime(b) - getTime(a));
622
+ }, [events]);
623
+ useEffect(() => {
624
+ if (!selectedEvent && events.length > 0) {
625
+ const today = /* @__PURE__ */ new Date();
626
+ const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
627
+ const next = [...events].filter((e) => e.event_date && new Date(e.event_date).getTime() >= startOfToday).sort((a, b) => new Date(a.event_date).getTime() - new Date(b.event_date).getTime())[0];
628
+ if (next) {
629
+ setSelectedEvent(next);
630
+ if (onEventChange) onEventChange(next);
631
+ }
632
+ }
633
+ }, [events, selectedEvent, setSelectedEvent, onEventChange]);
634
+ if (isLoading) {
635
+ return /* @__PURE__ */ jsxs3("div", { className: `flex items-center gap-2 ${className}`, children: [
636
+ /* @__PURE__ */ jsx8(LoadingSpinner, { size: "sm" }),
637
+ /* @__PURE__ */ jsx8("span", { className: "text-sm text-muted-foreground", children: "Loading events..." })
638
+ ] });
639
+ }
640
+ if (error) {
641
+ return /* @__PURE__ */ jsx8("div", { className, children: /* @__PURE__ */ jsxs3(Alert, { variant: "destructive", children: [
642
+ /* @__PURE__ */ jsx8(Lock, { className: "h-4 w-4" }),
643
+ /* @__PURE__ */ jsxs3(AlertDescription, { className: "flex items-center justify-between", children: [
644
+ /* @__PURE__ */ jsx8("span", { children: error.message }),
645
+ showRetryButton && /* @__PURE__ */ jsxs3(
646
+ Button,
647
+ {
648
+ variant: "outline",
649
+ size: "sm",
650
+ onClick: handleRetry,
651
+ className: "ml-2",
652
+ children: [
653
+ /* @__PURE__ */ jsx8(RefreshCw, { className: "h-3 w-3 mr-1" }),
654
+ "Retry"
655
+ ]
656
+ }
657
+ )
658
+ ] })
659
+ ] }) });
660
+ }
661
+ if (events.length === 0) {
662
+ if (showNoEventsMessage) {
663
+ return /* @__PURE__ */ jsx8("div", { className, children: /* @__PURE__ */ jsxs3(Alert, { variant: "inline", children: [
664
+ /* @__PURE__ */ jsx8(AlertCircle, { className: "h-4 w-4 text-acc-700" }),
665
+ /* @__PURE__ */ jsxs3(AlertDescription, { className: "flex items-center justify-between", children: [
666
+ /* @__PURE__ */ jsx8("span", { children: "No events available." }),
667
+ showRetryButton && /* @__PURE__ */ jsxs3(
668
+ Button,
669
+ {
670
+ variant: "outline",
671
+ size: "sm",
672
+ onClick: handleRetry,
673
+ className: "ml-2",
674
+ children: [
675
+ /* @__PURE__ */ jsx8(RefreshCw, { className: "h-3 w-3 mr-1" }),
676
+ "Refresh"
677
+ ]
678
+ }
679
+ )
680
+ ] })
681
+ ] }) });
682
+ }
683
+ return null;
684
+ }
685
+ return /* @__PURE__ */ jsxs3(
686
+ Select,
687
+ {
688
+ value: selectedEvent ? selectedEvent.event_id || selectedEvent.id : "",
689
+ onValueChange: handleValueChange,
690
+ className,
691
+ children: [
692
+ /* @__PURE__ */ jsx8(SelectTrigger, { className: "text-left", variant: "outline", children: /* @__PURE__ */ jsx8(SelectValue, { placeholder, children: selectedEvent && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
693
+ /* @__PURE__ */ jsx8(Calendar, { className: "h-4 w-4 flex-shrink-0" }),
694
+ /* @__PURE__ */ jsx8("span", { className: "truncate", children: selectedEvent.event_name || selectedEvent.name }),
695
+ selectedEvent.event_date && /* @__PURE__ */ jsxs3("span", { className: "text-xs text-muted-foreground flex-shrink-0", children: [
696
+ "(",
697
+ formatEventDate(selectedEvent.event_date),
698
+ ")"
699
+ ] })
700
+ ] }) }) }),
701
+ /* @__PURE__ */ jsx8(SelectContent, { children: sortedEvents.map((event) => {
702
+ const isNext = isNextEvent(event);
703
+ const isSelected = selectedEvent && (selectedEvent.event_id === event.event_id || selectedEvent.id === event.id);
704
+ return /* @__PURE__ */ jsx8(
705
+ SelectItem,
706
+ {
707
+ value: event.event_id || event.id,
708
+ className: "flex items-center justify-between",
709
+ children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 w-full", children: [
710
+ showNextEventIndicator && isNext && /* @__PURE__ */ jsx8(Star, { className: "h-3 w-3 text-acc-500" }),
711
+ /* @__PURE__ */ jsxs3("div", { className: "flex-1", children: [
712
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
713
+ /* @__PURE__ */ jsx8("span", { className: isSelected ? "font-semibold" : "", children: event.event_name || event.name }),
714
+ isSelected && /* @__PURE__ */ jsx8("span", { className: "text-xs bg-primary text-primary-foreground px-1 rounded", children: "Current" })
715
+ ] }),
716
+ showEventDetails && event.event_date && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
717
+ /* @__PURE__ */ jsx8(Calendar, { className: "h-3 w-3" }),
718
+ /* @__PURE__ */ jsx8("span", { children: formatEventDate(event.event_date) }),
719
+ showNextEventIndicator && isNext && /* @__PURE__ */ jsx8("span", { className: "text-acc-600 font-medium", children: "(Next)" })
720
+ ] }),
721
+ showEventDetails && event.event_venue && /* @__PURE__ */ jsxs3("div", { className: "text-xs text-muted-foreground", children: [
722
+ "\u{1F4CD} ",
723
+ event.event_venue
724
+ ] })
725
+ ] })
726
+ ] })
727
+ },
728
+ event.event_id || event.id
729
+ );
730
+ }) })
731
+ ]
732
+ }
733
+ );
734
+ }
735
+
736
+ // src/components/PasswordReset/PasswordChangeForm.tsx
737
+ init_Button();
738
+ import { useState as useState2 } from "react";
739
+ init_cn();
740
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
741
+ function PasswordChangeForm({ onSubmit, className }) {
742
+ const [newPassword, setNewPassword] = useState2("");
743
+ const [confirmPassword, setConfirmPassword] = useState2("");
744
+ const [error, setError] = useState2(null);
745
+ const [isSubmitting, setIsSubmitting] = useState2(false);
746
+ const handleSubmit = async (e) => {
747
+ e.preventDefault();
748
+ setError(null);
749
+ if (newPassword.length < 8) {
750
+ setError("Password must be at least 8 characters.");
751
+ return;
752
+ }
753
+ if (newPassword !== confirmPassword) {
754
+ setError("Passwords do not match.");
755
+ return;
756
+ }
757
+ setIsSubmitting(true);
758
+ try {
759
+ const result = await onSubmit({ newPassword, confirmPassword });
760
+ if (result && result.error) {
761
+ setError(result.error.message || "Failed to change password.");
762
+ }
763
+ } catch (err) {
764
+ setError(err?.message || "An unexpected error occurred.");
765
+ } finally {
766
+ setIsSubmitting(false);
767
+ }
768
+ };
769
+ return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
770
+ error && /* @__PURE__ */ jsx9("div", { role: "alert", children: error }),
771
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
772
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "new-password", children: "New Password" }),
773
+ /* @__PURE__ */ jsx9(
774
+ Input,
775
+ {
776
+ id: "new-password",
777
+ type: "password",
778
+ value: newPassword,
779
+ onChange: (e) => setNewPassword(e.target.value),
780
+ required: true,
781
+ disabled: isSubmitting
782
+ }
783
+ )
784
+ ] }),
785
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
786
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "confirm-password", children: "Confirm Password" }),
787
+ /* @__PURE__ */ jsx9(
788
+ Input,
789
+ {
790
+ id: "confirm-password",
791
+ type: "password",
792
+ value: confirmPassword,
793
+ onChange: (e) => setConfirmPassword(e.target.value),
794
+ required: true,
795
+ disabled: isSubmitting
796
+ }
797
+ )
798
+ ] }),
799
+ /* @__PURE__ */ jsx9(
800
+ Button,
801
+ {
802
+ type: "submit",
803
+ className: "w-full",
804
+ disabled: isSubmitting || !newPassword || !confirmPassword,
805
+ children: isSubmitting ? "Changing..." : "Change Password"
806
+ }
807
+ )
808
+ ] });
809
+ }
810
+
811
+ // src/components/Button/index.ts
812
+ init_Button();
813
+
814
+ // src/components/UserMenu/UserMenu.tsx
815
+ import React8, { useCallback as useCallback2, useMemo as useMemo3, useState as useState3 } from "react";
816
+ import { ChevronDown, LogOut, KeyRound } from "lucide-react";
817
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
818
+ var UserMenu = React8.memo(function UserMenu2({
819
+ user,
820
+ onSignOut,
821
+ onChangePassword,
822
+ className,
823
+ showAvatar = true
824
+ }) {
825
+ const [isPasswordDialogOpen, setPasswordDialogOpen] = useState3(false);
826
+ const userInfo = useMemo3(() => {
827
+ if (!user) return null;
828
+ return {
829
+ email: user.email,
830
+ displayName: user.user_metadata?.display_name || user.user_metadata?.full_name || user.email?.split("@")[0],
831
+ avatarUrl: user.user_metadata?.avatar_url,
832
+ initial: (user.user_metadata?.display_name || user.user_metadata?.full_name || user.email || "U").charAt(0).toUpperCase()
833
+ };
834
+ }, [user]);
835
+ const handleSignOut = useCallback2(async () => {
836
+ if (onSignOut) await onSignOut();
837
+ }, [onSignOut]);
838
+ if (!user || !userInfo) {
839
+ return null;
840
+ }
841
+ return /* @__PURE__ */ jsxs5(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
842
+ /* @__PURE__ */ jsxs5(Select, { className, children: [
843
+ /* @__PURE__ */ jsx10(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
844
+ showAvatar && /* @__PURE__ */ jsxs5(Avatar, { className: "h-8 w-8", children: [
845
+ /* @__PURE__ */ jsx10(AvatarImage, { src: userInfo.avatarUrl, alt: userInfo.displayName }),
846
+ /* @__PURE__ */ jsx10(AvatarFallback, { children: userInfo.initial })
847
+ ] }),
848
+ /* @__PURE__ */ jsx10("span", { className: "hidden sm:inline-block", children: userInfo.displayName }),
849
+ /* @__PURE__ */ jsx10(ChevronDown, { className: "h-4 w-4" })
850
+ ] }) }),
851
+ /* @__PURE__ */ jsxs5(SelectContent, { children: [
852
+ /* @__PURE__ */ jsx10(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-col space-y-1", children: [
853
+ /* @__PURE__ */ jsx10("p", { className: "font-medium", children: userInfo.displayName }),
854
+ /* @__PURE__ */ jsx10("p", { className: "text-muted-foreground", children: userInfo.email })
855
+ ] }) }),
856
+ /* @__PURE__ */ jsx10(SelectSeparator, {}),
857
+ /* @__PURE__ */ jsx10(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(SelectItem, { value: "change-password", children: [
858
+ /* @__PURE__ */ jsx10(KeyRound, { className: "mr-2 h-4 w-4" }),
859
+ /* @__PURE__ */ jsx10("span", { children: "Change Password" })
860
+ ] }) }),
861
+ /* @__PURE__ */ jsxs5(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
862
+ /* @__PURE__ */ jsx10(LogOut, { className: "mr-2 h-4 w-4" }),
863
+ /* @__PURE__ */ jsx10("span", { children: "Sign out" })
864
+ ] })
865
+ ] })
866
+ ] }),
867
+ /* @__PURE__ */ jsx10(DialogOverlay, {}),
868
+ /* @__PURE__ */ jsxs5(DialogContent, { className, children: [
869
+ /* @__PURE__ */ jsx10(DialogHeader, { children: /* @__PURE__ */ jsx10(DialogTitle, { children: "Change Password" }) }),
870
+ /* @__PURE__ */ jsx10(
871
+ PasswordChangeForm,
872
+ {
873
+ onSubmit: async ({ newPassword, confirmPassword }) => {
874
+ if (onChangePassword) {
875
+ const { error } = await onChangePassword(newPassword, confirmPassword);
876
+ if (!error) {
877
+ setPasswordDialogOpen(false);
878
+ }
879
+ return { error };
880
+ }
881
+ return {};
882
+ }
883
+ }
884
+ )
885
+ ] })
886
+ ] });
887
+ });
888
+ var UserMenuLoading = React8.memo(function UserMenuLoading2() {
889
+ return /* @__PURE__ */ jsxs5("div", { className: "relative inline-block text-left", children: [
890
+ /* @__PURE__ */ jsxs5(
891
+ "button",
892
+ {
893
+ type: "button",
894
+ disabled: true,
895
+ className: "flex items-center space-x-2 px-3 py-2 text-sm font-medium text-muted-foreground bg-muted border border-input rounded-md",
896
+ children: [
897
+ /* @__PURE__ */ jsx10("div", { className: "w-6 h-6 rounded-full bg-muted animate-pulse" }),
898
+ /* @__PURE__ */ jsx10("span", { className: "truncate max-w-[150px]", children: "Loading..." }),
899
+ /* @__PURE__ */ jsx10(ChevronDown, { className: "w-4 h-4 text-muted-foreground" })
900
+ ]
901
+ }
902
+ ),
903
+ /* @__PURE__ */ jsx10("div", { role: "status", "aria-label": "Loading user menu", "aria-live": "polite", className: "w-6 h-6 rounded-full bg-muted animate-pulse" })
904
+ ] });
905
+ });
906
+ UserMenu.Loading = UserMenuLoading;
907
+
908
+ // src/components/NavigationMenu/NavigationMenu.tsx
909
+ import * as React9 from "react";
910
+ import { ChevronDown as ChevronDown2 } from "lucide-react";
911
+ init_UnifiedAuthProvider();
912
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
913
+ var NavigationMenu = React9.forwardRef(({
914
+ items,
915
+ mode = "dropdown",
916
+ currentPath,
917
+ onNavigate,
918
+ className,
919
+ disabled = false,
920
+ buttonText = "Menu",
921
+ showIcons = true,
922
+ navigationLabel = "Main navigation",
923
+ // NEW: Phase 2 - Enhanced Security Features
924
+ strictMode = true,
925
+ auditLog = true,
926
+ onNavigationAccessDenied,
927
+ onStrictModeViolation,
928
+ filterByPermissions = true,
929
+ ...props
930
+ }, ref) => {
931
+ const [expandedItems, setExpandedItems] = React9.useState(/* @__PURE__ */ new Set());
932
+ const buttonRef = React9.useRef(null);
933
+ let authContext = null;
934
+ try {
935
+ authContext = useUnifiedAuth();
936
+ } catch (error) {
937
+ console.warn("[NavigationMenu] useUnifiedAuth not available, running in unauthenticated mode");
938
+ }
939
+ const filteredItems = React9.useMemo(() => {
940
+ if (!filterByPermissions || !authContext) return items || [];
941
+ return (items || []).filter((item) => {
942
+ if (item.meta?.hidden) return false;
943
+ if (item.permissions && item.permissions.length > 0) {
944
+ const hasPermission = item.permissions.some((permission) => {
945
+ if (typeof permission !== "string") return true;
946
+ return authContext.hasPermission(permission);
947
+ });
948
+ if (!hasPermission) return false;
949
+ }
950
+ if (item.roles && item.roles.length > 0) {
951
+ const hasRole = item.roles.some((role) => {
952
+ if (typeof role !== "string") return true;
953
+ return authContext.hasRole(role);
954
+ });
955
+ if (!hasRole) return false;
956
+ }
957
+ if (item.accessLevel) {
958
+ if (typeof item.accessLevel === "string") {
959
+ const accessLevel = item.accessLevel;
960
+ const hasAccessLevel = authContext.hasAccessLevel(accessLevel);
961
+ if (!hasAccessLevel) return false;
962
+ }
963
+ }
964
+ return true;
965
+ });
966
+ }, [items, filterByPermissions, authContext]);
967
+ React9.useEffect(() => {
968
+ if (auditLog && authContext) {
969
+ console.log("[NavigationMenu] Navigation access attempt:", {
970
+ itemId: "navigation-menu",
971
+ label: "Navigation Menu",
972
+ href: currentPath,
973
+ permissions: authContext.permissions,
974
+ roles: authContext.roles,
975
+ accessLevel: authContext.accessLevel,
976
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
977
+ });
978
+ }
979
+ }, [auditLog, authContext, currentPath]);
980
+ const handleHierarchicalKeyDown = (event, item) => {
981
+ switch (event.key) {
982
+ case "Enter":
983
+ case " ":
984
+ event.preventDefault();
985
+ if (item.children && item.children.length > 0) {
986
+ toggleExpanded(item.id);
987
+ } else if (item.href) {
988
+ onNavigate?.(item);
989
+ }
990
+ break;
991
+ case "Escape":
992
+ if (expandedItems.has(item.id)) {
993
+ toggleExpanded(item.id);
994
+ }
995
+ break;
996
+ }
997
+ };
998
+ const toggleExpanded = (itemId) => {
999
+ const newExpanded = new Set(expandedItems);
1000
+ if (newExpanded.has(itemId)) {
1001
+ newExpanded.delete(itemId);
1002
+ } else {
1003
+ newExpanded.add(itemId);
1004
+ }
1005
+ setExpandedItems(newExpanded);
1006
+ };
1007
+ const handleItemClick = (item) => {
1008
+ if (auditLog) {
1009
+ console.log(`[NavigationMenu] Navigation access attempt:`, {
1010
+ itemId: item.id,
1011
+ label: item.label,
1012
+ href: item.href,
1013
+ permissions: item.permissions,
1014
+ roles: item.roles,
1015
+ accessLevel: item.accessLevel,
1016
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1017
+ });
1018
+ }
1019
+ const hasPermission = true;
1020
+ if (!hasPermission) {
1021
+ if (onNavigationAccessDenied) {
1022
+ onNavigationAccessDenied(item.id, "Insufficient permissions");
1023
+ }
1024
+ if (strictMode) {
1025
+ console.error(`[NavigationMenu] STRICT MODE VIOLATION: User attempted to access protected navigation item without permission`, {
1026
+ itemId: item.id,
1027
+ label: item.label,
1028
+ href: item.href,
1029
+ permissions: item.permissions,
1030
+ roles: item.roles,
1031
+ accessLevel: item.accessLevel,
1032
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1033
+ });
1034
+ if (onStrictModeViolation) {
1035
+ onStrictModeViolation(item.id, "Insufficient permissions");
1036
+ }
1037
+ }
1038
+ return;
1039
+ }
1040
+ if (onNavigate) {
1041
+ onNavigate(item);
1042
+ } else if (item.href) {
1043
+ window.location.href = item.href;
1044
+ }
1045
+ };
1046
+ const isActiveItem = (item) => {
1047
+ if (item.isActive !== void 0) return item.isActive;
1048
+ if (currentPath === item.href) return true;
1049
+ if (item.children && item.children.length > 0) {
1050
+ return item.children.some((child) => isActiveItem(child));
1051
+ }
1052
+ return false;
1053
+ };
1054
+ const handleNavigationSelect = (itemId) => {
1055
+ const item = filteredItems.find((i) => i.id === itemId);
1056
+ if (item) {
1057
+ handleItemClick(item);
1058
+ }
1059
+ };
1060
+ const renderHierarchicalItem = (item, level = 0) => {
1061
+ const hasChildren = item.children && item.children.length > 0;
1062
+ const isExpanded = expandedItems.has(item.id);
1063
+ const itemIsActive = isActiveItem(item);
1064
+ return /* @__PURE__ */ jsx11("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs6("div", { children: [
1065
+ /* @__PURE__ */ jsxs6(
1066
+ "button",
1067
+ {
1068
+ onClick: () => toggleExpanded(item.id),
1069
+ onKeyDown: (e) => handleHierarchicalKeyDown(e, item),
1070
+ "aria-expanded": isExpanded,
1071
+ "aria-controls": `submenu-${item.id}`,
1072
+ "aria-current": itemIsActive ? "page" : void 0,
1073
+ children: [
1074
+ /* @__PURE__ */ jsx11("span", { children: item.label }),
1075
+ /* @__PURE__ */ jsx11(ChevronDown2, { "aria-hidden": "true" })
1076
+ ]
1077
+ }
1078
+ ),
1079
+ isExpanded && item.children && /* @__PURE__ */ jsx11(
1080
+ "ul",
1081
+ {
1082
+ id: `submenu-${item.id}`,
1083
+ role: "menu",
1084
+ "aria-label": `${item.label} submenu`,
1085
+ children: item.children.map((child) => /* @__PURE__ */ jsx11(React9.Fragment, { children: renderHierarchicalItem(child, level + 1) }, child.id))
1086
+ }
1087
+ )
1088
+ ] }) : /* @__PURE__ */ jsx11(
1089
+ "a",
1090
+ {
1091
+ href: item.href || "#",
1092
+ onClick: (e) => {
1093
+ if (onNavigate && item.href) {
1094
+ e.preventDefault();
1095
+ onNavigate(item);
1096
+ }
1097
+ },
1098
+ onKeyDown: (e) => handleHierarchicalKeyDown(e, item),
1099
+ role: "menuitem",
1100
+ "aria-current": itemIsActive ? "page" : void 0,
1101
+ children: item.label
1102
+ }
1103
+ ) });
1104
+ };
1105
+ if (mode === "dropdown") {
1106
+ return /* @__PURE__ */ jsxs6(
1107
+ Select,
1108
+ {
1109
+ onValueChange: handleNavigationSelect,
1110
+ className,
1111
+ "data-testid": "navigation-menu-root",
1112
+ children: [
1113
+ /* @__PURE__ */ jsx11(
1114
+ SelectTrigger,
1115
+ {
1116
+ ref: buttonRef,
1117
+ disabled,
1118
+ "aria-label": buttonText,
1119
+ "data-testid": "navigation-menu-trigger",
1120
+ children: /* @__PURE__ */ jsx11(SelectValue, { placeholder: buttonText })
1121
+ }
1122
+ ),
1123
+ /* @__PURE__ */ jsx11(SelectContent, { children: filteredItems.map((item) => {
1124
+ const isActive = isActiveItem(item);
1125
+ return /* @__PURE__ */ jsx11(
1126
+ SelectItem,
1127
+ {
1128
+ value: item.id,
1129
+ disabled: !item.href,
1130
+ "data-testid": `navigation-menu-item-${item.id}`,
1131
+ children: item.label
1132
+ },
1133
+ item.id
1134
+ );
1135
+ }) })
1136
+ ]
1137
+ }
1138
+ );
1139
+ }
1140
+ return /* @__PURE__ */ jsx11(
1141
+ "nav",
1142
+ {
1143
+ ref,
1144
+ className,
1145
+ "aria-label": navigationLabel,
1146
+ ...props,
1147
+ children: /* @__PURE__ */ jsx11("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx11(React9.Fragment, { children: renderHierarchicalItem(item, 0) }, item.id)) })
1148
+ }
1149
+ );
1150
+ });
1151
+ NavigationMenu.displayName = "NavigationMenu";
1152
+
1153
+ // src/components/Header/Header.tsx
1154
+ init_cn();
1155
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1156
+ function Header({
1157
+ logoUrl,
1158
+ logoAlt = "Logo",
1159
+ logo,
1160
+ navItems = [],
1161
+ user,
1162
+ onSignOut,
1163
+ onChangePassword,
1164
+ actions,
1165
+ userMenu,
1166
+ className,
1167
+ showEventSelector = true,
1168
+ showUserMenu = true,
1169
+ currentPath,
1170
+ onNavigate
1171
+ }) {
1172
+ return /* @__PURE__ */ jsx12("header", { className: cn(
1173
+ "w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
1174
+ className
1175
+ ), role: "banner", children: /* @__PURE__ */ jsxs7("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto grid grid-cols-[auto_auto_1fr_auto] gap-4 h-full items-center", children: [
1176
+ logo ? logo : logoUrl ? /* @__PURE__ */ jsx12(
1177
+ "img",
1178
+ {
1179
+ src: logoUrl,
1180
+ alt: logoAlt || "Logo",
1181
+ className: "h-[2.15rem] w-auto max-w-[200px] object-contain rounded-md shadow-md bg-transparent"
1182
+ }
1183
+ ) : /* @__PURE__ */ jsx12(
1184
+ "img",
1185
+ {
1186
+ src: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23000'/%3E%3Ctext x='16' y='20' text-anchor='middle' fill='white' font-family='Arial' font-size='14' font-weight='bold'%3EL%3C/text%3E%3C/svg%3E",
1187
+ alt: logoAlt || "Logo",
1188
+ className: "h-8 w-8 shadow-md"
1189
+ }
1190
+ ),
1191
+ navItems && navItems.length > 0 && /* @__PURE__ */ jsx12(
1192
+ NavigationMenu,
1193
+ {
1194
+ items: navItems,
1195
+ currentPath,
1196
+ onNavigate,
1197
+ buttonText: "Menu",
1198
+ className: "w-48"
1199
+ }
1200
+ ),
1201
+ showEventSelector && /* @__PURE__ */ jsx12(
1202
+ EventSelector,
1203
+ {
1204
+ placeholder: "Select event",
1205
+ className: "justify-self-end hidden sm:block w-96",
1206
+ "data-testid": "event-selector"
1207
+ }
1208
+ ),
1209
+ actions,
1210
+ showUserMenu && (userMenu ? userMenu : /* @__PURE__ */ jsx12(
1211
+ UserMenu,
1212
+ {
1213
+ user: user || null,
1214
+ onSignOut,
1215
+ onChangePassword,
1216
+ className: "w-70"
1217
+ }
1218
+ ))
1219
+ ] }) });
1220
+ }
1221
+
1222
+ // src/components/Footer/Footer.tsx
1223
+ init_cn();
1224
+ import React10 from "react";
1225
+ import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1226
+ var FooterComponent = ({
1227
+ companyName = "Solvera Solutions Pty Ltd",
1228
+ year = (/* @__PURE__ */ new Date()).getFullYear(),
1229
+ links,
1230
+ className = "",
1231
+ logo,
1232
+ copyright,
1233
+ children
1234
+ }) => {
1235
+ const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
1236
+ return /* @__PURE__ */ jsx13("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs8("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
1237
+ logo && /* @__PURE__ */ jsx13("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
1238
+ children && /* @__PURE__ */ jsx13(Fragment3, { children }),
1239
+ /* @__PURE__ */ jsx13("span", { className: "text-muted-foreground", children: copyrightText }),
1240
+ links && links.length > 0 && /* @__PURE__ */ jsx13("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
1241
+ ] }) });
1242
+ };
1243
+ FooterComponent.displayName = "Footer";
1244
+ var Footer = React10.memo(FooterComponent);
1245
+ Footer.displayName = "Footer";
1246
+
1247
+ // src/components/PaceAppLayout/PaceAppLayout.tsx
1248
+ init_UnifiedAuthProvider();
1249
+ import { useState as useState5, useEffect as useEffect3, useMemo as useMemo5, useCallback as useCallback3 } from "react";
1250
+ import { Outlet, useNavigate, useLocation } from "react-router-dom";
1251
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1252
+ var EMPTY_PAGE_ID_MAPPING = {};
1253
+ var EMPTY_ROUTE_PERMISSIONS = {};
1254
+ function PaceAppLayout({
1255
+ appName,
1256
+ navItems,
1257
+ showEventSelector,
1258
+ headerActions,
1259
+ customLogo,
1260
+ customUserMenu,
1261
+ headerClassName,
1262
+ showUserMenu = true,
1263
+ enforcePermissions = false,
1264
+ defaultPermission = "read",
1265
+ routePermissions = EMPTY_ROUTE_PERMISSIONS,
1266
+ permissionFallback,
1267
+ filterNavigationByPermissions = false,
1268
+ pageIdMapping = EMPTY_PAGE_ID_MAPPING,
1269
+ // NEW: Phase 1 - Enhanced Security Features
1270
+ strictMode = true,
1271
+ enforcePagePermissions = false,
1272
+ pagePermissionFallback,
1273
+ auditLog = true,
1274
+ onPageAccessDenied,
1275
+ onStrictModeViolation,
1276
+ // NEW: Phase 2 - Enhanced Routing Features
1277
+ roleBasedRouting = false,
1278
+ routeConfig = [],
1279
+ fallbackRoute = "/unauthorized",
1280
+ onRouteAccessDenied,
1281
+ onRouteStrictModeViolation
1282
+ }) {
1283
+ const { user, signOut, updatePassword } = useUnifiedAuth();
1284
+ const navigate = useNavigate();
1285
+ const location = useLocation();
1286
+ const checkPermission = useCallback3(async (permission, pageId) => {
1287
+ try {
1288
+ if (!user?.id) return false;
1289
+ const scope = {
1290
+ organisationId: user.user_metadata?.organisationId || user.app_metadata?.organisationId,
1291
+ eventId: user.user_metadata?.eventId || user.app_metadata?.eventId,
1292
+ appId: user.user_metadata?.appId || user.app_metadata?.appId
1293
+ };
1294
+ const { isSuperAdmin } = await import("./api-GZHIDA4X.js");
1295
+ const isSuper = await isSuperAdmin(user.id);
1296
+ if (isSuper) {
1297
+ return true;
1298
+ }
1299
+ if (!scope.organisationId) {
1300
+ console.warn("No organisation context available for permission check, denying access");
1301
+ return false;
1302
+ }
1303
+ return await isPermitted({
1304
+ userId: user.id,
1305
+ scope,
1306
+ permission,
1307
+ pageId
1308
+ });
1309
+ } catch (error) {
1310
+ console.error("Permission check failed:", error);
1311
+ throw error;
1312
+ }
1313
+ }, [user?.id]);
1314
+ const [hasPermission, setHasPermission] = useState5(null);
1315
+ const [isCheckingPermission, setIsCheckingPermission] = useState5(false);
1316
+ const [permissionError, setPermissionError] = useState5(null);
1317
+ const defaultNavItems = useMemo5(() => [
1318
+ { id: "home", label: "Home", href: "/", icon: "Home" },
1319
+ { id: "dashboard", label: "Dashboard", href: "/dashboard", icon: "LayoutDashboard" },
1320
+ { id: "settings", label: "Settings", href: "/settings", icon: "Settings" },
1321
+ { id: "ui-showcase", label: "UI Showcase", href: "/ui-showcase", icon: "Component" },
1322
+ { id: "data-table-showcase", label: "DataTable Showcase", href: "/data-table-showcase", icon: "Table" }
1323
+ ], []);
1324
+ const baseMenuItems = useMemo5(() => navItems || defaultNavItems, [navItems]);
1325
+ const currentRoutePermission = useMemo5(() => {
1326
+ const currentPath = location.pathname;
1327
+ return routePermissions[currentPath] || defaultPermission;
1328
+ }, [location.pathname, routePermissions, defaultPermission]);
1329
+ const currentPageId = useMemo5(() => {
1330
+ const currentPath = location.pathname;
1331
+ return pageIdMapping[currentPath] || currentPath.slice(1) || "home";
1332
+ }, [location.pathname, pageIdMapping]);
1333
+ useEffect3(() => {
1334
+ if (!enforcePermissions) {
1335
+ setHasPermission(true);
1336
+ return;
1337
+ }
1338
+ let isMounted = true;
1339
+ const checkRoutePermission = async () => {
1340
+ if (!isMounted) return;
1341
+ setIsCheckingPermission(true);
1342
+ setPermissionError(null);
1343
+ try {
1344
+ const hasAccess = await checkPermission(currentRoutePermission, currentPageId);
1345
+ if (!isMounted) return;
1346
+ setHasPermission(hasAccess);
1347
+ if (auditLog) {
1348
+ console.log(`[PaceAppLayout] Page access attempt:`, {
1349
+ pageName: currentPageId,
1350
+ operation: currentRoutePermission,
1351
+ userId: user?.id,
1352
+ allowed: hasAccess,
1353
+ strictMode,
1354
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1355
+ });
1356
+ }
1357
+ if (strictMode && !hasAccess) {
1358
+ console.error(`[PaceAppLayout] STRICT MODE VIOLATION: User attempted to access protected page without permission`, {
1359
+ pageName: currentPageId,
1360
+ operation: currentRoutePermission,
1361
+ userId: user?.id,
1362
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1363
+ });
1364
+ if (onStrictModeViolation) {
1365
+ onStrictModeViolation(currentPageId, currentRoutePermission);
1366
+ }
1367
+ }
1368
+ if (!hasAccess && onPageAccessDenied) {
1369
+ onPageAccessDenied(currentPageId, currentRoutePermission);
1370
+ }
1371
+ } catch (error) {
1372
+ if (!isMounted) return;
1373
+ console.error(`[PaceAppLayout] Permission check failed for ${currentPageId}:`, error);
1374
+ setPermissionError(error instanceof Error ? error : new Error("Permission check failed"));
1375
+ setHasPermission(false);
1376
+ } finally {
1377
+ if (isMounted) {
1378
+ setIsCheckingPermission(false);
1379
+ }
1380
+ }
1381
+ };
1382
+ checkRoutePermission();
1383
+ return () => {
1384
+ isMounted = false;
1385
+ };
1386
+ }, [enforcePermissions, currentRoutePermission, currentPageId, strictMode, user?.id]);
1387
+ const [filteredMenuItems, setFilteredMenuItems] = useState5(baseMenuItems);
1388
+ useEffect3(() => {
1389
+ if (!filterNavigationByPermissions || !enforcePermissions) {
1390
+ setFilteredMenuItems(baseMenuItems);
1391
+ return;
1392
+ }
1393
+ let isMounted = true;
1394
+ const filterItems = async () => {
1395
+ const filtered = await Promise.all(
1396
+ baseMenuItems.map(async (item) => {
1397
+ if (!item.href) return { item, hasAccess: true };
1398
+ const pageId = pageIdMapping[item.href] || item.href.slice(1) || "home";
1399
+ const permission = routePermissions[item.href] || defaultPermission;
1400
+ try {
1401
+ const hasAccess = await checkPermission(permission, pageId);
1402
+ return { item, hasAccess };
1403
+ } catch {
1404
+ return { item, hasAccess: false };
1405
+ }
1406
+ })
1407
+ );
1408
+ if (!isMounted) return;
1409
+ const accessibleItems = filtered.filter(({ hasAccess }) => hasAccess).map(({ item }) => item);
1410
+ setFilteredMenuItems(accessibleItems);
1411
+ };
1412
+ filterItems();
1413
+ return () => {
1414
+ isMounted = false;
1415
+ };
1416
+ }, [baseMenuItems, filterNavigationByPermissions, enforcePermissions, pageIdMapping, routePermissions, defaultPermission]);
1417
+ useEffect3(() => {
1418
+ if (!roleBasedRouting || routeConfig.length === 0) return;
1419
+ const currentPath = location.pathname;
1420
+ const currentRoute = routeConfig.find((route) => route.path === currentPath);
1421
+ if (!currentRoute) {
1422
+ if (strictMode) {
1423
+ console.error(`[PaceAppLayout] STRICT MODE VIOLATION: Route not found in configuration`, {
1424
+ route: currentPath,
1425
+ userId: user?.id,
1426
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1427
+ });
1428
+ if (onRouteStrictModeViolation) {
1429
+ onRouteStrictModeViolation(currentPath, "Route not found in configuration");
1430
+ }
1431
+ }
1432
+ return;
1433
+ }
1434
+ const hasAccess = true;
1435
+ if (!hasAccess) {
1436
+ if (onRouteAccessDenied) {
1437
+ onRouteAccessDenied(currentPath, "Insufficient permissions");
1438
+ }
1439
+ if (strictMode) {
1440
+ console.error(`[PaceAppLayout] STRICT MODE VIOLATION: User attempted to access protected route without permission`, {
1441
+ route: currentPath,
1442
+ userId: user?.id,
1443
+ permissions: currentRoute.permissions,
1444
+ roles: currentRoute.roles,
1445
+ accessLevel: currentRoute.accessLevel,
1446
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1447
+ });
1448
+ if (onRouteStrictModeViolation) {
1449
+ onRouteStrictModeViolation(currentPath, "Insufficient permissions");
1450
+ }
1451
+ }
1452
+ navigate(fallbackRoute, { replace: true });
1453
+ }
1454
+ if (auditLog) {
1455
+ console.log(`[PaceAppLayout] Route access attempt:`, {
1456
+ route: currentPath,
1457
+ userId: user?.id,
1458
+ allowed: hasAccess,
1459
+ permissions: currentRoute.permissions,
1460
+ roles: currentRoute.roles,
1461
+ accessLevel: currentRoute.accessLevel,
1462
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1463
+ });
1464
+ }
1465
+ }, [roleBasedRouting, routeConfig, location.pathname, strictMode, user?.id, fallbackRoute]);
1466
+ const handleSignOut = async () => {
1467
+ await signOut();
1468
+ };
1469
+ const handleChangePassword = async (newPassword) => {
1470
+ const result = await updatePassword(newPassword);
1471
+ if (result?.error) {
1472
+ console.error("Failed to change password:", result.error.message);
1473
+ }
1474
+ return result || { error: null };
1475
+ };
1476
+ if (enforcePermissions && isCheckingPermission) {
1477
+ return /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs9("div", { className: "text-center", children: [
1478
+ /* @__PURE__ */ jsx14("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-sec-900 mx-auto mb-4" }),
1479
+ /* @__PURE__ */ jsx14("p", { className: "text-sec-600", children: "Checking permissions..." })
1480
+ ] }) });
1481
+ }
1482
+ if (enforcePermissions && permissionError) {
1483
+ return /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs9("div", { className: "text-center", children: [
1484
+ /* @__PURE__ */ jsx14("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Permission Error" }),
1485
+ /* @__PURE__ */ jsx14("p", { className: "text-sec-600 mb-4", children: permissionError.message }),
1486
+ /* @__PURE__ */ jsx14(Button, { onClick: () => navigate("/"), children: "Go Home" })
1487
+ ] }) });
1488
+ }
1489
+ if (enforcePermissions && hasPermission === false) {
1490
+ if (enforcePagePermissions && pagePermissionFallback) {
1491
+ return /* @__PURE__ */ jsx14(Fragment4, { children: pagePermissionFallback });
1492
+ }
1493
+ if (permissionFallback) {
1494
+ return /* @__PURE__ */ jsx14(Fragment4, { children: permissionFallback });
1495
+ }
1496
+ return /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs9("div", { className: "text-center", children: [
1497
+ /* @__PURE__ */ jsx14("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Access Denied" }),
1498
+ /* @__PURE__ */ jsx14("p", { className: "text-sec-600 mb-4", children: "You don't have permission to access this page." }),
1499
+ /* @__PURE__ */ jsx14(Button, { onClick: () => navigate("/"), children: "Go Home" })
1500
+ ] }) });
1501
+ }
1502
+ return /* @__PURE__ */ jsxs9(Fragment4, { children: [
1503
+ /* @__PURE__ */ jsx14(
1504
+ Header,
1505
+ {
1506
+ logo: customLogo || void 0,
1507
+ logoUrl: !customLogo ? `/${appName.toLowerCase()}_logo_wide.svg` : void 0,
1508
+ logoAlt: `${appName} Logo`,
1509
+ navItems: filteredMenuItems,
1510
+ actions: headerActions,
1511
+ userMenu: customUserMenu,
1512
+ user,
1513
+ onSignOut: handleSignOut,
1514
+ onChangePassword: handleChangePassword,
1515
+ currentPath: window.location.pathname,
1516
+ onNavigate: (item) => {
1517
+ if (item.href) {
1518
+ navigate(item.href);
1519
+ }
1520
+ },
1521
+ showEventSelector,
1522
+ showUserMenu,
1523
+ className: headerClassName || "sticky top-0 z-[40] w-full"
1524
+ }
1525
+ ),
1526
+ /* @__PURE__ */ jsx14("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: /* @__PURE__ */ jsx14(Outlet, {}) }),
1527
+ /* @__PURE__ */ jsx14(Footer, {})
1528
+ ] });
1529
+ }
1530
+
1531
+ // src/components/PaceLoginPage/PaceLoginPage.tsx
1532
+ import { useEffect as useEffect4, useState as useState6 } from "react";
1533
+ import { useNavigate as useNavigate2 } from "react-router-dom";
1534
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1535
+ var PaceLoginPage = ({
1536
+ appName = "Pace",
1537
+ onSuccessRedirectPath = "/"
1538
+ }) => {
1539
+ const { signIn, isAuthenticated, isLoading, authError, hasRole } = useUnifiedAuth();
1540
+ const navigate = useNavigate2();
1541
+ const [isSigningIn, setIsSigningIn] = useState6(false);
1542
+ useEffect4(() => {
1543
+ if (isAuthenticated && !isLoading && hasRole("super_admin")) {
1544
+ try {
1545
+ navigate(onSuccessRedirectPath, { replace: true });
1546
+ } catch (error) {
1547
+ console.error("Navigation error:", error);
1548
+ }
1549
+ }
1550
+ }, [isAuthenticated, isLoading, navigate, onSuccessRedirectPath, hasRole]);
1551
+ const handleSubmit = async (data) => {
1552
+ setIsSigningIn(true);
1553
+ try {
1554
+ const { error } = await signIn(data.email, data.password);
1555
+ if (!error) {
1556
+ try {
1557
+ navigate(onSuccessRedirectPath, { replace: true });
1558
+ } catch (navError) {
1559
+ console.error("Navigation error after sign-in:", navError);
1560
+ }
1561
+ }
1562
+ } finally {
1563
+ setIsSigningIn(false);
1564
+ }
1565
+ };
1566
+ return /* @__PURE__ */ jsxs10("main", { className: "min-h-screen grid mx-auto w-fit content-center justify-items-center gap-y-8", "aria-label": `${appName} Login Page`, children: [
1567
+ /* @__PURE__ */ jsx15(
1568
+ "img",
1569
+ {
1570
+ src: `/${appName.toLowerCase()}_logo_square.svg`,
1571
+ alt: `${appName} logo`,
1572
+ className: "h-48"
1573
+ }
1574
+ ),
1575
+ /* @__PURE__ */ jsx15(
1576
+ LoginForm,
1577
+ {
1578
+ className: "w-md",
1579
+ onSignIn: handleSubmit,
1580
+ appName,
1581
+ isLoading: isSigningIn,
1582
+ onError: (error) => {
1583
+ console.error("Login error:", error);
1584
+ }
1585
+ }
1586
+ ),
1587
+ authError && /* @__PURE__ */ jsx15("em", { className: "mt-4 text-destructive text-center", children: authError.message })
1588
+ ] });
1589
+ };
1590
+
1591
+ // src/components/ErrorBoundary/ErrorBoundary.tsx
1592
+ import { Component } from "react";
1593
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1594
+ var ErrorBoundary = class extends Component {
1595
+ constructor(props) {
1596
+ super(props);
1597
+ this.retryTimeoutId = null;
1598
+ this.reportError = (errorId, componentName) => {
1599
+ if (true) {
1600
+ console.warn("Error reporting would be triggered in production:", { errorId, componentName });
1601
+ }
1602
+ };
1603
+ this.handleRetry = () => {
1604
+ const { maxRetries = 3 } = this.props;
1605
+ const { retryCount } = this.state;
1606
+ if (retryCount < maxRetries) {
1607
+ console.log(`Retrying component render (attempt ${retryCount + 1}/${maxRetries})`);
1608
+ this.setState((prevState) => ({
1609
+ hasError: false,
1610
+ error: void 0,
1611
+ errorInfo: void 0,
1612
+ errorId: void 0,
1613
+ retryCount: prevState.retryCount + 1
1614
+ }));
1615
+ }
1616
+ };
1617
+ this.state = {
1618
+ hasError: false,
1619
+ retryCount: 0
1620
+ };
1621
+ }
1622
+ static getDerivedStateFromError(error) {
1623
+ const errorId = `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1624
+ return {
1625
+ hasError: true,
1626
+ error,
1627
+ errorId
1628
+ };
1629
+ }
1630
+ componentDidCatch(error, errorInfo) {
1631
+ const { componentName = "Unknown Component", onError, enableReporting = true } = this.props;
1632
+ const errorId = this.state.errorId;
1633
+ this.setState({ errorInfo });
1634
+ console.error(`ErrorBoundary [${componentName}] caught error ${errorId}:`, error, errorInfo);
1635
+ performanceBudgetMonitor.measure("ERROR_BOUNDARY_TRIGGER", 1, {
1636
+ componentName,
1637
+ errorId,
1638
+ errorMessage: error.message,
1639
+ stack: error.stack?.substring(0, 200)
1640
+ // Truncated stack trace
1641
+ });
1642
+ if (enableReporting) {
1643
+ this.reportError(errorId, componentName);
1644
+ }
1645
+ if (onError) {
1646
+ onError(error, errorInfo, errorId);
1647
+ }
1648
+ }
1649
+ componentWillUnmount() {
1650
+ if (this.retryTimeoutId) {
1651
+ clearTimeout(this.retryTimeoutId);
1652
+ }
1653
+ }
1654
+ render() {
1655
+ if (this.state.hasError) {
1656
+ const {
1657
+ componentName = "Component",
1658
+ fallback,
1659
+ enableRetry = true,
1660
+ maxRetries = 3
1661
+ } = this.props;
1662
+ const { retryCount, errorId } = this.state;
1663
+ if (fallback) {
1664
+ return fallback;
1665
+ }
1666
+ return /* @__PURE__ */ jsx16(
1667
+ "div",
1668
+ {
1669
+ role: "alert",
1670
+ className: "p-6 bg-destructive/10 border border-destructive/20 rounded-lg",
1671
+ "data-error-boundary": errorId,
1672
+ children: /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-3", children: [
1673
+ /* @__PURE__ */ jsx16("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx16("svg", { className: "w-5 h-5 text-destructive", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx16("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }) }),
1674
+ /* @__PURE__ */ jsxs11("div", { className: "flex-1 min-w-0", children: [
1675
+ /* @__PURE__ */ jsxs11("h3", { className: "text-destructive", children: [
1676
+ "Error in ",
1677
+ componentName
1678
+ ] }),
1679
+ /* @__PURE__ */ jsx16("p", { className: "text-destructive/80", children: this.state.error?.message || "An unexpected error occurred." }),
1680
+ enableRetry && retryCount < maxRetries && /* @__PURE__ */ jsxs11("div", { className: "flex gap-3 mb-4", children: [
1681
+ /* @__PURE__ */ jsxs11(
1682
+ "button",
1683
+ {
1684
+ onClick: this.handleRetry,
1685
+ className: "px-4 py-2 bg-destructive text-destructive-foreground rounded-md hover:bg-destructive/90 transition-colors text-sm font-medium",
1686
+ children: [
1687
+ "Retry (",
1688
+ retryCount + 1,
1689
+ "/",
1690
+ maxRetries,
1691
+ ")"
1692
+ ]
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ jsx16(
1696
+ "button",
1697
+ {
1698
+ onClick: () => window.location.reload(),
1699
+ className: "px-4 py-2 bg-sec-600 text-main-50 rounded-md hover:bg-sec-700 transition-colors text-sm font-medium",
1700
+ children: "Reload Page"
1701
+ }
1702
+ )
1703
+ ] }),
1704
+ retryCount >= maxRetries && /* @__PURE__ */ jsxs11("div", { className: "mb-4 p-3 bg-acc-50 border border-acc-200 rounded-md", children: [
1705
+ /* @__PURE__ */ jsx16("p", { className: "text-acc-800", children: "Maximum retry attempts reached. Please reload the page or contact support." }),
1706
+ /* @__PURE__ */ jsx16(
1707
+ "button",
1708
+ {
1709
+ onClick: () => window.location.reload(),
1710
+ className: "mt-2 px-3 py-1 bg-acc-600 text-main-50 rounded text-sm hover:bg-acc-700",
1711
+ children: "Reload Page"
1712
+ }
1713
+ )
1714
+ ] }),
1715
+ false
1716
+ ] })
1717
+ ] })
1718
+ }
1719
+ );
1720
+ }
1721
+ return this.props.children;
1722
+ }
1723
+ };
1724
+
1725
+ // src/components/OrganisationSelector/OrganisationSelector.tsx
1726
+ import { useState as useState7, useCallback as useCallback4 } from "react";
1727
+ init_Button();
1728
+ init_OrganisationProvider();
1729
+ import { RefreshCw as RefreshCw2, AlertCircle as AlertCircle2, Building2, Shield } from "lucide-react";
1730
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1731
+ function OrganisationSelector({
1732
+ placeholder = "Select organisation",
1733
+ className,
1734
+ onOrganisationChange,
1735
+ showNoOrganisationsMessage = true,
1736
+ showRetryButton = true,
1737
+ showRole = false,
1738
+ compact = false,
1739
+ disabled = false
1740
+ }) {
1741
+ const [isLoading, setIsLoading] = useState7(false);
1742
+ const [switchError, setSwitchError] = useState7(null);
1743
+ const {
1744
+ organisations,
1745
+ selectedOrganisation,
1746
+ isLoading: orgLoading,
1747
+ error: orgError,
1748
+ switchOrganisation,
1749
+ getUserRole,
1750
+ validateOrganisationAccess,
1751
+ refreshOrganisations
1752
+ } = useOrganisations();
1753
+ const handleOrganisationChange = useCallback4(async (orgId) => {
1754
+ if (disabled || isLoading) return;
1755
+ setSwitchError(null);
1756
+ setIsLoading(true);
1757
+ try {
1758
+ if (!validateOrganisationAccess(orgId)) {
1759
+ throw new Error("You do not have access to this organisation");
1760
+ }
1761
+ await switchOrganisation(orgId);
1762
+ const newOrganisation = organisations.find((org) => org.id === orgId);
1763
+ if (newOrganisation && onOrganisationChange) {
1764
+ onOrganisationChange(newOrganisation);
1765
+ }
1766
+ console.log("[OrganisationSelector] Successfully switched to organisation:", orgId);
1767
+ } catch (error) {
1768
+ console.error("[OrganisationSelector] Failed to switch organisation:", error);
1769
+ setSwitchError(error instanceof Error ? error.message : "Failed to switch organisation");
1770
+ } finally {
1771
+ setIsLoading(false);
1772
+ }
1773
+ }, [
1774
+ disabled,
1775
+ isLoading,
1776
+ validateOrganisationAccess,
1777
+ switchOrganisation,
1778
+ organisations,
1779
+ onOrganisationChange
1780
+ ]);
1781
+ const handleRetry = useCallback4(async () => {
1782
+ setIsLoading(true);
1783
+ setSwitchError(null);
1784
+ try {
1785
+ await refreshOrganisations();
1786
+ } catch (error) {
1787
+ console.error("[OrganisationSelector] Failed to refresh organisations:", error);
1788
+ setSwitchError("Failed to refresh organisations");
1789
+ } finally {
1790
+ setIsLoading(false);
1791
+ }
1792
+ }, [refreshOrganisations]);
1793
+ if (orgLoading) {
1794
+ return /* @__PURE__ */ jsxs12("div", { className: `flex items-center gap-2 ${className}`, children: [
1795
+ /* @__PURE__ */ jsx17(LoadingSpinner, { size: "sm" }),
1796
+ /* @__PURE__ */ jsx17("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
1797
+ ] });
1798
+ }
1799
+ if (orgError) {
1800
+ return /* @__PURE__ */ jsxs12("div", { className: `space-y-2 ${className}`, children: [
1801
+ /* @__PURE__ */ jsxs12(Alert, { variant: "destructive", children: [
1802
+ /* @__PURE__ */ jsx17(AlertCircle2, { className: "h-4 w-4" }),
1803
+ /* @__PURE__ */ jsxs12(AlertDescription, { children: [
1804
+ "Failed to load organisations: ",
1805
+ orgError.message
1806
+ ] })
1807
+ ] }),
1808
+ showRetryButton && /* @__PURE__ */ jsxs12(
1809
+ Button,
1810
+ {
1811
+ variant: "outline",
1812
+ size: "sm",
1813
+ onClick: handleRetry,
1814
+ disabled: isLoading,
1815
+ className: "w-full",
1816
+ children: [
1817
+ /* @__PURE__ */ jsx17(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1818
+ "Retry"
1819
+ ]
1820
+ }
1821
+ )
1822
+ ] });
1823
+ }
1824
+ if (organisations.length === 0) {
1825
+ if (showNoOrganisationsMessage) {
1826
+ return /* @__PURE__ */ jsxs12("div", { className: `space-y-2 ${className}`, children: [
1827
+ /* @__PURE__ */ jsxs12(Alert, { children: [
1828
+ /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4" }),
1829
+ /* @__PURE__ */ jsx17(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
1830
+ ] }),
1831
+ showRetryButton && /* @__PURE__ */ jsxs12(
1832
+ Button,
1833
+ {
1834
+ variant: "outline",
1835
+ size: "sm",
1836
+ onClick: handleRetry,
1837
+ disabled: isLoading,
1838
+ className: "w-full",
1839
+ children: [
1840
+ /* @__PURE__ */ jsx17(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1841
+ "Check Again"
1842
+ ]
1843
+ }
1844
+ )
1845
+ ] });
1846
+ }
1847
+ return null;
1848
+ }
1849
+ const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs12(Alert, { variant: "destructive", className: "mt-2", children: [
1850
+ /* @__PURE__ */ jsx17(AlertCircle2, { className: "h-4 w-4" }),
1851
+ /* @__PURE__ */ jsx17(AlertDescription, { children: switchError })
1852
+ ] });
1853
+ return /* @__PURE__ */ jsxs12("div", { className: `space-y-2 ${className}`, children: [
1854
+ /* @__PURE__ */ jsxs12(
1855
+ Select,
1856
+ {
1857
+ value: selectedOrganisation.id,
1858
+ onValueChange: handleOrganisationChange,
1859
+ disabled: disabled || isLoading,
1860
+ children: [
1861
+ /* @__PURE__ */ jsx17(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1862
+ isLoading ? /* @__PURE__ */ jsx17(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4 text-muted-foreground" }),
1863
+ /* @__PURE__ */ jsx17(SelectValue, { placeholder })
1864
+ ] }) }),
1865
+ /* @__PURE__ */ jsx17(SelectContent, { children: organisations.map((org) => {
1866
+ const userRole = getUserRole(org.id);
1867
+ const hasAccess = validateOrganisationAccess(org.id);
1868
+ return /* @__PURE__ */ jsx17(
1869
+ SelectItem,
1870
+ {
1871
+ value: org.id,
1872
+ disabled: !hasAccess,
1873
+ className: !hasAccess ? "opacity-50" : "",
1874
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between w-full", children: [
1875
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1876
+ /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4" }),
1877
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-col", children: [
1878
+ /* @__PURE__ */ jsx17("span", { className: "font-medium", children: org.display_name }),
1879
+ !compact && org.description && /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
1880
+ ] })
1881
+ ] }),
1882
+ showRole && /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1 ml-4", children: [
1883
+ /* @__PURE__ */ jsx17(Shield, { className: "h-3 w-3 text-muted-foreground" }),
1884
+ /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground capitalize", children: userRole.replace("_", " ") })
1885
+ ] })
1886
+ ] })
1887
+ },
1888
+ org.id
1889
+ );
1890
+ }) })
1891
+ ]
1892
+ }
1893
+ ),
1894
+ switchErrorDisplay
1895
+ ] });
1896
+ }
1897
+
1898
+ // src/components/PasswordReset/PasswordResetForm.tsx
1899
+ init_Button();
1900
+ import { useState as useState8 } from "react";
1901
+ init_cn();
1902
+ init_UnifiedAuthProvider();
1903
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1904
+ function PasswordResetForm({
1905
+ onSuccess,
1906
+ onError,
1907
+ className
1908
+ }) {
1909
+ const { resetPassword } = useUnifiedAuth();
1910
+ const [email, setEmail] = useState8("");
1911
+ const [isLoading, setIsLoading] = useState8(false);
1912
+ const [isSuccess, setIsSuccess] = useState8(false);
1913
+ const [error, setError] = useState8(null);
1914
+ const handleSubmit = async (e) => {
1915
+ e.preventDefault();
1916
+ if (!email.trim()) {
1917
+ return;
1918
+ }
1919
+ setIsLoading(true);
1920
+ setError(null);
1921
+ try {
1922
+ const { error: resetError } = await resetPassword(email);
1923
+ if (resetError) {
1924
+ const errorObj = new Error(resetError.message || "Failed to send reset email");
1925
+ setError(errorObj.message);
1926
+ onError?.(errorObj);
1927
+ } else {
1928
+ setIsSuccess(true);
1929
+ onSuccess?.();
1930
+ }
1931
+ } catch (err) {
1932
+ const errorObj = err instanceof Error ? err : new Error("An unexpected error occurred");
1933
+ setError(errorObj.message);
1934
+ onError?.(errorObj);
1935
+ } finally {
1936
+ setIsLoading(false);
1937
+ }
1938
+ };
1939
+ const handleSendAnother = () => {
1940
+ setIsSuccess(false);
1941
+ setError(null);
1942
+ };
1943
+ if (isSuccess) {
1944
+ return /* @__PURE__ */ jsx18("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4 text-center", children: [
1945
+ /* @__PURE__ */ jsx18("h2", { children: "Check your email" }),
1946
+ /* @__PURE__ */ jsxs13("p", { className: "text-sec-600", children: [
1947
+ "We have sent a password reset link to ",
1948
+ email
1949
+ ] }),
1950
+ /* @__PURE__ */ jsx18(
1951
+ Button,
1952
+ {
1953
+ variant: "outline",
1954
+ onClick: handleSendAnother,
1955
+ className: "w-full",
1956
+ children: "Send another email"
1957
+ }
1958
+ )
1959
+ ] }) });
1960
+ }
1961
+ return /* @__PURE__ */ jsx18("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
1962
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
1963
+ /* @__PURE__ */ jsx18("h2", { children: "Reset Password" }),
1964
+ /* @__PURE__ */ jsx18("p", { className: "text-sec-600", children: "Enter your email address and we'll send you a reset link." })
1965
+ ] }),
1966
+ /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
1967
+ /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
1968
+ /* @__PURE__ */ jsx18(Label, { htmlFor: "email", children: "Email Address" }),
1969
+ /* @__PURE__ */ jsx18(
1970
+ Input,
1971
+ {
1972
+ id: "email",
1973
+ type: "email",
1974
+ value: email,
1975
+ onChange: (e) => setEmail(e.target.value),
1976
+ placeholder: "Enter your email",
1977
+ required: true,
1978
+ disabled: isLoading
1979
+ }
1980
+ )
1981
+ ] }),
1982
+ error && /* @__PURE__ */ jsx18("div", { className: "text-sm text-destructive", role: "alert", children: error }),
1983
+ /* @__PURE__ */ jsx18(
1984
+ Button,
1985
+ {
1986
+ type: "submit",
1987
+ className: "w-full",
1988
+ disabled: !email.trim() || isLoading,
1989
+ children: isLoading ? "Sending..." : "Send Reset Link"
1990
+ }
1991
+ )
1992
+ ] })
1993
+ ] }) });
1994
+ }
1995
+
1996
+ // src/utils/storage/config.ts
1997
+ var FILE_SIZE_LIMITS = {
1998
+ // Images
1999
+ "image/jpeg": 5 * 1024 * 1024,
2000
+ // 5MB
2001
+ "image/png": 5 * 1024 * 1024,
2002
+ // 5MB
2003
+ "image/gif": 10 * 1024 * 1024,
2004
+ // 10MB (for animations)
2005
+ "image/webp": 5 * 1024 * 1024,
2006
+ // 5MB
2007
+ "image/svg+xml": 1 * 1024 * 1024,
2008
+ // 1MB (vector graphics)
2009
+ // Documents
2010
+ "application/pdf": 50 * 1024 * 1024,
2011
+ // 50MB
2012
+ "application/msword": 25 * 1024 * 1024,
2013
+ // 25MB
2014
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": 25 * 1024 * 1024,
2015
+ // 25MB
2016
+ "application/vnd.ms-excel": 25 * 1024 * 1024,
2017
+ // 25MB
2018
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": 25 * 1024 * 1024,
2019
+ // 25MB
2020
+ // Archives
2021
+ "application/zip": 100 * 1024 * 1024,
2022
+ // 100MB
2023
+ "application/x-rar-compressed": 100 * 1024 * 1024,
2024
+ // 100MB
2025
+ // Text files
2026
+ "text/plain": 1 * 1024 * 1024,
2027
+ // 1MB
2028
+ "text/csv": 10 * 1024 * 1024,
2029
+ // 10MB
2030
+ "application/json": 10 * 1024 * 1024
2031
+ // 10MB
2032
+ };
2033
+ var DEFAULT_FILE_SIZE_LIMIT = 10 * 1024 * 1024;
2034
+ var APP_PATH_MAPPING = {
2035
+ "PACE": "event_logos",
2036
+ "TRAC": "trac_accommodation",
2037
+ // Default category for TRAC files
2038
+ "MEDI": "documents",
2039
+ "CAKE": "documents"
2040
+ };
2041
+ var STORAGE_CONFIG = {
2042
+ bucketName: "files",
2043
+ fileSizeLimits: FILE_SIZE_LIMITS,
2044
+ defaultFileSizeLimit: DEFAULT_FILE_SIZE_LIMIT
2045
+ };
2046
+ function getFileSizeLimit(mimeType) {
2047
+ return STORAGE_CONFIG.fileSizeLimits[mimeType] || STORAGE_CONFIG.defaultFileSizeLimit;
2048
+ }
2049
+ function validateFileSize(file) {
2050
+ const limit = getFileSizeLimit(file.type);
2051
+ if (file.size > limit) {
2052
+ const limitMB = Math.round(limit / (1024 * 1024));
2053
+ const fileMB = Math.round(file.size / (1024 * 1024));
2054
+ return {
2055
+ isValid: false,
2056
+ error: `File size (${fileMB}MB) exceeds limit (${limitMB}MB) for ${file.type}`
2057
+ };
2058
+ }
2059
+ return { isValid: true };
2060
+ }
2061
+ function formatFileSize(bytes) {
2062
+ if (bytes === 0) return "0 Bytes";
2063
+ if (bytes < 0) return `${bytes} Bytes`;
2064
+ const k = 1024;
2065
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
2066
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
2067
+ const sizeIndex = Math.min(Math.max(i, 0), sizes.length - 1);
2068
+ return parseFloat((bytes / Math.pow(k, sizeIndex)).toFixed(2)) + " " + sizes[sizeIndex];
2069
+ }
2070
+
2071
+ // src/utils/storage/helpers.ts
2072
+ function generateFilePath(options, fileName) {
2073
+ const { appName, orgId, isPublic = false, customPath } = options;
2074
+ if (isPublic) {
2075
+ if (customPath) {
2076
+ return `public/${customPath}/${fileName}`;
2077
+ }
2078
+ return `public/assets/${appName}/${fileName}`;
2079
+ }
2080
+ const categoryMap = {
2081
+ "accommodation": "trac_accommodation",
2082
+ "activity": "trac_activity",
2083
+ "transport": "trac_transport",
2084
+ "journal": "trac_journal",
2085
+ "logos": "event_logos",
2086
+ "documents": "files"
2087
+ };
2088
+ if (customPath) {
2089
+ const mappedCategory = categoryMap[customPath] || customPath;
2090
+ return `apps/${appName}/${orgId}/${mappedCategory}/${fileName}`;
2091
+ }
2092
+ return `apps/${appName}/${orgId}/files/${fileName}`;
2093
+ }
2094
+ function generateUniqueFileName(originalName) {
2095
+ const timestamp = Date.now();
2096
+ const uuid = crypto.randomUUID();
2097
+ const extension = originalName.split(".").pop() || "";
2098
+ const baseName = originalName.replace(/\.[^/.]+$/, "");
2099
+ return `${timestamp}-${uuid}-${baseName}.${extension}`;
2100
+ }
2101
+ async function extractFileMetadata(file, options, uploadedBy) {
2102
+ const metadata = {
2103
+ mimeType: file.type,
2104
+ size: file.size,
2105
+ orgId: options.orgId,
2106
+ appName: options.appName,
2107
+ uploadedBy,
2108
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
2109
+ tags: options.tags || [],
2110
+ isPublic: options.isPublic || false,
2111
+ customMetadata: options.metadata || {}
2112
+ };
2113
+ if (file.type.startsWith("image/")) {
2114
+ try {
2115
+ const dimensions = await getImageDimensions(file);
2116
+ metadata.width = dimensions.width;
2117
+ metadata.height = dimensions.height;
2118
+ } catch (error) {
2119
+ console.warn("Could not extract image dimensions:", error);
2120
+ }
2121
+ }
2122
+ try {
2123
+ metadata.hash = await generateFileHash(file);
2124
+ } catch (error) {
2125
+ console.warn("Could not generate file hash:", error);
2126
+ }
2127
+ return metadata;
2128
+ }
2129
+ async function getImageDimensions(file) {
2130
+ return new Promise((resolve, reject) => {
2131
+ const img = new Image();
2132
+ const url = URL.createObjectURL(file);
2133
+ img.onload = () => {
2134
+ URL.revokeObjectURL(url);
2135
+ resolve({ width: img.width, height: img.height });
2136
+ };
2137
+ img.onerror = () => {
2138
+ URL.revokeObjectURL(url);
2139
+ reject(new Error("Could not load image"));
2140
+ };
2141
+ img.src = url;
2142
+ });
2143
+ }
2144
+ async function generateFileHash(file) {
2145
+ const buffer = await file.arrayBuffer();
2146
+ const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
2147
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
2148
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2149
+ return `sha256:${hashHex}`;
2150
+ }
2151
+ async function uploadFile(supabase, file, options) {
2152
+ try {
2153
+ const sizeValidation = validateFileSize(file);
2154
+ if (!sizeValidation.isValid) {
2155
+ return {
2156
+ success: false,
2157
+ error: sizeValidation.error
2158
+ };
2159
+ }
2160
+ const uniqueFileName = generateUniqueFileName(file.name);
2161
+ const filePath = generateFilePath(options, uniqueFileName);
2162
+ const metadata = await extractFileMetadata(file, options, "current-user");
2163
+ const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).upload(filePath, file, {
2164
+ cacheControl: "3600",
2165
+ upsert: false,
2166
+ contentType: file.type
2167
+ });
2168
+ if (error) {
2169
+ return {
2170
+ success: false,
2171
+ error: `Upload failed: ${error.message}`
2172
+ };
2173
+ }
2174
+ let publicUrl;
2175
+ if (options.isPublic) {
2176
+ const { data: urlData } = supabase.storage.from(STORAGE_CONFIG.bucketName).getPublicUrl(filePath);
2177
+ publicUrl = urlData.publicUrl;
2178
+ }
2179
+ return {
2180
+ success: true,
2181
+ path: filePath,
2182
+ publicUrl,
2183
+ metadata
2184
+ };
2185
+ } catch (error) {
2186
+ return {
2187
+ success: false,
2188
+ error: `Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`
2189
+ };
2190
+ }
2191
+ }
2192
+ function getPublicUrl(supabase, path) {
2193
+ const { data } = supabase.storage.from(STORAGE_CONFIG.bucketName).getPublicUrl(path);
2194
+ return data.publicUrl;
2195
+ }
2196
+ async function getSignedUrl(supabase, path, options) {
2197
+ try {
2198
+ const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).createSignedUrl(path, options.expiresIn || 3600);
2199
+ if (error) {
2200
+ console.error("Failed to create signed URL:", error);
2201
+ return null;
2202
+ }
2203
+ return {
2204
+ url: data.signedUrl,
2205
+ expiresAt: new Date(Date.now() + (options.expiresIn || 3600) * 1e3).toISOString()
2206
+ };
2207
+ } catch (error) {
2208
+ console.error("Failed to create signed URL:", error);
2209
+ return null;
2210
+ }
2211
+ }
2212
+ async function deleteFile(supabase, path) {
2213
+ try {
2214
+ const { error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).remove([path]);
2215
+ if (error) {
2216
+ return {
2217
+ success: false,
2218
+ error: `Delete failed: ${error.message}`
2219
+ };
2220
+ }
2221
+ return { success: true };
2222
+ } catch (error) {
2223
+ return {
2224
+ success: false,
2225
+ error: `Delete failed: ${error instanceof Error ? error.message : "Unknown error"}`
2226
+ };
2227
+ }
2228
+ }
2229
+ async function listFiles(supabase, options) {
2230
+ try {
2231
+ const pathPrefix = `apps/${options.appName}/${options.orgId}/`;
2232
+ const searchPath = options.pathPrefix ? `${pathPrefix}${options.pathPrefix}` : pathPrefix;
2233
+ const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).list(searchPath, {
2234
+ limit: options.limit || 100,
2235
+ offset: options.offset || 0,
2236
+ sortBy: { column: "created_at", order: "desc" }
2237
+ });
2238
+ if (error) {
2239
+ console.error("Failed to list files:", error);
2240
+ return { files: [], totalCount: 0, hasMore: false };
2241
+ }
2242
+ const files = (data || []).map((item) => ({
2243
+ name: item.name,
2244
+ path: `${searchPath}${item.name}`,
2245
+ size: item.metadata?.size || 0,
2246
+ mimeType: item.metadata?.mimetype || "application/octet-stream",
2247
+ lastModified: item.updated_at || item.created_at || (/* @__PURE__ */ new Date()).toISOString(),
2248
+ metadata: {
2249
+ mimeType: item.metadata?.mimetype || "application/octet-stream",
2250
+ size: item.metadata?.size || 0,
2251
+ orgId: options.orgId,
2252
+ appName: options.appName,
2253
+ uploadedBy: "unknown",
2254
+ uploadedAt: item.created_at || (/* @__PURE__ */ new Date()).toISOString(),
2255
+ isPublic: false
2256
+ }
2257
+ }));
2258
+ return {
2259
+ files,
2260
+ totalCount: files.length,
2261
+ hasMore: files.length >= (options.limit || 100)
2262
+ };
2263
+ } catch (error) {
2264
+ console.error("Failed to list files:", error);
2265
+ return { files: [], totalCount: 0, hasMore: false };
2266
+ }
2267
+ }
2268
+ async function archiveFile(supabase, path, options) {
2269
+ try {
2270
+ const archivedPath = path.replace(`apps/${options.appName}/${options.orgId}/`, `archived/${options.appName}/${options.orgId}/`);
2271
+ const { error: copyError } = await supabase.storage.from(STORAGE_CONFIG.bucketName).copy(path, archivedPath);
2272
+ if (copyError) {
2273
+ return {
2274
+ success: false,
2275
+ error: `Archive failed: ${copyError.message}`
2276
+ };
2277
+ }
2278
+ const deleteResult = await deleteFile(supabase, path);
2279
+ if (!deleteResult.success) {
2280
+ return deleteResult;
2281
+ }
2282
+ return { success: true };
2283
+ } catch (error) {
2284
+ return {
2285
+ success: false,
2286
+ error: `Archive failed: ${error instanceof Error ? error.message : "Unknown error"}`
2287
+ };
2288
+ }
2289
+ }
2290
+
2291
+ // src/hooks/useStorage.ts
2292
+ import { useState as useState9, useCallback as useCallback5 } from "react";
2293
+ function useStorage({ supabase, appName, orgId }) {
2294
+ const [isUploading, setIsUploading] = useState9(false);
2295
+ const [uploadError, setUploadError] = useState9(null);
2296
+ const [isListing, setIsListing] = useState9(false);
2297
+ const [listError, setListError] = useState9(null);
2298
+ const [files, setFiles] = useState9([]);
2299
+ const handleUploadFile = useCallback5(async (file, options = {}) => {
2300
+ setIsUploading(true);
2301
+ setUploadError(null);
2302
+ try {
2303
+ const uploadOptions = {
2304
+ appName,
2305
+ orgId,
2306
+ isPublic: false,
2307
+ ...options
2308
+ };
2309
+ const result = await uploadFile(supabase, file, uploadOptions);
2310
+ if (result.success) {
2311
+ await refreshFiles();
2312
+ } else {
2313
+ setUploadError(result.error || "Upload failed");
2314
+ }
2315
+ return result;
2316
+ } catch (error) {
2317
+ const errorMessage = error instanceof Error ? error.message : "Upload failed";
2318
+ setUploadError(errorMessage);
2319
+ return {
2320
+ success: false,
2321
+ error: errorMessage
2322
+ };
2323
+ } finally {
2324
+ setIsUploading(false);
2325
+ }
2326
+ }, [supabase, appName, orgId]);
2327
+ const handleGetPublicUrl = useCallback5((path) => {
2328
+ return getPublicUrl(supabase, path);
2329
+ }, [supabase]);
2330
+ const handleGetSignedUrl = useCallback5(async (path, expiresIn) => {
2331
+ try {
2332
+ const result = await getSignedUrl(supabase, path, {
2333
+ appName,
2334
+ orgId,
2335
+ expiresIn
2336
+ });
2337
+ return result?.url || null;
2338
+ } catch (error) {
2339
+ console.error("Failed to get signed URL:", error);
2340
+ return null;
2341
+ }
2342
+ }, [supabase, appName, orgId]);
2343
+ const handleDeleteFile = useCallback5(async (path) => {
2344
+ try {
2345
+ const result = await deleteFile(supabase, path);
2346
+ if (result.success) {
2347
+ await refreshFiles();
2348
+ }
2349
+ return result;
2350
+ } catch (error) {
2351
+ return {
2352
+ success: false,
2353
+ error: error instanceof Error ? error.message : "Delete failed"
2354
+ };
2355
+ }
2356
+ }, [supabase]);
2357
+ const handleArchiveFile = useCallback5(async (path) => {
2358
+ try {
2359
+ const result = await archiveFile(supabase, path, { appName, orgId });
2360
+ if (result.success) {
2361
+ await refreshFiles();
2362
+ }
2363
+ return result;
2364
+ } catch (error) {
2365
+ return {
2366
+ success: false,
2367
+ error: error instanceof Error ? error.message : "Archive failed"
2368
+ };
2369
+ }
2370
+ }, [supabase, appName, orgId]);
2371
+ const handleListFiles = useCallback5(async (options = {}) => {
2372
+ setIsListing(true);
2373
+ setListError(null);
2374
+ try {
2375
+ const listOptions = {
2376
+ appName,
2377
+ orgId,
2378
+ ...options
2379
+ };
2380
+ const result = await listFiles(supabase, listOptions);
2381
+ setFiles(result.files);
2382
+ return result;
2383
+ } catch (error) {
2384
+ const errorMessage = error instanceof Error ? error.message : "List failed";
2385
+ setListError(errorMessage);
2386
+ return { files: [], totalCount: 0, hasMore: false };
2387
+ } finally {
2388
+ setIsListing(false);
2389
+ }
2390
+ }, [supabase, appName, orgId]);
2391
+ const refreshFiles = useCallback5(async () => {
2392
+ await handleListFiles();
2393
+ }, [handleListFiles]);
2394
+ return {
2395
+ // Upload
2396
+ uploadFile: handleUploadFile,
2397
+ isUploading,
2398
+ uploadError,
2399
+ // URLs
2400
+ getPublicUrl: handleGetPublicUrl,
2401
+ getSignedUrl: handleGetSignedUrl,
2402
+ getFileUrl: handleGetPublicUrl,
2403
+ // Alias for getPublicUrl
2404
+ // File management
2405
+ deleteFile: handleDeleteFile,
2406
+ archiveFile: handleArchiveFile,
2407
+ // Listing
2408
+ listFiles: handleListFiles,
2409
+ isListing,
2410
+ listError,
2411
+ isLoading: isListing,
2412
+ // Alias for isListing
2413
+ error: listError,
2414
+ // Alias for listError
2415
+ // State
2416
+ files,
2417
+ refreshFiles
2418
+ };
2419
+ }
2420
+ function useFileUpload({ supabase, appName, orgId }) {
2421
+ const [uploadProgress, setUploadProgress] = useState9(0);
2422
+ const [isUploading, setIsUploading] = useState9(false);
2423
+ const [uploadError, setUploadError] = useState9(null);
2424
+ const uploadWithProgress = useCallback5(async (file, options = {}) => {
2425
+ setIsUploading(true);
2426
+ setUploadProgress(0);
2427
+ setUploadError(null);
2428
+ try {
2429
+ const progressInterval = setInterval(() => {
2430
+ setUploadProgress((prev) => Math.min(prev + 10, 90));
2431
+ }, 100);
2432
+ const uploadOptions = {
2433
+ appName,
2434
+ orgId,
2435
+ isPublic: false,
2436
+ ...options
2437
+ };
2438
+ const result = await uploadFile(supabase, file, uploadOptions);
2439
+ clearInterval(progressInterval);
2440
+ setUploadProgress(100);
2441
+ if (!result.success) {
2442
+ setUploadError(result.error || "Upload failed");
2443
+ }
2444
+ return result;
2445
+ } catch (error) {
2446
+ const errorMessage = error instanceof Error ? error.message : "Upload failed";
2447
+ setUploadError(errorMessage);
2448
+ return {
2449
+ success: false,
2450
+ error: errorMessage
2451
+ };
2452
+ } finally {
2453
+ setIsUploading(false);
2454
+ setTimeout(() => setUploadProgress(0), 1e3);
2455
+ }
2456
+ }, [supabase, appName, orgId]);
2457
+ return {
2458
+ uploadWithProgress,
2459
+ uploadProgress,
2460
+ isUploading,
2461
+ uploadError
2462
+ };
2463
+ }
2464
+
2465
+ // src/components/FileUpload/FileUpload.tsx
2466
+ import { useCallback as useCallback6, useState as useState10 } from "react";
2467
+ init_Button();
2468
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2469
+ function FileUpload({
2470
+ supabase,
2471
+ appName,
2472
+ orgId,
2473
+ onUploadComplete,
2474
+ onUploadStart,
2475
+ accept = "*/*",
2476
+ maxSize,
2477
+ multiple = false,
2478
+ disabled = false,
2479
+ className = "",
2480
+ children
2481
+ }) {
2482
+ const [dragActive, setDragActive] = useState10(false);
2483
+ const [selectedFiles, setSelectedFiles] = useState10([]);
2484
+ const [validationErrors, setValidationErrors] = useState10([]);
2485
+ const { uploadWithProgress, uploadProgress, isUploading, uploadError } = useFileUpload({
2486
+ supabase,
2487
+ appName,
2488
+ orgId
2489
+ });
2490
+ const validateFiles = useCallback6((files) => {
2491
+ const errors = [];
2492
+ files.forEach((file, index) => {
2493
+ const sizeValidation = validateFileSize(file);
2494
+ if (!sizeValidation.isValid) {
2495
+ errors.push(`File ${index + 1}: ${sizeValidation.error}`);
2496
+ }
2497
+ if (maxSize && file.size > maxSize) {
2498
+ const fileMB = Math.round(file.size / (1024 * 1024));
2499
+ const maxMB = Math.round(maxSize / (1024 * 1024));
2500
+ errors.push(`File ${index + 1}: Size (${fileMB}MB) exceeds limit (${maxMB}MB)`);
2501
+ }
2502
+ });
2503
+ return errors;
2504
+ }, [maxSize]);
2505
+ const handleFileSelect = useCallback6((files) => {
2506
+ if (!files) return;
2507
+ const fileArray = Array.from(files);
2508
+ const errors = validateFiles(fileArray);
2509
+ setValidationErrors(errors);
2510
+ setSelectedFiles(fileArray);
2511
+ }, [validateFiles]);
2512
+ const handleDrag = useCallback6((e) => {
2513
+ e.preventDefault();
2514
+ e.stopPropagation();
2515
+ if (e.type === "dragenter" || e.type === "dragover") {
2516
+ setDragActive(true);
2517
+ } else if (e.type === "dragleave") {
2518
+ setDragActive(false);
2519
+ }
2520
+ }, []);
2521
+ const handleDrop = useCallback6((e) => {
2522
+ e.preventDefault();
2523
+ e.stopPropagation();
2524
+ setDragActive(false);
2525
+ if (disabled) return;
2526
+ const files = e.dataTransfer.files;
2527
+ handleFileSelect(files);
2528
+ }, [disabled, handleFileSelect]);
2529
+ const handleFileInputChange = useCallback6((e) => {
2530
+ handleFileSelect(e.target.files);
2531
+ }, [handleFileSelect]);
2532
+ const handleUpload = useCallback6(async () => {
2533
+ if (selectedFiles.length === 0 || validationErrors.length > 0) return;
2534
+ onUploadStart?.();
2535
+ for (const file of selectedFiles) {
2536
+ const result = await uploadWithProgress(file);
2537
+ onUploadComplete?.(result);
2538
+ }
2539
+ setSelectedFiles([]);
2540
+ setValidationErrors([]);
2541
+ }, [selectedFiles, validationErrors, uploadWithProgress, onUploadComplete, onUploadStart]);
2542
+ const handleClear = useCallback6(() => {
2543
+ setSelectedFiles([]);
2544
+ setValidationErrors([]);
2545
+ }, []);
2546
+ const canUpload = selectedFiles.length > 0 && validationErrors.length === 0 && !isUploading && !disabled;
2547
+ return /* @__PURE__ */ jsxs14("div", { className: `file-upload ${className}`, children: [
2548
+ /* @__PURE__ */ jsxs14(
2549
+ "div",
2550
+ {
2551
+ className: `file-upload__dropzone ${dragActive ? "file-upload__dropzone--active" : ""} ${disabled ? "file-upload__dropzone--disabled" : ""}`,
2552
+ onDragEnter: handleDrag,
2553
+ onDragLeave: handleDrag,
2554
+ onDragOver: handleDrag,
2555
+ onDrop: handleDrop,
2556
+ children: [
2557
+ /* @__PURE__ */ jsx19(
2558
+ "input",
2559
+ {
2560
+ type: "file",
2561
+ accept,
2562
+ multiple,
2563
+ onChange: handleFileInputChange,
2564
+ disabled,
2565
+ className: "file-upload__input"
2566
+ }
2567
+ ),
2568
+ children || /* @__PURE__ */ jsxs14("div", { className: "file-upload__content", children: [
2569
+ /* @__PURE__ */ jsx19("p", { className: "file-upload__text", children: dragActive ? "Drop files here" : "Drag and drop files here or click to select" }),
2570
+ /* @__PURE__ */ jsx19(
2571
+ Button,
2572
+ {
2573
+ type: "button",
2574
+ variant: "outline",
2575
+ disabled,
2576
+ onClick: () => document.querySelector(".file-upload__input")?.click(),
2577
+ children: "Select Files"
2578
+ }
2579
+ )
2580
+ ] })
2581
+ ]
2582
+ }
2583
+ ),
2584
+ selectedFiles.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "file-upload__files", children: [
2585
+ /* @__PURE__ */ jsx19("h4", { className: "file-upload__files-title", children: "Selected Files:" }),
2586
+ /* @__PURE__ */ jsx19("ul", { className: "file-upload__files-list", children: selectedFiles.map((file, index) => /* @__PURE__ */ jsxs14("li", { className: "file-upload__file-item", children: [
2587
+ /* @__PURE__ */ jsx19("span", { className: "file-upload__file-name", children: file.name }),
2588
+ /* @__PURE__ */ jsx19("span", { className: "file-upload__file-size", children: formatFileSize(file.size) })
2589
+ ] }, index)) })
2590
+ ] }),
2591
+ validationErrors.length > 0 && /* @__PURE__ */ jsx19(Alert, { variant: "destructive", className: "file-upload__errors", children: /* @__PURE__ */ jsx19("ul", { children: validationErrors.map((error, index) => /* @__PURE__ */ jsx19("li", { children: error }, index)) }) }),
2592
+ isUploading && /* @__PURE__ */ jsxs14("div", { className: "file-upload__progress", children: [
2593
+ /* @__PURE__ */ jsx19(Progress, { value: uploadProgress, max: 100 }),
2594
+ /* @__PURE__ */ jsxs14("p", { className: "file-upload__progress-text", children: [
2595
+ "Uploading... ",
2596
+ uploadProgress,
2597
+ "%"
2598
+ ] })
2599
+ ] }),
2600
+ uploadError && /* @__PURE__ */ jsx19(Alert, { variant: "destructive", className: "file-upload__error", children: uploadError }),
2601
+ selectedFiles.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "file-upload__actions", children: [
2602
+ /* @__PURE__ */ jsx19(
2603
+ Button,
2604
+ {
2605
+ onClick: handleUpload,
2606
+ disabled: !canUpload,
2607
+ className: "file-upload__upload-btn",
2608
+ children: isUploading ? "Uploading..." : `Upload ${selectedFiles.length} file${selectedFiles.length > 1 ? "s" : ""}`
2609
+ }
2610
+ ),
2611
+ /* @__PURE__ */ jsx19(
2612
+ Button,
2613
+ {
2614
+ variant: "outline",
2615
+ onClick: handleClear,
2616
+ disabled: isUploading,
2617
+ className: "file-upload__clear-btn",
2618
+ children: "Clear"
2619
+ }
2620
+ )
2621
+ ] })
2622
+ ] });
2623
+ }
2624
+
2625
+ // src/components/PublicLayout/EventLogo.tsx
2626
+ import { useMemo as useMemo6 } from "react";
2627
+ import { jsx as jsx20 } from "react/jsx-runtime";
2628
+ var sizeClasses = {
2629
+ xs: "h-4 w-4 text-xs",
2630
+ sm: "h-6 w-6 text-sm",
2631
+ md: "h-8 w-8 text-base",
2632
+ lg: "h-12 w-12 text-lg",
2633
+ xl: "h-16 w-16 text-xl",
2634
+ "2xl": "h-20 w-20 text-2xl"
2635
+ };
2636
+ function defaultGenerateFallbackText(eventName) {
2637
+ if (!eventName) return "EV";
2638
+ return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
2639
+ }
2640
+ function EventLogo({
2641
+ eventId,
2642
+ eventName,
2643
+ organisationId,
2644
+ size = "md",
2645
+ className = "",
2646
+ showFallback = true,
2647
+ generateFallbackText = defaultGenerateFallbackText,
2648
+ validateImage = true,
2649
+ loadingComponent: LoadingComponent,
2650
+ errorComponent: ErrorComponent
2651
+ }) {
2652
+ let isPublicPage = false;
2653
+ try {
2654
+ const { isPublicPage: publicContext } = usePublicPageContext();
2655
+ isPublicPage = publicContext === true;
2656
+ } catch {
2657
+ isPublicPage = false;
2658
+ }
2659
+ const shouldAvoidAuthContext = useMemo6(() => {
2660
+ if (isPublicPage) return true;
2661
+ try {
2662
+ (init_UnifiedAuthProvider(), __toCommonJS(UnifiedAuthProvider_exports)).useUnifiedAuth();
2663
+ return false;
2664
+ } catch {
2665
+ return true;
2666
+ }
2667
+ }, [isPublicPage]);
2668
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2669
+ const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
2670
+ const { supabase } = usePublicPageContext();
2671
+ if (!supabase) {
2672
+ return /* @__PURE__ */ jsx20("div", { className: `${sizeClasses[size]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText(eventName) : "EV" });
2673
+ }
2674
+ const {
2675
+ logoUrl,
2676
+ fallbackText,
2677
+ isLoading,
2678
+ error
2679
+ } = usePublicEventLogo(
2680
+ eventId,
2681
+ eventName,
2682
+ organisationId,
2683
+ // Always pass organisationId, let the hook handle validation
2684
+ {
2685
+ validateImage,
2686
+ generateFallbackText,
2687
+ supabase
2688
+ }
2689
+ );
2690
+ const sizeClass = useMemo6(() => sizeClasses[size], [size]);
2691
+ const combinedClasses = useMemo6(() => {
2692
+ const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
2693
+ return `${baseClasses} ${sizeClass} ${className}`.trim();
2694
+ }, [sizeClass, className]);
2695
+ if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
2696
+ return /* @__PURE__ */ jsx20("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
2697
+ }
2698
+ if (isLoading) {
2699
+ if (LoadingComponent) {
2700
+ return /* @__PURE__ */ jsx20(LoadingComponent, {});
2701
+ }
2702
+ return /* @__PURE__ */ jsx20("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx20("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
2703
+ }
2704
+ if (error) {
2705
+ if (ErrorComponent) {
2706
+ return /* @__PURE__ */ jsx20(ErrorComponent, { error });
2707
+ }
2708
+ if (showFallback) {
2709
+ return /* @__PURE__ */ jsx20("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
2710
+ }
2711
+ return null;
2712
+ }
2713
+ if (!logoUrl) {
2714
+ if (showFallback) {
2715
+ return /* @__PURE__ */ jsx20("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
2716
+ }
2717
+ return null;
2718
+ }
2719
+ return /* @__PURE__ */ jsx20(
2720
+ "img",
2721
+ {
2722
+ src: logoUrl,
2723
+ alt: `${eventName} logo`,
2724
+ className: `${sizeClass} ${className}`.trim(),
2725
+ onError: (e) => {
2726
+ const target = e.target;
2727
+ target.style.display = "none";
2728
+ const fallback = document.createElement("div");
2729
+ fallback.className = combinedClasses;
2730
+ fallback.textContent = fallbackText;
2731
+ fallback.title = `${eventName} logo`;
2732
+ target.parentNode?.insertBefore(fallback, target.nextSibling);
2733
+ }
2734
+ }
2735
+ );
2736
+ }
2737
+ function EventLogoCompact(props) {
2738
+ return /* @__PURE__ */ jsx20(
2739
+ EventLogo,
2740
+ {
2741
+ ...props,
2742
+ size: "sm",
2743
+ className: `${props.className || ""} rounded-sm`
2744
+ }
2745
+ );
2746
+ }
2747
+ function EventLogoLarge(props) {
2748
+ return /* @__PURE__ */ jsx20(
2749
+ EventLogo,
2750
+ {
2751
+ ...props,
2752
+ size: "xl",
2753
+ className: `${props.className || ""} rounded-lg`
2754
+ }
2755
+ );
2756
+ }
2757
+
2758
+ // src/components/PublicLayout/PublicPageHeader.tsx
2759
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2760
+ function PublicPageHeader({
2761
+ event,
2762
+ eventCode,
2763
+ title,
2764
+ description,
2765
+ showEventLogo = true,
2766
+ showAppLogo = true,
2767
+ className = "",
2768
+ children,
2769
+ customAppLogo,
2770
+ customEventLogo
2771
+ }) {
2772
+ const { appName } = useAppConfig();
2773
+ const headerClasses = `bg-white border-b border-gray-200 ${className}`.trim();
2774
+ return /* @__PURE__ */ jsx21("header", { className: headerClasses, children: /* @__PURE__ */ jsxs15("div", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto", children: [
2775
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between py-4", children: [
2776
+ showAppLogo && /* @__PURE__ */ jsx21("div", { className: "flex-shrink-0", children: customAppLogo || /* @__PURE__ */ jsxs15("div", { className: "flex items-center", children: [
2777
+ /* @__PURE__ */ jsx21(
2778
+ "img",
2779
+ {
2780
+ className: "h-8 w-auto",
2781
+ src: `/${appName.toLowerCase()}_logo_wide.svg`,
2782
+ alt: appName
2783
+ }
2784
+ ),
2785
+ /* @__PURE__ */ jsx21("span", { className: "ml-2 text-lg font-semibold text-gray-900", children: appName })
2786
+ ] }) }),
2787
+ showEventLogo && /* @__PURE__ */ jsx21("div", { className: "flex-shrink-0", children: customEventLogo || /* @__PURE__ */ jsx21(
2788
+ EventLogo,
2789
+ {
2790
+ eventId: event.event_id,
2791
+ eventName: event.event_name,
2792
+ organisationId: event.organisation_id,
2793
+ size: "md",
2794
+ className: "h-12 w-12"
2795
+ }
2796
+ ) })
2797
+ ] }),
2798
+ /* @__PURE__ */ jsx21("div", { className: "pb-4", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
2799
+ /* @__PURE__ */ jsx21("h1", { className: "text-3xl font-bold text-gray-900 mb-2", children: event.event_name }),
2800
+ event.event_venue && /* @__PURE__ */ jsx21("p", { className: "text-md text-gray-500 mb-4", children: event.event_venue }),
2801
+ title && /* @__PURE__ */ jsxs15("div", { className: "mt-6", children: [
2802
+ /* @__PURE__ */ jsx21("h2", { className: "text-2xl font-semibold text-gray-800 mb-2", children: title }),
2803
+ description && /* @__PURE__ */ jsx21("p", { className: "text-lg text-gray-600 max-w-3xl mx-auto", children: description })
2804
+ ] }),
2805
+ children && /* @__PURE__ */ jsx21("div", { className: "mt-4", children })
2806
+ ] }) })
2807
+ ] }) });
2808
+ }
2809
+
2810
+ // src/components/PublicLayout/PublicPageFooter.tsx
2811
+ init_cn();
2812
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2813
+ function PublicPageFooter({
2814
+ event,
2815
+ companyName = "Solvera Solutions Pty Ltd",
2816
+ year = (/* @__PURE__ */ new Date()).getFullYear(),
2817
+ links,
2818
+ className = "",
2819
+ logo,
2820
+ copyright,
2821
+ children
2822
+ }) {
2823
+ const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
2824
+ return /* @__PURE__ */ jsx22("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs16("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
2825
+ logo && /* @__PURE__ */ jsx22("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
2826
+ children && /* @__PURE__ */ jsx22(Fragment5, { children }),
2827
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: copyrightText }),
2828
+ links && links.length > 0 && /* @__PURE__ */ jsx22("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx22("li", { children: /* @__PURE__ */ jsx22("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
2829
+ ] }) });
2830
+ }
2831
+
2832
+ // src/components/PublicLayout/PublicLoadingSpinner.tsx
2833
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
2834
+ var sizeClasses2 = {
2835
+ sm: "h-4 w-4",
2836
+ md: "h-8 w-8",
2837
+ lg: "h-12 w-12",
2838
+ xl: "h-16 w-16"
2839
+ };
2840
+ function PublicLoadingSpinner({
2841
+ message = "Loading...",
2842
+ size = "md",
2843
+ className = "",
2844
+ showLogo = true,
2845
+ customMessage,
2846
+ centered = true
2847
+ }) {
2848
+ const sizeClass = sizeClasses2[size];
2849
+ const displayMessage = customMessage || message;
2850
+ const content = /* @__PURE__ */ jsxs17("div", { className: `flex flex-col items-center ${className}`, children: [
2851
+ showLogo && /* @__PURE__ */ jsx23("div", { className: "mb-4", children: /* @__PURE__ */ jsx23(
2852
+ "img",
2853
+ {
2854
+ className: "h-8 w-auto",
2855
+ src: "/pace_logo_wide.svg",
2856
+ alt: "PACE Core"
2857
+ }
2858
+ ) }),
2859
+ /* @__PURE__ */ jsxs17("div", { className: "relative", children: [
2860
+ /* @__PURE__ */ jsx23(
2861
+ "div",
2862
+ {
2863
+ className: `${sizeClass} border-2 border-gray-200 border-t-blue-600 rounded-full animate-spin`,
2864
+ role: "status",
2865
+ "aria-label": "Loading"
2866
+ }
2867
+ ),
2868
+ /* @__PURE__ */ jsx23("span", { className: "sr-only", children: displayMessage })
2869
+ ] }),
2870
+ displayMessage && /* @__PURE__ */ jsx23("p", { className: "mt-4 text-sm text-gray-600 text-center", children: displayMessage })
2871
+ ] });
2872
+ if (centered) {
2873
+ return /* @__PURE__ */ jsx23("div", { className: "min-h-screen bg-white flex items-center justify-center", children: /* @__PURE__ */ jsx23("div", { className: "max-w-md mx-auto px-4", children: content }) });
2874
+ }
2875
+ return content;
2876
+ }
2877
+ function PublicLoadingSpinnerFullPage({
2878
+ message = "Loading event details...",
2879
+ eventName,
2880
+ className = ""
2881
+ }) {
2882
+ return /* @__PURE__ */ jsx23("div", { className: `min-h-screen bg-white flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs17("div", { className: "max-w-md mx-auto text-center px-4", children: [
2883
+ /* @__PURE__ */ jsx23("div", { className: "mb-8", children: /* @__PURE__ */ jsx23(
2884
+ "img",
2885
+ {
2886
+ className: "h-12 w-auto mx-auto",
2887
+ src: "/pace_logo_wide.svg",
2888
+ alt: "PACE Core"
2889
+ }
2890
+ ) }),
2891
+ eventName && /* @__PURE__ */ jsx23("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: eventName }),
2892
+ /* @__PURE__ */ jsx23("div", { className: "relative mb-6", children: /* @__PURE__ */ jsx23(
2893
+ "div",
2894
+ {
2895
+ className: "h-12 w-12 border-4 border-gray-200 border-t-blue-600 rounded-full animate-spin mx-auto",
2896
+ role: "status",
2897
+ "aria-label": "Loading"
2898
+ }
2899
+ ) }),
2900
+ /* @__PURE__ */ jsx23("p", { className: "text-lg text-gray-600", children: message }),
2901
+ /* @__PURE__ */ jsxs17("div", { className: "mt-4 flex justify-center space-x-1", children: [
2902
+ /* @__PURE__ */ jsx23("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
2903
+ /* @__PURE__ */ jsx23("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
2904
+ /* @__PURE__ */ jsx23("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
2905
+ ] })
2906
+ ] }) });
2907
+ }
2908
+ function PublicLoadingSkeleton({
2909
+ lines = 3,
2910
+ className = ""
2911
+ }) {
2912
+ return /* @__PURE__ */ jsx23("div", { className: `animate-pulse ${className}`, children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx23(
2913
+ "div",
2914
+ {
2915
+ className: `h-4 bg-gray-200 rounded mb-2 ${index === lines - 1 ? "w-3/4" : "w-full"}`
2916
+ },
2917
+ index
2918
+ )) });
2919
+ }
2920
+
2921
+ // src/components/PublicLayout/PublicPageLayout.tsx
2922
+ import { useMemo as useMemo7 } from "react";
2923
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
2924
+ function PublicPageLayout({
2925
+ eventCode,
2926
+ children,
2927
+ event = null,
2928
+ showFooter = true,
2929
+ className = "",
2930
+ errorFallback: ErrorFallback,
2931
+ loadingFallback: LoadingFallback = PublicLoadingSpinner,
2932
+ customHeader,
2933
+ customFooter,
2934
+ showValidationErrors = true
2935
+ }) {
2936
+ const isLoading = false;
2937
+ const error = null;
2938
+ const refetch = async () => {
2939
+ };
2940
+ const layoutClasses = useMemo7(() => {
2941
+ const baseClasses = "min-h-screen bg-white flex flex-col";
2942
+ return `${baseClasses} ${className}`.trim();
2943
+ }, [className]);
2944
+ if (isLoading) {
2945
+ return /* @__PURE__ */ jsx24("div", { className: layoutClasses, children: /* @__PURE__ */ jsx24("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx24(LoadingFallback, {}) }) });
2946
+ }
2947
+ if (error && showValidationErrors) {
2948
+ return /* @__PURE__ */ jsx24("div", { className: layoutClasses, children: /* @__PURE__ */ jsx24("div", { className: "flex-1 flex items-center justify-center", children: ErrorFallback ? /* @__PURE__ */ jsx24(ErrorFallback, { error, retry: refetch }) : /* @__PURE__ */ jsxs18("div", { className: "text-center p-8", children: [
2949
+ /* @__PURE__ */ jsx24("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Found" }),
2950
+ /* @__PURE__ */ jsxs18("p", { className: "text-gray-600 mb-6", children: [
2951
+ 'The event code "',
2952
+ eventCode,
2953
+ '" is invalid or the event is not available for public viewing.'
2954
+ ] }),
2955
+ /* @__PURE__ */ jsx24(
2956
+ "button",
2957
+ {
2958
+ onClick: refetch,
2959
+ className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
2960
+ children: "Try Again"
2961
+ }
2962
+ )
2963
+ ] }) }) });
2964
+ }
2965
+ if (!event) {
2966
+ return /* @__PURE__ */ jsx24("div", { className: layoutClasses, children: /* @__PURE__ */ jsx24("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs18("div", { className: "text-center p-8", children: [
2967
+ /* @__PURE__ */ jsx24("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Available" }),
2968
+ /* @__PURE__ */ jsx24("p", { className: "text-gray-600 mb-6", children: "This event is not available for public viewing." }),
2969
+ /* @__PURE__ */ jsx24(
2970
+ "button",
2971
+ {
2972
+ onClick: refetch,
2973
+ className: "px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
2974
+ children: "Try Again"
2975
+ }
2976
+ )
2977
+ ] }) }) });
2978
+ }
2979
+ return /* @__PURE__ */ jsx24(PublicErrorBoundary, { children: /* @__PURE__ */ jsxs18("div", { className: layoutClasses, children: [
2980
+ customHeader || /* @__PURE__ */ jsx24(
2981
+ PublicPageHeader,
2982
+ {
2983
+ event,
2984
+ eventCode
2985
+ }
2986
+ ),
2987
+ /* @__PURE__ */ jsx24("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children }),
2988
+ showFooter && (customFooter || /* @__PURE__ */ jsx24(PublicPageFooter, { event }))
2989
+ ] }) });
2990
+ }
2991
+ function usePublicPageContext2() {
2992
+ return {
2993
+ eventCode: null,
2994
+ eventId: null,
2995
+ event: null,
2996
+ isLoading: false,
2997
+ error: null,
2998
+ refetch: async () => {
2999
+ },
3000
+ isPublicPage: true
3001
+ };
3002
+ }
3003
+
3004
+ // src/components/PublicLayout/PublicPageDebugger.tsx
3005
+ import { useEffect as useEffect5 } from "react";
3006
+ import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
3007
+ function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
3008
+ useEffect5(() => {
3009
+ if (!enabled) return;
3010
+ console.log(`[${label}] Component mounted`);
3011
+ try {
3012
+ const { isPublicPage } = usePublicPageContext();
3013
+ console.log(`[${label}] Public page context detected:`, isPublicPage);
3014
+ } catch (error) {
3015
+ console.warn(`[${label}] Not in PublicPageProvider context:`, error instanceof Error ? error.message : String(error));
3016
+ }
3017
+ try {
3018
+ const { isAuthenticated } = (init_UnifiedAuthProvider(), __toCommonJS(UnifiedAuthProvider_exports)).useUnifiedAuth();
3019
+ console.warn(`[${label}] AUTHENTICATION CONTEXT DETECTED! This should not happen in public pages.`);
3020
+ console.warn(`[${label}] isAuthenticated:`, isAuthenticated);
3021
+ } catch (error) {
3022
+ console.log(`[${label}] No authentication context detected (good for public pages)`);
3023
+ }
3024
+ try {
3025
+ const { selectedOrganisation } = (init_OrganisationProvider(), __toCommonJS(OrganisationProvider_exports)).useOrganisations();
3026
+ console.warn(`[${label}] ORGANISATION CONTEXT DETECTED! This should not happen in public pages.`);
3027
+ console.warn(`[${label}] selectedOrganisation:`, selectedOrganisation);
3028
+ } catch (error) {
3029
+ console.log(`[${label}] No organisation context detected (good for public pages)`);
3030
+ }
3031
+ try {
3032
+ const { events } = (init_EventProvider(), __toCommonJS(EventProvider_exports)).useEvents();
3033
+ console.warn(`[${label}] EVENT CONTEXT DETECTED! This should not happen in public pages.`);
3034
+ console.warn(`[${label}] events:`, events);
3035
+ } catch (error) {
3036
+ console.log(`[${label}] No event context detected (good for public pages)`);
3037
+ }
3038
+ const supabaseUrl = import.meta.env?.VITE_SUPABASE_URL || process.env.VITE_SUPABASE_URL;
3039
+ const supabaseKey = import.meta.env?.VITE_SUPABASE_ANON_KEY || process.env.VITE_SUPABASE_ANON_KEY;
3040
+ console.log(`[${label}] Environment variables:`, {
3041
+ supabaseUrl: supabaseUrl ? "Present" : "Missing",
3042
+ supabaseKey: supabaseKey ? "Present" : "Missing"
3043
+ });
3044
+ return () => {
3045
+ console.log(`[${label}] Component unmounted`);
3046
+ };
3047
+ }, [enabled, label]);
3048
+ if (!enabled) return null;
3049
+ return /* @__PURE__ */ jsxs19("div", { style: {
3050
+ position: "fixed",
3051
+ top: 0,
3052
+ right: 0,
3053
+ background: "rgba(0,0,0,0.8)",
3054
+ color: "white",
3055
+ padding: "8px",
3056
+ fontSize: "12px",
3057
+ zIndex: 9999,
3058
+ fontFamily: "monospace"
3059
+ }, children: [
3060
+ /* @__PURE__ */ jsx25("div", { children: "Public Page Debugger" }),
3061
+ /* @__PURE__ */ jsx25("div", { children: "Check console for context analysis" })
3062
+ ] });
3063
+ }
3064
+
3065
+ // src/components/PublicLayout/PublicPageDiagnostic.tsx
3066
+ import { useEffect as useEffect6, useState as useState11 } from "react";
3067
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
3068
+ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
3069
+ const [diagnostics, setDiagnostics] = useState11({
3070
+ hasPublicPageContext: false,
3071
+ hasAuthContext: false,
3072
+ hasOrgContext: false,
3073
+ hasEventContext: false,
3074
+ hasEnvironmentVars: false,
3075
+ routeParams: null
3076
+ });
3077
+ useEffect6(() => {
3078
+ if (!enabled) return;
3079
+ const runDiagnostics = () => {
3080
+ const newDiagnostics = {
3081
+ hasPublicPageContext: false,
3082
+ hasAuthContext: false,
3083
+ hasOrgContext: false,
3084
+ hasEventContext: false,
3085
+ hasEnvironmentVars: false,
3086
+ routeParams: null
3087
+ };
3088
+ try {
3089
+ const { isPublicPage } = usePublicPageContext();
3090
+ newDiagnostics.hasPublicPageContext = isPublicPage === true;
3091
+ } catch (error) {
3092
+ newDiagnostics.hasPublicPageContext = false;
3093
+ }
3094
+ try {
3095
+ const { isAuthenticated } = (init_UnifiedAuthProvider(), __toCommonJS(UnifiedAuthProvider_exports)).useUnifiedAuth();
3096
+ newDiagnostics.hasAuthContext = true;
3097
+ } catch (error) {
3098
+ newDiagnostics.hasAuthContext = false;
3099
+ }
3100
+ try {
3101
+ const { selectedOrganisation } = (init_OrganisationProvider(), __toCommonJS(OrganisationProvider_exports)).useOrganisations();
3102
+ newDiagnostics.hasOrgContext = true;
3103
+ } catch (error) {
3104
+ newDiagnostics.hasOrgContext = false;
3105
+ }
3106
+ try {
3107
+ const { events } = (init_EventProvider(), __toCommonJS(EventProvider_exports)).useEvents();
3108
+ newDiagnostics.hasEventContext = true;
3109
+ } catch (error) {
3110
+ newDiagnostics.hasEventContext = false;
3111
+ }
3112
+ const supabaseUrl = import.meta.env?.VITE_SUPABASE_URL || process.env.VITE_SUPABASE_URL;
3113
+ const supabaseKey = import.meta.env?.VITE_SUPABASE_ANON_KEY || process.env.VITE_SUPABASE_ANON_KEY;
3114
+ newDiagnostics.hasEnvironmentVars = !!(supabaseUrl && supabaseKey);
3115
+ try {
3116
+ const { useParams } = __require("react-router-dom");
3117
+ const params = useParams();
3118
+ newDiagnostics.routeParams = params;
3119
+ } catch (error) {
3120
+ newDiagnostics.routeParams = null;
3121
+ }
3122
+ setDiagnostics(newDiagnostics);
3123
+ console.group(`\u{1F50D} [${label}] Public Page Diagnostics`);
3124
+ console.log("\u2705 Public Page Context:", newDiagnostics.hasPublicPageContext ? "PRESENT" : "MISSING");
3125
+ console.log("\u274C Auth Context:", newDiagnostics.hasAuthContext ? "PRESENT (BAD!)" : "ABSENT (GOOD!)");
3126
+ console.log("\u274C Org Context:", newDiagnostics.hasOrgContext ? "PRESENT (BAD!)" : "ABSENT (GOOD!)");
3127
+ console.log("\u274C Event Context:", newDiagnostics.hasEventContext ? "PRESENT (BAD!)" : "ABSENT (GOOD!)");
3128
+ console.log("\u2705 Environment Vars:", newDiagnostics.hasEnvironmentVars ? "PRESENT" : "MISSING");
3129
+ console.log("\u2705 Route Params:", newDiagnostics.routeParams);
3130
+ console.groupEnd();
3131
+ if (newDiagnostics.hasAuthContext || newDiagnostics.hasOrgContext || newDiagnostics.hasEventContext) {
3132
+ console.error(`\u{1F6A8} [${label}] PROBLEM DETECTED: Public page is inside authentication context!`);
3133
+ console.error("\u{1F527} SOLUTION: Move public routes outside of UnifiedAuthProvider, OrganisationProvider, and EventProvider");
3134
+ console.error("\u{1F4D6} See: packages/core/docs/emergency-public-pages-fix.md");
3135
+ } else if (!newDiagnostics.hasPublicPageContext) {
3136
+ console.warn(`\u26A0\uFE0F [${label}] WARNING: Not in PublicPageProvider context`);
3137
+ console.warn("\u{1F527} SOLUTION: Wrap your public page component in <PublicPageProvider>");
3138
+ } else if (!newDiagnostics.hasEnvironmentVars) {
3139
+ console.warn(`\u26A0\uFE0F [${label}] WARNING: Missing environment variables`);
3140
+ console.warn("\u{1F527} SOLUTION: Set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in your environment");
3141
+ } else {
3142
+ console.log(`\u2705 [${label}] All diagnostics passed! Public page should work correctly.`);
3143
+ }
3144
+ };
3145
+ runDiagnostics();
3146
+ }, [enabled, label]);
3147
+ if (!enabled) return null;
3148
+ return /* @__PURE__ */ jsxs20("div", { style: {
3149
+ position: "fixed",
3150
+ top: 0,
3151
+ left: 0,
3152
+ background: "rgba(0,0,0,0.9)",
3153
+ color: "white",
3154
+ padding: "12px",
3155
+ fontSize: "11px",
3156
+ zIndex: 9999,
3157
+ fontFamily: "monospace",
3158
+ maxWidth: "300px",
3159
+ borderRadius: "0 0 8px 0"
3160
+ }, children: [
3161
+ /* @__PURE__ */ jsx26("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F50D} Public Page Diagnostics" }),
3162
+ /* @__PURE__ */ jsxs20("div", { children: [
3163
+ "Public Context: ",
3164
+ diagnostics.hasPublicPageContext ? "\u2705" : "\u274C"
3165
+ ] }),
3166
+ /* @__PURE__ */ jsxs20("div", { children: [
3167
+ "Auth Context: ",
3168
+ diagnostics.hasAuthContext ? "\u274C BAD" : "\u2705 GOOD"
3169
+ ] }),
3170
+ /* @__PURE__ */ jsxs20("div", { children: [
3171
+ "Org Context: ",
3172
+ diagnostics.hasOrgContext ? "\u274C BAD" : "\u2705 GOOD"
3173
+ ] }),
3174
+ /* @__PURE__ */ jsxs20("div", { children: [
3175
+ "Event Context: ",
3176
+ diagnostics.hasEventContext ? "\u274C BAD" : "\u2705 GOOD"
3177
+ ] }),
3178
+ /* @__PURE__ */ jsxs20("div", { children: [
3179
+ "Env Vars: ",
3180
+ diagnostics.hasEnvironmentVars ? "\u2705" : "\u274C"
3181
+ ] }),
3182
+ /* @__PURE__ */ jsxs20("div", { children: [
3183
+ "Route Params: ",
3184
+ diagnostics.routeParams ? "\u2705" : "\u274C"
3185
+ ] }),
3186
+ /* @__PURE__ */ jsx26("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.8 }, children: "Check console for detailed analysis" })
3187
+ ] });
3188
+ }
3189
+
3190
+ // src/components/PublicLayout/PublicPageContextChecker.tsx
3191
+ import { useEffect as useEffect7 } from "react";
3192
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
3193
+ function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
3194
+ useEffect7(() => {
3195
+ if (!enabled) return;
3196
+ console.group(`\u{1F6A8} [${label}] PUBLIC PAGE CONTEXT CHECK`);
3197
+ try {
3198
+ const { isAuthenticated } = (init_UnifiedAuthProvider(), __toCommonJS(UnifiedAuthProvider_exports)).useUnifiedAuth();
3199
+ console.error(`\u274C [${label}] AUTHENTICATION CONTEXT DETECTED!`);
3200
+ console.error(`\u274C [${label}] isAuthenticated:`, isAuthenticated);
3201
+ console.error(`\u274C [${label}] This public page is inside UnifiedAuthProvider - THIS IS WRONG!`);
3202
+ console.error(`\u274C [${label}] SOLUTION: Move public routes outside of authentication providers`);
3203
+ } catch (error) {
3204
+ console.log(`\u2705 [${label}] No authentication context detected (GOOD!)`);
3205
+ }
3206
+ try {
3207
+ const { selectedOrganisation } = (init_OrganisationProvider(), __toCommonJS(OrganisationProvider_exports)).useOrganisations();
3208
+ console.error(`\u274C [${label}] ORGANISATION CONTEXT DETECTED!`);
3209
+ console.error(`\u274C [${label}] selectedOrganisation:`, selectedOrganisation);
3210
+ console.error(`\u274C [${label}] This public page is inside OrganisationProvider - THIS IS WRONG!`);
3211
+ console.error(`\u274C [${label}] SOLUTION: Move public routes outside of authentication providers`);
3212
+ } catch (error) {
3213
+ console.log(`\u2705 [${label}] No organisation context detected (GOOD!)`);
3214
+ }
3215
+ try {
3216
+ const { events } = (init_EventProvider(), __toCommonJS(EventProvider_exports)).useEvents();
3217
+ console.error(`\u274C [${label}] EVENT CONTEXT DETECTED!`);
3218
+ console.error(`\u274C [${label}] events:`, events);
3219
+ console.error(`\u274C [${label}] This public page is inside EventProvider - THIS IS WRONG!`);
3220
+ console.error(`\u274C [${label}] SOLUTION: Move public routes outside of authentication providers`);
3221
+ } catch (error) {
3222
+ console.log(`\u2705 [${label}] No event context detected (GOOD!)`);
3223
+ }
3224
+ try {
3225
+ const { isPublicPage } = usePublicPageContext();
3226
+ if (isPublicPage) {
3227
+ console.log(`\u2705 [${label}] Public page context detected (GOOD!)`);
3228
+ } else {
3229
+ console.warn(`\u26A0\uFE0F [${label}] Not in PublicPageProvider context`);
3230
+ console.warn(`\u26A0\uFE0F [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
3231
+ }
3232
+ } catch (error) {
3233
+ console.warn(`\u26A0\uFE0F [${label}] Not in PublicPageProvider context`);
3234
+ console.warn(`\u26A0\uFE0F [${label}] SOLUTION: Wrap your public page in <PublicPageProvider>`);
3235
+ }
3236
+ console.groupEnd();
3237
+ console.group(`\u{1F4D6} [${label}] IMMEDIATE ACTION REQUIRED`);
3238
+ console.log(`If you see any \u274C errors above, your public page is inside authentication context.`);
3239
+ console.log(`This will cause infinite loading loops and authentication errors.`);
3240
+ console.log(``);
3241
+ console.log(`\u{1F527} SOLUTION:`);
3242
+ console.log(`1. Check your main App.tsx file`);
3243
+ console.log(`2. Make sure public routes are completely separate from authentication providers`);
3244
+ console.log(`3. Follow the architecture in: packages/core/docs/public-pages-guide.md`);
3245
+ console.log(``);
3246
+ console.log(`\u2705 CORRECT ARCHITECTURE:`);
3247
+ console.log(`<BrowserRouter>`);
3248
+ console.log(` <Routes>`);
3249
+ console.log(` <Route path="/events/*" element={<PublicPageApp />} />`);
3250
+ console.log(` <Route path="/*" element={<AuthenticatedApp />} />`);
3251
+ console.log(` </Routes>`);
3252
+ console.log(`</BrowserRouter>`);
3253
+ console.groupEnd();
3254
+ }, [enabled, label]);
3255
+ if (!enabled) return null;
3256
+ return /* @__PURE__ */ jsxs21("div", { style: {
3257
+ position: "fixed",
3258
+ top: 0,
3259
+ left: 0,
3260
+ background: "rgba(220, 38, 38, 0.95)",
3261
+ color: "white",
3262
+ padding: "12px",
3263
+ fontSize: "12px",
3264
+ zIndex: 9999,
3265
+ fontFamily: "monospace",
3266
+ maxWidth: "400px",
3267
+ borderRadius: "0 0 8px 0",
3268
+ border: "2px solid #dc2626"
3269
+ }, children: [
3270
+ /* @__PURE__ */ jsx27("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F6A8} PUBLIC PAGE CONTEXT CHECK" }),
3271
+ /* @__PURE__ */ jsx27("div", { children: "Check console for authentication context analysis" }),
3272
+ /* @__PURE__ */ jsx27("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.9 }, children: "If you see \u274C errors in console, your public page is inside auth context!" })
3273
+ ] });
3274
+ }
3275
+
3276
+ export {
3277
+ Card,
3278
+ CardHeader,
3279
+ CardTitle,
3280
+ CardDescription,
3281
+ CardContent,
3282
+ CardFooter,
3283
+ CardActions,
3284
+ Label,
3285
+ Avatar,
3286
+ AvatarImage,
3287
+ AvatarFallback,
3288
+ Progress,
3289
+ ToastProvider,
3290
+ ToastViewport,
3291
+ Toast,
3292
+ ToastAction,
3293
+ ToastClose,
3294
+ ToastTitle,
3295
+ ToastDescription,
3296
+ useToast,
3297
+ Toaster,
3298
+ Form,
3299
+ LoginForm,
3300
+ EventSelector,
3301
+ PasswordChangeForm,
3302
+ UserMenu,
3303
+ NavigationMenu,
3304
+ Header,
3305
+ Footer,
3306
+ PaceAppLayout,
3307
+ PaceLoginPage,
3308
+ ErrorBoundary,
3309
+ OrganisationSelector,
3310
+ PasswordResetForm,
3311
+ FILE_SIZE_LIMITS,
3312
+ DEFAULT_FILE_SIZE_LIMIT,
3313
+ APP_PATH_MAPPING,
3314
+ STORAGE_CONFIG,
3315
+ getFileSizeLimit,
3316
+ validateFileSize,
3317
+ formatFileSize,
3318
+ generateFilePath,
3319
+ generateUniqueFileName,
3320
+ extractFileMetadata,
3321
+ uploadFile,
3322
+ getPublicUrl,
3323
+ getSignedUrl,
3324
+ deleteFile,
3325
+ listFiles,
3326
+ archiveFile,
3327
+ useStorage,
3328
+ useFileUpload,
3329
+ FileUpload,
3330
+ EventLogo,
3331
+ EventLogoCompact,
3332
+ EventLogoLarge,
3333
+ PublicPageHeader,
3334
+ PublicPageFooter,
3335
+ PublicLoadingSpinner,
3336
+ PublicLoadingSpinnerFullPage,
3337
+ PublicLoadingSkeleton,
3338
+ PublicPageLayout,
3339
+ usePublicPageContext2 as usePublicPageContext,
3340
+ PublicPageDebugger,
3341
+ PublicPageDiagnostic,
3342
+ PublicPageContextChecker
3343
+ };
3344
+ //# sourceMappingURL=chunk-7JL3T7BO.js.map