@jmruthers/pace-core 0.5.189 → 0.5.191

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 (438) 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-IVYljGJ6.d.ts → DataTable-Be6dH_dR.d.ts} +1 -1
  4. package/dist/{DataTable-GUFUNZ3N.js → DataTable-WKRZD47S.js} +8 -8
  5. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-ULXC_u6U.d.ts} +84 -25
  6. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  7. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-FTSG5XH7.js} +4 -2
  8. package/dist/{api-YP7XD5L6.js → api-IHKALJZD.js} +4 -2
  9. package/dist/{chunk-VGZZXKBR.js → chunk-6LTQQAT6.js} +351 -157
  10. package/dist/chunk-6LTQQAT6.js.map +1 -0
  11. package/dist/{chunk-MX64ZF6I.js → chunk-6TQDD426.js} +15 -15
  12. package/dist/chunk-6TQDD426.js.map +1 -0
  13. package/dist/{chunk-YHCN776L.js → chunk-G37KK66H.js} +2 -75
  14. package/dist/chunk-G37KK66H.js.map +1 -0
  15. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  16. package/dist/chunk-HW3OVDUF.js.map +1 -0
  17. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  18. package/dist/chunk-I7PSE6JW.js.map +1 -0
  19. package/dist/{chunk-IM4QE42D.js → chunk-LOMZXPSN.js} +141 -326
  20. package/dist/chunk-LOMZXPSN.js.map +1 -0
  21. package/dist/chunk-OETXORNB.js +614 -0
  22. package/dist/chunk-OETXORNB.js.map +1 -0
  23. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  24. package/dist/{chunk-HEHYGYOX.js → chunk-ROXMHMY2.js} +403 -46
  25. package/dist/chunk-ROXMHMY2.js.map +1 -0
  26. package/dist/{chunk-2UUZZJFT.js → chunk-ULHIJK66.js} +228 -177
  27. package/dist/{chunk-2UUZZJFT.js.map → chunk-ULHIJK66.js.map} +1 -1
  28. package/dist/{chunk-YGPFYGA6.js → chunk-VKB2CO4Z.js} +838 -503
  29. package/dist/chunk-VKB2CO4Z.js.map +1 -0
  30. package/dist/{chunk-3GOZZZYH.js → chunk-VRGWKHDB.js} +238 -301
  31. package/dist/chunk-VRGWKHDB.js.map +1 -0
  32. package/dist/{chunk-UCQSRW7Z.js → chunk-XNYQOL3Z.js} +431 -384
  33. package/dist/chunk-XNYQOL3Z.js.map +1 -0
  34. package/dist/{chunk-DDM4CCYT.js → chunk-XYXSXPUK.js} +79 -59
  35. package/dist/chunk-XYXSXPUK.js.map +1 -0
  36. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  37. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  38. package/dist/components.d.ts +5 -6
  39. package/dist/components.js +19 -19
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database.generated-DI89OQeI.d.ts → database.generated-CzIvgcPu.d.ts} +165 -201
  42. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  43. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  44. package/dist/hooks.d.ts +20 -15
  45. package/dist/hooks.js +14 -8
  46. package/dist/hooks.js.map +1 -1
  47. package/dist/index.d.ts +17 -15
  48. package/dist/index.js +86 -81
  49. package/dist/index.js.map +1 -1
  50. package/dist/providers.d.ts +3 -3
  51. package/dist/providers.js +3 -1
  52. package/dist/rbac/index.d.ts +77 -13
  53. package/dist/rbac/index.js +12 -9
  54. package/dist/{types-Bwgl--Xo.d.ts → types-CEpcvwwF.d.ts} +1 -1
  55. package/dist/types.d.ts +3 -3
  56. package/dist/types.js +1 -1
  57. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-TZe0gy-4.d.ts} +17 -10
  58. package/dist/utils.d.ts +8 -8
  59. package/dist/utils.js +16 -16
  60. package/docs/README.md +2 -2
  61. package/docs/api/classes/ColumnFactory.md +1 -1
  62. package/docs/api/classes/ErrorBoundary.md +1 -1
  63. package/docs/api/classes/InvalidScopeError.md +2 -2
  64. package/docs/api/classes/Logger.md +1 -1
  65. package/docs/api/classes/MissingUserContextError.md +2 -2
  66. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  67. package/docs/api/classes/PermissionDeniedError.md +1 -1
  68. package/docs/api/classes/RBACAuditManager.md +2 -2
  69. package/docs/api/classes/RBACCache.md +1 -1
  70. package/docs/api/classes/RBACEngine.md +5 -5
  71. package/docs/api/classes/RBACError.md +1 -1
  72. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  73. package/docs/api/classes/SecureSupabaseClient.md +25 -20
  74. package/docs/api/classes/StorageUtils.md +7 -4
  75. package/docs/api/enums/FileCategory.md +1 -1
  76. package/docs/api/enums/LogLevel.md +1 -1
  77. package/docs/api/enums/RBACErrorCode.md +1 -1
  78. package/docs/api/enums/RPCFunction.md +1 -1
  79. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  80. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +1 -1
  82. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  83. package/docs/api/interfaces/AvatarProps.md +1 -1
  84. package/docs/api/interfaces/BadgeProps.md +1 -1
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CalendarProps.md +20 -6
  87. package/docs/api/interfaces/CardProps.md +1 -1
  88. package/docs/api/interfaces/ColorPalette.md +1 -1
  89. package/docs/api/interfaces/ColorShade.md +1 -1
  90. package/docs/api/interfaces/ComplianceResult.md +1 -1
  91. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  92. package/docs/api/interfaces/DataRecord.md +1 -1
  93. package/docs/api/interfaces/DataTableAction.md +1 -1
  94. package/docs/api/interfaces/DataTableColumn.md +1 -1
  95. package/docs/api/interfaces/DataTableProps.md +1 -1
  96. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  97. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  98. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  99. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  100. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  101. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  102. package/docs/api/interfaces/ExportColumn.md +1 -1
  103. package/docs/api/interfaces/ExportOptions.md +1 -1
  104. package/docs/api/interfaces/FileDisplayProps.md +62 -16
  105. package/docs/api/interfaces/FileMetadata.md +1 -1
  106. package/docs/api/interfaces/FileReference.md +2 -2
  107. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  108. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  109. package/docs/api/interfaces/FileUploadProps.md +30 -19
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/FormFieldProps.md +1 -1
  112. package/docs/api/interfaces/FormProps.md +1 -1
  113. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  114. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  115. package/docs/api/interfaces/InputProps.md +1 -1
  116. package/docs/api/interfaces/LabelProps.md +1 -1
  117. package/docs/api/interfaces/LoggerConfig.md +1 -1
  118. package/docs/api/interfaces/LoginFormProps.md +1 -1
  119. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  120. package/docs/api/interfaces/NavigationContextType.md +9 -9
  121. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  122. package/docs/api/interfaces/NavigationItem.md +1 -1
  123. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  124. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  125. package/docs/api/interfaces/Organisation.md +1 -1
  126. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  127. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  128. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  129. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  130. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  131. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  132. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  133. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  134. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  135. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  136. package/docs/api/interfaces/PaletteData.md +1 -1
  137. package/docs/api/interfaces/ParsedAddress.md +2 -2
  138. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  139. package/docs/api/interfaces/ProgressProps.md +3 -11
  140. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  141. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  142. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  143. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  144. package/docs/api/interfaces/QuickFix.md +1 -1
  145. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  146. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  147. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  148. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  149. package/docs/api/interfaces/RBACConfig.md +2 -2
  150. package/docs/api/interfaces/RBACContext.md +1 -1
  151. package/docs/api/interfaces/RBACLogger.md +1 -1
  152. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  153. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  154. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  155. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  156. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  157. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  158. package/docs/api/interfaces/RBACResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  160. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  161. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  162. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  163. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  164. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  165. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  166. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  167. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  168. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  169. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  170. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  171. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  172. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  173. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  174. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  175. package/docs/api/interfaces/RouteConfig.md +10 -10
  176. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  177. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  178. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  179. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  180. package/docs/api/interfaces/SetupIssue.md +1 -1
  181. package/docs/api/interfaces/StorageConfig.md +4 -4
  182. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  183. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  184. package/docs/api/interfaces/StorageListOptions.md +22 -9
  185. package/docs/api/interfaces/StorageListResult.md +4 -4
  186. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  187. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  188. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  189. package/docs/api/interfaces/StyleImport.md +1 -1
  190. package/docs/api/interfaces/SwitchProps.md +1 -1
  191. package/docs/api/interfaces/TabsContentProps.md +1 -1
  192. package/docs/api/interfaces/TabsListProps.md +1 -1
  193. package/docs/api/interfaces/TabsProps.md +1 -1
  194. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  195. package/docs/api/interfaces/TextareaProps.md +1 -1
  196. package/docs/api/interfaces/ToastActionElement.md +1 -1
  197. package/docs/api/interfaces/ToastProps.md +1 -1
  198. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  199. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  200. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  201. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  202. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  203. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  205. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  207. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  208. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  209. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  210. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  211. package/docs/api/interfaces/UseResolvedScopeOptions.md +5 -5
  212. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  213. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  214. package/docs/api/interfaces/UserEventAccess.md +11 -11
  215. package/docs/api/interfaces/UserMenuProps.md +1 -1
  216. package/docs/api/interfaces/UserProfile.md +1 -1
  217. package/docs/api/modules.md +165 -106
  218. package/docs/api-reference/components.md +15 -7
  219. package/docs/api-reference/providers.md +2 -2
  220. package/docs/api-reference/rpc-functions.md +1 -0
  221. package/docs/best-practices/README.md +1 -1
  222. package/docs/best-practices/deployment.md +8 -8
  223. package/docs/getting-started/examples/README.md +2 -2
  224. package/docs/getting-started/installation-guide.md +4 -4
  225. package/docs/getting-started/quick-start.md +3 -3
  226. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  227. package/docs/migration/README.md +18 -0
  228. package/docs/migration/database-changes-december-2025.md +767 -0
  229. package/docs/migration/person-scoped-profiles-migration-guide.md +472 -0
  230. package/docs/rbac/compliance/compliance-guide.md +2 -2
  231. package/docs/rbac/event-based-apps.md +2 -2
  232. package/docs/rbac/getting-started.md +2 -2
  233. package/docs/rbac/quick-start.md +2 -2
  234. package/docs/security/README.md +4 -4
  235. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  236. package/docs/troubleshooting/README.md +2 -2
  237. package/docs/troubleshooting/migration.md +3 -3
  238. package/package.json +1 -3
  239. package/scripts/check-pace-core-compliance.cjs +1 -1
  240. package/scripts/check-pace-core-compliance.js +1 -1
  241. package/src/__tests__/fixtures/supabase.ts +301 -0
  242. package/src/__tests__/public-recipe-view.test.ts +19 -19
  243. package/src/__tests__/rls-policies.test.ts +210 -74
  244. package/src/components/AddressField/AddressField.test.tsx +42 -0
  245. package/src/components/AddressField/AddressField.tsx +71 -60
  246. package/src/components/AddressField/README.md +7 -6
  247. package/src/components/Alert/Alert.test.tsx +50 -10
  248. package/src/components/Alert/Alert.tsx +5 -3
  249. package/src/components/Avatar/Avatar.test.tsx +95 -43
  250. package/src/components/Avatar/Avatar.tsx +16 -16
  251. package/src/components/Button/Button.test.tsx +2 -1
  252. package/src/components/Button/Button.tsx +3 -3
  253. package/src/components/Calendar/Calendar.test.tsx +53 -37
  254. package/src/components/Calendar/Calendar.tsx +409 -82
  255. package/src/components/Card/Card.test.tsx +7 -4
  256. package/src/components/Card/Card.tsx +3 -6
  257. package/src/components/Checkbox/Checkbox.tsx +2 -2
  258. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  259. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  260. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  261. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  262. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  263. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  264. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  265. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  266. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  267. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  268. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  269. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  270. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  271. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  272. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  273. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  274. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  275. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  276. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  277. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  278. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  279. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  280. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  281. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  282. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  284. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  285. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  286. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  287. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  288. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  289. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  290. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  291. package/src/components/Dialog/Dialog.tsx +2 -2
  292. package/src/components/EventSelector/EventSelector.tsx +7 -7
  293. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  294. package/src/components/FileUpload/FileUpload.tsx +7 -4
  295. package/src/components/Header/Header.test.tsx +28 -0
  296. package/src/components/Header/Header.tsx +22 -9
  297. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  298. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  299. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  301. package/src/components/OrganisationSelector/OrganisationSelector.tsx +42 -22
  302. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  303. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  304. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  305. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  306. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  307. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  308. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  309. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  310. package/src/components/Progress/Progress.test.tsx +18 -19
  311. package/src/components/Progress/Progress.tsx +31 -32
  312. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  313. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  314. package/src/components/Select/Select.test.tsx +4 -1
  315. package/src/components/Select/Select.tsx +65 -20
  316. package/src/components/Switch/Switch.test.tsx +2 -1
  317. package/src/components/Switch/Switch.tsx +1 -1
  318. package/src/components/Toast/Toast.tsx +1 -1
  319. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  320. package/src/components/UserMenu/UserMenu.tsx +3 -3
  321. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  322. package/src/eslint-rules/pace-core-compliance.js +0 -2
  323. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  324. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  325. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  326. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  327. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  328. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  329. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -1
  330. package/src/hooks/__tests__/usePublicEvent.test.ts +608 -0
  331. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  332. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +67 -24
  333. package/src/hooks/index.ts +1 -1
  334. package/src/hooks/public/usePublicEvent.ts +10 -10
  335. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  336. package/src/hooks/useAppConfig.ts +24 -5
  337. package/src/hooks/useFileDisplay.ts +298 -36
  338. package/src/hooks/useFileReference.ts +56 -11
  339. package/src/hooks/useFileUrl.ts +1 -1
  340. package/src/hooks/useInactivityTracker.ts +16 -7
  341. package/src/hooks/usePermissionCache.test.ts +85 -8
  342. package/src/hooks/useQueryCache.ts +27 -6
  343. package/src/hooks/useSecureDataAccess.test.ts +87 -42
  344. package/src/hooks/useSecureDataAccess.ts +95 -48
  345. package/src/providers/__tests__/OrganisationProvider.test.tsx +27 -21
  346. package/src/providers/services/EventServiceProvider.tsx +37 -17
  347. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  348. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  349. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  350. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  351. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  352. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  353. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  354. package/src/rbac/api.ts +240 -36
  355. package/src/rbac/cache-invalidation.ts +21 -7
  356. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  357. package/src/rbac/components/NavigationGuard.tsx +23 -63
  358. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  359. package/src/rbac/components/NavigationProvider.tsx +13 -11
  360. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  361. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  362. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  363. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  364. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  365. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  366. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  367. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  368. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  369. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  370. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  371. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  372. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  373. package/src/rbac/engine.ts +4 -2
  374. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  375. package/src/rbac/hooks/index.ts +3 -0
  376. package/src/rbac/hooks/useCan.test.ts +101 -53
  377. package/src/rbac/hooks/usePermissions.ts +108 -41
  378. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  379. package/src/rbac/hooks/useRBAC.ts +83 -40
  380. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  381. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  382. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  383. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  384. package/src/rbac/request-deduplication.ts +1 -1
  385. package/src/rbac/secureClient.ts +72 -12
  386. package/src/rbac/security.ts +29 -23
  387. package/src/rbac/types.ts +10 -0
  388. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  389. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  390. package/src/rbac/utils/__tests__/eventContext.test.ts +8 -3
  391. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +74 -12
  392. package/src/rbac/utils/contextValidator.ts +288 -0
  393. package/src/rbac/utils/eventContext.ts +52 -3
  394. package/src/services/AuthService.ts +37 -8
  395. package/src/services/EventService.ts +165 -21
  396. package/src/services/OrganisationService.ts +125 -137
  397. package/src/services/__tests__/EventService.test.ts +26 -21
  398. package/src/services/__tests__/OrganisationService.pagination.test.ts +34 -8
  399. package/src/services/__tests__/OrganisationService.test.ts +218 -86
  400. package/src/types/database.generated.ts +166 -201
  401. package/src/types/file-reference.ts +13 -10
  402. package/src/types/supabase.ts +2 -2
  403. package/src/utils/__tests__/secureDataAccess.unit.test.ts +3 -2
  404. package/src/utils/app/appNameResolver.test.ts +346 -73
  405. package/src/utils/context/superAdminOverride.ts +58 -0
  406. package/src/utils/file-reference/index.ts +65 -37
  407. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  408. package/src/utils/google-places/googlePlacesUtils.ts +1 -1
  409. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  410. package/src/utils/google-places/types.ts +1 -1
  411. package/src/utils/request-deduplication.ts +4 -4
  412. package/src/utils/security/secureDataAccess.test.ts +1 -1
  413. package/src/utils/security/secureDataAccess.ts +7 -4
  414. package/src/utils/storage/README.md +1 -1
  415. package/src/utils/storage/helpers.test.ts +1 -1
  416. package/src/utils/storage/helpers.ts +38 -19
  417. package/src/utils/storage/types.ts +15 -8
  418. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  419. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  420. package/src/vite-env.d.ts +2 -2
  421. package/dist/chunk-3GOZZZYH.js.map +0 -1
  422. package/dist/chunk-DDM4CCYT.js.map +0 -1
  423. package/dist/chunk-E7UAOUMY.js +0 -75
  424. package/dist/chunk-E7UAOUMY.js.map +0 -1
  425. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  426. package/dist/chunk-HEHYGYOX.js.map +0 -1
  427. package/dist/chunk-IM4QE42D.js.map +0 -1
  428. package/dist/chunk-MX64ZF6I.js.map +0 -1
  429. package/dist/chunk-SAUPYVLF.js.map +0 -1
  430. package/dist/chunk-THRPYOFK.js.map +0 -1
  431. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  432. package/dist/chunk-VGZZXKBR.js.map +0 -1
  433. package/dist/chunk-YGPFYGA6.js.map +0 -1
  434. package/dist/chunk-YHCN776L.js.map +0 -1
  435. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-WKRZD47S.js.map} +0 -0
  436. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-FTSG5XH7.js.map} +0 -0
  437. /package/dist/{api-YP7XD5L6.js.map → api-IHKALJZD.js.map} +0 -0
  438. /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-ULHIJK66.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-VRGWKHDB.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-XNYQOL3Z.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-OETXORNB.js";
