@jmruthers/pace-core 0.5.189 → 0.5.190

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 (420) hide show
  1. package/core-usage-manifest.json +0 -4
  2. package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
  3. package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
  4. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
  5. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  6. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
  7. package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
  8. package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
  9. package/dist/chunk-4QYC5L4K.js.map +1 -0
  10. package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
  11. package/dist/chunk-73HSNNOQ.js.map +1 -0
  12. package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
  13. package/dist/chunk-DZWK57KZ.js.map +1 -0
  14. package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
  15. package/dist/chunk-HQVPB5MZ.js.map +1 -0
  16. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  17. package/dist/chunk-HW3OVDUF.js.map +1 -0
  18. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  19. package/dist/chunk-I7PSE6JW.js.map +1 -0
  20. package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
  21. package/dist/chunk-J2XXC7R5.js.map +1 -0
  22. package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
  23. package/dist/chunk-NIU6J6OX.js.map +1 -0
  24. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  25. package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
  26. package/dist/chunk-RUYZKXOD.js.map +1 -0
  27. package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
  28. package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
  29. package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
  30. package/dist/chunk-STYK4OH2.js.map +1 -0
  31. package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
  32. package/dist/chunk-VVBAW5A5.js.map +1 -0
  33. package/dist/chunk-Y4BUBBHD.js +614 -0
  34. package/dist/chunk-Y4BUBBHD.js.map +1 -0
  35. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  36. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  37. package/dist/components.d.ts +3 -4
  38. package/dist/components.js +19 -19
  39. package/dist/components.js.map +1 -1
  40. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  41. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  42. package/dist/hooks.d.ts +10 -5
  43. package/dist/hooks.js +14 -8
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +13 -11
  46. package/dist/index.js +79 -69
  47. package/dist/index.js.map +1 -1
  48. package/dist/providers.d.ts +3 -3
  49. package/dist/providers.js +3 -1
  50. package/dist/rbac/index.d.ts +76 -12
  51. package/dist/rbac/index.js +12 -9
  52. package/dist/types.d.ts +1 -1
  53. package/dist/types.js +1 -1
  54. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
  55. package/dist/utils.js +16 -16
  56. package/docs/README.md +2 -2
  57. package/docs/api/classes/ColumnFactory.md +1 -1
  58. package/docs/api/classes/ErrorBoundary.md +1 -1
  59. package/docs/api/classes/InvalidScopeError.md +2 -2
  60. package/docs/api/classes/Logger.md +1 -1
  61. package/docs/api/classes/MissingUserContextError.md +2 -2
  62. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  63. package/docs/api/classes/PermissionDeniedError.md +1 -1
  64. package/docs/api/classes/RBACAuditManager.md +1 -1
  65. package/docs/api/classes/RBACCache.md +1 -1
  66. package/docs/api/classes/RBACEngine.md +4 -4
  67. package/docs/api/classes/RBACError.md +1 -1
  68. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  69. package/docs/api/classes/SecureSupabaseClient.md +21 -16
  70. package/docs/api/classes/StorageUtils.md +7 -4
  71. package/docs/api/enums/FileCategory.md +1 -1
  72. package/docs/api/enums/LogLevel.md +1 -1
  73. package/docs/api/enums/RBACErrorCode.md +1 -1
  74. package/docs/api/enums/RPCFunction.md +1 -1
  75. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  76. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  77. package/docs/api/interfaces/AggregateConfig.md +1 -1
  78. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  79. package/docs/api/interfaces/AvatarProps.md +1 -1
  80. package/docs/api/interfaces/BadgeProps.md +1 -1
  81. package/docs/api/interfaces/ButtonProps.md +1 -1
  82. package/docs/api/interfaces/CalendarProps.md +20 -6
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/ComplianceResult.md +1 -1
  87. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  88. package/docs/api/interfaces/DataRecord.md +1 -1
  89. package/docs/api/interfaces/DataTableAction.md +1 -1
  90. package/docs/api/interfaces/DataTableColumn.md +1 -1
  91. package/docs/api/interfaces/DataTableProps.md +1 -1
  92. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  93. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  94. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  95. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  96. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  97. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  98. package/docs/api/interfaces/ExportColumn.md +1 -1
  99. package/docs/api/interfaces/ExportOptions.md +1 -1
  100. package/docs/api/interfaces/FileDisplayProps.md +62 -16
  101. package/docs/api/interfaces/FileMetadata.md +1 -1
  102. package/docs/api/interfaces/FileReference.md +2 -2
  103. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  104. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  105. package/docs/api/interfaces/FileUploadProps.md +30 -19
  106. package/docs/api/interfaces/FooterProps.md +1 -1
  107. package/docs/api/interfaces/FormFieldProps.md +1 -1
  108. package/docs/api/interfaces/FormProps.md +1 -1
  109. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  110. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  111. package/docs/api/interfaces/InputProps.md +1 -1
  112. package/docs/api/interfaces/LabelProps.md +1 -1
  113. package/docs/api/interfaces/LoggerConfig.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  116. package/docs/api/interfaces/NavigationContextType.md +9 -9
  117. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  118. package/docs/api/interfaces/NavigationItem.md +1 -1
  119. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  120. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  121. package/docs/api/interfaces/Organisation.md +1 -1
  122. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  123. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  124. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  125. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  126. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  127. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  128. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  129. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  130. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  131. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  132. package/docs/api/interfaces/PaletteData.md +1 -1
  133. package/docs/api/interfaces/ParsedAddress.md +1 -1
  134. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  135. package/docs/api/interfaces/ProgressProps.md +3 -11
  136. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  137. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  138. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  139. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  140. package/docs/api/interfaces/QuickFix.md +1 -1
  141. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  142. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  143. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  144. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  145. package/docs/api/interfaces/RBACConfig.md +1 -1
  146. package/docs/api/interfaces/RBACContext.md +1 -1
  147. package/docs/api/interfaces/RBACLogger.md +1 -1
  148. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  149. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  150. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  151. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  152. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  153. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  154. package/docs/api/interfaces/RBACResult.md +1 -1
  155. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  156. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  157. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  158. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  160. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  161. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  162. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  163. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  164. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  165. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  166. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  167. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  168. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  169. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  170. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  171. package/docs/api/interfaces/RouteConfig.md +10 -10
  172. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  173. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  174. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  175. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  176. package/docs/api/interfaces/SetupIssue.md +1 -1
  177. package/docs/api/interfaces/StorageConfig.md +4 -4
  178. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  179. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  180. package/docs/api/interfaces/StorageListOptions.md +22 -9
  181. package/docs/api/interfaces/StorageListResult.md +4 -4
  182. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  183. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  184. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  185. package/docs/api/interfaces/StyleImport.md +1 -1
  186. package/docs/api/interfaces/SwitchProps.md +1 -1
  187. package/docs/api/interfaces/TabsContentProps.md +1 -1
  188. package/docs/api/interfaces/TabsListProps.md +1 -1
  189. package/docs/api/interfaces/TabsProps.md +1 -1
  190. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  191. package/docs/api/interfaces/TextareaProps.md +1 -1
  192. package/docs/api/interfaces/ToastActionElement.md +1 -1
  193. package/docs/api/interfaces/ToastProps.md +1 -1
  194. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  195. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  196. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  197. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  198. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  199. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  200. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  201. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  202. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  203. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  205. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  207. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  208. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  209. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  210. package/docs/api/interfaces/UserEventAccess.md +11 -11
  211. package/docs/api/interfaces/UserMenuProps.md +1 -1
  212. package/docs/api/interfaces/UserProfile.md +1 -1
  213. package/docs/api/modules.md +151 -92
  214. package/docs/api-reference/components.md +15 -7
  215. package/docs/api-reference/providers.md +2 -2
  216. package/docs/api-reference/rpc-functions.md +1 -0
  217. package/docs/best-practices/README.md +1 -1
  218. package/docs/best-practices/deployment.md +8 -8
  219. package/docs/getting-started/examples/README.md +2 -2
  220. package/docs/getting-started/installation-guide.md +4 -4
  221. package/docs/getting-started/quick-start.md +3 -3
  222. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  223. package/docs/rbac/compliance/compliance-guide.md +2 -2
  224. package/docs/rbac/event-based-apps.md +2 -2
  225. package/docs/rbac/getting-started.md +2 -2
  226. package/docs/rbac/quick-start.md +2 -2
  227. package/docs/security/README.md +4 -4
  228. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  229. package/docs/troubleshooting/README.md +2 -2
  230. package/docs/troubleshooting/migration.md +3 -3
  231. package/package.json +1 -3
  232. package/scripts/check-pace-core-compliance.cjs +1 -1
  233. package/scripts/check-pace-core-compliance.js +1 -1
  234. package/src/__tests__/fixtures/supabase.ts +301 -0
  235. package/src/__tests__/public-recipe-view.test.ts +9 -9
  236. package/src/__tests__/rls-policies.test.ts +197 -61
  237. package/src/components/AddressField/AddressField.test.tsx +42 -0
  238. package/src/components/AddressField/AddressField.tsx +71 -60
  239. package/src/components/AddressField/README.md +1 -0
  240. package/src/components/Alert/Alert.test.tsx +50 -10
  241. package/src/components/Alert/Alert.tsx +5 -3
  242. package/src/components/Avatar/Avatar.test.tsx +95 -43
  243. package/src/components/Avatar/Avatar.tsx +16 -16
  244. package/src/components/Button/Button.test.tsx +2 -1
  245. package/src/components/Button/Button.tsx +3 -3
  246. package/src/components/Calendar/Calendar.test.tsx +53 -37
  247. package/src/components/Calendar/Calendar.tsx +409 -82
  248. package/src/components/Card/Card.test.tsx +7 -4
  249. package/src/components/Card/Card.tsx +3 -6
  250. package/src/components/Checkbox/Checkbox.tsx +2 -2
  251. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  252. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  253. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  254. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  255. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  256. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  257. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  258. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  259. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  260. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  261. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  262. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  264. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  265. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  266. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  267. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  268. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  269. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  270. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  271. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  272. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  273. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  274. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  275. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  276. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  277. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  278. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  280. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  281. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  282. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  283. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  284. package/src/components/Dialog/Dialog.tsx +2 -2
  285. package/src/components/EventSelector/EventSelector.tsx +7 -7
  286. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  287. package/src/components/FileUpload/FileUpload.tsx +7 -4
  288. package/src/components/Header/Header.test.tsx +28 -0
  289. package/src/components/Header/Header.tsx +22 -9
  290. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  291. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  292. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  293. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  294. package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
  295. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  296. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  297. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  298. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  299. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  300. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  301. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  302. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  303. package/src/components/Progress/Progress.test.tsx +18 -19
  304. package/src/components/Progress/Progress.tsx +31 -32
  305. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  306. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  307. package/src/components/Select/Select.tsx +5 -5
  308. package/src/components/Switch/Switch.test.tsx +2 -1
  309. package/src/components/Switch/Switch.tsx +1 -1
  310. package/src/components/Toast/Toast.tsx +1 -1
  311. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  312. package/src/components/UserMenu/UserMenu.tsx +3 -3
  313. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  314. package/src/eslint-rules/pace-core-compliance.js +0 -2
  315. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  316. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  317. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  318. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  319. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  320. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  321. package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
  322. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  323. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
  324. package/src/hooks/index.ts +1 -1
  325. package/src/hooks/public/usePublicEvent.ts +2 -2
  326. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  327. package/src/hooks/useAppConfig.ts +24 -5
  328. package/src/hooks/useFileDisplay.ts +297 -34
  329. package/src/hooks/useFileReference.ts +56 -11
  330. package/src/hooks/useFileUrl.ts +1 -1
  331. package/src/hooks/useInactivityTracker.ts +16 -7
  332. package/src/hooks/usePermissionCache.test.ts +85 -8
  333. package/src/hooks/useQueryCache.ts +21 -0
  334. package/src/hooks/useSecureDataAccess.test.ts +80 -35
  335. package/src/hooks/useSecureDataAccess.ts +80 -37
  336. package/src/providers/services/EventServiceProvider.tsx +37 -17
  337. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  338. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  339. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  340. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  341. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  342. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  343. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  344. package/src/rbac/api.ts +240 -36
  345. package/src/rbac/cache-invalidation.ts +21 -7
  346. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  347. package/src/rbac/components/NavigationGuard.tsx +23 -63
  348. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  349. package/src/rbac/components/NavigationProvider.tsx +13 -11
  350. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  351. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  352. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  353. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  354. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  355. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  356. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  357. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  358. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  359. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  360. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  361. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  362. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  363. package/src/rbac/engine.ts +4 -2
  364. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  365. package/src/rbac/hooks/index.ts +3 -0
  366. package/src/rbac/hooks/useCan.test.ts +101 -53
  367. package/src/rbac/hooks/usePermissions.ts +108 -41
  368. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  369. package/src/rbac/hooks/useRBAC.ts +83 -40
  370. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  371. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  372. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  373. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  374. package/src/rbac/request-deduplication.ts +1 -1
  375. package/src/rbac/secureClient.ts +72 -12
  376. package/src/rbac/security.ts +29 -23
  377. package/src/rbac/types.ts +10 -0
  378. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  379. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  380. package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
  381. package/src/rbac/utils/contextValidator.ts +288 -0
  382. package/src/rbac/utils/eventContext.ts +48 -2
  383. package/src/services/EventService.ts +165 -21
  384. package/src/services/OrganisationService.ts +37 -2
  385. package/src/services/__tests__/EventService.test.ts +26 -21
  386. package/src/types/file-reference.ts +13 -10
  387. package/src/utils/app/appNameResolver.test.ts +346 -73
  388. package/src/utils/context/superAdminOverride.ts +58 -0
  389. package/src/utils/file-reference/index.ts +61 -33
  390. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  391. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  392. package/src/utils/storage/helpers.test.ts +1 -1
  393. package/src/utils/storage/helpers.ts +38 -19
  394. package/src/utils/storage/types.ts +15 -8
  395. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  396. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  397. package/src/vite-env.d.ts +2 -2
  398. package/dist/chunk-3GOZZZYH.js.map +0 -1
  399. package/dist/chunk-DDM4CCYT.js.map +0 -1
  400. package/dist/chunk-E7UAOUMY.js +0 -75
  401. package/dist/chunk-E7UAOUMY.js.map +0 -1
  402. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  403. package/dist/chunk-HEHYGYOX.js.map +0 -1
  404. package/dist/chunk-IM4QE42D.js.map +0 -1
  405. package/dist/chunk-MX64ZF6I.js.map +0 -1
  406. package/dist/chunk-SAUPYVLF.js.map +0 -1
  407. package/dist/chunk-THRPYOFK.js.map +0 -1
  408. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  409. package/dist/chunk-VGZZXKBR.js.map +0 -1
  410. package/dist/chunk-YGPFYGA6.js.map +0 -1
  411. package/dist/chunk-YHCN776L.js.map +0 -1
  412. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  413. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  414. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
  415. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  416. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
  417. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
  418. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
  419. /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
  420. /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
@@ -25,57 +25,57 @@ import {
25
25
  SelectSeparator,
26
26
  SelectTrigger,
27
27
  SelectValue
28
- } from "./chunk-2UUZZJFT.js";
28
+ } from "./chunk-SDMHPX3X.js";
29
29
  import {
30
30
  useCan,
31
31
  usePermissions,
32
- useRBAC,
33
- useResolvedScope
34
- } from "./chunk-3GOZZZYH.js";
35
- import {
36
- isSuperAdmin
37
- } from "./chunk-HEHYGYOX.js";
32
+ useRBAC
33
+ } from "./chunk-HQVPB5MZ.js";
38
34
  import {
39
- ErrorBoundary,
40
- PublicPageContext,
41
35
  createFileReferenceService,
42
36
  generateFileUrlsBatch,
43
37
  getPublicUrl,
44
38
  getSignedUrl,
45
39
  uploadFileWithReference,
46
40
  useAddressAutocomplete,
47
- useAppConfig,
48
41
  useEventTheme,
49
42
  useFileDisplay,
50
- useIsPublicPage,
51
43
  usePreventTabReload,
52
44
  usePublicFileDisplay
53
- } from "./chunk-UCQSRW7Z.js";
45
+ } from "./chunk-NIU6J6OX.js";
54
46
  import {
55
47
  useToast
56
48
  } from "./chunk-6C4YBBJM.js";
57
49
  import {
50
+ ErrorBoundary,
51
+ PublicPageContext,
52
+ useAppConfig,
58
53
  useEvents,
59
- useOrganisations
60
- } from "./chunk-E7UAOUMY.js";
54
+ useIsPublicPage,
55
+ useResolvedScope
56
+ } from "./chunk-Y4BUBBHD.js";
61
57
  import {
62
58
  EventServiceContext,
59
+ useOrganisations,
63
60
  useSessionRestoration,
64
61
  useUnifiedAuth
65
- } from "./chunk-VGZZXKBR.js";
62
+ } from "./chunk-J2XXC7R5.js";
63
+ import {
64
+ isSuperAdmin
65
+ } from "./chunk-RUYZKXOD.js";
66
66
  import {
67
67
  assertAppId
68
68
  } from "./chunk-QXHPKYJV.js";
69
69
  import {
70
70
  LoadingSpinner,
71
71
  getAppId
72
- } from "./chunk-THRPYOFK.js";
72
+ } from "./chunk-HW3OVDUF.js";
73
73
  import {
74
74
  cn
75
75
  } from "./chunk-R77UEZ4E.js";
76
76
  import {
77
77
  getCurrentAppName
78
- } from "./chunk-F2IMUDXZ.js";
78
+ } from "./chunk-I7PSE6JW.js";
79
79
  import {
80
80
  clearPalette
81
81
  } from "./chunk-SQGMNID3.js";
@@ -229,47 +229,47 @@ var AddressField = React.forwardRef(
229
229
  };
230
230
  }
231
231
  }, [isOpen]);
232
+ const suggestionsId = React.useId();
232
233
  React.useEffect(() => {
233
- if (selectedIndex >= 0 && suggestionsRef.current) {
234
- const selectedItem = suggestionsRef.current.children[selectedIndex];
234
+ if (selectedIndex >= 0) {
235
+ const selectedItem = document.getElementById(
236
+ `${suggestionsId}-item-${selectedIndex}`
237
+ );
235
238
  if (selectedItem && typeof selectedItem.scrollIntoView === "function") {
236
239
  selectedItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
237
240
  }
238
241
  }
239
- }, [selectedIndex]);
242
+ }, [selectedIndex, suggestionsId]);
240
243
  React.useImperativeHandle(ref, () => inputRef.current);
241
- const suggestionsId = React.useId();
242
244
  const hasError = error || !!autocompleteError;
