@jmruthers/pace-core 0.5.191 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +372 -0
  4. package/cursor-rules/01-standards-compliance.mdc +275 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +341 -0
  7. package/cursor-rules/04-testing-standards.mdc +315 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +392 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +309 -0
  11. package/cursor-rules/CHANGELOG.md +101 -0
  12. package/cursor-rules/README.md +191 -0
  13. package/dist/{AuthService-CbP_utw2.d.ts → AuthService-DjnJHDtC.d.ts} +1 -0
  14. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-CH1U5Tpy.d.ts} +1 -1
  15. package/dist/{DataTable-WKRZD47S.js → DataTable-DQ7RSOHE.js} +8 -7
  16. package/dist/{PublicPageProvider-ULXC_u6U.d.ts → PublicPageProvider-ce4xlHYA.d.ts} +37 -156
  17. package/dist/{UnifiedAuthProvider-BYA9qB-o.d.ts → UnifiedAuthProvider-185Ih4dj.d.ts} +2 -0
  18. package/dist/{UnifiedAuthProvider-FTSG5XH7.js → UnifiedAuthProvider-ATAP5UTR.js} +3 -3
  19. package/dist/{api-IHKALJZD.js → api-N774RPUA.js} +2 -2
  20. package/dist/{chunk-6C4YBBJM.js → chunk-3QRJFVBR.js} +1 -1
  21. package/dist/chunk-3QRJFVBR.js.map +1 -0
  22. package/dist/{chunk-OETXORNB.js → chunk-3XTALGJF.js} +211 -136
  23. package/dist/chunk-3XTALGJF.js.map +1 -0
  24. package/dist/{chunk-6TQDD426.js → chunk-4N5C5XZU.js} +47 -228
  25. package/dist/chunk-4N5C5XZU.js.map +1 -0
  26. package/dist/{chunk-LOMZXPSN.js → chunk-4ZC4GX36.js} +47 -74
  27. package/dist/chunk-4ZC4GX36.js.map +1 -0
  28. package/dist/{chunk-6LTQQAT6.js → chunk-BYFSK72L.js} +357 -158
  29. package/dist/chunk-BYFSK72L.js.map +1 -0
  30. package/dist/{chunk-XYXSXPUK.js → chunk-EXUD6RNJ.js} +50 -10
  31. package/dist/chunk-EXUD6RNJ.js.map +1 -0
  32. package/dist/{chunk-VKB2CO4Z.js → chunk-GLK6VM3F.js} +244 -249
  33. package/dist/chunk-GLK6VM3F.js.map +1 -0
  34. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  35. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  36. package/dist/{chunk-XNYQOL3Z.js → chunk-JBKQ3SAO.js} +9 -18
  37. package/dist/chunk-JBKQ3SAO.js.map +1 -0
  38. package/dist/{chunk-ROXMHMY2.js → chunk-KNC55RTG.js} +13 -3
  39. package/dist/{chunk-ROXMHMY2.js.map → chunk-KNC55RTG.js.map} +1 -1
  40. package/dist/{chunk-QWWZ5CAQ.js → chunk-LXQLPRQ2.js} +2 -2
  41. package/dist/{chunk-ULHIJK66.js → chunk-T33XF5ZC.js} +255 -140
  42. package/dist/chunk-T33XF5ZC.js.map +1 -0
  43. package/dist/{chunk-VRGWKHDB.js → chunk-XM25TVIE.js} +100 -33
  44. package/dist/chunk-XM25TVIE.js.map +1 -0
  45. package/dist/components.d.ts +4 -4
  46. package/dist/components.js +9 -9
  47. package/dist/hooks.d.ts +6 -6
  48. package/dist/hooks.js +20 -25
  49. package/dist/hooks.js.map +1 -1
  50. package/dist/index.d.ts +11 -11
  51. package/dist/index.js +18 -21
  52. package/dist/index.js.map +1 -1
  53. package/dist/providers.d.ts +3 -3
  54. package/dist/providers.js +2 -2
  55. package/dist/rbac/index.d.ts +2 -20
  56. package/dist/rbac/index.js +7 -9
  57. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-BJAlWfuJ.d.ts} +3 -3
  58. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  59. package/dist/utils.d.ts +1 -1
  60. package/dist/utils.js +3 -3
  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 +1 -1
  64. package/docs/api/classes/Logger.md +1 -1
  65. package/docs/api/classes/MissingUserContextError.md +1 -1
  66. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  67. package/docs/api/classes/PermissionDeniedError.md +2 -2
  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 +2 -2
  71. package/docs/api/classes/RBACError.md +1 -1
  72. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  73. package/docs/api/classes/SecureSupabaseClient.md +10 -10
  74. package/docs/api/classes/StorageUtils.md +1 -1
  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 +1 -1
  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 +1 -1
  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 +24 -11
  105. package/docs/api/interfaces/FileMetadata.md +1 -1
  106. package/docs/api/interfaces/FileReference.md +1 -1
  107. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  108. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  109. package/docs/api/interfaces/FileUploadProps.md +1 -1
  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 +2 -2
  120. package/docs/api/interfaces/NavigationContextType.md +1 -1
  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 +1 -1
  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 +1 -1
  133. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  134. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  135. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  136. package/docs/api/interfaces/PaletteData.md +1 -1
  137. package/docs/api/interfaces/ParsedAddress.md +1 -1
  138. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  139. package/docs/api/interfaces/ProgressProps.md +1 -1
  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 +2 -2
  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 +2 -2
  160. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  161. package/docs/api/interfaces/RBACRoleRevokeParams.md +2 -2
  162. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  163. package/docs/api/interfaces/RBACRoleValidateParams.md +2 -2
  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 +2 -2
  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 +1 -1
  172. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  173. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  174. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  175. package/docs/api/interfaces/RouteConfig.md +2 -2
  176. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  177. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  178. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  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 +1 -1
  182. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  183. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  184. package/docs/api/interfaces/StorageListOptions.md +1 -1
  185. package/docs/api/interfaces/StorageListResult.md +1 -1
  186. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  187. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  188. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  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 +60 -38
  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 +2 -2
  212. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  213. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  214. package/docs/api/interfaces/UserEventAccess.md +1 -1
  215. package/docs/api/interfaces/UserMenuProps.md +1 -1
  216. package/docs/api/interfaces/UserProfile.md +1 -1
  217. package/docs/api/modules.md +194 -209
  218. package/docs/getting-started/cursor-rules.md +262 -0
  219. package/docs/getting-started/installation-guide.md +6 -1
  220. package/docs/getting-started/quick-start.md +6 -1
  221. package/docs/migration/MIGRATION_GUIDE.md +4 -4
  222. package/docs/migration/REACT_19_MIGRATION.md +227 -0
  223. package/docs/migration/database-changes-december-2025.md +2 -1
  224. package/docs/rbac/event-based-apps.md +124 -6
  225. package/docs/standards/README.md +39 -0
  226. package/docs/troubleshooting/migration.md +4 -4
  227. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  228. package/package.json +11 -6
  229. package/scripts/audit-consuming-app.cjs +961 -0
  230. package/scripts/check-pace-core-compliance.cjs +315 -61
  231. package/scripts/install-cursor-rules.cjs +236 -0
  232. package/src/__tests__/helpers/test-providers.tsx +1 -1
  233. package/src/__tests__/helpers/test-utils.tsx +1 -1
  234. package/src/__tests__/rls-policies.test.ts +3 -1
  235. package/src/components/Badge/Badge.tsx +2 -4
  236. package/src/components/Button/Button.tsx +5 -4
  237. package/src/components/Calendar/Calendar.tsx +1 -1
  238. package/src/components/DataTable/DataTable.test.tsx +57 -93
  239. package/src/components/DataTable/DataTable.tsx +2 -2
  240. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +172 -45
  241. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +121 -28
  242. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +9 -8
  243. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +20 -52
  244. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +170 -34
  245. package/src/components/DataTable/__tests__/keyboard.test.tsx +75 -12
  246. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +88 -16
  247. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  248. package/src/components/DataTable/components/AccessDeniedPage.tsx +1 -1
  249. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  250. package/src/components/DataTable/components/DataTableCore.tsx +4 -7
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -1
  252. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  253. package/src/components/DataTable/components/UnifiedTableBody.tsx +86 -17
  254. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  255. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  256. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  257. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  258. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  259. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  260. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  261. package/src/components/DataTable/hooks/useColumnReordering.ts +2 -2
  262. package/src/components/DataTable/hooks/useDataTablePermissions.ts +75 -10
  263. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  264. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  265. package/src/components/Dialog/Dialog.tsx +6 -5
  266. package/src/components/ErrorBoundary/ErrorBoundary.tsx +1 -1
  267. package/src/components/EventSelector/EventSelector.tsx +1 -1
  268. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -3
  269. package/src/components/FileDisplay/FileDisplay.tsx +16 -4
  270. package/src/components/Footer/Footer.tsx +1 -1
  271. package/src/components/Form/Form.test.tsx +36 -15
  272. package/src/components/Form/Form.tsx +30 -26
  273. package/src/components/Header/Header.tsx +1 -1
  274. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  275. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  276. package/src/components/Input/Input.tsx +28 -30
  277. package/src/components/Label/Label.tsx +1 -1
  278. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  279. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  280. package/src/components/LoginForm/LoginForm.tsx +8 -8
  281. package/src/components/NavigationMenu/NavigationMenu.test.tsx +6 -4
  282. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -11
  283. package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -1
  284. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  285. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +75 -52
  286. package/src/components/PaceAppLayout/PaceAppLayout.tsx +98 -69
  287. package/src/components/PaceAppLayout/README.md +1 -1
  288. package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -8
  289. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  290. package/src/components/PasswordChange/PasswordChangeForm.tsx +1 -1
  291. package/src/components/Progress/Progress.tsx +1 -1
  292. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +5 -9
  293. package/src/components/ProtectedRoute/ProtectedRoute.tsx +0 -1
  294. package/src/components/PublicLayout/PublicPageLayout.tsx +1 -1
  295. package/src/components/PublicLayout/PublicPageProvider.tsx +0 -1
  296. package/src/components/Select/Select.tsx +33 -22
  297. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +1 -1
  298. package/src/components/Table/Table.tsx +1 -1
  299. package/src/components/Textarea/Textarea.tsx +27 -29
  300. package/src/components/Toast/Toast.tsx +1 -1
  301. package/src/components/Tooltip/Tooltip.tsx +1 -1
  302. package/src/components/UserMenu/UserMenu.tsx +1 -1
  303. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  304. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +14 -7
  305. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  306. package/src/hooks/public/usePublicEvent.ts +1 -1
  307. package/src/hooks/public/usePublicEventLogo.ts +1 -1
  308. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  309. package/src/hooks/services/useAuthService.ts +21 -3
  310. package/src/hooks/services/useEventService.ts +21 -3
  311. package/src/hooks/services/useInactivityService.ts +21 -3
  312. package/src/hooks/services/useOrganisationService.ts +21 -3
  313. package/src/hooks/useDataTableState.ts +8 -18
  314. package/src/hooks/useFileDisplay.ts +10 -17
  315. package/src/hooks/useFocusManagement.ts +2 -2
  316. package/src/hooks/useFocusTrap.ts +4 -4
  317. package/src/hooks/useFormDialog.ts +8 -7
  318. package/src/hooks/useInactivityTracker.ts +1 -1
  319. package/src/hooks/usePermissionCache.ts +1 -1
  320. package/src/hooks/useSecureDataAccess.test.ts +16 -9
  321. package/src/hooks/useSecureDataAccess.ts +22 -6
  322. package/src/hooks/useToast.ts +2 -2
  323. package/src/providers/__tests__/OrganisationProvider.test.tsx +57 -13
  324. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  325. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  326. package/src/providers/services/EventServiceProvider.tsx +0 -8
  327. package/src/providers/services/UnifiedAuthProvider.tsx +196 -46
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +13 -3
  329. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +34 -40
  330. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +82 -0
  331. package/src/rbac/adapters.tsx +3 -22
  332. package/src/rbac/api.test.ts +2 -2
  333. package/src/rbac/api.ts +7 -1
  334. package/src/rbac/components/EnhancedNavigationMenu.tsx +3 -16
  335. package/src/rbac/components/NavigationGuard.tsx +2 -11
  336. package/src/rbac/components/NavigationProvider.tsx +1 -2
  337. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  338. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  339. package/src/rbac/components/PermissionEnforcer.tsx +46 -13
  340. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  341. package/src/rbac/components/SecureDataProvider.tsx +1 -2
  342. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +7 -43
  343. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +4 -11
  344. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +3 -3
  345. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +1 -1
  346. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +1 -1
  347. package/src/rbac/engine.ts +14 -2
  348. package/src/rbac/hooks/index.ts +0 -3
  349. package/src/rbac/hooks/usePermissions.ts +51 -11
  350. package/src/rbac/hooks/useRBAC.ts +3 -13
  351. package/src/rbac/hooks/useResolvedScope.test.ts +75 -54
  352. package/src/rbac/hooks/useResolvedScope.ts +58 -33
  353. package/src/rbac/hooks/useSecureSupabase.ts +4 -9
  354. package/src/rbac/secureClient.ts +43 -0
  355. package/src/services/EventService.ts +4 -57
  356. package/src/services/InactivityService.ts +127 -34
  357. package/src/services/OrganisationService.ts +68 -10
  358. package/src/utils/security/secureDataAccess.test.ts +31 -20
  359. package/src/utils/security/secureDataAccess.ts +4 -3
  360. package/dist/chunk-6C4YBBJM.js.map +0 -1
  361. package/dist/chunk-6LTQQAT6.js.map +0 -1
  362. package/dist/chunk-6TQDD426.js.map +0 -1
  363. package/dist/chunk-LOMZXPSN.js.map +0 -1
  364. package/dist/chunk-OETXORNB.js.map +0 -1
  365. package/dist/chunk-ULHIJK66.js.map +0 -1
  366. package/dist/chunk-VKB2CO4Z.js.map +0 -1
  367. package/dist/chunk-VRGWKHDB.js.map +0 -1
  368. package/dist/chunk-XNYQOL3Z.js.map +0 -1
  369. package/dist/chunk-XYXSXPUK.js.map +0 -1
  370. package/scripts/check-pace-core-compliance.js +0 -512
  371. package/src/rbac/hooks/useSuperAdminBypass.ts +0 -126
  372. package/src/utils/context/superAdminOverride.ts +0 -58
  373. /package/dist/{DataTable-WKRZD47S.js.map → DataTable-DQ7RSOHE.js.map} +0 -0
  374. /package/dist/{UnifiedAuthProvider-FTSG5XH7.js.map → UnifiedAuthProvider-ATAP5UTR.js.map} +0 -0
  375. /package/dist/{api-IHKALJZD.js.map → api-N774RPUA.js.map} +0 -0
  376. /package/dist/{chunk-QWWZ5CAQ.js.map → chunk-LXQLPRQ2.js.map} +0 -0
  377. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  378. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  379. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  380. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -48,7 +48,7 @@ import {
48
48
  useFileReferenceById,
49
49
  useFileReferenceForRecord,
50
50
  useFilesByCategory
51
- } from "./chunk-VKB2CO4Z.js";
51
+ } from "./chunk-GLK6VM3F.js";
52
52
  import {
53
53
  Alert,
54
54
  AlertDescription,
@@ -89,24 +89,24 @@ import {
89
89
  TooltipProvider,
90
90
  TooltipRoot,
91
91
  TooltipTrigger
92
- } from "./chunk-ULHIJK66.js";
93
- import "./chunk-VRGWKHDB.js";
94
- import "./chunk-XNYQOL3Z.js";
92
+ } from "./chunk-T33XF5ZC.js";
93
+ import "./chunk-XM25TVIE.js";
94
+ import "./chunk-JBKQ3SAO.js";
95
95
  import {
96
96
  useToast
97
- } from "./chunk-6C4YBBJM.js";
97
+ } from "./chunk-3QRJFVBR.js";
98
98
  import {
99
99
  ErrorBoundary,
100
100
  PublicPageProvider,
101
101
  useIsPublicPage,
102
102
  usePublicPageContext
103
- } from "./chunk-OETXORNB.js";
103
+ } from "./chunk-3XTALGJF.js";
104
104
  import "./chunk-KQCRWDSA.js";
105
105
  import {
106
106
  UnifiedAuthProvider,
107
107
  useUnifiedAuth
108
- } from "./chunk-6LTQQAT6.js";
109
- import "./chunk-ROXMHMY2.js";
108
+ } from "./chunk-BYFSK72L.js";
109
+ import "./chunk-KNC55RTG.js";
110
110
  import "./chunk-63FOKYGO.js";
111
111
  import {
112
112
  FileCategory
@@ -117,7 +117,7 @@ import {
117
117
  fromZonedTime,
118
118
  getUserTimeZone,
119
119
  toZonedTime
120
- } from "./chunk-HW3OVDUF.js";
120
+ } from "./chunk-J36DSWQK.js";
121
121
  import {
122
122
  cn
123
123
  } from "./chunk-R77UEZ4E.js";