61
57
  import {
62
58
  EventServiceContext,
59
+ useOrganisations,
63
60
  useSessionRestoration,
64
61
  useUnifiedAuth
65
- } from "./chunk-VGZZXKBR.js";
62
+ } from "./chunk-6LTQQAT6.js";
63
+ import {
64
+ isSuperAdmin
65
+ } from "./chunk-ROXMHMY2.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, useMemo as useMemo6 } 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,22 +2681,33 @@ 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
+ const isSelectDisabled = disabled || isLoading;
2689
+ const selectValue = useMemo6(() => {
2690
+ return selectedOrganisation?.id || "";
2691
+ }, [selectedOrganisation?.id]);
2692
+ return /* @__PURE__ */ jsxs9("div", { className, children: [
2693
+ /* @__PURE__ */ jsxs9(
2391
2694
  Select,
2392
2695
  {
2393
- value: selectedOrganisation?.id || "",
2696
+ value: selectValue,
2394
2697
  onValueChange: handleOrganisationChange,
2395
- disabled: disabled || isLoading || !selectedOrganisation,
2698
+ disabled: isSelectDisabled,
2396
2699
  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" }),
2399
- /* @__PURE__ */ jsx14(SelectValue, { placeholder })
2400
- ] }) }),
2700
+ /* @__PURE__ */ jsx14(
2701
+ SelectTrigger,
2702
+ {
2703
+ className: "text-left",
2704
+ variant: "outline",
2705
+ children: /* @__PURE__ */ jsx14(SelectValue, { placeholder, children: selectedOrganisation && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2706
+ isLoading ? /* @__PURE__ */ jsx14(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx14(Building2, { className: "size-4 flex-shrink-0" }),
2707
+ /* @__PURE__ */ jsx14("span", { className: "truncate", children: selectedOrganisation.display_name })
2708
+ ] }) })
2709
+ }
2710
+ ),
2401
2711
  /* @__PURE__ */ jsx14(SelectContent, { children: organisations.map((org) => {
2402
2712
  const userRole = getUserRole(org.id);
2403
2713
  const hasAccess = validateOrganisationAccess(org.id);
@@ -2407,16 +2717,16 @@ function OrganisationSelector({
2407
2717
  value: org.id,
2408
2718
  disabled: !hasAccess,
2409
2719
  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: [
2720
+ children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between w-full", children: [
2721
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2722
+ /* @__PURE__ */ jsx14(Building2, { className: "size-4" }),
2723
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
2414
2724
  /* @__PURE__ */ jsx14("span", { className: "font-medium", children: org.display_name }),
2415
2725
  !compact && org.description && /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
2416
2726
  ] })
2417
2727
  ] }),
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" }),
2728
+ showRole && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1 ml-4", children: [
2729
+ /* @__PURE__ */ jsx14(Shield, { className: "size-3 text-muted-foreground" }),
2420
2730
  /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
2421
2731
  ] })