243
- return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cn("relative w-full", className), children: [
244
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
245
- /* @__PURE__ */ jsx(
246
- Input,
247
- {
248
- ref: inputRef,
249
- type: "text",
250
- value,
251
- onChange: handleInputChange,
252
- onKeyDown: handleKeyDown,
253
- onFocus: handleFocus,
254
- onBlur: handleBlur,
255
- placeholder,
256
- disabled,
257
- error: hasError,
258
- size,
259
- variant,
260
- role: "combobox",
261
- "aria-expanded": isOpen,
262
- "aria-autocomplete": "list",
263
- "aria-controls": suggestionsId,
264
- "aria-haspopup": "listbox",
265
- "aria-activedescendant": selectedIndex >= 0 ? `${suggestionsId}-item-${selectedIndex}` : void 0,
266
- ...props
267
- }
268
- ),
269
- isLoading && /* @__PURE__ */ jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(LoadingSpinner, { size: "sm" }) })
270
- ] }),
245
+ return /* @__PURE__ */ jsxs("form", { ref: containerRef, className: cn("relative w-full", className), children: [
246
+ /* @__PURE__ */ jsx(
247
+ Input,
248
+ {
249
+ ref: inputRef,
250
+ type: "text",
251
+ value,
252
+ onChange: handleInputChange,
253
+ onKeyDown: handleKeyDown,
254
+ onFocus: handleFocus,
255
+ onBlur: handleBlur,
256
+ placeholder,
257
+ disabled,
258
+ error: hasError,
259
+ size,
260
+ variant,
261
+ role: "combobox",
262
+ "aria-expanded": isOpen,
263
+ "aria-autocomplete": "list",
264
+ "aria-controls": suggestionsId,
265
+ "aria-haspopup": "listbox",
266
+ "aria-activedescendant": selectedIndex >= 0 ? `${suggestionsId}-item-${selectedIndex}` : void 0,
267
+ ...props
268
+ }
269
+ ),
270
+ isLoading && /* @__PURE__ */ jsx("p", { className: "absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx(LoadingSpinner, { size: "sm" }) }),
271
271
  isOpen && suggestions.length > 0 && /* @__PURE__ */ jsx(
272
- "ul",
272
+ "dl",
273
273
  {
274
274
  ref: suggestionsRef,
275
275
  id: suggestionsId,
@@ -280,28 +280,28 @@ var AddressField = React.forwardRef(
280
280
  "list-none p-0 m-0"
281
281
  ),
282
282
  "data-testid": "address-suggestions",
283
- children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(
284
- "li",
285
- {
286
- id: `${suggestionsId}-item-${index}`,
287
- role: "option",
288
- "aria-selected": selectedIndex === index,
289
- className: cn(
290
- "px-3 py-2 cursor-pointer text-sm",
291
- "hover:bg-main-100 focus:bg-main-100",
292
- "border-b border-main-200 last:border-b-0",
293
- selectedIndex === index && "bg-main-100"
294
- ),
295
- onClick: () => handleSelectAddress(suggestion.place_id),
296
- onMouseEnter: () => setSelectedIndex(index),
297
- "data-testid": `address-suggestion-${index}`,
298
- children: [
299
- /* @__PURE__ */ jsx("div", { className: "font-medium text-main-900", children: suggestion.structured_formatting?.main_text || suggestion.description }),
300
- suggestion.structured_formatting?.secondary_text && /* @__PURE__ */ jsx("div", { className: "text-xs text-main-600 mt-0.5", children: suggestion.structured_formatting.secondary_text })
301
- ]
302
- },
303
- suggestion.place_id
304
- ))
283
+ children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
284
+ /* @__PURE__ */ jsx(
285
+ "dt",
286
+ {
287
+ id: `${suggestionsId}-item-${index}`,
288
+ role: "option",
289
+ "aria-selected": selectedIndex === index,
290
+ className: cn(
291
+ "px-3 py-2 cursor-pointer text-sm",
292
+ "hover:bg-main-100 focus:bg-main-100",
293
+ "border-b border-main-200 last:border-b-0",
294
+ selectedIndex === index && "bg-main-100",
295
+ "font-medium text-main-900"
296
+ ),
297
+ onClick: () => handleSelectAddress(suggestion.place_id),
298
+ onMouseEnter: () => setSelectedIndex(index),
299
+ "data-testid": `address-suggestion-${index}`,
300
+ children: suggestion.structured_formatting?.main_text || suggestion.description
301
+ }
302
+ ),
303
+ suggestion.structured_formatting?.secondary_text && /* @__PURE__ */ jsx("dd", { className: "px-3 pb-2 text-xs text-main-600 mt-0.5", children: suggestion.structured_formatting.secondary_text })
304
+ ] }, suggestion.place_id))
305
305
  }
306
306
  ),
307
307
  autocompleteError && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-destructive", role: "alert", children: autocompleteError.message })
@@ -313,7 +313,7 @@ AddressField.displayName = "AddressField";
313
313
  // src/components/Label/Label.tsx
314
314
  import * as React2 from "react";
315
315
  import * as LabelPrimitive from "@radix-ui/react-label";
316
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
316
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
317
317
  var getLabelClasses = () => {
318
318
  return "font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70";
319
319
  };