package/dist/hooks.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { u as useToast } from './useToast-C8gR5ir4.js';
2
- import { a as StorageUploadOptions, c as StorageUploadResult, e as StorageListOptions, f as StorageListResult, m as StorageFileInfo } from './usePublicRouteParams-TZe0gy-4.js';
3
- export { O as OrganisationSecurityHook, K as UseAppConfigReturn, U as UseFormDialogOptions, h as UseFormDialogReturn, J as UseOrganisationPermissionsReturn, H as UsePublicEventLogoOptions, G as UsePublicEventLogoReturn, C as UsePublicEventOptions, B as UsePublicEventReturn, E as UsePublicFileDisplayOptions, D as UsePublicFileDisplayReturn, I as UsePublicRouteParamsReturn, o as clearPublicEventCache, r as clearPublicFileDisplayCache, v as clearPublicLogoCache, A as extractEventCodeFromPath, z as generatePublicRoutePath, p as getPublicEventCacheStats, s as getPublicFileDisplayCacheStats, w as getPublicLogoCacheStats, k as useAppConfig, l as useEventTheme, g as useFormDialog, i as useOrganisationPermissions, j as useOrganisationSecurity, n as usePublicEvent, y as usePublicEventCode, t as usePublicEventLogo, q as usePublicFileDisplay, x as usePublicRouteParams, u as useZodForm } from './usePublicRouteParams-TZe0gy-4.js';
1
+ export { u as useToast } from './useToast-AyaT-x7p.js';
2
+ import { a as StorageUploadOptions, c as StorageUploadResult, e as StorageListOptions, f as StorageListResult, m as StorageFileInfo } from './usePublicRouteParams-BJAlWfuJ.js';
3
+ export { O as OrganisationSecurityHook, K as UseAppConfigReturn, U as UseFormDialogOptions, h as UseFormDialogReturn, J as UseOrganisationPermissionsReturn, H as UsePublicEventLogoOptions, G as UsePublicEventLogoReturn, C as UsePublicEventOptions, B as UsePublicEventReturn, E as UsePublicFileDisplayOptions, D as UsePublicFileDisplayReturn, I as UsePublicRouteParamsReturn, o as clearPublicEventCache, r as clearPublicFileDisplayCache, v as clearPublicLogoCache, A as extractEventCodeFromPath, z as generatePublicRoutePath, p as getPublicEventCacheStats, s as getPublicFileDisplayCacheStats, w as getPublicLogoCacheStats, k as useAppConfig, l as useEventTheme, g as useFormDialog, i as useOrganisationPermissions, j as useOrganisationSecurity, n as usePublicEvent, y as usePublicEventCode, t as usePublicEventLogo, q as usePublicFileDisplay, x as usePublicRouteParams, u as useZodForm } from './usePublicRouteParams-BJAlWfuJ.js';
4
4
  import * as React$1 from 'react';
5
5
  import { SortingState, ColumnFiltersState, ExpandedState } from '@tanstack/react-table';
6
6
  import { d as DataRecord, g as PerformanceConfig, S as ServerSideConfig, C as ChunkingConfig, i as SearchIndexConfig, h as PaginationMode, k as ServerSideParams, l as ServerSideResponse, A as AutocompleteOptions, m as GooglePlaceAutocompletePrediction, P as ParsedAddress } from './types-CEpcvwwF.js';
@@ -91,8 +91,8 @@ interface FocusManagementOptions {
91
91
  onFocusLast?: () => void;
92
92
  }
93
93
  interface FocusManagementReturn {
94
- containerRef: React.RefObject<HTMLDivElement>;
95
- focusRef: React.RefObject<HTMLElement>;
94
+ containerRef: React.RefObject<HTMLDivElement | null>;
95
+ focusRef: React.RefObject<HTMLElement | null>;
96
96
  setFocus: (element: HTMLElement | null) => void;
97
97
  focusFirst: () => void;
98
98
  focusLast: () => void;
@@ -117,7 +117,7 @@ interface FocusTrapOptions {
117
117
  }
118
118
  interface FocusTrapReturn {
119
119
  /** Ref to attach to the container element */
120
- containerRef: React.RefObject<HTMLElement>;
120
+ containerRef: React.RefObject<HTMLElement | null>;
121
121
  /** Focus the first focusable element */
122
122
  focusFirst: () => void;
123
123
  /** Focus the last focusable element */
package/dist/hooks.js CHANGED
@@ -7,16 +7,15 @@ import {
7
7
  getPublicLogoCacheStats,
8
8
  useFormDialog,
9
9
  useOrganisationPermissions,
10
- useOrganisationSecurity,
11
10
  usePublicEvent,
12
11
  usePublicEventCode,
13
12
  usePublicEventLogo,
14
13
  usePublicRouteParams,
15
14
  useZodForm
16
- } from "./chunk-6TQDD426.js";
15
+ } from "./chunk-4N5C5XZU.js";
17
16
  import {
18
17
  useSecureDataAccess
19
- } from "./chunk-XYXSXPUK.js";
18
+ } from "./chunk-EXUD6RNJ.js";
20
19
  import {
21
20
  archiveFile,
22
21
  cleanupQueryCache,
@@ -38,17 +37,18 @@ import {
38
37
  usePreventTabReload,
39
38
  usePublicFileDisplay,
40
39
  useQueryCache
41
- } from "./chunk-XNYQOL3Z.js";
40
+ } from "./chunk-JBKQ3SAO.js";
42
41
  import {
43
42
  useDataTablePerformance,
44
43
  useToast
45
- } from "./chunk-6C4YBBJM.js";
44
+ } from "./chunk-3QRJFVBR.js";
46
45
  import {
47
- useAppConfig
48
- } from "./chunk-OETXORNB.js";
46
+ useAppConfig,
47
+ useOrganisationSecurity
48
+ } from "./chunk-3XTALGJF.js";
49
49
  import "./chunk-KQCRWDSA.js";
50
- import "./chunk-6LTQQAT6.js";
51
- import "./chunk-ROXMHMY2.js";
50
+ import "./chunk-BYFSK72L.js";
51
+ import "./chunk-KNC55RTG.js";
52
52
  import "./chunk-63FOKYGO.js";
53
53
  import "./chunk-ZSAAAMVR.js";
54
54
  import "./chunk-QXHPKYJV.js";
@@ -208,7 +208,10 @@ function useFocusTrap(options = {}) {
208
208
  return Array.from(
209
209
  containerRef.current.querySelectorAll(focusableSelector)
210
210
  ).filter((element) => {
211
- return !element.hasAttribute("disabled") && !element.hasAttribute("hidden") && element.offsetParent !== null;
211
+ return (
212
+ // visible check
213
+ !element.hasAttribute("disabled") && !element.hasAttribute("hidden") && element.offsetParent !== null
214
+ );
212
215
  });
213
216
  }, [focusableSelector]);