2422
2732
  ] })
@@ -2427,18 +2737,18 @@ function OrganisationSelector({
2427
2737
  ]
2428
2738
  }
2429
2739
  ),
2430
- switchErrorDisplay
2740
+ switchErrorDisplay && /* @__PURE__ */ jsx14("div", { className: "mt-2", children: switchErrorDisplay })
2431
2741
  ] });
2432
2742
  }
2433
2743
 
2434
2744
  // src/components/PasswordChange/PasswordChangeForm.tsx
2435
- import { useState as useState8 } from "react";
2436
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2745
+ import { useState as useState9 } from "react";
2746
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2437
2747
  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);
2748
+ const [newPassword, setNewPassword] = useState9("");
2749
+ const [confirmPassword, setConfirmPassword] = useState9("");
2750
+ const [error, setError] = useState9(null);
2751
+ const [isSubmitting, setIsSubmitting] = useState9(false);
2442
2752
  const handleSubmit = async (e) => {
2443
2753
  e.preventDefault();
2444
2754
  setError(null);
@@ -2463,9 +2773,9 @@ function PasswordChangeForm({ onSubmit, className }) {
2463
2773
  setIsSubmitting(false);
2464
2774
  }
2465
2775
  };
2466
- return /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
2776
+ return /* @__PURE__ */ jsxs10("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
2467
2777
  error && /* @__PURE__ */ jsx15("div", { role: "alert", children: error }),
2468
- /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2778
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2469
2779
  /* @__PURE__ */ jsx15(Label, { htmlFor: "new-password", children: "New Password" }),
2470
2780
  /* @__PURE__ */ jsx15(
2471
2781
  Input,
@@ -2479,7 +2789,7 @@ function PasswordChangeForm({ onSubmit, className }) {
2479
2789
  }
2480
2790
  )
2481
2791
  ] }),
2482
- /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2792
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
2483
2793
  /* @__PURE__ */ jsx15(Label, { htmlFor: "confirm-password", children: "Confirm Password" }),
