@jmruthers/pace-core 0.5.136 → 0.5.137
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/dist/{DataTable-CYOHOX3O.js → DataTable-6M4L6BI2.js} +10 -9
- package/dist/{EventLogo-801uofbR.d.ts → EventLogo-rFL_kRjk.d.ts} +73 -1
- package/dist/{UnifiedAuthProvider-5E5TUNMS.js → UnifiedAuthProvider-XIQQ7LVU.js} +4 -5
- package/dist/{chunk-YLKIDTUK.js → chunk-22WKWKRX.js} +4 -4
- package/dist/{chunk-TVYPTYOY.js → chunk-4C7EXCAR.js} +60 -24
- package/dist/chunk-4C7EXCAR.js.map +1 -0
- package/dist/{chunk-2TWNJ46Y.js → chunk-6LAAY47Q.js} +2 -2
- package/dist/{chunk-444EZN6N.js → chunk-7QCC6MCP.js} +88 -1
- package/dist/chunk-7QCC6MCP.js.map +1 -0
- package/dist/{chunk-FHWWBIHA.js → chunk-BCIBECNB.js} +5 -5
- package/dist/chunk-BJPBT3CU.js +21 -0
- package/dist/chunk-BJPBT3CU.js.map +1 -0
- package/dist/{chunk-L6PGMCMD.js → chunk-BLCXZEYF.js} +3 -3
- package/dist/{chunk-HJGGOMQ6.js → chunk-HAWZXGR2.js} +147 -103
- package/dist/chunk-HAWZXGR2.js.map +1 -0
- package/dist/{chunk-XARJS7CD.js → chunk-INQLMHPF.js} +2 -2
- package/dist/chunk-JISYG63F.js +70 -0
- package/dist/chunk-JISYG63F.js.map +1 -0
- package/dist/{chunk-NOHEVYVX.js → chunk-KYRHUBIU.js} +417 -319
- package/dist/chunk-KYRHUBIU.js.map +1 -0
- package/dist/{chunk-SL2YQDR6.js → chunk-MA6EPSGZ.js} +2 -2
- package/dist/{chunk-5DPZ5EAT.js → chunk-OWAG3GSU.js} +1 -3
- package/dist/{chunk-LTV3XIJJ.js → chunk-T6JN6LH6.js} +4 -4
- package/dist/{chunk-4MT5BGGL.js → chunk-YCWDTTUK.js} +4 -6
- package/dist/{chunk-4MT5BGGL.js.map → chunk-YCWDTTUK.js.map} +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +12 -11
- package/dist/components.js.map +1 -1
- package/dist/hooks.js +8 -9
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +15 -14
- package/dist/index.js.map +1 -1
- package/dist/providers.js +3 -4
- package/dist/rbac/index.js +8 -9
- package/dist/schema-DTDZQe2u.d.ts +28 -0
- package/dist/types.d.ts +152 -3
- package/dist/types.js +51 -16
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +89 -4
- package/dist/utils.js +214 -96
- package/dist/utils.js.map +1 -1
- package/dist/validation.d.ts +1 -343
- package/dist/validation.js +3 -100
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +27 -0
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +79 -10
- package/docs/architecture/README.md +0 -1
- package/docs/styles/README.md +0 -2
- package/examples/RBAC/CompleteRBACExample.tsx +324 -0
- package/examples/RBAC/EventBasedApp.tsx +239 -0
- package/examples/RBAC/PermissionExample.tsx +151 -0
- package/examples/RBAC/index.ts +13 -0
- package/examples/public-pages/CorrectPublicPageImplementation.tsx +301 -0
- package/examples/public-pages/PublicEventPage.tsx +274 -0
- package/examples/public-pages/PublicPageApp.tsx +308 -0
- package/examples/public-pages/PublicPageUsageExample.tsx +216 -0
- package/examples/public-pages/index.ts +14 -0
- package/package.json +1 -10
- package/src/__tests__/TEST_STANDARD.md +92 -0
- package/src/components/Badge/Badge.test.tsx +314 -0
- package/src/components/Badge/Badge.tsx +304 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
- package/src/components/DataTable/__tests__/styles.test.ts +1 -1
- package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
- package/src/components/DataTable/components/DataTableBody.tsx +461 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
- package/src/components/DataTable/components/FilterRow.tsx +9 -3
- package/src/components/DataTable/components/PaginationControls.tsx +1 -0
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
- package/src/components/DataTable/core/ActionManager.ts +235 -0
- package/src/components/DataTable/core/ColumnManager.ts +205 -0
- package/src/components/DataTable/core/DataManager.ts +188 -0
- package/src/components/DataTable/core/DataTableContext.tsx +181 -0
- package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
- package/src/components/DataTable/core/PluginRegistry.ts +229 -0
- package/src/components/DataTable/core/StateManager.ts +311 -0
- package/src/components/DataTable/core/interfaces.ts +338 -0
- package/src/components/DataTable/styles.ts +27 -6
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/columnUtils.ts +40 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/index.ts +1 -0
- package/src/components/Dialog/README.md +804 -0
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +611 -0
- package/src/components/Dialog/utils/safeHtml.ts +185 -0
- package/src/components/Footer/Footer.test.tsx +1 -1
- package/src/components/Form/Form.test.tsx +1 -1
- package/src/components/Form/FormErrorSummary.tsx +113 -0
- package/src/components/Form/FormFieldset.tsx +127 -0
- package/src/components/Form/FormLiveRegion.tsx +198 -0
- package/src/components/LoginForm/LoginForm.test.tsx +1 -1
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +597 -0
- package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
- package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
- package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +20 -8
- package/src/components/Table/__tests__/Table.test.tsx +1 -1
- package/src/components/index.ts +3 -0
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
- package/src/index.ts +4 -0
- package/src/styles/core.css +3 -0
- package/src/utils/appConfig.ts +47 -0
- package/src/utils/appIdResolver.test.ts +499 -0
- package/src/utils/appIdResolver.ts +130 -0
- package/src/utils/appNameResolver.simple.test.ts +212 -0
- package/src/utils/appNameResolver.test.ts +121 -0
- package/src/utils/appNameResolver.ts +191 -0
- package/src/utils/audit.ts +127 -0
- package/src/utils/auth-utils.ts +96 -0
- package/src/utils/bundleAnalysis.ts +129 -0
- package/src/utils/cn.ts +7 -0
- package/src/utils/debugLogger.ts +67 -0
- package/src/utils/deviceFingerprint.ts +215 -0
- package/src/utils/dynamicUtils.ts +105 -0
- package/src/utils/file-reference.test.ts +788 -0
- package/src/utils/file-reference.ts +519 -0
- package/src/utils/formatDate.test.ts +237 -0
- package/src/utils/formatting.ts +133 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/lazyLoad.tsx +44 -0
- package/src/utils/logger.ts +179 -0
- package/src/utils/organisationContext.test.ts +322 -0
- package/src/utils/organisationContext.ts +153 -0
- package/src/utils/performanceBenchmark.ts +64 -0
- package/src/utils/performanceBudgets.ts +110 -0
- package/src/utils/permissionTypes.ts +37 -0
- package/src/utils/permissionUtils.test.ts +393 -0
- package/src/utils/permissionUtils.ts +34 -0
- package/src/utils/sanitization.ts +264 -0
- package/src/utils/schemaUtils.ts +37 -0
- package/src/utils/secureDataAccess.test.ts +711 -0
- package/src/utils/secureDataAccess.ts +377 -0
- package/src/utils/secureErrors.ts +79 -0
- package/src/utils/secureStorage.ts +244 -0
- package/src/utils/security.ts +156 -0
- package/src/utils/securityMonitor.ts +45 -0
- package/src/utils/sessionTracking.ts +126 -0
- package/src/utils/validation.ts +111 -0
- package/src/utils/validationUtils.ts +120 -0
- package/src/validation/index.ts +2 -2
- package/dist/chunk-444EZN6N.js.map +0 -1
- package/dist/chunk-APIBCTL2.js +0 -670
- package/dist/chunk-APIBCTL2.js.map +0 -1
- package/dist/chunk-HJGGOMQ6.js.map +0 -1
- package/dist/chunk-K2WWTH7O.js +0 -94
- package/dist/chunk-K2WWTH7O.js.map +0 -1
- package/dist/chunk-LMC26NLJ.js +0 -84
- package/dist/chunk-LMC26NLJ.js.map +0 -1
- package/dist/chunk-NOHEVYVX.js.map +0 -1
- package/dist/chunk-TVYPTYOY.js.map +0 -1
- package/dist/validation-8npbysjg.d.ts +0 -177
- /package/dist/{DataTable-CYOHOX3O.js.map → DataTable-6M4L6BI2.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-5E5TUNMS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
- /package/dist/{chunk-YLKIDTUK.js.map → chunk-22WKWKRX.js.map} +0 -0
- /package/dist/{chunk-2TWNJ46Y.js.map → chunk-6LAAY47Q.js.map} +0 -0
- /package/dist/{chunk-FHWWBIHA.js.map → chunk-BCIBECNB.js.map} +0 -0
- /package/dist/{chunk-L6PGMCMD.js.map → chunk-BLCXZEYF.js.map} +0 -0
- /package/dist/{chunk-XARJS7CD.js.map → chunk-INQLMHPF.js.map} +0 -0
- /package/dist/{chunk-SL2YQDR6.js.map → chunk-MA6EPSGZ.js.map} +0 -0
- /package/dist/{chunk-5DPZ5EAT.js.map → chunk-OWAG3GSU.js.map} +0 -0
- /package/dist/{chunk-LTV3XIJJ.js.map → chunk-T6JN6LH6.js.map} +0 -0
- /package/examples/{components → components 2}/DataTable/HierarchicalActionsExample.tsx +0 -0
- /package/examples/{components → components 2}/DataTable/HierarchicalExample.tsx +0 -0
- /package/examples/{components → components 2}/DataTable/InitialPageSizeExample.tsx +0 -0
- /package/examples/{components → components 2}/DataTable/PerformanceExample.tsx +0 -0
- /package/examples/{components → components 2}/DataTable/index.ts +0 -0
- /package/examples/{components → components 2}/Dialog/BasicHtmlTest.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/DebugHtmlExample.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/HtmlDialogExample.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/ScrollableDialogExample.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/SimpleHtmlTest.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/SmartDialogExample.tsx +0 -0
- /package/examples/{components → components 2}/Dialog/index.ts +0 -0
- /package/examples/{components → components 2}/index.ts +0 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DataTable State Manager
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Components/DataTable/Architecture/Managers
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { StateManager, DataTableState, DataTableObserver, Observable, UIState } from './interfaces';
|
|
9
|
+
import type { DataRecord } from '../types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* State manager implementation with observer pattern
|
|
13
|
+
* Responsible only for state management
|
|
14
|
+
*/
|
|
15
|
+
export class StateManagerImpl<TData extends DataRecord> implements StateManager<TData>, Observable<TData> {
|
|
16
|
+
private state: DataTableState<TData>;
|
|
17
|
+
private observers: Map<string, DataTableObserver<TData>> = new Map();
|
|
18
|
+
private observerIdCounter = 0;
|
|
19
|
+
|
|
20
|
+
constructor(initialState?: Partial<DataTableState<TData>>) {
|
|
21
|
+
this.state = this.createInitialState(initialState);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get current state
|
|
26
|
+
*/
|
|
27
|
+
getState(): DataTableState<TData> {
|
|
28
|
+
return { ...this.state };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set state with updater function
|
|
33
|
+
*/
|
|
34
|
+
setState(updater: (state: DataTableState<TData>) => DataTableState<TData>): void {
|
|
35
|
+
const newState = updater(this.getState());
|
|
36
|
+
const oldState = this.state;
|
|
37
|
+
this.state = newState;
|
|
38
|
+
|
|
39
|
+
// Notify observers of state changes
|
|
40
|
+
this.notifyStateChange(oldState, newState);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Subscribe to state changes
|
|
45
|
+
*/
|
|
46
|
+
subscribe(observer: DataTableObserver<TData> | ((state: DataTableState<TData>) => void)): () => void {
|
|
47
|
+
const observerId = `observer-${++this.observerIdCounter}`;
|
|
48
|
+
|
|
49
|
+
let dataTableObserver: DataTableObserver<TData>;
|
|
50
|
+
|
|
51
|
+
if (typeof observer === 'function') {
|
|
52
|
+
dataTableObserver = {
|
|
53
|
+
id: observerId,
|
|
54
|
+
onStateChange: observer,
|
|
55
|
+
};
|
|
56
|
+
} else {
|
|
57
|
+
dataTableObserver = observer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.observers.set(observerId, dataTableObserver);
|
|
61
|
+
|
|
62
|
+
// Return unsubscribe function
|
|
63
|
+
return () => this.unsubscribe(observerId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Subscribe to specific state changes
|
|
68
|
+
*/
|
|
69
|
+
subscribeToObserver(observer: DataTableObserver<TData>): () => void {
|
|
70
|
+
this.observers.set(observer.id, observer);
|
|
71
|
+
return () => this.unsubscribe(observer.id);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Unsubscribe observer
|
|
76
|
+
*/
|
|
77
|
+
unsubscribe(observerId: string): void {
|
|
78
|
+
this.observers.delete(observerId);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Notify all observers of an event
|
|
83
|
+
*/
|
|
84
|
+
notify(event: string, data: any): void {
|
|
85
|
+
this.observers.forEach(observer => {
|
|
86
|
+
switch (event) {
|
|
87
|
+
case 'dataChange':
|
|
88
|
+
observer.onDataChange?.(data);
|
|
89
|
+
break;
|
|
90
|
+
case 'columnChange':
|
|
91
|
+
observer.onColumnChange?.(data);
|
|
92
|
+
break;
|
|
93
|
+
case 'stateChange':
|
|
94
|
+
observer.onStateChange?.(data);
|
|
95
|
+
break;
|
|
96
|
+
case 'error':
|
|
97
|
+
observer.onError?.(data);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Update data and notify observers
|
|
105
|
+
*/
|
|
106
|
+
updateData(data: TData[]): void {
|
|
107
|
+
const oldData = this.state.data;
|
|
108
|
+
this.setState(state => ({ ...state, data }));
|
|
109
|
+
|
|
110
|
+
if (oldData !== data) {
|
|
111
|
+
this.notify('dataChange', data);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Update columns and notify observers
|
|
117
|
+
*/
|
|
118
|
+
updateColumns(columns: any[]): void {
|
|
119
|
+
const oldColumns = this.state.columns;
|
|
120
|
+
this.setState(state => ({ ...state, columns }));
|
|
121
|
+
|
|
122
|
+
if (oldColumns !== columns) {
|
|
123
|
+
this.notify('columnChange', columns);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Update actions and notify observers
|
|
129
|
+
*/
|
|
130
|
+
updateActions(actions: any[]): void {
|
|
131
|
+
this.setState(state => ({ ...state, actions }));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Update UI state
|
|
136
|
+
*/
|
|
137
|
+
updateUI(uiUpdates: Partial<UIState>): void {
|
|
138
|
+
this.setState(state => ({
|
|
139
|
+
...state,
|
|
140
|
+
ui: { ...state.ui, ...uiUpdates }
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Update global filter
|
|
146
|
+
*/
|
|
147
|
+
updateGlobalFilter(filter: string): void {
|
|
148
|
+
this.updateUI({ globalFilter: filter });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Update column filters
|
|
153
|
+
*/
|
|
154
|
+
updateColumnFilters(filters: Array<{ id: string; value: any }>): void {
|
|
155
|
+
this.updateUI({ columnFilters: filters });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Update sorting
|
|
160
|
+
*/
|
|
161
|
+
updateSorting(sorting: Array<{ id: string; desc: boolean }>): void {
|
|
162
|
+
this.updateUI({ sorting });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Update grouping
|
|
167
|
+
*/
|
|
168
|
+
updateGrouping(grouping: string[]): void {
|
|
169
|
+
this.updateUI({ grouping });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Update pagination
|
|
174
|
+
*/
|
|
175
|
+
updatePagination(pagination: { pageIndex: number; pageSize: number }): void {
|
|
176
|
+
this.updateUI({ pagination });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Update row selection
|
|
181
|
+
*/
|
|
182
|
+
updateRowSelection(selection: Record<string, boolean>): void {
|
|
183
|
+
this.updateUI({ rowSelection: selection });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Update editing state
|
|
188
|
+
*/
|
|
189
|
+
updateEditing(editing: DataTableState<TData>['ui']['editing']): void {
|
|
190
|
+
this.updateUI({ editing });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Update modal state
|
|
195
|
+
*/
|
|
196
|
+
updateModals(modals: DataTableState<TData>['ui']['modals']): void {
|
|
197
|
+
this.updateUI({ modals });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Update feature state
|
|
202
|
+
*/
|
|
203
|
+
updateFeatureState(featureName: string, state: any): void {
|
|
204
|
+
this.setState(currentState => ({
|
|
205
|
+
...currentState,
|
|
206
|
+
features: new Map(currentState.features).set(featureName, state)
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Update plugin state
|
|
212
|
+
*/
|
|
213
|
+
updatePluginState(pluginName: string, state: any): void {
|
|
214
|
+
this.setState(currentState => ({
|
|
215
|
+
...currentState,
|
|
216
|
+
plugins: new Map(currentState.plugins).set(pluginName, state)
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Set loading state
|
|
222
|
+
*/
|
|
223
|
+
setLoading(loading: boolean): void {
|
|
224
|
+
this.setState(state => ({ ...state, isLoading: loading }));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Set error state
|
|
229
|
+
*/
|
|
230
|
+
setError(error: Error | null): void {
|
|
231
|
+
this.setState(state => ({ ...state, error }));
|
|
232
|
+
|
|
233
|
+
if (error) {
|
|
234
|
+
this.notify('error', error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Reset state to initial values
|
|
240
|
+
*/
|
|
241
|
+
reset(): void {
|
|
242
|
+
this.state = this.createInitialState();
|
|
243
|
+
this.notify('stateChange', this.state);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Get observer count
|
|
248
|
+
*/
|
|
249
|
+
getObserverCount(): number {
|
|
250
|
+
return this.observers.size;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Create initial state
|
|
255
|
+
*/
|
|
256
|
+
private createInitialState(overrides?: Partial<DataTableState<TData>>): DataTableState<TData> {
|
|
257
|
+
const defaultState: DataTableState<TData> = {
|
|
258
|
+
data: [],
|
|
259
|
+
isLoading: false,
|
|
260
|
+
error: null,
|
|
261
|
+
columns: [],
|
|
262
|
+
columnVisibility: {},
|
|
263
|
+
actions: [],
|
|
264
|
+
ui: {
|
|
265
|
+
globalFilter: '',
|
|
266
|
+
columnFilters: [],
|
|
267
|
+
sorting: [],
|
|
268
|
+
grouping: [],
|
|
269
|
+
expanded: {},
|
|
270
|
+
pagination: {
|
|
271
|
+
pageIndex: 0,
|
|
272
|
+
pageSize: 10,
|
|
273
|
+
},
|
|
274
|
+
rowSelection: {},
|
|
275
|
+
editing: {
|
|
276
|
+
rowId: null,
|
|
277
|
+
data: {},
|
|
278
|
+
isCreating: false,
|
|
279
|
+
creationData: {},
|
|
280
|
+
},
|
|
281
|
+
modals: {
|
|
282
|
+
import: false,
|
|
283
|
+
export: false,
|
|
284
|
+
view: false,
|
|
285
|
+
viewData: null,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
features: new Map(),
|
|
289
|
+
plugins: new Map(),
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
return { ...defaultState, ...overrides };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Notify observers of state changes
|
|
297
|
+
*/
|
|
298
|
+
private notifyStateChange(oldState: DataTableState<TData>, newState: DataTableState<TData>): void {
|
|
299
|
+
// Check for specific changes and notify accordingly
|
|
300
|
+
if (oldState.data !== newState.data) {
|
|
301
|
+
this.notify('dataChange', newState.data);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (oldState.columns !== newState.columns) {
|
|
305
|
+
this.notify('columnChange', newState.columns);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Always notify of state change
|
|
309
|
+
this.notify('stateChange', newState);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DataTable Architecture Interfaces
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Components/DataTable/Architecture
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import type { ColumnDef } from '@tanstack/react-table';
|
|
10
|
+
import type { DataRecord, DataTableAction } from '../types';
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// CORE RESPONSIBILITY INTERFACES (SRP)
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Data management responsibility
|
|
18
|
+
*/
|
|
19
|
+
export interface DataTableDataManager<TData extends DataRecord> {
|
|
20
|
+
getData(): TData[];
|
|
21
|
+
updateData(id: string, data: Partial<TData>): Promise<void>;
|
|
22
|
+
deleteData(id: string): Promise<void>;
|
|
23
|
+
createData(data: Partial<TData>): Promise<TData>;
|
|
24
|
+
isLoading(): boolean;
|
|
25
|
+
getError(): Error | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Column management responsibility
|
|
30
|
+
*/
|
|
31
|
+
export interface ColumnManager<TData extends DataRecord> {
|
|
32
|
+
getColumns(): ColumnDef<TData>[];
|
|
33
|
+
addColumn(column: ColumnDef<TData>): void;
|
|
34
|
+
removeColumn(id: string): void;
|
|
35
|
+
updateColumn(id: string, column: Partial<ColumnDef<TData>>): void;
|
|
36
|
+
getColumn(id: string): ColumnDef<TData> | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Action management responsibility
|
|
41
|
+
*/
|
|
42
|
+
export interface ActionManager<TData extends DataRecord> {
|
|
43
|
+
getActions(): DataTableAction<TData>[];
|
|
44
|
+
addAction(action: DataTableAction<TData>): void;
|
|
45
|
+
removeAction(id: string): void;
|
|
46
|
+
updateAction(id: string, action: Partial<DataTableAction<TData>>): void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* State management responsibility
|
|
51
|
+
*/
|
|
52
|
+
export interface StateManager<TData extends DataRecord> {
|
|
53
|
+
getState(): DataTableState<TData>;
|
|
54
|
+
setState(updater: (state: DataTableState<TData>) => DataTableState<TData>): void;
|
|
55
|
+
subscribe(callback: (state: DataTableState<TData>) => void): () => void;
|
|
56
|
+
|
|
57
|
+
// Additional methods for convenience
|
|
58
|
+
updateData(data: TData[]): void;
|
|
59
|
+
updateColumns(columns: any[]): void;
|
|
60
|
+
updateActions(actions: any[]): void;
|
|
61
|
+
updateUI(uiUpdates: Partial<UIState>): void;
|
|
62
|
+
updateGlobalFilter(filter: string): void;
|
|
63
|
+
updateColumnFilters(filters: Array<{ id: string; value: any }>): void;
|
|
64
|
+
updateSorting(sorting: Array<{ id: string; desc: boolean }>): void;
|
|
65
|
+
updateGrouping(grouping: string[]): void;
|
|
66
|
+
updatePagination(pagination: { pageIndex: number; pageSize: number }): void;
|
|
67
|
+
updateRowSelection(selection: Record<string, boolean>): void;
|
|
68
|
+
updateEditing(editing: DataTableState<TData>['ui']['editing']): void;
|
|
69
|
+
updateModals(modals: DataTableState<TData>['ui']['modals']): void;
|
|
70
|
+
updateFeatureState(featureName: string, state: any): void;
|
|
71
|
+
updatePluginState(pluginName: string, state: any): void;
|
|
72
|
+
setLoading(loading: boolean): void;
|
|
73
|
+
setError(error: Error | null): void;
|
|
74
|
+
reset(): void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// FEATURE STRATEGY INTERFACES (OCP)
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Feature strategy interface for extensible features
|
|
83
|
+
*/
|
|
84
|
+
export interface DataTableFeature<TData extends DataRecord = DataRecord> {
|
|
85
|
+
name: string;
|
|
86
|
+
priority: number;
|
|
87
|
+
isEnabled(): boolean;
|
|
88
|
+
initialize(context: DataTableContext<TData>): void;
|
|
89
|
+
render(): React.ReactNode;
|
|
90
|
+
cleanup(): void;
|
|
91
|
+
getState(): any;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Feature configuration
|
|
96
|
+
*/
|
|
97
|
+
export interface FeatureConfig {
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
options?: Record<string, any>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// PLUGIN ARCHITECTURE INTERFACES
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Plugin interface for extensible functionality
|
|
108
|
+
*/
|
|
109
|
+
export interface DataTablePlugin<TData extends DataRecord = DataRecord> {
|
|
110
|
+
name: string;
|
|
111
|
+
version: string;
|
|
112
|
+
priority: number;
|
|
113
|
+
dependencies?: string[];
|
|
114
|
+
|
|
115
|
+
initialize(context: DataTableContext<TData>): Promise<void>;
|
|
116
|
+
render(): React.ReactNode;
|
|
117
|
+
cleanup(): Promise<void>;
|
|
118
|
+
|
|
119
|
+
onDataChange?(data: TData[]): void;
|
|
120
|
+
onColumnChange?(columns: ColumnDef<TData>[]): void;
|
|
121
|
+
onStateChange?(state: Partial<DataTableState<TData>>): void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Plugin registry for managing plugins
|
|
126
|
+
*/
|
|
127
|
+
export interface PluginRegistry<TData extends DataRecord = DataRecord> {
|
|
128
|
+
register(plugin: DataTablePlugin<TData>): void;
|
|
129
|
+
unregister(name: string): void;
|
|
130
|
+
getPlugin(name: string): DataTablePlugin<TData> | undefined;
|
|
131
|
+
getEnabledPlugins(): DataTablePlugin<TData>[];
|
|
132
|
+
getDependencyOrder(): DataTablePlugin<TData>[];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// ADAPTER PATTERN INTERFACES (DIP)
|
|
137
|
+
// ============================================================================
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Data adapter interface for different data sources
|
|
141
|
+
*/
|
|
142
|
+
export interface DataAdapter<TData extends DataRecord = DataRecord> {
|
|
143
|
+
name: string;
|
|
144
|
+
|
|
145
|
+
fetchData(options: FetchOptions): Promise<TData[]>;
|
|
146
|
+
updateData(id: string, data: Partial<TData>): Promise<void>;
|
|
147
|
+
deleteData(id: string): Promise<void>;
|
|
148
|
+
createData(data: Partial<TData>): Promise<TData>;
|
|
149
|
+
exportData(format: ExportFormat, options?: ExportOptions): Promise<string>;
|
|
150
|
+
importData(data: TData[]): Promise<void>;
|
|
151
|
+
|
|
152
|
+
isConnected(): boolean;
|
|
153
|
+
getError(): Error | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Fetch options for data adapters
|
|
158
|
+
*/
|
|
159
|
+
export interface FetchOptions {
|
|
160
|
+
page?: number;
|
|
161
|
+
pageSize?: number;
|
|
162
|
+
sortBy?: string;
|
|
163
|
+
sortDirection?: 'asc' | 'desc';
|
|
164
|
+
filters?: Record<string, any>;
|
|
165
|
+
search?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Export options
|
|
170
|
+
*/
|
|
171
|
+
export interface ExportOptions {
|
|
172
|
+
filename?: string;
|
|
173
|
+
includeHeaders?: boolean;
|
|
174
|
+
dateFormat?: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Export format types
|
|
179
|
+
*/
|
|
180
|
+
export type ExportFormat = 'csv' | 'json' | 'xlsx';
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// OBSERVER PATTERN INTERFACES
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Observer interface for state changes
|
|
188
|
+
*/
|
|
189
|
+
export interface DataTableObserver<TData extends DataRecord = DataRecord> {
|
|
190
|
+
id: string;
|
|
191
|
+
onDataChange?(data: TData[]): void;
|
|
192
|
+
onColumnChange?(columns: ColumnDef<TData>[]): void;
|
|
193
|
+
onStateChange?(state: Partial<DataTableState<TData>>): void;
|
|
194
|
+
onError?(error: Error): void;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Observable interface for state management
|
|
199
|
+
*/
|
|
200
|
+
export interface Observable<TData extends DataRecord = DataRecord> {
|
|
201
|
+
subscribe(observer: DataTableObserver<TData> | ((state: DataTableState<TData>) => void)): () => void;
|
|
202
|
+
unsubscribe(observerId: string): void;
|
|
203
|
+
notify(event: string, data: any): void;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// STATE INTERFACES
|
|
208
|
+
// ============================================================================
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Core DataTable state
|
|
212
|
+
*/
|
|
213
|
+
export interface DataTableState<TData extends DataRecord = DataRecord> {
|
|
214
|
+
// Data state
|
|
215
|
+
data: TData[];
|
|
216
|
+
isLoading: boolean;
|
|
217
|
+
error: Error | null;
|
|
218
|
+
|
|
219
|
+
// Column state
|
|
220
|
+
columns: ColumnDef<TData>[];
|
|
221
|
+
columnVisibility: Record<string, boolean>;
|
|
222
|
+
|
|
223
|
+
// Action state
|
|
224
|
+
actions: DataTableAction<TData>[];
|
|
225
|
+
|
|
226
|
+
// UI state
|
|
227
|
+
ui: UIState;
|
|
228
|
+
|
|
229
|
+
// Feature state
|
|
230
|
+
features: Map<string, any>;
|
|
231
|
+
|
|
232
|
+
// Plugin state
|
|
233
|
+
plugins: Map<string, any>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* UI-specific state
|
|
238
|
+
*/
|
|
239
|
+
export interface UIState {
|
|
240
|
+
// Filtering
|
|
241
|
+
globalFilter: string;
|
|
242
|
+
columnFilters: Array<{ id: string; value: any }>;
|
|
243
|
+
|
|
244
|
+
// Sorting
|
|
245
|
+
sorting: Array<{ id: string; desc: boolean }>;
|
|
246
|
+
|
|
247
|
+
// Grouping
|
|
248
|
+
grouping: string[];
|
|
249
|
+
expanded: Record<string, boolean>;
|
|
250
|
+
|
|
251
|
+
// Pagination
|
|
252
|
+
pagination: {
|
|
253
|
+
pageIndex: number;
|
|
254
|
+
pageSize: number;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Selection
|
|
258
|
+
rowSelection: Record<string, boolean>;
|
|
259
|
+
|
|
260
|
+
// Editing
|
|
261
|
+
editing: {
|
|
262
|
+
rowId: string | null;
|
|
263
|
+
data: Record<string, any>;
|
|
264
|
+
isCreating: boolean;
|
|
265
|
+
creationData: Record<string, any>;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Modals
|
|
269
|
+
modals: {
|
|
270
|
+
import: boolean;
|
|
271
|
+
export: boolean;
|
|
272
|
+
view: boolean;
|
|
273
|
+
viewData: any;
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ============================================================================
|
|
278
|
+
// CONTEXT INTERFACES
|
|
279
|
+
// ============================================================================
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* DataTable context for sharing state and managers
|
|
283
|
+
*/
|
|
284
|
+
export interface DataTableContext<TData extends DataRecord = DataRecord> {
|
|
285
|
+
// Core managers
|
|
286
|
+
dataManager: DataTableDataManager<TData>;
|
|
287
|
+
columnManager: ColumnManager<TData>;
|
|
288
|
+
actionManager: ActionManager<TData>;
|
|
289
|
+
stateManager: StateManager<TData>;
|
|
290
|
+
|
|
291
|
+
// Architecture components
|
|
292
|
+
pluginRegistry: PluginRegistry<TData>;
|
|
293
|
+
adapter: DataAdapter<TData>;
|
|
294
|
+
observable: Observable<TData>;
|
|
295
|
+
|
|
296
|
+
// Configuration
|
|
297
|
+
config: DataTableConfig<TData>;
|
|
298
|
+
|
|
299
|
+
// Utilities
|
|
300
|
+
utils: DataTableUtils<TData>;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* DataTable configuration
|
|
305
|
+
*/
|
|
306
|
+
export interface DataTableConfig<TData extends DataRecord = DataRecord> {
|
|
307
|
+
// Core settings
|
|
308
|
+
title?: string;
|
|
309
|
+
description?: string;
|
|
310
|
+
className?: string;
|
|
311
|
+
variant?: 'default' | 'compact' | 'spacious';
|
|
312
|
+
|
|
313
|
+
// Feature flags
|
|
314
|
+
features: Record<string, FeatureConfig>;
|
|
315
|
+
|
|
316
|
+
// Performance settings
|
|
317
|
+
enableVirtualization: boolean;
|
|
318
|
+
enableCaching: boolean;
|
|
319
|
+
cacheTimeout: number;
|
|
320
|
+
|
|
321
|
+
// Accessibility settings
|
|
322
|
+
enableKeyboardNavigation: boolean;
|
|
323
|
+
enableScreenReaderSupport: boolean;
|
|
324
|
+
|
|
325
|
+
// Event handlers
|
|
326
|
+
onDataChange?: (data: TData[]) => void;
|
|
327
|
+
onError?: (error: Error) => void;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* DataTable utilities
|
|
332
|
+
*/
|
|
333
|
+
export interface DataTableUtils<TData extends DataRecord = DataRecord> {
|
|
334
|
+
getRowId: (row: TData, index: number) => string;
|
|
335
|
+
formatValue: (value: any, column: ColumnDef<TData>) => string;
|
|
336
|
+
validateData: (data: Partial<TData>) => string[] | null;
|
|
337
|
+
debounce: <T extends (...args: any[]) => any>(func: T, delay: number) => T;
|
|
338
|
+
}
|
|
@@ -148,12 +148,33 @@ export const getTableClasses = (options: {
|
|
|
148
148
|
} = {}) => {
|
|
149
149
|
const { isFixed = false, variant = 'default', className } = options;
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
if (isFixed) {
|
|
152
|
+
// For fixed tables, use tableFixed and add variant-specific text size
|
|
153
|
+
return cn(
|
|
154
|
+
tableStyles.tableFixed,
|
|
155
|
+
variant === 'compact' && 'text-sm',
|
|
156
|
+
variant === 'spacious' && 'text-base',
|
|
157
|
+
className
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// For regular tables, build classes based on variant
|
|
162
|
+
// tableStyles.table includes 'text-sm', so we need to handle variants carefully
|
|
163
|
+
if (variant === 'compact') {
|
|
164
|
+
// Compact uses text-sm (same as default), so just use base table styles
|
|
165
|
+
return cn(tableStyles.table, className);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (variant === 'spacious') {
|
|
169
|
+
// Spacious uses text-base, so replace text-sm with text-base
|
|
170
|
+
return cn(
|
|
171
|
+
tableStyles.table.replace('text-sm', 'text-base'),
|
|
172
|
+
className
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Default variant
|
|
177
|
+
return cn(tableStyles.table, className);
|
|
157
178
|
};
|
|
158
179
|
|
|
159
180
|
/**
|