214
217
  const focusFirst = useCallback2(() => {
@@ -347,7 +350,7 @@ function useIsMobile() {
347
350
  }
348
351
 
349
352
  // src/hooks/useDataTableState.ts
350
- import { useState as useState2, useCallback as useCallback4, useMemo } from "react";
353
+ import { useState as useState2, useCallback as useCallback4 } from "react";
351
354
  function useDataTableState(options) {
352
355
  const { initialPageSize = 10, data } = options;
353
356
  const [sorting, setSorting] = useState2([]);
@@ -364,20 +367,12 @@ function useDataTableState(options) {
364
367
  setPageIndex(0);
365
368
  setSelectedRows([]);
366
369
  }, [initialPageSize]);
367
- const paginatedData = useMemo(() => {
368
- const start = pageIndex * pageSize;
369
- const end = start + pageSize;
370
- return data.slice(start, end);
371
- }, [data, pageIndex, pageSize]);
372
- const totalPages = useMemo(() => {
373
- return Math.ceil(data.length / pageSize);
374
- }, [data.length, pageSize]);
375
- const hasNextPage = useMemo(() => {
376
- return pageIndex < totalPages - 1;
377
- }, [pageIndex, totalPages]);
378
- const hasPreviousPage = useMemo(() => {
379
- return pageIndex > 0;
380
- }, [pageIndex]);
370
+ const start = pageIndex * pageSize;
371
+ const end = start + pageSize;
372
+ const paginatedData = data.slice(start, end);
373
+ const totalPages = Math.ceil(data.length / pageSize);
374
+ const hasNextPage = pageIndex < totalPages - 1;
375
+ const hasPreviousPage = pageIndex > 0;
381
376
  return {
382
377
  state: {
383
378
  sorting,
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useFocusManagement.ts","../src/hooks/useFocusTrap.ts","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/useIsMobile.ts","../src/hooks/useDataTableState.ts","../src/hooks/usePerformanceMonitor.ts","../src/hooks/useFileUrlCache.ts","../src/hooks/useStorage.ts"],"sourcesContent":["\nimport { useRef, useCallback, useEffect } from 'react';\n\nexport interface FocusManagementOptions {\n trapFocus?: boolean;\n autoFocus?: boolean;\n restoreFocus?: boolean;\n onEscape?: () => void;\n onFocusFirst?: () => void;\n onFocusLast?: () => void;\n}\n\nexport interface FocusManagementReturn {\n containerRef: React.RefObject<HTMLDivElement>;\n focusRef: React.RefObject<HTMLElement>;\n setFocus: (element: HTMLElement | null) => void;\n focusFirst: () => void;\n focusLast: () => void;\n trapFocus: () => void;\n releaseFocus: () => void;\n getFocusableElements: () => HTMLElement[];\n handleEscape: (callback: () => void) => () => void;\n}\n\nexport function useFocusManagement(options: FocusManagementOptions = {}): FocusManagementReturn {\n const { \n trapFocus = false, \n autoFocus = false, \n restoreFocus = false,\n onEscape,\n onFocusFirst,\n onFocusLast \n } = options;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const focusRef = useRef<HTMLElement | null>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n const trapFocusActiveRef = useRef<boolean>(false);\n\n const setFocus = useCallback((element: HTMLElement | null) => {\n focusRef.current = element;\n element?.focus();\n }, []);\n\n const getFocusableElements = useCallback((): HTMLElement[] => {\n if (!containerRef.current) return [];\n\n return Array.from(\n containerRef.current.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n )\n ).filter((el) => !el.hasAttribute('disabled') && !el.hasAttribute('hidden'));\n }, []);\n\n const focusFirst = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n setFocus(elements[0]);\n onFocusFirst?.();\n }\n }, [getFocusableElements, setFocus, onFocusFirst]);\n\n const focusLast = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n setFocus(elements[elements.length - 1]);\n onFocusLast?.();\n }\n }, [getFocusableElements, setFocus, onFocusLast]);\n\n const trapFocusMethod = useCallback(() => {\n trapFocusActiveRef.current = true;\n }, []);\n\n const releaseFocus = useCallback(() => {\n trapFocusActiveRef.current = false;\n }, []);\n\n const handleEscape = useCallback((callback: () => void) => {\n return () => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n callback();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n };\n }, []);\n\n // Handle focus trap\n useEffect(() => {\n if (!trapFocus || !containerRef.current) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && onEscape) {\n onEscape();\n return;\n }\n\n if (event.key !== 'Tab') return;\n\n const elements = getFocusableElements();\n if (elements.length === 0) return;\n\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n\n if (event.shiftKey) {\n if (document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n }\n } else {\n if (document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n };\n\n const current = containerRef.current;\n current.addEventListener('keydown', handleKeyDown);\n return () => {\n current?.removeEventListener('keydown', handleKeyDown);\n };\n }, [trapFocus, onEscape, getFocusableElements]);\n\n // Handle auto focus\n useEffect(() => {\n if (autoFocus) {\n focusFirst();\n }\n }, [autoFocus, focusFirst]);\n\n // Handle focus restoration\n useEffect(() => {\n if (!restoreFocus) return;\n\n previousFocusRef.current = document.activeElement as HTMLElement;\n\n return () => {\n if (previousFocusRef.current) {\n previousFocusRef.current.focus();\n }\n };\n }, [restoreFocus]);\n\n return {\n containerRef,\n focusRef,\n setFocus,\n focusFirst,\n focusLast,\n trapFocus: trapFocusMethod,\n releaseFocus,\n getFocusableElements,\n handleEscape,\n };\n}\n","\nimport { useRef, useEffect, useCallback } from 'react';\n\nexport interface FocusTrapOptions {\n /** Whether the focus trap is active */\n isActive?: boolean;\n /** Whether to auto-focus the first element when activated */\n autoFocus?: boolean;\n /** Whether to restore focus to the previously focused element when deactivated */\n restoreFocus?: boolean;\n /** Callback when Escape key is pressed */\n onEscape?: () => void;\n /** Selector for focusable elements (optional override) */\n focusableSelector?: string;\n}\n\nexport interface FocusTrapReturn {\n /** Ref to attach to the container element */\n containerRef: React.RefObject<HTMLElement>;\n /** Focus the first focusable element */\n focusFirst: () => void;\n /** Focus the last focusable element */\n focusLast: () => void;\n /** Get all focusable elements in the container */\n getFocusableElements: () => HTMLElement[];\n}\n\nconst DEFAULT_FOCUSABLE_SELECTOR = [\n 'button:not([disabled])',\n '[href]',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n].join(', ');\n\n/**\n * Hook for creating accessible focus traps\n * Useful for modals, dropdowns, and other overlay components\n */\nexport function useFocusTrap(options: FocusTrapOptions = {}): FocusTrapReturn {\n const {\n isActive = false,\n autoFocus = false,\n restoreFocus = false,\n onEscape,\n focusableSelector = DEFAULT_FOCUSABLE_SELECTOR\n } = options;\n\n const containerRef = useRef<HTMLElement>(null);\n const previouslyFocusedElement = useRef<HTMLElement | null>(null);\n\n const getFocusableElements = useCallback((): HTMLElement[] => {\n if (!containerRef.current) return [];\n\n return Array.from(\n containerRef.current.querySelectorAll<HTMLElement>(focusableSelector)\n ).filter((element) => {\n return (\n !element.hasAttribute('disabled') &&\n !element.hasAttribute('hidden') &&\n element.offsetParent !== null // visible check\n );\n });\n }, [focusableSelector]);\n\n const focusFirst = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n elements[0].focus();\n }\n }, [getFocusableElements]);\n\n const focusLast = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n elements[elements.length - 1].focus();\n }\n }, [getFocusableElements]);\n\n // Handle keyboard events\n useEffect(() => {\n if (!isActive || !containerRef.current) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Handle Escape key\n if (event.key === 'Escape' && onEscape) {\n onEscape();\n return;\n }\n\n // Handle Tab key for focus trapping\n if (event.key === 'Tab') {\n const focusableElements = getFocusableElements();\n if (focusableElements.length === 0) return;\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (event.shiftKey) {\n // Shift + Tab: moving backwards\n if (document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n }\n } else {\n // Tab: moving forwards\n if (document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n }\n };\n\n const container = containerRef.current;\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n };\n }, [isActive, onEscape, getFocusableElements]);\n\n // Handle focus restoration\n useEffect(() => {\n if (!isActive) return;\n\n // Store the previously focused element\n if (restoreFocus) {\n previouslyFocusedElement.current = document.activeElement as HTMLElement;\n }\n\n // Auto-focus first element if requested\n if (autoFocus) {\n const timer = setTimeout(focusFirst, 0);\n return () => clearTimeout(timer);\n }\n\n return () => {\n // Restore focus when trap is deactivated\n if (restoreFocus && previouslyFocusedElement.current) {\n previouslyFocusedElement.current.focus();\n previouslyFocusedElement.current = null;\n }\n };\n }, [isActive, autoFocus, restoreFocus, focusFirst]);\n\n return {\n containerRef,\n focusFirst,\n focusLast,\n getFocusableElements\n };\n}\n","import { useEffect, useCallback } from 'react';\n\nexport interface KeyboardShortcut {\n /** Key combination (e.g., 'Escape', 'Enter', 'ArrowDown', 'ctrl+s') */\n key: string;\n /** Callback function to execute */\n handler: (event: KeyboardEvent) => void;\n /** Description for documentation/help */\n description?: string;\n /** Whether the shortcut is enabled */\n enabled?: boolean;\n /** Prevent default browser behavior */\n preventDefault?: boolean;\n /** Stop event propagation */\n stopPropagation?: boolean;\n}\n\nexport interface KeyboardShortcutsOptions {\n /** Element to attach listeners to (defaults to document) */\n element?: HTMLElement | Document;\n /** Whether shortcuts are globally enabled */\n enabled?: boolean;\n}\n\n/**\n * Parse key combination string into modifier and key parts\n */\nfunction parseKeyCombo(combo: string) {\n const parts = combo.toLowerCase().split('+');\n const key = parts.pop()!;\n const modifiers = {\n ctrl: parts.includes('ctrl') || parts.includes('control'),\n alt: parts.includes('alt'),\n shift: parts.includes('shift'),\n meta: parts.includes('meta') || parts.includes('cmd')\n };\n return { key, modifiers };\n}\n\n/**\n * Check if event matches the key combination\n */\nfunction matchesKeyCombo(event: KeyboardEvent, combo: string): boolean {\n const { key, modifiers } = parseKeyCombo(combo);\n \n // Check if the main key matches\n const eventKey = event.key.toLowerCase();\n const targetKey = key.toLowerCase();\n \n if (eventKey !== targetKey) {\n return false;\n }\n \n // Check modifiers\n return (\n event.ctrlKey === modifiers.ctrl &&\n event.altKey === modifiers.alt &&\n event.shiftKey === modifiers.shift &&\n event.metaKey === modifiers.meta\n );\n}\n\n/**\n * Hook for managing keyboard shortcuts\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const shortcuts = [\n * {\n * key: 'Escape',\n * handler: () => setIsOpen(false),\n * description: 'Close modal'\n * },\n * {\n * key: 'ctrl+s',\n * handler: (e) => handleSave(),\n * description: 'Save document',\n * preventDefault: true\n * }\n * ];\n * \n * useKeyboardShortcuts(shortcuts);\n * \n * return <div>Content</div>;\n * }\n * ```\n */\nexport function useKeyboardShortcuts(\n shortcuts: KeyboardShortcut[],\n options: KeyboardShortcutsOptions = {}\n): void {\n const { element = document, enabled = true } = options;\n\n const handleKeyDown = useCallback((event: KeyboardEvent) => {\n if (!enabled) return;\n\n for (const shortcut of shortcuts) {\n if (shortcut.enabled === false) continue;\n\n if (matchesKeyCombo(event, shortcut.key)) {\n if (shortcut.preventDefault) {\n event.preventDefault();\n }\n if (shortcut.stopPropagation) {\n event.stopPropagation();\n }\n \n shortcut.handler(event);\n break; // Only handle first matching shortcut\n }\n }\n }, [shortcuts, enabled]);\n\n useEffect(() => {\n if (!enabled) return;\n\n element.addEventListener('keydown', handleKeyDown as EventListener);\n return () => element.removeEventListener('keydown', handleKeyDown as EventListener);\n }, [element, enabled, handleKeyDown]);\n}\n\n/**\n * Hook for common accessibility keyboard shortcuts\n */\nexport function useAccessibilityShortcuts(handlers: {\n onEscape?: () => void;\n onEnter?: () => void;\n onSpace?: () => void;\n onArrowUp?: () => void;\n onArrowDown?: () => void;\n onArrowLeft?: () => void;\n onArrowRight?: () => void;\n onHome?: () => void;\n onEnd?: () => void;\n onTab?: () => void;\n onShiftTab?: () => void;\n}) {\n const shortcuts: KeyboardShortcut[] = [];\n\n if (handlers.onEscape) {\n shortcuts.push({\n key: 'Escape',\n handler: handlers.onEscape,\n description: 'Escape/Cancel'\n });\n }\n\n if (handlers.onEnter) {\n shortcuts.push({\n key: 'Enter',\n handler: handlers.onEnter,\n description: 'Activate/Submit'\n });\n }\n\n if (handlers.onSpace) {\n shortcuts.push({\n key: ' ',\n handler: handlers.onSpace,\n description: 'Activate',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowUp) {\n shortcuts.push({\n key: 'ArrowUp',\n handler: handlers.onArrowUp,\n description: 'Navigate up',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowDown) {\n shortcuts.push({\n key: 'ArrowDown',\n handler: handlers.onArrowDown,\n description: 'Navigate down',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowLeft) {\n shortcuts.push({\n key: 'ArrowLeft',\n handler: handlers.onArrowLeft,\n description: 'Navigate left',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowRight) {\n shortcuts.push({\n key: 'ArrowRight',\n handler: handlers.onArrowRight,\n description: 'Navigate right',\n preventDefault: true\n });\n }\n\n if (handlers.onHome) {\n shortcuts.push({\n key: 'Home',\n handler: handlers.onHome,\n description: 'Go to first item',\n preventDefault: true\n });\n }\n\n if (handlers.onEnd) {\n shortcuts.push({\n key: 'End',\n handler: handlers.onEnd,\n description: 'Go to last item',\n preventDefault: true\n });\n }\n\n if (handlers.onTab) {\n shortcuts.push({\n key: 'Tab',\n handler: handlers.onTab,\n description: 'Navigate forward'\n });\n }\n\n if (handlers.onShiftTab) {\n shortcuts.push({\n key: 'shift+Tab',\n handler: handlers.onShiftTab,\n description: 'Navigate backward'\n });\n }\n\n useKeyboardShortcuts(shortcuts);\n}\n","/**\n * @file useIsMobile Hook\n * @description Hook for detecting mobile viewport using modern matchMedia API\n */\n\nimport { useState, useEffect } from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\n/**\n * Hook to detect if the viewport is mobile-sized using matchMedia API.\n * More performant than window resize events.\n * @returns {boolean} True if mobile, false otherwise.\n */\nexport function useIsMobile(): boolean {\n const [isMobile, setIsMobile] = useState<boolean | undefined>(undefined);\n\n useEffect(() => {\n // Handle SSR case\n if (typeof window === 'undefined') {\n setIsMobile(false);\n return;\n }\n\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n \n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n\n // Set initial value\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n\n // Add event listener\n mql.addEventListener('change', onChange);\n\n // Cleanup\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n return !!isMobile;\n}\n","/**\n * @file useDataTableState Hook\n * @description Hook for managing DataTable state\n */\n\nimport { useState, useCallback, useMemo } from 'react';\nimport type { SortingState, ColumnFiltersState, ExpandedState } from '@tanstack/react-table';\n\nexport interface DataTableState {\n sorting: SortingState;\n columnFilters: ColumnFiltersState;\n expanded: ExpandedState;\n pageSize: number;\n pageIndex: number;\n selectedRows: string[];\n}\n\nexport interface DataTableActions {\n setSorting: (sorting: SortingState) => void;\n setColumnFilters: (filters: ColumnFiltersState) => void;\n setExpanded: (expanded: ExpandedState) => void;\n setPageSize: (size: number) => void;\n setPageIndex: (index: number) => void;\n setSelectedRows: (rows: string[]) => void;\n resetState: () => void;\n}\n\nexport interface DataTableComputed {\n paginatedData: any[];\n totalPages: number;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n}\n\nexport interface UseDataTableStateOptions {\n initialPageSize?: number;\n data: any[];\n}\n\n/**\n * Hook for managing DataTable state\n * @param options Configuration options\n * @returns Object containing state, actions, and computed values\n */\nexport function useDataTableState(options: UseDataTableStateOptions) {\n const { initialPageSize = 10, data } = options;\n\n // State\n const [sorting, setSorting] = useState<SortingState>([]);\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [expanded, setExpanded] = useState<ExpandedState>({});\n const [pageSize, setPageSize] = useState(initialPageSize);\n const [pageIndex, setPageIndex] = useState(0);\n const [selectedRows, setSelectedRows] = useState<string[]>([]);\n\n // Actions\n const resetState = useCallback(() => {\n setSorting([]);\n setColumnFilters([]);\n setExpanded({});\n setPageSize(initialPageSize);\n setPageIndex(0);\n setSelectedRows([]);\n }, [initialPageSize]);\n\n // Computed values\n const paginatedData = useMemo(() => {\n const start = pageIndex * pageSize;\n const end = start + pageSize;\n return data.slice(start, end);\n }, [data, pageIndex, pageSize]);\n\n const totalPages = useMemo(() => {\n return Math.ceil(data.length / pageSize);\n }, [data.length, pageSize]);\n\n const hasNextPage = useMemo(() => {\n return pageIndex < totalPages - 1;\n }, [pageIndex, totalPages]);\n\n const hasPreviousPage = useMemo(() => {\n return pageIndex > 0;\n }, [pageIndex]);\n\n return {\n state: {\n sorting,\n columnFilters,\n expanded,\n pageSize,\n pageIndex,\n selectedRows\n },\n actions: {\n setSorting,\n setColumnFilters,\n setExpanded,\n setPageSize,\n setPageIndex,\n setSelectedRows,\n resetState\n },\n computed: {\n paginatedData,\n totalPages,\n hasNextPage,\n hasPreviousPage\n }\n };\n}\n","\nimport { useEffect, useRef, useCallback } from 'react';\nimport { performanceBudgetMonitor, PERFORMANCE_BUDGETS } from '../utils/performance/performanceBudgets';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('usePerformanceMonitor');\n\nexport interface PerformanceMetrics {\n renderTime: number;\n componentName: string;\n timestamp: number;\n}\n\n/**\n * Hook for monitoring component performance with budget validation\n * @param componentName - Name of the component being monitored\n * @param enabled - Whether performance monitoring is enabled\n * @param budgetName - Performance budget to validate against\n */\nexport function usePerformanceMonitor(\n componentName: string, \n enabled = import.meta.env.MODE === 'development',\n budgetName: string = 'COMPONENT_RENDER'\n) {\n const renderStartTime = useRef<number>(0);\n const metrics = useRef<PerformanceMetrics[]>([]);\n\n // Start performance measurement\n const startMeasurement = useCallback(() => {\n if (!enabled) return;\n renderStartTime.current = performance.now();\n }, [enabled]);\n\n // End performance measurement with budget validation\n const endMeasurement = useCallback(() => {\n if (!enabled || renderStartTime.current === 0) return;\n \n const renderTime = performance.now() - renderStartTime.current;\n const metric: PerformanceMetrics = {\n renderTime,\n componentName,\n timestamp: Date.now()\n };\n \n metrics.current.push(metric);\n \n // Keep only last 10 measurements\n if (metrics.current.length > 10) {\n metrics.current = metrics.current.slice(-10);\n }\n \n // Validate against performance budget\n const measurement = performanceBudgetMonitor.measure(budgetName, renderTime, {\n componentName,\n renderCount: metrics.current.length\n });\n \n // Log slow renders in development\n if (!measurement.passed) {\n log.warn(\n `Performance budget exceeded in ${componentName}: ${renderTime.toFixed(2)}ms ` +\n `(budget: ${PERFORMANCE_BUDGETS[budgetName]?.threshold}ms)`\n );\n }\n \n renderStartTime.current = 0;\n }, [enabled, componentName, budgetName]);\n\n // Get performance metrics\n const getMetrics = useCallback(() => {\n return metrics.current.slice();\n }, []);\n\n // Get average render time\n const getAverageRenderTime = useCallback(() => {\n if (metrics.current.length === 0) return 0;\n \n const total = metrics.current.reduce((sum, metric) => sum + metric.renderTime, 0);\n return total / metrics.current.length;\n }, []);\n\n // Get performance budget status\n const getBudgetStatus = useCallback(() => {\n const budget = PERFORMANCE_BUDGETS[budgetName];\n if (!budget) return null;\n\n const averageTime = getAverageRenderTime();\n return {\n budget: budget.threshold,\n average: averageTime,\n passed: averageTime <= budget.threshold,\n efficiency: budget.threshold > 0 ? (budget.threshold - averageTime) / budget.threshold : 0\n };\n }, [budgetName, getAverageRenderTime]);\n\n // Start measurement on every render\n useEffect(() => {\n startMeasurement();\n return endMeasurement;\n });\n\n return {\n getMetrics,\n getAverageRenderTime,\n getBudgetStatus,\n startMeasurement,\n endMeasurement\n };\n}\n\n// Hook for measuring specific operations\nexport function useOperationPerformance(operationName: string, budgetName?: string) {\n const measureOperation = useCallback(async <T>(\n operation: () => Promise<T> | T,\n context?: Record<string, any>\n ): Promise<T> => {\n const start = performance.now();\n const result = await operation();\n const duration = performance.now() - start;\n \n const budget = budgetName || 'COMPONENT_RENDER';\n performanceBudgetMonitor.measure(budget, duration, {\n operation: operationName,\n ...context\n });\n \n return result;\n }, [operationName, budgetName]);\n\n return { measureOperation };\n}\n","/**\n * @file File URL Cache Hook\n * @package @jmruthers/pace-core\n * @module Hooks\n *\n * Centralized caching hook for file URLs to prevent duplicate requests\n * and improve performance across components.\n *\n * Features:\n * - TTL-based caching matching signed URL expiration (3600s)\n * - Automatic cache cleanup\n * - Supports both public and signed URLs\n * - Thread-safe cache operations\n *\n * @example\n * ```tsx\n * import { useFileUrlCache } from '@jmruthers/pace-core';\n *\n * function MyComponent() {\n * const { getUrl, setUrl, clearCache } = useFileUrlCache();\n *\n * const url = await getUrl(fileReference, supabase, organisationId);\n * return <img src={url} alt=\"File\" />;\n * }\n * ```\n */\n\nimport { useRef, useCallback } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { FileReference } from '../types/file-reference';\nimport { getPublicUrl, getSignedUrl } from '../utils/storage/helpers';\n\ninterface CachedUrl {\n url: string;\n expiresAt: number; // Timestamp in milliseconds\n}\n\n// Global cache shared across all hook instances\nconst globalUrlCache = new Map<string, CachedUrl>();\n\n// Cache size limit to prevent memory leaks\nconst MAX_CACHE_SIZE = 500;\n\n// Default TTL matches signed URL expiration (3600 seconds = 1 hour)\nconst DEFAULT_TTL_MS = 3600 * 1000;\n\n/**\n * Generate cache key from file reference\n */\nfunction getCacheKey(fileReference: FileReference): string {\n return `file-url:${fileReference.id}:${fileReference.is_public ? 'public' : 'private'}`;\n}\n\n/**\n * Clean up expired entries and enforce size limit\n */\nfunction cleanupCache(): void {\n const now = Date.now();\n \n // Remove expired entries\n for (const [key, value] of globalUrlCache.entries()) {\n if (value.expiresAt < now) {\n globalUrlCache.delete(key);\n }\n }\n \n // Enforce size limit by removing oldest entries\n if (globalUrlCache.size > MAX_CACHE_SIZE) {\n const entries = Array.from(globalUrlCache.entries());\n // Sort by expiration time (oldest first)\n entries.sort((a, b) => a[1].expiresAt - b[1].expiresAt);\n \n // Remove oldest 20% of entries\n const toRemove = Math.floor(MAX_CACHE_SIZE * 0.2);\n for (let i = 0; i < toRemove && i < entries.length; i++) {\n globalUrlCache.delete(entries[i][0]);\n }\n }\n}\n\nexport interface UseFileUrlCacheReturn {\n /**\n * Get URL for a file reference, using cache if available\n * @param fileReference - File reference to get URL for\n * @param supabase - Supabase client instance\n * @param organisationId - Organisation ID for signed URLs\n * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)\n * @returns Promise resolving to URL string or null\n */\n getUrl: (\n fileReference: FileReference,\n supabase: SupabaseClient,\n organisationId: string,\n ttl?: number\n ) => Promise<string | null>;\n \n /**\n * Set URL in cache\n * @param fileReference - File reference\n * @param url - URL to cache\n * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)\n */\n setUrl: (fileReference: FileReference, url: string, ttl?: number) => void;\n \n /**\n * Get URL from cache without generating if missing\n * @param fileReference - File reference\n * @returns Cached URL or null if not in cache or expired\n */\n getCachedUrl: (fileReference: FileReference) => string | null;\n \n /**\n * Clear cache for a specific file reference\n * @param fileReference - File reference to clear\n */\n clearFile: (fileReference: FileReference) => void;\n \n /**\n * Clear all cached URLs\n */\n clearCache: () => void;\n \n /**\n * Get cache statistics\n */\n getCacheStats: () => { size: number; maxSize: number };\n}\n\n/**\n * Hook for centralized file URL caching\n * \n * This hook provides a shared cache for file URLs across all components,\n * preventing duplicate requests for the same file.\n * \n * @returns Cache operations and utilities\n */\nexport function useFileUrlCache(): UseFileUrlCacheReturn {\n // Use ref to ensure stable reference across renders\n const cleanupIntervalRef = useRef<number | null>(null);\n \n // Set up periodic cleanup (every 5 minutes)\n if (cleanupIntervalRef.current === null && typeof window !== 'undefined') {\n cleanupIntervalRef.current = window.setInterval(() => {\n cleanupCache();\n }, 5 * 60 * 1000); // 5 minutes\n }\n \n const getUrl = useCallback(async (\n fileReference: FileReference,\n supabase: SupabaseClient,\n organisationId: string,\n ttl: number = DEFAULT_TTL_MS\n ): Promise<string | null> => {\n const cacheKey = getCacheKey(fileReference);\n const cached = globalUrlCache.get(cacheKey);\n const now = Date.now();\n \n // Return cached URL if still valid\n if (cached && cached.expiresAt > now) {\n return cached.url;\n }\n \n // Generate new URL\n let url: string | null = null;\n \n try {\n if (fileReference.is_public) {\n // Public files: generate public URL (synchronous)\n url = getPublicUrl(supabase, fileReference.file_path, true);\n } else {\n // Private files: generate signed URL (async)\n const signedUrlResult = await getSignedUrl(supabase, fileReference.file_path, {\n appName: 'pace-core',\n orgId: organisationId,\n expiresIn: Math.floor(ttl / 1000) // Convert ms to seconds\n });\n url = signedUrlResult?.url || null;\n }\n \n // Cache the URL if generated successfully\n if (url) {\n globalUrlCache.set(cacheKey, {\n url,\n expiresAt: now + ttl\n });\n cleanupCache(); // Clean up after adding\n }\n \n return url;\n } catch (error) {\n console.error('Failed to generate file URL:', error);\n return null;\n }\n }, []);\n \n const setUrl = useCallback((\n fileReference: FileReference,\n url: string,\n ttl: number = DEFAULT_TTL_MS\n ): void => {\n const cacheKey = getCacheKey(fileReference);\n globalUrlCache.set(cacheKey, {\n url,\n expiresAt: Date.now() + ttl\n });\n cleanupCache();\n }, []);\n \n const getCachedUrl = useCallback((fileReference: FileReference): string | null => {\n const cacheKey = getCacheKey(fileReference);\n const cached = globalUrlCache.get(cacheKey);\n const now = Date.now();\n \n if (cached && cached.expiresAt > now) {\n return cached.url;\n }\n \n return null;\n }, []);\n \n const clearFile = useCallback((fileReference: FileReference): void => {\n const cacheKey = getCacheKey(fileReference);\n globalUrlCache.delete(cacheKey);\n }, []);\n \n const clearCache = useCallback((): void => {\n globalUrlCache.clear();\n }, []);\n \n const getCacheStats = useCallback(() => {\n return {\n size: globalUrlCache.size,\n maxSize: MAX_CACHE_SIZE\n };\n }, []);\n \n return {\n getUrl,\n setUrl,\n getCachedUrl,\n clearFile,\n clearCache,\n getCacheStats\n };\n}\n\n","/**\n * React hook for storage operations\n */\n\nimport { useState, useCallback } from 'react';\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { \n StorageUploadOptions, \n StorageUploadResult, \n StorageFileInfo,\n StorageListOptions,\n StorageListResult,\n uploadFile,\n getPublicUrl,\n getSignedUrl,\n deleteFile,\n listFiles,\n archiveFile\n} from '../utils/storage';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('useStorage');\n\nexport interface UseStorageOptions {\n supabase: SupabaseClient;\n appName: string;\n orgId: string;\n}\n\nexport interface UseStorageReturn {\n // Upload\n uploadFile: (file: File, options?: Partial<StorageUploadOptions>) => Promise<StorageUploadResult>;\n isUploading: boolean;\n uploadError: string | null;\n \n // URLs\n getPublicUrl: (path: string) => string;\n getSignedUrl: (path: string, expiresIn?: number) => Promise<string | null>;\n getFileUrl: (path: string) => string; // Alias for getPublicUrl\n \n // File management\n deleteFile: (path: string) => Promise<{ success: boolean; error?: string }>;\n archiveFile: (path: string) => Promise<{ success: boolean; error?: string }>;\n \n // Listing\n listFiles: (options?: Partial<StorageListOptions>) => Promise<StorageListResult>;\n isListing: boolean;\n listError: string | null;\n isLoading: boolean; // Alias for isListing\n error: string | null; // Alias for listError\n \n // State\n files: StorageFileInfo[];\n refreshFiles: () => Promise<void>;\n}\n\n/**\n * Hook for storage operations with app and organisation context\n */\nexport function useStorage({ supabase, appName, orgId }: UseStorageOptions): UseStorageReturn {\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [isListing, setIsListing] = useState(false);\n const [listError, setListError] = useState<string | null>(null);\n const [files, setFiles] = useState<StorageFileInfo[]>([]);\n\n // Upload file\n const handleUploadFile = useCallback(async (\n file: File, \n options: Partial<StorageUploadOptions> = {}\n ): Promise<StorageUploadResult> => {\n setIsUploading(true);\n setUploadError(null);\n\n try {\n const uploadOptions: StorageUploadOptions = {\n appName,\n orgId,\n isPublic: false,\n ...options\n };\n\n const result = await uploadFile(supabase, file, uploadOptions);\n \n if (result.success) {\n // Refresh file list\n await refreshFiles();\n } else {\n setUploadError(result.error || 'Upload failed');\n }\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Upload failed';\n setUploadError(errorMessage);\n return {\n success: false,\n error: errorMessage\n };\n } finally {\n setIsUploading(false);\n }\n }, [supabase, appName, orgId]);\n\n // Get public URL\n const handleGetPublicUrl = useCallback((path: string): string => {\n return getPublicUrl(supabase, path);\n }, [supabase]);\n\n // Get signed URL\n const handleGetSignedUrl = useCallback(async (\n path: string, \n expiresIn?: number\n ): Promise<string | null> => {\n try {\n const result = await getSignedUrl(supabase, path, {\n appName,\n orgId,\n expiresIn\n });\n return result?.url || null;\n } catch (error) {\n log.error('Failed to get signed URL:', error);\n return null;\n }\n }, [supabase, appName, orgId]);\n\n // Delete file\n const handleDeleteFile = useCallback(async (path: string) => {\n try {\n const result = await deleteFile(supabase, path);\n if (result.success) {\n await refreshFiles();\n }\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Delete failed'\n };\n }\n }, [supabase]);\n\n // Archive file\n const handleArchiveFile = useCallback(async (path: string) => {\n try {\n const result = await archiveFile(supabase, path, { appName, orgId });\n if (result.success) {\n await refreshFiles();\n }\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Archive failed'\n };\n }\n }, [supabase, appName, orgId]);\n\n // List files\n const handleListFiles = useCallback(async (\n options: Partial<StorageListOptions> = {}\n ): Promise<StorageListResult> => {\n setIsListing(true);\n setListError(null);\n\n try {\n const listOptions: StorageListOptions = {\n appName,\n orgId,\n ...options\n };\n\n const result = await listFiles(supabase, listOptions);\n setFiles(result.files);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'List failed';\n setListError(errorMessage);\n return { files: [], totalCount: 0, hasMore: false };\n } finally {\n setIsListing(false);\n }\n }, [supabase, appName, orgId]);\n\n // Refresh files\n const refreshFiles = useCallback(async () => {\n await handleListFiles();\n }, [handleListFiles]);\n\n return {\n // Upload\n uploadFile: handleUploadFile,\n isUploading,\n uploadError,\n \n // URLs\n getPublicUrl: handleGetPublicUrl,\n getSignedUrl: handleGetSignedUrl,\n getFileUrl: handleGetPublicUrl, // Alias for getPublicUrl\n \n // File management\n deleteFile: handleDeleteFile,\n archiveFile: handleArchiveFile,\n \n // Listing\n listFiles: handleListFiles,\n isListing,\n listError,\n isLoading: isListing, // Alias for isListing\n error: listError, // Alias for listError\n \n // State\n files,\n refreshFiles\n };\n}\n\n/**\n * Hook for file upload with progress tracking\n */\nexport function useFileUpload({ supabase, appName, orgId }: UseStorageOptions) {\n const [uploadProgress, setUploadProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n\n const uploadWithProgress = useCallback(async (\n file: File,\n options: Partial<StorageUploadOptions> = {}\n ): Promise<StorageUploadResult> => {\n setIsUploading(true);\n setUploadProgress(0);\n setUploadError(null);\n\n try {\n // Simulate progress (Supabase doesn't provide real progress)\n const progressInterval = setInterval(() => {\n setUploadProgress(prev => Math.min(prev + 10, 90));\n }, 100);\n\n const uploadOptions: StorageUploadOptions = {\n appName,\n orgId,\n isPublic: false,\n ...options\n };\n\n const result = await uploadFile(supabase, file, uploadOptions);\n \n clearInterval(progressInterval);\n setUploadProgress(100);\n\n if (!result.success) {\n setUploadError(result.error || 'Upload failed');\n }\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Upload failed';\n setUploadError(errorMessage);\n return {\n success: false,\n error: errorMessage\n };\n } finally {\n setIsUploading(false);\n setTimeout(() => setUploadProgress(0), 1000);\n }\n }, [supabase, appName, orgId]);\n\n return {\n uploadWithProgress,\n uploadProgress,\n isUploading,\n uploadError\n };\n}\n"],"mappings":"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","names":["useRef","useEffect","useCallback","useEffect","useCallback","useEffect","useState","useCallback","useEffect","useRef","useCallback","useRef","useCallback","useEffect","useRef","useCallback","useRef","useCallback","useState","useCallback","log","useState","useCallback"]}
1
+ {"version":3,"sources":["../src/hooks/useFocusManagement.ts","../src/hooks/useFocusTrap.ts","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/useIsMobile.ts","../src/hooks/useDataTableState.ts","../src/hooks/usePerformanceMonitor.ts","../src/hooks/useFileUrlCache.ts","../src/hooks/useStorage.ts"],"sourcesContent":["\nimport { useRef, useCallback, useEffect } from 'react';\n\nexport interface FocusManagementOptions {\n trapFocus?: boolean;\n autoFocus?: boolean;\n restoreFocus?: boolean;\n onEscape?: () => void;\n onFocusFirst?: () => void;\n onFocusLast?: () => void;\n}\n\nexport interface FocusManagementReturn {\n containerRef: React.RefObject<HTMLDivElement | null>;\n focusRef: React.RefObject<HTMLElement | null>;\n setFocus: (element: HTMLElement | null) => void;\n focusFirst: () => void;\n focusLast: () => void;\n trapFocus: () => void;\n releaseFocus: () => void;\n getFocusableElements: () => HTMLElement[];\n handleEscape: (callback: () => void) => () => void;\n}\n\nexport function useFocusManagement(options: FocusManagementOptions = {}): FocusManagementReturn {\n const { \n trapFocus = false, \n autoFocus = false, \n restoreFocus = false,\n onEscape,\n onFocusFirst,\n onFocusLast \n } = options;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const focusRef = useRef<HTMLElement | null>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n const trapFocusActiveRef = useRef<boolean>(false);\n\n const setFocus = useCallback((element: HTMLElement | null) => {\n focusRef.current = element;\n element?.focus();\n }, []);\n\n const getFocusableElements = useCallback((): HTMLElement[] => {\n if (!containerRef.current) return [];\n\n return Array.from(\n containerRef.current.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n )\n ).filter((el) => !el.hasAttribute('disabled') && !el.hasAttribute('hidden'));\n }, []);\n\n const focusFirst = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n setFocus(elements[0]);\n onFocusFirst?.();\n }\n }, [getFocusableElements, setFocus, onFocusFirst]);\n\n const focusLast = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n setFocus(elements[elements.length - 1]);\n onFocusLast?.();\n }\n }, [getFocusableElements, setFocus, onFocusLast]);\n\n const trapFocusMethod = useCallback(() => {\n trapFocusActiveRef.current = true;\n }, []);\n\n const releaseFocus = useCallback(() => {\n trapFocusActiveRef.current = false;\n }, []);\n\n const handleEscape = useCallback((callback: () => void) => {\n return () => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n callback();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n };\n }, []);\n\n // Handle focus trap\n useEffect(() => {\n if (!trapFocus || !containerRef.current) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && onEscape) {\n onEscape();\n return;\n }\n\n if (event.key !== 'Tab') return;\n\n const elements = getFocusableElements();\n if (elements.length === 0) return;\n\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n\n if (event.shiftKey) {\n if (document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n }\n } else {\n if (document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n };\n\n const current = containerRef.current;\n current.addEventListener('keydown', handleKeyDown);\n return () => {\n current?.removeEventListener('keydown', handleKeyDown);\n };\n }, [trapFocus, onEscape, getFocusableElements]);\n\n // Handle auto focus\n useEffect(() => {\n if (autoFocus) {\n focusFirst();\n }\n }, [autoFocus, focusFirst]);\n\n // Handle focus restoration\n useEffect(() => {\n if (!restoreFocus) return;\n\n previousFocusRef.current = document.activeElement as HTMLElement;\n\n return () => {\n if (previousFocusRef.current) {\n previousFocusRef.current.focus();\n }\n };\n }, [restoreFocus]);\n\n return {\n containerRef,\n focusRef,\n setFocus,\n focusFirst,\n focusLast,\n trapFocus: trapFocusMethod,\n releaseFocus,\n getFocusableElements,\n handleEscape,\n };\n}\n","\nimport { useRef, useEffect, useCallback } from 'react';\n\nexport interface FocusTrapOptions {\n /** Whether the focus trap is active */\n isActive?: boolean;\n /** Whether to auto-focus the first element when activated */\n autoFocus?: boolean;\n /** Whether to restore focus to the previously focused element when deactivated */\n restoreFocus?: boolean;\n /** Callback when Escape key is pressed */\n onEscape?: () => void;\n /** Selector for focusable elements (optional override) */\n focusableSelector?: string;\n}\n\nexport interface FocusTrapReturn {\n /** Ref to attach to the container element */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Focus the first focusable element */\n focusFirst: () => void;\n /** Focus the last focusable element */\n focusLast: () => void;\n /** Get all focusable elements in the container */\n getFocusableElements: () => HTMLElement[];\n}\n\nconst DEFAULT_FOCUSABLE_SELECTOR = [\n 'button:not([disabled])',\n '[href]',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]'\n].join(', ');\n\n/**\n * Hook for creating accessible focus traps\n * Useful for modals, dropdowns, and other overlay components\n */\nexport function useFocusTrap(options: FocusTrapOptions = {}): FocusTrapReturn {\n const {\n isActive = false,\n autoFocus = false,\n restoreFocus = false,\n onEscape,\n focusableSelector = DEFAULT_FOCUSABLE_SELECTOR\n } = options;\n\n const containerRef = useRef<HTMLElement>(null);\n const previouslyFocusedElement = useRef<HTMLElement | null>(null);\n\n const getFocusableElements = useCallback((): HTMLElement[] => {\n if (!containerRef.current) return [];\n\n return Array.from(\n containerRef.current.querySelectorAll<HTMLElement>(focusableSelector)\n ).filter((element) => {\n return (\n // visible check\n (!element.hasAttribute('disabled') &&\n !element.hasAttribute('hidden') && element.offsetParent !== null)\n );\n });\n }, [focusableSelector]);\n\n const focusFirst = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n elements[0].focus();\n }\n }, [getFocusableElements]);\n\n const focusLast = useCallback(() => {\n const elements = getFocusableElements();\n if (elements.length > 0) {\n elements[elements.length - 1].focus();\n }\n }, [getFocusableElements]);\n\n // Handle keyboard events\n useEffect(() => {\n if (!isActive || !containerRef.current) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Handle Escape key\n if (event.key === 'Escape' && onEscape) {\n onEscape();\n return;\n }\n\n // Handle Tab key for focus trapping\n if (event.key === 'Tab') {\n const focusableElements = getFocusableElements();\n if (focusableElements.length === 0) return;\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (event.shiftKey) {\n // Shift + Tab: moving backwards\n if (document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n }\n } else {\n // Tab: moving forwards\n if (document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n }\n };\n\n const container = containerRef.current;\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n };\n }, [isActive, onEscape, getFocusableElements]);\n\n // Handle focus restoration\n useEffect(() => {\n if (!isActive) return;\n\n // Store the previously focused element\n if (restoreFocus) {\n previouslyFocusedElement.current = document.activeElement as HTMLElement;\n }\n\n // Auto-focus first element if requested\n if (autoFocus) {\n const timer = setTimeout(focusFirst, 0);\n return () => clearTimeout(timer);\n }\n\n return () => {\n // Restore focus when trap is deactivated\n if (restoreFocus && previouslyFocusedElement.current) {\n previouslyFocusedElement.current.focus();\n previouslyFocusedElement.current = null;\n }\n };\n }, [isActive, autoFocus, restoreFocus, focusFirst]);\n\n return {\n containerRef,\n focusFirst,\n focusLast,\n getFocusableElements\n };\n}\n","import { useEffect, useCallback } from 'react';\n\nexport interface KeyboardShortcut {\n /** Key combination (e.g., 'Escape', 'Enter', 'ArrowDown', 'ctrl+s') */\n key: string;\n /** Callback function to execute */\n handler: (event: KeyboardEvent) => void;\n /** Description for documentation/help */\n description?: string;\n /** Whether the shortcut is enabled */\n enabled?: boolean;\n /** Prevent default browser behavior */\n preventDefault?: boolean;\n /** Stop event propagation */\n stopPropagation?: boolean;\n}\n\nexport interface KeyboardShortcutsOptions {\n /** Element to attach listeners to (defaults to document) */\n element?: HTMLElement | Document;\n /** Whether shortcuts are globally enabled */\n enabled?: boolean;\n}\n\n/**\n * Parse key combination string into modifier and key parts\n */\nfunction parseKeyCombo(combo: string) {\n const parts = combo.toLowerCase().split('+');\n const key = parts.pop()!;\n const modifiers = {\n ctrl: parts.includes('ctrl') || parts.includes('control'),\n alt: parts.includes('alt'),\n shift: parts.includes('shift'),\n meta: parts.includes('meta') || parts.includes('cmd')\n };\n return { key, modifiers };\n}\n\n/**\n * Check if event matches the key combination\n */\nfunction matchesKeyCombo(event: KeyboardEvent, combo: string): boolean {\n const { key, modifiers } = parseKeyCombo(combo);\n \n // Check if the main key matches\n const eventKey = event.key.toLowerCase();\n const targetKey = key.toLowerCase();\n \n if (eventKey !== targetKey) {\n return false;\n }\n \n // Check modifiers\n return (\n event.ctrlKey === modifiers.ctrl &&\n event.altKey === modifiers.alt &&\n event.shiftKey === modifiers.shift &&\n event.metaKey === modifiers.meta\n );\n}\n\n/**\n * Hook for managing keyboard shortcuts\n * \n * @example\n * ```tsx\n * function MyComponent() {\n * const shortcuts = [\n * {\n * key: 'Escape',\n * handler: () => setIsOpen(false),\n * description: 'Close modal'\n * },\n * {\n * key: 'ctrl+s',\n * handler: (e) => handleSave(),\n * description: 'Save document',\n * preventDefault: true\n * }\n * ];\n * \n * useKeyboardShortcuts(shortcuts);\n * \n * return <div>Content</div>;\n * }\n * ```\n */\nexport function useKeyboardShortcuts(\n shortcuts: KeyboardShortcut[],\n options: KeyboardShortcutsOptions = {}\n): void {\n const { element = document, enabled = true } = options;\n\n const handleKeyDown = useCallback((event: KeyboardEvent) => {\n if (!enabled) return;\n\n for (const shortcut of shortcuts) {\n if (shortcut.enabled === false) continue;\n\n if (matchesKeyCombo(event, shortcut.key)) {\n if (shortcut.preventDefault) {\n event.preventDefault();\n }\n if (shortcut.stopPropagation) {\n event.stopPropagation();\n }\n \n shortcut.handler(event);\n break; // Only handle first matching shortcut\n }\n }\n }, [shortcuts, enabled]);\n\n useEffect(() => {\n if (!enabled) return;\n\n element.addEventListener('keydown', handleKeyDown as EventListener);\n return () => element.removeEventListener('keydown', handleKeyDown as EventListener);\n }, [element, enabled, handleKeyDown]);\n}\n\n/**\n * Hook for common accessibility keyboard shortcuts\n */\nexport function useAccessibilityShortcuts(handlers: {\n onEscape?: () => void;\n onEnter?: () => void;\n onSpace?: () => void;\n onArrowUp?: () => void;\n onArrowDown?: () => void;\n onArrowLeft?: () => void;\n onArrowRight?: () => void;\n onHome?: () => void;\n onEnd?: () => void;\n onTab?: () => void;\n onShiftTab?: () => void;\n}) {\n const shortcuts: KeyboardShortcut[] = [];\n\n if (handlers.onEscape) {\n shortcuts.push({\n key: 'Escape',\n handler: handlers.onEscape,\n description: 'Escape/Cancel'\n });\n }\n\n if (handlers.onEnter) {\n shortcuts.push({\n key: 'Enter',\n handler: handlers.onEnter,\n description: 'Activate/Submit'\n });\n }\n\n if (handlers.onSpace) {\n shortcuts.push({\n key: ' ',\n handler: handlers.onSpace,\n description: 'Activate',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowUp) {\n shortcuts.push({\n key: 'ArrowUp',\n handler: handlers.onArrowUp,\n description: 'Navigate up',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowDown) {\n shortcuts.push({\n key: 'ArrowDown',\n handler: handlers.onArrowDown,\n description: 'Navigate down',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowLeft) {\n shortcuts.push({\n key: 'ArrowLeft',\n handler: handlers.onArrowLeft,\n description: 'Navigate left',\n preventDefault: true\n });\n }\n\n if (handlers.onArrowRight) {\n shortcuts.push({\n key: 'ArrowRight',\n handler: handlers.onArrowRight,\n description: 'Navigate right',\n preventDefault: true\n });\n }\n\n if (handlers.onHome) {\n shortcuts.push({\n key: 'Home',\n handler: handlers.onHome,\n description: 'Go to first item',\n preventDefault: true\n });\n }\n\n if (handlers.onEnd) {\n shortcuts.push({\n key: 'End',\n handler: handlers.onEnd,\n description: 'Go to last item',\n preventDefault: true\n });\n }\n\n if (handlers.onTab) {\n shortcuts.push({\n key: 'Tab',\n handler: handlers.onTab,\n description: 'Navigate forward'\n });\n }\n\n if (handlers.onShiftTab) {\n shortcuts.push({\n key: 'shift+Tab',\n handler: handlers.onShiftTab,\n description: 'Navigate backward'\n });\n }\n\n useKeyboardShortcuts(shortcuts);\n}\n","/**\n * @file useIsMobile Hook\n * @description Hook for detecting mobile viewport using modern matchMedia API\n */\n\nimport { useState, useEffect } from 'react';\n\nconst MOBILE_BREAKPOINT = 768;\n\n/**\n * Hook to detect if the viewport is mobile-sized using matchMedia API.\n * More performant than window resize events.\n * @returns {boolean} True if mobile, false otherwise.\n */\nexport function useIsMobile(): boolean {\n const [isMobile, setIsMobile] = useState<boolean | undefined>(undefined);\n\n useEffect(() => {\n // Handle SSR case\n if (typeof window === 'undefined') {\n setIsMobile(false);\n return;\n }\n\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n \n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n\n // Set initial value\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n\n // Add event listener\n mql.addEventListener('change', onChange);\n\n // Cleanup\n return () => mql.removeEventListener('change', onChange);\n }, []);\n\n return !!isMobile;\n}\n","/**\n * @file useDataTableState Hook\n * @description Hook for managing DataTable state\n */\n\nimport { useState, useCallback } from 'react';\nimport type { SortingState, ColumnFiltersState, ExpandedState } from '@tanstack/react-table';\n\nexport interface DataTableState {\n sorting: SortingState;\n columnFilters: ColumnFiltersState;\n expanded: ExpandedState;\n pageSize: number;\n pageIndex: number;\n selectedRows: string[];\n}\n\nexport interface DataTableActions {\n setSorting: (sorting: SortingState) => void;\n setColumnFilters: (filters: ColumnFiltersState) => void;\n setExpanded: (expanded: ExpandedState) => void;\n setPageSize: (size: number) => void;\n setPageIndex: (index: number) => void;\n setSelectedRows: (rows: string[]) => void;\n resetState: () => void;\n}\n\nexport interface DataTableComputed {\n paginatedData: any[];\n totalPages: number;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n}\n\nexport interface UseDataTableStateOptions {\n initialPageSize?: number;\n data: any[];\n}\n\n/**\n * Hook for managing DataTable state\n * @param options Configuration options\n * @returns Object containing state, actions, and computed values\n */\nexport function useDataTableState(options: UseDataTableStateOptions) {\n const { initialPageSize = 10, data } = options;\n\n // State\n const [sorting, setSorting] = useState<SortingState>([]);\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [expanded, setExpanded] = useState<ExpandedState>({});\n const [pageSize, setPageSize] = useState(initialPageSize);\n const [pageIndex, setPageIndex] = useState(0);\n const [selectedRows, setSelectedRows] = useState<string[]>([]);\n\n // Actions\n const resetState = useCallback(() => {\n setSorting([]);\n setColumnFilters([]);\n setExpanded({});\n setPageSize(initialPageSize);\n setPageIndex(0);\n setSelectedRows([]);\n }, [initialPageSize]);\n\n // Computed values - React Compiler handles memoization automatically\n const start = pageIndex * pageSize;\n const end = start + pageSize;\n const paginatedData = data.slice(start, end);\n\n const totalPages = Math.ceil(data.length / pageSize);\n const hasNextPage = pageIndex < totalPages - 1;\n const hasPreviousPage = pageIndex > 0;\n\n return {\n state: {\n sorting,\n columnFilters,\n expanded,\n pageSize,\n pageIndex,\n selectedRows\n },\n actions: {\n setSorting,\n setColumnFilters,\n setExpanded,\n setPageSize,\n setPageIndex,\n setSelectedRows,\n resetState\n },\n computed: {\n paginatedData,\n totalPages,\n hasNextPage,\n hasPreviousPage\n }\n };\n}\n","\nimport { useEffect, useRef, useCallback } from 'react';\nimport { performanceBudgetMonitor, PERFORMANCE_BUDGETS } from '../utils/performance/performanceBudgets';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('usePerformanceMonitor');\n\nexport interface PerformanceMetrics {\n renderTime: number;\n componentName: string;\n timestamp: number;\n}\n\n/**\n * Hook for monitoring component performance with budget validation\n * @param componentName - Name of the component being monitored\n * @param enabled - Whether performance monitoring is enabled\n * @param budgetName - Performance budget to validate against\n */\nexport function usePerformanceMonitor(\n componentName: string, \n enabled = import.meta.env.MODE === 'development',\n budgetName: string = 'COMPONENT_RENDER'\n) {\n const renderStartTime = useRef<number>(0);\n const metrics = useRef<PerformanceMetrics[]>([]);\n\n // Start performance measurement\n const startMeasurement = useCallback(() => {\n if (!enabled) return;\n renderStartTime.current = performance.now();\n }, [enabled]);\n\n // End performance measurement with budget validation\n const endMeasurement = useCallback(() => {\n if (!enabled || renderStartTime.current === 0) return;\n \n const renderTime = performance.now() - renderStartTime.current;\n const metric: PerformanceMetrics = {\n renderTime,\n componentName,\n timestamp: Date.now()\n };\n \n metrics.current.push(metric);\n \n // Keep only last 10 measurements\n if (metrics.current.length > 10) {\n metrics.current = metrics.current.slice(-10);\n }\n \n // Validate against performance budget\n const measurement = performanceBudgetMonitor.measure(budgetName, renderTime, {\n componentName,\n renderCount: metrics.current.length\n });\n \n // Log slow renders in development\n if (!measurement.passed) {\n log.warn(\n `Performance budget exceeded in ${componentName}: ${renderTime.toFixed(2)}ms ` +\n `(budget: ${PERFORMANCE_BUDGETS[budgetName]?.threshold}ms)`\n );\n }\n \n renderStartTime.current = 0;\n }, [enabled, componentName, budgetName]);\n\n // Get performance metrics\n const getMetrics = useCallback(() => {\n return metrics.current.slice();\n }, []);\n\n // Get average render time\n const getAverageRenderTime = useCallback(() => {\n if (metrics.current.length === 0) return 0;\n \n const total = metrics.current.reduce((sum, metric) => sum + metric.renderTime, 0);\n return total / metrics.current.length;\n }, []);\n\n // Get performance budget status\n const getBudgetStatus = useCallback(() => {\n const budget = PERFORMANCE_BUDGETS[budgetName];\n if (!budget) return null;\n\n const averageTime = getAverageRenderTime();\n return {\n budget: budget.threshold,\n average: averageTime,\n passed: averageTime <= budget.threshold,\n efficiency: budget.threshold > 0 ? (budget.threshold - averageTime) / budget.threshold : 0\n };\n }, [budgetName, getAverageRenderTime]);\n\n // Start measurement on every render\n useEffect(() => {\n startMeasurement();\n return endMeasurement;\n });\n\n return {\n getMetrics,\n getAverageRenderTime,\n getBudgetStatus,\n startMeasurement,\n endMeasurement\n };\n}\n\n// Hook for measuring specific operations\nexport function useOperationPerformance(operationName: string, budgetName?: string) {\n const measureOperation = useCallback(async <T>(\n operation: () => Promise<T> | T,\n context?: Record<string, any>\n ): Promise<T> => {\n const start = performance.now();\n const result = await operation();\n const duration = performance.now() - start;\n \n const budget = budgetName || 'COMPONENT_RENDER';\n performanceBudgetMonitor.measure(budget, duration, {\n operation: operationName,\n ...context\n });\n \n return result;\n }, [operationName, budgetName]);\n\n return { measureOperation };\n}\n","/**\n * @file File URL Cache Hook\n * @package @jmruthers/pace-core\n * @module Hooks\n *\n * Centralized caching hook for file URLs to prevent duplicate requests\n * and improve performance across components.\n *\n * Features:\n * - TTL-based caching matching signed URL expiration (3600s)\n * - Automatic cache cleanup\n * - Supports both public and signed URLs\n * - Thread-safe cache operations\n *\n * @example\n * ```tsx\n * import { useFileUrlCache } from '@jmruthers/pace-core';\n *\n * function MyComponent() {\n * const { getUrl, setUrl, clearCache } = useFileUrlCache();\n *\n * const url = await getUrl(fileReference, supabase, organisationId);\n * return <img src={url} alt=\"File\" />;\n * }\n * ```\n */\n\nimport { useRef, useCallback } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport { FileReference } from '../types/file-reference';\nimport { getPublicUrl, getSignedUrl } from '../utils/storage/helpers';\n\ninterface CachedUrl {\n url: string;\n expiresAt: number; // Timestamp in milliseconds\n}\n\n// Global cache shared across all hook instances\nconst globalUrlCache = new Map<string, CachedUrl>();\n\n// Cache size limit to prevent memory leaks\nconst MAX_CACHE_SIZE = 500;\n\n// Default TTL matches signed URL expiration (3600 seconds = 1 hour)\nconst DEFAULT_TTL_MS = 3600 * 1000;\n\n/**\n * Generate cache key from file reference\n */\nfunction getCacheKey(fileReference: FileReference): string {\n return `file-url:${fileReference.id}:${fileReference.is_public ? 'public' : 'private'}`;\n}\n\n/**\n * Clean up expired entries and enforce size limit\n */\nfunction cleanupCache(): void {\n const now = Date.now();\n \n // Remove expired entries\n for (const [key, value] of globalUrlCache.entries()) {\n if (value.expiresAt < now) {\n globalUrlCache.delete(key);\n }\n }\n \n // Enforce size limit by removing oldest entries\n if (globalUrlCache.size > MAX_CACHE_SIZE) {\n const entries = Array.from(globalUrlCache.entries());\n // Sort by expiration time (oldest first)\n entries.sort((a, b) => a[1].expiresAt - b[1].expiresAt);\n \n // Remove oldest 20% of entries\n const toRemove = Math.floor(MAX_CACHE_SIZE * 0.2);\n for (let i = 0; i < toRemove && i < entries.length; i++) {\n globalUrlCache.delete(entries[i][0]);\n }\n }\n}\n\nexport interface UseFileUrlCacheReturn {\n /**\n * Get URL for a file reference, using cache if available\n * @param fileReference - File reference to get URL for\n * @param supabase - Supabase client instance\n * @param organisationId - Organisation ID for signed URLs\n * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)\n * @returns Promise resolving to URL string or null\n */\n getUrl: (\n fileReference: FileReference,\n supabase: SupabaseClient,\n organisationId: string,\n ttl?: number\n ) => Promise<string | null>;\n \n /**\n * Set URL in cache\n * @param fileReference - File reference\n * @param url - URL to cache\n * @param ttl - Time to live in milliseconds (default: 3600000 = 1 hour)\n */\n setUrl: (fileReference: FileReference, url: string, ttl?: number) => void;\n \n /**\n * Get URL from cache without generating if missing\n * @param fileReference - File reference\n * @returns Cached URL or null if not in cache or expired\n */\n getCachedUrl: (fileReference: FileReference) => string | null;\n \n /**\n * Clear cache for a specific file reference\n * @param fileReference - File reference to clear\n */\n clearFile: (fileReference: FileReference) => void;\n \n /**\n * Clear all cached URLs\n */\n clearCache: () => void;\n \n /**\n * Get cache statistics\n */\n getCacheStats: () => { size: number; maxSize: number };\n}\n\n/**\n * Hook for centralized file URL caching\n * \n * This hook provides a shared cache for file URLs across all components,\n * preventing duplicate requests for the same file.\n * \n * @returns Cache operations and utilities\n */\nexport function useFileUrlCache(): UseFileUrlCacheReturn {\n // Use ref to ensure stable reference across renders\n const cleanupIntervalRef = useRef<number | null>(null);\n \n // Set up periodic cleanup (every 5 minutes)\n if (cleanupIntervalRef.current === null && typeof window !== 'undefined') {\n cleanupIntervalRef.current = window.setInterval(() => {\n cleanupCache();\n }, 5 * 60 * 1000); // 5 minutes\n }\n \n const getUrl = useCallback(async (\n fileReference: FileReference,\n supabase: SupabaseClient,\n organisationId: string,\n ttl: number = DEFAULT_TTL_MS\n ): Promise<string | null> => {\n const cacheKey = getCacheKey(fileReference);\n const cached = globalUrlCache.get(cacheKey);\n const now = Date.now();\n \n // Return cached URL if still valid\n if (cached && cached.expiresAt > now) {\n return cached.url;\n }\n \n // Generate new URL\n let url: string | null = null;\n \n try {\n if (fileReference.is_public) {\n // Public files: generate public URL (synchronous)\n url = getPublicUrl(supabase, fileReference.file_path, true);\n } else {\n // Private files: generate signed URL (async)\n const signedUrlResult = await getSignedUrl(supabase, fileReference.file_path, {\n appName: 'pace-core',\n orgId: organisationId,\n expiresIn: Math.floor(ttl / 1000) // Convert ms to seconds\n });\n url = signedUrlResult?.url || null;\n }\n \n // Cache the URL if generated successfully\n if (url) {\n globalUrlCache.set(cacheKey, {\n url,\n expiresAt: now + ttl\n });\n cleanupCache(); // Clean up after adding\n }\n \n return url;\n } catch (error) {\n console.error('Failed to generate file URL:', error);\n return null;\n }\n }, []);\n \n const setUrl = useCallback((\n fileReference: FileReference,\n url: string,\n ttl: number = DEFAULT_TTL_MS\n ): void => {\n const cacheKey = getCacheKey(fileReference);\n globalUrlCache.set(cacheKey, {\n url,\n expiresAt: Date.now() + ttl\n });\n cleanupCache();\n }, []);\n \n const getCachedUrl = useCallback((fileReference: FileReference): string | null => {\n const cacheKey = getCacheKey(fileReference);\n const cached = globalUrlCache.get(cacheKey);\n const now = Date.now();\n \n if (cached && cached.expiresAt > now) {\n return cached.url;\n }\n \n return null;\n }, []);\n \n const clearFile = useCallback((fileReference: FileReference): void => {\n const cacheKey = getCacheKey(fileReference);\n globalUrlCache.delete(cacheKey);\n }, []);\n \n const clearCache = useCallback((): void => {\n globalUrlCache.clear();\n }, []);\n \n const getCacheStats = useCallback(() => {\n return {\n size: globalUrlCache.size,\n maxSize: MAX_CACHE_SIZE\n };\n }, []);\n \n return {\n getUrl,\n setUrl,\n getCachedUrl,\n clearFile,\n clearCache,\n getCacheStats\n };\n}\n\n","/**\n * React hook for storage operations\n */\n\nimport { useState, useCallback } from 'react';\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { \n StorageUploadOptions, \n StorageUploadResult, \n StorageFileInfo,\n StorageListOptions,\n StorageListResult,\n uploadFile,\n getPublicUrl,\n getSignedUrl,\n deleteFile,\n listFiles,\n archiveFile\n} from '../utils/storage';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('useStorage');\n\nexport interface UseStorageOptions {\n supabase: SupabaseClient;\n appName: string;\n orgId: string;\n}\n\nexport interface UseStorageReturn {\n // Upload\n uploadFile: (file: File, options?: Partial<StorageUploadOptions>) => Promise<StorageUploadResult>;\n isUploading: boolean;\n uploadError: string | null;\n \n // URLs\n getPublicUrl: (path: string) => string;\n getSignedUrl: (path: string, expiresIn?: number) => Promise<string | null>;\n getFileUrl: (path: string) => string; // Alias for getPublicUrl\n \n // File management\n deleteFile: (path: string) => Promise<{ success: boolean; error?: string }>;\n archiveFile: (path: string) => Promise<{ success: boolean; error?: string }>;\n \n // Listing\n listFiles: (options?: Partial<StorageListOptions>) => Promise<StorageListResult>;\n isListing: boolean;\n listError: string | null;\n isLoading: boolean; // Alias for isListing\n error: string | null; // Alias for listError\n \n // State\n files: StorageFileInfo[];\n refreshFiles: () => Promise<void>;\n}\n\n/**\n * Hook for storage operations with app and organisation context\n */\nexport function useStorage({ supabase, appName, orgId }: UseStorageOptions): UseStorageReturn {\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [isListing, setIsListing] = useState(false);\n const [listError, setListError] = useState<string | null>(null);\n const [files, setFiles] = useState<StorageFileInfo[]>([]);\n\n // Upload file\n const handleUploadFile = useCallback(async (\n file: File, \n options: Partial<StorageUploadOptions> = {}\n ): Promise<StorageUploadResult> => {\n setIsUploading(true);\n setUploadError(null);\n\n try {\n const uploadOptions: StorageUploadOptions = {\n appName,\n orgId,\n isPublic: false,\n ...options\n };\n\n const result = await uploadFile(supabase, file, uploadOptions);\n \n if (result.success) {\n // Refresh file list\n await refreshFiles();\n } else {\n setUploadError(result.error || 'Upload failed');\n }\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Upload failed';\n setUploadError(errorMessage);\n return {\n success: false,\n error: errorMessage\n };\n } finally {\n setIsUploading(false);\n }\n }, [supabase, appName, orgId]);\n\n // Get public URL\n const handleGetPublicUrl = useCallback((path: string): string => {\n return getPublicUrl(supabase, path);\n }, [supabase]);\n\n // Get signed URL\n const handleGetSignedUrl = useCallback(async (\n path: string, \n expiresIn?: number\n ): Promise<string | null> => {\n try {\n const result = await getSignedUrl(supabase, path, {\n appName,\n orgId,\n expiresIn\n });\n return result?.url || null;\n } catch (error) {\n log.error('Failed to get signed URL:', error);\n return null;\n }\n }, [supabase, appName, orgId]);\n\n // Delete file\n const handleDeleteFile = useCallback(async (path: string) => {\n try {\n const result = await deleteFile(supabase, path);\n if (result.success) {\n await refreshFiles();\n }\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Delete failed'\n };\n }\n }, [supabase]);\n\n // Archive file\n const handleArchiveFile = useCallback(async (path: string) => {\n try {\n const result = await archiveFile(supabase, path, { appName, orgId });\n if (result.success) {\n await refreshFiles();\n }\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Archive failed'\n };\n }\n }, [supabase, appName, orgId]);\n\n // List files\n const handleListFiles = useCallback(async (\n options: Partial<StorageListOptions> = {}\n ): Promise<StorageListResult> => {\n setIsListing(true);\n setListError(null);\n\n try {\n const listOptions: StorageListOptions = {\n appName,\n orgId,\n ...options\n };\n\n const result = await listFiles(supabase, listOptions);\n setFiles(result.files);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'List failed';\n setListError(errorMessage);\n return { files: [], totalCount: 0, hasMore: false };\n } finally {\n setIsListing(false);\n }\n }, [supabase, appName, orgId]);\n\n // Refresh files\n const refreshFiles = useCallback(async () => {\n await handleListFiles();\n }, [handleListFiles]);\n\n return {\n // Upload\n uploadFile: handleUploadFile,\n isUploading,\n uploadError,\n \n // URLs\n getPublicUrl: handleGetPublicUrl,\n getSignedUrl: handleGetSignedUrl,\n getFileUrl: handleGetPublicUrl, // Alias for getPublicUrl\n \n // File management\n deleteFile: handleDeleteFile,\n archiveFile: handleArchiveFile,\n \n // Listing\n listFiles: handleListFiles,\n isListing,\n listError,\n isLoading: isListing, // Alias for isListing\n error: listError, // Alias for listError\n \n // State\n files,\n refreshFiles\n };\n}\n\n/**\n * Hook for file upload with progress tracking\n */\nexport function useFileUpload({ supabase, appName, orgId }: UseStorageOptions) {\n const [uploadProgress, setUploadProgress] = useState(0);\n const [isUploading, setIsUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n\n const uploadWithProgress = useCallback(async (\n file: File,\n options: Partial<StorageUploadOptions> = {}\n ): Promise<StorageUploadResult> => {\n setIsUploading(true);\n setUploadProgress(0);\n setUploadError(null);\n\n try {\n // Simulate progress (Supabase doesn't provide real progress)\n const progressInterval = setInterval(() => {\n setUploadProgress(prev => Math.min(prev + 10, 90));\n }, 100);\n\n const uploadOptions: StorageUploadOptions = {\n appName,\n orgId,\n isPublic: false,\n ...options\n };\n\n const result = await uploadFile(supabase, file, uploadOptions);\n \n clearInterval(progressInterval);\n setUploadProgress(100);\n\n if (!result.success) {\n setUploadError(result.error || 'Upload failed');\n }\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Upload failed';\n setUploadError(errorMessage);\n return {\n success: false,\n error: errorMessage\n };\n } finally {\n setIsUploading(false);\n setTimeout(() => setUploadProgress(0), 1000);\n }\n }, [supabase, appName, orgId]);\n\n return {\n uploadWithProgress,\n uploadProgress,\n isUploading,\n uploadError\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,QAAQ,aAAa,iBAAiB;AAuBxC,SAAS,mBAAmB,UAAkC,CAAC,GAA0B;AAC9F,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,WAAW,OAA2B,IAAI;AAChD,QAAM,mBAAmB,OAA2B,IAAI;AACxD,QAAM,qBAAqB,OAAgB,KAAK;AAEhD,QAAM,WAAW,YAAY,CAAC,YAAgC;AAC5D,aAAS,UAAU;AACnB,aAAS,MAAM;AAAA,EACjB,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAuB,YAAY,MAAqB;AAC5D,QAAI,CAAC,aAAa,QAAS,QAAO,CAAC;AAEnC,WAAO,MAAM;AAAA,MACX,aAAa,QAAQ;AAAA,QACnB;AAAA,MACF;AAAA,IACF,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,aAAa,UAAU,KAAK,CAAC,GAAG,aAAa,QAAQ,CAAC;AAAA,EAC7E,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,YAAY,MAAM;AACnC,UAAM,WAAW,qBAAqB;AACtC,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,SAAS,CAAC,CAAC;AACpB,qBAAe;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,sBAAsB,UAAU,YAAY,CAAC;AAEjD,QAAM,YAAY,YAAY,MAAM;AAClC,UAAM,WAAW,qBAAqB;AACtC,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,SAAS,SAAS,SAAS,CAAC,CAAC;AACtC,oBAAc;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,sBAAsB,UAAU,WAAW,CAAC;AAEhD,QAAM,kBAAkB,YAAY,MAAM;AACxC,uBAAmB,UAAU;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,MAAM;AACrC,uBAAmB,UAAU;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,CAAC,aAAyB;AACzD,WAAO,MAAM;AACX,YAAM,gBAAgB,CAAC,UAAyB;AAC9C,YAAI,MAAM,QAAQ,UAAU;AAC1B,mBAAS;AAAA,QACX;AAAA,MACF;AAEA,eAAS,iBAAiB,WAAW,aAAa;AAClD,aAAO,MAAM,SAAS,oBAAoB,WAAW,aAAa;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,aAAa,QAAS;AAEzC,UAAM,gBAAgB,CAAC,UAAyB;AAC9C,UAAI,MAAM,QAAQ,YAAY,UAAU;AACtC,iBAAS;AACT;AAAA,MACF;AAEA,UAAI,MAAM,QAAQ,MAAO;AAEzB,YAAM,WAAW,qBAAqB;AACtC,UAAI,SAAS,WAAW,EAAG;AAE3B,YAAM,eAAe,SAAS,CAAC;AAC/B,YAAM,cAAc,SAAS,SAAS,SAAS,CAAC;AAEhD,UAAI,MAAM,UAAU;AAClB,YAAI,SAAS,kBAAkB,cAAc;AAC3C,gBAAM,eAAe;AACrB,sBAAY,MAAM;AAAA,QACpB;AAAA,MACF,OAAO;AACL,YAAI,SAAS,kBAAkB,aAAa;AAC1C,gBAAM,eAAe;AACrB,uBAAa,MAAM;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,aAAa;AAC7B,YAAQ,iBAAiB,WAAW,aAAa;AACjD,WAAO,MAAM;AACX,eAAS,oBAAoB,WAAW,aAAa;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,oBAAoB,CAAC;AAG9C,YAAU,MAAM;AACd,QAAI,WAAW;AACb,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,CAAC;AAG1B,YAAU,MAAM;AACd,QAAI,CAAC,aAAc;AAEnB,qBAAiB,UAAU,SAAS;AAEpC,WAAO,MAAM;AACX,UAAI,iBAAiB,SAAS;AAC5B,yBAAiB,QAAQ,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC/JA,SAAS,UAAAA,SAAQ,aAAAC,YAAW,eAAAC,oBAAmB;AA0B/C,IAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAMJ,SAAS,aAAa,UAA4B,CAAC,GAAoB;AAC5E,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,eAAe;AAAA,IACf;AAAA,IACA,oBAAoB;AAAA,EACtB,IAAI;AAEJ,QAAM,eAAeF,QAAoB,IAAI;AAC7C,QAAM,2BAA2BA,QAA2B,IAAI;AAEhE,QAAM,uBAAuBE,aAAY,MAAqB;AAC5D,QAAI,CAAC,aAAa,QAAS,QAAO,CAAC;AAEnC,WAAO,MAAM;AAAA,MACX,aAAa,QAAQ,iBAA8B,iBAAiB;AAAA,IACtE,EAAE,OAAO,CAAC,YAAY;AACpB;AAAA;AAAA,QAEG,CAAC,QAAQ,aAAa,UAAU,KACjC,CAAC,QAAQ,aAAa,QAAQ,KAAK,QAAQ,iBAAiB;AAAA;AAAA,IAEhE,CAAC;AAAA,EACH,GAAG,CAAC,iBAAiB,CAAC;AAEtB,QAAM,aAAaA,aAAY,MAAM;AACnC,UAAM,WAAW,qBAAqB;AACtC,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,CAAC,EAAE,MAAM;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,YAAYA,aAAY,MAAM;AAClC,UAAM,WAAW,qBAAqB;AACtC,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,SAAS,SAAS,CAAC,EAAE,MAAM;AAAA,IACtC;AAAA,EACF,GAAG,CAAC,oBAAoB,CAAC;AAGzB,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,aAAa,QAAS;AAExC,UAAM,gBAAgB,CAAC,UAAyB;AAE9C,UAAI,MAAM,QAAQ,YAAY,UAAU;AACtC,iBAAS;AACT;AAAA,MACF;AAGA,UAAI,MAAM,QAAQ,OAAO;AACvB,cAAM,oBAAoB,qBAAqB;AAC/C,YAAI,kBAAkB,WAAW,EAAG;AAEpC,cAAM,eAAe,kBAAkB,CAAC;AACxC,cAAM,cAAc,kBAAkB,kBAAkB,SAAS,CAAC;AAElE,YAAI,MAAM,UAAU;AAElB,cAAI,SAAS,kBAAkB,cAAc;AAC3C,kBAAM,eAAe;AACrB,wBAAY,MAAM;AAAA,UACpB;AAAA,QACF,OAAO;AAEL,cAAI,SAAS,kBAAkB,aAAa;AAC1C,kBAAM,eAAe;AACrB,yBAAa,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,aAAa;AAC/B,cAAU,iBAAiB,WAAW,aAAa;AAEnD,WAAO,MAAM;AACX,gBAAU,oBAAoB,WAAW,aAAa;AAAA,IACxD;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,oBAAoB,CAAC;AAG7C,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAGf,QAAI,cAAc;AAChB,+BAAyB,UAAU,SAAS;AAAA,IAC9C;AAGA,QAAI,WAAW;AACb,YAAM,QAAQ,WAAW,YAAY,CAAC;AACtC,aAAO,MAAM,aAAa,KAAK;AAAA,IACjC;AAEA,WAAO,MAAM;AAEX,UAAI,gBAAgB,yBAAyB,SAAS;AACpD,iCAAyB,QAAQ,MAAM;AACvC,iCAAyB,UAAU;AAAA,MACrC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,WAAW,cAAc,UAAU,CAAC;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC1JA,SAAS,aAAAE,YAAW,eAAAC,oBAAmB;AA2BvC,SAAS,cAAc,OAAe;AACpC,QAAM,QAAQ,MAAM,YAAY,EAAE,MAAM,GAAG;AAC3C,QAAM,MAAM,MAAM,IAAI;AACtB,QAAM,YAAY;AAAA,IAChB,MAAM,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,SAAS;AAAA,IACxD,KAAK,MAAM,SAAS,KAAK;AAAA,IACzB,OAAO,MAAM,SAAS,OAAO;AAAA,IAC7B,MAAM,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK;AAAA,EACtD;AACA,SAAO,EAAE,KAAK,UAAU;AAC1B;AAKA,SAAS,gBAAgB,OAAsB,OAAwB;AACrE,QAAM,EAAE,KAAK,UAAU,IAAI,cAAc,KAAK;AAG9C,QAAM,WAAW,MAAM,IAAI,YAAY;AACvC,QAAM,YAAY,IAAI,YAAY;AAElC,MAAI,aAAa,WAAW;AAC1B,WAAO;AAAA,EACT;AAGA,SACE,MAAM,YAAY,UAAU,QAC5B,MAAM,WAAW,UAAU,OAC3B,MAAM,aAAa,UAAU,SAC7B,MAAM,YAAY,UAAU;AAEhC;AA4BO,SAAS,qBACd,WACA,UAAoC,CAAC,GAC/B;AACN,QAAM,EAAE,UAAU,UAAU,UAAU,KAAK,IAAI;AAE/C,QAAM,gBAAgBA,aAAY,CAAC,UAAyB;AAC1D,QAAI,CAAC,QAAS;AAEd,eAAW,YAAY,WAAW;AAChC,UAAI,SAAS,YAAY,MAAO;AAEhC,UAAI,gBAAgB,OAAO,SAAS,GAAG,GAAG;AACxC,YAAI,SAAS,gBAAgB;AAC3B,gBAAM,eAAe;AAAA,QACvB;AACA,YAAI,SAAS,iBAAiB;AAC5B,gBAAM,gBAAgB;AAAA,QACxB;AAEA,iBAAS,QAAQ,KAAK;AACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,OAAO,CAAC;AAEvB,EAAAD,WAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,YAAQ,iBAAiB,WAAW,aAA8B;AAClE,WAAO,MAAM,QAAQ,oBAAoB,WAAW,aAA8B;AAAA,EACpF,GAAG,CAAC,SAAS,SAAS,aAAa,CAAC;AACtC;;;ACnHA,SAAS,UAAU,aAAAE,kBAAiB;AAEpC,IAAM,oBAAoB;AAOnB,SAAS,cAAuB;AACrC,QAAM,CAAC,UAAU,WAAW,IAAI,SAA8B,MAAS;AAEvE,EAAAA,WAAU,MAAM;AAEd,QAAI,OAAO,WAAW,aAAa;AACjC,kBAAY,KAAK;AACjB;AAAA,IACF;AAEA,UAAM,MAAM,OAAO,WAAW,eAAe,oBAAoB,CAAC,KAAK;AAEvE,UAAM,WAAW,MAAM;AACrB,kBAAY,OAAO,aAAa,iBAAiB;AAAA,IACnD;AAGA,gBAAY,OAAO,aAAa,iBAAiB;AAGjD,QAAI,iBAAiB,UAAU,QAAQ;AAGvC,WAAO,MAAM,IAAI,oBAAoB,UAAU,QAAQ;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,SAAO,CAAC,CAAC;AACX;;;ACpCA,SAAS,YAAAC,WAAU,eAAAC,oBAAmB;AAuC/B,SAAS,kBAAkB,SAAmC;AACnE,QAAM,EAAE,kBAAkB,IAAI,KAAK,IAAI;AAGvC,QAAM,CAAC,SAAS,UAAU,IAAID,UAAuB,CAAC,CAAC;AACvD,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAA6B,CAAC,CAAC;AACzE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,CAAC,CAAC;AAC1D,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,eAAe;AACxD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,CAAC;AAC5C,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAmB,CAAC,CAAC;AAG7D,QAAM,aAAaC,aAAY,MAAM;AACnC,eAAW,CAAC,CAAC;AACb,qBAAiB,CAAC,CAAC;AACnB,gBAAY,CAAC,CAAC;AACd,gBAAY,eAAe;AAC3B,iBAAa,CAAC;AACd,oBAAgB,CAAC,CAAC;AAAA,EACpB,GAAG,CAAC,eAAe,CAAC;AAGpB,QAAM,QAAQ,YAAY;AAC1B,QAAM,MAAM,QAAQ;AACpB,QAAM,gBAAgB,KAAK,MAAM,OAAO,GAAG;AAE3C,QAAM,aAAa,KAAK,KAAK,KAAK,SAAS,QAAQ;AACnD,QAAM,cAAc,YAAY,aAAa;AAC7C,QAAM,kBAAkB,YAAY;AAEpC,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AClGA,SAAS,aAAAC,YAAW,UAAAC,SAAQ,eAAAC,oBAAmB;AAI/C,IAAM,MAAM,aAAa,uBAAuB;AAczC,SAAS,sBACd,eACA,UAAU,YAAY,IAAI,SAAS,eACnC,aAAqB,oBACrB;AACA,QAAM,kBAAkBC,QAAe,CAAC;AACxC,QAAM,UAAUA,QAA6B,CAAC,CAAC;AAG/C,QAAM,mBAAmBC,aAAY,MAAM;AACzC,QAAI,CAAC,QAAS;AACd,oBAAgB,UAAU,YAAY,IAAI;AAAA,EAC5C,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,iBAAiBA,aAAY,MAAM;AACvC,QAAI,CAAC,WAAW,gBAAgB,YAAY,EAAG;AAE/C,UAAM,aAAa,YAAY,IAAI,IAAI,gBAAgB;AACvD,UAAM,SAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,YAAQ,QAAQ,KAAK,MAAM;AAG3B,QAAI,QAAQ,QAAQ,SAAS,IAAI;AAC/B,cAAQ,UAAU,QAAQ,QAAQ,MAAM,GAAG;AAAA,IAC7C;AAGA,UAAM,cAAc,yBAAyB,QAAQ,YAAY,YAAY;AAAA,MAC3E;AAAA,MACA,aAAa,QAAQ,QAAQ;AAAA,IAC/B,CAAC;AAGD,QAAI,CAAC,YAAY,QAAQ;AACvB,UAAI;AAAA,QACF,kCAAkC,aAAa,KAAK,WAAW,QAAQ,CAAC,CAAC,eAC7D,oBAAoB,UAAU,GAAG,SAAS;AAAA,MACxD;AAAA,IACF;AAEA,oBAAgB,UAAU;AAAA,EAC5B,GAAG,CAAC,SAAS,eAAe,UAAU,CAAC;AAGvC,QAAM,aAAaA,aAAY,MAAM;AACnC,WAAO,QAAQ,QAAQ,MAAM;AAAA,EAC/B,GAAG,CAAC,CAAC;AAGL,QAAM,uBAAuBA,aAAY,MAAM;AAC7C,QAAI,QAAQ,QAAQ,WAAW,EAAG,QAAO;AAEzC,UAAM,QAAQ,QAAQ,QAAQ,OAAO,CAAC,KAAK,WAAW,MAAM,OAAO,YAAY,CAAC;AAChF,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EACjC,GAAG,CAAC,CAAC;AAGL,QAAM,kBAAkBA,aAAY,MAAM;AACxC,UAAM,SAAS,oBAAoB,UAAU;AAC7C,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,cAAc,qBAAqB;AACzC,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,MACT,QAAQ,eAAe,OAAO;AAAA,MAC9B,YAAY,OAAO,YAAY,KAAK,OAAO,YAAY,eAAe,OAAO,YAAY;AAAA,IAC3F;AAAA,EACF,GAAG,CAAC,YAAY,oBAAoB,CAAC;AAGrC,EAAAC,WAAU,MAAM;AACd,qBAAiB;AACjB,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjFA,SAAS,UAAAC,SAAQ,eAAAC,oBAAmB;AAWpC,IAAM,iBAAiB,oBAAI,IAAuB;AAGlD,IAAM,iBAAiB;AAGvB,IAAM,iBAAiB,OAAO;AAK9B,SAAS,YAAY,eAAsC;AACzD,SAAO,YAAY,cAAc,EAAE,IAAI,cAAc,YAAY,WAAW,SAAS;AACvF;AAKA,SAAS,eAAqB;AAC5B,QAAM,MAAM,KAAK,IAAI;AAGrB,aAAW,CAAC,KAAK,KAAK,KAAK,eAAe,QAAQ,GAAG;AACnD,QAAI,MAAM,YAAY,KAAK;AACzB,qBAAe,OAAO,GAAG;AAAA,IAC3B;AAAA,EACF;AAGA,MAAI,eAAe,OAAO,gBAAgB;AACxC,UAAM,UAAU,MAAM,KAAK,eAAe,QAAQ,CAAC;AAEnD,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS;AAGtD,UAAM,WAAW,KAAK,MAAM,iBAAiB,GAAG;AAChD,aAAS,IAAI,GAAG,IAAI,YAAY,IAAI,QAAQ,QAAQ,KAAK;AACvD,qBAAe,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;AAAA,IACrC;AAAA,EACF;AACF;AA0DO,SAAS,kBAAyC;AAEvD,QAAM,qBAAqBC,QAAsB,IAAI;AAGrD,MAAI,mBAAmB,YAAY,QAAQ,OAAO,WAAW,aAAa;AACxE,uBAAmB,UAAU,OAAO,YAAY,MAAM;AACpD,mBAAa;AAAA,IACf,GAAG,IAAI,KAAK,GAAI;AAAA,EAClB;AAEA,QAAM,SAASC,aAAY,OACzB,eACA,UACA,gBACA,MAAc,mBACa;AAC3B,UAAM,WAAW,YAAY,aAAa;AAC1C,UAAM,SAAS,eAAe,IAAI,QAAQ;AAC1C,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,UAAU,OAAO,YAAY,KAAK;AACpC,aAAO,OAAO;AAAA,IAChB;AAGA,QAAI,MAAqB;AAEzB,QAAI;AACF,UAAI,cAAc,WAAW;AAE3B,cAAM,aAAa,UAAU,cAAc,WAAW,IAAI;AAAA,MAC5D,OAAO;AAEL,cAAM,kBAAkB,MAAM,aAAa,UAAU,cAAc,WAAW;AAAA,UAC5E,SAAS;AAAA,UACT,OAAO;AAAA,UACP,WAAW,KAAK,MAAM,MAAM,GAAI;AAAA;AAAA,QAClC,CAAC;AACD,cAAM,iBAAiB,OAAO;AAAA,MAChC;AAGA,UAAI,KAAK;AACP,uBAAe,IAAI,UAAU;AAAA,UAC3B;AAAA,UACA,WAAW,MAAM;AAAA,QACnB,CAAC;AACD,qBAAa;AAAA,MACf;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,gCAAgC,KAAK;AACnD,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,SAASA,aAAY,CACzB,eACA,KACA,MAAc,mBACL;AACT,UAAM,WAAW,YAAY,aAAa;AAC1C,mBAAe,IAAI,UAAU;AAAA,MAC3B;AAAA,MACA,WAAW,KAAK,IAAI,IAAI;AAAA,IAC1B,CAAC;AACD,iBAAa;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,QAAM,eAAeA,aAAY,CAAC,kBAAgD;AAChF,UAAM,WAAW,YAAY,aAAa;AAC1C,UAAM,SAAS,eAAe,IAAI,QAAQ;AAC1C,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,UAAU,OAAO,YAAY,KAAK;AACpC,aAAO,OAAO;AAAA,IAChB;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,YAAYA,aAAY,CAAC,kBAAuC;AACpE,UAAM,WAAW,YAAY,aAAa;AAC1C,mBAAe,OAAO,QAAQ;AAAA,EAChC,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA,aAAY,MAAY;AACzC,mBAAe,MAAM;AAAA,EACvB,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA,aAAY,MAAM;AACtC,WAAO;AAAA,MACL,MAAM,eAAe;AAAA,MACrB,SAAS;AAAA,IACX;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChPA,SAAS,YAAAC,WAAU,eAAAC,oBAAmB;AAiBtC,IAAMC,OAAM,aAAa,YAAY;AAsC9B,SAAS,WAAW,EAAE,UAAU,SAAS,MAAM,GAAwC;AAC5F,QAAM,CAAC,aAAa,cAAc,IAAIC,UAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAwB,IAAI;AAClE,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAChD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAwB,IAAI;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAA4B,CAAC,CAAC;AAGxD,QAAM,mBAAmBC,aAAY,OACnC,MACA,UAAyC,CAAC,MACT;AACjC,mBAAe,IAAI;AACnB,mBAAe,IAAI;AAEnB,QAAI;AACF,YAAM,gBAAsC;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAEA,YAAM,SAAS,MAAM,WAAW,UAAU,MAAM,aAAa;AAE7D,UAAI,OAAO,SAAS;AAElB,cAAM,aAAa;AAAA,MACrB,OAAO;AACL,uBAAe,OAAO,SAAS,eAAe;AAAA,MAChD;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,qBAAe,YAAY;AAC3B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAG7B,QAAM,qBAAqBA,aAAY,CAAC,SAAyB;AAC/D,WAAO,aAAa,UAAU,IAAI;AAAA,EACpC,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,qBAAqBA,aAAY,OACrC,MACA,cAC2B;AAC3B,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,UAAU,MAAM;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,QAAQ,OAAO;AAAA,IACxB,SAAS,OAAO;AACd,MAAAF,KAAI,MAAM,6BAA6B,KAAK;AAC5C,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAG7B,QAAM,mBAAmBE,aAAY,OAAO,SAAiB;AAC3D,QAAI;AACF,YAAM,SAAS,MAAM,WAAW,UAAU,IAAI;AAC9C,UAAI,OAAO,SAAS;AAClB,cAAM,aAAa;AAAA,MACrB;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,oBAAoBA,aAAY,OAAO,SAAiB;AAC5D,QAAI;AACF,YAAM,SAAS,MAAM,YAAY,UAAU,MAAM,EAAE,SAAS,MAAM,CAAC;AACnE,UAAI,OAAO,SAAS;AAClB,cAAM,aAAa;AAAA,MACrB;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAG7B,QAAM,kBAAkBA,aAAY,OAClC,UAAuC,CAAC,MACT;AAC/B,iBAAa,IAAI;AACjB,iBAAa,IAAI;AAEjB,QAAI;AACF,YAAM,cAAkC;AAAA,QACtC;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL;AAEA,YAAM,SAAS,MAAM,UAAU,UAAU,WAAW;AACpD,eAAS,OAAO,KAAK;AACrB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,mBAAa,YAAY;AACzB,aAAO,EAAE,OAAO,CAAC,GAAG,YAAY,GAAG,SAAS,MAAM;AAAA,IACpD,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAG7B,QAAM,eAAeA,aAAY,YAAY;AAC3C,UAAM,gBAAgB;AAAA,EACxB,GAAG,CAAC,eAAe,CAAC;AAEpB,SAAO;AAAA;AAAA,IAEL,YAAY;AAAA,IACZ;AAAA,IACA;AAAA;AAAA,IAGA,cAAc;AAAA,IACd,cAAc;AAAA,IACd,YAAY;AAAA;AAAA;AAAA,IAGZ,YAAY;AAAA,IACZ,aAAa;AAAA;AAAA,IAGb,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,WAAW;AAAA;AAAA,IACX,OAAO;AAAA;AAAA;AAAA,IAGP;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,cAAc,EAAE,UAAU,SAAS,MAAM,GAAsB;AAC7E,QAAM,CAAC,gBAAgB,iBAAiB,IAAID,UAAS,CAAC;AACtD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAwB,IAAI;AAElE,QAAM,qBAAqBC,aAAY,OACrC,MACA,UAAyC,CAAC,MACT;AACjC,mBAAe,IAAI;AACnB,sBAAkB,CAAC;AACnB,mBAAe,IAAI;AAEnB,QAAI;AAEF,YAAM,mBAAmB,YAAY,MAAM;AACzC,0BAAkB,UAAQ,KAAK,IAAI,OAAO,IAAI,EAAE,CAAC;AAAA,MACnD,GAAG,GAAG;AAEN,YAAM,gBAAsC;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAEA,YAAM,SAAS,MAAM,WAAW,UAAU,MAAM,aAAa;AAE7D,oBAAc,gBAAgB;AAC9B,wBAAkB,GAAG;AAErB,UAAI,CAAC,OAAO,SAAS;AACnB,uBAAe,OAAO,SAAS,eAAe;AAAA,MAChD;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,qBAAe,YAAY;AAC3B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,IACF,UAAE;AACA,qBAAe,KAAK;AACpB,iBAAW,MAAM,kBAAkB,CAAC,GAAG,GAAI;AAAA,IAC7C;AAAA,EACF,GAAG,CAAC,UAAU,SAAS,KAAK,CAAC;AAE7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useRef","useEffect","useCallback","useEffect","useCallback","useEffect","useState","useCallback","useEffect","useRef","useCallback","useRef","useCallback","useEffect","useRef","useCallback","useRef","useCallback","useState","useCallback","log","useState","useCallback"]}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, U as UserEventAccess, u as useUnifiedAuth } from './UnifiedAuthProvider-BYA9qB-o.js';
1
+ export { a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, U as UserEventAccess, u as useUnifiedAuth } from './UnifiedAuthProvider-185Ih4dj.js';
2
2
  export { j as LogLevel, L as Logger, k as LoggerConfig, d as cn, i as createLogger, c as createSecureDataAccess, e as emailSchema, w as formatCompactNumber, r as formatCurrency, m as formatDate, q as formatDateTime, x as formatFileSize, y as formatInTimeZone, t as formatNumber, v as formatPercent, o as formatTime, A as formatTimeInTimeZone, D as fromZonedTime, g as getAppConfig, h as getCurrentAppId, f as getCurrentAppName, F as getTimeZoneDifference, z as getTimezoneAbbreviation, B as getUserTimeZone, l as logger, n as nameSchema, b as passwordSchema, p as phoneSchema, E as roundToNearestMinutes, s as setAppConfig, C as toZonedTime, a as urlSchema, u as useSessionTracking } from './timezone-_pgH8qrY.js';