2484
2794
  /* @__PURE__ */ jsx15(
2485
2795
  Input,
@@ -2506,9 +2816,9 @@ function PasswordChangeForm({ onSubmit, className }) {
2506
2816
  }
2507
2817
 
2508
2818
  // src/components/UserMenu/UserMenu.tsx
2509
- import React14, { useCallback as useCallback8, useMemo as useMemo5, useState as useState9 } from "react";
2819
+ import React14, { useCallback as useCallback9, useMemo as useMemo7, useState as useState10 } from "react";
2510
2820
  import { ChevronDown, LogOut, KeyRound } from "lucide-react";
2511
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2821
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2512
2822
  var UserMenu = React14.memo(function UserMenu2({
2513
2823
  user,
2514
2824
  onSignOut,
@@ -2516,8 +2826,8 @@ var UserMenu = React14.memo(function UserMenu2({
2516
2826
  className,
2517
2827
  showAvatar = true
2518
2828
  }) {
2519
- const [isPasswordDialogOpen, setPasswordDialogOpen] = useState9(false);
2520
- const userInfo = useMemo5(() => {
2829
+ const [isPasswordDialogOpen, setPasswordDialogOpen] = useState10(false);
2830
+ const userInfo = useMemo7(() => {
2521
2831
  if (!user) return null;
2522
2832
  return {
2523
2833
  email: user.email,
@@ -2526,15 +2836,15 @@ var UserMenu = React14.memo(function UserMenu2({
2526
2836
  initial: (user.user_metadata?.display_name || user.user_metadata?.full_name || user.email || "U").charAt(0).toUpperCase()
2527
2837
  };
2528
2838
  }, [user]);
2529
- const handleSignOut = useCallback8(async () => {
2839
+ const handleSignOut = useCallback9(async () => {
2530
2840
  if (onSignOut) await onSignOut();
2531
2841
  }, [onSignOut]);
2532
2842
  if (!user || !userInfo) {
2533
2843
  return null;
2534
2844
  }
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: [
2845
+ return /* @__PURE__ */ jsxs11(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
2846
+ /* @__PURE__ */ jsxs11(Select, { className, children: [
2847
+ /* @__PURE__ */ jsx16(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
2538
2848
  showAvatar && /* @__PURE__ */ jsx16(
2539
2849
  Avatar,
2540
2850
  {
@@ -2545,26 +2855,26 @@ var UserMenu = React14.memo(function UserMenu2({
2545
2855
  }
2546
2856
  ),
2547
2857
  /* @__PURE__ */ jsx16("span", { children: userInfo.displayName }),
2548
- /* @__PURE__ */ jsx16(ChevronDown, { className: "h-4 w-4" })
2858
+ /* @__PURE__ */ jsx16(ChevronDown, { className: "size-4" })
2549
2859
  ] }) }),
2550
- /* @__PURE__ */ jsxs10(SelectContent, { children: [
2551
- /* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col space-y-1", children: [
2860
+ /* @__PURE__ */ jsxs11(SelectContent, { children: [
2861
+ /* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs11("div", { className: "flex flex-col space-y-1", children: [
2552
2862
  /* @__PURE__ */ jsx16("p", { className: "font-medium", children: userInfo.displayName }),
2553
2863
  /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: userInfo.email })
2554
2864
  ] }) }),
2555
2865
  /* @__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" }),
2866
+ /* @__PURE__ */ jsx16(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(SelectItem, { value: "change-password", children: [
2867
+ /* @__PURE__ */ jsx16(KeyRound, { className: "mr-2 size-4" }),
2558
2868
  /* @__PURE__ */ jsx16("span", { children: "Change Password" })
2559
2869
  ] }) }),
2560
- /* @__PURE__ */ jsxs10(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
2561
- /* @__PURE__ */ jsx16(LogOut, { className: "mr-2 h-4 w-4" }),
2870
+ /* @__PURE__ */ jsxs11(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
2871
+ /* @__PURE__ */ jsx16(LogOut, { className: "mr-2 size-4" }),
2562
2872
  /* @__PURE__ */ jsx16("span", { children: "Sign out" })
2563
2873
  ] })
2564
2874
  ] })
2565
2875
  ] }),
2566
2876
  /* @__PURE__ */ jsx16(DialogOverlay, {}),
2567
- /* @__PURE__ */ jsxs10(DialogContent, { className, children: [
2877
+ /* @__PURE__ */ jsxs11(DialogContent, { className, children: [
2568
2878
  /* @__PURE__ */ jsx16(DialogHeader, { children: /* @__PURE__ */ jsx16(DialogTitle, { children: "Change Password" }) }),
2569
2879
  /* @__PURE__ */ jsx16(
2570
2880
  PasswordChangeForm,
@@ -2585,8 +2895,8 @@ var UserMenu = React14.memo(function UserMenu2({
2585
2895
  ] });
2586
2896
  });
2587
2897
  var UserMenuLoading = React14.memo(function UserMenuLoading2() {
2588
- return /* @__PURE__ */ jsxs10("div", { className: "relative inline-block text-left", children: [
2589
- /* @__PURE__ */ jsxs10(
2898
+ return /* @__PURE__ */ jsxs11("div", { className: "relative inline-block text-left", children: [
2899
+ /* @__PURE__ */ jsxs11(
2590
2900
  "button",
2591
2901
  {
2592
2902
  type: "button",
@@ -2607,7 +2917,7 @@ UserMenu.Loading = UserMenuLoading;
2607
2917
  // src/components/NavigationMenu/NavigationMenu.tsx
2608
2918
  import * as React15 from "react";
2609
2919
  import { ChevronDown as ChevronDown2 } from "lucide-react";
2610
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2920
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2611
2921
  var NavigationMenu = React15.forwardRef(({
2612
2922
  items,
2613
2923
  mode = "dropdown",
@@ -2660,7 +2970,7 @@ var NavigationMenu = React15.forwardRef(({
2660
2970
  }
2661
2971
  const userId2 = authContext.user.id;
2662
2972
  const appName = authContext.appName;
2663
- import("./api-YP7XD5L6.js").then(({ resolveAppContext }) => {
2973
+ import("./api-IHKALJZD.js").then(({ resolveAppContext }) => {
2664
2974
  resolveAppContext({
2665
2975
  userId: userId2,
2666
2976
  appName
@@ -3011,8 +3321,8 @@ var NavigationMenu = React15.forwardRef(({
3011
3321
  const hasChildren = item.children && item.children.length > 0;
3012
3322
  const isExpanded = expandedItems.has(item.id);
3013
3323
  const itemIsActive = isActiveItem(item);
3014
- return /* @__PURE__ */ jsx17("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs11("div", { children: [
3015
- /* @__PURE__ */ jsxs11(
3324
+ return /* @__PURE__ */ jsx17("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs12("div", { children: [
3325
+ /* @__PURE__ */ jsxs12(
3016
3326
  "button",
3017
3327
  {
3018
3328
  onClick: () => toggleExpanded(item.id),
@@ -3053,7 +3363,7 @@ var NavigationMenu = React15.forwardRef(({
3053
3363
  ) });
3054
3364
  };
3055
3365
  if (mode === "dropdown") {
3056
- return /* @__PURE__ */ jsxs11(
3366
+ return /* @__PURE__ */ jsxs12(
3057
3367
  Select,
3058
3368
  {
3059
3369
  onValueChange: handleNavigationSelect,
@@ -3102,7 +3412,7 @@ NavigationMenu.displayName = "NavigationMenu";
3102
3412
 
3103
3413
  // src/components/Header/Header.tsx
3104
3414
  import { Link } from "react-router-dom";
3105
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
3415
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
3106
3416
  function Header({
3107
3417
  logoUrl,
3108
3418
  logoAlt = "Logo",
@@ -3121,10 +3431,25 @@ function Header({
3121
3431
  onNavigate,
3122
3432
  logoHref
3123
3433
  }) {
3434
+ const OrganisationSelectorConditional = () => {
3435
+ const { organisations, isContextReady } = useOrganisations();
3436
+ if (!isContextReady || !organisations || organisations.length === 0) {
3437
+ return null;
3438
+ }
3439
+ return /* @__PURE__ */ jsx18(
3440
+ OrganisationSelector,
3441
+ {
3442
+ placeholder: "Select organisation",
3443
+ className: "w-64",
3444
+ "data-testid": "org-selector",
3445
+ compact: true
3446
+ }
3447
+ );
3448
+ };
3124
3449
  return /* @__PURE__ */ jsx18("header", { className: cn(
3125
3450
  "w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
3126
3451
  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: [
3452
+ ), 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
3453
  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
3454
  "img",
3130
3455
  {
@@ -3144,14 +3469,14 @@ function Header({
3144
3469
  {
3145
3470
  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
3471
  alt: logoAlt || "Logo",
3147
- className: "h-8 w-8 shadow-md"
3472
+ className: "size-8 shadow-md"
3148
3473
  }
3149
3474
  ) }) : /* @__PURE__ */ jsx18(
3150
3475
  "img",
3151
3476
  {
3152
3477
  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
3478
  alt: logoAlt || "Logo",
3154
- className: "h-8 w-8 shadow-md"
3479
+ className: "size-8 shadow-md"
3155
3480
  }
3156
3481
  ),
3157
3482
  navItems && navItems.length > 0 && /* @__PURE__ */ jsx18(
@@ -3165,16 +3490,8 @@ function Header({
3165
3490
  itemsPreFiltered: true
3166
3491
  }
3167
3492
  ),
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,
3493
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-4 ml-auto", children: [
3494
+ showOrgSelector ? /* @__PURE__ */ jsx18(OrganisationSelectorConditional, {}) : null,
3178
3495
  showEventSelector ? /* @__PURE__ */ jsx18(
3179
3496
  EventSelector,
3180
3497
  {
@@ -3199,7 +3516,7 @@ function Header({
3199
3516
 
3200
3517
  // src/components/Footer/Footer.tsx
3201
3518
  import React16 from "react";
3202
- import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
3519
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3203
3520
  var FooterComponent = ({
3204
3521
  companyName = "Solvera Solutions Pty Ltd",
3205
3522
  year = (/* @__PURE__ */ new Date()).getFullYear(),
@@ -3210,9 +3527,9 @@ var FooterComponent = ({
3210
3527
  children
3211
3528
  }) => {
3212
3529
  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: [
3530
+ 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
3531
  logo && /* @__PURE__ */ jsx19("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
3215
- children && /* @__PURE__ */ jsx19(Fragment4, { children }),
3532
+ children && /* @__PURE__ */ jsx19(Fragment6, { children }),
3216
3533
  /* @__PURE__ */ jsx19("span", { className: "text-muted-foreground", children: copyrightText }),
3217
3534
  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
3535
  ] }) });
@@ -3222,9 +3539,9 @@ var Footer = React16.memo(FooterComponent);
3222
3539
  Footer.displayName = "Footer";
3223
3540
 
3224
3541
  // src/components/PaceAppLayout/PaceAppLayout.tsx
3225
- import { useState as useState11, useEffect as useEffect8, useMemo as useMemo7 } from "react";
3542
+ import { useState as useState12, useEffect as useEffect8, useMemo as useMemo9 } from "react";
3226
3543
  import { Outlet, useNavigate, useLocation } from "react-router-dom";
3227
- import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3544
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
3228
3545
  var EMPTY_PAGE_ID_MAPPING = {};
3229
3546
  var EMPTY_ROUTE_PERMISSIONS = {};
3230
3547
  function PaceAppLayout({
@@ -3258,7 +3575,13 @@ function PaceAppLayout({
3258
3575
  onRouteStrictModeViolation
3259
3576
  }) {
3260
3577
  const { user, signOut, updatePassword, supabase, appId: contextAppId } = useUnifiedAuth();
3261
- const { selectedOrganisation } = useOrganisations();
3578
+ const {
3579
+ selectedOrganisation,
3580
+ isContextReady,
3581
+ hasValidOrganisationContext,
3582
+ ensureOrganisationContext,
3583
+ isLoading: organisationLoading
3584
+ } = useOrganisations();
3262
3585
  const navigate = useNavigate();
3263
3586
  const location = useLocation();
3264
3587
  useEventTheme();
@@ -3274,7 +3597,7 @@ function PaceAppLayout({
3274
3597
  selectedEventId: selectedEvent?.event_id || null
3275
3598
  });
3276
3599
  const resolvedAppId = contextAppId || resolvedScope?.appId;
3277
- const scope = useMemo7(() => {
3600
+ const scope = useMemo9(() => {
3278
3601
  if (resolvedScope?.organisationId) {
3279
3602
  return resolvedScope;
3280
3603
  }
@@ -3291,19 +3614,19 @@ function PaceAppLayout({
3291
3614
  appId: resolvedAppId || resolvedScope?.appId || void 0
3292
3615
  };
3293
3616
  }, [resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id, resolvedAppId]);
3294
- const defaultNavItems = useMemo7(() => [
3617
+ const defaultNavItems = useMemo9(() => [
3295
3618
  { id: "home", label: "Home", href: "/", icon: "Home" },
3296
3619
  { id: "dashboard", label: "Dashboard", href: "/dashboard", icon: "LayoutDashboard" },
3297
3620
  { id: "settings", label: "Settings", href: "/settings", icon: "Settings" },
3298
3621
  { id: "ui-showcase", label: "UI Showcase", href: "/ui-showcase", icon: "Component" },
3299
3622
  { id: "data-table-showcase", label: "DataTable Showcase", href: "/data-table-showcase", icon: "Table" }
3300
3623
  ], []);
3301
- const baseMenuItems = useMemo7(() => navItems || defaultNavItems, [navItems]);
3302
- const currentRoutePermission = useMemo7(() => {
3624
+ const baseMenuItems = useMemo9(() => navItems || defaultNavItems, [navItems]);
3625
+ const currentRoutePermission = useMemo9(() => {
3303
3626
  const currentPath = location.pathname;
3304
3627
  return routePermissions[currentPath] || defaultPermission;
3305
3628
  }, [location.pathname, routePermissions, defaultPermission]);
3306
- const currentPageId = useMemo7(() => {
3629
+ const currentPageId = useMemo9(() => {
3307
3630
  const currentPath = location.pathname;
3308
3631
  if (pageIdMapping[currentPath]) {
3309
3632
  return pageIdMapping[currentPath];
@@ -3311,15 +3634,15 @@ function PaceAppLayout({
3311
3634
  const pathSegments = currentPath.slice(1).split("/").filter(Boolean);
3312
3635
  return pathSegments[0] || "home";
3313
3636
  }, [location.pathname, pageIdMapping]);
3314
- const currentPermission = useMemo7(() => {
3637
+ const currentPermission = useMemo9(() => {
3315
3638
  if (!enforcePermissions) {
3316
3639
  return "read:page.home";
3317
3640
  }
3318
3641
  const permissionString = `${currentRoutePermission}:page.${currentPageId}`;
3319
3642
  return permissionString;
3320
3643
  }, [enforcePermissions, currentRoutePermission, currentPageId]);
3321
- const [isSuperAdminUser, setIsSuperAdminUser] = useState11(false);
3322
- const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState11(false);
3644
+ const [isSuperAdminUser, setIsSuperAdminUser] = useState12(false);
3645
+ const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState12(false);
3323
3646
  useEffect8(() => {
3324
3647
  const checkSuperAdminStatus = async () => {
3325
3648
  if (!user?.id) {
@@ -3345,8 +3668,10 @@ function PaceAppLayout({
3345
3668
  scope,
3346
3669
  currentPermission,
3347
3670
  currentPageId,
3348
- true
3671
+ true,
3349
3672
  // useCache
3673
+ appName
3674
+ // Pass appName for PORTAL/ADMIN special case
3350
3675
  );
3351
3676
  const can = isSuperAdminUser ? true : canFromHook;
3352
3677
  const hasPermission = enforcePermissions ? can : true;
@@ -3373,7 +3698,7 @@ function PaceAppLayout({
3373
3698
  onPageAccessDenied(currentPageId, currentRoutePermission);
3374
3699
  }
3375
3700
  }, [enforcePermissions, can, isCheckingPermission, isCheckingSuperAdmin, isSuperAdminUser, currentPageId, currentRoutePermission, user?.id, strictMode, auditLog, onPageAccessDenied, onStrictModeViolation]);
3376
- const [filteredMenuItems, setFilteredMenuItems] = useState11(baseMenuItems);
3701
+ const [filteredMenuItems, setFilteredMenuItems] = useState12(baseMenuItems);
3377
3702
  useEffect8(() => {
3378
3703
  let isMounted = true;
3379
3704
  const filterItems = async () => {
@@ -3400,7 +3725,7 @@ function PaceAppLayout({
3400
3725
  return;
3401
3726
  }
3402
3727
  try {
3403
- const { isSuperAdmin: isSuperAdmin2 } = await import("./api-YP7XD5L6.js");
3728
+ const { isSuperAdmin: isSuperAdmin2 } = await import("./api-IHKALJZD.js");
3404
3729
  const isSuper = await isSuperAdmin2(user.id);
3405
3730
  if (isSuper) {
3406
3731
  if (isMounted) {
@@ -3415,7 +3740,7 @@ function PaceAppLayout({
3415
3740
  }
3416
3741
  }
3417
3742
  try {
3418
- const { getPermissionMap } = await import("./api-YP7XD5L6.js");
3743
+ const { getPermissionMap } = await import("./api-IHKALJZD.js");
3419
3744
  const permissionScope = {
3420
3745
  organisationId: currentScope.organisationId,
3421
3746
  eventId: currentScope.eventId,
@@ -3471,7 +3796,7 @@ function PaceAppLayout({
3471
3796
  let hasAccess = true;
3472
3797
  if (currentRoute.pageId && currentRoute.permissions && currentRoute.permissions.length > 0) {
3473
3798
  try {
3474
- const { isPermittedCached } = await import("./api-YP7XD5L6.js");
3799
+ const { isPermittedCached } = await import("./api-IHKALJZD.js");
3475
3800
  const hasPagePermission = await isPermittedCached({
3476
3801
  userId: user?.id || "",
3477
3802
  scope,
@@ -3487,7 +3812,7 @@ function PaceAppLayout({
3487
3812
  }
3488
3813
  }
3489
3814
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
3490
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-643PUAIM.js");
3815
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-FTSG5XH7.js");
3491
3816
  hasAccess = true;
3492
3817
  }
3493
3818
  if (!isMounted) return;
@@ -3533,14 +3858,20 @@ function PaceAppLayout({
3533
3858
  }
3534
3859
  return {};
3535
3860
  };
3861
+ if (user?.id && organisationLoading) {
3862
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3863
+ /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full size-8 border-b-2 border-sec-900 mx-auto mb-4" }),
3864
+ /* @__PURE__ */ jsx20("p", { className: "text-sec-600", children: "Loading organisation context..." })
3865
+ ] }) });
3866
+ }
3536
3867
  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" }),
3868
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3869
+ /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full size-8 border-b-2 border-sec-900 mx-auto mb-4" }),
3539
3870
  /* @__PURE__ */ jsx20("p", { className: "text-sec-600", children: "Checking permissions..." })
3540
3871
  ] }) });
3541
3872
  }
3542
3873
  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: [
3874
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3544
3875
  /* @__PURE__ */ jsx20("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Permission Error" }),
3545
3876
  /* @__PURE__ */ jsx20("p", { className: "text-sec-600 mb-4", children: permissionError.message }),
3546
3877
  /* @__PURE__ */ jsx20(Button, { onClick: () => navigate("/"), children: "Go Home" })
@@ -3548,15 +3879,15 @@ function PaceAppLayout({
3548
3879
  }
3549
3880
  if (enforcePermissions && hasPermission === false && !isCheckingSuperAdmin && !isSuperAdminUser) {
3550
3881
  if (enforcePagePermissions && pagePermissionFallback) {
3551
- return /* @__PURE__ */ jsx20(Fragment5, { children: pagePermissionFallback });
3882
+ return /* @__PURE__ */ jsx20(Fragment7, { children: pagePermissionFallback });
3552
3883
  }
3553
3884
  if (permissionFallback) {
3554
- return /* @__PURE__ */ jsx20(Fragment5, { children: permissionFallback });
3885
+ return /* @__PURE__ */ jsx20(Fragment7, { children: permissionFallback });
3555
3886
  }
3556
- return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs14("div", { className: "text-center", children: [
3887
+ return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
3557
3888
  /* @__PURE__ */ jsx20("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Access Denied" }),
3558
3889
  /* @__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: [
3890
+ /* @__PURE__ */ jsxs15("div", { className: "flex gap-2 justify-center", children: [
3560
3891
  /* @__PURE__ */ jsx20(Button, { onClick: () => navigate("/"), children: "Go Home" }),
3561
3892
  /* @__PURE__ */ jsx20(
3562
3893
  Button,
@@ -3572,7 +3903,7 @@ function PaceAppLayout({
3572
3903
  ] })
3573
3904
  ] }) });
3574
3905
  }
3575
- return /* @__PURE__ */ jsxs14(Fragment5, { children: [
3906
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
3576
3907
  /* @__PURE__ */ jsx20(
3577
3908
  Header,
3578
3909
  {
@@ -3604,9 +3935,9 @@ function PaceAppLayout({
3604
3935
  }
3605
3936
 
3606
3937
  // src/components/PaceLoginPage/PaceLoginPage.tsx
3607
- import { useEffect as useEffect9, useState as useState12, useContext as useContext2 } from "react";
3938
+ import { useEffect as useEffect9, useState as useState13, useContext as useContext2 } from "react";
3608
3939
  import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
3609
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
3940
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
3610
3941
  var PaceLoginPage = ({
3611
3942
  appName = "Pace",
3612
3943
  onSuccessRedirectPath = "/",
@@ -3615,9 +3946,9 @@ var PaceLoginPage = ({
3615
3946
  const { signIn, isAuthenticated, isLoading, authError, user, supabase } = useUnifiedAuth();
3616
3947
  const navigate = useNavigate2();
3617
3948
  const location = useLocation2();
3618
- const [isSigningIn, setIsSigningIn] = useState12(false);
3619
- const [accessError, setAccessError] = useState12(null);
3620
- const [isCheckingAccess, setIsCheckingAccess] = useState12(false);
3949
+ const [isSigningIn, setIsSigningIn] = useState13(false);
3950
+ const [accessError, setAccessError] = useState13(null);
3951
+ const [isCheckingAccess, setIsCheckingAccess] = useState13(false);
3621
3952
  const eventServiceContext = useContext2(EventServiceContext);
3622
3953
  const eventService = eventServiceContext?.eventService || null;
3623
3954
  useEffect9(() => {
@@ -3676,8 +4007,9 @@ var PaceLoginPage = ({
3676
4007
  setIsCheckingAccess(false);
3677
4008
  return;
3678
4009
  }
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) {
4010
+ 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();
4011
+ const organisationId = orgRow?.organisation_id;
4012
+ if (!organisationId) {
3681
4013
  logger.debug("PaceLoginPage", "User has no organisation access");
3682
4014
  setAccessError(`You do not have permission to access ${appName}. You are not assigned to any organisation. Please contact your administrator.`);
3683
4015
  setIsCheckingAccess(false);
@@ -3689,7 +4021,7 @@ var PaceLoginPage = ({
3689
4021
  p_user_id: userId,
3690
4022
  p_permission: `read:page.${page.page_name}`,
3691
4023
  // Permission format: operation:resource
3692
- p_organisation_id: orgData.organisation_id,
4024
+ p_organisation_id: organisationId,
3693
4025
  p_event_id: null,
3694
4026
  p_app_id: appData.id,
3695
4027
  p_page_id: page.page_name
@@ -3737,7 +4069,7 @@ var PaceLoginPage = ({
3737
4069
  setIsSigningIn(false);
3738
4070
  }
3739
4071
  };
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: [
4072
+ 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
4073
  /* @__PURE__ */ jsx21(
3742
4074
  "img",
3743
4075
  {
@@ -3768,12 +4100,12 @@ var PaceLoginPage = ({
3768
4100
  };
3769
4101
 
3770
4102
  // src/components/SessionRestorationLoader/SessionRestorationLoader.tsx
3771
- import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
4103
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
3772
4104
  var SessionRestorationLoader = ({
3773
4105
  message = "Restoring session...",
3774
4106
  className
3775
4107
  }) => {
3776
- return /* @__PURE__ */ jsxs16(
4108
+ return /* @__PURE__ */ jsxs17(
3777
4109
  "div",
3778
4110
  {
3779
4111
  className: cn(
@@ -3792,9 +4124,9 @@ var SessionRestorationLoader = ({
3792
4124
  };
3793
4125
 
3794
4126
  // src/components/ProtectedRoute/ProtectedRoute.tsx
3795
- import { useMemo as useMemo8, useEffect as useEffect10, useRef as useRef7, useState as useState13 } from "react";
4127
+ import { useMemo as useMemo10, useEffect as useEffect10, useRef as useRef8, useState as useState14 } from "react";
3796
4128
  import { Navigate, Outlet as Outlet2 } from "react-router-dom";
3797
- import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
4129
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
3798
4130
  function ProtectedRoute({
3799
4131
  requireEvent = false,
3800
4132
  allowSuperAdminBypass = false,
@@ -3809,9 +4141,9 @@ function ProtectedRoute({
3809
4141
  const eventLoading = requireEvent ? eventsContext.isLoading || false : false;
3810
4142
  const sessionRestoration = useSessionRestoration();
3811
4143
  usePreventTabReload({ enabled: true, gracePeriodMs: 2e3 });
3812
- const wasAuthenticatedRef = useRef7(false);
3813
- const [shouldRedirect, setShouldRedirect] = useState13(false);
3814
- const tabJustBecameVisibleRef = useRef7(false);
4144
+ const wasAuthenticatedRef = useRef8(false);
4145
+ const [shouldRedirect, setShouldRedirect] = useState14(false);
4146
+ const tabJustBecameVisibleRef = useRef8(false);
3815
4147
  useEffect10(() => {
3816
4148
  if (isAuthenticated) {
3817
4149
  wasAuthenticatedRef.current = true;
@@ -3869,7 +4201,7 @@ function ProtectedRoute({
3869
4201
  tabJustBecameVisibleRef.current = false;
3870
4202
  }
3871
4203
  }, [isAuthenticated]);
3872
- const isRestoringSession = useMemo8(() => {
4204
+ const isRestoringSession = useMemo10(() => {
3873
4205
  return sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError && !sessionRestoration.hasTimedOut;
3874
4206
  }, [
3875
4207
  sessionRestoration.isRestoring,
@@ -3913,7 +4245,7 @@ function ProtectedRoute({
3913
4245
  return /* @__PURE__ */ jsx23(Outlet2, {});
3914
4246
  }
3915
4247
  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: [
4248
+ 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
4249
  /* @__PURE__ */ jsx23(AlertTitle, { children: "No Events Available" }),
3918
4250
  /* @__PURE__ */ jsx23(AlertDescription, { children: "You don't have access to any events. Please contact your administrator if you believe this is an error." })
3919
4251
  ] }) });
@@ -3926,13 +4258,14 @@ function ProtectedRoute({
3926
4258
  }
3927
4259
 
3928
4260
  // 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";
4261
+ import { useState as useState15, useCallback as useCallback11, useRef as useRef9, useEffect as useEffect11, useMemo as useMemo11 } from "react";
4262
+ import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
3931
4263
  function FileUpload({
3932
4264
  supabase,
3933
4265
  table_name,
3934
4266
  record_id,
3935
4267
  organisation_id,
4268
+ userId,
3936
4269
  app_id,
3937
4270
  category,
3938
4271
  folder,
@@ -3952,12 +4285,12 @@ function FileUpload({
3952
4285
  onProgress,
3953
4286
  children
3954
4287
  }) {
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);
4288
+ const [isDragging, setIsDragging] = useState15(false);
4289
+ const [uploadStates, setUploadStates] = useState15(/* @__PURE__ */ new Map());
4290
+ const [resolvedAppId, setResolvedAppId] = useState15(app_id || null);
4291
+ const [isResolvingAppId, setIsResolvingAppId] = useState15(!app_id);
4292
+ const [appIdError, setAppIdError] = useState15(null);
4293
+ const fileInputRef = useRef9(null);
3961
4294
  const { uploadFile, isLoading, error } = useFileReference(supabase);
3962
4295
  useEffect11(() => {
3963
4296
  if (app_id) {
@@ -3994,15 +4327,15 @@ function FileUpload({
3994
4327
  };
3995
4328
  resolveAppId();
3996
4329
  }, [app_id, supabase]);
3997
- const isUploading = useMemo9(() => {
4330
+ const isUploading = useMemo11(() => {
3998
4331
  return uploadStates.size > 0 && Array.from(uploadStates.values()).some(
3999
4332
  (state) => state.progress.status === "uploading" || state.progress.status === "processing"
4000
4333
  );
4001
4334
  }, [uploadStates]);
4002
- const isDisabled = useMemo9(() => {
4335
+ const isDisabled = useMemo11(() => {
4003
4336
  return disabled || isUploading || isResolvingAppId || !resolvedAppId;
4004
4337
  }, [disabled, isUploading, isResolvingAppId, resolvedAppId]);
4005
- const generatePreview = useCallback10((file) => {
4338
+ const generatePreview = useCallback11((file) => {
4006
4339
  return new Promise((resolve) => {
4007
4340
  if (!file.type.startsWith("image/")) {
4008
4341
  resolve(null);
@@ -4016,7 +4349,7 @@ function FileUpload({
4016
4349
  reader.readAsDataURL(file);
4017
4350
  });
4018
4351
  }, []);
4019
- const validateFile = useCallback10((file) => {
4352
+ const validateFile = useCallback11((file) => {
4020
4353
  if (file.size > maxSize) {
4021
4354
  return `File "${file.name}" exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`;
4022
4355
  }
@@ -4040,7 +4373,7 @@ function FileUpload({
4040
4373
  }
4041
4374
  return null;
4042
4375
  }, [accept, maxSize]);
4043
- const handleFileSelect = useCallback10(async (files) => {
4376
+ const handleFileSelect = useCallback11(async (files) => {
4044
4377
  if (!files || files.length === 0) return;
4045
4378
  const fileArray = Array.from(files);
4046
4379
  const validationErrors = [];
@@ -4122,7 +4455,9 @@ function FileUpload({
4122
4455
  const result = await uploadFile({
4123
4456
  table_name,
4124
4457
  record_id,
4125
- organisation_id,
4458
+ organisation_id: organisation_id || null,
4459
+ userId,
4460
+ // Pass userId prop directly - it's required for user-scoped files when organisation_id is null
4126
4461
  app_id: resolvedAppId ? assertAppId(resolvedAppId) : assertAppId(""),
4127
4462
  category,
4128
4463
  folder,
@@ -4215,19 +4550,19 @@ function FileUpload({
4215
4550
  }
4216
4551
  }
4217
4552
  }, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
4218
- const handleDragOver = useCallback10((e) => {
4553
+ const handleDragOver = useCallback11((e) => {
4219
4554
  e.preventDefault();
4220
4555
  e.stopPropagation();
4221
4556
  if (!isDisabled) {
4222
4557
  setIsDragging(true);
4223
4558
  }
4224
4559
  }, [isDisabled]);
4225
- const handleDragLeave = useCallback10((e) => {
4560
+ const handleDragLeave = useCallback11((e) => {
4226
4561
  e.preventDefault();
4227
4562
  e.stopPropagation();
4228
4563
  setIsDragging(false);
4229
4564
  }, []);
4230
- const handleDrop = useCallback10((e) => {
4565
+ const handleDrop = useCallback11((e) => {
4231
4566
  e.preventDefault();
4232
4567
  e.stopPropagation();
4233
4568
  setIsDragging(false);
@@ -4235,13 +4570,13 @@ function FileUpload({
4235
4570
  const files = e.dataTransfer.files;
4236
4571
  handleFileSelect(files);
4237
4572
  }, [isDisabled, handleFileSelect]);
4238
- const handleFileInputChange = useCallback10((e) => {
4573
+ const handleFileInputChange = useCallback11((e) => {
4239
4574
  handleFileSelect(e.target.files);
4240
4575
  if (e.target) {
4241
4576
  e.target.value = "";
4242
4577
  }
4243
4578
  }, [handleFileSelect]);
4244
- const handleClick = useCallback10(() => {
4579
+ const handleClick = useCallback11(() => {
4245
4580
  if (!isDisabled && fileInputRef.current) {
4246
4581
  fileInputRef.current.click();
4247
4582
  }
@@ -4255,8 +4590,8 @@ function FileUpload({
4255
4590
  };
4256
4591
  const dragClasses = isDragging ? "border-main-500 bg-main-50" : "border-sec-300 hover:border-sec-400";
4257
4592
  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(
4593
+ return /* @__PURE__ */ jsxs19("div", { className: `space-y-4 ${className}`, children: [
4594
+ /* @__PURE__ */ jsxs19(
4260
4595
  "div",
4261
4596
  {
4262
4597
  role: "button",
@@ -4275,7 +4610,7 @@ function FileUpload({
4275
4610
  }
4276
4611
  } : void 0,
4277
4612
  children: [
4278
- children || /* @__PURE__ */ jsxs18("div", { className: "space-y-2", children: [
4613
+ children || /* @__PURE__ */ jsxs19("div", { className: "space-y-2", children: [
4279
4614
  /* @__PURE__ */ jsx24(
4280
4615
  "input",
4281
4616
  {
@@ -4289,12 +4624,12 @@ function FileUpload({
4289
4624
  "data-testid": "file-input"
4290
4625
  }
4291
4626
  ),
4292
- /* @__PURE__ */ jsx24("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs18(Fragment6, { children: [
4627
+ /* @__PURE__ */ jsx24("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs19(Fragment8, { children: [
4293
4628
  /* @__PURE__ */ jsx24("span", { className: "font-medium", children: "Click to upload" }),
4294
4629
  " ",
4295
4630
  "or drag and drop"
4296
4631
  ] }) }),
4297
- /* @__PURE__ */ jsxs18("div", { className: "text-sm text-sec-500", children: [
4632
+ /* @__PURE__ */ jsxs19("div", { className: "text-sm text-sec-500", children: [
4298
4633
  !isResolvingAppId && accept !== "*/*" && `Accepted formats: ${accept}`,
4299
4634
  !isResolvingAppId && maxSize && ` \u2022 Max size: ${Math.round(maxSize / 1024 / 1024)}MB`,
4300
4635
  !isResolvingAppId && multiple && " \u2022 Multiple files allowed"
@@ -4307,7 +4642,7 @@ function FileUpload({
4307
4642
  role: "status",
4308
4643
  "aria-live": "polite",
4309
4644
  "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" })
4645
+ children: /* @__PURE__ */ jsx24("div", { className: "animate-spin rounded-full size-8 border-b-2 border-main-500", "aria-hidden": "true" })
4311
4646
  }
4312
4647
  )
4313
4648
  ]
@@ -4318,7 +4653,7 @@ function FileUpload({
4318
4653
  const isError = progress.status === "error";
4319
4654
  const isCompleted = progress.status === "completed";
4320
4655
  const isUploading2 = progress.status === "uploading" || progress.status === "processing";
4321
- return /* @__PURE__ */ jsxs18(
4656
+ return /* @__PURE__ */ jsxs19(
4322
4657
  "div",
4323
4658
  {
4324
4659
  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 +4666,14 @@ function FileUpload({
4331
4666
  className: "w-12 h-12 object-cover rounded"
4332
4667
  }
4333
4668
  ) : /* @__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: [
4669
+ /* @__PURE__ */ jsxs19("div", { className: "flex-1 min-w-0", children: [
4335
4670
  /* @__PURE__ */ jsx24("div", { className: "font-medium text-sec-900 truncate", children: file.name }),
4336
- /* @__PURE__ */ jsxs18("div", { className: "text-sm text-sec-500", children: [
4671
+ /* @__PURE__ */ jsxs19("div", { className: "text-sm text-sec-500", children: [
4337
4672
  formatFileSize(file.size),
4338
4673
  isCompleted && result && " \u2022 Uploaded",
4339
4674
  isError && progress.error && ` \u2022 ${progress.error}`
4340
4675
  ] }),
4341
- showProgress && (isUploading2 || isError) && /* @__PURE__ */ jsxs18("div", { className: "mt-2", children: [
4676
+ showProgress && (isUploading2 || isError) && /* @__PURE__ */ jsxs19("div", { className: "mt-2", children: [
4342
4677
  /* @__PURE__ */ jsx24("div", { className: "w-full bg-sec-200 rounded-full h-2", children: /* @__PURE__ */ jsx24(
4343
4678
  "div",
4344
4679
  {
@@ -4346,7 +4681,7 @@ function FileUpload({
4346
4681
  style: { width: `${progress.percentage}%` }
4347
4682
  }
4348
4683
  ) }),
4349
- isUploading2 && /* @__PURE__ */ jsxs18("div", { className: "text-xs text-sec-500 mt-1", children: [
4684
+ isUploading2 && /* @__PURE__ */ jsxs19("div", { className: "text-xs text-sec-500 mt-1", children: [
4350
4685
  progress.percentage,
4351
4686
  "% \u2022 ",
4352
4687
  formatFileSize(progress.loaded),
@@ -4355,13 +4690,13 @@ function FileUpload({
4355
4690
  ] })
4356
4691
  ] })
4357
4692
  ] }),
4358
- /* @__PURE__ */ jsxs18("div", { className: "flex-shrink-0", children: [
4693
+ /* @__PURE__ */ jsxs19("div", { className: "flex-shrink-0", children: [
4359
4694
  isCompleted && /* @__PURE__ */ jsx24("span", { className: "text-success-500 text-xl", children: "\u2713" }),
4360
4695
  isError && /* @__PURE__ */ jsx24("span", { className: "text-acc-500 text-xl", children: "\u2715" }),
4361
4696
  isUploading2 && /* @__PURE__ */ jsx24(
4362
4697
  "div",
4363
4698
  {
4364
- className: "animate-spin rounded-full h-5 w-5 border-b-2 border-main-500",
4699
+ className: "animate-spin rounded-full size-5 border-b-2 border-main-500",
4365
4700
  role: "status",
4366
4701
  "aria-label": "Uploading",
4367
4702
  "aria-hidden": "true"
@@ -4473,7 +4808,7 @@ var TableCaption = React21.forwardRef(({ className, ...props }, ref) => /* @__PU
4473
4808
  TableCaption.displayName = "TableCaption";
4474
4809
 
4475
4810
  // src/components/PublicLayout/PublicPageLayout.tsx
4476
- import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
4811
+ import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
4477
4812
  function PublicPageHeader({
4478
4813
  event,
4479
4814
  eventCode,
@@ -4486,7 +4821,7 @@ function PublicPageHeader({
4486
4821
  customEventLogo
4487
4822
  }) {
4488
4823
  const { appName } = useAppConfig();
4489
- return /* @__PURE__ */ jsxs19("header", { className: cn(
4824
+ return /* @__PURE__ */ jsxs20("header", { className: cn(
4490
4825
  "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
4826
  className
4492
4827
  ), children: [
@@ -4498,9 +4833,9 @@ function PublicPageHeader({
4498
4833
  alt: appName
4499
4834
  }
4500
4835
  ),
4501
- event && /* @__PURE__ */ jsxs19(Fragment7, { children: [
4836
+ event && /* @__PURE__ */ jsxs20(Fragment9, { children: [
4502
4837
  /* @__PURE__ */ jsx26("h1", { children: event.event_name }),
4503
- showEventLogo && event && /* @__PURE__ */ jsx26(Fragment7, { children: customEventLogo || /* @__PURE__ */ jsx26(
4838
+ showEventLogo && event && /* @__PURE__ */ jsx26(Fragment9, { children: customEventLogo || /* @__PURE__ */ jsx26(
4504
4839
  FileDisplay,
4505
4840
  {
4506
4841
  table_name: "event",
@@ -4519,11 +4854,11 @@ function PublicPageHeader({
4519
4854
  ) }),
4520
4855
  event.event_venue && /* @__PURE__ */ jsx26("h4", { children: event.event_venue })
4521
4856
  ] }),
4522
- title && /* @__PURE__ */ jsxs19(Fragment7, { children: [
4857
+ title && /* @__PURE__ */ jsxs20(Fragment9, { children: [
4523
4858
  /* @__PURE__ */ jsx26("h1", { children: title }),
4524
4859
  description && /* @__PURE__ */ jsx26("p", { className: "text-lg text-sec-600 max-w-3xl mx-auto", children: description })
4525
4860
  ] }),
4526
- children && /* @__PURE__ */ jsx26(Fragment7, { children })
4861
+ children && /* @__PURE__ */ jsx26(Fragment9, { children })
4527
4862
  ] });
4528
4863
  }
4529
4864
  function PublicPageFooter({
@@ -4537,9 +4872,9 @@ function PublicPageFooter({
4537
4872
  children
4538
4873
  }) {
4539
4874
  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: [
4875
+ 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
4876
  logo && /* @__PURE__ */ jsx26("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
4542
- children && /* @__PURE__ */ jsx26(Fragment7, { children }),
4877
+ children && /* @__PURE__ */ jsx26(Fragment9, { children }),
4543
4878
  /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: copyrightText }),
4544
4879
  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
4880
  ] }) });
@@ -4567,7 +4902,7 @@ function PublicPageLayout({
4567
4902
  if (LoadingFallback) {
4568
4903
  return /* @__PURE__ */ jsx26(LoadingFallback, {});
4569
4904
  }
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: [
4905
+ 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
4906
  /* @__PURE__ */ jsx26(LoadingSpinner, { size: "lg", className: "mx-auto mb-4" }),
4572
4907
  loadingMessage && /* @__PURE__ */ jsx26("p", { className: "text-sec-600", children: loadingMessage })
4573
4908
  ] }) });
@@ -4576,9 +4911,9 @@ function PublicPageLayout({
4576
4911
  if (ErrorFallback) {
4577
4912
  return /* @__PURE__ */ jsx26(ErrorFallback, { error, retry: handleRefetch });
4578
4913
  }
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: [
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: [
4580
4915
  /* @__PURE__ */ jsx26("h1", { children: "Event Not Found" }),
4581
- /* @__PURE__ */ jsxs19("p", { children: [
4916
+ /* @__PURE__ */ jsxs20("p", { children: [
4582
4917
  'The event code "',
4583
4918
  eventCode,
4584
4919
  '" is invalid or the event is not available for public viewing.'
@@ -4587,13 +4922,13 @@ function PublicPageLayout({
4587
4922
  ] });
4588
4923
  }
4589
4924
  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: [
4925
+ 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
4926
  /* @__PURE__ */ jsx26("h1", { children: "Event Not Available" }),
4592
4927
  /* @__PURE__ */ jsx26("p", { children: "This event is not available for public viewing." }),
4593
4928
  handleRefetch && /* @__PURE__ */ jsx26(Button, { onClick: handleRefetch, children: "Try Again" })
4594
4929
  ] });
4595
4930
  }
4596
- return /* @__PURE__ */ jsx26(ErrorBoundary, { componentName: "PublicPageLayout", children: /* @__PURE__ */ jsxs19(Fragment7, { children: [
4931
+ return /* @__PURE__ */ jsx26(ErrorBoundary, { componentName: "PublicPageLayout", children: /* @__PURE__ */ jsxs20(Fragment9, { children: [
4597
4932
  customHeader || /* @__PURE__ */ jsx26(
4598
4933
  PublicPageHeader,
4599
4934
  {
@@ -4658,4 +4993,4 @@ export {
4658
4993
  PublicPageFooter,
4659
4994
  PublicPageLayout
4660
4995
  };
4661
- //# sourceMappingURL=chunk-YGPFYGA6.js.map
4996
+ //# sourceMappingURL=chunk-VKB2CO4Z.js.map