@jmruthers/pace-core 0.4.1 → 0.5.1

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