3
- import { j as EventService, k as OrganisationService, A as AuthService, l as InactivityService } from './AuthService-CbP_utw2.js';
4
- export { c as EventServiceProvider, i as InactivityServiceProvider, f as OrganisationServiceProvider } from './AuthService-CbP_utw2.js';
3
+ import { j as EventService, k as OrganisationService, A as AuthService, l as InactivityService } from './AuthService-DjnJHDtC.js';
4
+ export { c as EventServiceProvider, i as InactivityServiceProvider, f as OrganisationServiceProvider } from './AuthService-DjnJHDtC.js';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import React__default from 'react';
7
7
  import { i as OrganisationProviderProps$1, E as Event, h as OrganisationContextType } from './event-CW5YB_2p.js';
@@ -9,15 +9,15 @@ export { O as Organisation, a as OrganisationMembership, g as OrganisationSecuri
9
9
  import { S as SessionRestorationState } from './auth-BZOJqrdd.js';
10
10
  export { A as AccessLevel, E as EventAppRole, G as GlobalRole, I as InvalidScopeError, M as MissingUserContextError, O as Operation, e as OrganisationContextRequiredError, c as OrganisationRole, P as Permission, a as PermissionCheck, d as PermissionDeniedError, b as PermissionMap, R as RBACError, f as RBACNotInitializedError, S as Scope, U as UUID } from './types-UU913iLA.js';
11
11
  export { A as AccessLevelContext, s as AuditEventType, P as PermissionSource, d as RBACAccessValidateParams, e as RBACAccessValidateResult, q as RBACAuditLogParams, r as RBACAuditLogResult, t as RBACContext, w as RBACErrorCode, v as RBACFunctionResponse, f as RBACPageAccessCheckParams, R as RBACPermissionCheckParams, a as RBACPermissionCheckResult, b as RBACPermissionsGetParams, c as RBACPermissionsGetResult, u as RBACResult, g as RBACRoleGrantParams, h as RBACRoleGrantResult, i as RBACRoleRevokeParams, j as RBACRoleRevokeResult, m as RBACRoleValidateParams, n as RBACRoleValidateResult, k as RBACRolesListParams, l as RBACRolesListResult, o as RBACSessionTrackParams, p as RBACSessionTrackResult, x as RPCFunction, S as SessionType } from './functions-D_kgHktt.js';
12
- export { ALL_PERMISSIONS, AccessLevelGuard, AllPermissions, CACHE_PATTERNS, ComplianceResult, DataAccessRecord, DatabaseComplianceResult, DatabaseIssue, EVENT_APP_PERMISSIONS, EnhancedNavigationMenu, EnhancedNavigationMenuProps, EventAppRoleData, GLOBAL_PERMISSIONS, GrantEventAppRoleParams, NavigationAccessRecord, NavigationContextType, NavigationGuard, NavigationGuardProps, NavigationProvider, NavigationProviderProps, ORGANISATION_PERMISSIONS, PAGE_PERMISSIONS, PageAccessRecord, PagePermissionContextType, PagePermissionGuard, PagePermissionGuardProps, PagePermissionProvider, PagePermissionProviderProps, PermissionEnforcer, PermissionEnforcerProps, PermissionGuard, QuickFix, RBACAuditManager, RBACCache, RBACConfig, RBACEngine, RBACLogger, RBACPerformanceMetrics, ResourcePermissions, RevokeEventAppRoleParams, RoleBasedRouter, RoleBasedRouterContextType, RoleBasedRouterProps, RoleManagementResult, RouteAccessRecord, RouteConfig, RuntimeComplianceResult, SecureDataContextType, SecureDataProvider, SecureDataProviderProps, SecureSupabaseClient, SetupIssue, UseResolvedScopeOptions, UseResolvedScopeReturn, UseResourcePermissionsOptions, checkRuntimeCompliance, clearInFlightRequests, createAuditManager, createRBACConfig, createRBACEngine, createRBACExpressMiddleware, createRBACMiddleware, createSecureClient, disablePerformanceMonitoring, emitAuditEvent, enablePerformanceMonitoring, fromSupabaseClient, getAccessLevel, getCustomAuthCodeFixes, getDirectSupabaseAuthFixes, getDuplicateConfigFixes, getGlobalAuditManager, getInFlightRequestCount, getPerformanceMetrics, getPerformanceSummary, getPermissionMap, getPermissionsForRole, getQuickFixes, getRBACConfig, getRBACLogger, getRoleContext, getSetupIssues, getUnprotectedPageFixes, hasAllPermissions, hasAnyPermission, hasAnyPermissionCached, hasPermission, hasPermissionCached, isDebugMode, isDevelopmentMode, isPerformanceMonitoringEnabled, isPermitted, isPermittedCached, isRBACInitialized, isValidPermission, rbacCache, recordAuditEvent, recordPermissionCheck, resetPerformanceMetrics, resolveAppContext, setGlobalAuditManager, setupRBAC, useAccessLevel, useCachedPermissions, useCan, useHasAllPermissions, useHasAnyPermission, useMultiplePermissions, useNavigationPermissions, usePagePermissions, usePermissions, useRBAC, useResolvedScope, useResourcePermissions, useRoleBasedRouter, useRoleManagement, useSecureData, useSecureSupabase, useSuperAdminBypass, validateAndWarn, validateDatabaseConfiguration, validateRBACSetup, withAccessLevelGuard, withPermissionGuard, withRoleGuard } from './rbac/index.js';
13
- export { A as AddressField, k as AddressFieldProps, l as AddressFieldRef, o as Alert, q as AlertDescription, p as AlertTitle, r as Avatar, s as AvatarProps, t as Badge, u as BadgeProps, v as BadgeVariant, B as Button, a as ButtonProps, an as Calendar, ao as CalendarProps, C as Card, g as CardActions, f as CardContent, e as CardDescription, c as CardFooter, b as CardHeader, h as CardProps, d as CardTitle, w as Checkbox, M as Dialog, W as DialogBody, R as DialogClose, U as DialogContent, Z as DialogDescription, X as DialogFooter, V as DialogHeader, O as DialogOverlay, N as DialogPortal, Y as DialogTitle, Q as DialogTrigger, aV as ErrorBoundary, a$ as EventSelector, b2 as FileDisplay, b3 as FileDisplayProps, b0 as FileUpload, b1 as FileUploadProps, aL as Footer, aM as FooterProps, aE as Form, aF as FormField, aH as FormFieldProps, aG as FormProps, aK as Header, I as Input, j as InputProps, L as Label, m as LabelProps, aY as LoadingSpinner, aI as LoginForm, aJ as LoginFormProps, aR as NavigationItem, aP as NavigationMenu, aQ as NavigationMenuProps, bo as NavigationMode, aS as OrganisationSelector, bl as PaceAppLayout, bk as PaceAppLayoutProps, bn as PaceLoginPage, bm as PaceLoginPageProps, bq as PasswordChangeForm, P as Progress, y as ProgressProps, aN as ProtectedRoute, aO as ProtectedRouteProps, bd as PublicPageFooter, bj as PublicPageFooterProps, bc as PublicPageHeader, bi as PublicPageHeaderProps, bb as PublicPageLayout, bh as PublicPageLayoutProps, be as PublicPageProvider, a7 as Select, ab as SelectContent, a8 as SelectGroup, ad as SelectItem, ac as SelectLabel, ae as SelectSeparator, aa as SelectTrigger, a9 as SelectValue, aZ as SessionRestorationLoader, a_ as SessionRestorationLoaderProps, S as Switch, x as SwitchProps, z as Table, E as TableBody, F as TableCaption, G as TableCell, H as TableFooter, J as TableHead, D as TableHeader, K as TableRow, af as Tabs, ai as TabsContent, am as TabsContentProps, ag as TabsList, ak as TabsListProps, aj as TabsProps, ah as TabsTrigger, al as TabsTriggerProps, T as Textarea, n as TextareaProps, ap as Toast, ar as ToastAction, ax as ToastActionElement, aw as ToastClose, av as ToastDescription, ay as ToastProps, as as ToastProvider, au as ToastTitle, at as ToastViewport, aq as Toaster, az as Tooltip, aB as TooltipContent, aC as TooltipProvider, aD as TooltipRoot, aA as TooltipTrigger, ba as UseFileReferenceForRecordReturn, b8 as UseFileReferenceOptions, b9 as UseFileReferenceReturn, aU as UserMenu, bp as UserMenuProps, b4 as useFileReference, b6 as useFileReferenceById, b5 as useFileReferenceForRecord, b7 as useFilesByCategory, bg as useIsPublicPage, bf as usePublicPageContext } from './PublicPageProvider-ULXC_u6U.js';
14
- export { u as useToast } from './useToast-C8gR5ir4.js';
15
- export { D as DataTable, a as DataTableProps } from './DataTable-Be6dH_dR.js';
12
+ export { ALL_PERMISSIONS, AccessLevelGuard, AllPermissions, CACHE_PATTERNS, ComplianceResult, DataAccessRecord, DatabaseComplianceResult, DatabaseIssue, EVENT_APP_PERMISSIONS, EnhancedNavigationMenu, EnhancedNavigationMenuProps, EventAppRoleData, GLOBAL_PERMISSIONS, GrantEventAppRoleParams, NavigationAccessRecord, NavigationContextType, NavigationGuard, NavigationGuardProps, NavigationProvider, NavigationProviderProps, ORGANISATION_PERMISSIONS, PAGE_PERMISSIONS, PageAccessRecord, PagePermissionContextType, PagePermissionGuard, PagePermissionGuardProps, PagePermissionProvider, PagePermissionProviderProps, PermissionEnforcer, PermissionEnforcerProps, PermissionGuard, QuickFix, RBACAuditManager, RBACCache, RBACConfig, RBACEngine, RBACLogger, RBACPerformanceMetrics, ResourcePermissions, RevokeEventAppRoleParams, RoleBasedRouter, RoleBasedRouterContextType, RoleBasedRouterProps, RoleManagementResult, RouteAccessRecord, RouteConfig, RuntimeComplianceResult, SecureDataContextType, SecureDataProvider, SecureDataProviderProps, SecureSupabaseClient, SetupIssue, UseResolvedScopeOptions, UseResolvedScopeReturn, UseResourcePermissionsOptions, checkRuntimeCompliance, clearInFlightRequests, createAuditManager, createRBACConfig, createRBACEngine, createRBACExpressMiddleware, createRBACMiddleware, createSecureClient, disablePerformanceMonitoring, emitAuditEvent, enablePerformanceMonitoring, fromSupabaseClient, getAccessLevel, getCustomAuthCodeFixes, getDirectSupabaseAuthFixes, getDuplicateConfigFixes, getGlobalAuditManager, getInFlightRequestCount, getPerformanceMetrics, getPerformanceSummary, getPermissionMap, getPermissionsForRole, getQuickFixes, getRBACConfig, getRBACLogger, getRoleContext, getSetupIssues, getUnprotectedPageFixes, hasAllPermissions, hasAnyPermission, hasAnyPermissionCached, hasPermission, hasPermissionCached, isDebugMode, isDevelopmentMode, isPerformanceMonitoringEnabled, isPermitted, isPermittedCached, isRBACInitialized, isValidPermission, rbacCache, recordAuditEvent, recordPermissionCheck, resetPerformanceMetrics, resolveAppContext, setGlobalAuditManager, setupRBAC, useAccessLevel, useCachedPermissions, useCan, useHasAllPermissions, useHasAnyPermission, useMultiplePermissions, useNavigationPermissions, usePagePermissions, usePermissions, useRBAC, useResolvedScope, useResourcePermissions, useRoleBasedRouter, useRoleManagement, useSecureData, useSecureSupabase, validateAndWarn, validateDatabaseConfiguration, validateRBACSetup, withAccessLevelGuard, withPermissionGuard, withRoleGuard } from './rbac/index.js';
13
+ export { A as AddressField, k as AddressFieldProps, l as AddressFieldRef, o as Alert, q as AlertDescription, p as AlertTitle, r as Avatar, s as AvatarProps, t as Badge, u as BadgeProps, v as BadgeVariant, B as Button, a as ButtonProps, an as Calendar, ao as CalendarProps, C as Card, g as CardActions, f as CardContent, e as CardDescription, c as CardFooter, b as CardHeader, h as CardProps, d as CardTitle, w as Checkbox, M as Dialog, W as DialogBody, R as DialogClose, U as DialogContent, Z as DialogDescription, X as DialogFooter, V as DialogHeader, O as DialogOverlay, N as DialogPortal, Y as DialogTitle, Q as DialogTrigger, aV as ErrorBoundary, a$ as EventSelector, b2 as FileDisplay, b3 as FileDisplayProps, b0 as FileUpload, b1 as FileUploadProps, aL as Footer, aM as FooterProps, aE as Form, aF as FormField, aH as FormFieldProps, aG as FormProps, aK as Header, I as Input, j as InputProps, L as Label, m as LabelProps, aY as LoadingSpinner, aI as LoginForm, aJ as LoginFormProps, aR as NavigationItem, aP as NavigationMenu, aQ as NavigationMenuProps, bo as NavigationMode, aS as OrganisationSelector, bl as PaceAppLayout, bk as PaceAppLayoutProps, bn as PaceLoginPage, bm as PaceLoginPageProps, bq as PasswordChangeForm, P as Progress, y as ProgressProps, aN as ProtectedRoute, aO as ProtectedRouteProps, bd as PublicPageFooter, bj as PublicPageFooterProps, bc as PublicPageHeader, bi as PublicPageHeaderProps, bb as PublicPageLayout, bh as PublicPageLayoutProps, be as PublicPageProvider, a7 as Select, ab as SelectContent, a8 as SelectGroup, ad as SelectItem, ac as SelectLabel, ae as SelectSeparator, aa as SelectTrigger, a9 as SelectValue, aZ as SessionRestorationLoader, a_ as SessionRestorationLoaderProps, S as Switch, x as SwitchProps, z as Table, E as TableBody, F as TableCaption, G as TableCell, H as TableFooter, J as TableHead, D as TableHeader, K as TableRow, af as Tabs, ai as TabsContent, am as TabsContentProps, ag as TabsList, ak as TabsListProps, aj as TabsProps, ah as TabsTrigger, al as TabsTriggerProps, T as Textarea, n as TextareaProps, ap as Toast, ar as ToastAction, ax as ToastActionElement, aw as ToastClose, av as ToastDescription, ay as ToastProps, as as ToastProvider, au as ToastTitle, at as ToastViewport, aq as Toaster, az as Tooltip, aB as TooltipContent, aC as TooltipProvider, aD as TooltipRoot, aA as TooltipTrigger, ba as UseFileReferenceForRecordReturn, b8 as UseFileReferenceOptions, b9 as UseFileReferenceReturn, aU as UserMenu, bp as UserMenuProps, b4 as useFileReference, b6 as useFileReferenceById, b5 as useFileReferenceForRecord, b7 as useFilesByCategory, bg as useIsPublicPage, bf as usePublicPageContext } from './PublicPageProvider-ce4xlHYA.js';
14
+ export { u as useToast } from './useToast-AyaT-x7p.js';
15
+ export { D as DataTable, a as DataTableProps } from './DataTable-CH1U5Tpy.js';
16
16
  import { d as DataRecord, a as DataTableAction, D as DataTableColumn } from './types-CEpcvwwF.js';
17
17
  export { c as AggregateConfig, A as AutocompleteOptions, f as DataTableFeatureConfig, b as DataTableToolbarButton, E as EmptyStateConfig, j as ExportOptions, G as GetRowId, P as ParsedAddress } from './types-CEpcvwwF.js';
18
18
  import { ColumnDef } from '@tanstack/react-table';
19
- import { F as FileSizeLimits, S as StorageConfig, a as StorageUploadOptions, b as StorageFileMetadata, c as StorageUploadResult, d as StorageUrlOptions, e as StorageListOptions, f as StorageListResult } from './usePublicRouteParams-TZe0gy-4.js';
20
- export { m as StorageFileInfo, U as UseFormDialogOptions, h as UseFormDialogReturn, H as UsePublicEventLogoOptions, G as UsePublicEventLogoReturn, C as UsePublicEventOptions, B as UsePublicEventReturn, E as UsePublicFileDisplayOptions, D as UsePublicFileDisplayReturn, I as UsePublicRouteParamsReturn, o as clearPublicEventCache, r as clearPublicFileDisplayCache, v as clearPublicLogoCache, A as extractEventCodeFromPath, z as generatePublicRoutePath, p as getPublicEventCacheStats, s as getPublicFileDisplayCacheStats, w as getPublicLogoCacheStats, k as useAppConfig, l as useEventTheme, g as useFormDialog, i as useOrganisationPermissions, j as useOrganisationSecurity, n as usePublicEvent, y as usePublicEventCode, t as usePublicEventLogo, q as usePublicFileDisplay, x as usePublicRouteParams, u as useZodForm } from './usePublicRouteParams-TZe0gy-4.js';
19
+ import { F as FileSizeLimits, S as StorageConfig, a as StorageUploadOptions, b as StorageFileMetadata, c as StorageUploadResult, d as StorageUrlOptions, e as StorageListOptions, f as StorageListResult } from './usePublicRouteParams-BJAlWfuJ.js';
20
+ export { m as StorageFileInfo, U as UseFormDialogOptions, h as UseFormDialogReturn, H as UsePublicEventLogoOptions, G as UsePublicEventLogoReturn, C as UsePublicEventOptions, B as UsePublicEventReturn, E as UsePublicFileDisplayOptions, D as UsePublicFileDisplayReturn, I as UsePublicRouteParamsReturn, o as clearPublicEventCache, r as clearPublicFileDisplayCache, v as clearPublicLogoCache, A as extractEventCodeFromPath, z as generatePublicRoutePath, p as getPublicEventCacheStats, s as getPublicFileDisplayCacheStats, w as getPublicLogoCacheStats, k as useAppConfig, l as useEventTheme, g as useFormDialog, i as useOrganisationPermissions, j as useOrganisationSecurity, n as usePublicEvent, y as usePublicEventCode, t as usePublicEventLogo, q as usePublicFileDisplay, x as usePublicRouteParams, u as useZodForm } from './usePublicRouteParams-BJAlWfuJ.js';
21
21
  export { z } from 'zod';
22
22
  export { F as FileCategory, b as FileMetadata, a as FileReference, c as FileUploadOptions } from './file-reference-BavO2eQj.js';
23
23
  import { SupabaseClient } from '@supabase/supabase-js';
@@ -254,7 +254,7 @@ declare function useSessionRestoration(): UseSessionRestorationResult;
254
254
  * - Optimized timer management
255
255
  *
256
256
  * @dependencies
257
- * - React 18+ - Hooks and effects
257
+ * - React 19+ - Hooks and effects
258
258
  * - Dialog components - Modal functionality
259
259
  * - Tailwind CSS v4 - Styling
260
260
  */
@@ -326,7 +326,7 @@ declare function InactivityWarningModal({ isOpen, timeRemaining, onStaySignedIn,
326
326
  * - Cross-tab optimization
327
327
  *
328
328
  * @dependencies
329
- * - React 18+ - Hooks and effects
329
+ * - React 19+ - Hooks and effects
330
330
  * - Browser APIs - BroadcastChannel, localStorage, timers
331
331
  */
332
332
  interface UseInactivityTrackerOptions {