@@ -332,7 +332,7 @@ var Label = React2.forwardRef(({
332
332
  }, ref) => {
333
333
  const hasError = !!error;
334
334
  const showHelperText = helperText && !hasError;
335
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
335
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
336
336
  /* @__PURE__ */ jsxs2(
337
337
  LabelPrimitive.Root,
338
338
  {
@@ -482,15 +482,20 @@ function useFileUrl(fileReference, options) {
482
482
  }
483
483
 
484
484
  // src/components/FileDisplay/FileDisplay.tsx
485
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
485
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
486
486
  var fallbackSizeClasses = {
487
- xs: "h-4 w-4 text-xs",
488
- sm: "h-6 w-6 text-sm",
489
- md: "h-8 w-8 text-base",
490
- lg: "h-12 w-12 text-lg",
491
- xl: "h-16 w-16 text-xl",
492
- "2xl": "h-20 w-20 text-2xl"
487
+ xs: "size-4 text-xs",
488
+ sm: "size-6 text-sm",
489
+ md: "size-8 text-base",
490
+ lg: "size-12 text-lg",
491
+ xl: "size-16 text-xl",
492
+ "2xl": "size-20 text-2xl"
493
493
  };
494
+ var fallbackBaseClasses = "size-full grid place-items-center text-center text-sec-600 font-semibold";
495
+ function getFallbackClasses(size = "md") {
496
+ const sizeClass = fallbackSizeClasses[size];
497
+ return `${fallbackBaseClasses} ${sizeClass}`.trim();
498
+ }
494
499
  function defaultGenerateFallbackText(fileName) {
495
500
  if (!fileName) return "FL";
496
501
  const baseName = fileName.replace(/\.[^/.]+$/, "");
@@ -519,7 +524,10 @@ function FileDisplayContent({
519
524
  showFallback = false,
520
525
  generateFallbackText = defaultGenerateFallbackText,
521
526
  fallbackText,
522
- fallbackSize = "md"
527
+ fallbackSourceText,
528
+ fallbackSize = "md",
529
+ enableChildren = false,
530
+ showMetadata = true
523
531
  }) {
524
532
  const [imageError, setImageError] = useState3(false);
525
533
  const [internalFileUrls, setInternalFileUrls] = useState3(new Map(fileUrls));
@@ -527,14 +535,12 @@ function FileDisplayContent({
527
535
  const fileReferencesRef = useRef3([]);
528
536
  const computedFallbackText = useMemo(() => {
529
537
  if (fallbackText) return fallbackText;
530
- const fileName = fileReference?.file_metadata?.fileName;
531
- return generateFallbackText(fileName);
532
- }, [fallbackText, fileReference, generateFallbackText]);
538
+ const sourceText = fallbackSourceText ?? fileReference?.file_metadata?.fileName;
539
+ return generateFallbackText(sourceText);
540
+ }, [fallbackText, fallbackSourceText, fileReference, generateFallbackText]);
533
541
  const fallbackClasses = useMemo(() => {
534
- const sizeClass = fallbackSizeClasses[fallbackSize];
535
- const baseClasses = "flex items-center justify-center bg-sec-100 text-sec-600 font-semibold rounded";
536
- return `${baseClasses} ${sizeClass} ${className}`.trim();
537
- }, [fallbackSize, className]);
542
+ return getFallbackClasses(fallbackSize);
543
+ }, [fallbackSize]);
538
544
  useEffect3(() => {
539
545
  const currentIds = fileReferences.map((f) => f.id).join(",");
540
546
  const prevIds = fileReferencesRef.current.map((f) => f.id).join(",");
@@ -555,20 +561,8 @@ function FileDisplayContent({
555
561
  }
556
562
  setImageError(false);
557
563
  };
558
- const handleImageError = (e) => {
564
+ const handleImageError = () => {
559
565
  setImageError(true);
560
- if (showFallback && e) {
561
- const target = e.target;
562
- target.style.display = "none";
563
- if (target.nextSibling && target.nextSibling.className.includes("bg-sec-100")) {
564
- return;
565
- }
566
- const fallback = document.createElement("div");
567
- fallback.className = fallbackClasses;
568
- fallback.textContent = computedFallbackText;
569
- fallback.title = fileReference?.file_metadata?.fileName || "File";
570
- target.parentNode?.insertBefore(fallback, target.nextSibling);
571
- }
572
566
  };
573
567
  const getFileIcon = (fileType) => {
574
568
  if (fileType.startsWith("image/")) return "\u{1F5BC}\uFE0F";
@@ -592,18 +586,18 @@ function FileDisplayContent({
592
586
  return /* @__PURE__ */ jsx4(ErrorComponent, { error, retry: clearError });
593
587
  }
594
588
  if (showFallback) {
595
- return /* @__PURE__ */ jsx4("div", { className: fallbackClasses, title: "File unavailable", children: computedFallbackText });
589
+ return /* @__PURE__ */ jsx4("figure", { className, title: "File unavailable", children: /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: computedFallbackText }) });
596
590
  }
597
- return /* @__PURE__ */ jsxs3("div", { className: `p-4 bg-acc-50 border border-acc-200 rounded-lg ${className}`, children: [
598
- /* @__PURE__ */ jsxs3("div", { className: "text-acc-600", children: [
591
+ return /* @__PURE__ */ jsxs3("figure", { className, title: "Error", children: [
592
+ /* @__PURE__ */ jsxs3("p", { className: getFallbackClasses(fallbackSize || "md"), children: [
599
593
  "Error loading file: ",
600
594
  error instanceof Error ? error.message : String(error)
601
595
  ] }),
602
596
  clearError && /* @__PURE__ */ jsx4(
603
- "button",
597
+ Button,
604
598
  {
605
599
  onClick: clearError,
606
- className: "mt-2 text-sm text-acc-700 hover:text-acc-800 underline",
600
+ className: "mt-2",
607
601
  "aria-label": "Retry loading file",
608
602
  children: "Try again"
609
603
  }
@@ -612,19 +606,19 @@ function FileDisplayContent({
612
606
  }
613
607
  if (fileCount === 0 && !isLoading) {
614
608
  if (showFallback) {
615
- return /* @__PURE__ */ jsxs3("div", { className: fallbackClasses, title: "No file", children: [
616
- computedFallbackText,
609
+ return /* @__PURE__ */ jsxs3("figure", { className, title: "No file", children: [
610
+ /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: computedFallbackText }),
617
611
  children
618
612
  ] });
619
613
  }
620
- return /* @__PURE__ */ jsxs3("div", { className: `text-sec-500 text-center p-4 ${className}`, children: [
621
- "No files found",
614
+ return /* @__PURE__ */ jsxs3("figure", { className: `text-sec-500 text-center p-4 ${className}`, children: [
615
+ /* @__PURE__ */ jsx4("p", { children: "No files found" }),
622
616
  children
623
617
  ] });
624
618
  }
625
619
  if (isLoading && showFallback && fileCount === 0) {
626
- return /* @__PURE__ */ jsxs3("div", { className: fallbackClasses, title: "Loading...", children: [
627
- computedFallbackText,
620
+ return /* @__PURE__ */ jsxs3("figure", { className, title: "Loading...", children: [
621
+ /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: computedFallbackText }),
628
622
  children
629
623
  ] });
630
624
  }
@@ -632,98 +626,125 @@ function FileDisplayContent({
632
626
  if (LoadingComponent) {
633
627
  return /* @__PURE__ */ jsx4(LoadingComponent, {});
634
628
  }
635
- return /* @__PURE__ */ jsx4("div", { className: `flex items-center justify-center p-4 ${className}`, children: /* @__PURE__ */ jsx4("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500" }) });
629
+ return /* @__PURE__ */ jsx4("figure", { className, title: "Loading", children: /* @__PURE__ */ jsx4("p", { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsx4(LoadingSpinner, {}) }) });
636
630
  }
637
631
  if ((category || displayOnly) && fileReference) {
638
632
  const isImage = fileReference.file_metadata.fileType?.startsWith("image/");
639
- if (displayOnly && isImage && !showDelete) {
633
+ if (displayOnly && isImage && !showDelete && !enableChildren) {
640
634
  if (imageError && showFallback) {
641
- return /* @__PURE__ */ jsx4("div", { className: fallbackClasses, title: fileReference.file_metadata.fileName || "File", children: computedFallbackText });
635
+ return /* @__PURE__ */ jsx4("figure", { className, title: fileReference.file_metadata.fileName || "File", children: /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: computedFallbackText }) });
642
636
  }
643
637
  if (!fileUrl) {
644
- return /* @__PURE__ */ jsx4("div", { className: `bg-sec-100 rounded animate-pulse ${className || "max-w-full h-48"}`, children: /* @__PURE__ */ jsx4("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx4("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500" }) }) });
638
+ return /* @__PURE__ */ jsx4("figure", { className: className || "max-w-full h-48", title: "Loading", children: /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: /* @__PURE__ */ jsx4(LoadingSpinner, {}) }) });
645
639
  }
646
- return /* @__PURE__ */ jsx4(
640
+ return /* @__PURE__ */ jsx4("figure", { className: className || "max-w-full h-auto", children: /* @__PURE__ */ jsx4(
647
641
  "img",
648
642
  {
649
643
  src: fileUrl,
650
644
  alt: fileReference.file_metadata.fileName || "File",
651
- className: className || "max-w-full h-auto",
645
+ className: "max-w-full h-auto",
652
646
  onError: handleImageError
653
647
  }
654
- );
648
+ ) });
655
649
  }
656
650
  if (displayOnly && !isImage && fileUrl && fileReference && !showDelete) {
657
651
  const fileName = fileReference.file_metadata?.fileName || "Document";
658
652
  const ariaLabel = `Open ${fileName} in new tab`;
659
- return /* @__PURE__ */ jsxs3(
660
- "a",
661
- {
662
- href: fileUrl,
663
- target: "_blank",
664
- rel: "noopener noreferrer",
665
- "aria-label": ariaLabel,
666
- className: `flex items-center gap-2 p-3 bg-sec-50 border border-sec-200 rounded-lg hover:bg-sec-100 transition-colors text-main-600 hover:text-main-700 focus:outline-none focus:ring-2 focus:ring-main-500 focus:ring-offset-2 ${className || ""}`.trim(),
667
- children: [
668
- /* @__PURE__ */ jsx4(FileText, { className: "h-5 w-5 shrink-0", "aria-hidden": "true" }),
669
- /* @__PURE__ */ jsx4("span", { className: "flex-1 font-medium truncate", children: fileName }),
670
- /* @__PURE__ */ jsx4(ExternalLink, { className: "h-5 w-5 shrink-0", "aria-hidden": "true" })
671
- ]
672
- }
673
- );
653
+ return /* @__PURE__ */ jsxs3("figure", { className, children: [
654
+ /* @__PURE__ */ jsxs3(
655
+ "a",
656
+ {
657
+ href: fileUrl,
658
+ target: "_blank",
659
+ rel: "noopener noreferrer",
660
+ "aria-label": ariaLabel,
661
+ className: "flex items-center gap-2 p-3 bg-sec-50 border border-sec-200 rounded-lg hover:bg-sec-100 transition-colors text-main-600 hover:text-main-700 focus:outline-none focus:ring-2 focus:ring-main-500 focus:ring-offset-2",
662
+ children: [
663
+ /* @__PURE__ */ jsx4(FileText, { className: "size-5 shrink-0", "aria-hidden": "true" }),
664
+ /* @__PURE__ */ jsx4("span", { className: "flex-1 font-medium truncate", children: fileName }),
665
+ /* @__PURE__ */ jsx4(ExternalLink, { className: "size-5 shrink-0", "aria-hidden": "true" })
666
+ ]
667
+ }
668
+ ),
669
+ showMetadata && /* @__PURE__ */ jsxs3("figcaption", { children: [
670
+ /* @__PURE__ */ jsx4("p", { children: fileName }),
671
+ fileReference.file_metadata.fileSize && /* @__PURE__ */ jsxs3("p", { children: [
672
+ formatFileSize(fileReference.file_metadata.fileSize),
673
+ " \u2022 ",
674
+ fileReference.file_metadata.fileType
675
+ ] })
676
+ ] })
677
+ ] });
674
678
  }
675
679
  if (displayOnly && showFallback && (!fileUrl || imageError || !isImage)) {
676
- return /* @__PURE__ */ jsx4("div", { className: fallbackClasses, title: fileReference.file_metadata.fileName || "File", children: computedFallbackText });
680
+ return /* @__PURE__ */ jsx4("figure", { className, title: fileReference.file_metadata.fileName || "File", children: /* @__PURE__ */ jsx4("p", { className: fallbackClasses, children: computedFallbackText }) });
677
681
  }
678
- return /* @__PURE__ */ jsxs3("div", { className: `space-y-2 ${className}`, children: [
679
- isImage && fileUrl && !imageError ? /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
682
+ return /* @__PURE__ */ jsx4("figure", { className: `relative ${className}`, children: isImage && fileUrl && !imageError ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
683
+ /* @__PURE__ */ jsx4(
684
+ "img",
685
+ {
686
+ src: fileUrl,
687
+ alt: fileReference.file_metadata.fileName || "File",
688
+ className: "max-w-full h-auto",
689
+ onError: handleImageError
690
+ }
691
+ ),
692
+ showDelete && /* @__PURE__ */ jsxs3(Fragment3, { children: [
680
693
  /* @__PURE__ */ jsx4(
681
- "img",
694
+ Button,
682
695
  {
683
- src: fileUrl,
684
- alt: fileReference.file_metadata.fileName || "File",
685
- className: "max-w-full h-auto",
686
- onError: handleImageError
696
+ variant: "destructive",
697
+ size: "icon",
698
+ onClick: handleDeleteClick,
699
+ className: "absolute top-2 right-2",
700
+ title: "Delete file",
701
+ "aria-label": "Delete file",
702
+ children: "\xD7"
687
703
  }
688
704
  ),
689
- showDelete && /* @__PURE__ */ jsxs3(Fragment2, { children: [
690
- /* @__PURE__ */ jsx4(
691
- "button",
692
- {
693
- onClick: handleDeleteClick,
694
- className: "absolute top-2 right-2 bg-acc-500 text-white rounded-full w-6 h-6 flex items-center justify-center text-sm hover:bg-acc-600",
695
- title: "Delete file",
696
- "aria-label": "Delete file",
697
- children: "\xD7"
698
- }
699
- ),
700
- /* @__PURE__ */ jsx4(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxs3(DialogContent, { size: "sm", children: [
701
- /* @__PURE__ */ jsx4(DialogHeader, { children: /* @__PURE__ */ jsx4(DialogTitle, { children: "Confirm Delete" }) }),
702
- /* @__PURE__ */ jsx4(DialogBody, { children: /* @__PURE__ */ jsx4("p", { children: "Are you sure you want to delete this file? This action cannot be undone." }) }),
703
- /* @__PURE__ */ jsxs3(DialogFooter, { children: [
704
- /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: () => setDeleteDialogOpen(false), children: "Cancel" }),
705
- /* @__PURE__ */ jsx4(Button, { variant: "destructive", onClick: handleDeleteConfirm, children: "Delete" })
706
- ] })
707
- ] }) })
705
+ /* @__PURE__ */ jsx4(Dialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: /* @__PURE__ */ jsxs3(DialogContent, { size: "sm", children: [
706
+ /* @__PURE__ */ jsx4(DialogHeader, { children: /* @__PURE__ */ jsx4(DialogTitle, { children: "Confirm Delete" }) }),
707
+ /* @__PURE__ */ jsx4(DialogBody, { children: /* @__PURE__ */ jsx4("p", { children: "Are you sure you want to delete this file? This action cannot be undone." }) }),
708
+ /* @__PURE__ */ jsxs3(DialogFooter, { children: [
709
+ /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: () => setDeleteDialogOpen(false), children: "Cancel" }),
710
+ /* @__PURE__ */ jsx4(Button, { variant: "destructive", onClick: handleDeleteConfirm, children: "Delete" })
711
+ ] })
712
+ ] }) })
713
+ ] }),
714
+ children,
715
+ showMetadata && /* @__PURE__ */ jsxs3("figcaption", { children: [
716
+ /* @__PURE__ */ jsx4("p", { children: fileReference.file_metadata.fileName || "Unknown file" }),
717
+ (fileReference.file_metadata.fileSize || fileReference.file_metadata.fileType) && /* @__PURE__ */ jsxs3("p", { children: [
718
+ fileReference.file_metadata.fileSize && formatFileSize(fileReference.file_metadata.fileSize),
719
+ fileReference.file_metadata.fileSize && fileReference.file_metadata.fileType && " \u2022 ",
720
+ fileReference.file_metadata.fileType
708
721
  ] })
709
- ] }) : isImage && imageError && showFallback ? (
710
- // Show fallback when image fails to load and fallback is enabled
711
- /* @__PURE__ */ jsx4("div", { className: fallbackClasses, title: fileReference.file_metadata.fileName || "File", children: computedFallbackText })
712
- ) : /* @__PURE__ */ jsxs3("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
713
- /* @__PURE__ */ jsx4("span", { className: "text-2xl", children: getFileIcon(fileReference.file_metadata.fileType || "") }),
714
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
715
- /* @__PURE__ */ jsx4("div", { className: "font-medium text-sec-900 truncate", children: fileReference.file_metadata.fileName || "Unknown file" }),
716
- /* @__PURE__ */ jsxs3("div", { className: "text-sm text-sec-500", children: [
722
+ ] })
723
+ ] }) : isImage && imageError && showFallback ? (
724
+ // Show fallback when image fails to load and fallback is enabled
725
+ /* @__PURE__ */ jsxs3(Fragment3, { children: [
726
+ /* @__PURE__ */ jsx4("p", { className: fallbackClasses, title: fileReference.file_metadata.fileName || "File", children: computedFallbackText }),
727
+ children,
728
+ showMetadata && /* @__PURE__ */ jsxs3("figcaption", { children: [
729
+ /* @__PURE__ */ jsx4("p", { children: fileReference.file_metadata.fileName || "Unknown file" }),
730
+ (fileReference.file_metadata.fileSize || fileReference.file_metadata.fileType) && /* @__PURE__ */ jsxs3("p", { children: [
717
731
  fileReference.file_metadata.fileSize && formatFileSize(fileReference.file_metadata.fileSize),
718
- fileReference.file_metadata.fileType && ` \u2022 ${fileReference.file_metadata.fileType}`
732
+ fileReference.file_metadata.fileSize && fileReference.file_metadata.fileType && " \u2022 ",
733
+ fileReference.file_metadata.fileType
719
734
  ] })
720
- ] }),
721
- showDelete && /* @__PURE__ */ jsxs3(Fragment2, { children: [
735
+ ] })
736
+ ] })
737
+ ) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
738
+ /* @__PURE__ */ jsxs3("p", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
739
+ /* @__PURE__ */ jsx4("span", { className: "text-2xl", children: getFileIcon(fileReference.file_metadata.fileType || "") }),
740
+ showDelete && /* @__PURE__ */ jsxs3(Fragment3, { children: [
722
741
  /* @__PURE__ */ jsx4(
723
- "button",
742
+ Button,
724
743
  {
744
+ variant: "destructive",
745
+ size: "icon",
725
746
  onClick: handleDeleteClick,
726
- className: "text-acc-500 hover:text-acc-700 p-1",
747
+ className: "ml-auto",
727
748
  title: "Delete file",
728
749
  "aria-label": "Delete file",
729
750
  children: "\xD7"
@@ -739,15 +760,23 @@ function FileDisplayContent({
739
760
  ] }) })
740
761
  ] })
741
762
  ] }),
742
- children
743
- ] });
763
+ children,
764
+ showMetadata && /* @__PURE__ */ jsxs3("figcaption", { children: [
765
+ /* @__PURE__ */ jsx4("p", { children: fileReference.file_metadata.fileName || "Unknown file" }),
766
+ (fileReference.file_metadata.fileSize || fileReference.file_metadata.fileType) && /* @__PURE__ */ jsxs3("p", { children: [
767
+ fileReference.file_metadata.fileSize && formatFileSize(fileReference.file_metadata.fileSize),
768
+ fileReference.file_metadata.fileSize && fileReference.file_metadata.fileType && " \u2022 ",
769
+ fileReference.file_metadata.fileType
770
+ ] })
771
+ ] })
772
+ ] }) });
744
773
  }
745
- return /* @__PURE__ */ jsxs3("div", { className: `space-y-2 ${className}`, children: [
774
+ return /* @__PURE__ */ jsxs3("figure", { className: `space-y-2 ${className}`, children: [
746
775
  fileReferences.map((fileRef) => {
747
776
  const isImage = fileRef.file_metadata.fileType?.startsWith("image/");
748
777
  const fileUrl2 = internalFileUrls.get(fileRef.id) || null;
749
778
  const canDownload = !isImage && fileUrl2;
750
- return /* @__PURE__ */ jsxs3("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
779
+ return /* @__PURE__ */ jsxs3("figure", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
751
780
  isImage && fileUrl2 ? /* @__PURE__ */ jsx4(
752
781
  "img",
753
782
  {
@@ -757,15 +786,17 @@ function FileDisplayContent({
757
786
  onError: handleImageError
758
787
  }
759
788
  ) : /* @__PURE__ */ jsx4("span", { className: "text-2xl", children: getFileIcon(fileRef.file_metadata.fileType || "") }),
760
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
761
- /* @__PURE__ */ jsx4("div", { className: "font-medium text-sec-900 truncate", children: fileRef.file_metadata.fileName || "Unknown file" }),
762
- /* @__PURE__ */ jsxs3("div", { className: "text-sm text-sec-500", children: [
789
+ showMetadata && /* @__PURE__ */ jsxs3("figcaption", { className: "flex-1 min-w-0", children: [
790
+ /* @__PURE__ */ jsx4("p", { className: "font-medium text-sec-900 truncate", children: fileRef.file_metadata.fileName || "Unknown file" }),
791
+ (fileRef.file_metadata.fileSize || fileRef.file_metadata.fileType || fileRef.file_metadata.category) && /* @__PURE__ */ jsxs3("p", { className: "text-sm text-sec-500", children: [
763
792
  fileRef.file_metadata.fileSize && formatFileSize(fileRef.file_metadata.fileSize),
764
- fileRef.file_metadata.fileType && ` \u2022 ${fileRef.file_metadata.fileType}`,
765
- fileRef.file_metadata.category && ` \u2022 ${fileRef.file_metadata.category}`
793
+ fileRef.file_metadata.fileSize && fileRef.file_metadata.fileType && " \u2022 ",
794
+ fileRef.file_metadata.fileType,
795
+ (fileRef.file_metadata.fileSize || fileRef.file_metadata.fileType) && fileRef.file_metadata.category && " \u2022 ",
796
+ fileRef.file_metadata.category
766
797
  ] })
767
798
  ] }),
768
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center space-x-2", children: [
799
+ /* @__PURE__ */ jsxs3("p", { className: "flex items-center space-x-2", children: [
769
800
  canDownload && /* @__PURE__ */ jsx4(
770
801
  "a",
771
802
  {
@@ -777,10 +808,11 @@ function FileDisplayContent({
777
808
  }
778
809
  ),
779
810
  showDelete && onDelete && /* @__PURE__ */ jsx4(
780
- "button",
811
+ Button,
781
812
  {
813
+ variant: "destructive",
814
+ size: "icon",
782
815
  onClick: handleDeleteClick,
783
- className: "text-acc-500 hover:text-acc-700 p-1",
784
816
  title: "Delete file",
785
817
  "aria-label": "Delete file",
786
818
  children: "\xD7"
@@ -806,7 +838,10 @@ function FileDisplayPublic({
806
838
  showFallback,
807
839
  generateFallbackText,
808
840
  fallbackText,
809
- fallbackSize
841
+ fallbackSourceText,
842
+ fallbackSize,
843
+ enableChildren,
844
+ showMetadata
810
845
  }) {
811
846
  const publicPageContext = useContext(PublicPageContext);
812
847
  const supabase = publicPageContext?.supabase ?? null;
@@ -834,11 +869,14 @@ function FileDisplayPublic({
834
869
  showFallback,
835
870
  generateFallbackText,
836
871
  fallbackText,
837
- fallbackSize
872
+ fallbackSourceText,
873
+ fallbackSize,
874
+ enableChildren,
875
+ showMetadata
838
876
  }
839
877
  );
840
878
  }
841
- return /* @__PURE__ */ jsx4("div", { className: `text-sec-500 text-center p-4 ${className}`, children: "Supabase client not available in public context" });
879
+ return /* @__PURE__ */ jsx4("figure", { className, title: "Error", children: /* @__PURE__ */ jsx4("p", { className: getFallbackClasses(fallbackSize || "md"), children: "Supabase client not available in public context" }) });
842
880
  }
843
881
  const {
844
882
  fileUrl,
@@ -904,7 +942,10 @@ function FileDisplayPublic({
904
942
  showFallback,
905
943
  generateFallbackText,
906
944
  fallbackText,
907
- fallbackSize
945
+ fallbackSourceText,
946
+ fallbackSize,
947
+ enableChildren,
948
+ showMetadata
908
949
  }
909
950
  );
910
951
  }
@@ -922,11 +963,14 @@ function FileDisplayAuthenticated({
922
963
  showFallback,
923
964
  generateFallbackText,
924
965
  fallbackText,
925
- fallbackSize
966
+ fallbackSourceText,
967
+ fallbackSize,
968
+ enableChildren,
969
+ showMetadata
926
970
  }) {
927
971
  const { supabase } = useUnifiedAuth();
928
972
  if (!supabase) {
929
- return /* @__PURE__ */ jsx4("div", { className: `text-sec-500 text-center p-4 ${className}`, children: "Supabase client not available in authenticated context" });
973
+ return /* @__PURE__ */ jsx4("figure", { className, title: "Error", children: /* @__PURE__ */ jsx4("p", { className: getFallbackClasses(fallbackSize || "md"), children: "Supabase client not available in authenticated context" }) });
930
974
  }
931
975
  const {
932
976
  fileUrl,
@@ -1007,7 +1051,10 @@ function FileDisplayAuthenticated({
1007
1051
  showFallback,
1008
1052
  generateFallbackText,
1009
1053
  fallbackText,
1010
- fallbackSize
1054
+ fallbackSourceText,
1055
+ fallbackSize,
1056
+ enableChildren,
1057
+ showMetadata
1011
1058
  }
1012
1059
  );
1013
1060
  }
@@ -1025,7 +1072,10 @@ function FileDisplay({
1025
1072
  showFallback,
1026
1073
  generateFallbackText,
1027
1074
  fallbackText,
1028
- fallbackSize
1075
+ fallbackSourceText,
1076
+ fallbackSize,
1077
+ enableChildren,
1078
+ showMetadata
1029
1079
  }) {
1030
1080
  const isPublicPage = useIsPublicPage();
1031
1081
  if (isPublicPage) {
@@ -1045,7 +1095,10 @@ function FileDisplay({
1045
1095
  showFallback,
1046
1096
  generateFallbackText,
1047
1097
  fallbackText,
1048
- fallbackSize
1098
+ fallbackSourceText,
1099
+ fallbackSize,
1100
+ enableChildren,
1101
+ showMetadata
1049
1102
  }
1050
1103
  );
1051
1104
  }
@@ -1065,7 +1118,10 @@ function FileDisplay({
1065
1118
  showFallback,
1066
1119
  generateFallbackText,
1067
1120
  fallbackText,
1068
- fallbackSize
1121
+ fallbackSourceText,
1122
+ fallbackSize,
1123
+ enableChildren,
1124
+ showMetadata
1069
1125
  }
1070
1126
  );
1071
1127
  }
@@ -1073,6 +1129,36 @@ function FileDisplay({
1073
1129
  // src/hooks/useFileReference.ts
1074
1130
  import { useState as useState4, useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4, useMemo as useMemo2 } from "react";
1075
1131
  var log2 = createLogger("useFileReference");
1132
+ var urlRefreshManager = {
1133
+ subscriptions: /* @__PURE__ */ new Map(),
1134
+ subscribe(key, callback) {
1135
+ let entry = this.subscriptions.get(key);
1136
+ if (!entry) {
1137
+ entry = { callbacks: /* @__PURE__ */ new Set(), intervalId: null };
1138
+ this.subscriptions.set(key, entry);
1139
+ }
1140
+ entry.callbacks.add(callback);
1141
+ if (!entry.intervalId) {
1142
+ entry.intervalId = setInterval(() => {
1143
+ entry?.callbacks.forEach((cb) => cb());
1144
+ }, 55 * 60 * 1e3);
1145
+ }
1146
+ return () => {
1147
+ this.unsubscribe(key, callback);
1148
+ };
1149
+ },
1150
+ unsubscribe(key, callback) {
1151
+ const entry = this.subscriptions.get(key);
1152
+ if (!entry) return;
1153
+ entry.callbacks.delete(callback);
1154
+ if (entry.callbacks.size === 0) {
1155
+ if (entry.intervalId) {
1156
+ clearInterval(entry.intervalId);
1157
+ }
1158
+ this.subscriptions.delete(key);
1159
+ }
1160
+ }
1161
+ };
1076
1162
  function useFileReference(supabase) {
1077
1163
  const [isLoading, setIsLoading] = useState4(false);
1078
1164
  const [error, setError] = useState4(null);
@@ -1243,7 +1329,7 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
1243
1329
  const [fileReference, setFileReference] = useState4(null);
1244
1330
  const [fileReferences, setFileReferences] = useState4([]);
1245
1331
  const [fileCount, setFileCount] = useState4(0);
1246
- const urlRefreshIntervalRef = useRef4(null);
1332
+ const refreshSubscriptionRef = useRef4(null);
1247
1333
  const loadFileReference = useCallback4(async () => {
1248
1334
  const reference = await getFileReference(table_name, record_id, organisation_id);
1249
1335
  setFileReference(reference);
@@ -1274,23 +1360,24 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
1274
1360
  return success;
1275
1361
  }, [deleteFileReference, table_name, record_id, organisation_id, loadFileCount]);
1276
1362
  useEffect4(() => {
1363
+ if (refreshSubscriptionRef.current) {
1364
+ refreshSubscriptionRef.current();
1365
+ refreshSubscriptionRef.current = null;
1366
+ }
1277
1367
  if (!fileReference || fileReference.is_public) {
1278
- if (urlRefreshIntervalRef.current) {
1279
- clearInterval(urlRefreshIntervalRef.current);
1280
- urlRefreshIntervalRef.current = null;
1281
- }
1282
1368
  return;
1283
1369
  }
1284
- urlRefreshIntervalRef.current = setInterval(() => {
1370
+ const key = `${fileReference.table_name}:${fileReference.record_id}:${organisation_id}`;
1371
+ refreshSubscriptionRef.current = urlRefreshManager.subscribe(key, () => {
1285
1372
  loadFileUrl();
1286
- }, 55 * 60 * 1e3);
1373
+ });
1287
1374
  return () => {
1288
- if (urlRefreshIntervalRef.current) {
1289
- clearInterval(urlRefreshIntervalRef.current);
1290
- urlRefreshIntervalRef.current = null;
1375
+ if (refreshSubscriptionRef.current) {
1376
+ refreshSubscriptionRef.current();
1377
+ refreshSubscriptionRef.current = null;
1291
1378
  }
1292
1379
  };
1293
- }, [fileReference, loadFileUrl]);
1380
+ }, [fileReference, loadFileUrl, organisation_id]);
1294
1381
  return {
1295
1382
  isLoading,
1296
1383
  error,
@@ -1396,12 +1483,12 @@ function useFilesByCategory(supabase, table_name, record_id, category, organisat
1396
1483
  import * as React5 from "react";
1397
1484
  import { jsx as jsx5 } from "react/jsx-runtime";
1398
1485
  var sizeClasses = {
1399
- xs: "h-4 w-4 text-xs",
1400
- sm: "h-6 w-6 text-sm",
1401
- md: "h-10 w-10 text-base",
1402
- lg: "h-12 w-12 text-lg",
1403
- xl: "h-16 w-16 text-xl",
1404
- "2xl": "h-20 w-20 text-2xl"
1486
+ xs: "size-4 text-xs",
1487
+ sm: "size-6 text-sm",
1488
+ md: "size-10 text-base",
1489
+ lg: "size-12 text-lg",
1490
+ xl: "size-16 text-xl",
1491
+ "2xl": "size-20 text-2xl"
1405
1492
  };
1406
1493
  var Avatar = React5.forwardRef(
1407
1494
  ({
@@ -1430,9 +1517,9 @@ var Avatar = React5.forwardRef(
1430
1517
  const hasFileId = canFetchFileId && fileIdUrl && !fileIdLoading;
1431
1518
  const hasDirectUrl = src && !imageError;
1432
1519
  const showFallback = !hasDirectUrl && (!hasFileProps && !hasFileId) || imageError || canFetchFileId && !fileIdUrl && !fileIdLoading;
1433
- const baseClasses = size === "md" ? "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full" : `relative flex ${sizeClasses[size]} shrink-0 overflow-hidden rounded-full`;
1434
- const fallbackClasses = "flex h-full w-full items-center justify-center rounded-full text-sec-50 bg-sec-500";
1435
- const imageClasses = "object-cover h-full w-full";
1520
+ const baseClasses = size === "md" ? " size-10 overflow-hidden rounded-full" : ` ${sizeClasses[size]} overflow-hidden rounded-full`;
1521
+ const fallbackClasses = "size-full grid place-items-center text-center text-sec-50 bg-sec-500";
1522
+ const imageClasses = "object-cover size-full";
1436
1523
  const containerClasses = cn(baseClasses, className);
1437
1524
  const handleImageError = React5.useCallback(() => {
1438
1525
  setImageError(true);
@@ -1443,12 +1530,12 @@ var Avatar = React5.forwardRef(
1443
1530
  }
1444
1531
  }, [src]);
1445
1532
  return /* @__PURE__ */ jsx5(
1446
- "div",
1533
+ "figure",
1447
1534
  {
1448
1535
  ref,
1449
1536
  className: containerClasses,
1450
1537
  ...props,
1451
- children: showFallback ? /* @__PURE__ */ jsx5("div", { className: fallbackClasses, "aria-label": alt || fallback, children: fallback }) : hasFileProps ? (
1538
+ children: showFallback ? /* @__PURE__ */ jsx5("figcaption", { className: fallbackClasses, "aria-label": alt || fallback, children: fallback }) : hasFileProps ? (
1452
1539
  // File reference props approach - use FileDisplay
1453
1540
  /* @__PURE__ */ jsx5(
1454
1541
  FileDisplay,
@@ -1487,7 +1574,7 @@ var Avatar = React5.forwardRef(
1487
1574
  )
1488
1575
  ) : (
1489
1576
  // Fallback if nothing else works
1490
- /* @__PURE__ */ jsx5("div", { className: fallbackClasses, "aria-label": alt || fallback, children: fallback })
1577
+ /* @__PURE__ */ jsx5("figcaption", { className: fallbackClasses, "aria-label": alt || fallback, children: fallback })
1491
1578
  )
1492
1579
  }
1493
1580
  );
@@ -1624,7 +1711,7 @@ var Switch = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
1624
1711
  {
1625
1712
  className: cn(
1626
1713
  // Base styles
1627
- "pointer-events-none block h-5 w-5 rounded-full",
1714
+ "pointer-events-none block size-5 rounded-full",
1628
1715
  // Background and shadow
1629
1716
  "bg-background shadow-lg ring-0",
1630
1717
  // Transition
@@ -1691,86 +1778,298 @@ TabsContent.displayName = TabsPrimitive.Content.displayName || "TabsContent";
1691
1778
 
1692
1779
  // src/components/Calendar/Calendar.tsx
1693
1780
  import * as React9 from "react";
1694
- import { DayPicker } from "react-day-picker";
1695
- import { jsx as jsx9 } from "react/jsx-runtime";
1781
+ import {
1782
+ DayPicker,
1783
+ useDayPicker
1784
+ } from "react-day-picker";
1785
+ import { enAU } from "date-fns/locale";
1786
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1787
+ var assignToRef = (ref, value) => {
1788
+ if (!ref) {
1789
+ return;
1790
+ }
1791
+ if (typeof ref === "function") {
1792
+ ref(value);
1793
+ return;
1794
+ }
1795
+ ref.current = value;
1796
+ };
1696
1797
  var Calendar = React9.forwardRef(
1697
- ({ className, classNames, mode, components, ...props }, ref) => {
1698
- const defaultComponents = {
1699
- IconLeft: ({ ...iconProps }) => /* @__PURE__ */ jsx9(
1700
- "svg",
1701
- {
1702
- xmlns: "http://www.w3.org/2000/svg",
1703
- viewBox: "0 0 24 24",
1704
- fill: "none",
1705
- stroke: "currentColor",
1706
- strokeWidth: "2",
1707
- strokeLinecap: "round",
1708
- strokeLinejoin: "round",
1709
- className: "h-4 w-4",
1710
- ...iconProps,
1711
- children: /* @__PURE__ */ jsx9("path", { d: "m15 18-6-6 6-6" })
1798
+ ({ className, classNames, mode, components, locale, month: controlledMonth, onMonthChange: controlledOnMonthChange, onSelect, ...props }, ref) => {
1799
+ const tableRef = React9.useRef(null);
1800
+ const setForwardedRef = React9.useCallback(
1801
+ (node) => {
1802
+ tableRef.current = node;
1803
+ if (!ref) {
1804
+ return;
1712
1805
  }
1713
- ),
1714
- IconRight: ({ ...iconProps }) => /* @__PURE__ */ jsx9(
1715
- "svg",
1716
- {
1717
- xmlns: "http://www.w3.org/2000/svg",
1718
- viewBox: "0 0 24 24",
1719
- fill: "none",
1720
- stroke: "currentColor",
1721
- strokeWidth: "2",
1722
- strokeLinecap: "round",
1723
- strokeLinejoin: "round",
1724
- className: "h-4 w-4",
1725
- ...iconProps,
1726
- children: /* @__PURE__ */ jsx9("path", { d: "m9 18 6-6-6-6" })
1806
+ if (typeof ref === "function") {
1807
+ ref(node);
1808
+ } else {
1809
+ ref.current = node;
1727
1810
  }
1728
- ),
1729
- ...components
1730
- };
1731
- return /* @__PURE__ */ jsx9("div", { ref, className: cn("p-3", className), children: /* @__PURE__ */ jsx9(
1811
+ },
1812
+ [ref]
1813
+ );
1814
+ const rootPropsRef = React9.useRef(null);
1815
+ const selected = props.selected;
1816
+ const isMonthControlled = controlledMonth !== void 0;
1817
+ const [internalMonth, setInternalMonth] = React9.useState(() => {
1818
+ const now = /* @__PURE__ */ new Date();
1819
+ return new Date(now.getFullYear(), now.getMonth(), 1);
1820
+ });
1821
+ const month = React9.useMemo(() => {
1822
+ const monthToUse = isMonthControlled ? controlledMonth : internalMonth;
1823
+ if (!monthToUse) {
1824
+ const now = /* @__PURE__ */ new Date();
1825
+ return new Date(now.getFullYear(), now.getMonth(), 1);
1826
+ }
1827
+ const normalized = new Date(monthToUse.getFullYear(), monthToUse.getMonth(), 1);
1828
+ return normalized;
1829
+ }, [isMonthControlled, controlledMonth, internalMonth]);
1830
+ const handleMonthChange = React9.useCallback((newMonth) => {
1831
+ if (!isMonthControlled) {
1832
+ setInternalMonth(newMonth);
1833
+ }
1834
+ controlledOnMonthChange?.(newMonth);
1835
+ }, [isMonthControlled, controlledOnMonthChange]);
1836
+ const wrappedHandleMonthChange = React9.useCallback((newMonth) => {
1837
+ handleMonthChange(newMonth);
1838
+ }, [handleMonthChange]);
1839
+ const CustomRoot = React9.memo(({ children, rootRef: dayPickerRootRef, ...rootProps }) => {
1840
+ const {
1841
+ className: rootClassName,
1842
+ style: rootStyle,
1843
+ children: _ignoredChildren,
1844
+ ...restProps
1845
+ } = rootProps;
1846
+ rootPropsRef.current = {
1847
+ className: rootClassName,
1848
+ style: rootStyle,
1849
+ rootRef: dayPickerRootRef,
1850
+ restProps
1851
+ };
1852
+ return /* @__PURE__ */ jsx9(Fragment4, { children });
1853
+ });
1854
+ CustomRoot.displayName = "CustomRoot";
1855
+ const CustomMonths = React9.memo(({ children }) => {
1856
+ return /* @__PURE__ */ jsx9(Fragment4, { children });
1857
+ });
1858
+ CustomMonths.displayName = "CustomMonths";
1859
+ const CustomMonthGrid = React9.forwardRef((props2, forwardedRef) => {
1860
+ return /* @__PURE__ */ jsx9("table", { ref: forwardedRef, ...props2 });
1861
+ });
1862
+ CustomMonthGrid.displayName = "CustomMonthGrid";
1863
+ const CustomMonth = React9.memo(({ calendarMonth, displayIndex, className: className2, children }) => {
1864
+ const { formatters, components: components2, labels, classNames: classNames2, previousMonth, nextMonth, goToMonth } = useDayPicker();
1865
+ const caption = formatters.formatCaption(calendarMonth.date, {});
1866
+ const Chevron = components2?.Chevron;
1867
+ const childrenArray = React9.Children.toArray(children);
1868
+ const monthGridIndex = childrenArray.findIndex((child) => {
1869
+ if (!React9.isValidElement(child)) return false;
1870
+ const childType = child.type;
1871
+ return typeof childType === "function" && childType.displayName === "MonthGrid" || child.type === "table";
1872
+ });
1873
+ return /* @__PURE__ */ jsx9(Fragment4, { children: childrenArray.map((child, index) => {
1874
+ if (React9.isValidElement(child) && child.type?.displayName === "MonthCaption") {
1875
+ return null;
1876
+ }
1877
+ if (index === monthGridIndex && React9.isValidElement(child)) {
1878
+ const monthGridChild = child;
1879
+ const applyRootProps = displayIndex === 0 && index === monthGridIndex;
1880
+ const storedRootProps = applyRootProps ? rootPropsRef.current : null;
1881
+ const { children: monthGridChildren, className: monthGridClassName, style: monthGridStyle, ...monthGridRest } = monthGridChild.props;
1882
+ const mergedClassName = cn(
1883
+ "w-full border-collapse rounded-md border border-sec-200 bg-background",
1884
+ applyRootProps ? storedRootProps?.className : void 0,
1885
+ className2,
1886
+ monthGridClassName
1887
+ );
1888
+ const mergedStyle = {
1889
+ ...applyRootProps ? storedRootProps?.style ?? {} : {},
1890
+ ...monthGridStyle ?? {}
1891
+ };
1892
+ const tableProps = {
1893
+ ...applyRootProps && storedRootProps?.restProps ? storedRootProps.restProps : {},
1894
+ ...monthGridRest,
1895
+ className: mergedClassName,
1896
+ ...Object.keys(mergedStyle).length ? { style: mergedStyle } : {}
1897
+ };
1898
+ if (mode && tableProps["data-mode"] === void 0) {
1899
+ tableProps["data-mode"] = mode;
1900
+ }
1901
+ const shouldAttachRef = applyRootProps || storedRootProps?.rootRef;
1902
+ const handleTableRef = shouldAttachRef ? (node) => {
1903
+ if (applyRootProps) {
1904
+ setForwardedRef(node);
1905
+ }
1906
+ if (storedRootProps?.rootRef) {
1907
+ assignToRef(storedRootProps.rootRef, node);
1908
+ }
1909
+ } : void 0;
1910
+ const handlePreviousClick = (event) => {
1911
+ event.preventDefault();
1912
+ if (!previousMonth) return;
1913
+ goToMonth(previousMonth);
1914
+ };
1915
+ const handleNextClick = (event) => {
1916
+ event.preventDefault();
1917
+ if (!nextMonth) return;
1918
+ goToMonth(nextMonth);
1919
+ };
1920
+ const monthGridElement = monthGridChild;
1921
+ const mergedRef = handleTableRef || monthGridElement.ref ? (node) => {
1922
+ if (handleTableRef) {
1923
+ handleTableRef(node);
1924
+ }
1925
+ assignToRef(monthGridElement.ref, node);
1926
+ } : void 0;
1927
+ return React9.cloneElement(
1928
+ monthGridElement,
1929
+ {
1930
+ key: child.key ?? `month-grid-${displayIndex}`,
1931
+ ...tableProps,
1932
+ ...mergedRef ? { ref: mergedRef } : {}
1933
+ },
1934
+ /* @__PURE__ */ jsxs4(Fragment4, { children: [
1935
+ /* @__PURE__ */ jsx9("caption", { className: "relative", children: /* @__PURE__ */ jsxs4("nav", { className: "relative flex items-center justify-center gap-1", children: [
1936
+ /* @__PURE__ */ jsx9(
1937
+ "button",
1938
+ {
1939
+ type: "button",
1940
+ className: cn(
1941
+ "h-7 w-7 bg-transparent p-0",
1942
+ "inline-flex items-center justify-center rounded-md",
1943
+ "hover:bg-acc-100",
1944
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
1945
+ "disabled:opacity-50 disabled:pointer-events-none",
1946
+ classNames2?.button_previous
1947
+ ),
1948
+ tabIndex: previousMonth ? void 0 : -1,
1949
+ "aria-disabled": previousMonth ? void 0 : true,
1950
+ "aria-label": previousMonth ? labels.labelPrevious(previousMonth) : void 0,
1951
+ onClick: handlePreviousClick,
1952
+ disabled: !previousMonth,
1953
+ children: Chevron ? /* @__PURE__ */ jsx9(Chevron, { orientation: "left", className: "size-4", disabled: !previousMonth }) : /* @__PURE__ */ jsx9("span", { children: "\u2039" })
1954
+ }
1955
+ ),
1956
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium", children: caption }),
1957
+ /* @__PURE__ */ jsx9(
1958
+ "button",
1959
+ {
1960
+ type: "button",
1961
+ className: cn(
1962
+ "h-7 w-7 bg-transparent p-0",
1963
+ "inline-flex items-center justify-center rounded-md",
1964
+ "hover:bg-acc-100",
1965
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
1966
+ "disabled:opacity-50 disabled:pointer-events-none",
1967
+ classNames2?.button_next
1968
+ ),
1969
+ tabIndex: nextMonth ? void 0 : -1,
1970
+ "aria-disabled": nextMonth ? void 0 : true,
1971
+ "aria-label": nextMonth ? labels.labelNext(nextMonth) : void 0,
1972
+ onClick: handleNextClick,
1973
+ disabled: !nextMonth,
1974
+ children: Chevron ? /* @__PURE__ */ jsx9(Chevron, { orientation: "right", className: "size-4", disabled: !nextMonth }) : /* @__PURE__ */ jsx9("span", { children: "\u203A" })
1975
+ }
1976
+ )
1977
+ ] }) }),
1978
+ monthGridChildren
1979
+ ] })
1980
+ );
1981
+ }
1982
+ return child;
1983
+ }) });
1984
+ });
1985
+ CustomMonth.displayName = "CustomMonth";
1986
+ const CustomWeekdays = React9.memo(({ className: className2, children, ...props2 }) => {
1987
+ return /* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsx9("tr", { className: cn("text-xs text-sec-500", className2), ...props2, children }) });
1988
+ });
1989
+ CustomWeekdays.displayName = "CustomWeekdays";
1990
+ const defaultComponents = React9.useMemo(() => ({
1991
+ Root: CustomRoot,
1992
+ Months: CustomMonths,
1993
+ Month: CustomMonth,
1994
+ MonthGrid: CustomMonthGrid,
1995
+ // MonthCaption is now handled inside CustomMonth (injected into table)
1996
+ Weekdays: CustomWeekdays,
1997
+ // Spread user components AFTER ours so ours take precedence
1998
+ ...components || {}
1999
+ }), [components, CustomRoot, CustomMonths, CustomMonth, CustomWeekdays]);
2000
+ return /* @__PURE__ */ jsx9(
1732
2001
  DayPicker,
1733
2002
  {
1734
2003
  ...mode ? { mode } : {},
2004
+ locale: locale ?? enAU,
2005
+ hideNavigation: true,
1735
2006
  ...props,
1736
- className: "rounded-md border border-sec-200 bg-background",
2007
+ selected,
2008
+ onSelect,
2009
+ month,
2010
+ onMonthChange: wrappedHandleMonthChange,
2011
+ className,
1737
2012
  classNames: {
1738
- months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
1739
- month: "space-y-4",
1740
- caption: "flex justify-center pt-1 relative items-center",
2013
+ // v9 API: Updated for table-based structure
2014
+ months: "",
2015
+ // No wrapper - removed by CustomMonths
2016
+ month: "",
2017
+ // No wrapper - removed by CustomMonth
2018
+ month_caption: "",
2019
+ // Now handled by custom component (renders as <caption>)
1741
2020
  caption_label: "text-sm font-medium",
1742
- nav: "space-x-1 flex items-center",
1743
- nav_button: cn(
1744
- "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
2021
+ nav: "relative flex items-center justify-center space-x-1",
2022
+ // v9: button_previous and button_next for navigation buttons
2023
+ button_previous: cn(
2024
+ "absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
2025
+ "border border-input hover:bg-acc-100",
2026
+ "inline-flex items-center justify-center rounded-md",
2027
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2"
2028
+ ),
2029
+ button_next: cn(
2030
+ "absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
1745
2031
  "border border-input hover:bg-acc-100",
1746
2032
  "inline-flex items-center justify-center rounded-md",
1747
2033
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2"
1748
2034
  ),
1749
- nav_button_previous: "absolute left-1",
1750
- nav_button_next: "absolute right-1",
1751
- table: "w-full border-collapse space-y-1",
1752
- head_row: "flex",
1753
- head_cell: "text-sec-600 rounded-md w-9 font-normal text-[0.8rem]",
1754
- row: "flex w-full mt-2",
1755
- cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-acc-50/50 [&:has([aria-selected])]:bg-acc-100 first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
1756
- day: cn(
2035
+ // v9: table -> month_grid (now a proper <table>)
2036
+ month_grid: "",
2037
+ // Styles applied directly to table in CustomMonth
2038
+ // v9: head_row -> weekdays (now wrapped in <thead> by custom component)
2039
+ weekdays: "",
2040
+ // Styles applied to <tr> inside <thead>
2041
+ weekday: "text-sec-600 rounded-md w-9 font-normal text-[0.8rem]",
2042
+ // v9: row -> week (now a proper <tr>)
2043
+ week: "mt-2",
2044
+ // v9: cell -> day (now a proper <td> by custom component)
2045
+ day: "",
2046
+ // Styles moved to <td> in custom component
2047
+ // v9: day -> day_button (the button inside the cell)
2048
+ day_button: cn(
1757
2049
  "h-9 w-9 p-0 font-normal aria-selected:opacity-100",
1758
2050
  "hover:bg-acc-100 hover:text-main-600",
1759
2051
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
1760
2052
  "inline-flex items-center justify-center rounded-md"
1761
2053
  ),
1762
- day_range_end: "day-range-end",
1763
- day_selected: "bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50 focus:bg-main-600 focus:text-main-50",
1764
- day_today: "bg-sec-100 text-main-600 font-semibold",
1765
- day_outside: "day-outside text-sec-400 opacity-50 aria-selected:bg-acc-50/50 aria-selected:text-sec-400 aria-selected:opacity-30",
1766
- day_disabled: "text-sec-400 opacity-50 cursor-not-allowed",
1767
- day_range_middle: "aria-selected:bg-acc-100 aria-selected:text-main-600",
1768
- day_hidden: "invisible",
2054
+ // v9: day_range_end -> range_end
2055
+ range_end: "range-end",
2056
+ // v9: day_selected -> selected
2057
+ selected: "bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50 focus:bg-main-600 focus:text-main-50",
2058
+ // v9: day_today -> today
2059
+ today: "bg-sec-100 text-main-600 font-semibold",
2060
+ // v9: day_outside -> outside
2061
+ outside: "outside text-sec-400 opacity-50 aria-selected:bg-acc-50/50 aria-selected:text-sec-400 aria-selected:opacity-30",
2062
+ // v9: day_disabled -> disabled
2063
+ disabled: "text-sec-400 opacity-50 cursor-not-allowed",
2064
+ // v9: day_range_middle -> range_middle
2065
+ range_middle: "aria-selected:bg-acc-100 aria-selected:text-main-600",
2066
+ // v9: day_hidden -> hidden
2067
+ hidden: "invisible",
1769
2068
  ...classNames
1770
2069
  },
1771
2070
  components: defaultComponents
1772
2071
  }
1773
- ) });
2072
+ );
1774
2073
  }
1775
2074
  );
1776
2075
  Calendar.displayName = "Calendar";
@@ -1779,7 +2078,7 @@ Calendar.displayName = "Calendar";
1779
2078
  import * as React10 from "react";
1780
2079
  import * as ToastPrimitives from "@radix-ui/react-toast";
1781
2080
  import { X } from "lucide-react";
1782
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
2081
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1783
2082
  var ToastProvider = ToastPrimitives.Provider;
1784
2083
  var ToastViewport = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
1785
2084
  ToastPrimitives.Viewport,
@@ -1833,7 +2132,7 @@ var ToastClose = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE
1833
2132
  ),
1834
2133
  "toast-close": "",
1835
2134
  ...props,
1836
- children: /* @__PURE__ */ jsx10(X, { className: "h-4 w-4" })
2135
+ children: /* @__PURE__ */ jsx10(X, { className: "size-4" })
1837
2136
  }
1838
2137
  ));
1839
2138
  ToastClose.displayName = ToastPrimitives.Close.displayName;
@@ -1859,11 +2158,11 @@ var ToastDescription = React10.forwardRef(({ className, ...props }, ref) => /* @
1859
2158
  ToastDescription.displayName = ToastPrimitives.Description.displayName;
1860
2159
  function Toaster() {
1861
2160
  const { toasts } = useToast();
1862
- return /* @__PURE__ */ jsxs4(ToastProvider, { "data-testid": "toast-provider", children: [
2161
+ return /* @__PURE__ */ jsxs5(ToastProvider, { "data-testid": "toast-provider", children: [
1863
2162
  /* @__PURE__ */ jsx10(ToastViewport, {}),
1864
2163
  toasts.map((toast) => {
1865
2164
  const { id, title, description, action, dismiss, duration, ...toastProps } = toast;
1866
- return /* @__PURE__ */ jsxs4(Toast, { ...toastProps, duration, children: [
2165
+ return /* @__PURE__ */ jsxs5(Toast, { ...toastProps, duration, children: [
1867
2166
  title && /* @__PURE__ */ jsx10(ToastTitle, { children: title }),
1868
2167
  description && /* @__PURE__ */ jsx10(ToastDescription, { children: description }),
1869
2168
  action && action,
@@ -1876,7 +2175,7 @@ function Toaster() {
1876
2175
  // src/components/Form/Form.tsx
1877
2176
  import { useForm, FormProvider, useFormContext, Controller } from "react-hook-form";
1878
2177
  import { zodResolver } from "@hookform/resolvers/zod";
1879
- import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
2178
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1880
2179
  function Form({
1881
2180
  schema,
1882
2181
  defaultValues,
@@ -1908,8 +2207,8 @@ function FormField({
1908
2207
  const { control, formState: { errors } } = useFormContext();
1909
2208
  const fieldError = errors[name];
1910
2209
  const errorMessage = fieldError && typeof fieldError === "object" && "message" in fieldError ? String(fieldError.message) : void 0;
1911
- return /* @__PURE__ */ jsxs5("div", { className: cn("space-y-2", className), children: [
1912
- label && /* @__PURE__ */ jsxs5(Label, { htmlFor: name, children: [
2210
+ return /* @__PURE__ */ jsxs6("div", { className: cn("space-y-2", className), children: [
2211
+ label && /* @__PURE__ */ jsxs6(Label, { htmlFor: name, children: [
1913
2212
  label,
1914
2213
  validation?.required && /* @__PURE__ */ jsx11("span", { className: "text-destructive ml-1", "aria-label": "required", children: "*" })
1915
2214
  ] }),
@@ -1946,8 +2245,8 @@ function FormField({
1946
2245
  }
1947
2246
 
1948
2247
  // src/components/LoginForm/LoginForm.tsx
1949
- import React11, { useState as useState6, useCallback as useCallback6, useMemo as useMemo3 } from "react";
1950
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
2248
+ import React11, { useState as useState7, useCallback as useCallback7, useMemo as useMemo4 } from "react";
2249
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1951
2250
  var LoginForm = React11.memo(({
1952
2251
  onSignIn,
1953
2252
  onSuccess,
@@ -1960,18 +2259,18 @@ var LoginForm = React11.memo(({
1960
2259
  onSignUp,
1961
2260
  className
1962
2261
  }) => {
1963
- const [formData, setFormData] = useState6({ email: "", password: "" });
1964
- const [error, setError] = useState6(null);
1965
- const isFormValid = useMemo3(() => {
2262
+ const [formData, setFormData] = useState7({ email: "", password: "" });
2263
+ const [error, setError] = useState7(null);
2264
+ const isFormValid = useMemo4(() => {
1966
2265
  return formData.email.length > 0 && formData.password.length > 0;
1967
2266
  }, [formData.email, formData.password]);
1968
- const handleEmailChange = useCallback6((e) => {
2267
+ const handleEmailChange = useCallback7((e) => {
1969
2268
  setFormData((prev) => ({ ...prev, email: e.target.value }));
1970
2269
  }, []);
1971
- const handlePasswordChange = useCallback6((e) => {
2270
+ const handlePasswordChange = useCallback7((e) => {
1972
2271
  setFormData((prev) => ({ ...prev, password: e.target.value }));
1973
2272
  }, []);
1974
- const handleSubmit = useCallback6(async (e) => {
2273
+ const handleSubmit = useCallback7(async (e) => {
1975
2274
  e.preventDefault();
1976
2275
  setError(null);
1977
2276
  if (!isFormValid || isLoading) return;
@@ -1984,17 +2283,17 @@ var LoginForm = React11.memo(({
1984
2283
  onError?.(err instanceof Error ? err : new Error(errorMessage));
1985
2284
  }
1986
2285
  }, [formData, isFormValid, isLoading, onSignIn, onSuccess, onError]);
1987
- const handleSignUpClick = useCallback6(() => {
2286
+ const handleSignUpClick = useCallback7(() => {
1988
2287
  onSignUp?.();
1989
2288
  }, [onSignUp]);
1990
- const displayTitle = useMemo3(() => title || (appName ? `Sign in to ${appName}` : "Sign In"), [title, appName]);
1991
- const displaySubtitle = useMemo3(() => subtitle || "Enter your credentials to continue.", [subtitle]);
1992
- return /* @__PURE__ */ jsx12(Card, { className: cn("w-full max-w-md mx-auto", className), children: /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, "data-testid": "login-form", children: [
1993
- /* @__PURE__ */ jsxs6(CardHeader, { className: "space-y-1", children: [
2289
+ const displayTitle = useMemo4(() => title || (appName ? `Sign in to ${appName}` : "Sign In"), [title, appName]);
2290
+ const displaySubtitle = useMemo4(() => subtitle || "Enter your credentials to continue.", [subtitle]);
2291
+ return /* @__PURE__ */ jsx12(Card, { className: cn("w-full max-w-md mx-auto", className), children: /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, "data-testid": "login-form", children: [
2292
+ /* @__PURE__ */ jsxs7(CardHeader, { className: "space-y-1", children: [
1994
2293
  /* @__PURE__ */ jsx12(CardTitle, { className: "text-2xl text-center", children: displayTitle }),
1995
2294
  /* @__PURE__ */ jsx12(CardDescription, { className: "text-center", children: displaySubtitle })
1996
2295
  ] }),
1997
- /* @__PURE__ */ jsxs6(CardContent, { className: "space-y-4", children: [
2296
+ /* @__PURE__ */ jsxs7(CardContent, { className: "space-y-4", children: [
1998
2297
  error && /* @__PURE__ */ jsx12(Alert, { variant: "destructive", role: "alert", "aria-live": "assertive", children: /* @__PURE__ */ jsx12(AlertDescription, { children: error }) }),
1999
2298
  /* @__PURE__ */ jsx12(Label, { htmlFor: "email", children: "Email" }),
2000
2299
  /* @__PURE__ */ jsx12(
@@ -2023,7 +2322,7 @@ var LoginForm = React11.memo(({
2023
2322
  }
2024
2323
  )
2025
2324
  ] }),
2026
- /* @__PURE__ */ jsxs6(CardFooter, { className: "flex flex-col space-y-4", children: [
2325
+ /* @__PURE__ */ jsxs7(CardFooter, { className: "flex flex-col space-y-4", children: [
2027
2326
  /* @__PURE__ */ jsx12(
2028
2327
  Button,
2029
2328
  {
@@ -2041,7 +2340,7 @@ var LoginForm = React11.memo(({
2041
2340
  className: "text-primary hover:underline",
2042
2341
  children: "Don't have an account? Sign up"
2043
2342
  }
2044
- ) }) : /* @__PURE__ */ jsxs6("p", { className: "text-center text-muted-foreground", children: [
2343
+ ) }) : /* @__PURE__ */ jsxs7("p", { className: "text-center text-muted-foreground", children: [
2045
2344
  "Don't have an account?",
2046
2345
  " ",
2047
2346
  /* @__PURE__ */ jsx12("a", { href: "/signup", className: "text-primary hover:underline", children: "Sign up" })
@@ -2052,8 +2351,8 @@ var LoginForm = React11.memo(({
2052
2351
 
2053
2352
  // src/components/EventSelector/EventSelector.tsx
2054
2353
  import { RefreshCw, AlertCircle, Lock, Calendar as Calendar2, Star } from "lucide-react";
2055
- import { useEffect as useEffect6, useMemo as useMemo4, useRef as useRef5 } from "react";
2056
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
2354
+ import { useEffect as useEffect6, useMemo as useMemo5, useRef as useRef6 } from "react";
2355
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2057
2356
  function EventSelector({
2058
2357
  placeholder = "Select an event",
2059
2358
  className,
@@ -2111,13 +2410,13 @@ function EventSelector({
2111
2410
  return date.toLocaleDateString();
2112
2411
  }
2113
2412
  };
2114
- const sortedEvents = useMemo4(() => {
2413
+ const sortedEvents = useMemo5(() => {
2115
2414
  const getTime = (e) => e.event_date ? new Date(e.event_date).getTime() : Number.NEGATIVE_INFINITY;
2116
2415
  return [...events].sort((a, b) => getTime(b) - getTime(a));
2117
2416
  }, [events]);
2118
- const prevEventsLengthRef = useRef5(events.length);
2119
- const prevSelectedEventIdRef = useRef5(selectedEvent?.event_id);
2120
- const hasAutoSelectedRef = useRef5(false);
2417
+ const prevEventsLengthRef = useRef6(events.length);
2418
+ const prevSelectedEventIdRef = useRef6(selectedEvent?.event_id);
2419
+ const hasAutoSelectedRef = useRef6(false);
2121
2420
  useEffect6(() => {
2122
2421
  const eventsLengthChanged = events.length !== prevEventsLengthRef.current;
2123
2422
  const selectedEventChanged = selectedEvent?.event_id !== prevSelectedEventIdRef.current;
@@ -2159,17 +2458,17 @@ function EventSelector({
2159
2458
  }
2160
2459
  }, [events.length, selectedEvent?.event_id, isLoading, setSelectedEvent, onEventChange]);
2161
2460
  if (isLoading) {
2162
- return /* @__PURE__ */ jsxs7("div", { className: `flex items-center gap-2 ${className}`, children: [
2461
+ return /* @__PURE__ */ jsxs8("div", { className: `flex items-center gap-2 ${className}`, children: [
2163
2462
  /* @__PURE__ */ jsx13(LoadingSpinner, { size: "sm" }),
2164
2463
  /* @__PURE__ */ jsx13("span", { className: "text-sm text-muted-foreground", children: "Loading events..." })
2165
2464
  ] });
2166
2465
  }
2167
2466
  if (error) {
2168
- return /* @__PURE__ */ jsx13("div", { className, children: /* @__PURE__ */ jsxs7(Alert, { variant: "destructive", children: [
2169
- /* @__PURE__ */ jsx13(Lock, { className: "h-4 w-4" }),
2170
- /* @__PURE__ */ jsxs7(AlertDescription, { className: "flex items-center justify-between", children: [
2467
+ return /* @__PURE__ */ jsx13("div", { className, children: /* @__PURE__ */ jsxs8(Alert, { variant: "destructive", children: [
2468
+ /* @__PURE__ */ jsx13(Lock, { className: "size-4" }),
2469
+ /* @__PURE__ */ jsxs8(AlertDescription, { className: "flex items-center justify-between", children: [
2171
2470
  /* @__PURE__ */ jsx13("span", { children: error.message }),
2172
- showRetryButton && /* @__PURE__ */ jsxs7(
2471
+ showRetryButton && /* @__PURE__ */ jsxs8(
2173
2472
  Button,
2174
2473
  {
2175
2474
  variant: "outline",
@@ -2177,7 +2476,7 @@ function EventSelector({
2177
2476
  onClick: handleRetry,
2178
2477
  className: "ml-2",
2179
2478
  children: [
2180
- /* @__PURE__ */ jsx13(RefreshCw, { className: "h-3 w-3 mr-1" }),
2479
+ /* @__PURE__ */ jsx13(RefreshCw, { className: "size-3 mr-1" }),
2181
2480
  "Retry"
2182
2481
  ]
2183
2482
  }
@@ -2187,11 +2486,11 @@ function EventSelector({
2187
2486
  }
2188
2487
  if (events.length === 0) {
2189
2488
  if (showNoEventsMessage) {
2190
- return /* @__PURE__ */ jsx13("div", { className, children: /* @__PURE__ */ jsxs7(Alert, { variant: "inline", children: [
2191
- /* @__PURE__ */ jsx13(AlertCircle, { className: "h-4 w-4 text-acc-700" }),
2192
- /* @__PURE__ */ jsxs7(AlertDescription, { className: "flex items-center justify-between", children: [
2489
+ return /* @__PURE__ */ jsx13("div", { className, children: /* @__PURE__ */ jsxs8(Alert, { variant: "inline", children: [
2490
+ /* @__PURE__ */ jsx13(AlertCircle, { className: "size-4 text-acc-700" }),
2491
+ /* @__PURE__ */ jsxs8(AlertDescription, { className: "flex items-center justify-between", children: [
2193
2492
  /* @__PURE__ */ jsx13("span", { children: "No events available." }),
2194
- showRetryButton && /* @__PURE__ */ jsxs7(
2493
+ showRetryButton && /* @__PURE__ */ jsxs8(
2195
2494
  Button,
2196
2495
  {
2197
2496
  variant: "outline",
@@ -2199,7 +2498,7 @@ function EventSelector({
2199
2498
  onClick: handleRetry,
2200
2499
  className: "ml-2",
2201
2500
  children: [
2202
- /* @__PURE__ */ jsx13(RefreshCw, { className: "h-3 w-3 mr-1" }),
2501
+ /* @__PURE__ */ jsx13(RefreshCw, { className: "size-3 mr-1" }),
2203
2502
  "Refresh"
2204
2503
  ]
2205
2504
  }
@@ -2209,17 +2508,17 @@ function EventSelector({
2209
2508
  }
2210
2509
  return null;
2211
2510
  }
2212
- return /* @__PURE__ */ jsxs7(
2511
+ return /* @__PURE__ */ jsxs8(
2213
2512
  Select,
2214
2513
  {
2215
2514
  value: selectedEvent ? selectedEvent.event_id || selectedEvent.id : "",
2216
2515
  onValueChange: handleValueChange,
2217
2516
  className,
2218
2517
  children: [
2219
- /* @__PURE__ */ jsx13(SelectTrigger, { className: "text-left", variant: "outline", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder, children: selectedEvent && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
2220
- /* @__PURE__ */ jsx13(Calendar2, { className: "h-4 w-4 flex-shrink-0" }),
2518
+ /* @__PURE__ */ jsx13(SelectTrigger, { className: "text-left", variant: "outline", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder, children: selectedEvent && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2519
+ /* @__PURE__ */ jsx13(Calendar2, { className: "size-4 flex-shrink-0" }),
2221
2520
  /* @__PURE__ */ jsx13("span", { className: "truncate", children: selectedEvent.event_name }),
2222
- selectedEvent.event_date && /* @__PURE__ */ jsxs7("span", { className: "text-xs text-muted-foreground flex-shrink-0", children: [
2521
+ selectedEvent.event_date && /* @__PURE__ */ jsxs8("span", { className: "text-xs text-muted-foreground flex-shrink-0", children: [
2223
2522
  "(",
2224
2523
  formatEventDate(selectedEvent.event_date),
2225
2524
  ")"
@@ -2233,19 +2532,19 @@ function EventSelector({
2233
2532
  {
2234
2533
  value: event.event_id || event.id,
2235
2534
  className: "flex items-center justify-between",
2236
- children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 w-full", children: [
2237
- showNextEventIndicator && isNext && /* @__PURE__ */ jsx13(Star, { className: "h-3 w-3 text-acc-500" }),
2238
- /* @__PURE__ */ jsxs7("div", { className: "flex-1", children: [
2239
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
2535
+ children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 w-full", children: [
2536
+ showNextEventIndicator && isNext && /* @__PURE__ */ jsx13(Star, { className: "size-3 text-acc-500" }),
2537
+ /* @__PURE__ */ jsxs8("div", { className: "flex-1", children: [
2538
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2240
2539
  /* @__PURE__ */ jsx13("span", { className: isSelected ? "font-semibold" : "", children: event.event_name }),
2241
2540
  isSelected && /* @__PURE__ */ jsx13("span", { className: "text-xs bg-primary text-primary-foreground px-1 rounded", children: "Current" })
2242
2541
  ] }),
2243
- showEventDetails && event.event_date && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
2244
- /* @__PURE__ */ jsx13(Calendar2, { className: "h-3 w-3" }),
2542
+ showEventDetails && event.event_date && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
2543
+ /* @__PURE__ */ jsx13(Calendar2, { className: "size-3" }),
2245
2544
  /* @__PURE__ */ jsx13("span", { children: formatEventDate(event.event_date) }),
2246
2545
  showNextEventIndicator && isNext && /* @__PURE__ */ jsx13("span", { className: "text-acc-600 font-medium", children: "(Next)" })
2247
2546
  ] }),
2248
- showEventDetails && event.event_venue && /* @__PURE__ */ jsxs7("div", { className: "text-xs text-muted-foreground", children: [
2547
+ showEventDetails && event.event_venue && /* @__PURE__ */ jsxs8("div", { className: "text-xs text-muted-foreground", children: [
2249
2548
  "\u{1F4CD} ",
2250
2549
  event.event_venue
2251
2550
  ] })
@@ -2261,9 +2560,9 @@ function EventSelector({
2261
2560
  }
2262
2561
 
2263
2562
  // src/components/OrganisationSelector/OrganisationSelector.tsx
2264
- import { useState as useState7, useCallback as useCallback7 } from "react";
2563
+ import { useState as useState8, useCallback as useCallback8 } from "react";
2265
2564
  import { RefreshCw as RefreshCw2, AlertCircle as AlertCircle2, Building2, Shield } from "lucide-react";
2266
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
2565
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2267
2566
  function OrganisationSelector({
2268
2567
  placeholder = "Select organisation",
2269
2568
  className,
@@ -2274,8 +2573,8 @@ function OrganisationSelector({
2274
2573
  compact = false,
2275
2574
  disabled = false
2276
2575
  }) {
2277
- const [isLoading, setIsLoading] = useState7(false);
2278
- const [switchError, setSwitchError] = useState7(null);
2576
+ const [isLoading, setIsLoading] = useState8(false);
2577
+ const [switchError, setSwitchError] = useState8(null);
2279
2578
  const {
2280
2579
  organisations,
2281
2580
  selectedOrganisation,
@@ -2286,7 +2585,7 @@ function OrganisationSelector({
2286
2585
  validateOrganisationAccess,
2287
2586
  refreshOrganisations
2288
2587
  } = useOrganisations();
2289
- const handleOrganisationChange = useCallback7(async (orgId) => {
2588
+ const handleOrganisationChange = useCallback8(async (orgId) => {
2290
2589
  if (disabled || isLoading) return;
2291
2590
  setSwitchError(null);
2292
2591
  setIsLoading(true);
@@ -2314,7 +2613,7 @@ function OrganisationSelector({
2314
2613
  organisations,
2315
2614
  onOrganisationChange
2316
2615
  ]);
2317
- const handleRetry = useCallback7(async () => {
2616
+ const handleRetry = useCallback8(async () => {
2318
2617
  setIsLoading(true);
2319
2618
  setSwitchError(null);
2320
2619
  try {
@@ -2327,21 +2626,21 @@ function OrganisationSelector({
2327
2626
  }
2328
2627
  }, [refreshOrganisations]);
2329
2628
  if (orgLoading) {
2330
- return /* @__PURE__ */ jsxs8("div", { className: `flex items-center gap-2 ${className}`, children: [
2629
+ return /* @__PURE__ */ jsxs9("div", { className: `flex items-center gap-2 ${className}`, children: [
2331
2630
  /* @__PURE__ */ jsx14(LoadingSpinner, { size: "sm" }),
2332
2631
  /* @__PURE__ */ jsx14("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
2333
2632
  ] });
2334
2633
  }
2335
2634
  if (orgError) {
2336
- return /* @__PURE__ */ jsxs8("div", { className: `space-y-2 ${className}`, children: [
2337
- /* @__PURE__ */ jsxs8(Alert, { variant: "destructive", children: [
2338
- /* @__PURE__ */ jsx14(AlertCircle2, { className: "h-4 w-4" }),
2339
- /* @__PURE__ */ jsxs8(AlertDescription, { children: [
2635
+ return /* @__PURE__ */ jsxs9("div", { className: `space-y-2 ${className}`, children: [
2636
+ /* @__PURE__ */ jsxs9(Alert, { variant: "destructive", children: [
2637
+ /* @__PURE__ */ jsx14(AlertCircle2, { className: "size-4" }),
2638
+ /* @__PURE__ */ jsxs9(AlertDescription, { children: [
2340
2639
  "Failed to load organisations: ",
2341
2640
  orgError.message
2342
2641
  ] })
2343
2642
  ] }),
2344
- showRetryButton && /* @__PURE__ */ jsxs8(
2643
+ showRetryButton && /* @__PURE__ */ jsxs9(
2345
2644
  Button,
2346
2645
  {
2347
2646
  variant: "outline",
@@ -2350,7 +2649,7 @@ function OrganisationSelector({
2350
2649
  disabled: isLoading,
2351
2650
  className: "w-full",
2352
2651
  children: [
2353
- /* @__PURE__ */ jsx14(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2652
+ /* @__PURE__ */ jsx14(RefreshCw2, { className: `size-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2354
2653
  "Retry"
2355
2654
  ]
2356
2655
  }
@@ -2359,12 +2658,12 @@ function OrganisationSelector({
2359
2658
  }
2360
2659
  if (organisations.length === 0) {
2361
2660
  if (showNoOrganisationsMessage) {
2362
- return /* @__PURE__ */ jsxs8("div", { className: `space-y-2 ${className}`, children: [
2363
- /* @__PURE__ */ jsxs8(Alert, { children: [
2364
- /* @__PURE__ */ jsx14(Building2, { className: "h-4 w-4" }),
2661
+ return /* @__PURE__ */ jsxs9("div", { className: `space-y-2 ${className}`, children: [
2662
+ /* @__PURE__ */ jsxs9(Alert, { children: [
2663
+ /* @__PURE__ */ jsx14(Building2, { className: "size-4" }),
2365
2664
  /* @__PURE__ */ jsx14(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
2366
2665
  ] }),
2367
- showRetryButton && /* @__PURE__ */ jsxs8(
2666
+ showRetryButton && /* @__PURE__ */ jsxs9(
2368
2667
  Button,
2369
2668
  {
2370
2669
  variant: "outline",
@@ -2373,7 +2672,7 @@ function OrganisationSelector({
2373
2672
  disabled: isLoading,
2374
2673
  className: "w-full",
2375
2674
  children: [
2376
- /* @__PURE__ */ jsx14(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2675
+ /* @__PURE__ */ jsx14(RefreshCw2, { className: `size-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2377
2676
  "Check Again"
2378
2677
  ]
2379
2678
  }
@@ -2382,20 +2681,20 @@ function OrganisationSelector({
2382
2681
  }
2383
2682
  return null;
2384
2683
  }
2385
- const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs8(Alert, { variant: "destructive", className: "mt-2", children: [
2386
- /* @__PURE__ */ jsx14(AlertCircle2, { className: "h-4 w-4" }),
2684
+ const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs9(Alert, { variant: "destructive", className: "mt-2", children: [
2685
+ /* @__PURE__ */ jsx14(AlertCircle2, { className: "size-4" }),
2387
2686
  /* @__PURE__ */ jsx14(AlertDescription, { children: switchError })
2388
2687
  ] });
2389
- return /* @__PURE__ */ jsxs8("div", { className: `space-y-2 ${className}`, children: [
2390
- /* @__PURE__ */ jsxs8(
2688
+ return /* @__PURE__ */ jsxs9("div", { className: `space-y-2 ${className}`, children: [
2689
+ /* @__PURE__ */ jsxs9(
2391
2690
  Select,
2392
2691
  {
2393
2692
  value: selectedOrganisation?.id || "",
2394
2693
  onValueChange: handleOrganisationChange,
2395
2694
  disabled: disabled || isLoading || !selectedOrganisation,
2396
2695
  children: [
2397
- /* @__PURE__ */ jsx14(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2398
- isLoading ? /* @__PURE__ */ jsx14(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx14(Building2, { className: "h-4 w-4 text-muted-foreground" }),
2696
+ /* @__PURE__ */ jsx14(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2697
+ isLoading ? /* @__PURE__ */ jsx14(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx14(Building2, { className: "size-4 text-muted-foreground" }),
2399
2698
  /* @__PURE__ */ jsx14(SelectValue, { placeholder })
2400
2699
  ] }) }),
2401
2700
  /* @__PURE__ */ jsx14(SelectContent, { children: organisations.map((org) => {
@@ -2407,16 +2706,16 @@ function OrganisationSelector({
2407
2706
  value: org.id,
2408
2707
  disabled: !hasAccess,
2409
2708
  className: !hasAccess ? "opacity-50" : "",
2410
- children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between w-full", children: [
2411
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2412
- /* @__PURE__ */ jsx14(Building2, { className: "h-4 w-4" }),
2413
- /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
2709
+ children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between w-full", children: [
2710
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2711
+ /* @__PURE__ */ jsx14(Building2, { className: "size-4" }),
2712
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
2414
2713
  /* @__PURE__ */ jsx14("span", { className: "font-medium", children: org.display_name }),
2415
2714
  !compact && org.description && /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
2416
2715
  ] })
2417
2716
  ] }),
2418
- showRole && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1 ml-4", children: [
2419
- /* @__PURE__ */ jsx14(Shield, { className: "h-3 w-3 text-muted-foreground" }),
2717
+ showRole && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1 ml-4", children: [
2718
+ /* @__PURE__ */ jsx14(Shield, { className: "size-3 text-muted-foreground" }),
2420
2719
  /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
2421
2720
  ] })
2422
2721
  ] })
@@ -2432,13 +2731,13 @@ function OrganisationSelector({
2432
2731
  }
2433
2732
 
2434
2733
  // src/components/PasswordChange/PasswordChangeForm.tsx
2435
- import { useState as useState8 } from "react";
2436
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2734
+ import { useState as useState9 } from "react";
2735
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2437
2736
  function PasswordChangeForm({ onSubmit, className }) {
2438
- const [newPassword, setNewPassword] = useState8("");
2439
- const [confirmPassword, setConfirmPassword] = useState8("");
2440
- const [error, setError] = useState8(null);
2441
- const [isSubmitting, setIsSubmitting] = useState8(false);
2737
+ const [newPassword, setNewPassword] = useState9("");
2738
+ const [confirmPassword, setConfirmPassword] = useState9("");
2739
+ const [error, setError] = useState9(null);
2740
+ const [isSubmitting, setIsSubmitting] = useState9(false);
2442
2741
  const handleSubmit = async (e) => {
2443
2742
  e.preventDefault();
2444
2743
  setError(null);
@@ -2463,9 +2762,9 @@ function PasswordChangeForm({ onSubmit, className }) {
2463
2762
  setIsSubmitting(false);
2464
2763
  }
2465
2764
  };
2466
- return /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
2765
+ return /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
2467
2766
  error && /* @__PURE__ */ jsx15("div", { role: "alert", children: error }),
2468
- /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2767
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2469
2768
  /* @__PURE__ */ jsx15(Label, { htmlFor: "new-password", children: "New Password" }),
2470
2769
  /* @__PURE__ */ jsx15(
2471
2770
  Input,
@@ -2479,7 +2778,7 @@ function PasswordChangeForm({ onSubmit, className }) {
2479
2778
  }
2480
2779
  )
2481
2780
  ] }),
2482
- /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2781
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2483
2782
  /* @__PURE__ */ jsx15(Label, { htmlFor: "confirm-password", children: "Confirm Password" }),
2484
2783
  /* @__PURE__ */ jsx15(
2485
2784
  Input,
@@ -2506,9 +2805,9 @@ function PasswordChangeForm({ onSubmit, className }) {
2506
2805
  }
2507
2806
 
2508
2807
  // src/components/UserMenu/UserMenu.tsx
2509
- import React14, { useCallback as useCallback8, useMemo as useMemo5, useState as useState9 } from "react";
2808
+ import React14, { useCallback as useCallback9, useMemo as useMemo6, useState as useState10 } from "react";
2510
2809
  import { ChevronDown, LogOut, KeyRound } from "lucide-react";
2511
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2810
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2512
2811
  var UserMenu = React14.memo(function UserMenu2({
2513
2812
  user,
2514
2813
  onSignOut,
@@ -2516,8 +2815,8 @@ var UserMenu = React14.memo(function UserMenu2({
2516
2815
  className,
2517
2816
  showAvatar = true
2518
2817
  }) {
2519
- const [isPasswordDialogOpen, setPasswordDialogOpen] = useState9(false);
2520
- const userInfo = useMemo5(() => {
2818
+ const [isPasswordDialogOpen, setPasswordDialogOpen] = useState10(false);
2819
+ const userInfo = useMemo6(() => {
2521
2820
  if (!user) return null;
2522
2821
  return {
2523
2822
  email: user.email,
@@ -2526,15 +2825,15 @@ var UserMenu = React14.memo(function UserMenu2({
2526
2825
  initial: (user.user_metadata?.display_name || user.user_metadata?.full_name || user.email || "U").charAt(0).toUpperCase()
2527
2826
  };
2528
2827
  }, [user]);
2529
- const handleSignOut = useCallback8(async () => {
2828
+ const handleSignOut = useCallback9(async () => {
2530
2829
  if (onSignOut) await onSignOut();
2531
2830
  }, [onSignOut]);
2532
2831
  if (!user || !userInfo) {
2533
2832
  return null;
2534
2833
  }
2535
- return /* @__PURE__ */ jsxs10(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
2536
- /* @__PURE__ */ jsxs10(Select, { className, children: [
2537
- /* @__PURE__ */ jsx16(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
2834
+ return /* @__PURE__ */ jsxs11(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
2835
+ /* @__PURE__ */ jsxs11(Select, { className, children: [
2836
+ /* @__PURE__ */ jsx16(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
2538
2837
  showAvatar && /* @__PURE__ */ jsx16(
2539
2838
  Avatar,
2540
2839
  {
@@ -2545,26 +2844,26 @@ var UserMenu = React14.memo(function UserMenu2({
2545
2844
  }
2546
2845
  ),
2547
2846
  /* @__PURE__ */ jsx16("span", { children: userInfo.displayName }),
2548
- /* @__PURE__ */ jsx16(ChevronDown, { className: "h-4 w-4" })
2847
+ /* @__PURE__ */ jsx16(ChevronDown, { className: "size-4" })
2549
2848
  ] }) }),
2550
- /* @__PURE__ */ jsxs10(SelectContent, { children: [
2551
- /* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col space-y-1", children: [
2849
+ /* @__PURE__ */ jsxs11(SelectContent, { children: [
2850
+ /* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs11("div", { className: "flex flex-col space-y-1", children: [
2552
2851
  /* @__PURE__ */ jsx16("p", { className: "font-medium", children: userInfo.displayName }),
2553
2852
  /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: userInfo.email })
2554
2853
  ] }) }),
2555
2854
  /* @__PURE__ */ jsx16(SelectSeparator, {}),
2556
- /* @__PURE__ */ jsx16(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs10(SelectItem, { value: "change-password", children: [
2557
- /* @__PURE__ */ jsx16(KeyRound, { className: "mr-2 h-4 w-4" }),
2855
+ /* @__PURE__ */ jsx16(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(SelectItem, { value: "change-password", children: [
2856
+ /* @__PURE__ */ jsx16(KeyRound, { className: "mr-2 size-4" }),
2558
2857
  /* @__PURE__ */ jsx16("span", { children: "Change Password" })
2559
2858
  ] }) }),
2560
- /* @__PURE__ */ jsxs10(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
2561
- /* @__PURE__ */ jsx16(LogOut, { className: "mr-2 h-4 w-4" }),
2859
+ /* @__PURE__ */ jsxs11(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
2860
+ /* @__PURE__ */ jsx16(LogOut, { className: "mr-2 size-4" }),
2562
2861
  /* @__PURE__ */ jsx16("span", { children: "Sign out" })
2563
2862
  ] })
2564
2863
  ] })
2565
2864
  ] }),
2566
2865
  /* @__PURE__ */ jsx16(DialogOverlay, {}),
2567
- /* @__PURE__ */ jsxs10(DialogContent, { className, children: [
2866
+ /* @__PURE__ */ jsxs11(DialogContent, { className, children: [
2568
2867
  /* @__PURE__ */ jsx16(DialogHeader, { children: /* @__PURE__ */ jsx16(DialogTitle, { children: "Change Password" }) }),
2569
2868
  /* @__PURE__ */ jsx16(
2570
2869
  PasswordChangeForm,
@@ -2585,8 +2884,8 @@ var UserMenu = React14.memo(function UserMenu2({
2585
2884
  ] });
2586
2885
  });
2587
2886
  var UserMenuLoading = React14.memo(function UserMenuLoading2() {
2588
- return /* @__PURE__ */ jsxs10("div", { className: "relative inline-block text-left", children: [
2589
- /* @__PURE__ */ jsxs10(
2887
+ return /* @__PURE__ */ jsxs11("div", { className: "relative inline-block text-left", children: [
2888
+ /* @__PURE__ */ jsxs11(
2590
2889
  "button",
2591
2890
  {
2592
2891
  type: "button",
@@ -2607,7 +2906,7 @@ UserMenu.Loading = UserMenuLoading;
2607
2906
  // src/components/NavigationMenu/NavigationMenu.tsx
2608
2907
  import * as React15 from "react";
2609
2908
  import { ChevronDown as ChevronDown2 } from "lucide-react";
2610
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2909
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2611
2910
  var NavigationMenu = React15.forwardRef(({
2612
2911
  items,
2613
2912
  mode = "dropdown",
@@ -2660,7 +2959,7 @@ var NavigationMenu = React15.forwardRef(({
2660
2959
  }
2661
2960
  const userId2 = authContext.user.id;
2662
2961
  const appName = authContext.appName;
2663
- import("./api-YP7XD5L6.js").then(({ resolveAppContext }) => {
2962
+ import("./api-I6UCQ5S6.js").then(({ resolveAppContext }) => {
2664
2963
  resolveAppContext({
2665
2964
  userId: userId2,
2666
2965
  appName
@@ -3011,8 +3310,8 @@ var NavigationMenu = React15.forwardRef(({
3011
3310
  const hasChildren = item.children && item.children.length > 0;
3012
3311
  const isExpanded = expandedItems.has(item.id);
3013
3312
  const itemIsActive = isActiveItem(item);
3014
- return /* @__PURE__ */ jsx17("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs11("div", { children: [
3015
- /* @__PURE__ */ jsxs11(
3313
+ return /* @__PURE__ */ jsx17("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs12("div", { children: [
3314
+ /* @__PURE__ */ jsxs12(
3016
3315
  "button",
3017
3316
  {
3018
3317
  onClick: () => toggleExpanded(item.id),
@@ -3053,7 +3352,7 @@ var NavigationMenu = React15.forwardRef(({
3053
3352
  ) });
3054
3353
  };
3055
3354
  if (mode === "dropdown") {
3056
- return /* @__PURE__ */ jsxs11(
3355
+ return /* @__PURE__ */ jsxs12(
3057
3356
  Select,
3058
3357
  {
3059
3358
  onValueChange: handleNavigationSelect,
@@ -3102,7 +3401,7 @@ NavigationMenu.displayName = "NavigationMenu";
3102
3401
 
3103
3402
  // src/components/Header/Header.tsx
3104
3403
  import { Link } from "react-router-dom";
3105
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
3404
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
3106
3405
  function Header({
3107
3406
  logoUrl,
3108
3407
  logoAlt = "Logo",
@@ -3121,10 +3420,25 @@ function Header({
3121
3420
  onNavigate,
3122
3421
  logoHref
3123
3422
  }) {
3423
+ const OrganisationSelectorConditional = () => {
3424
+ const { organisations, isContextReady } = useOrganisations();
3425
+ if (!isContextReady || !organisations || organisations.length === 0) {
3426
+ return null;
3427
+ }
3428
+ return /* @__PURE__ */ jsx18(
3429
+ OrganisationSelector,
3430
+ {
3431
+ placeholder: "Select organisation",
3432
+ className: "w-64",
3433
+ "data-testid": "org-selector",
3434
+ compact: true
3435
+ }
3436
+ );
3437
+ };
3124
3438
  return /* @__PURE__ */ jsx18("header", { className: cn(
3125
3439
  "w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
3126
3440
  className
3127
- ), role: "banner", children: /* @__PURE__ */ jsxs12("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto flex items-center gap-4 h-full", children: [
3441
+ ), role: "banner", children: /* @__PURE__ */ jsxs13("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto flex items-center gap-4 h-full", children: [
3128
3442
  logo ? logoHref ? /* @__PURE__ */ jsx18(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: logo }) : logo : logoUrl ? logoHref ? /* @__PURE__ */ jsx18(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx18(
3129
3443
  "img",
3130
3444
  {
@@ -3144,14 +3458,14 @@ function Header({
3144
3458
  {
3145
3459
  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",
3146
3460
  alt: logoAlt || "Logo",
3147
- className: "h-8 w-8 shadow-md"
3461
+ className: "size-8 shadow-md"
3148
3462
  }
3149
3463
  ) }) : /* @__PURE__ */ jsx18(
3150
3464
  "img",
3151
3465
  {
3152
3466
  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",
3153
3467
  alt: logoAlt || "Logo",
3154
- className: "h-8 w-8 shadow-md"
3468
+ className: "size-8 shadow-md"
3155
3469
  }
3156
3470
  ),
3157
3471
  navItems && navItems.length > 0 && /* @__PURE__ */ jsx18(
@@ -3165,16 +3479,8 @@ function Header({
3165
3479
  itemsPreFiltered: true
3166
3480
  }
3167
3481
  ),
3168
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-4 ml-auto", children: [
3169
- showOrgSelector ? /* @__PURE__ */ jsx18(
3170
- OrganisationSelector,
3171
- {
3172
- placeholder: "Select organisation",
3173
- className: "w-64",
3174
- "data-testid": "org-selector",
3175
- compact: true
3176
- }
3177
- ) : null,
3482
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-4 ml-auto", children: [
3483
+ showOrgSelector ? /* @__PURE__ */ jsx18(OrganisationSelectorConditional, {}) : null,
3178
3484
  showEventSelector ? /* @__PURE__ */ jsx18(
3179
3485
  EventSelector,
3180
3486
  {
@@ -3199,7 +3505,7 @@ function Header({
3199
3505
 
3200
3506
  // src/components/Footer/Footer.tsx
3201
3507
  import React16 from "react";
3202
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
3508
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3203
3509
  var FooterComponent = ({
3204
3510
  companyName = "Solvera Solutions Pty Ltd",
3205
3511
  year = (/* @__PURE__ */ new Date()).getFullYear(),
@@ -3210,9 +3516,9 @@ var FooterComponent = ({
3210
3516
  children
3211
3517
  }) => {
3212
3518
  const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
3213
- return /* @__PURE__ */ jsx19("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs13("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
3519
+ return /* @__PURE__ */ jsx19("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs14("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
3214
3520
  logo && /* @__PURE__ */ jsx19("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
3215
- children && /* @__PURE__ */ jsx19(Fragment4, { children }),
3521
+ children && /* @__PURE__ */ jsx19(Fragment6, { children }),
3216
3522
  /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground", children: copyrightText }),
3217
3523
  links && links.length > 0 && /* @__PURE__ */ jsx19("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx19("li", { children: /* @__PURE__ */ jsx19("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
3218
3524
  ] }) });
@@ -3222,9 +3528,9 @@ var Footer = React16.memo(FooterComponent);
3222
3528
  Footer.displayName = "Footer";
3223
3529
 
3224
3530
  // src/components/PaceAppLayout/PaceAppLayout.tsx
3225
- import { useState as useState11, useEffect as useEffect8, useMemo as useMemo7 } from "react";
3531
+ import { useState as useState12, useEffect as useEffect8, useMemo as useMemo8 } from "react";
3226
3532
  import { Outlet, useNavigate, useLocation } from "react-router-dom";
3227
- import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3533
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
3228
3534
  var EMPTY_PAGE_ID_MAPPING = {};
3229
3535
  var EMPTY_ROUTE_PERMISSIONS = {};
3230
3536
  function PaceAppLayout({
@@ -3258,7 +3564,13 @@ function PaceAppLayout({
3258
3564
  onRouteStrictModeViolation
3259
3565
  }) {
3260
3566
  const { user, signOut, updatePassword, supabase, appId: contextAppId } = useUnifiedAuth();
3261
- const { selectedOrganisation } = useOrganisations();
3567
+ const {
3568
+ selectedOrganisation,
3569
+ isContextReady,
3570
+ hasValidOrganisationContext,
3571
+ ensureOrganisationContext,
3572
+ isLoading: organisationLoading
3573
+ } = useOrganisations();
3262
3574
  const navigate = useNavigate();
3263
3575
  const location = useLocation();
3264
3576
  useEventTheme();
@@ -3274,7 +3586,7 @@ function PaceAppLayout({
3274
3586
  selectedEventId: selectedEvent?.event_id || null
3275
3587
  });
3276
3588
  const resolvedAppId = contextAppId || resolvedScope?.appId;
3277
- const scope = useMemo7(() => {
3589
+ const scope = useMemo8(() => {
3278
3590
  if (resolvedScope?.organisationId) {
3279
3591
  return resolvedScope;
3280
3592
  }
@@ -3291,19 +3603,19 @@ function PaceAppLayout({
3291
3603
  appId: resolvedAppId || resolvedScope?.appId || void 0
3292
3604
  };
3293
3605
  }, [resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id, resolvedAppId]);
3294
- const defaultNavItems = useMemo7(() => [
3606
+ const defaultNavItems = useMemo8(() => [
3295
3607
  { id: "home", label: "Home", href: "/", icon: "Home" },
3296
3608
  { id: "dashboard", label: "Dashboard", href: "/dashboard", icon: "LayoutDashboard" },
3297
3609
  { id: "settings", label: "Settings", href: "/settings", icon: "Settings" },
3298
3610
  { id: "ui-showcase", label: "UI Showcase", href: "/ui-showcase", icon: "Component" },
3299
3611
  { id: "data-table-showcase", label: "DataTable Showcase", href: "/data-table-showcase", icon: "Table" }
3300
3612
  ], []);
3301
- const baseMenuItems = useMemo7(() => navItems || defaultNavItems, [navItems]);
3302
- const currentRoutePermission = useMemo7(() => {
3613
+ const baseMenuItems = useMemo8(() => navItems || defaultNavItems, [navItems]);
3614
+ const currentRoutePermission = useMemo8(() => {
3303
3615
  const currentPath = location.pathname;
3304
3616
  return routePermissions[currentPath] || defaultPermission;
3305
3617
  }, [location.pathname, routePermissions, defaultPermission]);
3306
- const currentPageId = useMemo7(() => {
3618
+ const currentPageId = useMemo8(() => {
3307
3619
  const currentPath = location.pathname;
3308
3620
  if (pageIdMapping[currentPath]) {
3309
3621
  return pageIdMapping[currentPath];
@@ -3311,15 +3623,15 @@ function PaceAppLayout({
3311
3623
  const pathSegments = currentPath.slice(1).split("/").filter(Boolean);
3312
3624
  return pathSegments[0] || "home";
3313
3625
  }, [location.pathname, pageIdMapping]);
3314
- const currentPermission = useMemo7(() => {
3626
+ const currentPermission = useMemo8(() => {
3315
3627
  if (!enforcePermissions) {
3316
3628
  return "read:page.home";
3317
3629
  }
3318
3630
  const permissionString = `${currentRoutePermission}:page.${currentPageId}`;
3319
3631
  return permissionString;
3320
3632
  }, [enforcePermissions, currentRoutePermission, currentPageId]);
3321
- const [isSuperAdminUser, setIsSuperAdminUser] = useState11(false);
3322
- const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState11(false);
3633
+ const [isSuperAdminUser, setIsSuperAdminUser] = useState12(false);
3634
+ const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState12(false);
3323
3635
  useEffect8(() => {
3324
3636
  const checkSuperAdminStatus = async () => {
3325
3637
  if (!user?.id) {
@@ -3345,8 +3657,10 @@ function PaceAppLayout({
3345
3657
  scope,
3346
3658
  currentPermission,
3347
3659
  currentPageId,
3348
- true
3660
+ true,
3349
3661
  // useCache
3662
+ appName
3663
+ // Pass appName for PORTAL/ADMIN special case
3350
3664
  );
3351
3665
  const can = isSuperAdminUser ? true : canFromHook;
3352
3666
  const hasPermission = enforcePermissions ? can : true;
@@ -3373,7 +3687,7 @@ function PaceAppLayout({
3373
3687
  onPageAccessDenied(currentPageId, currentRoutePermission);
3374
3688
  }
3375
3689
  }, [enforcePermissions, can, isCheckingPermission, isCheckingSuperAdmin, isSuperAdminUser, currentPageId, currentRoutePermission, user?.id, strictMode, auditLog, onPageAccessDenied, onStrictModeViolation]);
3376
- const [filteredMenuItems, setFilteredMenuItems] = useState11(baseMenuItems);
3690
+ const [filteredMenuItems, setFilteredMenuItems] = useState12(baseMenuItems);
3377
3691
  useEffect8(() => {
3378
3692
  let isMounted = true;
3379
3693
  const filterItems = async () => {
@@ -3400,7 +3714,7 @@ function PaceAppLayout({
3400
3714
  return;
3401
3715
  }
3402
3716
  try {
3403
- const { isSuperAdmin: isSuperAdmin2 } = await import("./api-YP7XD5L6.js");
3717
+ const { isSuperAdmin: isSuperAdmin2 } = await import("./api-I6UCQ5S6.js");
3404
3718
  const isSuper = await isSuperAdmin2(user.id);
3405
3719
  if (isSuper) {
3406
3720
  if (isMounted) {
@@ -3415,7 +3729,7 @@ function PaceAppLayout({
3415
3729
  }
3416
3730
  }
3417
3731
  try {
3418
- const { getPermissionMap } = await import("./api-YP7XD5L6.js");
3732
+ const { getPermissionMap } = await import("./api-I6UCQ5S6.js");
3419
3733
  const permissionScope = {
3420
3734
  organisationId: currentScope.organisationId,
3421
3735
  eventId: currentScope.eventId,
@@ -3471,7 +3785,7 @@ function PaceAppLayout({
3471
3785
  let hasAccess = true;
3472
3786
  if (currentRoute.pageId && currentRoute.permissions && currentRoute.permissions.length > 0) {
3473
3787
  try {
3474
- const { isPermittedCached } = await import("./api-YP7XD5L6.js");
3788
+ const { isPermittedCached } = await import("./api-I6UCQ5S6.js");
3475
3789
  const hasPagePermission = await isPermittedCached({
3476
3790
  userId: user?.id || "",
3477
3791
  scope,
@@ -3487,7 +3801,7 @@ function PaceAppLayout({
3487
3801
  }
3488
3802
  }
3489
3803
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
3490
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-643PUAIM.js");
3804
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-X5NXANVI.js");
3491
3805
  hasAccess = true;
3492
3806
  }
3493
3807
  if (!isMounted) return;
@@ -3533,14 +3847,20 @@ function PaceAppLayout({
3533
3847
  }
3534
3848
  return {};
3535
3849
  };
3850
+ if (user?.id && organisationLoading) {
3851
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3852
+ /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full size-8 border-b-2 border-sec-900 mx-auto mb-4" }),
3853
+ /* @__PURE__ */ jsx20("p", { className: "text-sec-600", children: "Loading organisation context..." })
3854
+ ] }) });
3855
+ }
3536
3856
  if (enforcePermissions && (isCheckingSuperAdmin || isCheckingPermission)) {
3537
- return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs14("div", { className: "text-center", children: [
3538
- /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-sec-900 mx-auto mb-4" }),
3857
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3858
+ /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full size-8 border-b-2 border-sec-900 mx-auto mb-4" }),
3539
3859
  /* @__PURE__ */ jsx20("p", { className: "text-sec-600", children: "Checking permissions..." })
3540
3860
  ] }) });
3541
3861
  }
3542
3862
  if (enforcePermissions && permissionError && !isSuperAdminUser) {
3543
- return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs14("div", { className: "text-center", children: [
3863
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3544
3864
  /* @__PURE__ */ jsx20("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Permission Error" }),
3545
3865
  /* @__PURE__ */ jsx20("p", { className: "text-sec-600 mb-4", children: permissionError.message }),
3546
3866
  /* @__PURE__ */ jsx20(Button, { onClick: () => navigate("/"), children: "Go Home" })
@@ -3548,15 +3868,15 @@ function PaceAppLayout({
3548
3868
  }
3549
3869
  if (enforcePermissions && hasPermission === false && !isCheckingSuperAdmin && !isSuperAdminUser) {
3550
3870
  if (enforcePagePermissions && pagePermissionFallback) {
3551
- return /* @__PURE__ */ jsx20(Fragment5, { children: pagePermissionFallback });
3871
+ return /* @__PURE__ */ jsx20(Fragment7, { children: pagePermissionFallback });
3552
3872
  }
3553
3873
  if (permissionFallback) {
3554
- return /* @__PURE__ */ jsx20(Fragment5, { children: permissionFallback });
3874
+ return /* @__PURE__ */ jsx20(Fragment7, { children: permissionFallback });
3555
3875
  }
3556
- return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs14("div", { className: "text-center", children: [
3876
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3557
3877
  /* @__PURE__ */ jsx20("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Access Denied" }),
3558
3878
  /* @__PURE__ */ jsx20("p", { className: "text-sec-600 mb-4", children: "You don't have permission to access this page." }),
3559
- /* @__PURE__ */ jsxs14("div", { className: "flex gap-2 justify-center", children: [
3879
+ /* @__PURE__ */ jsxs15("div", { className: "flex gap-2 justify-center", children: [
3560
3880
  /* @__PURE__ */ jsx20(Button, { onClick: () => navigate("/"), children: "Go Home" }),
3561
3881
  /* @__PURE__ */ jsx20(
3562
3882
  Button,
@@ -3572,7 +3892,7 @@ function PaceAppLayout({
3572
3892
  ] })
3573
3893
  ] }) });
3574
3894
  }
3575
- return /* @__PURE__ */ jsxs14(Fragment5, { children: [
3895
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
3576
3896
  /* @__PURE__ */ jsx20(
3577
3897
  Header,
3578
3898
  {
@@ -3604,9 +3924,9 @@ function PaceAppLayout({
3604
3924
  }
3605
3925
 
3606
3926
  // src/components/PaceLoginPage/PaceLoginPage.tsx
3607
- import { useEffect as useEffect9, useState as useState12, useContext as useContext2 } from "react";
3927
+ import { useEffect as useEffect9, useState as useState13, useContext as useContext2 } from "react";
3608
3928
  import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
3609
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
3929
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
3610
3930
  var PaceLoginPage = ({
3611
3931
  appName = "Pace",
3612
3932
  onSuccessRedirectPath = "/",
@@ -3615,9 +3935,9 @@ var PaceLoginPage = ({
3615
3935
  const { signIn, isAuthenticated, isLoading, authError, user, supabase } = useUnifiedAuth();
3616
3936
  const navigate = useNavigate2();
3617
3937
  const location = useLocation2();
3618
- const [isSigningIn, setIsSigningIn] = useState12(false);
3619
- const [accessError, setAccessError] = useState12(null);
3620
- const [isCheckingAccess, setIsCheckingAccess] = useState12(false);
3938
+ const [isSigningIn, setIsSigningIn] = useState13(false);
3939
+ const [accessError, setAccessError] = useState13(null);
3940
+ const [isCheckingAccess, setIsCheckingAccess] = useState13(false);
3621
3941
  const eventServiceContext = useContext2(EventServiceContext);
3622
3942
  const eventService = eventServiceContext?.eventService || null;
3623
3943
  useEffect9(() => {
@@ -3676,8 +3996,9 @@ var PaceLoginPage = ({
3676
3996
  setIsCheckingAccess(false);
3677
3997
  return;
3678
3998
  }
3679
- const { data: orgData } = await supabase.from("rbac_organisation_roles").select("organisation_id").eq("user_id", userId).eq("status", "active").is("revoked_at", null).limit(1).single();
3680
- if (!orgData) {
3999
+ const { data: orgRow } = await supabase.from("rbac_organisation_roles").select("organisation_id").eq("user_id", userId).eq("status", "active").is("revoked_at", null).limit(1).maybeSingle();
4000
+ const organisationId = orgRow?.organisation_id;
4001
+ if (!organisationId) {
3681
4002
  logger.debug("PaceLoginPage", "User has no organisation access");
3682
4003
  setAccessError(`You do not have permission to access ${appName}. You are not assigned to any organisation. Please contact your administrator.`);
3683
4004
  setIsCheckingAccess(false);
@@ -3689,7 +4010,7 @@ var PaceLoginPage = ({
3689
4010
  p_user_id: userId,
3690
4011
  p_permission: `read:page.${page.page_name}`,
3691
4012
  // Permission format: operation:resource
3692
- p_organisation_id: orgData.organisation_id,
4013
+ p_organisation_id: organisationId,
3693
4014
  p_event_id: null,
3694
4015
  p_app_id: appData.id,
3695
4016
  p_page_id: page.page_name
@@ -3737,7 +4058,7 @@ var PaceLoginPage = ({
3737
4058
  setIsSigningIn(false);
3738
4059
  }
3739
4060
  };
3740
- return /* @__PURE__ */ jsxs15("main", { className: "min-h-screen grid mx-auto w-fit content-center justify-items-center gap-y-8", "aria-label": `${appName} Login Page`, children: [
4061
+ return /* @__PURE__ */ jsxs16("main", { className: "min-h-screen grid mx-auto w-fit content-center justify-items-center gap-y-8", "aria-label": `${appName} Login Page`, children: [
3741
4062
  /* @__PURE__ */ jsx21(
3742
4063
  "img",
3743
4064
  {
@@ -3768,12 +4089,12 @@ var PaceLoginPage = ({
3768
4089
  };
3769
4090
 
3770
4091
  // src/components/SessionRestorationLoader/SessionRestorationLoader.tsx
3771
- import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
4092
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
3772
4093
  var SessionRestorationLoader = ({
3773
4094
  message = "Restoring session...",
3774
4095
  className
3775
4096
  }) => {
3776
- return /* @__PURE__ */ jsxs16(
4097
+ return /* @__PURE__ */ jsxs17(
3777
4098
  "div",
3778
4099
  {
3779
4100
  className: cn(
@@ -3792,9 +4113,9 @@ var SessionRestorationLoader = ({
3792
4113
  };
3793
4114
 
3794
4115
  // src/components/ProtectedRoute/ProtectedRoute.tsx
3795
- import { useMemo as useMemo8, useEffect as useEffect10, useRef as useRef7, useState as useState13 } from "react";
4116
+ import { useMemo as useMemo9, useEffect as useEffect10, useRef as useRef8, useState as useState14 } from "react";
3796
4117
  import { Navigate, Outlet as Outlet2 } from "react-router-dom";
3797
- import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
4118
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
3798
4119
  function ProtectedRoute({
3799
4120
  requireEvent = false,
3800
4121
  allowSuperAdminBypass = false,
@@ -3809,9 +4130,9 @@ function ProtectedRoute({
3809
4130
  const eventLoading = requireEvent ? eventsContext.isLoading || false : false;
3810
4131
  const sessionRestoration = useSessionRestoration();
3811
4132
  usePreventTabReload({ enabled: true, gracePeriodMs: 2e3 });
3812
- const wasAuthenticatedRef = useRef7(false);
3813
- const [shouldRedirect, setShouldRedirect] = useState13(false);
3814
- const tabJustBecameVisibleRef = useRef7(false);
4133
+ const wasAuthenticatedRef = useRef8(false);
4134
+ const [shouldRedirect, setShouldRedirect] = useState14(false);
4135
+ const tabJustBecameVisibleRef = useRef8(false);
3815
4136
  useEffect10(() => {
3816
4137
  if (isAuthenticated) {
3817
4138
  wasAuthenticatedRef.current = true;
@@ -3869,7 +4190,7 @@ function ProtectedRoute({
3869
4190
  tabJustBecameVisibleRef.current = false;
3870
4191
  }
3871
4192
  }, [isAuthenticated]);
3872
- const isRestoringSession = useMemo8(() => {
4193
+ const isRestoringSession = useMemo9(() => {
3873
4194
  return sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError && !sessionRestoration.hasTimedOut;
3874
4195
  }, [
3875
4196
  sessionRestoration.isRestoring,
@@ -3913,7 +4234,7 @@ function ProtectedRoute({
3913
4234
  return /* @__PURE__ */ jsx23(Outlet2, {});
3914
4235
  }
3915
4236
  if (!events || events.length === 0) {
3916
- return noEventsFallback || /* @__PURE__ */ jsx23("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", padding: "2rem" }, children: /* @__PURE__ */ jsxs17(Alert, { variant: "destructive", className: "max-w-md", children: [
4237
+ return noEventsFallback || /* @__PURE__ */ jsx23("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", padding: "2rem" }, children: /* @__PURE__ */ jsxs18(Alert, { variant: "destructive", className: "max-w-md", children: [
3917
4238
  /* @__PURE__ */ jsx23(AlertTitle, { children: "No Events Available" }),
3918
4239
  /* @__PURE__ */ jsx23(AlertDescription, { children: "You don't have access to any events. Please contact your administrator if you believe this is an error." })
3919
4240
  ] }) });
@@ -3926,13 +4247,14 @@ function ProtectedRoute({
3926
4247
  }
3927
4248
 
3928
4249
  // src/components/FileUpload/FileUpload.tsx
3929
- import { useState as useState14, useCallback as useCallback10, useRef as useRef8, useEffect as useEffect11, useMemo as useMemo9 } from "react";
3930
- import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
4250
+ import { useState as useState15, useCallback as useCallback11, useRef as useRef9, useEffect as useEffect11, useMemo as useMemo10 } from "react";
4251
+ import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
3931
4252
  function FileUpload({
3932
4253
  supabase,
3933
4254
  table_name,
3934
4255
  record_id,
3935
4256
  organisation_id,
4257
+ userId,
3936
4258
  app_id,
3937
4259
  category,
3938
4260
  folder,
@@ -3952,12 +4274,12 @@ function FileUpload({
3952
4274
  onProgress,
3953
4275
  children
3954
4276
  }) {
3955
- const [isDragging, setIsDragging] = useState14(false);
3956
- const [uploadStates, setUploadStates] = useState14(/* @__PURE__ */ new Map());
3957
- const [resolvedAppId, setResolvedAppId] = useState14(app_id || null);
3958
- const [isResolvingAppId, setIsResolvingAppId] = useState14(!app_id);
3959
- const [appIdError, setAppIdError] = useState14(null);
3960
- const fileInputRef = useRef8(null);
4277
+ const [isDragging, setIsDragging] = useState15(false);
4278
+ const [uploadStates, setUploadStates] = useState15(/* @__PURE__ */ new Map());
4279
+ const [resolvedAppId, setResolvedAppId] = useState15(app_id || null);
4280
+ const [isResolvingAppId, setIsResolvingAppId] = useState15(!app_id);
4281
+ const [appIdError, setAppIdError] = useState15(null);
4282
+ const fileInputRef = useRef9(null);
3961
4283
  const { uploadFile, isLoading, error } = useFileReference(supabase);
3962
4284
  useEffect11(() => {
3963
4285
  if (app_id) {
@@ -3994,15 +4316,15 @@ function FileUpload({
3994
4316
  };
3995
4317
  resolveAppId();
3996
4318
  }, [app_id, supabase]);
3997
- const isUploading = useMemo9(() => {
4319
+ const isUploading = useMemo10(() => {
3998
4320
  return uploadStates.size > 0 && Array.from(uploadStates.values()).some(
3999
4321
  (state) => state.progress.status === "uploading" || state.progress.status === "processing"
4000
4322
  );
4001
4323
  }, [uploadStates]);
4002
- const isDisabled = useMemo9(() => {
4324
+ const isDisabled = useMemo10(() => {
4003
4325
  return disabled || isUploading || isResolvingAppId || !resolvedAppId;
4004
4326
  }, [disabled, isUploading, isResolvingAppId, resolvedAppId]);
4005
- const generatePreview = useCallback10((file) => {
4327
+ const generatePreview = useCallback11((file) => {
4006
4328
  return new Promise((resolve) => {
4007
4329
  if (!file.type.startsWith("image/")) {
4008
4330
  resolve(null);
@@ -4016,7 +4338,7 @@ function FileUpload({
4016
4338
  reader.readAsDataURL(file);
4017
4339
  });
4018
4340
  }, []);
4019
- const validateFile = useCallback10((file) => {
4341
+ const validateFile = useCallback11((file) => {
4020
4342
  if (file.size > maxSize) {
4021
4343
  return `File "${file.name}" exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`;
4022
4344
  }
@@ -4040,7 +4362,7 @@ function FileUpload({
4040
4362
  }
4041
4363
  return null;
4042
4364
  }, [accept, maxSize]);
4043
- const handleFileSelect = useCallback10(async (files) => {
4365
+ const handleFileSelect = useCallback11(async (files) => {
4044
4366
  if (!files || files.length === 0) return;
4045
4367
  const fileArray = Array.from(files);
4046
4368
  const validationErrors = [];
@@ -4122,7 +4444,9 @@ function FileUpload({
4122
4444
  const result = await uploadFile({
4123
4445
  table_name,
4124
4446
  record_id,
4125
- organisation_id,
4447
+ organisation_id: organisation_id || null,
4448
+ userId,
4449
+ // Pass userId prop directly - it's required for user-scoped files when organisation_id is null
4126
4450
  app_id: resolvedAppId ? assertAppId(resolvedAppId) : assertAppId(""),
4127
4451
  category,
4128
4452
  folder,
@@ -4215,19 +4539,19 @@ function FileUpload({
4215
4539
  }
4216
4540
  }
4217
4541
  }, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
4218
- const handleDragOver = useCallback10((e) => {
4542
+ const handleDragOver = useCallback11((e) => {
4219
4543
  e.preventDefault();
4220
4544
  e.stopPropagation();
4221
4545
  if (!isDisabled) {
4222
4546
  setIsDragging(true);
4223
4547
  }
4224
4548
  }, [isDisabled]);
4225
- const handleDragLeave = useCallback10((e) => {
4549
+ const handleDragLeave = useCallback11((e) => {
4226
4550
  e.preventDefault();
4227
4551
  e.stopPropagation();
4228
4552
  setIsDragging(false);
4229
4553
  }, []);
4230
- const handleDrop = useCallback10((e) => {
4554
+ const handleDrop = useCallback11((e) => {
4231
4555
  e.preventDefault();
4232
4556
  e.stopPropagation();
4233
4557
  setIsDragging(false);
@@ -4235,13 +4559,13 @@ function FileUpload({
4235
4559
  const files = e.dataTransfer.files;
4236
4560
  handleFileSelect(files);
4237
4561
  }, [isDisabled, handleFileSelect]);
4238
- const handleFileInputChange = useCallback10((e) => {
4562
+ const handleFileInputChange = useCallback11((e) => {
4239
4563
  handleFileSelect(e.target.files);
4240
4564
  if (e.target) {
4241
4565
  e.target.value = "";
4242
4566
  }
4243
4567
  }, [handleFileSelect]);
4244
- const handleClick = useCallback10(() => {
4568
+ const handleClick = useCallback11(() => {
4245
4569
  if (!isDisabled && fileInputRef.current) {
4246
4570
  fileInputRef.current.click();
4247
4571
  }
@@ -4255,8 +4579,8 @@ function FileUpload({
4255
4579
  };
4256
4580
  const dragClasses = isDragging ? "border-main-500 bg-main-50" : "border-sec-300 hover:border-sec-400";
4257
4581
  const disabledClasses = isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:bg-sec-50";
4258
- return /* @__PURE__ */ jsxs18("div", { className: `space-y-4 ${className}`, children: [
4259
- /* @__PURE__ */ jsxs18(
4582
+ return /* @__PURE__ */ jsxs19("div", { className: `space-y-4 ${className}`, children: [
4583
+ /* @__PURE__ */ jsxs19(
4260
4584
  "div",
4261
4585
  {
4262
4586
  role: "button",
@@ -4275,7 +4599,7 @@ function FileUpload({
4275
4599
  }
4276
4600
  } : void 0,
4277
4601
  children: [
4278
- children || /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4602
+ children || /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4279
4603
  /* @__PURE__ */ jsx24(
4280
4604
  "input",
4281
4605
  {
@@ -4289,12 +4613,12 @@ function FileUpload({
4289
4613
  "data-testid": "file-input"
4290
4614
  }
4291
4615
  ),
4292
- /* @__PURE__ */ jsx24("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs18(Fragment6, { children: [
4616
+ /* @__PURE__ */ jsx24("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs19(Fragment8, { children: [
4293
4617
  /* @__PURE__ */ jsx24("span", { className: "font-medium", children: "Click to upload" }),
4294
4618
  " ",
4295
4619
  "or drag and drop"
4296
4620
  ] }) }),
4297
- /* @__PURE__ */ jsxs18("div", { className: "text-sm text-sec-500", children: [
4621
+ /* @__PURE__ */ jsxs19("div", { className: "text-sm text-sec-500", children: [
4298
4622
  !isResolvingAppId && accept !== "*/*" && `Accepted formats: ${accept}`,
4299
4623
  !isResolvingAppId && maxSize && ` \u2022 Max size: ${Math.round(maxSize / 1024 / 1024)}MB`,
4300
4624
  !isResolvingAppId && multiple && " \u2022 Multiple files allowed"
@@ -4307,7 +4631,7 @@ function FileUpload({
4307
4631
  role: "status",
4308
4632
  "aria-live": "polite",
4309
4633
  "aria-label": "Uploading file",
4310
- children: /* @__PURE__ */ jsx24("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500", "aria-hidden": "true" })
4634
+ children: /* @__PURE__ */ jsx24("div", { className: "animate-spin rounded-full size-8 border-b-2 border-main-500", "aria-hidden": "true" })
4311
4635
  }
4312
4636
  )
4313
4637
  ]
@@ -4318,7 +4642,7 @@ function FileUpload({
4318
4642
  const isError = progress.status === "error";
4319
4643
  const isCompleted = progress.status === "completed";
4320
4644
  const isUploading2 = progress.status === "uploading" || progress.status === "processing";
4321
- return /* @__PURE__ */ jsxs18(
4645
+ return /* @__PURE__ */ jsxs19(
4322
4646
  "div",
4323
4647
  {
4324
4648
  className: `flex items-center space-x-3 p-3 rounded-lg border ${isError ? "bg-acc-50 border-acc-200" : isCompleted ? "bg-success-50 border-success-200" : "bg-sec-50 border-sec-200"}`,
@@ -4331,14 +4655,14 @@ function FileUpload({
4331
4655
  className: "w-12 h-12 object-cover rounded"
4332
4656
  }
4333
4657
  ) : /* @__PURE__ */ jsx24("div", { className: "w-12 h-12 flex items-center justify-center bg-sec-200 rounded", children: /* @__PURE__ */ jsx24("span", { className: "text-2xl", children: "\u{1F4C4}" }) }) }),
4334
- /* @__PURE__ */ jsxs18("div", { className: "flex-1 min-w-0", children: [
4658
+ /* @__PURE__ */ jsxs19("div", { className: "flex-1 min-w-0", children: [
4335
4659
  /* @__PURE__ */ jsx24("div", { className: "font-medium text-sec-900 truncate", children: file.name }),
4336
- /* @__PURE__ */ jsxs18("div", { className: "text-sm text-sec-500", children: [
4660
+ /* @__PURE__ */ jsxs19("div", { className: "text-sm text-sec-500", children: [
4337
4661
  formatFileSize(file.size),
4338
4662
  isCompleted && result && " \u2022 Uploaded",
4339
4663
  isError && progress.error && ` \u2022 ${progress.error}`
4340
4664
  ] }),
4341
- showProgress && (isUploading2 || isError) && /* @__PURE__ */ jsxs18("div", { className: "mt-2", children: [
4665
+ showProgress && (isUploading2 || isError) && /* @__PURE__ */ jsxs19("div", { className: "mt-2", children: [
4342
4666
  /* @__PURE__ */ jsx24("div", { className: "w-full bg-sec-200 rounded-full h-2", children: /* @__PURE__ */ jsx24(
4343
4667
  "div",
4344
4668
  {
@@ -4346,7 +4670,7 @@ function FileUpload({
4346
4670
  style: { width: `${progress.percentage}%` }
4347
4671
  }
4348
4672
  ) }),
4349
- isUploading2 && /* @__PURE__ */ jsxs18("div", { className: "text-xs text-sec-500 mt-1", children: [
4673
+ isUploading2 && /* @__PURE__ */ jsxs19("div", { className: "text-xs text-sec-500 mt-1", children: [
4350
4674
  progress.percentage,
4351
4675
  "% \u2022 ",
4352
4676
  formatFileSize(progress.loaded),
@@ -4355,13 +4679,13 @@ function FileUpload({
4355
4679
  ] })
4356
4680
  ] })
4357
4681
  ] }),
4358
- /* @__PURE__ */ jsxs18("div", { className: "flex-shrink-0", children: [
4682
+ /* @__PURE__ */ jsxs19("div", { className: "flex-shrink-0", children: [
4359
4683
  isCompleted && /* @__PURE__ */ jsx24("span", { className: "text-success-500 text-xl", children: "\u2713" }),
4360
4684
  isError && /* @__PURE__ */ jsx24("span", { className: "text-acc-500 text-xl", children: "\u2715" }),
4361
4685
  isUploading2 && /* @__PURE__ */ jsx24(
4362
4686
  "div",
4363
4687
  {
4364
- className: "animate-spin rounded-full h-5 w-5 border-b-2 border-main-500",
4688
+ className: "animate-spin rounded-full size-5 border-b-2 border-main-500",
4365
4689
  role: "status",
4366
4690
  "aria-label": "Uploading",
4367
4691
  "aria-hidden": "true"
@@ -4473,7 +4797,7 @@ var TableCaption = React21.forwardRef(({ className, ...props }, ref) => /* @__PU
4473
4797
  TableCaption.displayName = "TableCaption";
4474
4798
 
4475
4799
  // src/components/PublicLayout/PublicPageLayout.tsx
4476
- import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
4800
+ import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
4477
4801
  function PublicPageHeader({
4478
4802
  event,
4479
4803
  eventCode,
@@ -4486,7 +4810,7 @@ function PublicPageHeader({
4486
4810
  customEventLogo
4487
4811
  }) {
4488
4812
  const { appName } = useAppConfig();
4489
- return /* @__PURE__ */ jsxs19("header", { className: cn(
4813
+ return /* @__PURE__ */ jsxs20("header", { className: cn(
4490
4814
  "w-full px-[max(0rem,calc((100vw-var(--app-width))/2-0.5rem))] grid grid-cols-[auto_1fr_auto] place-items-center gap-2",
4491
4815
  className
4492
4816
  ), children: [
@@ -4498,9 +4822,9 @@ function PublicPageHeader({
4498
4822
  alt: appName
4499
4823
  }
4500
4824
  ),
4501
- event && /* @__PURE__ */ jsxs19(Fragment7, { children: [
4825
+ event && /* @__PURE__ */ jsxs20(Fragment9, { children: [
4502
4826
  /* @__PURE__ */ jsx26("h1", { children: event.event_name }),
4503
- showEventLogo && event && /* @__PURE__ */ jsx26(Fragment7, { children: customEventLogo || /* @__PURE__ */ jsx26(
4827
+ showEventLogo && event && /* @__PURE__ */ jsx26(Fragment9, { children: customEventLogo || /* @__PURE__ */ jsx26(
4504
4828
  FileDisplay,
4505
4829
  {
4506
4830
  table_name: "event",
@@ -4519,11 +4843,11 @@ function PublicPageHeader({
4519
4843
  ) }),
4520
4844
  event.event_venue && /* @__PURE__ */ jsx26("h4", { children: event.event_venue })
4521
4845
  ] }),
4522
- title && /* @__PURE__ */ jsxs19(Fragment7, { children: [
4846
+ title && /* @__PURE__ */ jsxs20(Fragment9, { children: [
4523
4847
  /* @__PURE__ */ jsx26("h1", { children: title }),
4524
4848
  description && /* @__PURE__ */ jsx26("p", { className: "text-lg text-sec-600 max-w-3xl mx-auto", children: description })
4525
4849
  ] }),
4526
- children && /* @__PURE__ */ jsx26(Fragment7, { children })
4850
+ children && /* @__PURE__ */ jsx26(Fragment9, { children })
4527
4851
  ] });
4528
4852
  }
4529
4853
  function PublicPageFooter({
@@ -4537,9 +4861,9 @@ function PublicPageFooter({
4537
4861
  children
4538
4862
  }) {
4539
4863
  const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
4540
- return /* @__PURE__ */ jsx26("footer", { className: cn("mt-8 py-6 flex justify-center", className), children: /* @__PURE__ */ jsxs19("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
4864
+ return /* @__PURE__ */ jsx26("footer", { className: cn("mt-8 py-6 flex justify-center", className), children: /* @__PURE__ */ jsxs20("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
4541
4865
  logo && /* @__PURE__ */ jsx26("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
4542
- children && /* @__PURE__ */ jsx26(Fragment7, { children }),
4866
+ children && /* @__PURE__ */ jsx26(Fragment9, { children }),
4543
4867
  /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: copyrightText }),
4544
4868
  links && links.length > 0 && /* @__PURE__ */ jsx26("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
4545
4869
  ] }) });
@@ -4567,7 +4891,7 @@ function PublicPageLayout({
4567
4891
  if (LoadingFallback) {
4568
4892
  return /* @__PURE__ */ jsx26(LoadingFallback, {});
4569
4893
  }
4570
- return /* @__PURE__ */ jsx26("div", { className: "min-h-screen bg-background flex items-center justify-center", children: /* @__PURE__ */ jsxs19("div", { className: "max-w-md mx-auto text-center px-4", children: [
4894
+ return /* @__PURE__ */ jsx26("div", { className: "min-h-screen bg-background flex items-center justify-center", children: /* @__PURE__ */ jsxs20("div", { className: "max-w-md mx-auto text-center px-4", children: [
4571
4895
  /* @__PURE__ */ jsx26(LoadingSpinner, { size: "lg", className: "mx-auto mb-4" }),
4572
4896
  loadingMessage && /* @__PURE__ */ jsx26("p", { className: "text-sec-600", children: loadingMessage })
4573
4897
  ] }) });
@@ -4576,9 +4900,9 @@ function PublicPageLayout({
4576
4900
  if (ErrorFallback) {
4577
4901
  return /* @__PURE__ */ jsx26(ErrorFallback, { error, retry: handleRefetch });
4578
4902
  }
4579
- return /* @__PURE__ */ jsxs19("main", { className: "flex flex-col items-center justify-center px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: [
4903
+ return /* @__PURE__ */ jsxs20("main", { className: "flex flex-col items-center justify-center px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: [
4580
4904
  /* @__PURE__ */ jsx26("h1", { children: "Event Not Found" }),
4581
- /* @__PURE__ */ jsxs19("p", { children: [
4905
+ /* @__PURE__ */ jsxs20("p", { children: [
4582
4906
  'The event code "',
4583
4907
  eventCode,
4584
4908
  '" is invalid or the event is not available for public viewing.'
@@ -4587,13 +4911,13 @@ function PublicPageLayout({
4587
4911
  ] });
4588
4912
  }
4589
4913
  if (!event && showValidationErrors) {
4590
- return /* @__PURE__ */ jsxs19("main", { className: "flex flex-col items-center justify-center px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: [
4914
+ return /* @__PURE__ */ jsxs20("main", { className: "flex flex-col items-center justify-center px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: [
4591
4915
  /* @__PURE__ */ jsx26("h1", { children: "Event Not Available" }),
4592
4916
  /* @__PURE__ */ jsx26("p", { children: "This event is not available for public viewing." }),
4593
4917
  handleRefetch && /* @__PURE__ */ jsx26(Button, { onClick: handleRefetch, children: "Try Again" })
4594
4918
  ] });
4595
4919
  }
4596
- return /* @__PURE__ */ jsx26(ErrorBoundary, { componentName: "PublicPageLayout", children: /* @__PURE__ */ jsxs19(Fragment7, { children: [
4920
+ return /* @__PURE__ */ jsx26(ErrorBoundary, { componentName: "PublicPageLayout", children: /* @__PURE__ */ jsxs20(Fragment9, { children: [
4597
4921
  customHeader || /* @__PURE__ */ jsx26(
4598
4922
  PublicPageHeader,
4599
4923
  {
@@ -4658,4 +4982,4 @@ export {
4658
4982
  PublicPageFooter,
4659
4983
  PublicPageLayout
4660
4984
  };
4661
- //# sourceMappingURL=chunk-YGPFYGA6.js.map
4985
+ //# sourceMappingURL=chunk-VVBAW5A5.js.map