@jmruthers/pace-core 0.5.193 → 0.6.2
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/CHANGELOG.md +62 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +299 -0
- package/cursor-rules/01-standards-compliance.mdc +244 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +222 -0
- package/cursor-rules/04-testing-standards.mdc +268 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +309 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +119 -0
- package/cursor-rules/README.md +192 -0
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
- package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
- package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
- package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +6 -6
- package/dist/components.js +15 -12
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +59 -126
- package/dist/hooks.js +19 -28
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +63 -16
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +146 -115
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +15 -15
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- 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 +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- 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 +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- 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 +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- 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 +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- 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 +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- 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 +3 -3
- package/docs/api/interfaces/SetupIssue.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- 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 +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +263 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +6 -28
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +40 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +12 -6
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +86 -0
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/install-cursor-rules.cjs +236 -0
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +16 -4
- package/src/components/Button/Button.tsx +27 -4
- package/src/components/Calendar/Calendar.tsx +9 -3
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +40 -6
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +200 -561
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +9 -1
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +9 -1
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +8 -7
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +4 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +15 -12
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +31 -26
- package/src/components/Header/Header.tsx +22 -11
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +36 -34
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +12 -8
- package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +95 -438
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +5 -1
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +22 -19
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +5 -1
- package/src/hooks/public/usePublicEventLogo.ts +5 -1
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +5 -1
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +16 -2
- package/src/hooks/useFocusTrap.ts +7 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +4 -1
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +8 -1
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +3 -3
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.tsx +5 -2
- package/src/rbac/components/PagePermissionGuard.tsx +158 -18
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +6 -2
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +21 -6
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +212 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js +0 -628
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
- package/dist/chunk-7EQTDTTJ.js.map +0 -1
- package/dist/chunk-7FLMSG37.js 2.map +0 -1
- package/dist/chunk-7FLMSG37.js.map +0 -1
- package/dist/chunk-BC4IJKSL.js.map +0 -1
- package/dist/chunk-E3SPN4VZ.js +0 -12917
- package/dist/chunk-E3SPN4VZ.js.map +0 -1
- package/dist/chunk-E66EQZE6 5.js +0 -37
- package/dist/chunk-E66EQZE6.js 2.map +0 -1
- package/dist/chunk-HWIIPPNI.js.map +0 -1
- package/dist/chunk-I7PSE6JW 5.js +0 -191
- package/dist/chunk-I7PSE6JW.js 2.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-IIELH4DL.js.map +0 -1
- package/dist/chunk-KNC55RTG.js 5.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js 5.map +0 -1
- package/dist/chunk-LFNCN2SP.js +0 -412
- package/dist/chunk-LFNCN2SP.js 2.map +0 -1
- package/dist/chunk-LFNCN2SP.js.map +0 -1
- package/dist/chunk-LMC26NLJ 2.js +0 -84
- package/dist/chunk-NOAYCWCX.js +0 -4993
- package/dist/chunk-NOAYCWCX.js.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
- package/dist/chunk-QWWZ5CAQ.js.map +0 -1
- package/dist/chunk-QXHPKYJV 3.js +0 -113
- package/dist/chunk-R77UEZ4E.js +0 -68
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
- package/dist/chunk-XNXXZ43G.js.map +0 -1
- package/dist/chunk-ZSAAAMVR 6.js +0 -25
- package/dist/components.js 5.map +0 -1
- package/dist/styles/index 2.js +0 -12
- package/dist/styles/index.js 5.map +0 -1
- package/dist/theming/runtime 5.js +0 -19
- package/dist/theming/runtime.js 5.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -666
- /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
- /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/index.ts +0 -0
|
@@ -166,7 +166,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
166
166
|
return result.current;
|
|
167
167
|
};
|
|
168
168
|
|
|
169
|
-
const
|
|
169
|
+
const baseProps = {
|
|
170
170
|
table: createMockTable(),
|
|
171
171
|
isCreating: false,
|
|
172
172
|
creationData: {},
|
|
@@ -213,7 +213,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
213
213
|
const table = createMockTable();
|
|
214
214
|
render(
|
|
215
215
|
<table>
|
|
216
|
-
<UnifiedTableBody {...
|
|
216
|
+
<UnifiedTableBody {...baseProps} table={table} />
|
|
217
217
|
</table>
|
|
218
218
|
);
|
|
219
219
|
|
|
@@ -225,7 +225,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
225
225
|
const table = createMockTable([]);
|
|
226
226
|
render(
|
|
227
227
|
<table>
|
|
228
|
-
<UnifiedTableBody {...
|
|
228
|
+
<UnifiedTableBody {...baseProps} table={table} dataLength={0} />
|
|
229
229
|
</table>
|
|
230
230
|
);
|
|
231
231
|
|
|
@@ -241,7 +241,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
241
241
|
render(
|
|
242
242
|
<table>
|
|
243
243
|
<UnifiedTableBody
|
|
244
|
-
{...
|
|
244
|
+
{...baseProps}
|
|
245
245
|
table={table}
|
|
246
246
|
dataLength={0}
|
|
247
247
|
emptyState={emptyState}
|
|
@@ -258,7 +258,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
258
258
|
render(
|
|
259
259
|
<table>
|
|
260
260
|
<UnifiedTableBody
|
|
261
|
-
{...
|
|
261
|
+
{...baseProps}
|
|
262
262
|
table={table}
|
|
263
263
|
enableFiltering={true}
|
|
264
264
|
showFilterRow={true}
|
|
@@ -276,7 +276,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
276
276
|
render(
|
|
277
277
|
<table>
|
|
278
278
|
<UnifiedTableBody
|
|
279
|
-
{...
|
|
279
|
+
{...baseProps}
|
|
280
280
|
table={table}
|
|
281
281
|
isCreating={true}
|
|
282
282
|
creationData={{ name: 'New User', email: 'new@example.com' }}
|
|
@@ -297,7 +297,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
297
297
|
render(
|
|
298
298
|
<table>
|
|
299
299
|
<UnifiedTableBody
|
|
300
|
-
{...
|
|
300
|
+
{...baseProps}
|
|
301
301
|
table={table}
|
|
302
302
|
isCreating={true}
|
|
303
303
|
creationData={{ name: '' }}
|
|
@@ -321,7 +321,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
321
321
|
render(
|
|
322
322
|
<table>
|
|
323
323
|
<UnifiedTableBody
|
|
324
|
-
{...
|
|
324
|
+
{...baseProps}
|
|
325
325
|
table={table}
|
|
326
326
|
isCreating={true}
|
|
327
327
|
creationData={{ name: 'New User' }}
|
|
@@ -344,7 +344,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
344
344
|
render(
|
|
345
345
|
<table>
|
|
346
346
|
<UnifiedTableBody
|
|
347
|
-
{...
|
|
347
|
+
{...baseProps}
|
|
348
348
|
table={table}
|
|
349
349
|
isCreating={true}
|
|
350
350
|
creationData={{ name: 'New User' }}
|
|
@@ -377,7 +377,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
377
377
|
render(
|
|
378
378
|
<table>
|
|
379
379
|
<UnifiedTableBody
|
|
380
|
-
{...
|
|
380
|
+
{...baseProps}
|
|
381
381
|
table={table}
|
|
382
382
|
isCreating={true}
|
|
383
383
|
creationData={{ status: 'active' }}
|
|
@@ -402,7 +402,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
402
402
|
render(
|
|
403
403
|
<table>
|
|
404
404
|
<UnifiedTableBody
|
|
405
|
-
{...
|
|
405
|
+
{...baseProps}
|
|
406
406
|
table={table}
|
|
407
407
|
isCreating={true}
|
|
408
408
|
creationData={{ age: '25' }}
|
|
@@ -429,7 +429,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
429
429
|
render(
|
|
430
430
|
<table>
|
|
431
431
|
<UnifiedTableBody
|
|
432
|
-
{...
|
|
432
|
+
{...baseProps}
|
|
433
433
|
table={table}
|
|
434
434
|
isCreating={true}
|
|
435
435
|
creationData={{ createdAt: '2024-01-01' }}
|
|
@@ -451,7 +451,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
451
451
|
render(
|
|
452
452
|
<table>
|
|
453
453
|
<UnifiedTableBody
|
|
454
|
-
{...
|
|
454
|
+
{...baseProps}
|
|
455
455
|
table={table}
|
|
456
456
|
editingRowId={rowId}
|
|
457
457
|
editingData={{ name: 'Edited Name' }}
|
|
@@ -471,7 +471,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
471
471
|
render(
|
|
472
472
|
<table>
|
|
473
473
|
<UnifiedTableBody
|
|
474
|
-
{...
|
|
474
|
+
{...baseProps}
|
|
475
475
|
table={table}
|
|
476
476
|
editingRowId={rowId}
|
|
477
477
|
editingData={{ name: 'Current Name' }}
|
|
@@ -496,7 +496,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
496
496
|
render(
|
|
497
497
|
<table>
|
|
498
498
|
<UnifiedTableBody
|
|
499
|
-
{...
|
|
499
|
+
{...baseProps}
|
|
500
500
|
table={table}
|
|
501
501
|
editingRowId={rowId}
|
|
502
502
|
editingData={{ name: 'Edited Name' }}
|
|
@@ -520,7 +520,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
520
520
|
render(
|
|
521
521
|
<table>
|
|
522
522
|
<UnifiedTableBody
|
|
523
|
-
{...
|
|
523
|
+
{...baseProps}
|
|
524
524
|
table={table}
|
|
525
525
|
editingRowId={rowId}
|
|
526
526
|
editingData={{ name: 'Edited Name' }}
|
|
@@ -559,7 +559,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
559
559
|
render(
|
|
560
560
|
<table>
|
|
561
561
|
<UnifiedTableBody
|
|
562
|
-
{...
|
|
562
|
+
{...baseProps}
|
|
563
563
|
table={tableWithGrouped as any}
|
|
564
564
|
grouping={['department']}
|
|
565
565
|
/>
|
|
@@ -593,7 +593,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
593
593
|
render(
|
|
594
594
|
<table>
|
|
595
595
|
<UnifiedTableBody
|
|
596
|
-
{...
|
|
596
|
+
{...baseProps}
|
|
597
597
|
table={tableWithGrouped as any}
|
|
598
598
|
grouping={['department']}
|
|
599
599
|
/>
|
|
@@ -625,7 +625,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
625
625
|
render(
|
|
626
626
|
<table>
|
|
627
627
|
<UnifiedTableBody
|
|
628
|
-
{...
|
|
628
|
+
{...baseProps}
|
|
629
629
|
table={table}
|
|
630
630
|
hierarchical={{
|
|
631
631
|
enabled: true,
|
|
@@ -656,7 +656,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
656
656
|
render(
|
|
657
657
|
<table>
|
|
658
658
|
<UnifiedTableBody
|
|
659
|
-
{...
|
|
659
|
+
{...baseProps}
|
|
660
660
|
table={table}
|
|
661
661
|
hierarchical={{
|
|
662
662
|
enabled: true,
|
|
@@ -693,7 +693,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
693
693
|
render(
|
|
694
694
|
<table>
|
|
695
695
|
<UnifiedTableBody
|
|
696
|
-
{...
|
|
696
|
+
{...baseProps}
|
|
697
697
|
table={table}
|
|
698
698
|
actions={actions}
|
|
699
699
|
/>
|
|
@@ -728,7 +728,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
728
728
|
render(
|
|
729
729
|
<table>
|
|
730
730
|
<UnifiedTableBody
|
|
731
|
-
{...
|
|
731
|
+
{...baseProps}
|
|
732
732
|
table={table}
|
|
733
733
|
actions={actions}
|
|
734
734
|
/>
|
|
@@ -754,7 +754,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
754
754
|
render(
|
|
755
755
|
<table>
|
|
756
756
|
<UnifiedTableBody
|
|
757
|
-
{...
|
|
757
|
+
{...baseProps}
|
|
758
758
|
table={table}
|
|
759
759
|
dataLength={0}
|
|
760
760
|
isFiltered={true}
|
|
@@ -777,7 +777,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
777
777
|
render(
|
|
778
778
|
<table>
|
|
779
779
|
<UnifiedTableBody
|
|
780
|
-
{...
|
|
780
|
+
{...baseProps}
|
|
781
781
|
table={table}
|
|
782
782
|
dataLength={5}
|
|
783
783
|
forceVirtualization={false}
|
|
@@ -796,7 +796,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
796
796
|
render(
|
|
797
797
|
<table>
|
|
798
798
|
<UnifiedTableBody
|
|
799
|
-
{...
|
|
799
|
+
{...baseProps}
|
|
800
800
|
table={table}
|
|
801
801
|
dataLength={1500}
|
|
802
802
|
forceVirtualization={false}
|
|
@@ -814,7 +814,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
814
814
|
render(
|
|
815
815
|
<table>
|
|
816
816
|
<UnifiedTableBody
|
|
817
|
-
{...
|
|
817
|
+
{...baseProps}
|
|
818
818
|
table={table}
|
|
819
819
|
dataLength={5}
|
|
820
820
|
forceVirtualization={true}
|
|
@@ -833,7 +833,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
833
833
|
render(
|
|
834
834
|
<table>
|
|
835
835
|
<UnifiedTableBody
|
|
836
|
-
{...
|
|
836
|
+
{...baseProps}
|
|
837
837
|
table={table}
|
|
838
838
|
isCreating={true}
|
|
839
839
|
creationData={{ name: null as any, email: null as any }}
|
|
@@ -850,7 +850,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
850
850
|
render(
|
|
851
851
|
<table>
|
|
852
852
|
<UnifiedTableBody
|
|
853
|
-
{...
|
|
853
|
+
{...baseProps}
|
|
854
854
|
table={table}
|
|
855
855
|
getRowId={undefined}
|
|
856
856
|
/>
|
|
@@ -866,7 +866,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
866
866
|
render(
|
|
867
867
|
<table>
|
|
868
868
|
<UnifiedTableBody
|
|
869
|
-
{...
|
|
869
|
+
{...baseProps}
|
|
870
870
|
table={table}
|
|
871
871
|
actions={[]}
|
|
872
872
|
/>
|
|
@@ -891,7 +891,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
891
891
|
render(
|
|
892
892
|
<table>
|
|
893
893
|
<UnifiedTableBody
|
|
894
|
-
{...
|
|
894
|
+
{...baseProps}
|
|
895
895
|
table={table}
|
|
896
896
|
isCreating={true}
|
|
897
897
|
creationData={{ fullName: 'New Name' }}
|
|
@@ -925,7 +925,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
925
925
|
render(
|
|
926
926
|
<table>
|
|
927
927
|
<UnifiedTableBody
|
|
928
|
-
{...
|
|
928
|
+
{...baseProps}
|
|
929
929
|
table={table}
|
|
930
930
|
isCreating={true}
|
|
931
931
|
creationData={{ status: '' }}
|
|
@@ -960,7 +960,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
960
960
|
render(
|
|
961
961
|
<table>
|
|
962
962
|
<UnifiedTableBody
|
|
963
|
-
{...
|
|
963
|
+
{...baseProps}
|
|
964
964
|
table={table}
|
|
965
965
|
isCreating={true}
|
|
966
966
|
creationData={{ category: '' }}
|
|
@@ -989,7 +989,7 @@ describe('[component] UnifiedTableBody', () => {
|
|
|
989
989
|
render(
|
|
990
990
|
<table>
|
|
991
991
|
<UnifiedTableBody
|
|
992
|
-
{...
|
|
992
|
+
{...baseProps}
|
|
993
993
|
table={table}
|
|
994
994
|
isCreating={true}
|
|
995
995
|
creationData={{ status: '' }}
|
|
@@ -76,7 +76,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
76
76
|
createdAt: new Date('2024-01-01'),
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
const
|
|
79
|
+
const baseProps = {
|
|
80
80
|
isOpen: true,
|
|
81
81
|
onClose: vi.fn(),
|
|
82
82
|
data: mockData,
|
|
@@ -93,20 +93,20 @@ describe('[component] ViewRowModal', () => {
|
|
|
93
93
|
describe('Rendering', () => {
|
|
94
94
|
it('returns null when data is null', () => {
|
|
95
95
|
const { container } = render(
|
|
96
|
-
<ViewRowModal {...
|
|
96
|
+
<ViewRowModal {...baseProps} data={null} />
|
|
97
97
|
);
|
|
98
98
|
expect(container.firstChild).toBeNull();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
it('returns null when modal is closed', () => {
|
|
102
102
|
const { container } = render(
|
|
103
|
-
<ViewRowModal {...
|
|
103
|
+
<ViewRowModal {...baseProps} isOpen={false} />
|
|
104
104
|
);
|
|
105
105
|
expect(container.firstChild).toBeNull();
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
it('renders modal when open with data', () => {
|
|
109
|
-
render(<ViewRowModal {...
|
|
109
|
+
render(<ViewRowModal {...baseProps} />);
|
|
110
110
|
|
|
111
111
|
// Dialog renders with role="dialog" from Radix UI
|
|
112
112
|
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
@@ -116,21 +116,21 @@ describe('[component] ViewRowModal', () => {
|
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
it('renders default title when title prop is not provided', () => {
|
|
119
|
-
render(<ViewRowModal {...
|
|
119
|
+
render(<ViewRowModal {...baseProps} />);
|
|
120
120
|
|
|
121
121
|
// DialogTitle renders as h2, check for text content
|
|
122
122
|
expect(screen.getByText('Row Details')).toBeInTheDocument();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
it('renders custom title when title prop is provided', () => {
|
|
126
|
-
render(<ViewRowModal {...
|
|
126
|
+
render(<ViewRowModal {...baseProps} title="Custom Title" />);
|
|
127
127
|
|
|
128
128
|
// DialogTitle renders as h2, check for text content
|
|
129
129
|
expect(screen.getByText('Custom Title')).toBeInTheDocument();
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
it('renders all data fields', () => {
|
|
133
|
-
render(<ViewRowModal {...
|
|
133
|
+
render(<ViewRowModal {...baseProps} />);
|
|
134
134
|
|
|
135
135
|
expect(screen.getByText(/id/i)).toBeInTheDocument();
|
|
136
136
|
expect(screen.getByText(/name/i)).toBeInTheDocument();
|
|
@@ -140,7 +140,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
it('renders field values correctly', () => {
|
|
143
|
-
render(<ViewRowModal {...
|
|
143
|
+
render(<ViewRowModal {...baseProps} />);
|
|
144
144
|
|
|
145
145
|
expect(screen.getByText('1')).toBeInTheDocument();
|
|
146
146
|
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
@@ -150,7 +150,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
it('formats Date values as locale date strings', () => {
|
|
153
|
-
render(<ViewRowModal {...
|
|
153
|
+
render(<ViewRowModal {...baseProps} />);
|
|
154
154
|
|
|
155
155
|
const dateValue = screen.getByText(new Date('2024-01-01').toLocaleDateString());
|
|
156
156
|
expect(dateValue).toBeInTheDocument();
|
|
@@ -162,7 +162,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
162
162
|
metadata: { key: 'value', nested: { data: 'test' } },
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
-
render(<ViewRowModal {...
|
|
165
|
+
render(<ViewRowModal {...baseProps} data={dataWithObject} />);
|
|
166
166
|
|
|
167
167
|
// JSON stringified objects contain the key parts
|
|
168
168
|
expect(screen.getByText(/key/i)).toBeInTheDocument();
|
|
@@ -176,7 +176,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
176
176
|
nullableField: null,
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
-
render(<ViewRowModal {...
|
|
179
|
+
render(<ViewRowModal {...baseProps} data={dataWithNull} />);
|
|
180
180
|
|
|
181
181
|
// Check that the field label is rendered
|
|
182
182
|
expect(screen.getByText(/nullable field/i)).toBeInTheDocument();
|
|
@@ -189,7 +189,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
189
189
|
lastName: 'Doe',
|
|
190
190
|
};
|
|
191
191
|
|
|
192
|
-
render(<ViewRowModal {...
|
|
192
|
+
render(<ViewRowModal {...baseProps} data={dataWithCamelCase} />);
|
|
193
193
|
|
|
194
194
|
expect(screen.getByText(/first name/i)).toBeInTheDocument();
|
|
195
195
|
expect(screen.getByText(/last name/i)).toBeInTheDocument();
|
|
@@ -201,7 +201,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
201
201
|
const user = userEvent.setup();
|
|
202
202
|
const handleClose = vi.fn();
|
|
203
203
|
|
|
204
|
-
render(<ViewRowModal {...
|
|
204
|
+
render(<ViewRowModal {...baseProps} onClose={handleClose} />);
|
|
205
205
|
|
|
206
206
|
// Get the main "Close" button (not the X icon button)
|
|
207
207
|
const closeButtons = screen.getAllByRole('button', { name: /close/i });
|
|
@@ -217,7 +217,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
217
217
|
const user = userEvent.setup();
|
|
218
218
|
const handleClose = vi.fn();
|
|
219
219
|
|
|
220
|
-
render(<ViewRowModal {...
|
|
220
|
+
render(<ViewRowModal {...baseProps} onClose={handleClose} />);
|
|
221
221
|
|
|
222
222
|
// Get the X icon button specifically (first button with X icon)
|
|
223
223
|
const xButtons = screen.getAllByTestId('x-icon');
|
|
@@ -235,7 +235,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
235
235
|
|
|
236
236
|
render(
|
|
237
237
|
<ViewRowModal
|
|
238
|
-
{...
|
|
238
|
+
{...baseProps}
|
|
239
239
|
onClose={handleOpenChange}
|
|
240
240
|
/>
|
|
241
241
|
);
|
|
@@ -253,7 +253,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
253
253
|
|
|
254
254
|
describe('Edge Cases', () => {
|
|
255
255
|
it('handles empty data object', () => {
|
|
256
|
-
render(<ViewRowModal {...
|
|
256
|
+
render(<ViewRowModal {...baseProps} data={{}} />);
|
|
257
257
|
|
|
258
258
|
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
259
259
|
expect(screen.getAllByRole('button', { name: /close/i }).length).toBeGreaterThan(0);
|
|
@@ -265,7 +265,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
265
265
|
optionalField: undefined,
|
|
266
266
|
};
|
|
267
267
|
|
|
268
|
-
render(<ViewRowModal {...
|
|
268
|
+
render(<ViewRowModal {...baseProps} data={dataWithUndefined} />);
|
|
269
269
|
|
|
270
270
|
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
271
271
|
});
|
|
@@ -276,7 +276,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
276
276
|
tags: ['tag1', 'tag2', 'tag3'],
|
|
277
277
|
};
|
|
278
278
|
|
|
279
|
-
render(<ViewRowModal {...
|
|
279
|
+
render(<ViewRowModal {...baseProps} data={dataWithArray} />);
|
|
280
280
|
|
|
281
281
|
// Check that array values are displayed (they'll be JSON stringified)
|
|
282
282
|
expect(screen.getByText(/tag1/i)).toBeInTheDocument();
|
|
@@ -294,7 +294,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
294
294
|
},
|
|
295
295
|
};
|
|
296
296
|
|
|
297
|
-
render(<ViewRowModal {...
|
|
297
|
+
render(<ViewRowModal {...baseProps} data={dataWithNested} />);
|
|
298
298
|
|
|
299
299
|
// JSON stringified objects contain the key parts
|
|
300
300
|
expect(screen.getByText(/street/i)).toBeInTheDocument();
|
|
@@ -309,7 +309,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
309
309
|
description: longString,
|
|
310
310
|
};
|
|
311
311
|
|
|
312
|
-
render(<ViewRowModal {...
|
|
312
|
+
render(<ViewRowModal {...baseProps} data={dataWithLongString} />);
|
|
313
313
|
|
|
314
314
|
expect(screen.getByText(longString)).toBeInTheDocument();
|
|
315
315
|
});
|
|
@@ -320,7 +320,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
320
320
|
'field-with-special-chars!@#': 'value',
|
|
321
321
|
};
|
|
322
322
|
|
|
323
|
-
render(<ViewRowModal {...
|
|
323
|
+
render(<ViewRowModal {...baseProps} data={dataWithSpecial} />);
|
|
324
324
|
|
|
325
325
|
// The component only handles camelCase, not special characters
|
|
326
326
|
// Special characters remain in the field name, so check for parts of the name
|
|
@@ -334,7 +334,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
334
334
|
count: 0,
|
|
335
335
|
};
|
|
336
336
|
|
|
337
|
-
render(<ViewRowModal {...
|
|
337
|
+
render(<ViewRowModal {...baseProps} data={dataWithZero} />);
|
|
338
338
|
|
|
339
339
|
// Zero should render as "0" - check for it in the value cell
|
|
340
340
|
const countLabel = screen.getByText(/count:/i);
|
|
@@ -348,7 +348,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
348
348
|
active: false,
|
|
349
349
|
};
|
|
350
350
|
|
|
351
|
-
render(<ViewRowModal {...
|
|
351
|
+
render(<ViewRowModal {...baseProps} data={dataWithFalse} />);
|
|
352
352
|
|
|
353
353
|
// Boolean false should render as "false" - check for it in the value cell
|
|
354
354
|
const activeLabel = screen.getByText(/active:/i);
|
|
@@ -359,21 +359,21 @@ describe('[component] ViewRowModal', () => {
|
|
|
359
359
|
|
|
360
360
|
describe('Accessibility', () => {
|
|
361
361
|
it('provides close button with aria-label', () => {
|
|
362
|
-
render(<ViewRowModal {...
|
|
362
|
+
render(<ViewRowModal {...baseProps} />);
|
|
363
363
|
|
|
364
364
|
const buttons = screen.getAllByRole('button');
|
|
365
365
|
expect(buttons.length).toBeGreaterThan(0);
|
|
366
366
|
});
|
|
367
367
|
|
|
368
368
|
it('provides main close button with accessible text', () => {
|
|
369
|
-
render(<ViewRowModal {...
|
|
369
|
+
render(<ViewRowModal {...baseProps} />);
|
|
370
370
|
|
|
371
371
|
const closeButtons = screen.getAllByRole('button', { name: /close/i });
|
|
372
372
|
expect(closeButtons.length).toBeGreaterThan(0);
|
|
373
373
|
});
|
|
374
374
|
|
|
375
375
|
it('renders dialog with proper structure', () => {
|
|
376
|
-
render(<ViewRowModal {...
|
|
376
|
+
render(<ViewRowModal {...baseProps} />);
|
|
377
377
|
|
|
378
378
|
expect(screen.getByRole('dialog')).toBeInTheDocument();
|
|
379
379
|
// Check for content structure instead of testids
|
|
@@ -384,7 +384,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
384
384
|
|
|
385
385
|
describe('Layout and Styling', () => {
|
|
386
386
|
it('applies max-width and max-height classes to dialog content', () => {
|
|
387
|
-
render(<ViewRowModal {...
|
|
387
|
+
render(<ViewRowModal {...baseProps} />);
|
|
388
388
|
|
|
389
389
|
// DialogContent receives className prop, check if dialog has the classes
|
|
390
390
|
const dialog = screen.getByRole('dialog');
|
|
@@ -394,7 +394,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
394
394
|
});
|
|
395
395
|
|
|
396
396
|
it('renders field labels with proper styling classes', () => {
|
|
397
|
-
render(<ViewRowModal {...
|
|
397
|
+
render(<ViewRowModal {...baseProps} />);
|
|
398
398
|
|
|
399
399
|
// Check that field labels are rendered (they should have specific classes)
|
|
400
400
|
const nameLabel = screen.getByText(/name/i);
|
|
@@ -402,7 +402,7 @@ describe('[component] ViewRowModal', () => {
|
|
|
402
402
|
});
|
|
403
403
|
|
|
404
404
|
it('renders close button in header with proper styling', () => {
|
|
405
|
-
render(<ViewRowModal {...
|
|
405
|
+
render(<ViewRowModal {...baseProps} />);
|
|
406
406
|
|
|
407
407
|
const xIcons = screen.getAllByTestId('x-icon');
|
|
408
408
|
expect(xIcons.length).toBeGreaterThan(0);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CellValue, DataRecord } from '../types';
|
|
2
|
+
|
|
3
|
+
const isCellValue = (value: unknown): value is CellValue => {
|
|
4
|
+
if (value === null || value === undefined) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (value instanceof Date) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const valueType = typeof value;
|
|
13
|
+
return valueType === 'string' || valueType === 'number' || valueType === 'boolean';
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Converts a data record to a cell value record.
|
|
18
|
+
* Filters and converts values to valid cell values (string, number, boolean, Date, null, undefined).
|
|
19
|
+
*
|
|
20
|
+
* @template TData - The type of data records
|
|
21
|
+
* @param row - The data record to convert
|
|
22
|
+
* @returns A record with cell-compatible values
|
|
23
|
+
*/
|
|
24
|
+
export const toCellValueRecord = <TData extends DataRecord>(row: TData): Record<string, CellValue> => {
|
|
25
|
+
if (typeof row !== 'object' || row === null) {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return Object.entries(row).reduce<Record<string, CellValue>>((accumulator, [key, entryValue]) => {
|
|
30
|
+
if (isCellValue(entryValue)) {
|
|
31
|
+
accumulator[key] = entryValue;
|
|
32
|
+
} else if (entryValue && typeof entryValue === 'object' && 'toString' in entryValue) {
|
|
33
|
+
accumulator[key] = String(entryValue) as CellValue;
|
|
34
|
+
} else {
|
|
35
|
+
accumulator[key] = entryValue as CellValue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return accumulator;
|
|
39
|
+
}, {});
|
|
40
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import type { UseKeyboardNavigationReturn } from '../../hooks/useKeyboardNavigation';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook for managing focus when the import modal opens/closes.
|
|
6
|
+
* Stores and restores focus to maintain keyboard navigation flow.
|
|
7
|
+
*
|
|
8
|
+
* @param isImportOpen - Whether the import modal is currently open
|
|
9
|
+
* @param keyboardNavigation - Keyboard navigation utilities
|
|
10
|
+
* @returns Object with last focused element reference
|
|
11
|
+
*/
|
|
12
|
+
export function useImportModalFocus(isImportOpen: boolean, keyboardNavigation: UseKeyboardNavigationReturn) {
|
|
13
|
+
const lastFocusedElementRef = useRef<HTMLElement | null>(null);
|
|
14
|
+
const wasImportModalOpenRef = useRef(false);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (isImportOpen) {
|
|
18
|
+
wasImportModalOpenRef.current = true;
|
|
19
|
+
keyboardNavigation.storeFocus();
|
|
20
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
21
|
+
lastFocusedElementRef.current = document.activeElement;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}, [isImportOpen, keyboardNavigation]);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (isImportOpen) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!wasImportModalOpenRef.current) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
wasImportModalOpenRef.current = false;
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
const storedElement = lastFocusedElementRef.current;
|
|
38
|
+
lastFocusedElementRef.current = null;
|
|
39
|
+
|
|
40
|
+
const elementToRestore = storedElement?.isConnected
|
|
41
|
+
? storedElement
|
|
42
|
+
: document.querySelector<HTMLElement>('[data-restore-target="datatable-import-button"]');
|
|
43
|
+
|
|
44
|
+
if (elementToRestore && typeof elementToRestore.focus === 'function') {
|
|
45
|
+
elementToRestore.focus();
|
|
46
|
+
} else {
|
|
47
|
+
keyboardNavigation.restoreFocus();
|
|
48
|
+
}
|
|
49
|
+
}, 100);
|
|
50
|
+
}, [isImportOpen, keyboardNavigation]);
|
|
51
|
+
|
|
52
|
+
return { lastFocusedElementRef };
|
|
53
|
+
}
|