@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
|
@@ -127,7 +127,7 @@ export function BulkOperationsDropdown({
|
|
|
127
127
|
disabled={!hasSelection}
|
|
128
128
|
className={`min-w-[140px] h-9 px-3 py-2 text-sm font-medium ${className || ''}`}
|
|
129
129
|
>
|
|
130
|
-
<MoreHorizontal className="
|
|
130
|
+
<MoreHorizontal className="size-4 mr-2 flex-shrink-0" />
|
|
131
131
|
<span className="truncate">
|
|
132
132
|
Bulk Actions ({selectedCount})
|
|
133
133
|
</span>
|
|
@@ -149,7 +149,7 @@ export function BulkOperationsDropdown({
|
|
|
149
149
|
variant === 'destructive' ? 'text-destructive focus:text-destructive' : ''
|
|
150
150
|
}`}
|
|
151
151
|
>
|
|
152
|
-
<Icon className="
|
|
152
|
+
<Icon className="size-4" />
|
|
153
153
|
<span>{label}</span>
|
|
154
154
|
</SelectItem>
|
|
155
155
|
);
|
|
@@ -30,7 +30,7 @@ export function ColumnVisibilityDropdown<TData>({
|
|
|
30
30
|
<Button
|
|
31
31
|
variant="outline"
|
|
32
32
|
>
|
|
33
|
-
<Settings2 className="
|
|
33
|
+
<Settings2 className="size-4 mr-2 flex-shrink-0" />
|
|
34
34
|
<span className="truncate">Columns</span>
|
|
35
35
|
</Button>
|
|
36
36
|
</SelectTrigger>
|
|
@@ -49,7 +49,7 @@ export function ColumnVisibilityDropdown<TData>({
|
|
|
49
49
|
});
|
|
50
50
|
}}
|
|
51
51
|
>
|
|
52
|
-
<Eye className="
|
|
52
|
+
<Eye className="size-3 mr-1" />
|
|
53
53
|
Show All
|
|
54
54
|
</Button>
|
|
55
55
|
<Button
|
|
@@ -64,7 +64,7 @@ export function ColumnVisibilityDropdown<TData>({
|
|
|
64
64
|
});
|
|
65
65
|
}}
|
|
66
66
|
>
|
|
67
|
-
<EyeOff className="
|
|
67
|
+
<EyeOff className="size-3 mr-1" />
|
|
68
68
|
Hide All
|
|
69
69
|
</Button>
|
|
70
70
|
</div>
|
|
@@ -222,14 +222,14 @@ export function DataTableBody<TData extends DataRecord>({
|
|
|
222
222
|
variant="ghost"
|
|
223
223
|
size="sm"
|
|
224
224
|
onClick={hierarchical.isAllExpanded ? hierarchical.collapseAll : hierarchical.expandAll}
|
|
225
|
-
className="
|
|
225
|
+
className="size-8 p-0"
|
|
226
226
|
aria-label={hierarchical.isAllExpanded ? 'Collapse all' : 'Expand all'}
|
|
227
227
|
title={hierarchical.isAllExpanded ? 'Collapse all' : 'Expand all'}
|
|
228
228
|
>
|
|
229
229
|
{hierarchical.isAllExpanded ? (
|
|
230
|
-
<ChevronDown className="
|
|
230
|
+
<ChevronDown className="size-4" />
|
|
231
231
|
) : (
|
|
232
|
-
<ChevronRight className="
|
|
232
|
+
<ChevronRight className="size-4" />
|
|
233
233
|
)}
|
|
234
234
|
</Button>
|
|
235
235
|
</th>
|
|
@@ -263,11 +263,11 @@ export function DataTableBody<TData extends DataRecord>({
|
|
|
263
263
|
? header.column.columnDef.header(header.getContext())
|
|
264
264
|
: header.column.columnDef.header}
|
|
265
265
|
{header.column.getIsSorted() === 'asc' ? (
|
|
266
|
-
<ChevronUp className="
|
|
266
|
+
<ChevronUp className="size-4" />
|
|
267
267
|
) : header.column.getIsSorted() === 'desc' ? (
|
|
268
|
-
<ChevronDown className="
|
|
268
|
+
<ChevronDown className="size-4" />
|
|
269
269
|
) : (
|
|
270
|
-
<ChevronsUpDown className="
|
|
270
|
+
<ChevronsUpDown className="size-4" />
|
|
271
271
|
)}
|
|
272
272
|
</div>
|
|
273
273
|
</Button>
|
|
@@ -308,19 +308,19 @@ export function DataTableBody<TData extends DataRecord>({
|
|
|
308
308
|
<>
|
|
309
309
|
<button
|
|
310
310
|
onClick={onSaveCreation}
|
|
311
|
-
className="
|
|
311
|
+
className="size-8 p-0 bg-app-main-500 text-app-main-50 rounded hover:bg-app-main-600 flex items-center justify-center"
|
|
312
312
|
title="Save new row"
|
|
313
313
|
>
|
|
314
|
-
<svg className="
|
|
314
|
+
<svg className="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
315
315
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
316
316
|
</svg>
|
|
317
317
|
</button>
|
|
318
318
|
<button
|
|
319
319
|
onClick={onCancelCreation}
|
|
320
|
-
className="
|
|
320
|
+
className="size-8 p-0 bg-app-sec-500 text-app-main-50 rounded hover:bg-app-sec-600 flex items-center justify-center"
|
|
321
321
|
title="Cancel new row"
|
|
322
322
|
>
|
|
323
|
-
<svg className="
|
|
323
|
+
<svg className="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
324
324
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
325
325
|
</svg>
|
|
326
326
|
</button>
|
|
@@ -368,9 +368,9 @@ export function DataTableBody<TData extends DataRecord>({
|
|
|
368
368
|
className="p-0 h-auto mr-2"
|
|
369
369
|
>
|
|
370
370
|
{isExpanded ? (
|
|
371
|
-
<ChevronDown className="
|
|
371
|
+
<ChevronDown className="size-4" />
|
|
372
372
|
) : (
|
|
373
|
-
<ChevronRight className="
|
|
373
|
+
<ChevronRight className="size-4" />
|
|
374
374
|
)}
|
|
375
375
|
</Button>
|
|
376
376
|
<span className="text-sm">
|
|
@@ -1120,11 +1120,11 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
1120
1120
|
? header.column.columnDef.header(header.getContext())
|
|
1121
1121
|
: header.column.columnDef.header}
|
|
1122
1122
|
{header.column.getIsSorted() === 'asc' ? (
|
|
1123
|
-
<ChevronUp className="
|
|
1123
|
+
<ChevronUp className="size-4" />
|
|
1124
1124
|
) : header.column.getIsSorted() === 'desc' ? (
|
|
1125
|
-
<ChevronDown className="
|
|
1125
|
+
<ChevronDown className="size-4" />
|
|
1126
1126
|
) : (
|
|
1127
|
-
<ChevronsUpDown className="
|
|
1127
|
+
<ChevronsUpDown className="size-4" />
|
|
1128
1128
|
)}
|
|
1129
1129
|
</Button>
|
|
1130
1130
|
) : (
|
|
@@ -204,7 +204,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
204
204
|
variant="outline"
|
|
205
205
|
onClick={onToggleFilterRow}
|
|
206
206
|
>
|
|
207
|
-
<Filter className="
|
|
207
|
+
<Filter className="size-4 mr-2 flex-shrink-0" />
|
|
208
208
|
<span className="truncate">
|
|
209
209
|
{showFilterRow ? 'Hide Filters' : 'Show Filters'}
|
|
210
210
|
</span>
|
|
@@ -217,7 +217,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
217
217
|
variant="outline"
|
|
218
218
|
onClick={onCreateRow}
|
|
219
219
|
>
|
|
220
|
-
<Plus className="
|
|
220
|
+
<Plus className="size-4 mr-2 flex-shrink-0" />
|
|
221
221
|
<span className="truncate">Add Row</span>
|
|
222
222
|
</Button>
|
|
223
223
|
)}
|
|
@@ -229,7 +229,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
229
229
|
onClick={onImportClick}
|
|
230
230
|
data-restore-target="datatable-import-button"
|
|
231
231
|
>
|
|
232
|
-
<Upload className="
|
|
232
|
+
<Upload className="size-4 mr-2 flex-shrink-0" />
|
|
233
233
|
<span className="truncate">Import</span>
|
|
234
234
|
</Button>
|
|
235
235
|
)}
|
|
@@ -240,7 +240,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
240
240
|
variant="outline"
|
|
241
241
|
onClick={onExport}
|
|
242
242
|
>
|
|
243
|
-
<Download className="
|
|
243
|
+
<Download className="size-4 mr-2 flex-shrink-0" />
|
|
244
244
|
<span className="truncate">Export</span>
|
|
245
245
|
</Button>
|
|
246
246
|
)}
|
|
@@ -252,7 +252,7 @@ export function DataTableToolbar<TData extends DataRecord>({
|
|
|
252
252
|
onClick={() => onDeleteSelected?.(rowSelection)}
|
|
253
253
|
disabled={Object.values(rowSelection).filter(Boolean).length === 0}
|
|
254
254
|
>
|
|
255
|
-
<Trash2 className="
|
|
255
|
+
<Trash2 className="size-4 mr-2 flex-shrink-0" />
|
|
256
256
|
<span className="truncate">Delete</span>
|
|
257
257
|
</Button>
|
|
258
258
|
)}
|
|
@@ -121,11 +121,11 @@ export function DraggableColumnHeader<TData>({
|
|
|
121
121
|
? header.column.columnDef.header(header.getContext())
|
|
122
122
|
: header.column.columnDef.header}
|
|
123
123
|
{header.column.getIsSorted() === 'asc' ? (
|
|
124
|
-
<ChevronUp className="
|
|
124
|
+
<ChevronUp className="size-4" />
|
|
125
125
|
) : header.column.getIsSorted() === 'desc' ? (
|
|
126
|
-
<ChevronDown className="
|
|
126
|
+
<ChevronDown className="size-4" />
|
|
127
127
|
) : (
|
|
128
|
-
<ChevronsUpDown className="
|
|
128
|
+
<ChevronsUpDown className="size-4" />
|
|
129
129
|
)}
|
|
130
130
|
</div>
|
|
131
131
|
</Button>
|
|
@@ -378,10 +378,10 @@ export function EditableRow<TData extends DataRecord>({
|
|
|
378
378
|
cell.column.id === 'actions' ? (
|
|
379
379
|
<div className="flex gap-1">
|
|
380
380
|
<Button onClick={onSave} size="sm" variant="default" aria-label="Save changes">
|
|
381
|
-
<Check className="
|
|
381
|
+
<Check className="size-4" />
|
|
382
382
|
</Button>
|
|
383
383
|
<Button onClick={onCancel} size="sm" variant="outline" aria-label="Cancel editing">
|
|
384
|
-
<X className="
|
|
384
|
+
<X className="size-4" />
|
|
385
385
|
</Button>
|
|
386
386
|
</div>
|
|
387
387
|
) : (
|
|
@@ -36,7 +36,7 @@ export function EmptyState({
|
|
|
36
36
|
<Icon
|
|
37
37
|
role="img"
|
|
38
38
|
aria-hidden="true"
|
|
39
|
-
className="
|
|
39
|
+
className="size-12 text-muted-foreground mb-4"
|
|
40
40
|
data-testid={Icon === Database ? 'lucide-database' : Icon === User ? 'lucide-user' : 'custom-icon'}
|
|
41
41
|
/>
|
|
42
42
|
<h3 className="text-lg font-semibold mb-2">
|
|
@@ -50,14 +50,14 @@ export function EmptyState({
|
|
|
50
50
|
<div className="flex gap-2">
|
|
51
51
|
{isFiltered && onClearFilters && (
|
|
52
52
|
<Button variant="outline" onClick={onClearFilters}>
|
|
53
|
-
<Search className="
|
|
53
|
+
<Search className="size-4 mr-2" />
|
|
54
54
|
Clear filters
|
|
55
55
|
</Button>
|
|
56
56
|
)}
|
|
57
57
|
|
|
58
58
|
{action && (
|
|
59
59
|
<Button onClick={action.onClick}>
|
|
60
|
-
<Plus className="
|
|
60
|
+
<Plus className="size-4 mr-2" />
|
|
61
61
|
{action.label}
|
|
62
62
|
</Button>
|
|
63
63
|
)}
|
|
@@ -29,9 +29,9 @@ export function GroupHeader<TData>({
|
|
|
29
29
|
className="p-0 h-auto mr-2"
|
|
30
30
|
>
|
|
31
31
|
{isExpanded ? (
|
|
32
|
-
<ChevronDown className="
|
|
32
|
+
<ChevronDown className="size-4" />
|
|
33
33
|
) : (
|
|
34
|
-
<ChevronRight className="
|
|
34
|
+
<ChevronRight className="size-4" />
|
|
35
35
|
)}
|
|
36
36
|
</Button>
|
|
37
37
|
<span className="text-sm">
|
|
@@ -62,7 +62,7 @@ export function GroupingDropdown<TData extends DataRecord>({
|
|
|
62
62
|
variant="outline"
|
|
63
63
|
className={className || ''}
|
|
64
64
|
>
|
|
65
|
-
<Group className="
|
|
65
|
+
<Group className="size-4 mr-2 flex-shrink-0" />
|
|
66
66
|
<span className="truncate">Grouping</span>
|
|
67
67
|
</Button>
|
|
68
68
|
</SelectTrigger>
|
|
@@ -375,7 +375,7 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
375
375
|
|
|
376
376
|
<div className="space-y-4">
|
|
377
377
|
<div className="border-2 border-dashed border-sec-200 rounded-lg p-6 text-center">
|
|
378
|
-
<FileText className="
|
|
378
|
+
<FileText className="size-8 mx-auto text-sec-400 mb-2" />
|
|
379
379
|
<p className="text-sec-600 mb-2">
|
|
380
380
|
{file ? `Selected: ${file.name}` : uploadText}
|
|
381
381
|
</p>
|
|
@@ -389,7 +389,7 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
389
389
|
size="sm"
|
|
390
390
|
onClick={() => fileInputRef.current?.click()}
|
|
391
391
|
>
|
|
392
|
-
<Upload className="
|
|
392
|
+
<Upload className="size-4 mr-2" />
|
|
393
393
|
{selectFileButtonText}
|
|
394
394
|
</Button>
|
|
395
395
|
<Input
|
|
@@ -403,7 +403,7 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
403
403
|
|
|
404
404
|
{error && (
|
|
405
405
|
<div className="flex items-center gap-2 p-3 bg-acc-50 border border-acc-200 rounded text-acc-700">
|
|
406
|
-
<AlertCircle className="
|
|
406
|
+
<AlertCircle className="size-4" />
|
|
407
407
|
<span className="text-sm">{error}</span>
|
|
408
408
|
</div>
|
|
409
409
|
)}
|
|
@@ -411,7 +411,7 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
411
411
|
{validationErrors.length > 0 && (
|
|
412
412
|
<div className="space-y-2">
|
|
413
413
|
<div className="flex items-center gap-2 p-3 bg-acc-50 border border-acc-200 rounded text-acc-700">
|
|
414
|
-
<AlertCircle className="
|
|
414
|
+
<AlertCircle className="size-4" />
|
|
415
415
|
<span className="text-sm font-medium">
|
|
416
416
|
{validationErrors.length} validation error{validationErrors.length !== 1 ? 's' : ''} found
|
|
417
417
|
</span>
|
|
@@ -4,7 +4,7 @@ export function LoadingState() {
|
|
|
4
4
|
return (
|
|
5
5
|
<div className="p-8 text-center">
|
|
6
6
|
<div className="flex items-center justify-center space-x-2">
|
|
7
|
-
<div className="animate-spin rounded-full
|
|
7
|
+
<div className="animate-spin rounded-full size-6 border-b-2 border-primary"></div>
|
|
8
8
|
<span aria-live="polite" className="text-muted-foreground">Loading...</span>
|
|
9
9
|
</div>
|
|
10
10
|
</div>
|
|
@@ -76,11 +76,11 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
76
76
|
const getModeIcon = () => {
|
|
77
77
|
switch (paginationMode) {
|
|
78
78
|
case 'server':
|
|
79
|
-
return <Server className="
|
|
79
|
+
return <Server className="size-3" />;
|
|
80
80
|
case 'hybrid':
|
|
81
|
-
return <Database className="
|
|
81
|
+
return <Database className="size-3" />;
|
|
82
82
|
default:
|
|
83
|
-
return <Zap className="
|
|
83
|
+
return <Zap className="size-3" />;
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
|
|
@@ -157,49 +157,49 @@ export function PaginationControls<TData extends DataRecord>({
|
|
|
157
157
|
<Button
|
|
158
158
|
variant="outline"
|
|
159
159
|
size="sm"
|
|
160
|
-
className="
|
|
160
|
+
className="size-8 p-0"
|
|
161
161
|
onClick={goToFirstPage}
|
|
162
162
|
disabled={!canPreviousPage || isLoading}
|
|
163
163
|
aria-label="Go to first page"
|
|
164
164
|
tabIndex={0}
|
|
165
165
|
>
|
|
166
|
-
<ChevronsLeft className="
|
|
166
|
+
<ChevronsLeft className="size-4" />
|
|
167
167
|
</Button>
|
|
168
168
|
|
|
169
169
|
<Button
|
|
170
170
|
variant="outline"
|
|
171
171
|
size="sm"
|
|
172
|
-
className="
|
|
172
|
+
className="size-8 p-0"
|
|
173
173
|
onClick={goToPreviousPage}
|
|
174
174
|
disabled={!canPreviousPage || isLoading}
|
|
175
175
|
aria-label="Go to previous page"
|
|
176
176
|
tabIndex={0}
|
|
177
177
|
>
|
|
178
|
-
<ChevronLeft className="
|
|
178
|
+
<ChevronLeft className="size-4" />
|
|
179
179
|
</Button>
|
|
180
180
|
|
|
181
181
|
<Button
|
|
182
182
|
variant="outline"
|
|
183
183
|
size="sm"
|
|
184
|
-
className="
|
|
184
|
+
className="size-8 p-0"
|
|
185
185
|
onClick={goToNextPage}
|
|
186
186
|
disabled={!canNextPage || isLoading}
|
|
187
187
|
aria-label="Go to next page"
|
|
188
188
|
tabIndex={0}
|
|
189
189
|
>
|
|
190
|
-
<ChevronRight className="
|
|
190
|
+
<ChevronRight className="size-4" />
|
|
191
191
|
</Button>
|
|
192
192
|
|
|
193
193
|
<Button
|
|
194
194
|
variant="outline"
|
|
195
195
|
size="sm"
|
|
196
|
-
className="
|
|
196
|
+
className="size-8 p-0"
|
|
197
197
|
onClick={goToLastPage}
|
|
198
198
|
disabled={!canNextPage || isLoading}
|
|
199
199
|
aria-label="Go to last page"
|
|
200
200
|
tabIndex={0}
|
|
201
201
|
>
|
|
202
|
-
<ChevronsRight className="
|
|
202
|
+
<ChevronsRight className="size-4" />
|
|
203
203
|
</Button>
|
|
204
204
|
</footer>
|
|
205
205
|
);
|
|
@@ -594,9 +594,9 @@ const RowComponent = React.memo(({
|
|
|
594
594
|
className="p-0 h-auto mr-2"
|
|
595
595
|
>
|
|
596
596
|
{isExpanded ? (
|
|
597
|
-
<ChevronDown className="
|
|
597
|
+
<ChevronDown className="size-4" />
|
|
598
598
|
) : (
|
|
599
|
-
<ChevronRight className="
|
|
599
|
+
<ChevronRight className="size-4" />
|
|
600
600
|
)}
|
|
601
601
|
</Button>
|
|
602
602
|
<span className="text-sm">
|
|
@@ -755,14 +755,14 @@ const RowComponent = React.memo(({
|
|
|
755
755
|
variant="ghost"
|
|
756
756
|
size="sm"
|
|
757
757
|
onClick={() => hierarchical?.state?.toggleRow(rowId)}
|
|
758
|
-
className="
|
|
758
|
+
className="size-6 p-0 flex-shrink-0"
|
|
759
759
|
aria-label={isExpanded ? 'Collapse row' : 'Expand row'}
|
|
760
760
|
title={isExpanded ? 'Collapse row' : 'Expand row'}
|
|
761
761
|
>
|
|
762
762
|
{isExpanded ? (
|
|
763
|
-
<ChevronDown className="
|
|
763
|
+
<ChevronDown className="size-4" />
|
|
764
764
|
) : (
|
|
765
|
-
<ChevronRight className="
|
|
765
|
+
<ChevronRight className="size-4" />
|
|
766
766
|
)}
|
|
767
767
|
</Button>
|
|
768
768
|
)}
|
|
@@ -1039,19 +1039,19 @@ export function UnifiedTableBody<TData extends Record<string, any>>({
|
|
|
1039
1039
|
>
|
|
1040
1040
|
<button
|
|
1041
1041
|
onClick={onSaveCreation}
|
|
1042
|
-
className="
|
|
1042
|
+
className="size-8 p-0 hover:bg-muted/50 flex items-center justify-center"
|
|
1043
1043
|
title="Save new row"
|
|
1044
1044
|
>
|
|
1045
|
-
<svg className="
|
|
1045
|
+
<svg className="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
1046
1046
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
1047
1047
|
</svg>
|
|
1048
1048
|
</button>
|
|
1049
1049
|
<button
|
|
1050
1050
|
onClick={onCancelCreation}
|
|
1051
|
-
className="
|
|
1051
|
+
className="size-8 p-0 hover:bg-muted/50 flex items-center justify-center"
|
|
1052
1052
|
title="Cancel new row"
|
|
1053
1053
|
>
|
|
1054
|
-
<svg className="
|
|
1054
|
+
<svg className="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
1055
1055
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
1056
1056
|
</svg>
|
|
1057
1057
|
</button>
|
|
@@ -35,9 +35,9 @@ export function ViewRowModal<TData extends Record<string, any>>({
|
|
|
35
35
|
variant="ghost"
|
|
36
36
|
size="sm"
|
|
37
37
|
onClick={onClose}
|
|
38
|
-
className="
|
|
38
|
+
className="size-6 p-0"
|
|
39
39
|
>
|
|
40
|
-
<X className="
|
|
40
|
+
<X className="size-4" />
|
|
41
41
|
</Button>
|
|
42
42
|
</DialogTitle>
|
|
43
43
|
</DialogHeader>
|
|
@@ -14,35 +14,6 @@ import userEvent from '@testing-library/user-event';
|
|
|
14
14
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
15
15
|
import { AccessDeniedPage } from '../AccessDeniedPage';
|
|
16
16
|
|
|
17
|
-
// Mock lucide-react icons
|
|
18
|
-
vi.mock('lucide-react', () => ({
|
|
19
|
-
ShieldX: ({ className }: { className?: string }) => (
|
|
20
|
-
<div data-testid="shield-x-icon" className={className}>ShieldX</div>
|
|
21
|
-
),
|
|
22
|
-
ArrowLeft: ({ className }: { className?: string }) => (
|
|
23
|
-
<div data-testid="arrow-left-icon" className={className}>ArrowLeft</div>
|
|
24
|
-
),
|
|
25
|
-
RefreshCw: ({ className }: { className?: string }) => (
|
|
26
|
-
<div data-testid="refresh-cw-icon" className={className}>RefreshCw</div>
|
|
27
|
-
),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
// Mock Card component - need to match the actual import path
|
|
31
|
-
vi.mock('../../../Card/Card', () => ({
|
|
32
|
-
Card: ({ children, className }: any) => (
|
|
33
|
-
<article data-testid="card" className={className}>{children}</article>
|
|
34
|
-
),
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
// Mock Button component
|
|
38
|
-
vi.mock('../../Button/Button', () => ({
|
|
39
|
-
Button: ({ children, onClick, variant, className, ...props }: any) => (
|
|
40
|
-
<button onClick={onClick} data-variant={variant} className={className} {...props}>
|
|
41
|
-
{children}
|
|
42
|
-
</button>
|
|
43
|
-
),
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
17
|
describe('[component] AccessDeniedPage', () => {
|
|
47
18
|
beforeAll(() => {
|
|
48
19
|
// Set up navigator globally for all tests (needed for userEvent cleanup)
|
|
@@ -190,7 +161,7 @@ describe('[component] AccessDeniedPage', () => {
|
|
|
190
161
|
it('renders ShieldX icon', () => {
|
|
191
162
|
render(<AccessDeniedPage resource="users" />);
|
|
192
163
|
|
|
193
|
-
expect(screen.getByTestId('
|
|
164
|
+
expect(screen.getByTestId('lucide-shieldx')).toBeInTheDocument();
|
|
194
165
|
});
|
|
195
166
|
|
|
196
167
|
it('displays resource information', () => {
|
|
@@ -408,19 +379,19 @@ describe('[component] AccessDeniedPage', () => {
|
|
|
408
379
|
const handleRetry = vi.fn();
|
|
409
380
|
|
|
410
381
|
render(
|
|
411
|
-
<AccessDeniedPage
|
|
412
|
-
resource="users"
|
|
382
|
+
<AccessDeniedPage
|
|
383
|
+
resource="users"
|
|
413
384
|
onRetry={handleRetry}
|
|
414
385
|
/>
|
|
415
386
|
);
|
|
416
387
|
|
|
417
|
-
expect(screen.getByTestId('
|
|
388
|
+
expect(screen.getByTestId('lucide-refreshcw')).toBeInTheDocument();
|
|
418
389
|
});
|
|
419
390
|
|
|
420
391
|
it('renders ArrowLeft icon in back button', () => {
|
|
421
392
|
render(<AccessDeniedPage resource="users" />);
|
|
422
393
|
|
|
423
|
-
expect(screen.getByTestId('
|
|
394
|
+
expect(screen.getByTestId('lucide-arrowleft')).toBeInTheDocument();
|
|
424
395
|
});
|
|
425
396
|
});
|
|
426
397
|
|
|
@@ -479,7 +450,7 @@ describe('[component] AccessDeniedPage', () => {
|
|
|
479
450
|
it('has proper icon structure', () => {
|
|
480
451
|
render(<AccessDeniedPage resource="users" />);
|
|
481
452
|
|
|
482
|
-
expect(screen.getByTestId('
|
|
453
|
+
expect(screen.getByTestId('lucide-shieldx')).toBeInTheDocument();
|
|
483
454
|
});
|
|
484
455
|
});
|
|
485
456
|
|
|
@@ -529,9 +500,12 @@ describe('[component] AccessDeniedPage', () => {
|
|
|
529
500
|
});
|
|
530
501
|
}
|
|
531
502
|
|
|
532
|
-
render(<AccessDeniedPage resource="users" />);
|
|
503
|
+
const { container } = render(<AccessDeniedPage resource="users" />);
|
|
533
504
|
|
|
534
|
-
|
|
505
|
+
const card = screen.getByRole('article');
|
|
506
|
+
expect(card).toBeInTheDocument();
|
|
507
|
+
expect(container.firstChild).toContainElement(card);
|
|
508
|
+
expect(card.className).toContain('max-w-md');
|
|
535
509
|
});
|
|
536
510
|
});
|
|
537
511
|
|