@jmruthers/pace-core 0.5.189 → 0.5.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core-usage-manifest.json +0 -4
- package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
- package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
- package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
- package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
- package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
- package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
- package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
- package/dist/chunk-4QYC5L4K.js.map +1 -0
- package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
- package/dist/chunk-73HSNNOQ.js.map +1 -0
- package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
- package/dist/chunk-DZWK57KZ.js.map +1 -0
- package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
- package/dist/chunk-HQVPB5MZ.js.map +1 -0
- package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
- package/dist/chunk-HW3OVDUF.js.map +1 -0
- package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
- package/dist/chunk-I7PSE6JW.js.map +1 -0
- package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
- package/dist/chunk-J2XXC7R5.js.map +1 -0
- package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
- package/dist/chunk-NIU6J6OX.js.map +1 -0
- package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
- package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
- package/dist/chunk-RUYZKXOD.js.map +1 -0
- package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
- package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
- package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
- package/dist/chunk-STYK4OH2.js.map +1 -0
- package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
- package/dist/chunk-VVBAW5A5.js.map +1 -0
- package/dist/chunk-Y4BUBBHD.js +614 -0
- package/dist/chunk-Y4BUBBHD.js.map +1 -0
- package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
- package/dist/chunk-ZSAAAMVR.js.map +1 -0
- package/dist/components.d.ts +3 -4
- package/dist/components.js +19 -19
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
- package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
- package/dist/hooks.d.ts +10 -5
- package/dist/hooks.js +14 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.js +79 -69
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +76 -12
- package/dist/rbac/index.js +12 -9
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
- package/dist/utils.js +16 -16
- package/docs/README.md +2 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +2 -2
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +2 -2
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +4 -4
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +2 -2
- package/docs/api/classes/SecureSupabaseClient.md +21 -16
- package/docs/api/classes/StorageUtils.md +7 -4
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +20 -6
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +62 -16
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +2 -2
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +26 -12
- package/docs/api/interfaces/FileUploadProps.md +30 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +3 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +4 -4
- package/docs/api/interfaces/StorageFileInfo.md +7 -7
- package/docs/api/interfaces/StorageFileMetadata.md +25 -14
- package/docs/api/interfaces/StorageListOptions.md +22 -9
- package/docs/api/interfaces/StorageListResult.md +4 -4
- package/docs/api/interfaces/StorageUploadOptions.md +21 -8
- package/docs/api/interfaces/StorageUploadResult.md +6 -6
- package/docs/api/interfaces/StorageUrlOptions.md +19 -6
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +151 -92
- package/docs/api-reference/components.md +15 -7
- package/docs/api-reference/providers.md +2 -2
- package/docs/api-reference/rpc-functions.md +1 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/deployment.md +8 -8
- package/docs/getting-started/examples/README.md +2 -2
- package/docs/getting-started/installation-guide.md +4 -4
- package/docs/getting-started/quick-start.md +3 -3
- package/docs/migration/MIGRATION_GUIDE.md +3 -3
- package/docs/rbac/compliance/compliance-guide.md +2 -2
- package/docs/rbac/event-based-apps.md +2 -2
- package/docs/rbac/getting-started.md +2 -2
- package/docs/rbac/quick-start.md +2 -2
- package/docs/security/README.md +4 -4
- package/docs/standards/07-rbac-and-rls-standard.md +430 -7
- package/docs/troubleshooting/README.md +2 -2
- package/docs/troubleshooting/migration.md +3 -3
- package/package.json +1 -3
- package/scripts/check-pace-core-compliance.cjs +1 -1
- package/scripts/check-pace-core-compliance.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +301 -0
- package/src/__tests__/public-recipe-view.test.ts +9 -9
- package/src/__tests__/rls-policies.test.ts +197 -61
- package/src/components/AddressField/AddressField.test.tsx +42 -0
- package/src/components/AddressField/AddressField.tsx +71 -60
- package/src/components/AddressField/README.md +1 -0
- package/src/components/Alert/Alert.test.tsx +50 -10
- package/src/components/Alert/Alert.tsx +5 -3
- package/src/components/Avatar/Avatar.test.tsx +95 -43
- package/src/components/Avatar/Avatar.tsx +16 -16
- package/src/components/Button/Button.test.tsx +2 -1
- package/src/components/Button/Button.tsx +3 -3
- package/src/components/Calendar/Calendar.test.tsx +53 -37
- package/src/components/Calendar/Calendar.tsx +409 -82
- package/src/components/Card/Card.test.tsx +7 -4
- package/src/components/Card/Card.tsx +3 -6
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/components/ActionButtons.tsx +5 -5
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
- package/src/components/DataTable/components/DataTableBody.tsx +12 -12
- package/src/components/DataTable/components/DataTableCore.tsx +3 -3
- package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
- package/src/components/DataTable/components/EditableRow.tsx +2 -2
- package/src/components/DataTable/components/EmptyState.tsx +3 -3
- package/src/components/DataTable/components/GroupHeader.tsx +2 -2
- package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
- package/src/components/DataTable/components/ImportModal.tsx +4 -4
- package/src/components/DataTable/components/LoadingState.tsx +1 -1
- package/src/components/DataTable/components/PaginationControls.tsx +11 -11
- package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
- package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
- package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/EventSelector/EventSelector.tsx +7 -7
- package/src/components/FileDisplay/FileDisplay.tsx +291 -179
- package/src/components/FileUpload/FileUpload.tsx +7 -4
- package/src/components/Header/Header.test.tsx +28 -0
- package/src/components/Header/Header.tsx +22 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
- package/src/components/PaceAppLayout/test-setup.tsx +1 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
- package/src/components/Progress/Progress.test.tsx +18 -19
- package/src/components/Progress/Progress.tsx +31 -32
- package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
- package/src/components/Select/Select.tsx +5 -5
- package/src/components/Switch/Switch.test.tsx +2 -1
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.test.tsx +8 -2
- package/src/components/UserMenu/UserMenu.tsx +3 -3
- package/src/eslint-rules/pace-core-compliance.cjs +0 -2
- package/src/eslint-rules/pace-core-compliance.js +0 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
- package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
- package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
- package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
- package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
- package/src/hooks/index.ts +1 -1
- package/src/hooks/public/usePublicEvent.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.ts +173 -87
- package/src/hooks/useAppConfig.ts +24 -5
- package/src/hooks/useFileDisplay.ts +297 -34
- package/src/hooks/useFileReference.ts +56 -11
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useInactivityTracker.ts +16 -7
- package/src/hooks/usePermissionCache.test.ts +85 -8
- package/src/hooks/useQueryCache.ts +21 -0
- package/src/hooks/useSecureDataAccess.test.ts +80 -35
- package/src/hooks/useSecureDataAccess.ts +80 -37
- package/src/providers/services/EventServiceProvider.tsx +37 -17
- package/src/providers/services/InactivityServiceProvider.tsx +4 -4
- package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
- package/src/rbac/api.ts +240 -36
- package/src/rbac/cache-invalidation.ts +21 -7
- package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
- package/src/rbac/components/NavigationGuard.tsx +23 -63
- package/src/rbac/components/NavigationProvider.test.tsx +52 -23
- package/src/rbac/components/NavigationProvider.tsx +13 -11
- package/src/rbac/components/PagePermissionGuard.tsx +77 -203
- package/src/rbac/components/PagePermissionProvider.tsx +13 -11
- package/src/rbac/components/PermissionEnforcer.tsx +24 -62
- package/src/rbac/components/RoleBasedRouter.tsx +14 -12
- package/src/rbac/components/SecureDataProvider.tsx +13 -11
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
- package/src/rbac/engine.ts +4 -2
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/useCan.test.ts +101 -53
- package/src/rbac/hooks/usePermissions.ts +108 -41
- package/src/rbac/hooks/useRBAC.test.ts +11 -3
- package/src/rbac/hooks/useRBAC.ts +83 -40
- package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
- package/src/rbac/hooks/useResolvedScope.ts +128 -70
- package/src/rbac/hooks/useSecureSupabase.ts +36 -19
- package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
- package/src/rbac/request-deduplication.ts +1 -1
- package/src/rbac/secureClient.ts +72 -12
- package/src/rbac/security.ts +29 -23
- package/src/rbac/types.ts +10 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
- package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
- package/src/rbac/utils/contextValidator.ts +288 -0
- package/src/rbac/utils/eventContext.ts +48 -2
- package/src/services/EventService.ts +165 -21
- package/src/services/OrganisationService.ts +37 -2
- package/src/services/__tests__/EventService.test.ts +26 -21
- package/src/types/file-reference.ts +13 -10
- package/src/utils/app/appNameResolver.test.ts +346 -73
- package/src/utils/context/superAdminOverride.ts +58 -0
- package/src/utils/file-reference/index.ts +61 -33
- package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
- package/src/utils/storage/helpers.test.ts +1 -1
- package/src/utils/storage/helpers.ts +38 -19
- package/src/utils/storage/types.ts +15 -8
- package/src/utils/validation/__tests__/csrf.test.ts +105 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
- package/src/vite-env.d.ts +2 -2
- package/dist/chunk-3GOZZZYH.js.map +0 -1
- package/dist/chunk-DDM4CCYT.js.map +0 -1
- package/dist/chunk-E7UAOUMY.js +0 -75
- package/dist/chunk-E7UAOUMY.js.map +0 -1
- package/dist/chunk-F2IMUDXZ.js.map +0 -1
- package/dist/chunk-HEHYGYOX.js.map +0 -1
- package/dist/chunk-IM4QE42D.js.map +0 -1
- package/dist/chunk-MX64ZF6I.js.map +0 -1
- package/dist/chunk-SAUPYVLF.js.map +0 -1
- package/dist/chunk-THRPYOFK.js.map +0 -1
- package/dist/chunk-UCQSRW7Z.js.map +0 -1
- package/dist/chunk-VGZZXKBR.js.map +0 -1
- package/dist/chunk-YGPFYGA6.js.map +0 -1
- package/dist/chunk-YHCN776L.js.map +0 -1
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
- /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
- /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
- /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
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>;\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"]}
|
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-
|
|
1
|
+
export { a as UnifiedAuthContextType, d as UnifiedAuthProvider, c as UnifiedAuthProviderProps, U as UserEventAccess, u as useUnifiedAuth } from './UnifiedAuthProvider-BYA9qB-o.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-
|
|
4
|
-
export { c as EventServiceProvider, i as InactivityServiceProvider, f as OrganisationServiceProvider } from './AuthService-
|
|
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';
|
|
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,17 +9,17 @@ 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, 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-
|
|
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-C4uxosp6.js';
|
|
14
14
|
export { u as useToast } from './useToast-C8gR5ir4.js';
|
|
15
15
|
export { D as DataTable, a as DataTableProps } from './DataTable-IVYljGJ6.js';
|
|
16
16
|
import { d as DataRecord, a as DataTableAction, D as DataTableColumn } from './types-Bwgl--Xo.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-Bwgl--Xo.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-
|
|
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-
|
|
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-DxIDS4bC.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-DxIDS4bC.js';
|
|
21
21
|
export { z } from 'zod';
|
|
22
|
-
export { F as FileCategory, b as FileMetadata, a as FileReference, c as FileUploadOptions } from './file-reference-
|
|
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';
|
|
24
24
|
export { StyleImport, getAllStylePaths, getStylePath, styleConfig } from './styles/index.js';
|
|
25
25
|
export { ColorPalette, ColorShade, PaletteData, applyPalette, clearPalette, parseAndNormalizeEventColours } from './theming/runtime.js';
|
|
@@ -29,7 +29,6 @@ import './database.generated-DI89OQeI.js';
|
|
|
29
29
|
import '@radix-ui/react-label';
|
|
30
30
|
import '@radix-ui/react-checkbox';
|
|
31
31
|
import '@radix-ui/react-switch';
|
|
32
|
-
import '@radix-ui/react-progress';
|
|
33
32
|
import '@radix-ui/react-dialog';
|
|
34
33
|
import '@radix-ui/react-tabs';
|
|
35
34
|
import 'react-day-picker';
|
|
@@ -710,7 +709,9 @@ declare function validateFileSize(file: File): {
|
|
|
710
709
|
*/
|
|
711
710
|
|
|
712
711
|
/**
|
|
713
|
-
* Generate a file path based on organization-first structure
|
|
712
|
+
* Generate a file path based on organization-first or user-first structure
|
|
713
|
+
* - If orgId is provided: {orgId}/{folder}/filename
|
|
714
|
+
* - If userId is provided (and orgId is not): users/{userId}/{folder}/filename
|
|
714
715
|
*/
|
|
715
716
|
declare function generateFilePath(options: StorageUploadOptions, fileName: string): string;
|
|
716
717
|
/**
|
|
@@ -804,7 +805,8 @@ declare function downloadFile(supabase: SupabaseClient, path: string, isPublic?:
|
|
|
804
805
|
*/
|
|
805
806
|
declare function archiveFile(supabase: SupabaseClient, path: string, options: {
|
|
806
807
|
appName: string;
|
|
807
|
-
orgId
|
|
808
|
+
orgId?: string;
|
|
809
|
+
userId?: string;
|
|
808
810
|
isPublic?: boolean;
|
|
809
811
|
}): Promise<{
|
|
810
812
|
success: boolean;
|