@jmruthers/pace-core 0.6.9 → 0.6.11
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 +21 -0
- package/audit-tool/00-dependencies.cjs +46 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
- package/audit-tool/audits/02-project-structure.cjs +74 -2
- package/audit-tool/audits/03-architecture.cjs +220 -20
- package/audit-tool/audits/04-code-quality.cjs +95 -3
- package/audit-tool/audits/05-styling.cjs +19 -7
- package/audit-tool/audits/06-security-rbac.cjs +214 -25
- package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
- package/audit-tool/audits/08-testing-documentation.cjs +11 -3
- package/audit-tool/audits/09-operations.cjs +19 -7
- package/audit-tool/index.cjs +22 -11
- package/audit-tool/utils/report-utils.cjs +4 -0
- package/cursor-rules/01-pace-core-compliance.mdc +1 -0
- package/cursor-rules/02-project-structure.mdc +3 -26
- package/cursor-rules/03-architecture.mdc +3 -1
- package/cursor-rules/04-code-quality.mdc +1 -0
- package/cursor-rules/05-styling.mdc +120 -8
- package/cursor-rules/06-security-rbac.mdc +126 -2
- package/cursor-rules/07-api-tech-stack.mdc +1 -0
- package/cursor-rules/08-testing-documentation.mdc +1 -0
- package/cursor-rules/09-operations.mdc +1 -0
- package/dist/DataTable-EFYP2QLE.js +16 -0
- package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
- package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
- package/dist/api-BZR2CYXL.js +5 -0
- package/dist/api-result-USV1Czr-.d.ts +51 -0
- package/dist/assets/app-icons/admin_favicon.svg +462 -0
- package/dist/assets/app-icons/base_favicon.svg +85 -0
- package/dist/assets/app-icons/cake_favicon.svg +68 -0
- package/dist/assets/app-icons/core_favicon.svg +256 -0
- package/dist/assets/app-icons/gear_favicon.svg +91 -0
- package/dist/assets/app-icons/medi_favicon.svg +92 -0
- package/dist/assets/app-icons/mint_favicon.svg +83 -0
- package/dist/assets/app-icons/pace_favicon.svg +49 -0
- package/dist/assets/app-icons/pump_favicon.svg +68 -0
- package/dist/assets/app-icons/seed_favicon.svg +91 -0
- package/dist/assets/app-icons/team_favicon.svg +67 -0
- package/dist/assets/app-icons/trac_favicon.svg +112 -0
- package/dist/assets/app-icons/trip_favicon.svg +102 -0
- package/dist/audit-HI2DHUVU.js +4 -0
- package/dist/auth-JvdRVaud.d.ts +49 -0
- package/dist/chunk-2DL2WSOE.js +327 -0
- package/dist/chunk-2OEVOGGR.js +9598 -0
- package/dist/chunk-44CNXN4P.js +15 -0
- package/dist/chunk-4R3T5ENU.js +2943 -0
- package/dist/chunk-7A6IMHH2.js +2321 -0
- package/dist/chunk-BTHN5MKC.js +121 -0
- package/dist/chunk-CU2BU2MQ.js +2 -0
- package/dist/chunk-D6BMFMQZ.js +200 -0
- package/dist/chunk-DDMPHZ3D.js +58 -0
- package/dist/chunk-ENLXB7GP.js +721 -0
- package/dist/chunk-J2KQK6DG.js +2159 -0
- package/dist/chunk-KJXRL3XE.js +6434 -0
- package/dist/chunk-L5LFKKLJ.js +61 -0
- package/dist/chunk-PCSHBLPB.js +811 -0
- package/dist/chunk-QRYSEPHB.js +429 -0
- package/dist/chunk-RMLY6KB5.js +187 -0
- package/dist/chunk-SACF5YSM.js +31 -0
- package/dist/chunk-UZNAFKGW.js +125 -0
- package/dist/chunk-V7FTM2LU.js +1080 -0
- package/dist/chunk-WY6Y7KC3.js +264 -0
- package/dist/chunk-XOJME5T7.js +407 -0
- package/dist/chunk-XPFVT3GN.js +492 -0
- package/dist/chunk-YFTFFJIV.js +529 -0
- package/dist/chunk-YYTWKVHO.js +1334 -0
- package/dist/components.d.ts +12 -89
- package/dist/components.js +23 -55
- package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
- package/dist/eslint-rules/index.cjs +3 -0
- package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
- package/dist/eslint-rules/rules/05-styling.cjs +507 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +84 -0
- package/dist/event-BfCox3N2.d.ts +265 -0
- package/dist/file-reference-DU1hcawx.d.ts +164 -0
- package/dist/functions-DH45k8ec.d.ts +208 -0
- package/dist/hooks.d.ts +28 -14
- package/dist/hooks.js +90 -56
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +392 -155
- package/dist/index.js +337 -347
- package/dist/pagination-BW1mqywp.d.ts +201 -0
- package/dist/papaparseLoader-WG2UXQ22.js +7 -0
- package/dist/providers.d.ts +29 -14
- package/dist/providers.js +7 -5
- package/dist/rbac/eslint-rules.js +2 -2
- package/dist/rbac/index.d.ts +180 -351
- package/dist/rbac/index.js +13 -11
- package/dist/theming/runtime.d.ts +28 -5
- package/dist/theming/runtime.js +2 -2
- package/dist/timezone-BTWWXKVY.d.ts +696 -0
- package/dist/types-BE2sEHKd.d.ts +55 -0
- package/dist/types-CvOPXWWZ.d.ts +111 -0
- package/dist/types-Dr8sNhER.d.ts +50 -0
- package/dist/types.d.ts +20 -13
- package/dist/types.js +1 -0
- package/dist/usePublicPageContext-B91dGYW1.d.ts +4367 -0
- package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
- package/dist/utils.d.ts +338 -156
- package/dist/utils.js +78 -60
- package/dist/validation-g5n0hDkh.d.ts +177 -0
- package/docs/api/modules.md +1226 -1094
- package/docs/api-reference/components.md +5 -5
- package/docs/api-reference/rpc-functions.md +12 -3
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/getting-started/cursor-rules.md +17 -20
- package/docs/getting-started/dependencies.md +1 -1
- package/docs/getting-started/setup.md +235 -0
- package/docs/implementation-guides/authentication.md +27 -0
- package/docs/implementation-guides/data-tables.md +365 -10
- package/docs/migration/ApiResult-migration.md +25 -0
- package/docs/rbac/RBAC_CONTRACT.md +0 -12
- package/docs/rbac/api-reference.md +33 -31
- package/docs/standards/0-standards-overview.md +50 -15
- package/docs/standards/1-pace-core-compliance-standards.md +62 -57
- package/docs/standards/2-project-structure-standards.md +45 -90
- package/docs/standards/3-architecture-standards.md +41 -1
- package/docs/standards/4-code-quality-standards.md +26 -6
- package/docs/standards/5-styling-standards.md +35 -1
- package/docs/standards/6-security-rbac-standards.md +288 -7
- package/docs/standards/7-api-tech-stack-standards.md +116 -17
- package/docs/standards/8-testing-documentation-standards.md +31 -0
- package/docs/standards/9-operations-standards.md +19 -0
- package/docs/standards/README.md +20 -201
- package/docs/testing/README.md +10 -0
- package/docs/testing/test-setup-for-consumers.md +916 -0
- package/docs/troubleshooting/common-issues.md +17 -1
- package/docs/troubleshooting/organisation-context-setup.md +8 -0
- package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
- package/eslint-config-pace-core.cjs +24 -0
- package/package.json +14 -20
- package/scripts/build-docs.js +180 -0
- package/scripts/setup.cjs +536 -0
- package/scripts/validate.cjs +480 -0
- package/src/__mocks__/lucide-react.ts +0 -2
- package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
- package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
- package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
- package/src/__tests__/helpers/test-providers.test.tsx +99 -0
- package/src/__tests__/helpers/test-providers.tsx +37 -39
- package/src/__tests__/helpers/test-utils.test.tsx +447 -0
- package/src/__tests__/helpers/timer-utils.test.ts +371 -0
- package/src/assets/app-icons/admin_favicon.svg +462 -0
- package/src/assets/app-icons/base_favicon.svg +85 -0
- package/src/assets/app-icons/cake_favicon.svg +68 -0
- package/src/assets/app-icons/core_favicon.svg +256 -0
- package/src/assets/app-icons/gear_favicon.svg +91 -0
- package/src/assets/app-icons/index.test.ts +304 -0
- package/src/assets/app-icons/index.ts +83 -0
- package/src/assets/app-icons/medi_favicon.svg +92 -0
- package/src/assets/app-icons/mint_favicon.svg +83 -0
- package/src/assets/app-icons/pace_favicon.svg +49 -0
- package/src/assets/app-icons/pump_favicon.svg +68 -0
- package/src/assets/app-icons/seed_favicon.svg +91 -0
- package/src/assets/app-icons/team_favicon.svg +67 -0
- package/src/assets/app-icons/trac_favicon.svg +112 -0
- package/src/assets/app-icons/trip_favicon.svg +102 -0
- package/src/components/AddressField/AddressField.test.tsx +379 -4
- package/src/components/AddressField/AddressField.tsx +239 -213
- package/src/components/AddressField/types.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +35 -25
- package/src/components/Alert/Alert.tsx +8 -8
- package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
- package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
- package/src/components/Avatar/Avatar.test.tsx +11 -1
- package/src/components/Avatar/Avatar.tsx +3 -2
- package/src/components/Badge/Badge.test.tsx +11 -1
- package/src/components/Button/Button.test.tsx +13 -3
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Calendar/Calendar.test.tsx +523 -131
- package/src/components/Calendar/Calendar.tsx +107 -488
- package/src/components/Card/Card.test.tsx +384 -258
- package/src/components/Card/Card.tsx +19 -10
- package/src/components/Checkbox/Checkbox.test.tsx +58 -174
- package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
- package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
- package/src/components/ContextSelector/ContextSelector.tsx +66 -280
- package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
- package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
- package/src/components/DataTable/AUDIT_REPORT.md +59 -44
- package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
- package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
- package/src/components/DataTable/DataTable.export.test.tsx +705 -0
- package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
- package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
- package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
- package/src/components/DataTable/DataTable.test.tsx +787 -416
- package/src/components/DataTable/DataTable.tsx +14 -14
- package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
- package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
- package/src/components/DataTable/DataTableCore.test.tsx +970 -0
- package/src/components/DataTable/README.md +155 -0
- package/src/components/DataTable/TESTING.md +101 -0
- package/src/components/DataTable/a11y.basic.test.tsx +788 -0
- package/src/components/DataTable/components/DataTableCore.tsx +126 -894
- package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -3
- package/src/components/DataTable/components/ImportModal.tsx +82 -408
- package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
- package/src/components/DataTable/context/DataTableContext.tsx +13 -13
- package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
- package/src/components/DataTable/core/ColumnFactory.ts +3 -3
- package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +15 -3
- package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +81 -260
- package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
- package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
- package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
- package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
- package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
- package/src/components/DataTable/hooks/useDataTableState.ts +161 -114
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
- package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
- package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
- package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
- package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +311 -271
- package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
- package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +27 -4
- package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
- package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +13 -22
- package/src/components/DataTable/index.ts +28 -5
- package/src/components/DataTable/keyboard.test.tsx +734 -0
- package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
- package/src/components/DataTable/pagination.modes.test.tsx +728 -0
- package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
- package/src/components/DataTable/styles.test.ts +379 -0
- package/src/components/DataTable/styles.ts +0 -1
- package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
- package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
- package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
- package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
- package/src/components/DataTable/test-utils.ts +94 -0
- package/src/components/DataTable/types/actions.ts +71 -0
- package/src/components/DataTable/types/base.ts +39 -0
- package/src/components/DataTable/types/columns.ts +125 -0
- package/src/components/DataTable/types/export.ts +32 -0
- package/src/components/DataTable/types/features.ts +81 -0
- package/src/components/DataTable/types/hierarchical.ts +44 -0
- package/src/components/DataTable/types/index.ts +43 -0
- package/src/components/DataTable/types/pagination.ts +85 -0
- package/src/components/DataTable/types/performance.ts +47 -0
- package/src/components/DataTable/types/props.ts +62 -0
- package/src/components/DataTable/types/rbac.ts +45 -0
- package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
- package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
- package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
- package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
- package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
- package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
- package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
- package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
- package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
- package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
- package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
- package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
- package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
- package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
- package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
- package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
- package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
- package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
- package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
- package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
- package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
- package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
- package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
- package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
- package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
- package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
- package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
- package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
- package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
- package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
- package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
- package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
- package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
- package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
- package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
- package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
- package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
- package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
- package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
- package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
- package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
- package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
- package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
- package/src/components/DataTable/utils/a11yUtils.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
- package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
- package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/csvParse.test.ts +74 -0
- package/src/components/DataTable/utils/csvParse.ts +65 -0
- package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
- package/src/components/DataTable/utils/errorHandling.ts +3 -1
- package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
- package/src/components/DataTable/utils/flexibleImport.ts +3 -186
- package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
- package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
- package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
- package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
- package/src/components/DataTable/utils/importDateParser.ts +114 -0
- package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
- package/src/components/DataTable/utils/importValueParser.ts +91 -0
- package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
- package/src/components/DataTable/utils/paginationUtils.ts +7 -4
- package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
- package/src/components/DataTable/utils/performanceUtils.ts +1 -1
- package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
- package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
- package/src/components/DataTable/utils/selectFieldUtils.ts +97 -67
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +18 -25
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +3 -16
- package/src/components/DateTimeField/DateTimeField.tsx +1 -1
- package/src/components/Dialog/Dialog.test-utils.ts +49 -0
- package/src/components/Dialog/Dialog.test.tsx +2865 -458
- package/src/components/Dialog/Dialog.tsx +183 -986
- package/src/components/Dialog/dialogLock.test.ts +238 -0
- package/src/components/Dialog/dialogLock.ts +98 -0
- package/src/components/Dialog/index.ts +2 -0
- package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
- package/src/components/Dialog/useDialogDimensions.ts +140 -0
- package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
- package/src/components/Dialog/useDialogLifecycle.ts +135 -0
- package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
- package/src/components/Dialog/useDialogPersistence.ts +357 -0
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
- package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
- package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
- package/src/components/ErrorBoundary/index.ts +3 -4
- package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +479 -247
- package/src/components/FileDisplay/FileDisplay.tsx +29 -659
- package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
- package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
- package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
- package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
- package/src/components/FileDisplay/fallbackUtils.ts +44 -0
- package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
- package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
- package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
- package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
- package/src/components/FileDisplay/index.tsx +1 -1
- package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
- package/src/components/FileDisplay/useFileDisplay.ts +515 -0
- package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1438 -0
- package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
- package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
- package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
- package/src/components/FileUpload/FileUpload.test.tsx +69 -27
- package/src/components/FileUpload/FileUpload.tsx +112 -527
- package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
- package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
- package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
- package/src/components/FileUpload/index.tsx +1 -1
- package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
- package/src/components/FileUpload/useFileUploadManager.ts +454 -0
- package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
- package/src/components/FileUpload/useResolvedAppId.ts +77 -0
- package/src/components/Footer/Footer.test.tsx +15 -382
- package/src/components/Footer/Footer.tsx +8 -125
- package/src/components/Form/Form.test.tsx +425 -88
- package/src/components/Form/Form.tsx +91 -299
- package/src/components/Form/useFormPersistence.ts +257 -0
- package/src/components/Header/Header.test.tsx +653 -163
- package/src/components/Header/Header.tsx +62 -44
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
- package/src/components/Input/Input.test.tsx +34 -120
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.test.tsx +46 -45
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +8 -11
- package/src/components/LoginForm/LoginForm.test.tsx +0 -1
- package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +2422 -102
- package/src/components/NavigationMenu/NavigationMenu.tsx +62 -362
- package/src/components/NavigationMenu/index.ts +6 -1
- package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
- package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +199 -308
- package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1322 -0
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +50 -49
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +103 -85
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +774 -44
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +282 -764
- package/src/components/PaceAppLayout/README.md +0 -9
- package/src/components/PaceAppLayout/test-setup.tsx +15 -9
- package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
- package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
- package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +782 -20
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +33 -125
- package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
- package/src/components/Progress/Progress.test.tsx +127 -1
- package/src/components/Progress/Progress.tsx +1 -2
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -217
- package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
- package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
- package/src/components/PublicLayout/PublicLayout.test.tsx +1640 -38
- package/src/components/PublicLayout/PublicPageContext.ts +28 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +134 -75
- package/src/components/PublicLayout/PublicPageProvider.tsx +7 -42
- package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
- package/src/components/Select/Select.test.tsx +45 -8
- package/src/components/Select/Select.tsx +57 -40
- package/src/components/Select/context.test.tsx +56 -0
- package/src/components/Select/text.test.tsx +104 -0
- package/src/components/Select/text.ts +26 -0
- package/src/components/Select/types.ts +3 -0
- package/src/components/Select/useSelectEvents.test.ts +279 -0
- package/src/components/Select/useSelectEvents.ts +87 -0
- package/src/components/Select/useSelectSearch.test.tsx +295 -0
- package/src/components/Select/useSelectSearch.ts +91 -0
- package/src/components/Select/useSelectState.test.ts +268 -0
- package/src/components/Select/useSelectState.ts +104 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
- package/src/components/Switch/Switch.test.tsx +57 -153
- package/src/components/Table/Table.test.tsx +395 -317
- package/src/components/Tabs/Tabs.test.tsx +270 -0
- package/src/components/Tabs/Tabs.tsx +4 -4
- package/src/components/Textarea/Textarea.test.tsx +11 -38
- package/src/components/Toast/Toast.test.tsx +425 -496
- package/src/components/Tooltip/Tooltip.test.tsx +4 -21
- package/src/components/UserMenu/UserMenu.test.tsx +1 -21
- package/src/components/UserMenu/UserMenu.tsx +0 -1
- package/src/components/index.test.ts +346 -0
- package/src/components/index.ts +12 -1
- package/src/constants/performance.test.ts +91 -0
- package/src/hooks/ServiceHooks.test.tsx +725 -0
- package/src/hooks/hooks.integration.test.tsx +608 -0
- package/src/hooks/index.ts +18 -3
- package/src/hooks/index.unit.test.ts +220 -0
- package/src/hooks/public/usePublicEvent.test.ts +304 -0
- package/src/hooks/public/usePublicEvent.ts +11 -11
- package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
- package/src/hooks/public/usePublicEventLogo.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
- package/src/hooks/public/usePublicRouteParams.ts +2 -2
- package/src/hooks/services/useAuth.ts +9 -7
- package/src/hooks/services/useAuthService.ts +1 -1
- package/src/hooks/services/useEventService.ts +1 -1
- package/src/hooks/useAccessibleApps.test.ts +400 -0
- package/src/hooks/useAccessibleApps.ts +264 -0
- package/src/hooks/useAddressAutocomplete.test.ts +170 -47
- package/src/hooks/useAddressAutocomplete.ts +109 -81
- package/src/hooks/useApiFetch.unit.test.ts +111 -0
- package/src/hooks/useAppConfig.ts +13 -3
- package/src/hooks/useAppConfig.unit.test.ts +712 -0
- package/src/hooks/useComponentPerformance.unit.test.tsx +314 -0
- package/src/hooks/useDataTablePerformance.ts +111 -130
- package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
- package/src/hooks/useDataTableState.test.ts +170 -0
- package/src/hooks/useDataTableState.ts +5 -5
- package/src/hooks/useDebounce.unit.test.ts +157 -0
- package/src/hooks/useEventTheme.test.ts +70 -18
- package/src/hooks/useEventTheme.ts +50 -22
- package/src/hooks/useEvents.ts +49 -2
- package/src/hooks/useEvents.unit.test.ts +227 -0
- package/src/hooks/useFileReference.test.ts +388 -107
- package/src/hooks/useFileReference.ts +184 -179
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/useFileUrl.unit.test.ts +686 -0
- package/src/hooks/useFileUrlCache.test.ts +319 -0
- package/src/hooks/useFileUrlCache.ts +5 -2
- package/src/hooks/useFocusManagement.unit.test.ts +604 -0
- package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
- package/src/hooks/useFormDialog.test.ts +307 -0
- package/src/hooks/useFormDialog.ts +2 -2
- package/src/hooks/useInactivityTracker.ts +141 -134
- package/src/hooks/useInactivityTracker.unit.test.ts +446 -0
- package/src/hooks/useIsMobile.unit.test.ts +317 -0
- package/src/hooks/useIsPrint.ts +62 -0
- package/src/hooks/useIsPrint.unit.test.ts +545 -0
- package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
- package/src/hooks/useOrganisationPermissions.test.ts +1 -2
- package/src/hooks/useOrganisationPermissions.ts +1 -4
- package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
- package/src/hooks/useOrganisationSecurity.test.ts +4 -33
- package/src/hooks/useOrganisationSecurity.ts +192 -203
- package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
- package/src/hooks/useOrganisations.ts +1 -1
- package/src/hooks/useOrganisations.unit.test.ts +369 -0
- package/src/hooks/usePerformanceMonitor.ts +1 -1
- package/src/hooks/usePerformanceMonitor.unit.test.ts +693 -0
- package/src/hooks/usePermissionCache.test.ts +298 -329
- package/src/hooks/usePermissionCache.ts +277 -276
- package/src/hooks/usePreventTabReload.test.ts +307 -0
- package/src/hooks/usePublicEvent.simple.test.ts +794 -0
- package/src/hooks/usePublicEvent.test.ts +670 -0
- package/src/hooks/usePublicEvent.unit.test.ts +638 -0
- package/src/hooks/usePublicFileDisplay.test.ts +948 -0
- package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
- package/src/hooks/useQueryCache.test.ts +391 -0
- package/src/hooks/useQueryCache.ts +7 -9
- package/src/hooks/useRBAC.unit.test.ts +253 -0
- package/src/hooks/useSessionDraft.test.ts +556 -0
- package/src/hooks/useSessionDraft.ts +14 -11
- package/src/hooks/useSessionRestoration.ts +1 -1
- package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
- package/src/hooks/useStorage.ts +94 -54
- package/src/hooks/useStorage.unit.test.ts +684 -0
- package/src/hooks/useToast.test.ts +413 -0
- package/src/hooks/useToast.ts +2 -2
- package/src/hooks/useToast.unit.test.tsx +481 -0
- package/src/hooks/useZodForm.ts +3 -3
- package/src/hooks/useZodForm.unit.test.tsx +191 -0
- package/src/icons/index.test.ts +133 -0
- package/src/icons/index.ts +3 -1
- package/src/index.test.ts +528 -0
- package/src/index.ts +56 -9
- package/src/providers/AuthProvider.test.tsx +218 -0
- package/src/providers/EventProvider.test.tsx +487 -0
- package/src/providers/InactivityProvider.test-helper.tsx +40 -0
- package/src/providers/InactivityProvider.test.tsx +421 -0
- package/src/providers/ProviderLifecycle.test.tsx +308 -0
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
- package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
- package/src/providers/index.test.ts +138 -0
- package/src/providers/services/AuthServiceContext.ts +27 -0
- package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
- package/src/providers/services/AuthServiceProvider.test.tsx +638 -0
- package/src/providers/services/AuthServiceProvider.tsx +81 -20
- package/src/providers/services/EventServiceContext.ts +25 -0
- package/src/providers/services/EventServiceProvider.test.tsx +839 -0
- package/src/providers/services/EventServiceProvider.tsx +11 -20
- package/src/providers/services/InactivityServiceContext.ts +25 -0
- package/src/providers/services/InactivityServiceProvider.test.tsx +662 -0
- package/src/providers/services/InactivityServiceProvider.tsx +7 -17
- package/src/providers/services/OrganisationServiceContext.ts +25 -0
- package/src/providers/services/OrganisationServiceProvider.test.tsx +440 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
- package/src/providers/services/UnifiedAuthContext.ts +102 -0
- package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
- package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
- package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
- package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +147 -497
- package/src/providers/services/contexts.test.tsx +281 -0
- package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
- package/src/providers/services/useUnifiedAuth.ts +29 -0
- package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
- package/src/providers/useInactivity.test-helper.ts +27 -0
- package/src/rbac/README.md +5 -5
- package/src/rbac/adapters.comprehensive.test.tsx +429 -0
- package/src/rbac/adapters.test.tsx +654 -0
- package/src/rbac/adapters.tsx +53 -38
- package/src/rbac/api.test.ts +986 -259
- package/src/rbac/api.ts +260 -216
- package/src/rbac/audit-batched.test.ts +550 -0
- package/src/rbac/audit-batched.ts +5 -4
- package/src/rbac/audit.test.ts +225 -28
- package/src/rbac/audit.ts +26 -18
- package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
- package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
- package/src/rbac/cache-invalidation.test.ts +715 -0
- package/src/rbac/cache-invalidation.ts +18 -15
- package/src/rbac/cache.test.ts +123 -63
- package/src/rbac/cache.ts +3 -4
- package/src/rbac/components/AccessDenied.test.tsx +324 -0
- package/src/rbac/components/AccessDenied.tsx +20 -18
- package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
- package/src/rbac/components/NavigationGuard.tsx +10 -8
- package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
- package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
- package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
- package/src/rbac/components/PagePermissionGuard.test.tsx +1430 -0
- package/src/rbac/components/PagePermissionGuard.tsx +188 -381
- package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
- package/src/rbac/config.test.ts +131 -48
- package/src/rbac/config.ts +69 -26
- package/src/rbac/docs/event-based-apps.md +26 -13
- package/src/rbac/engine.comprehensive.test.ts +808 -0
- package/src/rbac/engine.test.ts +974 -130
- package/src/rbac/engine.ts +53 -13
- package/src/rbac/errors.test.ts +99 -87
- package/src/rbac/errors.ts +89 -55
- package/src/rbac/eslint-rules.js +2 -2
- package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
- package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +23 -14
- package/src/rbac/hooks/permissions/useCan.test.ts +798 -0
- package/src/rbac/hooks/permissions/useCan.ts +173 -253
- package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +63 -10
- package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +50 -78
- package/src/rbac/hooks/useCan.test.ts +348 -32
- package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
- package/src/rbac/hooks/usePageGuardScope.ts +117 -0
- package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
- package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
- package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
- package/src/rbac/hooks/usePermissions.test.ts +459 -33
- package/src/rbac/hooks/usePermissions.ts +5 -7
- package/src/rbac/hooks/useRBAC.test.ts +1784 -21
- package/src/rbac/hooks/useRBAC.ts +148 -88
- package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
- package/src/rbac/hooks/useResolvedScope.ts +4 -1
- package/src/rbac/hooks/useResourcePermissions.test.ts +561 -24
- package/src/rbac/hooks/useResourcePermissions.ts +76 -140
- package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
- package/src/rbac/hooks/useRoleManagement.test.ts +634 -61
- package/src/rbac/hooks/useRoleManagement.ts +158 -586
- package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
- package/src/rbac/hooks/useSecureSupabase.ts +21 -14
- package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
- package/src/rbac/index.test.ts +107 -0
- package/src/rbac/index.ts +32 -32
- package/src/rbac/performance.test.ts +451 -0
- package/src/rbac/permissions.test.ts +149 -68
- package/src/rbac/permissions.ts +0 -3
- package/src/rbac/rbac-core.test.tsx +276 -0
- package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
- package/src/rbac/rbac-engine-simplified.test.ts +252 -0
- package/src/rbac/rbac-functions.test.ts +703 -0
- package/src/rbac/rbac-integration.test.ts +523 -0
- package/src/rbac/rbac-role-isolation.test.ts +456 -0
- package/src/rbac/request-deduplication.test.ts +352 -0
- package/src/rbac/request-deduplication.ts +5 -4
- package/src/rbac/scenarios.user-role.test.tsx +271 -0
- package/src/rbac/secureClient.test.ts +499 -115
- package/src/rbac/secureClient.ts +54 -28
- package/src/rbac/security.test.ts +448 -44
- package/src/rbac/security.ts +7 -6
- package/src/rbac/types/roleManagement.ts +66 -0
- package/src/rbac/types.test.ts +236 -0
- package/src/rbac/types.ts +7 -5
- package/src/rbac/utils/clientSecurity.test.ts +192 -0
- package/src/rbac/utils/clientSecurity.ts +6 -4
- package/src/rbac/utils/contextValidator.test.ts +126 -0
- package/src/rbac/utils/contextValidator.ts +6 -3
- package/src/rbac/utils/deep-equal.test.ts +76 -0
- package/src/rbac/utils/eventContext.test.ts +401 -0
- package/src/rbac/utils/eventContext.ts +38 -34
- package/src/rbac/utils/fetchPermissionMap.ts +13 -0
- package/src/rbac/utils/permissionMapHelpers.ts +34 -0
- package/src/rbac/utils/roleManagementRpc.ts +303 -0
- package/src/services/AuthService.edge-cases.test.ts +746 -0
- package/src/services/AuthService.restoreSession.test.ts +59 -0
- package/src/services/AuthService.test.ts +1362 -0
- package/src/services/AuthService.ts +197 -216
- package/src/services/BaseService.edge-cases.test.ts +506 -0
- package/src/services/BaseService.test.ts +363 -0
- package/src/services/EventService.edge-cases.test.ts +636 -0
- package/src/services/EventService.eventColours.test.ts +64 -0
- package/src/services/EventService.test.ts +1250 -0
- package/src/services/EventService.ts +244 -315
- package/src/services/InactivityService.edge-cases.test.ts +492 -0
- package/src/services/InactivityService.lifecycle.test.ts +406 -0
- package/src/services/InactivityService.test.ts +829 -0
- package/src/services/InactivityService.ts +172 -213
- package/src/services/OrganisationService.edge-cases.test.ts +633 -0
- package/src/services/OrganisationService.pagination.test.ts +409 -0
- package/src/services/OrganisationService.test.ts +1579 -0
- package/src/services/OrganisationService.ts +186 -257
- package/src/services/base/BaseService.test.ts +214 -0
- package/src/services/interfaces/IAuthService.test.ts +184 -0
- package/src/services/interfaces/IAuthService.ts +10 -9
- package/src/services/interfaces/IEventService.test.ts +176 -0
- package/src/services/interfaces/IInactivityService.test.ts +183 -0
- package/src/services/interfaces/IOrganisationService.test.ts +207 -0
- package/src/services/interfaces/IOrganisationService.ts +0 -1
- package/src/styles/core.css +244 -12
- package/src/theming/parseEventColours.test.ts +321 -0
- package/src/theming/parseEventColours.ts +18 -9
- package/src/theming/runtime.test.ts +495 -0
- package/src/theming/runtime.ts +72 -7
- package/src/types/api-result.ts +53 -0
- package/src/types/auth.ts +0 -1
- package/src/types/core.test.ts +397 -0
- package/src/types/database-generated.test.ts +78 -0
- package/src/types/database.generated.ts +45 -10
- package/src/types/event.ts +39 -19
- package/src/types/file-reference.test.ts +351 -0
- package/src/types/file-reference.ts +37 -12
- package/src/types/guards.test.ts +246 -0
- package/src/types/index.test.ts +265 -0
- package/src/types/index.ts +3 -0
- package/src/types/organisation.roles.test.ts +55 -0
- package/src/types/organisation.test.ts +1105 -0
- package/src/types/organisation.ts +15 -15
- package/src/types/rpc-responses.ts +33 -0
- package/src/types/supabase.ts +14 -6
- package/src/types/theme.test.ts +830 -0
- package/src/types/type-validation.test.ts +526 -0
- package/src/types/validation.test.ts +729 -0
- package/src/types/vitest-globals.d.ts +1 -1
- package/src/utils/app/appConfig.test.ts +235 -0
- package/src/utils/app/appIdResolver.test.ts +252 -57
- package/src/utils/app/appIdResolver.ts +31 -20
- package/src/utils/app/appNameResolver.test.ts +18 -10
- package/src/utils/app/appNameResolver.ts +11 -9
- package/src/utils/app/appPortMap.test.ts +125 -0
- package/src/utils/app/appPortMap.ts +51 -0
- package/src/utils/app/buildAppUrl.test.ts +273 -0
- package/src/utils/app/buildAppUrl.ts +114 -0
- package/src/utils/appConfig.unit.test.ts +55 -0
- package/src/utils/audit/audit.test.ts +354 -39
- package/src/utils/audit.unit.test.ts +69 -0
- package/src/utils/auth-utils.unit.test.ts +69 -0
- package/src/utils/bundleAnalysis.unit.test.ts +326 -0
- package/src/utils/cn.unit.test.ts +34 -0
- package/src/utils/context/organisationContext.test.ts +115 -95
- package/src/utils/context/organisationContext.ts +32 -43
- package/src/utils/context/sessionTracking.test.ts +354 -0
- package/src/utils/core/cn.test.ts +66 -0
- package/src/utils/core/debugLogger.test.ts +113 -0
- package/src/utils/core/debugLogger.ts +15 -8
- package/src/utils/core/logger.test.ts +217 -0
- package/src/utils/core/logger.ts +20 -16
- package/src/utils/core/mergeRefs.ts +24 -0
- package/src/utils/debugLogger.test.ts +417 -0
- package/src/utils/device/deviceFingerprint.test.ts +8 -5
- package/src/utils/device/deviceFingerprint.ts +3 -3
- package/src/utils/deviceFingerprint.unit.test.ts +818 -0
- package/src/utils/dynamic/createLazyComponent.tsx +46 -0
- package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
- package/src/utils/dynamic/dynamicUtils.ts +6 -6
- package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
- package/src/utils/dynamic/lazyLoad.tsx +8 -36
- package/src/utils/dynamic/papaparseLoader.ts +7 -0
- package/src/utils/dynamicUtils.unit.test.ts +331 -0
- package/src/utils/file-reference/file-reference.test.ts +1238 -0
- package/src/utils/file-reference/index.ts +330 -348
- package/src/utils/formatDate.unit.test.ts +109 -0
- package/src/utils/formatting/formatDate.test.ts +22 -148
- package/src/utils/formatting/formatDateTime.test.ts +41 -119
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +41 -85
- package/src/utils/formatting/formatNumber.test.ts +259 -0
- package/src/utils/formatting/formatTime.test.ts +36 -128
- package/src/utils/formatting/formatting.ts +1 -1
- package/src/utils/formatting.unit.test.ts +99 -0
- package/src/utils/google-places/googlePlacesUtils.test.ts +127 -36
- package/src/utils/google-places/googlePlacesUtils.ts +67 -86
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +68 -8
- package/src/utils/google-places/loadGoogleMapsScript.ts +140 -118
- package/src/utils/index.ts +52 -11
- package/src/utils/index.unit.test.ts +251 -0
- package/src/utils/lazyLoad.unit.test.tsx +319 -0
- package/src/utils/location/location.test.ts +19 -116
- package/src/utils/logger.unit.test.ts +398 -0
- package/src/utils/organisationContext.unit.test.ts +180 -0
- package/src/utils/performance/bundleAnalysis.test.ts +148 -0
- package/src/utils/performance/bundleAnalysis.ts +16 -22
- package/src/utils/performance/performanceBenchmark.test.ts +251 -0
- package/src/utils/performance/performanceBenchmark.ts +12 -4
- package/src/utils/performance/performanceBudgets.test.ts +241 -0
- package/src/utils/performance/performanceBudgets.ts +9 -6
- package/src/utils/performanceBenchmark.test.ts +174 -0
- package/src/utils/performanceBudgets.unit.test.ts +288 -0
- package/src/utils/permissionTypes.unit.test.ts +250 -0
- package/src/utils/permissionUtils.unit.test.ts +362 -0
- package/src/utils/permissions/permissionTypes.test.ts +149 -0
- package/src/utils/permissions/permissionUtils.test.ts +20 -42
- package/src/utils/persistence/keyDerivation.test.ts +306 -0
- package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
- package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
- package/src/utils/request-deduplication.test.ts +349 -0
- package/src/utils/request-deduplication.ts +6 -4
- package/src/utils/sanitization.unit.test.ts +346 -0
- package/src/utils/schemaUtils.unit.test.ts +441 -0
- package/src/utils/secureDataAccess.unit.test.ts +334 -0
- package/src/utils/secureErrors.unit.test.ts +390 -0
- package/src/utils/secureStorage.unit.test.ts +289 -0
- package/src/utils/security/auth-utils.ts +38 -27
- package/src/utils/security/secureDataAccess.test.ts +22 -191
- package/src/utils/security/secureDataAccess.ts +241 -281
- package/src/utils/security/secureErrors.test.ts +163 -0
- package/src/utils/security/secureStorage.test.ts +156 -0
- package/src/utils/security/secureStorage.ts +1 -1
- package/src/utils/security/security.test.ts +212 -0
- package/src/utils/security/security.ts +15 -18
- package/src/utils/security/securityMonitor.test.ts +90 -0
- package/src/utils/security/securityMonitor.ts +1 -1
- package/src/utils/security.unit.test.ts +155 -0
- package/src/utils/securityMonitor.unit.test.ts +276 -0
- package/src/utils/sessionTracking.unit.test.ts +218 -0
- package/src/utils/storage/config.unit.test.ts +239 -0
- package/src/utils/storage/helpers.test.ts +769 -456
- package/src/utils/storage/helpers.ts +174 -253
- package/src/utils/storage/index.unit.test.ts +68 -0
- package/src/utils/storage/storageUtils.ts +32 -0
- package/src/utils/storage/types.ts +9 -2
- package/src/utils/supabase/createBaseClient.test.ts +201 -0
- package/src/utils/supabase/createBaseClient.ts +2 -1
- package/src/utils/timezone/timezone.test.ts +26 -44
- package/src/utils/timezone.test.ts +345 -0
- package/src/utils/validation/common.test.ts +115 -0
- package/src/utils/validation/csrf.test.ts +198 -0
- package/src/utils/validation/csrf.ts +42 -41
- package/src/utils/validation/htmlSanitization.ts +27 -31
- package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
- package/src/utils/validation/passwordSchema.test.ts +164 -0
- package/src/utils/validation/schema.test.ts +127 -0
- package/src/utils/validation/schema.ts +6 -3
- package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
- package/src/utils/validation/sqlInjectionProtection.ts +2 -2
- package/src/utils/validation/user.test.ts +173 -0
- package/src/utils/validation/validation.test.ts +197 -0
- package/src/utils/validation/validationUtils.test.ts +294 -0
- package/src/utils/validation.unit.test.ts +307 -0
- package/src/utils/validationUtils.unit.test.ts +558 -0
- package/src/vite-env.d.ts +6 -0
- package/dist/AuthService-DmfO5rGS.d.ts +0 -524
- package/dist/DataTable-DRUIgtUH.d.ts +0 -166
- package/dist/DataTable-SOAFXIWY.js +0 -15
- package/dist/PublicPageProvider-CIGSujI2.d.ts +0 -4147
- package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
- package/dist/UnifiedAuthProvider-CKvHP1MK.d.ts +0 -139
- package/dist/api-7P7DI652.js +0 -4
- package/dist/audit-MYQXYZFU.js +0 -3
- package/dist/auth-BZOJqrdd.d.ts +0 -49
- package/dist/chunk-4DDCYDQ3.js +0 -544
- package/dist/chunk-5HNSDQWH.js +0 -5046
- package/dist/chunk-5W2A3DRC.js +0 -164
- package/dist/chunk-6GLLNA6U.js +0 -31
- package/dist/chunk-7ILTDCL2.js +0 -80
- package/dist/chunk-A3W6LW53.js +0 -70
- package/dist/chunk-AHU7G2R5.js +0 -423
- package/dist/chunk-C7ZQ5O4C.js +0 -481
- package/dist/chunk-EF2UGZWY.js +0 -611
- package/dist/chunk-FEJLJNWA.js +0 -181
- package/dist/chunk-FYHN4DD5.js +0 -415
- package/dist/chunk-GS5672WG.js +0 -2003
- package/dist/chunk-HF6O3O37.js +0 -187
- package/dist/chunk-J2U36LHD.js +0 -8517
- package/dist/chunk-LX6U42O3.js +0 -2177
- package/dist/chunk-MPBLMWVR.js +0 -2161
- package/dist/chunk-OJ4SKRSV.js +0 -105
- package/dist/chunk-S6ZQKDY6.js +0 -62
- package/dist/chunk-S7DKJPLT.js +0 -699
- package/dist/chunk-T5CVK4R3.js +0 -2816
- package/dist/chunk-TTRFSOKR.js +0 -121
- package/dist/chunk-Z2FNRKF3.js +0 -994
- package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
- package/dist/event-CW5YB_2p.d.ts +0 -239
- package/dist/file-reference-BavO2eQj.d.ts +0 -148
- package/dist/functions-lBy5L2ry.d.ts +0 -208
- package/dist/timezone-0AyangqX.d.ts +0 -697
- package/dist/types-BeoeWV5I.d.ts +0 -110
- package/dist/types-DXstZpNI.d.ts +0 -614
- package/dist/types-t9H8qKRw.d.ts +0 -55
- package/dist/usePublicRouteParams-DQLrDqDb.d.ts +0 -876
- package/dist/useToast-AyaT-x7p.d.ts +0 -68
- package/dist/validation-643vUDZW.d.ts +0 -177
- package/scripts/build-docs-incremental.js +0 -179
- package/scripts/eslint-audit.cjs +0 -123
- package/scripts/generate-docs.js +0 -157
- package/scripts/install-cursor-rules.cjs +0 -255
- package/scripts/install-eslint-config.cjs +0 -349
- package/scripts/setup-build-cache.js +0 -73
- package/scripts/validate-pre-publish.js +0 -145
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -448
- package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
- package/src/__tests__/hooks/usePermissions.test.ts +0 -268
- package/src/__tests__/integration/UserProfile.test.tsx +0 -124
- package/src/__tests__/public-recipe-view.test.ts +0 -228
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -220
- package/src/__tests__/rls-policies.test.ts +0 -471
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
- package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
- package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -483
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -1474
- package/src/components/DataTable/__tests__/README.md +0 -145
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
- package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
- package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -730
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -325
- package/src/components/DataTable/__tests__/styles.test.ts +0 -382
- package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -380
- package/src/components/DataTable/__tests__/test-utils.ts +0 -94
- package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
- package/src/components/DataTable/components/ActionButtons.tsx +0 -190
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
- package/src/components/DataTable/components/ColumnFilter.tsx +0 -118
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
- package/src/components/DataTable/components/DataTableLayout.tsx +0 -573
- package/src/components/DataTable/components/DataTableModals.tsx +0 -245
- package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
- package/src/components/DataTable/components/EditFields.tsx +0 -327
- package/src/components/DataTable/components/EditableRow.tsx +0 -462
- package/src/components/DataTable/components/EmptyState.tsx +0 -79
- package/src/components/DataTable/components/FilterRow.tsx +0 -141
- package/src/components/DataTable/components/LoadingState.tsx +0 -17
- package/src/components/DataTable/components/PaginationControls.tsx +0 -289
- package/src/components/DataTable/components/RowComponent.tsx +0 -403
- package/src/components/DataTable/components/SortIndicator.tsx +0 -50
- package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -355
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -657
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -913
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -572
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -612
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -708
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -479
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -475
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -157
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -1061
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -437
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -474
- package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -617
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -1093
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -139
- package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -519
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -1004
- package/src/components/DataTable/components/cellValueUtils.ts +0 -40
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
- package/src/components/DataTable/components/index.ts +0 -16
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -342
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -205
- package/src/components/DataTable/core/DataManager.ts +0 -188
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -312
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -123
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -305
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -84
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -115
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -100
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -120
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -104
- package/src/components/DataTable/core/index.ts +0 -1
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -521
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -167
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -124
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -117
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -102
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -596
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -53
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -214
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -448
- package/src/components/DataTable/hooks/index.ts +0 -13
- package/src/components/DataTable/types.ts +0 -761
- package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -612
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
- package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -266
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -247
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -570
- package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -251
- package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -207
- package/src/components/DataTable/utils/index.ts +0 -10
- package/src/components/PublicLayout/index.ts +0 -32
- package/src/components/Select/hooks/useSelectEvents.ts +0 -87
- package/src/components/Select/hooks/useSelectSearch.ts +0 -91
- package/src/components/Select/hooks/useSelectState.ts +0 -104
- package/src/components/Select/utils/text.ts +0 -26
- package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -615
- package/src/hooks/__tests__/hooks.integration.test.tsx +0 -607
- package/src/hooks/__tests__/index.unit.test.ts +0 -220
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +0 -111
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -347
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -144
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -776
- package/src/hooks/__tests__/useDataTableState.test.ts +0 -76
- package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -82
- package/src/hooks/__tests__/useEvents.unit.test.ts +0 -252
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1112
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -916
- package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -129
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -230
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -828
- package/src/hooks/__tests__/useFormDialog.test.ts +0 -478
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
- package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -910
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -294
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
- package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -88
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -785
- package/src/hooks/__tests__/usePublicEvent.test.ts +0 -678
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -630
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -951
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -443
- package/src/hooks/__tests__/useQueryCache.test.ts +0 -144
- package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
- package/src/hooks/__tests__/useSessionDraft.test.ts +0 -163
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
- package/src/hooks/__tests__/useStorage.unit.test.ts +0 -751
- package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -37
- package/src/hooks/public/index.ts +0 -36
- package/src/hooks/public/usePublicFileDisplay.ts +0 -504
- package/src/hooks/useFileDisplay.ts +0 -715
- package/src/providers/OrganisationProvider.tsx +0 -92
- package/src/providers/__tests__/AuthProvider.test.tsx +0 -287
- package/src/providers/__tests__/EventProvider.test.tsx +0 -551
- package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
- package/src/providers/__tests__/InactivityProvider.test.tsx +0 -572
- package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -617
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -424
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -596
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -263
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -294
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -434
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -313
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -486
- package/src/rbac/__tests__/cache-invalidation.test.ts +0 -399
- package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -813
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
- package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -392
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -258
- package/src/rbac/__tests__/rbac-functions.test.ts +0 -647
- package/src/rbac/__tests__/rbac-integration.test.ts +0 -524
- package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -282
- package/src/rbac/audit-enhanced.ts +0 -384
- package/src/rbac/compliance/database-validator.ts +0 -165
- package/src/rbac/compliance/index.ts +0 -48
- package/src/rbac/compliance/pattern-detector.ts +0 -553
- package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
- package/src/rbac/compliance/runtime-compliance.ts +0 -99
- package/src/rbac/compliance/setup-validator.ts +0 -131
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -975
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -248
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -242
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1107
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -184
- package/src/rbac/components/index.ts +0 -26
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -432
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -579
- package/src/rbac/hooks/index.ts +0 -34
- package/src/rbac/hooks/permissions/index.ts +0 -4
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -128
- package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -53
- package/src/rbac/utils/__tests__/eventContext.test.ts +0 -433
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
- package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -39
- package/src/services/__tests__/AuthService.test.ts +0 -1332
- package/src/services/__tests__/BaseService.test.ts +0 -314
- package/src/services/__tests__/EventService.eventColours.test.ts +0 -76
- package/src/services/__tests__/EventService.test.ts +0 -1025
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -411
- package/src/services/__tests__/InactivityService.test.ts +0 -654
- package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
- package/src/services/__tests__/OrganisationService.test.ts +0 -1176
- package/src/theming/__tests__/parseEventColours.test.ts +0 -321
- package/src/theming/__tests__/runtime.test.ts +0 -569
- package/src/types/__tests__/file-reference.test.ts +0 -447
- package/src/types/__tests__/guards.test.ts +0 -246
- package/src/types/__tests__/organisation.roles.test.ts +0 -55
- package/src/types/__tests__/organisation.test.ts +0 -1133
- package/src/types/__tests__/theme.test.ts +0 -830
- package/src/types/__tests__/type-validation.test.ts +0 -526
- package/src/types/__tests__/validation.test.ts +0 -731
- package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
- package/src/utils/__tests__/audit.unit.test.ts +0 -69
- package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -339
- package/src/utils/__tests__/cn.unit.test.ts +0 -34
- package/src/utils/__tests__/debugLogger.test.ts +0 -417
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -318
- package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
- package/src/utils/__tests__/formatting.unit.test.ts +0 -99
- package/src/utils/__tests__/index.unit.test.ts +0 -251
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -321
- package/src/utils/__tests__/logger.unit.test.ts +0 -398
- package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
- package/src/utils/__tests__/performanceBenchmark.test.ts +0 -175
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -253
- package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
- package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
- package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
- package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -335
- package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
- package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
- package/src/utils/__tests__/security.unit.test.ts +0 -149
- package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
- package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
- package/src/utils/__tests__/timezone.test.ts +0 -345
- package/src/utils/__tests__/validation.unit.test.ts +0 -308
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
- package/src/utils/app/appNameResolver.simple.test.ts +0 -212
- package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -875
- package/src/utils/google-places/index.ts +0 -26
- package/src/utils/location/index.ts +0 -16
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -135
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -123
- package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
- package/src/utils/storage/__tests__/index.unit.test.ts +0 -16
- package/src/utils/storage/index.ts +0 -67
- package/src/utils/timezone/index.ts +0 -17
- package/src/utils/validation/__tests__/csrf.test.ts +0 -105
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -598
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -92
- package/src/utils/validation/__tests__/validationUtils.test.ts +0 -72
- package/src/utils/validation/index.ts +0 -73
- /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
- /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
- /package/src/providers/{__tests__/README.md → README.md} +0 -0
- /package/src/types/{__tests__/README.md → README.md} +0 -0
|
@@ -8,59 +8,40 @@
|
|
|
8
8
|
* This is the main component that consumers will use.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import React, { useMemo, useCallback
|
|
12
|
-
import {
|
|
11
|
+
import React, { useMemo, useCallback } from 'react';
|
|
12
|
+
import type { SortingState } from '@tanstack/react-table';
|
|
13
13
|
import { useLocation } from 'react-router-dom';
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
} from '
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { useColumnVisibilityPersistence } from '../hooks/useColumnVisibilityPersistence';
|
|
24
|
-
import { useDataTableState } from '../hooks/useDataTableState';
|
|
25
|
-
import { useDataTableDataPipeline } from '../hooks/useDataTableDataPipeline';
|
|
26
|
-
import { useServerSideDataEffect } from '../hooks/useServerSideDataEffect';
|
|
27
|
-
import { useEffectiveColumnOrder } from '../hooks/useEffectiveColumnOrder';
|
|
28
|
-
import { useTableHandlers } from '../hooks/useTableHandlers';
|
|
29
|
-
import { useDataTableConfiguration } from '../hooks/useDataTableConfiguration';
|
|
30
|
-
import type { TableStateSnapshot } from '../hooks/useTableHandlers';
|
|
31
|
-
import { ColumnFactory } from '../core/ColumnFactory';
|
|
32
|
-
import { AccessDeniedPage } from './AccessDeniedPage';
|
|
33
|
-
// NOTE: All toast() calls in this component use the default timeout (5 seconds).
|
|
34
|
-
// Do NOT set duration or timeout properties - let the toast system use its default.
|
|
35
|
-
import { toast } from '../../../hooks/useToast';
|
|
14
|
+
import { useIsPrint } from '../../../hooks/useIsPrint';
|
|
15
|
+
import { LoadingState } from '../ui/table/LoadingState';
|
|
16
|
+
import { DataTableLayout } from '../ui/layout/DataTableLayout';
|
|
17
|
+
import { DataTableErrorBoundary } from '../ui/layout/DataTableErrorBoundary';
|
|
18
|
+
import { useDataTableDeletionBatching } from '../hooks/useDataTableDeletionBatching';
|
|
19
|
+
import { useDataTableStateAndPersistence } from '../hooks/useDataTableStateAndPersistence';
|
|
20
|
+
import { useDataTablePipeline } from '../hooks/useDataTablePipeline';
|
|
21
|
+
import { useDataTableRenderGuard } from '../hooks/useDataTableRenderGuard';
|
|
22
|
+
import { AccessDeniedPage } from '../ui/shared/AccessDeniedPage';
|
|
36
23
|
import { useUnifiedAuth } from '../../../providers/services/UnifiedAuthProvider';
|
|
37
24
|
import { useDataTablePermissions } from '../hooks/useDataTablePermissions';
|
|
38
|
-
import { useTableColumns } from '../hooks/useTableColumns';
|
|
39
|
-
import { initializeLiveRegion } from '../utils/a11yUtils';
|
|
40
|
-
import { useKeyboardNavigation } from '../hooks/useKeyboardNavigation';
|
|
41
25
|
import { getRowIdSafe } from '../utils/rowUtils';
|
|
42
26
|
import { createLogger } from '../../../utils/core/logger';
|
|
43
|
-
import { usePermissionTracking } from '
|
|
44
|
-
import {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
DataTableAction,
|
|
62
|
-
HierarchicalConfig,
|
|
63
|
-
DataTableRBACConfig,
|
|
27
|
+
import { usePermissionTracking } from '../hooks/usePermissionTracking';
|
|
28
|
+
import {
|
|
29
|
+
normalizeDataTableFeatures,
|
|
30
|
+
type DataRecord,
|
|
31
|
+
type GetRowId,
|
|
32
|
+
type PerformanceConfig,
|
|
33
|
+
type ServerSideConfig,
|
|
34
|
+
type ChunkingConfig,
|
|
35
|
+
type SearchIndexConfig,
|
|
36
|
+
type PaginationMode,
|
|
37
|
+
type EmptyStateConfig,
|
|
38
|
+
type DataTableFeatureConfig,
|
|
39
|
+
type NormalizedDataTableFeatureConfig,
|
|
40
|
+
type DataTableColumn,
|
|
41
|
+
type AggregateConfig,
|
|
42
|
+
type DataTableAction,
|
|
43
|
+
type HierarchicalConfig,
|
|
44
|
+
type DataTableRBACConfig,
|
|
64
45
|
} from '../types';
|
|
65
46
|
import type { ImportModalConfig } from './ImportModal';
|
|
66
47
|
|
|
@@ -111,7 +92,7 @@ export interface DataTableCoreProps<TData extends DataRecord> {
|
|
|
111
92
|
onEditRow?: (row: TData, data: Partial<TData>) => void;
|
|
112
93
|
onDeleteRow?: (row: TData) => void;
|
|
113
94
|
onCreateRow?: (data: Partial<TData>) => void;
|
|
114
|
-
onImport?: (data: TData[]) =>
|
|
95
|
+
onImport?: (data: TData[]) => import('../ui/modals/importModalPersistence').ImportHandlerResult;
|
|
115
96
|
onExport?: (options: import('../types').ExportOptions<TData>) => void | Promise<void>;
|
|
116
97
|
onRowSelectionChange?: (selection: Record<string, boolean>) => void;
|
|
117
98
|
selection?: Record<string, boolean>;
|
|
@@ -120,15 +101,19 @@ export interface DataTableCoreProps<TData extends DataRecord> {
|
|
|
120
101
|
// Utilities
|
|
121
102
|
getRowId?: GetRowId<TData>;
|
|
122
103
|
isLoading?: boolean;
|
|
123
|
-
emptyState?: EmptyStateConfig | React.ReactElement
|
|
104
|
+
emptyState?: EmptyStateConfig | React.ReactElement;
|
|
124
105
|
aggregates?: AggregateConfig[];
|
|
125
106
|
importModalConfig?: ImportModalConfig;
|
|
107
|
+
/** Called when the import modal is closed (e.g. to refetch table data). */
|
|
108
|
+
onImportModalClose?: () => void;
|
|
126
109
|
actions?: DataTableAction<TData>[];
|
|
127
110
|
columnOrder?: string[];
|
|
128
111
|
|
|
129
112
|
// Default state configuration
|
|
130
113
|
defaultGrouping?: string[];
|
|
131
114
|
defaultSorting?: SortingState;
|
|
115
|
+
/** Initial column visibility state - columns with value `false` will be hidden by default */
|
|
116
|
+
initialColumnVisibility?: Record<string, boolean>;
|
|
132
117
|
|
|
133
118
|
// Persistence configuration
|
|
134
119
|
storageKey?: string;
|
|
@@ -158,7 +143,7 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
158
143
|
virtualHeight = 600,
|
|
159
144
|
enhancedPagination = false,
|
|
160
145
|
loadingComponent: LoadingComponent = LoadingState,
|
|
161
|
-
errorComponent:
|
|
146
|
+
errorComponent: _ErrorComponent,
|
|
162
147
|
initialPageSize = 10,
|
|
163
148
|
onEditRow,
|
|
164
149
|
onDeleteRow,
|
|
@@ -173,99 +158,37 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
173
158
|
emptyState,
|
|
174
159
|
aggregates = [],
|
|
175
160
|
importModalConfig,
|
|
161
|
+
onImportModalClose,
|
|
176
162
|
actions = [],
|
|
177
163
|
columnOrder: externalColumnOrder,
|
|
178
164
|
defaultGrouping,
|
|
179
165
|
defaultSorting,
|
|
166
|
+
initialColumnVisibility: initialColumnVisibilityProp,
|
|
180
167
|
storageKey,
|
|
181
168
|
onLayoutChange,
|
|
182
169
|
} = props;
|
|
183
170
|
|
|
184
171
|
const logger = createLogger('DataTableCore');
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const pendingDeletionsRef = useRef<Set<string>>(new Set());
|
|
190
|
-
const dataSnapshotRef = useRef<TData[]>(data);
|
|
191
|
-
const dataChangeCountRef = useRef(0);
|
|
192
|
-
const previousDataLengthRef = useRef(data.length);
|
|
193
|
-
|
|
194
|
-
// CRITICAL: Use useLayoutEffect to capture previous length synchronously
|
|
195
|
-
// This runs before paint, so we can detect changes before React commits
|
|
196
|
-
useLayoutEffect(() => {
|
|
197
|
-
const currentLength = data.length;
|
|
198
|
-
const previousLength = previousDataLengthRef.current;
|
|
199
|
-
|
|
200
|
-
// Check if length decreased - this is the key detection
|
|
201
|
-
const lengthDecreased = currentLength < previousLength;
|
|
202
|
-
|
|
203
|
-
if (lengthDecreased && !isDeleting) {
|
|
204
|
-
// Data length decreased - start deletion batching
|
|
205
|
-
const snapshotLength = dataSnapshotRef.current.length;
|
|
206
|
-
|
|
207
|
-
// Data decrease detected (logging removed for performance)
|
|
208
|
-
|
|
209
|
-
// If snapshot is larger, it's valid (has pre-deletion state)
|
|
210
|
-
// Otherwise, update it to preserve current state
|
|
211
|
-
if (snapshotLength <= currentLength) {
|
|
212
|
-
dataSnapshotRef.current = [...data];
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
setIsDeleting(true);
|
|
216
|
-
|
|
217
|
-
// Set timeout to reset after batching
|
|
218
|
-
if (deletionTimeoutRef.current) {
|
|
219
|
-
clearTimeout(deletionTimeoutRef.current);
|
|
220
|
-
}
|
|
221
|
-
deletionTimeoutRef.current = setTimeout(() => {
|
|
222
|
-
setIsDeleting(false);
|
|
223
|
-
dataSnapshotRef.current = data;
|
|
224
|
-
previousDataLengthRef.current = data.length;
|
|
225
|
-
// Batching complete (logging removed for performance)
|
|
226
|
-
}, 150);
|
|
227
|
-
|
|
228
|
-
// Update previous length AFTER setting up batching
|
|
229
|
-
previousDataLengthRef.current = currentLength;
|
|
230
|
-
} else if (!lengthDecreased && !isDeleting) {
|
|
231
|
-
// No deletion - update snapshot and previous length normally
|
|
232
|
-
dataSnapshotRef.current = data;
|
|
233
|
-
previousDataLengthRef.current = currentLength;
|
|
234
|
-
} else if (isDeleting) {
|
|
235
|
-
// Already deleting - just update previous length for next comparison
|
|
236
|
-
previousDataLengthRef.current = currentLength;
|
|
237
|
-
}
|
|
238
|
-
}, [data, isDeleting]);
|
|
239
|
-
|
|
240
|
-
// Keep data snapshot stable during deletions to prevent flashing
|
|
241
|
-
// Logging effect - runs after layout to show what happened
|
|
242
|
-
useEffect(() => {
|
|
243
|
-
dataChangeCountRef.current += 1;
|
|
244
|
-
|
|
245
|
-
const previousLength = previousDataLengthRef.current;
|
|
246
|
-
const currentLength = data.length;
|
|
247
|
-
const snapshotLength = dataSnapshotRef.current.length;
|
|
248
|
-
const lengthDecreased = currentLength < previousLength;
|
|
249
|
-
|
|
250
|
-
// Data prop changed (logging removed for performance)
|
|
251
|
-
}, [data, isDeleting]);
|
|
252
|
-
|
|
253
|
-
// Use snapshot data during deletions to prevent flashing
|
|
254
|
-
// CRITICAL: If we're deleting and data length decreased, use snapshot to prevent flashing
|
|
255
|
-
const dataLengthChanged = data.length !== dataSnapshotRef.current.length;
|
|
256
|
-
const isDataDecreasing = data.length < dataSnapshotRef.current.length;
|
|
257
|
-
const effectiveData = (isDeleting && isDataDecreasing) ? dataSnapshotRef.current : data;
|
|
258
|
-
|
|
259
|
-
// Effective data tracking (logging removed for performance)
|
|
260
|
-
|
|
172
|
+
|
|
173
|
+
const { effectiveData, isDeleting, setIsDeleting, deletionRefs } =
|
|
174
|
+
useDataTableDeletionBatching<TData>(data);
|
|
175
|
+
|
|
261
176
|
// ============================================================================
|
|
262
177
|
// ALL HOOKS MUST BE CALLED IN THE SAME ORDER EVERY RENDER
|
|
178
|
+
// Responsibilities: useDataTableDeletionBatching (in-flight delete UI),
|
|
179
|
+
// useUnifiedAuth (user), useIsPrint (print), useDataTablePermissions (RBAC),
|
|
180
|
+
// usePermissionTracking (timeout/loading), useDataTableStateAndPersistence (state +
|
|
181
|
+
// column order/visibility), useDataTablePipeline (table instance + layout props),
|
|
182
|
+
// useDataTableRenderGuard (loading / access-denied gate).
|
|
263
183
|
// ============================================================================
|
|
264
|
-
|
|
184
|
+
|
|
265
185
|
// MANDATORY: Get authenticated user - ALWAYS call this hook
|
|
266
186
|
const authResult = useUnifiedAuth();
|
|
267
187
|
const user = authResult.user;
|
|
268
188
|
|
|
189
|
+
// Detect print mode to disable pagination when printing
|
|
190
|
+
const isPrint = useIsPrint();
|
|
191
|
+
|
|
269
192
|
const requestedFeatures = useMemo<NormalizedDataTableFeatureConfig>(() =>
|
|
270
193
|
normalizeDataTableFeatures(incomingFeatures),
|
|
271
194
|
[incomingFeatures]);
|
|
@@ -285,808 +208,117 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
285
208
|
|
|
286
209
|
|
|
287
210
|
// ============================================================================
|
|
288
|
-
//
|
|
211
|
+
// STATE AND PERSISTENCE - column order/visibility, core state, sync effects
|
|
289
212
|
// ============================================================================
|
|
290
|
-
|
|
291
|
-
const
|
|
213
|
+
|
|
214
|
+
const location = useLocation();
|
|
215
|
+
|
|
216
|
+
const {
|
|
217
|
+
state,
|
|
218
|
+
stateActions,
|
|
219
|
+
rowSelection,
|
|
220
|
+
effectiveColumnOrder,
|
|
221
|
+
updateSavedColumnVisibility,
|
|
222
|
+
updateColumnOrder,
|
|
223
|
+
} = useDataTableStateAndPersistence<TData>({
|
|
292
224
|
columns,
|
|
293
225
|
externalColumnOrder,
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
// ============================================================================
|
|
298
|
-
// COLUMN VISIBILITY PERSISTENCE - ALWAYS call these hooks
|
|
299
|
-
// ============================================================================
|
|
300
|
-
|
|
301
|
-
const {
|
|
302
|
-
columnVisibility: savedColumnVisibility,
|
|
303
|
-
isLoaded: isColumnVisibilityLoaded,
|
|
304
|
-
updateColumnVisibility: updateSavedColumnVisibility,
|
|
305
|
-
} = useColumnVisibilityPersistence({
|
|
306
|
-
tableId: title ? `datatable-${title.toLowerCase().replace(/\s+/g, '-')}` : undefined,
|
|
307
|
-
defaultVisibility: {},
|
|
308
|
-
enablePersistence: secureFeatures.columnVisibility,
|
|
226
|
+
title,
|
|
227
|
+
initialColumnVisibility: initialColumnVisibilityProp || {},
|
|
309
228
|
storageKey,
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
return {};
|
|
318
|
-
}, [secureFeatures.columnVisibility, savedColumnVisibility]);
|
|
319
|
-
|
|
320
|
-
// Get location for route-based key derivation
|
|
321
|
-
let location: { pathname: string } | null = null;
|
|
322
|
-
try {
|
|
323
|
-
// useLocation may not be available if React Router is not set up
|
|
324
|
-
const routerLocation = useLocation();
|
|
325
|
-
location = routerLocation;
|
|
326
|
-
} catch {
|
|
327
|
-
// Router not available, location will be null
|
|
328
|
-
location = null;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Extract column field names for sensitive field filtering
|
|
332
|
-
const columnFieldNames = useMemo(() => {
|
|
333
|
-
return columns
|
|
334
|
-
.map((col) => col.accessorKey || col.id)
|
|
335
|
-
.filter((key): key is string => Boolean(key));
|
|
336
|
-
}, [columns]);
|
|
337
|
-
|
|
338
|
-
// Use the centralized state management hook for ALL table state
|
|
339
|
-
// Note: 'actions' prop parameter is shadowed by destructuring, so we rename to stateActions
|
|
340
|
-
const { state, actions: stateActions, clearDraft } = useDataTableState<TData>({
|
|
229
|
+
secureFeatures: {
|
|
230
|
+
columnVisibility: secureFeatures.columnVisibility,
|
|
231
|
+
columnReordering: secureFeatures.columnReordering,
|
|
232
|
+
selection: secureFeatures.selection,
|
|
233
|
+
},
|
|
234
|
+
rbacPageId: rbac.pageId,
|
|
341
235
|
initialPageSize,
|
|
342
|
-
|
|
343
|
-
initialRowSelection: selection || {},
|
|
236
|
+
selection,
|
|
344
237
|
onRowSelectionChange,
|
|
345
238
|
defaultSorting: defaultSorting || [],
|
|
346
239
|
defaultGrouping: defaultGrouping || [],
|
|
347
|
-
// Persistence props
|
|
348
|
-
rbacPageId: rbac.pageId,
|
|
349
|
-
title,
|
|
350
240
|
location,
|
|
351
|
-
columnFieldNames,
|
|
352
241
|
});
|
|
353
|
-
|
|
354
|
-
// Apply saved visibility to state if available
|
|
355
|
-
useEffect(() => {
|
|
356
|
-
if (secureFeatures.columnVisibility && isColumnVisibilityLoaded && Object.keys(initialColumnVisibility).length > 0) {
|
|
357
|
-
stateActions.setColumnVisibility(initialColumnVisibility);
|
|
358
|
-
}
|
|
359
|
-
}, [secureFeatures.columnVisibility, isColumnVisibilityLoaded, initialColumnVisibility, stateActions]);
|
|
360
|
-
|
|
361
|
-
// Initialize live region for accessibility announcements
|
|
362
|
-
useEffect(() => {
|
|
363
|
-
initializeLiveRegion();
|
|
364
|
-
}, []);
|
|
365
|
-
|
|
366
|
-
// Row selection: prefer controlled prop, fall back to state
|
|
367
|
-
const rowSelection = selection !== undefined ? selection : state.rowSelection;
|
|
368
242
|
|
|
369
243
|
const resolvedGetRowId = useCallback(
|
|
370
244
|
(row: TData, index: number) => getRowIdSafe(row, index, getRowId),
|
|
371
245
|
[getRowId]
|
|
372
246
|
);
|
|
373
|
-
|
|
374
|
-
// ============================================================================
|
|
375
|
-
// AUTO-EXPAND GROUPS WHEN DEFAULT GROUPING IS PROVIDED
|
|
376
|
-
// ============================================================================
|
|
377
|
-
|
|
378
|
-
// Track if we've already initialized expansion state
|
|
379
|
-
const hasInitializedExpansion = useRef(false);
|
|
380
|
-
|
|
381
|
-
// Auto-expand all groups when default grouping is provided (only once on mount)
|
|
382
|
-
useEffect(() => {
|
|
383
|
-
if (!hasInitializedExpansion.current && defaultGrouping && defaultGrouping.length > 0) {
|
|
384
|
-
stateActions.setExpanded(true); // Expand all groups
|
|
385
|
-
hasInitializedExpansion.current = true;
|
|
386
|
-
}
|
|
387
|
-
}, [defaultGrouping, stateActions]);
|
|
388
247
|
|
|
389
|
-
|
|
390
|
-
const { sorting, columnFilters, columnVisibility, grouping, expanded, pagination, columnOrder,
|
|
391
|
-
showImportModal, showFilterRow, isCreating, creationData, editingRowId, editingData } = state;
|
|
392
|
-
|
|
393
|
-
// ============================================================================
|
|
394
|
-
// PERFORMANCE HOOK - ALWAYS call this hook
|
|
395
|
-
// ============================================================================
|
|
396
|
-
|
|
397
|
-
const performanceHook = useDataTablePerformance({
|
|
248
|
+
const pipeline = useDataTablePipeline<TData>({
|
|
398
249
|
data,
|
|
250
|
+
effectiveData,
|
|
251
|
+
columns,
|
|
252
|
+
state,
|
|
253
|
+
stateActions,
|
|
254
|
+
rowSelection,
|
|
255
|
+
effectiveColumnOrder,
|
|
256
|
+
updateSavedColumnVisibility,
|
|
257
|
+
updateColumnOrder,
|
|
258
|
+
secureFeatures,
|
|
259
|
+
permissions,
|
|
260
|
+
deletionRefs,
|
|
261
|
+
isDeleting,
|
|
262
|
+
setIsDeleting,
|
|
263
|
+
onCreateRow,
|
|
264
|
+
onEditRow,
|
|
265
|
+
onDeleteRow,
|
|
266
|
+
onImport,
|
|
267
|
+
onExport,
|
|
268
|
+
onDeleteSelected,
|
|
269
|
+
actions,
|
|
270
|
+
resolvedGetRowId,
|
|
399
271
|
performance,
|
|
400
272
|
serverSide,
|
|
401
273
|
chunking,
|
|
402
274
|
searchIndex,
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
} = performanceHook;
|
|
416
|
-
|
|
417
|
-
const finalPaginationMode = paginationMode || detectedMode;
|
|
418
|
-
|
|
419
|
-
// ============================================================================
|
|
420
|
-
// KEYBOARD NAVIGATION - ALWAYS call this hook
|
|
421
|
-
// ============================================================================
|
|
422
|
-
|
|
423
|
-
const keyboardNavigation = useKeyboardNavigation(
|
|
424
|
-
data.length,
|
|
425
|
-
columns.length,
|
|
426
|
-
{
|
|
427
|
-
enabled: true,
|
|
428
|
-
announceNavigation: true,
|
|
429
|
-
supportsColumnReorder: secureFeatures.columnReordering,
|
|
430
|
-
supportsColumnResize: false, // Column resizing is not currently supported
|
|
431
|
-
}
|
|
432
|
-
);
|
|
433
|
-
|
|
434
|
-
const { lastFocusedElementRef } = useImportModalFocus(state.showImportModal, keyboardNavigation);
|
|
435
|
-
|
|
436
|
-
// ============================================================================
|
|
437
|
-
// HIERARCHICAL DATA VALIDATION AND PROCESSING - ALWAYS call these hooks
|
|
438
|
-
// ============================================================================
|
|
439
|
-
|
|
440
|
-
const {
|
|
441
|
-
finalTableData,
|
|
442
|
-
dataCount: finalDataCount,
|
|
443
|
-
hierarchicalState,
|
|
444
|
-
hierarchicalValidation,
|
|
445
|
-
} = useDataTableDataPipeline<TData>({
|
|
446
|
-
data: effectiveData,
|
|
447
|
-
features: secureFeatures,
|
|
275
|
+
paginationMode,
|
|
276
|
+
initialPageSize,
|
|
277
|
+
externalIsLoading,
|
|
278
|
+
isPrint,
|
|
279
|
+
effectivePageId,
|
|
280
|
+
logger,
|
|
281
|
+
title,
|
|
282
|
+
description,
|
|
283
|
+
variant,
|
|
284
|
+
className,
|
|
285
|
+
emptyState,
|
|
286
|
+
virtualHeight,
|
|
448
287
|
hierarchical,
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
useEffect(() => {
|
|
455
|
-
if (!hierarchicalValidation.isValid) {
|
|
456
|
-
logger.error('Hierarchical data validation failed:', hierarchicalValidation.errors);
|
|
457
|
-
}
|
|
458
|
-
}, [hierarchicalValidation, logger]);
|
|
459
|
-
|
|
460
|
-
// Final table data tracking (logging removed for performance)
|
|
461
|
-
|
|
462
|
-
// Cleanup deletion timeout on unmount
|
|
463
|
-
useEffect(() => {
|
|
464
|
-
return () => {
|
|
465
|
-
if (deletionTimeoutRef.current) {
|
|
466
|
-
clearTimeout(deletionTimeoutRef.current);
|
|
467
|
-
}
|
|
468
|
-
pendingDeletionsRef.current.clear();
|
|
469
|
-
};
|
|
470
|
-
}, []);
|
|
471
|
-
|
|
472
|
-
// Update data snapshot when data changes and we're not deleting
|
|
473
|
-
useEffect(() => {
|
|
474
|
-
if (!isDeleting && data !== dataSnapshotRef.current) {
|
|
475
|
-
dataSnapshotRef.current = data;
|
|
476
|
-
}
|
|
477
|
-
}, [data, isDeleting]);
|
|
478
|
-
|
|
479
|
-
// Cleanup deletion timeout on unmount
|
|
480
|
-
useEffect(() => {
|
|
481
|
-
return () => {
|
|
482
|
-
if (deletionTimeoutRef.current) {
|
|
483
|
-
clearTimeout(deletionTimeoutRef.current);
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
}, []);
|
|
487
|
-
|
|
488
|
-
const {
|
|
489
|
-
columnOrder: savedColumnOrder,
|
|
490
|
-
isLoaded: isColumnOrderLoaded,
|
|
491
|
-
updateColumnOrder,
|
|
492
|
-
} = useColumnOrderPersistence({
|
|
493
|
-
tableId: title ? `datatable-${title.toLowerCase().replace(/\s+/g, '-')}` : undefined,
|
|
494
|
-
defaultOrder: columns.map(col => col.id || col.accessorKey || ''),
|
|
495
|
-
enablePersistence: secureFeatures.columnReordering,
|
|
288
|
+
aggregates,
|
|
289
|
+
importModalConfig,
|
|
290
|
+
onImportModalClose,
|
|
496
291
|
storageKey,
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
useEffect(() => {
|
|
500
|
-
if (
|
|
501
|
-
secureFeatures.columnReordering &&
|
|
502
|
-
isColumnOrderLoaded &&
|
|
503
|
-
savedColumnOrder &&
|
|
504
|
-
savedColumnOrder.length > 0
|
|
505
|
-
) {
|
|
506
|
-
// Normalize: ensure 'select' is first if selection is enabled
|
|
507
|
-
const normalizedOrder = secureFeatures.selection && savedColumnOrder.includes('select')
|
|
508
|
-
? ['select', ...savedColumnOrder.filter(id => id !== 'select')]
|
|
509
|
-
: savedColumnOrder;
|
|
510
|
-
stateActions.setColumnOrder(normalizedOrder);
|
|
511
|
-
}
|
|
512
|
-
}, [secureFeatures.columnReordering, secureFeatures.selection, isColumnOrderLoaded, savedColumnOrder, stateActions]);
|
|
513
|
-
|
|
514
|
-
// CRITICAL: Always ensure state.columnOrder has 'select' first if selection is enabled
|
|
515
|
-
// This fixes any state that gets out of sync (e.g., from localStorage or user reordering)
|
|
516
|
-
useEffect(() => {
|
|
517
|
-
if (secureFeatures.selection && state.columnOrder.includes('select') && state.columnOrder[0] !== 'select') {
|
|
518
|
-
const normalizedOrder = ['select', ...state.columnOrder.filter(id => id !== 'select')];
|
|
519
|
-
stateActions.setColumnOrder(normalizedOrder);
|
|
520
|
-
// Also update persisted order if persistence is enabled
|
|
521
|
-
if (secureFeatures.columnReordering) {
|
|
522
|
-
updateColumnOrder(normalizedOrder);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}, [secureFeatures.selection, secureFeatures.columnReordering, state.columnOrder, stateActions, updateColumnOrder]);
|
|
526
|
-
|
|
527
|
-
// ============================================================================
|
|
528
|
-
// CONFIGURATION RESOLUTION - ALWAYS call these hooks
|
|
529
|
-
// ============================================================================
|
|
530
|
-
|
|
531
|
-
const finalPageSizeOptions = optimizedPageSizeOptions;
|
|
532
|
-
|
|
533
|
-
const validatedInitialPageSize = useMemo(() => {
|
|
534
|
-
if (!secureFeatures.pagination || !finalPageSizeOptions.length) {
|
|
535
|
-
return initialPageSize;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
if (finalPageSizeOptions.includes(initialPageSize)) {
|
|
539
|
-
return initialPageSize;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const sortedOptions = [...finalPageSizeOptions].sort((a, b) => a - b);
|
|
543
|
-
const closestOption = sortedOptions.reduce((prev, curr) =>
|
|
544
|
-
Math.abs(curr - initialPageSize) < Math.abs(prev - initialPageSize) ? curr : prev
|
|
545
|
-
);
|
|
546
|
-
|
|
547
|
-
logger.warn(
|
|
548
|
-
`initialPageSize ${initialPageSize} is not available in page size options [${finalPageSizeOptions.join(', ')}]. Using closest option: ${closestOption}`
|
|
549
|
-
);
|
|
550
|
-
|
|
551
|
-
return closestOption;
|
|
552
|
-
}, [initialPageSize, finalPageSizeOptions, secureFeatures.pagination, logger]);
|
|
553
|
-
|
|
554
|
-
// Determine the effective pageSize to use (validated or current state)
|
|
555
|
-
// CRITICAL: This ensures we always pass a valid pageSize to TanStack Table configuration.
|
|
556
|
-
// An invalid pageSize can cause getPaginationRowModel() to return empty rows.
|
|
557
|
-
const effectivePageSize = useMemo(() => {
|
|
558
|
-
if (!secureFeatures.pagination || !finalPageSizeOptions.length) {
|
|
559
|
-
return state.pagination.pageSize;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// If current pageSize is invalid (not in options), use validated value immediately
|
|
563
|
-
// This is a safety net in case the useEffect hasn't run yet
|
|
564
|
-
if (!finalPageSizeOptions.includes(state.pagination.pageSize)) {
|
|
565
|
-
return validatedInitialPageSize;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
return state.pagination.pageSize;
|
|
569
|
-
}, [state.pagination.pageSize, validatedInitialPageSize, secureFeatures.pagination, finalPageSizeOptions]);
|
|
570
|
-
|
|
571
|
-
// CRITICAL FIX: Ensure pagination state always uses a valid pageSize and pageIndex
|
|
572
|
-
// An invalid pageSize (not in page size options) causes getPaginationRowModel() to return empty rows,
|
|
573
|
-
// which manifests as "DataTable shows record count but no rows" bug for large datasets.
|
|
574
|
-
// An out-of-bounds pageIndex (beyond available pages) also causes empty rows.
|
|
575
|
-
// This fixes the bug where DataTable shows record count but no rows for large datasets.
|
|
576
|
-
useEffect(() => {
|
|
577
|
-
if (secureFeatures.pagination && finalPageSizeOptions.length > 0) {
|
|
578
|
-
const needsFix = !finalPageSizeOptions.includes(state.pagination.pageSize);
|
|
579
|
-
|
|
580
|
-
// Also check if pageIndex is out of bounds for the current data
|
|
581
|
-
const currentPageSize = effectivePageSize || validatedInitialPageSize;
|
|
582
|
-
const totalPages = currentPageSize > 0 ? Math.ceil(finalDataCount / currentPageSize) : 0;
|
|
583
|
-
const pageIndexOutOfBounds = totalPages > 0 && state.pagination.pageIndex >= totalPages;
|
|
584
|
-
|
|
585
|
-
if (needsFix || pageIndexOutOfBounds) {
|
|
586
|
-
// PageSize is invalid OR pageIndex is out of bounds - correct both to prevent empty rows
|
|
587
|
-
stateActions.setPagination({
|
|
588
|
-
pageSize: validatedInitialPageSize,
|
|
589
|
-
pageIndex: 0, // Reset to first page when correcting pagination issues
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}, [
|
|
594
|
-
secureFeatures.pagination,
|
|
595
|
-
finalPageSizeOptions,
|
|
596
|
-
state.pagination.pageSize,
|
|
597
|
-
state.pagination.pageIndex,
|
|
598
|
-
validatedInitialPageSize,
|
|
599
|
-
stateActions,
|
|
600
|
-
effectivePageSize,
|
|
601
|
-
finalDataCount
|
|
602
|
-
]);
|
|
603
|
-
|
|
604
|
-
// React 19 fix: Use useMemo to ensure isLoading updates when props change
|
|
605
|
-
// This prevents the component from getting stuck in loading state when externalIsLoading
|
|
606
|
-
// changes from true to false in React 19 with automatic memoization
|
|
607
|
-
const isLoading = useMemo(
|
|
608
|
-
() => externalIsLoading || performanceLoading,
|
|
609
|
-
[externalIsLoading, performanceLoading]
|
|
610
|
-
);
|
|
611
|
-
|
|
612
|
-
// ============================================================================
|
|
613
|
-
// DATA PROCESSING - ALWAYS call these hooks
|
|
614
|
-
// ============================================================================
|
|
615
|
-
|
|
616
|
-
// ============================================================================
|
|
617
|
-
// ACTIONS PROCESSING - ALWAYS call these hooks
|
|
618
|
-
// ============================================================================
|
|
619
|
-
|
|
620
|
-
// ============================================================================
|
|
621
|
-
// COLUMN PROCESSING - ALWAYS call these hooks
|
|
622
|
-
// ============================================================================
|
|
623
|
-
|
|
624
|
-
// ============================================================================
|
|
625
|
-
// TABLE CONFIGURATION - ALWAYS call these hooks
|
|
626
|
-
// ============================================================================
|
|
627
|
-
|
|
628
|
-
// ============================================================================
|
|
629
|
-
// SEARCH HANDLERS - ALWAYS call these hooks
|
|
630
|
-
// ============================================================================
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Handle search input changes.
|
|
634
|
-
*
|
|
635
|
-
* When a search query is entered, we reset to the first page to show results
|
|
636
|
-
* from the beginning. This provides a better user experience when searching
|
|
637
|
-
* large datasets.
|
|
638
|
-
*
|
|
639
|
-
* CRITICAL: Must sync both state.searchQuery (used by state management) and
|
|
640
|
-
* performance hook's searchQuery (used by table filtering and search index).
|
|
641
|
-
*
|
|
642
|
-
* @param value - The search query string
|
|
643
|
-
*/
|
|
644
|
-
const handleSearch = useCallback((value: string) => {
|
|
645
|
-
// Update both search query states to keep them in sync
|
|
646
|
-
stateActions.setSearchQuery(value);
|
|
647
|
-
setSearchQuery(value);
|
|
648
|
-
|
|
649
|
-
// Reset to first page when searching to show results from the beginning
|
|
650
|
-
if (secureFeatures.pagination) {
|
|
651
|
-
stateActions.setPagination({ ...state.pagination, pageIndex: 0 });
|
|
652
|
-
}
|
|
653
|
-
}, [stateActions, setSearchQuery, secureFeatures.pagination, state.pagination]);
|
|
654
|
-
|
|
655
|
-
// ============================================================================
|
|
656
|
-
// SERVER-SIDE DATA FETCHING - ALWAYS call these hooks
|
|
657
|
-
// ============================================================================
|
|
658
|
-
|
|
659
|
-
/**
|
|
660
|
-
* Handle server-side data fetching.
|
|
661
|
-
*
|
|
662
|
-
* This function is called when any state that affects server-side data changes:
|
|
663
|
-
* - pagination (page/size)
|
|
664
|
-
* - sorting (column/sort order)
|
|
665
|
-
* - filtering (column filters or global search)
|
|
666
|
-
* - grouping
|
|
667
|
-
*
|
|
668
|
-
* It collects all current table state and makes a single request to the server
|
|
669
|
-
* with those parameters, allowing for efficient server-side pagination, sorting,
|
|
670
|
-
* and filtering without loading all data client-side.
|
|
671
|
-
*
|
|
672
|
-
* Early return guards prevent unnecessary server calls when:
|
|
673
|
-
* - Component is in client-side mode (finalPaginationMode !== 'server')
|
|
674
|
-
* - No server-side config is provided (!serverSide)
|
|
675
|
-
*/
|
|
676
|
-
useServerSideDataEffect<TData>({
|
|
677
|
-
finalPaginationMode,
|
|
678
|
-
serverSide,
|
|
679
|
-
pagination: state.pagination,
|
|
680
|
-
sorting: state.sorting,
|
|
681
|
-
columnFilters: state.columnFilters,
|
|
682
|
-
grouping: state.grouping,
|
|
683
|
-
searchQuery,
|
|
684
|
-
tableDataLength: finalTableData.length,
|
|
685
|
-
fetchServerData,
|
|
686
|
-
cleanup,
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
// ============================================================================
|
|
690
|
-
// RBAC VALIDATION AND SECURE CONFIGURATION - ALWAYS call these hooks
|
|
691
|
-
// ============================================================================
|
|
692
|
-
|
|
693
|
-
// Wrap handlers - persistence is handled automatically via useDataTableState
|
|
694
|
-
// The state actions (clearCreationData, clearEditing) will automatically update persisted state
|
|
695
|
-
const wrappedOnCreateRow = onCreateRow;
|
|
696
|
-
const wrappedOnEditRow = onEditRow;
|
|
697
|
-
|
|
698
|
-
// MANDATORY: Handlers are automatically secured
|
|
699
|
-
const secureHandlers = useMemo(() => {
|
|
700
|
-
const handlers = {
|
|
701
|
-
onEditRow: permissions.canUpdate.can ? wrappedOnEditRow : undefined,
|
|
702
|
-
onDeleteRow: permissions.canDelete.can ? onDeleteRow : undefined,
|
|
703
|
-
onCreateRow: permissions.canCreate.can ? wrappedOnCreateRow : undefined,
|
|
704
|
-
onImport: permissions.canImport.can ? onImport : undefined,
|
|
705
|
-
onExport: permissions.canExport.can ? onExport : undefined,
|
|
706
|
-
onDeleteSelected: permissions.canDelete.can ? onDeleteSelected : undefined,
|
|
707
|
-
};
|
|
708
|
-
|
|
709
|
-
return handlers;
|
|
710
|
-
}, [permissions.canUpdate.can, permissions.canDelete.can, permissions.canCreate.can, permissions.canImport.can, permissions.canExport.can, wrappedOnEditRow, onDeleteRow, wrappedOnCreateRow, onImport, onExport, onDeleteSelected, secureFeatures.creation]);
|
|
711
|
-
|
|
712
|
-
// MANDATORY: Process actions with RBAC checks
|
|
713
|
-
const effectiveActions = useMemo(() => {
|
|
714
|
-
// Create a new array to avoid mutating the original
|
|
715
|
-
const result = [...actions];
|
|
716
|
-
|
|
717
|
-
// Add Edit action with RBAC check
|
|
718
|
-
if (secureFeatures.editing && secureHandlers.onEditRow && !result.some(a => a.label === 'Edit')) {
|
|
719
|
-
result.push({
|
|
720
|
-
label: 'Edit',
|
|
721
|
-
onClick: (row: TData) => {
|
|
722
|
-
if (!permissions.canUpdate.can) {
|
|
723
|
-
throw new Error('Insufficient permissions to edit this resource');
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
const rowIndex = data.findIndex(r => r === row);
|
|
727
|
-
const rowId = resolvedGetRowId(row, rowIndex >= 0 ? rowIndex : 0);
|
|
728
|
-
|
|
729
|
-
// Set the row into editing mode with the current row data
|
|
730
|
-
stateActions.setEditingRow(rowId, toCellValueRecord(row));
|
|
731
|
-
},
|
|
732
|
-
icon: Edit,
|
|
733
|
-
testId: 'edit',
|
|
734
|
-
hidden: !permissions.canUpdate.can,
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// Add Delete action with RBAC check
|
|
739
|
-
if (secureFeatures.deletion && secureHandlers.onDeleteRow && !result.some(a => a.label === 'Delete')) {
|
|
740
|
-
result.push({
|
|
741
|
-
label: 'Delete',
|
|
742
|
-
onClick: async (row: TData) => {
|
|
743
|
-
if (!permissions.canDelete.can) {
|
|
744
|
-
// NOTE: Toast notifications use default timeout (5 seconds) - do not set duration property
|
|
745
|
-
toast({
|
|
746
|
-
title: "Delete Failed",
|
|
747
|
-
description: "Insufficient permissions to delete this resource",
|
|
748
|
-
variant: "destructive"
|
|
749
|
-
});
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
// Get row ID for tracking - use current data, not effectiveData
|
|
754
|
-
const rowIndex = data.findIndex(r => r === row);
|
|
755
|
-
const rowId = resolvedGetRowId(row, rowIndex >= 0 ? rowIndex : 0);
|
|
756
|
-
|
|
757
|
-
// Mark deletion as in progress and track this deletion
|
|
758
|
-
// CRITICAL: Set isDeleting and snapshot BEFORE calling the handler
|
|
759
|
-
// This prevents the parent's data update from causing a flash
|
|
760
|
-
if (!isDeleting) {
|
|
761
|
-
// Snapshot current data BEFORE deletion
|
|
762
|
-
dataSnapshotRef.current = [...data]; // Create a copy to prevent reference issues
|
|
763
|
-
setIsDeleting(true);
|
|
764
|
-
}
|
|
765
|
-
pendingDeletionsRef.current.add(rowId);
|
|
766
|
-
|
|
767
|
-
// Clear any existing timeout
|
|
768
|
-
if (deletionTimeoutRef.current) {
|
|
769
|
-
clearTimeout(deletionTimeoutRef.current);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
try {
|
|
773
|
-
// Call the delete handler - this may update the parent's data prop
|
|
774
|
-
const deleteStartTime = Date.now();
|
|
775
|
-
const result = secureHandlers.onDeleteRow!(row) as any;
|
|
776
|
-
// Handle async operations
|
|
777
|
-
if (result !== undefined && result !== null && typeof result === 'object' && typeof result.then === 'function') {
|
|
778
|
-
await result;
|
|
779
|
-
}
|
|
780
|
-
// Remove from pending deletions
|
|
781
|
-
pendingDeletionsRef.current.delete(rowId);
|
|
782
|
-
|
|
783
|
-
// Reset deletion state after a delay to allow batching
|
|
784
|
-
// This prevents the table from refreshing after each individual deletion
|
|
785
|
-
deletionTimeoutRef.current = setTimeout(() => {
|
|
786
|
-
// Only reset if all deletions are complete
|
|
787
|
-
if (pendingDeletionsRef.current.size === 0) {
|
|
788
|
-
setIsDeleting(false);
|
|
789
|
-
// Update snapshot to latest data
|
|
790
|
-
dataSnapshotRef.current = data;
|
|
791
|
-
toast({
|
|
792
|
-
title: "Delete Successful",
|
|
793
|
-
description: "Row deleted successfully",
|
|
794
|
-
variant: "default"
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
}, 150); // Delay to batch rapid deletions
|
|
798
|
-
|
|
799
|
-
} catch (error) {
|
|
800
|
-
logger.error('Delete error:', error);
|
|
801
|
-
pendingDeletionsRef.current.delete(rowId);
|
|
802
|
-
if (pendingDeletionsRef.current.size === 0) {
|
|
803
|
-
setIsDeleting(false);
|
|
804
|
-
dataSnapshotRef.current = data;
|
|
805
|
-
}
|
|
806
|
-
toast({
|
|
807
|
-
title: "Delete Failed",
|
|
808
|
-
description: error instanceof Error ? error.message : 'Failed to delete row',
|
|
809
|
-
variant: "destructive"
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
},
|
|
813
|
-
icon: Trash,
|
|
814
|
-
testId: 'delete',
|
|
815
|
-
variant: 'destructive' as const,
|
|
816
|
-
hidden: !permissions.canDelete.can,
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
return result;
|
|
821
|
-
}, [actions, secureFeatures, permissions, secureHandlers, resolvedGetRowId, stateActions, effectiveData, isDeleting, pendingDeletionsRef, deletionTimeoutRef, dataSnapshotRef]);
|
|
822
|
-
|
|
823
|
-
// Normalize columnOrder for useTableColumns: ensure 'select' is always first
|
|
824
|
-
const normalizedColumnOrderForColumns = useMemo(() => {
|
|
825
|
-
if (secureFeatures.selection && state.columnOrder.includes('select')) {
|
|
826
|
-
return ['select', ...state.columnOrder.filter(id => id !== 'select')];
|
|
827
|
-
}
|
|
828
|
-
return state.columnOrder;
|
|
829
|
-
}, [state.columnOrder, secureFeatures.selection]);
|
|
830
|
-
|
|
831
|
-
// MANDATORY: Process columns with actions
|
|
832
|
-
const { enhancedColumns } = useTableColumns({
|
|
833
|
-
columns,
|
|
834
|
-
features: secureFeatures,
|
|
835
|
-
effectiveActions,
|
|
836
|
-
columnOrder: normalizedColumnOrderForColumns
|
|
837
|
-
});
|
|
838
|
-
|
|
839
|
-
// Use effective pageSize in pagination state snapshot to ensure table receives valid pageSize
|
|
840
|
-
const paginationStateWithValidatedSize = useMemo(() => ({
|
|
841
|
-
...state.pagination,
|
|
842
|
-
pageSize: effectivePageSize,
|
|
843
|
-
}), [state.pagination, effectivePageSize]);
|
|
844
|
-
|
|
845
|
-
const tableStateSnapshot = useMemo<TableStateSnapshot<TData>>(() => {
|
|
846
|
-
// Normalize columnOrder in snapshot: ensure 'select' is always first if selection is enabled
|
|
847
|
-
const normalizedColumnOrder = secureFeatures.selection && state.columnOrder.includes('select')
|
|
848
|
-
? ['select', ...state.columnOrder.filter(id => id !== 'select')]
|
|
849
|
-
: state.columnOrder;
|
|
850
|
-
|
|
851
|
-
return {
|
|
852
|
-
sorting: state.sorting,
|
|
853
|
-
columnFilters: state.columnFilters,
|
|
854
|
-
columnVisibility: state.columnVisibility,
|
|
855
|
-
rowSelection,
|
|
856
|
-
grouping: state.grouping,
|
|
857
|
-
expanded: state.expanded,
|
|
858
|
-
pagination: paginationStateWithValidatedSize,
|
|
859
|
-
globalFilter: searchQuery,
|
|
860
|
-
columnOrder: normalizedColumnOrder,
|
|
861
|
-
};
|
|
862
|
-
}, [
|
|
863
|
-
state.sorting,
|
|
864
|
-
state.columnFilters,
|
|
865
|
-
state.columnVisibility,
|
|
866
|
-
rowSelection,
|
|
867
|
-
state.grouping,
|
|
868
|
-
state.expanded,
|
|
869
|
-
paginationStateWithValidatedSize,
|
|
870
|
-
searchQuery,
|
|
871
|
-
state.columnOrder,
|
|
872
|
-
secureFeatures.selection,
|
|
873
|
-
]);
|
|
874
|
-
|
|
875
|
-
const tableHandlers = useTableHandlers({
|
|
876
|
-
state,
|
|
877
|
-
stateSnapshot: tableStateSnapshot,
|
|
878
|
-
actions: stateActions,
|
|
879
292
|
selection,
|
|
880
293
|
onRowSelectionChange,
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
updateSavedColumnVisibility,
|
|
885
|
-
updateColumnOrder,
|
|
294
|
+
shouldAllowRenderAfterTimeout,
|
|
295
|
+
rbac,
|
|
296
|
+
enhancedPagination,
|
|
886
297
|
onLayoutChange,
|
|
887
298
|
});
|
|
888
299
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
return [] as TData[];
|
|
900
|
-
}
|
|
901
|
-
// Permissions confirmed - return actual data
|
|
902
|
-
return finalTableData as TData[];
|
|
903
|
-
}, [finalTableData, permissions.canRead.isLoading, permissions.canRead.can, shouldAllowRenderAfterTimeout]);
|
|
904
|
-
|
|
905
|
-
const tableConfig = useDataTableConfiguration({
|
|
906
|
-
data: safeTableData,
|
|
907
|
-
columns: enhancedColumns,
|
|
908
|
-
stateSnapshot: tableStateSnapshot,
|
|
909
|
-
handlers: tableHandlers,
|
|
910
|
-
features: secureFeatures,
|
|
911
|
-
getRowId: resolvedGetRowId,
|
|
912
|
-
finalPaginationMode,
|
|
913
|
-
finalDataCount: safeTableData.length > 0 ? finalDataCount : 0,
|
|
914
|
-
pageSize: effectivePageSize,
|
|
915
|
-
hasServerSideConfig: !!serverSide,
|
|
300
|
+
const renderGuard = useDataTableRenderGuard<TData>({
|
|
301
|
+
...pipeline.guardInputs,
|
|
302
|
+
user,
|
|
303
|
+
permissions,
|
|
304
|
+
isPermissionLoading,
|
|
305
|
+
permissionElapsed,
|
|
306
|
+
shouldAllowRenderAfterTimeout,
|
|
307
|
+
logger,
|
|
308
|
+
LoadingComponent,
|
|
309
|
+
AccessDeniedPage,
|
|
916
310
|
});
|
|
917
|
-
|
|
918
311
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
// ============================================================================
|
|
922
|
-
// RBAC VALIDATION AND EARLY RETURNS - AFTER ALL HOOKS
|
|
923
|
-
// ============================================================================
|
|
924
|
-
|
|
925
|
-
// DIAGNOSTIC: Log render state for debugging
|
|
926
|
-
const renderDiagnostics = {
|
|
927
|
-
hasUser: !!user,
|
|
928
|
-
userId: user?.id,
|
|
929
|
-
permissionLoading: permissions.canRead.isLoading,
|
|
930
|
-
permissionCan: permissions.canRead.can,
|
|
931
|
-
permissionError: permissions.canRead.error,
|
|
932
|
-
effectivePageId,
|
|
933
|
-
externalIsLoading,
|
|
934
|
-
performanceLoading,
|
|
935
|
-
computedIsLoading: isLoading,
|
|
936
|
-
dataLength: data.length,
|
|
937
|
-
finalTableDataLength: finalTableData.length,
|
|
938
|
-
columnsLength: columns.length,
|
|
939
|
-
tableRowsCount: table?.getRowModel().rows.length || 0,
|
|
940
|
-
};
|
|
941
|
-
|
|
942
|
-
// Log diagnostics in development mode
|
|
943
|
-
if (process.env.NODE_ENV === 'development') {
|
|
944
|
-
logger.debug('DataTable render diagnostics:', renderDiagnostics);
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
// MANDATORY: Every DataTable must have a user
|
|
948
|
-
if (!user) {
|
|
949
|
-
logger.error('DataTable render blocked: No user', renderDiagnostics);
|
|
312
|
+
if (renderGuard.gate === 'throw') {
|
|
950
313
|
throw new Error('DataTable requires authenticated user for RBAC');
|
|
951
314
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
// After 3 seconds, allow table to render but keep data hidden until permissions confirm
|
|
955
|
-
// This provides better UX while maintaining security (data remains protected)
|
|
956
|
-
// Note: permissionElapsed and shouldAllowRenderAfterTimeout are calculated above for useMemo
|
|
957
|
-
// Wait for permission check to complete before making access decisions
|
|
958
|
-
// BUT: After 3s timeout, allow table structure to render (data will remain hidden)
|
|
959
|
-
if (isPermissionLoading) {
|
|
960
|
-
// Enhanced diagnostics for hanging permission checks
|
|
961
|
-
if (permissionElapsed > 10000) {
|
|
962
|
-
logger.error('DataTableCore', 'DataTable: Permission check hanging (>10s)', {
|
|
963
|
-
...renderDiagnostics,
|
|
964
|
-
permissionState: {
|
|
965
|
-
can: permissions.canRead.can,
|
|
966
|
-
isLoading: permissions.canRead.isLoading,
|
|
967
|
-
error: permissions.canRead.error?.message,
|
|
968
|
-
},
|
|
969
|
-
elapsedMs: permissionElapsed,
|
|
970
|
-
diagnostic: 'Permission check has been loading for over 10 seconds. This likely indicates a hanging database query or network issue. Check browser network tab for pending requests to Supabase.',
|
|
971
|
-
recommendation: 'Check: 1) Browser network tab for pending requests, 2) Supabase connection, 3) Database query performance, 4) Super admin check completion',
|
|
972
|
-
});
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
if (process.env.NODE_ENV === 'development') {
|
|
976
|
-
logger.debug('DataTable render blocked: Permissions loading', {
|
|
977
|
-
...renderDiagnostics,
|
|
978
|
-
permissionState: permissions.canRead,
|
|
979
|
-
elapsedMs: permissionElapsed,
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
return <LoadingComponent />;
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
// If timeout reached but permissions still loading, log warning and proceed with caution
|
|
986
|
-
if (permissions.canRead.isLoading && shouldAllowRenderAfterTimeout) {
|
|
987
|
-
logger.warn('DataTable: Rendering after timeout - permissions still loading. Data will remain hidden until confirmed.', {
|
|
988
|
-
pageId: effectivePageId,
|
|
989
|
-
elapsedMs: permissionElapsed,
|
|
990
|
-
permissionState: permissions.canRead,
|
|
991
|
-
});
|
|
992
|
-
// Continue to render check below - we'll show empty state until permissions confirm
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
// MANDATORY: No data access without read permission
|
|
996
|
-
// SECURITY: If permissions are still loading after timeout, allow table structure but hide data
|
|
997
|
-
// If permissions are confirmed as denied, show access denied page
|
|
998
|
-
if (!permissions.canRead.isLoading && !permissions.canRead.can) {
|
|
999
|
-
logger.warn('Access denied - no read permission:', {
|
|
1000
|
-
canRead: permissions.canRead,
|
|
1001
|
-
pageId: effectivePageId,
|
|
1002
|
-
isLoading: permissions.canRead.isLoading,
|
|
1003
|
-
diagnostics: renderDiagnostics,
|
|
1004
|
-
});
|
|
1005
|
-
return <AccessDeniedPage resource={effectivePageId || 'unknown-page'} operation="read" />;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// If permissions still loading after timeout, proceed to render but data will be empty/hidden
|
|
1009
|
-
// The table structure will render, but rows will be empty until permissions confirm
|
|
1010
|
-
if (permissions.canRead.isLoading && shouldAllowRenderAfterTimeout) {
|
|
1011
|
-
// Log that we're proceeding with timeout
|
|
1012
|
-
logger.debug('DataTable: Proceeding to render after timeout - permissions still loading', {
|
|
1013
|
-
pageId: effectivePageId,
|
|
1014
|
-
elapsedMs: permissionElapsed,
|
|
1015
|
-
});
|
|
1016
|
-
// Continue to render - data will be empty until permissions confirm
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
// ============================================================================
|
|
1020
|
-
// RENDER
|
|
1021
|
-
// ============================================================================
|
|
1022
|
-
|
|
1023
|
-
if (isLoading) {
|
|
1024
|
-
if (process.env.NODE_ENV === 'development') {
|
|
1025
|
-
logger.debug('DataTable render blocked: External isLoading', {
|
|
1026
|
-
...renderDiagnostics,
|
|
1027
|
-
isLoadingSource: {
|
|
1028
|
-
externalIsLoading,
|
|
1029
|
-
performanceLoading,
|
|
1030
|
-
computed: isLoading,
|
|
1031
|
-
},
|
|
1032
|
-
});
|
|
1033
|
-
}
|
|
1034
|
-
return <LoadingComponent />;
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
// DIAGNOSTIC: Log successful render path
|
|
1038
|
-
if (process.env.NODE_ENV === 'development') {
|
|
1039
|
-
logger.debug('DataTable proceeding to render:', {
|
|
1040
|
-
...renderDiagnostics,
|
|
1041
|
-
willRender: true,
|
|
1042
|
-
tableState: {
|
|
1043
|
-
rowCount: table?.getRowModel().rows.length || 0,
|
|
1044
|
-
columnCount: table?.getVisibleFlatColumns().length || 0,
|
|
1045
|
-
paginationMode: finalPaginationMode,
|
|
1046
|
-
},
|
|
1047
|
-
});
|
|
315
|
+
if (renderGuard.component) {
|
|
316
|
+
return renderGuard.component;
|
|
1048
317
|
}
|
|
1049
318
|
|
|
1050
319
|
return (
|
|
1051
320
|
<DataTableLayout
|
|
1052
|
-
|
|
1053
|
-
title={title}
|
|
1054
|
-
description={description}
|
|
1055
|
-
variant={variant}
|
|
1056
|
-
className={className}
|
|
1057
|
-
columns={columns}
|
|
1058
|
-
secureFeatures={secureFeatures}
|
|
1059
|
-
enhancedPagination={enhancedPagination}
|
|
1060
|
-
searchQuery={searchQuery}
|
|
1061
|
-
onSearch={handleSearch}
|
|
1062
|
-
state={state}
|
|
1063
|
-
stateActions={stateActions}
|
|
1064
|
-
rowSelection={rowSelection}
|
|
1065
|
-
onCreateRow={secureHandlers.onCreateRow}
|
|
1066
|
-
onEditRow={secureHandlers.onEditRow}
|
|
1067
|
-
onImport={secureHandlers.onImport}
|
|
1068
|
-
onExport={secureHandlers.onExport}
|
|
1069
|
-
onDeleteSelected={secureHandlers.onDeleteSelected}
|
|
1070
|
-
rbac={rbac}
|
|
1071
|
-
permissions={permissions}
|
|
1072
|
-
effectiveActions={effectiveActions}
|
|
1073
|
-
finalPageSizeOptions={finalPageSizeOptions}
|
|
1074
|
-
finalPaginationMode={finalPaginationMode}
|
|
1075
|
-
finalDataCount={finalDataCount}
|
|
1076
|
-
isLoading={isLoading}
|
|
1077
|
-
finalTableData={finalTableData}
|
|
1078
|
-
aggregates={aggregates}
|
|
1079
|
-
resolvedGetRowId={resolvedGetRowId}
|
|
1080
|
-
data={data}
|
|
1081
|
-
emptyState={emptyState}
|
|
1082
|
-
virtualHeight={virtualHeight}
|
|
1083
|
-
hierarchical={hierarchical}
|
|
1084
|
-
hierarchicalState={hierarchicalState}
|
|
1085
|
-
logger={logger}
|
|
1086
|
-
secureHandlers={secureHandlers}
|
|
1087
|
-
importModalConfig={importModalConfig}
|
|
1088
|
-
keyboardNavigation={keyboardNavigation}
|
|
1089
|
-
lastFocusedElementRef={lastFocusedElementRef}
|
|
321
|
+
{...(pipeline.layoutProps as unknown as React.ComponentProps<typeof DataTableLayout>)}
|
|
1090
322
|
/>
|
|
1091
323
|
);
|
|
1092
324
|
}
|