@jmruthers/pace-core 0.6.8 → 0.6.10
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 +3 -0
- package/audit-tool/audits/02-project-structure.cjs +97 -32
- package/audit-tool/audits/03-architecture.cjs +145 -19
- package/audit-tool/audits/04-code-quality.cjs +86 -1
- package/audit-tool/audits/06-security-rbac.cjs +109 -11
- package/cursor-rules/02-project-structure.mdc +2 -26
- package/cursor-rules/05-styling.mdc +84 -6
- package/cursor-rules/06-security-rbac.mdc +124 -1
- package/dist/{DataTable-6RMSCQJ6.js → DataTable-SAXFG4XI.js} +11 -13
- package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
- package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
- package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
- 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-Z6ZZBWLU.js +3 -0
- package/dist/chunk-3GWSPISD.js +61 -0
- package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
- package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
- package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
- package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
- package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
- package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
- package/dist/chunk-FN52B75D.js +246 -0
- package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
- package/dist/chunk-KPYQWGFQ.js +183 -0
- package/dist/{chunk-IUBRCBSY.js → chunk-KSNLMI7N.js} +14 -8
- package/dist/chunk-KYURMOQM.js +977 -0
- package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
- package/dist/{chunk-NKHKXPI4.js → chunk-MPY44PWB.js} +683 -627
- package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
- package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
- package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
- package/dist/{chunk-EURB7QFZ.js → chunk-TFIPNIPE.js} +867 -534
- package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
- package/dist/chunk-W46INAVW.js +1216 -0
- package/dist/chunk-X5EAU5G7.js +793 -0
- package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
- package/dist/components.d.ts +8 -86
- package/dist/components.js +21 -55
- package/dist/{database.generated-CcnC_DRc.d.ts → database.generated-DT8JTZiP.d.ts} +12 -12
- package/dist/eslint-rules/rules/05-styling.cjs +507 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
- package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
- package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
- package/dist/hooks.d.ts +12 -11
- package/dist/hooks.js +69 -44
- package/dist/index.d.ts +380 -32
- package/dist/index.js +46 -32
- package/dist/papaparseLoader-WG2UXQ22.js +7 -0
- package/dist/providers.d.ts +28 -14
- package/dist/providers.js +5 -5
- package/dist/rbac/eslint-rules.js +2 -2
- package/dist/rbac/index.d.ts +58 -214
- package/dist/rbac/index.js +11 -11
- package/dist/theming/runtime.d.ts +9 -3
- package/dist/theming/runtime.js +2 -2
- package/dist/{timezone-BZe_eUxx.d.ts → timezone-K-ptz3HO.d.ts} +22 -23
- package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
- package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
- package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
- package/dist/types-Dr8sNhER.d.ts +50 -0
- package/dist/types.d.ts +5 -5
- package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
- package/dist/{usePublicRouteParams-MamNgwqe.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +8 -7
- package/dist/utils.d.ts +301 -137
- package/dist/utils.js +42 -41
- package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
- package/docs/api/modules.md +542 -549
- package/docs/api-reference/components.md +5 -5
- package/docs/api-reference/rpc-functions.md +3 -3
- package/docs/implementation-guides/data-tables.md +256 -8
- package/docs/rbac/RBAC_CONTRACT.md +0 -12
- package/docs/standards/2-project-structure-standards.md +12 -74
- package/docs/standards/6-security-rbac-standards.md +222 -7
- package/docs/standards/7-api-tech-stack-standards.md +91 -3
- package/docs/testing/README.md +10 -0
- package/docs/testing/test-setup-for-consumers.md +914 -0
- package/eslint-config-pace-core.cjs +4 -0
- package/package.json +1 -1
- package/scripts/eslint-audit.cjs +110 -11
- package/src/__mocks__/lucide-react.ts +0 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
- package/src/__tests__/index.test.ts +532 -0
- package/src/__tests__/integration/UserProfile.test.tsx +1 -1
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
- package/src/__tests__/rls-policies.test.ts +3 -2
- 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.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 +378 -3
- package/src/components/AddressField/AddressField.tsx +2 -2
- 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/Calendar/Calendar.test.tsx +523 -131
- package/src/components/Calendar/Calendar.tsx +107 -488
- package/src/components/Card/Card.test.tsx +220 -249
- package/src/components/Checkbox/Checkbox.test.tsx +58 -174
- package/src/components/ContextSelector/ContextSelector.tsx +3 -3
- package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
- package/src/components/DataTable/DataTable.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +485 -0
- package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
- package/src/components/DataTable/__tests__/README.md +1 -1
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
- package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
- package/src/components/DataTable/components/ActionButtons.tsx +9 -4
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
- package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
- package/src/components/DataTable/components/DataTableCore.tsx +44 -52
- package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
- package/src/components/DataTable/components/DataTableModals.tsx +118 -30
- package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
- package/src/components/DataTable/components/EditFields.tsx +6 -47
- package/src/components/DataTable/components/EditableRow.tsx +8 -8
- package/src/components/DataTable/components/EmptyState.tsx +6 -3
- package/src/components/DataTable/components/FilterRow.tsx +18 -11
- package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
- package/src/components/DataTable/components/ImportModal.tsx +305 -133
- package/src/components/DataTable/components/LoadingState.tsx +2 -2
- package/src/components/DataTable/components/PaginationControls.tsx +0 -4
- package/src/components/DataTable/components/RowComponent.tsx +42 -22
- package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
- package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
- package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
- package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
- package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
- package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
- package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
- package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
- package/src/components/DataTable/context/DataTableContext.tsx +9 -10
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
- package/src/components/DataTable/core/ColumnFactory.ts +3 -3
- package/src/components/DataTable/core/ColumnManager.ts +0 -1
- package/src/components/DataTable/core/DataManager.ts +4 -2
- package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
- package/src/components/DataTable/core/PluginRegistry.ts +2 -2
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
- package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
- package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +298 -23
- package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
- package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
- package/src/components/DataTable/hooks/useTableColumns.ts +36 -38
- package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
- package/src/components/DataTable/index.ts +24 -2
- package/src/components/DataTable/types.ts +6 -3
- package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
- package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
- package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
- package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
- package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +208 -0
- package/src/components/DataTable/utils/a11yUtils.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
- package/src/components/DataTable/utils/errorHandling.ts +3 -1
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +2 -2
- package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/DataTable/utils/performanceUtils.ts +1 -1
- package/src/components/DataTable/utils/selectFieldUtils.ts +127 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
- package/src/components/DateTimeField/DateTimeField.tsx +1 -1
- package/src/components/Dialog/Dialog.test.tsx +2007 -407
- package/src/components/Dialog/Dialog.tsx +97 -192
- 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 +454 -222
- package/src/components/FileDisplay/FileDisplay.tsx +14 -12
- package/src/components/FileDisplay/index.tsx +1 -1
- package/src/components/FileUpload/FileUpload.test.tsx +54 -18
- package/src/components/FileUpload/FileUpload.tsx +10 -7
- package/src/components/FileUpload/index.tsx +1 -1
- package/src/components/Footer/Footer.test.tsx +33 -114
- package/src/components/Form/Form.test.tsx +388 -68
- package/src/components/Form/Form.tsx +57 -42
- package/src/components/Header/Header.test.tsx +645 -154
- package/src/components/Header/Header.tsx +52 -43
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
- package/src/components/Input/Input.test.tsx +34 -120
- package/src/components/Label/Label.test.tsx +47 -46
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
- package/src/components/LoginForm/LoginForm.test.tsx +0 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
- package/src/components/PaceAppLayout/README.md +0 -9
- package/src/components/PaceAppLayout/test-setup.tsx +15 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
- package/src/components/Progress/Progress.test.tsx +127 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
- package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
- package/src/components/PublicLayout/PublicPageContext.ts +28 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
- package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
- package/src/components/Select/Select.test.tsx +46 -9
- package/src/components/Select/Select.tsx +31 -24
- package/src/components/Select/__tests__/context.test.tsx +56 -0
- package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
- package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
- package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
- package/src/components/Select/hooks/useSelectState.ts +16 -16
- package/src/components/Select/types.ts +3 -0
- package/src/components/Select/utils/__tests__/text.test.tsx +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 +47 -317
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Textarea/Textarea.test.tsx +11 -38
- package/src/components/Toast/Toast.test.tsx +78 -569
- package/src/components/Tooltip/Tooltip.test.tsx +4 -21
- package/src/components/UserMenu/UserMenu.test.tsx +1 -21
- package/src/components/UserMenu/UserMenu.tsx +3 -6
- package/src/components/__tests__/index.test.ts +346 -0
- package/src/components/index.ts +12 -1
- package/src/constants/__tests__/performance.test.ts +91 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
- package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
- package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
- package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
- package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
- package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
- package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
- package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
- package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
- package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
- package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
- package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
- package/src/hooks/__tests__/useToast.test.ts +413 -0
- package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
- package/src/hooks/index.ts +13 -1
- 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/usePublicFileDisplay.test.ts +723 -0
- package/src/hooks/public/usePublicFileDisplay.ts +79 -49
- package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
- package/src/hooks/public/usePublicRouteParams.ts +2 -2
- 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 +165 -42
- package/src/hooks/useAddressAutocomplete.ts +41 -28
- package/src/hooks/useAppConfig.ts +13 -3
- package/src/hooks/useDataTablePerformance.ts +13 -12
- package/src/hooks/useDataTableState.ts +5 -5
- package/src/hooks/useEventTheme.test.ts +66 -17
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +8 -1
- package/src/hooks/useFileDisplay.ts +66 -33
- package/src/hooks/useFileReference.test.ts +365 -87
- package/src/hooks/useFileReference.ts +2 -6
- package/src/hooks/useFileUrlCache.ts +4 -1
- package/src/hooks/useFormDialog.ts +2 -2
- package/src/hooks/useInactivityTracker.ts +3 -3
- package/src/hooks/useOrganisationPermissions.test.ts +1 -2
- package/src/hooks/useOrganisationPermissions.ts +1 -4
- package/src/hooks/useOrganisationSecurity.test.ts +1 -30
- package/src/hooks/useOrganisationSecurity.ts +3 -3
- package/src/hooks/useOrganisations.ts +1 -1
- package/src/hooks/usePerformanceMonitor.ts +1 -1
- package/src/hooks/usePermissionCache.ts +2 -6
- package/src/hooks/useQueryCache.ts +7 -7
- package/src/hooks/useSessionDraft.ts +14 -11
- package/src/hooks/useSessionRestoration.ts +1 -1
- package/src/hooks/useStorage.ts +75 -40
- package/src/hooks/useToast.ts +2 -2
- package/src/hooks/useZodForm.ts +3 -3
- package/src/icons/__tests__/index.test.ts +133 -0
- package/src/icons/index.ts +1 -1
- package/src/index.ts +43 -4
- package/src/providers/OrganisationProvider.test.tsx +40 -0
- package/src/providers/OrganisationProvider.tsx +5 -5
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
- package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
- package/src/providers/__tests__/EventProvider.test.tsx +16 -80
- package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
- package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
- package/src/providers/__tests__/index.test.ts +138 -0
- package/src/providers/services/AuthServiceContext.ts +27 -0
- package/src/providers/services/AuthServiceProvider.tsx +81 -20
- package/src/providers/services/EventServiceContext.ts +25 -0
- package/src/providers/services/EventServiceProvider.tsx +11 -20
- package/src/providers/services/InactivityServiceContext.ts +25 -0
- package/src/providers/services/InactivityServiceProvider.tsx +7 -17
- package/src/providers/services/OrganisationServiceContext.ts +25 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
- package/src/providers/services/UnifiedAuthContext.ts +99 -0
- package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
- package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
- package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
- package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
- package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
- package/src/providers/services/__tests__/contexts.test.tsx +281 -0
- package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
- package/src/providers/services/useUnifiedAuth.ts +29 -0
- package/src/rbac/README.md +5 -5
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
- package/src/rbac/__tests__/audit-batched.test.ts +550 -0
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
- package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
- package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
- package/src/rbac/__tests__/index.test.ts +107 -0
- package/src/rbac/__tests__/performance.test.ts +451 -0
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
- package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
- package/src/rbac/adapters.test.tsx +654 -0
- package/src/rbac/adapters.tsx +24 -9
- package/src/rbac/api.test.ts +13 -217
- package/src/rbac/api.ts +85 -16
- package/src/rbac/audit-batched.ts +5 -4
- package/src/rbac/audit.test.ts +225 -28
- package/src/rbac/audit.ts +22 -17
- 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.tsx +20 -18
- package/src/rbac/components/NavigationGuard.tsx +10 -8
- package/src/rbac/components/PagePermissionGuard.tsx +27 -25
- package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
- package/src/rbac/config.test.ts +131 -48
- package/src/rbac/config.ts +11 -8
- package/src/rbac/docs/event-based-apps.md +26 -13
- package/src/rbac/engine.test.ts +496 -146
- package/src/rbac/engine.ts +53 -13
- package/src/rbac/errors.test.ts +99 -87
- package/src/rbac/eslint-rules.js +2 -2
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
- package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
- package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
- package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
- package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
- package/src/rbac/hooks/permissions/useCan.ts +12 -10
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
- package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
- package/src/rbac/hooks/useCan.test.ts +319 -3
- package/src/rbac/hooks/usePermissions.test.ts +426 -0
- package/src/rbac/hooks/usePermissions.ts +5 -7
- package/src/rbac/hooks/useRBAC.test.ts +1669 -2
- package/src/rbac/hooks/useRBAC.ts +7 -11
- package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
- package/src/rbac/hooks/useResolvedScope.ts +4 -1
- package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
- package/src/rbac/hooks/useResourcePermissions.ts +9 -7
- package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
- package/src/rbac/hooks/useRoleManagement.ts +16 -12
- package/src/rbac/hooks/useSecureSupabase.ts +11 -12
- package/src/rbac/index.ts +32 -32
- package/src/rbac/permissions.test.ts +149 -68
- package/src/rbac/permissions.ts +0 -3
- package/src/rbac/request-deduplication.test.ts +347 -0
- package/src/rbac/secureClient.test.ts +112 -159
- package/src/rbac/secureClient.ts +46 -26
- package/src/rbac/security.test.ts +125 -44
- package/src/rbac/security.ts +7 -6
- package/src/rbac/types.test.ts +236 -0
- package/src/rbac/types.ts +7 -5
- package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
- package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
- package/src/rbac/utils/clientSecurity.ts +6 -4
- package/src/rbac/utils/contextValidator.ts +1 -2
- package/src/rbac/utils/eventContext.ts +2 -2
- package/src/services/AuthService.ts +13 -11
- package/src/services/EventService.ts +4 -5
- package/src/services/OrganisationService.ts +13 -30
- package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
- package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
- package/src/services/__tests__/AuthService.test.ts +4 -8
- package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
- package/src/services/__tests__/BaseService.test.ts +49 -0
- package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
- package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
- package/src/services/__tests__/EventService.test.ts +0 -7
- package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
- package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
- package/src/services/base/BaseService.test.ts +214 -0
- package/src/services/interfaces/IOrganisationService.ts +0 -1
- package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
- package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
- package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
- package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
- package/src/styles/core.css +1 -0
- package/src/theming/__tests__/runtime.test.ts +29 -94
- package/src/theming/parseEventColours.ts +18 -9
- package/src/theming/runtime.ts +1 -5
- package/src/types/__tests__/core.test.ts +397 -0
- package/src/types/__tests__/database-generated.test.ts +78 -0
- package/src/types/__tests__/file-reference.test.ts +270 -366
- package/src/types/__tests__/guards.test.ts +26 -26
- package/src/types/__tests__/index.test.ts +265 -0
- package/src/types/__tests__/type-validation.test.ts +3 -3
- package/src/types/__tests__/validation.test.ts +0 -2
- package/src/types/auth.ts +0 -1
- package/src/types/database.generated.ts +9 -9
- package/src/types/event.ts +1 -1
- package/src/types/rpc-responses.ts +33 -0
- package/src/types/supabase.ts +1 -2
- package/src/types/vitest-globals.d.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
- package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
- package/src/utils/__tests__/request-deduplication.test.ts +349 -0
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
- package/src/utils/__tests__/timezone.test.ts +1 -1
- package/src/utils/__tests__/validation.unit.test.ts +1 -2
- package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
- package/src/utils/app/appConfig.test.ts +235 -0
- package/src/utils/app/appIdResolver.test.ts +188 -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/audit/audit.test.ts +354 -39
- package/src/utils/context/organisationContext.test.ts +10 -4
- package/src/utils/context/organisationContext.ts +5 -5
- package/src/utils/context/sessionTracking.test.ts +354 -0
- package/src/utils/core/__tests__/cn.test.ts +66 -0
- package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
- package/src/utils/core/__tests__/logger.test.ts +217 -0
- package/src/utils/core/debugLogger.ts +15 -8
- package/src/utils/core/logger.ts +20 -16
- package/src/utils/device/deviceFingerprint.test.ts +8 -5
- package/src/utils/device/deviceFingerprint.ts +3 -3
- package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
- package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
- package/src/utils/dynamic/createLazyComponent.tsx +38 -0
- package/src/utils/dynamic/dynamicUtils.ts +6 -6
- package/src/utils/dynamic/lazyLoad.tsx +8 -36
- package/src/utils/dynamic/papaparseLoader.ts +7 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
- package/src/utils/file-reference/index.ts +0 -1
- 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 +40 -84
- 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/google-places/googlePlacesUtils.test.ts +72 -3
- package/src/utils/google-places/googlePlacesUtils.ts +15 -2
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
- package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
- package/src/utils/index.ts +52 -11
- package/src/utils/location/location.test.ts +18 -115
- package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
- package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
- package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
- package/src/utils/performance/bundleAnalysis.ts +16 -22
- package/src/utils/performance/performanceBenchmark.ts +12 -4
- package/src/utils/performance/performanceBudgets.ts +9 -6
- package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
- package/src/utils/permissions/permissionUtils.test.ts +20 -42
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
- package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
- package/src/utils/request-deduplication.ts +6 -4
- package/src/utils/security/auth-utils.ts +7 -7
- package/src/utils/security/secureDataAccess.test.ts +22 -191
- 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 +204 -0
- package/src/utils/security/securityMonitor.test.ts +90 -0
- package/src/utils/security/securityMonitor.ts +1 -1
- package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
- package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
- package/src/utils/storage/helpers.test.ts +757 -430
- package/src/utils/storage/helpers.ts +1 -2
- package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
- package/src/utils/storage/types.ts +2 -2
- package/src/utils/supabase/createBaseClient.test.ts +201 -0
- package/src/utils/supabase/createBaseClient.ts +27 -8
- package/src/utils/timezone/timezone.test.ts +25 -43
- package/src/utils/validation/__tests__/common.test.ts +115 -0
- package/src/utils/validation/__tests__/csrf.test.ts +65 -0
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
- package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
- package/src/utils/validation/__tests__/schema.test.ts +127 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
- package/src/utils/validation/__tests__/user.test.ts +173 -0
- package/src/utils/validation/__tests__/validation.test.ts +197 -0
- package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
- package/src/utils/validation/htmlSanitization.ts +27 -31
- package/src/utils/validation/schema.ts +6 -3
- package/src/utils/validation/sqlInjectionProtection.ts +2 -2
- package/src/vite-env.d.ts +6 -0
- package/dist/DataTable-DRUIgtUH.d.ts +0 -166
- package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
- package/dist/audit-MYQXYZFU.js +0 -3
- package/dist/chunk-7ILTDCL2.js +0 -80
- package/dist/chunk-EF2UGZWY.js +0 -611
- package/dist/chunk-FEJLJNWA.js +0 -181
- package/dist/chunk-GS5672WG.js +0 -2003
- package/dist/chunk-S6ZQKDY6.js +0 -62
- package/dist/chunk-Z2FNRKF3.js +0 -994
- package/dist/useToast-AyaT-x7p.d.ts +0 -68
- package/src/components/DataTable/components/index.ts +0 -16
- package/src/components/DataTable/core/index.ts +0 -1
- package/src/components/DataTable/hooks/index.ts +0 -13
- package/src/components/DataTable/utils/index.ts +0 -9
- package/src/components/PublicLayout/index.ts +0 -32
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/public/index.ts +0 -36
- package/src/hooks/usePermissionCache.test.ts +0 -536
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
- 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/index.ts +0 -26
- 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__/eventContext.unit.test.ts +0 -490
- package/src/utils/app/appNameResolver.simple.test.ts +0 -212
- package/src/utils/google-places/index.ts +0 -26
- package/src/utils/location/index.ts +0 -16
- package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
- package/src/utils/timezone/index.ts +0 -17
- package/src/utils/validation/index.ts +0 -73
|
@@ -25,9 +25,26 @@ import React, { useEffect } from 'react';
|
|
|
25
25
|
import { ImportModal, type ImportModalConfig } from './ImportModal';
|
|
26
26
|
import { createLogger } from '../../../utils/core/logger';
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Normalizes a column name for comparison by:
|
|
30
|
+
* - Converting to lowercase
|
|
31
|
+
* - Replacing spaces with underscores
|
|
32
|
+
* - Removing special characters (keeping alphanumeric and underscores)
|
|
33
|
+
* - Collapsing multiple underscores/hyphens to single underscore
|
|
34
|
+
*/
|
|
35
|
+
function normalizeColumnName(name: string): string {
|
|
36
|
+
return name
|
|
37
|
+
.toLowerCase()
|
|
38
|
+
.replace(/\s+/g, '_') // Replace spaces with underscores
|
|
39
|
+
.replace(/[^a-z0-9_]/g, '_') // Replace special chars with underscores
|
|
40
|
+
.replace(/[_-]+/g, '_') // Collapse multiple underscores/hyphens
|
|
41
|
+
.trim();
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
/**
|
|
29
45
|
* Maps CSV column data to table column structure
|
|
30
46
|
* Handles reference fields (columns with editAccessorKey) and direct accessorKey columns
|
|
47
|
+
* Implements a comprehensive fallback chain for flexible column matching
|
|
31
48
|
*/
|
|
32
49
|
function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<string, unknown>>(
|
|
33
50
|
csvData: Array<Record<string, unknown>>,
|
|
@@ -36,69 +53,138 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
36
53
|
accessorKey?: string;
|
|
37
54
|
header?: string;
|
|
38
55
|
editAccessorKey?: string;
|
|
56
|
+
importAliases?: string[];
|
|
39
57
|
}>
|
|
40
58
|
): TData[] {
|
|
41
59
|
const logger = createLogger('mapCSVToTableColumns');
|
|
42
|
-
|
|
60
|
+
|
|
61
|
+
if (csvData.length === 0) {
|
|
62
|
+
logger.warn('No CSV data to map');
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Build comprehensive mapping from CSV headers to table field names
|
|
43
67
|
// Priority: editAccessorKey > accessorKey > id
|
|
68
|
+
// For each column, we create multiple mappings to support the fallback chain
|
|
44
69
|
const columnMap = new Map<string, string>();
|
|
45
70
|
|
|
46
71
|
columns.forEach(col => {
|
|
47
72
|
const fieldName = col.editAccessorKey || col.accessorKey || col.id;
|
|
48
73
|
const header = typeof col.header === 'string' ? col.header : '';
|
|
49
74
|
|
|
50
|
-
if (fieldName
|
|
75
|
+
if (!fieldName) {
|
|
76
|
+
logger.warn('Skipping column with missing fieldName:', col);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (header) {
|
|
81
|
+
// 1. Exact header match (case-sensitive)
|
|
82
|
+
columnMap.set(header, fieldName);
|
|
83
|
+
|
|
84
|
+
// 2. Exact header match (case-insensitive)
|
|
51
85
|
const headerLower = header.toLowerCase();
|
|
52
|
-
// Map header to field name (case-insensitive)
|
|
53
86
|
columnMap.set(headerLower, fieldName);
|
|
54
87
|
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
58
|
-
columnMap.set(
|
|
88
|
+
// 3. Normalized header match
|
|
89
|
+
const normalizedHeader = normalizeColumnName(header);
|
|
90
|
+
if (normalizedHeader !== headerLower) {
|
|
91
|
+
columnMap.set(normalizedHeader, fieldName);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 4. AccessorKey match (case-insensitive and normalized)
|
|
96
|
+
if (col.accessorKey) {
|
|
97
|
+
const accessorKeyLower = col.accessorKey.toLowerCase();
|
|
98
|
+
columnMap.set(accessorKeyLower, fieldName);
|
|
99
|
+
|
|
100
|
+
const normalizedAccessorKey = normalizeColumnName(col.accessorKey);
|
|
101
|
+
if (normalizedAccessorKey !== accessorKeyLower) {
|
|
102
|
+
columnMap.set(normalizedAccessorKey, fieldName);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 5. EditAccessorKey match (case-insensitive and normalized)
|
|
107
|
+
if (col.editAccessorKey) {
|
|
108
|
+
const editAccessorKeyLower = col.editAccessorKey.toLowerCase();
|
|
109
|
+
columnMap.set(editAccessorKeyLower, col.editAccessorKey);
|
|
110
|
+
|
|
111
|
+
const normalizedEditAccessorKey = normalizeColumnName(col.editAccessorKey);
|
|
112
|
+
if (normalizedEditAccessorKey !== editAccessorKeyLower) {
|
|
113
|
+
columnMap.set(normalizedEditAccessorKey, col.editAccessorKey);
|
|
59
114
|
}
|
|
60
115
|
|
|
61
116
|
// For reference fields with editAccessorKey, also map the ID column header
|
|
62
117
|
// This handles exports that include both "Type" and "Type (ID)" columns
|
|
63
|
-
if (
|
|
64
|
-
const editAccessorKey = col.editAccessorKey; // Store in const for proper type narrowing
|
|
118
|
+
if (header) {
|
|
65
119
|
const idColumnHeader = `${header} (ID)`;
|
|
66
|
-
columnMap.set(idColumnHeader.toLowerCase(), editAccessorKey);
|
|
67
|
-
|
|
68
|
-
|
|
120
|
+
columnMap.set(idColumnHeader.toLowerCase(), col.editAccessorKey);
|
|
121
|
+
const normalizedIdHeader = normalizeColumnName(idColumnHeader);
|
|
122
|
+
if (normalizedIdHeader !== idColumnHeader.toLowerCase()) {
|
|
123
|
+
columnMap.set(normalizedIdHeader, col.editAccessorKey);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 6. ImportAliases match (case-insensitive and normalized)
|
|
129
|
+
if (col.importAliases && Array.isArray(col.importAliases)) {
|
|
130
|
+
col.importAliases.forEach(alias => {
|
|
131
|
+
// Case-insensitive match
|
|
132
|
+
const aliasLower = alias.toLowerCase();
|
|
133
|
+
columnMap.set(aliasLower, fieldName);
|
|
134
|
+
|
|
135
|
+
// Normalized match
|
|
136
|
+
const normalizedAlias = normalizeColumnName(alias);
|
|
137
|
+
if (normalizedAlias !== aliasLower) {
|
|
138
|
+
columnMap.set(normalizedAlias, fieldName);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Also map id if different from header and accessorKey
|
|
144
|
+
if (col.id && col.id !== header && col.id !== col.accessorKey && col.id !== fieldName) {
|
|
145
|
+
const idLower = col.id.toLowerCase();
|
|
146
|
+
columnMap.set(idLower, fieldName);
|
|
147
|
+
|
|
148
|
+
const normalizedId = normalizeColumnName(col.id);
|
|
149
|
+
if (normalizedId !== idLower) {
|
|
150
|
+
columnMap.set(normalizedId, fieldName);
|
|
69
151
|
}
|
|
70
|
-
} else {
|
|
71
|
-
logger.warn('Skipping column with missing fieldName or header:', col);
|
|
72
152
|
}
|
|
73
153
|
});
|
|
74
154
|
|
|
75
|
-
|
|
76
|
-
logger.warn('No CSV data to map');
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Transform CSV data using the mapping
|
|
155
|
+
// Transform CSV data using the mapping with fallback chain
|
|
81
156
|
const mappedData = csvData.map((row, index) => {
|
|
82
157
|
const mappedRow: Record<string, unknown> = {};
|
|
83
158
|
|
|
84
|
-
// For each CSV column, find the corresponding table field
|
|
159
|
+
// For each CSV column, find the corresponding table field using fallback chain
|
|
85
160
|
Object.keys(row).forEach(csvHeader => {
|
|
86
|
-
|
|
161
|
+
let fieldName: string | undefined;
|
|
162
|
+
|
|
163
|
+
// Fallback chain - try each strategy in order
|
|
164
|
+
// 1. Exact case-sensitive match
|
|
165
|
+
fieldName = columnMap.get(csvHeader);
|
|
87
166
|
|
|
88
|
-
//
|
|
89
|
-
|
|
167
|
+
// 2. Exact case-insensitive match
|
|
168
|
+
if (!fieldName) {
|
|
169
|
+
fieldName = columnMap.get(csvHeader.toLowerCase());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 3. Normalized match
|
|
173
|
+
if (!fieldName) {
|
|
174
|
+
const normalizedCsvHeader = normalizeColumnName(csvHeader);
|
|
175
|
+
fieldName = columnMap.get(normalizedCsvHeader);
|
|
176
|
+
}
|
|
90
177
|
|
|
91
|
-
//
|
|
178
|
+
// 4. Flexible suffix matching (backward compatibility)
|
|
92
179
|
// If CSV header ends with " [space] ColumnHeader", match it
|
|
93
180
|
// This handles cases like "Meal Type" → "Type", "User Name" → "Name", etc.
|
|
94
|
-
// Also handles "Meal Type (ID)" → matches the column with header "Type (ID)"
|
|
95
181
|
if (!fieldName) {
|
|
182
|
+
const csvHeaderLower = csvHeader.toLowerCase();
|
|
96
183
|
for (const [mapKey, mapValue] of columnMap.entries()) {
|
|
97
|
-
// Check if CSV header ends with the mapped key (with a space before it, or exact match)
|
|
98
184
|
const keyWithSpace = ` ${mapKey}`;
|
|
99
185
|
if (csvHeaderLower === mapKey || csvHeaderLower.endsWith(keyWithSpace)) {
|
|
100
186
|
fieldName = mapValue;
|
|
101
|
-
break;
|
|
187
|
+
break;
|
|
102
188
|
}
|
|
103
189
|
}
|
|
104
190
|
}
|
|
@@ -106,8 +192,9 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
106
192
|
if (fieldName) {
|
|
107
193
|
mappedRow[fieldName] = row[csvHeader];
|
|
108
194
|
} else {
|
|
109
|
-
// If no mapping found, use the CSV header as-is (lowercase)
|
|
110
|
-
mappedRow[
|
|
195
|
+
// If no mapping found after all strategies, use the CSV header as-is (lowercase)
|
|
196
|
+
mappedRow[csvHeader.toLowerCase()] = row[csvHeader];
|
|
197
|
+
// Only warn on first row to avoid spam
|
|
111
198
|
if (index === 0) {
|
|
112
199
|
logger.warn(`No mapping found for "${csvHeader}", using as-is`);
|
|
113
200
|
}
|
|
@@ -140,6 +227,7 @@ export interface DataTableModalsProps<TData extends Record<string, unknown> = Re
|
|
|
140
227
|
accessorKey?: string;
|
|
141
228
|
header?: string;
|
|
142
229
|
editAccessorKey?: string;
|
|
230
|
+
importAliases?: string[];
|
|
143
231
|
}>;
|
|
144
232
|
|
|
145
233
|
// Focus management
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
import React from 'react';
|
|
56
56
|
import { Input } from '../../Input/Input';
|
|
57
57
|
import { Button } from '../../Button/Button';
|
|
58
|
-
import {
|
|
58
|
+
import { Plus, Upload, Download, Filter, Trash2 } from 'lucide-react';
|
|
59
59
|
import { GroupingDropdown } from './GroupingDropdown';
|
|
60
60
|
import { ColumnVisibilityDropdown } from './ColumnVisibilityDropdown';
|
|
61
61
|
import type { DataTableColumn, DataRecord, SimpleColumn, DataTableFeatureConfig, DataTableRBACConfig } from '../types';
|
|
@@ -151,7 +151,7 @@ interface DataTableToolbarProps<TData extends DataRecord = DataRecord> {
|
|
|
151
151
|
*/
|
|
152
152
|
export function DataTableToolbar<TData extends DataRecord>({
|
|
153
153
|
features,
|
|
154
|
-
rbac,
|
|
154
|
+
rbac: _rbac,
|
|
155
155
|
permissions,
|
|
156
156
|
globalFilter,
|
|
157
157
|
onGlobalFilterChange,
|
|
@@ -19,7 +19,7 @@ import type { CellValue, DataRecord, EditableColumnDef } from '../types';
|
|
|
19
19
|
*/
|
|
20
20
|
export function SelectEditField<TData extends DataRecord>({
|
|
21
21
|
columnDef,
|
|
22
|
-
accessorKey,
|
|
22
|
+
accessorKey: _accessorKey,
|
|
23
23
|
currentValue,
|
|
24
24
|
placeholder,
|
|
25
25
|
onChange,
|
|
@@ -72,27 +72,6 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
72
72
|
setSearchTerm(currentSearch);
|
|
73
73
|
|
|
74
74
|
if (currentSearch.trim()) {
|
|
75
|
-
const searchLower = currentSearch.toLowerCase().trim();
|
|
76
|
-
|
|
77
|
-
type FieldOption =
|
|
78
|
-
| { value: string | number; label: string }
|
|
79
|
-
| { type: 'group'; label: string; items: Array<{ value: string | number; label: string }> }
|
|
80
|
-
| { type: 'separator' };
|
|
81
|
-
|
|
82
|
-
const checkMatch = (opt: FieldOption): boolean => {
|
|
83
|
-
if ('value' in opt && !('type' in opt)) {
|
|
84
|
-
return opt.label.toLowerCase().includes(searchLower);
|
|
85
|
-
}
|
|
86
|
-
if ('type' in opt && opt.type === 'group') {
|
|
87
|
-
return (
|
|
88
|
-
(opt as { type: 'group'; label: string; items: Array<{ value: string | number; label: string }> }).items.some(
|
|
89
|
-
(item: { value: string | number; label: string }) => item.label.toLowerCase().includes(searchLower)
|
|
90
|
-
)
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
return false;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
75
|
const shouldShow = isCreatable && !!columnDef.onCreateNew;
|
|
97
76
|
|
|
98
77
|
setShowCreateOption(shouldShow);
|
|
@@ -107,27 +86,6 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
107
86
|
setSearchTerm(currentSearch);
|
|
108
87
|
|
|
109
88
|
if (currentSearch.trim()) {
|
|
110
|
-
const searchLower = currentSearch.toLowerCase().trim();
|
|
111
|
-
|
|
112
|
-
type FieldOption =
|
|
113
|
-
| { value: string | number; label: string }
|
|
114
|
-
| { type: 'group'; label: string; items: Array<{ value: string | number; label: string }> }
|
|
115
|
-
| { type: 'separator' };
|
|
116
|
-
|
|
117
|
-
const checkMatch = (opt: FieldOption): boolean => {
|
|
118
|
-
if ('value' in opt && !('type' in opt)) {
|
|
119
|
-
return opt.label.toLowerCase().includes(searchLower);
|
|
120
|
-
}
|
|
121
|
-
if ('type' in opt && opt.type === 'group') {
|
|
122
|
-
return (
|
|
123
|
-
(opt as { type: 'group'; label: string; items: Array<{ value: string | number; label: string }> }).items.some(
|
|
124
|
-
(item: { value: string | number; label: string }) => item.label.toLowerCase().includes(searchLower)
|
|
125
|
-
)
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
return false;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
89
|
const shouldShow = isCreatable && !!columnDef.onCreateNew;
|
|
132
90
|
setShowCreateOption(shouldShow);
|
|
133
91
|
} else {
|
|
@@ -142,7 +100,7 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
142
100
|
};
|
|
143
101
|
};
|
|
144
102
|
|
|
145
|
-
|
|
103
|
+
const cleanup: (() => void) | null = findAndAttachSearchInput();
|
|
146
104
|
|
|
147
105
|
if (!cleanup) {
|
|
148
106
|
let timeoutCleanup: (() => void) | null = null;
|
|
@@ -157,7 +115,7 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
157
115
|
}
|
|
158
116
|
|
|
159
117
|
return cleanup;
|
|
160
|
-
}, [isOpen, isSearchable, isCreatable, columnDef
|
|
118
|
+
}, [isOpen, isSearchable, isCreatable, columnDef]);
|
|
161
119
|
|
|
162
120
|
const handleCreateNew = React.useCallback(async () => {
|
|
163
121
|
if (!isCreatable || !columnDef.onCreateNew || !searchTerm.trim()) return;
|
|
@@ -170,7 +128,7 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
170
128
|
} catch (error) {
|
|
171
129
|
logger.error('Error creating new item:', error);
|
|
172
130
|
}
|
|
173
|
-
}, [isCreatable, columnDef
|
|
131
|
+
}, [isCreatable, columnDef, searchTerm, onChange, logger]);
|
|
174
132
|
|
|
175
133
|
return (
|
|
176
134
|
<Select
|
|
@@ -243,6 +201,7 @@ export function SelectEditField<TData extends DataRecord>({
|
|
|
243
201
|
/**
|
|
244
202
|
* Helper function to render the appropriate input type based on column configuration
|
|
245
203
|
*/
|
|
204
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
246
205
|
export const renderEditField = <TData extends DataRecord>(
|
|
247
206
|
column: Column<TData, unknown>,
|
|
248
207
|
value: CellValue,
|
|
@@ -270,7 +229,7 @@ export const renderEditField = <TData extends DataRecord>(
|
|
|
270
229
|
const handleValueChange = (newValue: CellValue) => {
|
|
271
230
|
// Store the new value - preserve original type if option values are numbers
|
|
272
231
|
// Check if any option has a numeric value to determine if we should convert
|
|
273
|
-
const hasNumericValues = columnDef.fieldOptions?.some((opt
|
|
232
|
+
const hasNumericValues = columnDef.fieldOptions?.some((opt) =>
|
|
274
233
|
'value' in opt && !('type' in opt) && typeof opt.value === 'number'
|
|
275
234
|
);
|
|
276
235
|
const finalValue = hasNumericValues && !isNaN(Number(newValue)) && newValue !== ''
|
|
@@ -32,7 +32,7 @@ interface EditableRowProps<TData extends DataRecord> {
|
|
|
32
32
|
// Component for select fields with searchable and creatable support
|
|
33
33
|
function SelectEditField<TData extends DataRecord>({
|
|
34
34
|
columnDef,
|
|
35
|
-
accessorKey,
|
|
35
|
+
accessorKey: _accessorKey,
|
|
36
36
|
currentValue,
|
|
37
37
|
placeholder,
|
|
38
38
|
onChange,
|
|
@@ -162,7 +162,7 @@ function SelectEditField<TData extends DataRecord>({
|
|
|
162
162
|
};
|
|
163
163
|
|
|
164
164
|
// Try to find immediately
|
|
165
|
-
|
|
165
|
+
const cleanup: (() => void) | null = findAndAttachSearchInput();
|
|
166
166
|
|
|
167
167
|
// If not found, try again after a short delay (SelectContent might render asynchronously)
|
|
168
168
|
if (!cleanup) {
|
|
@@ -178,7 +178,7 @@ function SelectEditField<TData extends DataRecord>({
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
return cleanup;
|
|
181
|
-
}, [isOpen, isSearchable, isCreatable, columnDef
|
|
181
|
+
}, [isOpen, isSearchable, isCreatable, columnDef]);
|
|
182
182
|
|
|
183
183
|
const handleCreateNew = React.useCallback(async () => {
|
|
184
184
|
if (!isCreatable || !columnDef.onCreateNew || !searchTerm.trim()) return;
|
|
@@ -191,7 +191,7 @@ function SelectEditField<TData extends DataRecord>({
|
|
|
191
191
|
} catch (error) {
|
|
192
192
|
logger.error('Error creating new item:', error);
|
|
193
193
|
}
|
|
194
|
-
}, [isCreatable, columnDef
|
|
194
|
+
}, [isCreatable, columnDef, searchTerm, onChange, logger]);
|
|
195
195
|
|
|
196
196
|
return (
|
|
197
197
|
<Select
|
|
@@ -351,12 +351,12 @@ export function EditableRow<TData extends DataRecord>({
|
|
|
351
351
|
onEditingDataChange,
|
|
352
352
|
onSave,
|
|
353
353
|
onCancel,
|
|
354
|
-
actions,
|
|
354
|
+
actions: _actions,
|
|
355
355
|
getRowId,
|
|
356
|
-
isParent = false,
|
|
357
|
-
hierarchical = false,
|
|
356
|
+
isParent: _isParent = false,
|
|
357
|
+
hierarchical: _hierarchical = false,
|
|
358
358
|
}: EditableRowProps<TData>) {
|
|
359
|
-
const
|
|
359
|
+
const _rowId = getRowId ? getRowId(row.original, row.index) : String(row.id);
|
|
360
360
|
const firstInputRef = React.useRef<HTMLInputElement>(null);
|
|
361
361
|
const hasAssignedRef = React.useRef(false);
|
|
362
362
|
|
|
@@ -28,7 +28,7 @@ interface EmptyStateProps {
|
|
|
28
28
|
export function EmptyState({
|
|
29
29
|
title,
|
|
30
30
|
description,
|
|
31
|
-
icon: Icon
|
|
31
|
+
icon: Icon,
|
|
32
32
|
action,
|
|
33
33
|
isFiltered = false,
|
|
34
34
|
onClearFilters
|
|
@@ -38,17 +38,20 @@ export function EmptyState({
|
|
|
38
38
|
? "Try adjusting your search or filter criteria"
|
|
39
39
|
: "Get started by adding your first entry";
|
|
40
40
|
|
|
41
|
+
// Use default icon only if no icon is provided
|
|
42
|
+
const DisplayIcon = Icon || Database;
|
|
43
|
+
|
|
41
44
|
return (
|
|
42
45
|
<Alert
|
|
43
46
|
role="status"
|
|
44
47
|
aria-live="polite"
|
|
45
48
|
className="grid place-items-center text-center max-w-lg mx-auto"
|
|
46
49
|
>
|
|
47
|
-
<
|
|
50
|
+
<DisplayIcon
|
|
48
51
|
role="img"
|
|
49
52
|
aria-hidden="true"
|
|
50
53
|
className="size-12 text-muted-foreground mb-4"
|
|
51
|
-
data-testid={
|
|
54
|
+
data-testid={DisplayIcon === Database ? 'lucide-database' : DisplayIcon === User ? 'lucide-user' : 'custom-icon'}
|
|
52
55
|
/>
|
|
53
56
|
<AlertTitle className="text-lg font-semibold mb-2">
|
|
54
57
|
{title || defaultTitle}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ColumnFilter } from './ColumnFilter';
|
|
3
|
-
import type { Header, Table } from '@tanstack/react-table';
|
|
3
|
+
import type { Column, Header, Table } from '@tanstack/react-table';
|
|
4
4
|
import { getColumnHeaderText } from '../utils/columnUtils';
|
|
5
|
-
import type {
|
|
6
|
-
import type { DataRecord } from '../types';
|
|
5
|
+
import type { DataRecord, DataTableColumn } from '../types';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Props for the FilterRow component.
|
|
10
9
|
* @template TData - The type of data records in the table
|
|
11
10
|
*/
|
|
12
|
-
interface FilterRowProps<TData> {
|
|
11
|
+
interface FilterRowProps<TData extends DataRecord> {
|
|
13
12
|
table: Table<TData>;
|
|
14
13
|
visibleColumns: Header<TData, unknown>[];
|
|
15
14
|
}
|
|
@@ -22,16 +21,14 @@ interface FilterRowProps<TData> {
|
|
|
22
21
|
* @param props - Filter row configuration
|
|
23
22
|
* @returns The rendered filter row
|
|
24
23
|
*/
|
|
25
|
-
export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData>) {
|
|
26
|
-
const { getState } = table;
|
|
27
|
-
const { columnFilters } = getState();
|
|
24
|
+
export function FilterRow<TData extends DataRecord>({ table, visibleColumns }: FilterRowProps<TData>) {
|
|
28
25
|
|
|
29
26
|
// Get unique values for select filters
|
|
30
27
|
const getColumnOptions = React.useCallback((columnId: string) => {
|
|
31
28
|
const column = table.getColumn(columnId);
|
|
32
29
|
if (!column) return [];
|
|
33
30
|
|
|
34
|
-
const columnDef = column.columnDef as
|
|
31
|
+
const columnDef = column.columnDef as DataTableColumn<TData>;
|
|
35
32
|
|
|
36
33
|
// Check for filterSelectOptions first (preferred for filters)
|
|
37
34
|
if (columnDef.filterSelectOptions && Array.isArray(columnDef.filterSelectOptions)) {
|
|
@@ -63,7 +60,7 @@ export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData
|
|
|
63
60
|
const column = table.getColumn(columnId);
|
|
64
61
|
if (!column) return 'text';
|
|
65
62
|
|
|
66
|
-
const columnDef = column.columnDef as
|
|
63
|
+
const columnDef = column.columnDef as DataTableColumn<TData>;
|
|
67
64
|
|
|
68
65
|
// PRIORITY 1: Check if column has explicit filter type configuration
|
|
69
66
|
// This MUST be checked first and must respect any explicit value, including 'text'
|
|
@@ -116,7 +113,17 @@ export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData
|
|
|
116
113
|
const column = header.column;
|
|
117
114
|
const canFilter = column.getCanFilter();
|
|
118
115
|
const filterType = getFilterType(column.id);
|
|
119
|
-
const
|
|
116
|
+
const rawOptions = filterType === 'select' ? getColumnOptions(column.id) : [];
|
|
117
|
+
|
|
118
|
+
// Filter and normalize options for ColumnFilter (only simple options, convert to string values)
|
|
119
|
+
const options: Array<{ value: string; label: string }> = rawOptions
|
|
120
|
+
.filter((opt): opt is { value: string | number; label: string } =>
|
|
121
|
+
'value' in opt && 'label' in opt && !('type' in opt)
|
|
122
|
+
)
|
|
123
|
+
.map(opt => ({
|
|
124
|
+
value: String(opt.value),
|
|
125
|
+
label: opt.label
|
|
126
|
+
}));
|
|
120
127
|
|
|
121
128
|
return (
|
|
122
129
|
<td
|
|
@@ -125,7 +132,7 @@ export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData
|
|
|
125
132
|
>
|
|
126
133
|
{canFilter ? (
|
|
127
134
|
<ColumnFilter
|
|
128
|
-
column={column}
|
|
135
|
+
column={column as unknown as Column<DataRecord, unknown>}
|
|
129
136
|
filterType={filterType}
|
|
130
137
|
options={options}
|
|
131
138
|
placeholder={`Filter ${getColumnHeaderText(column as unknown as Column<DataRecord, unknown>)}...`}
|