@jmruthers/pace-core 0.6.6 → 0.6.7
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +47 -31
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file DataTable Context
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Components/DataTable/Architecture
|
|
5
|
-
* @since 0.3.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React, { createContext, useContext, useMemo, useCallback, useRef, useEffect } from 'react';
|
|
9
|
-
import { useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel } from '@tanstack/react-table';
|
|
10
|
-
import { ChevronDown, ChevronUp, ChevronsUpDown, Filter, MoreHorizontal, Plus, Search, Settings, Trash2, Upload, Download, Eye, Edit, Copy } from 'lucide-react';
|
|
11
|
-
import { Button } from '../../Button/Button';
|
|
12
|
-
import { Input } from '../../Input/Input';
|
|
13
|
-
import { Checkbox } from '../../Checkbox/Checkbox';
|
|
14
|
-
// DropdownMenu components have been merged into Select components
|
|
15
|
-
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '../../Dialog/Dialog';
|
|
16
|
-
import type { DataTableContext as IDataTableContext, DataTableConfig, DataTableUtils } from './interfaces';
|
|
17
|
-
import type { DataRecord, DataTableAction } from '../types';
|
|
18
|
-
import type { ColumnDef } from '@tanstack/react-table';
|
|
19
|
-
import { DataManager } from './DataManager';
|
|
20
|
-
import { ColumnManagerImpl } from './ColumnManager';
|
|
21
|
-
import { ActionManagerImpl } from './ActionManager';
|
|
22
|
-
import { StateManagerImpl } from './StateManager';
|
|
23
|
-
import { PluginRegistryImpl } from './PluginRegistry';
|
|
24
|
-
import { LocalDataAdapter } from './LocalDataAdapter';
|
|
25
|
-
|
|
26
|
-
// Create the context
|
|
27
|
-
const DataTableContext = createContext<IDataTableContext<DataRecord> | null>(null);
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Props for the DataTableProvider component.
|
|
31
|
-
* @template TData - The type of data records in the table
|
|
32
|
-
*/
|
|
33
|
-
export interface DataTableProviderProps<TData extends DataRecord> {
|
|
34
|
-
children: React.ReactNode;
|
|
35
|
-
config: DataTableConfig<TData>;
|
|
36
|
-
data?: TData[];
|
|
37
|
-
columns?: ColumnDef<TData>[];
|
|
38
|
-
actions?: DataTableAction<TData>[];
|
|
39
|
-
pageSize?: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function DataTableProvider<TData extends DataRecord>({
|
|
43
|
-
children,
|
|
44
|
-
config,
|
|
45
|
-
data = [],
|
|
46
|
-
columns = [],
|
|
47
|
-
actions = [],
|
|
48
|
-
pageSize = 10,
|
|
49
|
-
}: DataTableProviderProps<TData>) {
|
|
50
|
-
// Create managers
|
|
51
|
-
const adapter = useMemo(() => new LocalDataAdapter<TData>(data), [data]);
|
|
52
|
-
const dataManager = useMemo(() => new DataManager<TData>(adapter), [adapter]);
|
|
53
|
-
const columnManager = useMemo(() => new ColumnManagerImpl<TData>(columns), [columns]);
|
|
54
|
-
const actionManager = useMemo(() => new ActionManagerImpl<TData>(actions), [actions]);
|
|
55
|
-
const stateManager = useMemo(() => new StateManagerImpl<TData>({
|
|
56
|
-
ui: {
|
|
57
|
-
globalFilter: '',
|
|
58
|
-
columnFilters: [],
|
|
59
|
-
sorting: [],
|
|
60
|
-
grouping: [],
|
|
61
|
-
expanded: {},
|
|
62
|
-
pagination: {
|
|
63
|
-
pageIndex: 0,
|
|
64
|
-
pageSize: pageSize,
|
|
65
|
-
},
|
|
66
|
-
rowSelection: {},
|
|
67
|
-
editing: {
|
|
68
|
-
rowId: null,
|
|
69
|
-
data: {},
|
|
70
|
-
isCreating: false,
|
|
71
|
-
creationData: {},
|
|
72
|
-
},
|
|
73
|
-
modals: {
|
|
74
|
-
import: false,
|
|
75
|
-
export: false,
|
|
76
|
-
view: false,
|
|
77
|
-
viewData: null,
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
}), [pageSize]);
|
|
81
|
-
const pluginRegistry = useMemo(() => new PluginRegistryImpl<TData>(), []);
|
|
82
|
-
|
|
83
|
-
// Create utilities
|
|
84
|
-
const utils: DataTableUtils<TData> = useMemo(() => ({
|
|
85
|
-
getRowId: (row: TData, index: number) => {
|
|
86
|
-
const record = row as Record<string, unknown>;
|
|
87
|
-
return (record.id ? String(record.id) : String(index));
|
|
88
|
-
},
|
|
89
|
-
formatValue: (value: unknown, column: ColumnDef<TData>) => String(value),
|
|
90
|
-
validateData: (data: Partial<TData>) => null,
|
|
91
|
-
debounce: <T extends (...args: unknown[]) => unknown>(func: T, delay: number) => {
|
|
92
|
-
let timeoutId: NodeJS.Timeout;
|
|
93
|
-
return ((...args: unknown[]) => {
|
|
94
|
-
clearTimeout(timeoutId);
|
|
95
|
-
timeoutId = setTimeout(() => func(...args), delay);
|
|
96
|
-
}) as T;
|
|
97
|
-
},
|
|
98
|
-
}), []);
|
|
99
|
-
|
|
100
|
-
// Create context value
|
|
101
|
-
const contextValue: IDataTableContext<TData> = useMemo(() => ({
|
|
102
|
-
dataManager,
|
|
103
|
-
columnManager,
|
|
104
|
-
actionManager,
|
|
105
|
-
stateManager,
|
|
106
|
-
pluginRegistry,
|
|
107
|
-
adapter,
|
|
108
|
-
observable: stateManager,
|
|
109
|
-
config,
|
|
110
|
-
utils,
|
|
111
|
-
}), [dataManager, columnManager, actionManager, stateManager, pluginRegistry, adapter, config, utils]);
|
|
112
|
-
|
|
113
|
-
// Initialize data
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
// Update the adapter with new data
|
|
116
|
-
adapter.setData(data);
|
|
117
|
-
|
|
118
|
-
if (data.length > 0) {
|
|
119
|
-
stateManager.updateData(data);
|
|
120
|
-
} else {
|
|
121
|
-
// Handle empty data case
|
|
122
|
-
stateManager.updateData([]);
|
|
123
|
-
}
|
|
124
|
-
}, [data, dataManager, stateManager, adapter]);
|
|
125
|
-
|
|
126
|
-
// Initialize columns
|
|
127
|
-
useEffect(() => {
|
|
128
|
-
if (columns.length > 0) {
|
|
129
|
-
columnManager.setColumns(columns);
|
|
130
|
-
stateManager.updateColumns(columns);
|
|
131
|
-
}
|
|
132
|
-
}, [columns, columnManager, stateManager]);
|
|
133
|
-
|
|
134
|
-
// Initialize actions
|
|
135
|
-
useEffect(() => {
|
|
136
|
-
if (actions.length > 0) {
|
|
137
|
-
actionManager.setActions(actions);
|
|
138
|
-
stateManager.updateActions(actions);
|
|
139
|
-
}
|
|
140
|
-
}, [actions, actionManager, stateManager]);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<DataTableContext.Provider value={contextValue as unknown as IDataTableContext<DataRecord>}>
|
|
144
|
-
{children}
|
|
145
|
-
</DataTableContext.Provider>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Hook to use DataTable context
|
|
151
|
-
*/
|
|
152
|
-
export function useDataTableContext<TData extends DataRecord = DataRecord>(): IDataTableContext<TData> {
|
|
153
|
-
const context = useContext(DataTableContext);
|
|
154
|
-
if (!context) {
|
|
155
|
-
throw new Error('useDataTableContext must be used within a DataTableProvider');
|
|
156
|
-
}
|
|
157
|
-
return context as unknown as IDataTableContext<TData>;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Hook to use specific managers
|
|
162
|
-
*/
|
|
163
|
-
/**
|
|
164
|
-
* Hook to access DataTable data manager.
|
|
165
|
-
*
|
|
166
|
-
* @template TData - The type of data records in the table
|
|
167
|
-
* @returns Data manager instance
|
|
168
|
-
*/
|
|
169
|
-
export function useDataManager<TData extends DataRecord = DataRecord>() {
|
|
170
|
-
const context = useDataTableContext<TData>();
|
|
171
|
-
return context.dataManager;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Hook to access DataTable column manager.
|
|
176
|
-
*
|
|
177
|
-
* @template TData - The type of data records in the table
|
|
178
|
-
* @returns Column manager instance
|
|
179
|
-
*/
|
|
180
|
-
export function useColumnManager<TData extends DataRecord = DataRecord>() {
|
|
181
|
-
const context = useDataTableContext<TData>();
|
|
182
|
-
return context.columnManager;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Hook to access DataTable action manager.
|
|
187
|
-
*
|
|
188
|
-
* @template TData - The type of data records in the table
|
|
189
|
-
* @returns Action manager instance
|
|
190
|
-
*/
|
|
191
|
-
export function useActionManager<TData extends DataRecord = DataRecord>() {
|
|
192
|
-
const context = useDataTableContext<TData>();
|
|
193
|
-
return context.actionManager;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Hook to access DataTable state manager.
|
|
198
|
-
*
|
|
199
|
-
* @template TData - The type of data records in the table
|
|
200
|
-
* @returns State manager instance
|
|
201
|
-
*/
|
|
202
|
-
export function useStateManager<TData extends DataRecord = DataRecord>() {
|
|
203
|
-
const context = useDataTableContext<TData>();
|
|
204
|
-
return context.stateManager;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Hook to access DataTable plugin registry.
|
|
209
|
-
*
|
|
210
|
-
* @template TData - The type of data records in the table
|
|
211
|
-
* @returns Plugin registry instance
|
|
212
|
-
*/
|
|
213
|
-
export function usePluginRegistry<TData extends DataRecord = DataRecord>() {
|
|
214
|
-
const context = useDataTableContext<TData>();
|
|
215
|
-
return context.pluginRegistry;
|
|
216
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, renderHook, waitFor, act } from '@testing-library/react';
|
|
3
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
-
import { DataTableProvider, useActionManager, useColumnManager, useDataManager, useDataTableContext, usePluginRegistry, useStateManager } from '../DataTableContext';
|
|
5
|
-
import type { DataTableConfig, DataTableContext as IDataTableContext } from '../interfaces';
|
|
6
|
-
import type { DataRecord, DataTableAction } from '../../types';
|
|
7
|
-
import type { ColumnDef } from '@tanstack/react-table';
|
|
8
|
-
|
|
9
|
-
interface TestRecord extends DataRecord {
|
|
10
|
-
id: string;
|
|
11
|
-
name: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const baseConfig: DataTableConfig<TestRecord> = {
|
|
15
|
-
features: {},
|
|
16
|
-
enableVirtualization: false,
|
|
17
|
-
enableCaching: false,
|
|
18
|
-
cacheTimeout: 0,
|
|
19
|
-
enableKeyboardNavigation: true,
|
|
20
|
-
enableScreenReaderSupport: true,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const columns: ColumnDef<TestRecord>[] = [
|
|
24
|
-
{ id: 'name', header: 'Name', accessorKey: 'name' },
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
const actions: DataTableAction<TestRecord>[] = [
|
|
28
|
-
{ label: 'View', testId: 'view', onClick: vi.fn() },
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
describe('DataTableContext', () => {
|
|
32
|
-
it('throws when hooks are used outside of the provider', () => {
|
|
33
|
-
expect(() => renderHook(() => useDataTableContext<TestRecord>())).toThrow(
|
|
34
|
-
'useDataTableContext must be used within a DataTableProvider'
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('exposes initialized managers populated from props', async () => {
|
|
39
|
-
const onContext = vi.fn();
|
|
40
|
-
const data: TestRecord[] = [{ id: '1', name: 'Alpha' }];
|
|
41
|
-
|
|
42
|
-
render(
|
|
43
|
-
<DataTableProvider config={baseConfig} data={data} columns={columns} actions={actions}>
|
|
44
|
-
<TestConsumer onContext={onContext} />
|
|
45
|
-
</DataTableProvider>
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
await waitFor(() => expect(onContext).toHaveBeenCalled());
|
|
49
|
-
const ctx = onContext.mock.calls.at(-1)?.[0];
|
|
50
|
-
|
|
51
|
-
expect(ctx.dataManager.getAdapter().name).toBe('local');
|
|
52
|
-
expect(ctx.stateManager.getState().data).toEqual(data);
|
|
53
|
-
expect(ctx.columnManager.getColumns()).toHaveLength(1);
|
|
54
|
-
expect(ctx.actionManager.getActions()).toHaveLength(1);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('reacts to prop changes and updates managed state', async () => {
|
|
58
|
-
const onContext = vi.fn();
|
|
59
|
-
const initialData: TestRecord[] = [{ id: '1', name: 'Alpha' }];
|
|
60
|
-
const updatedData: TestRecord[] = [{ id: '2', name: 'Beta' }];
|
|
61
|
-
const updatedColumns: ColumnDef<TestRecord>[] = [
|
|
62
|
-
{ id: 'name', header: 'Name', accessorKey: 'name' },
|
|
63
|
-
{ id: 'id', header: 'Identifier', accessorKey: 'id' },
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
const { rerender } = render(
|
|
67
|
-
<DataTableProvider config={baseConfig} data={initialData} columns={columns} actions={actions}>
|
|
68
|
-
<TestConsumer onContext={onContext} />
|
|
69
|
-
</DataTableProvider>
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
await waitFor(() => expect(onContext).toHaveBeenCalled());
|
|
73
|
-
onContext.mockClear();
|
|
74
|
-
|
|
75
|
-
rerender(
|
|
76
|
-
<DataTableProvider config={baseConfig} data={updatedData} columns={updatedColumns} actions={[...actions]}>
|
|
77
|
-
<TestConsumer onContext={onContext} />
|
|
78
|
-
</DataTableProvider>
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
await waitFor(() => expect(onContext).toHaveBeenCalled());
|
|
82
|
-
const ctx = onContext.mock.calls.at(-1)?.[0];
|
|
83
|
-
|
|
84
|
-
expect(ctx.stateManager.getState().data).toEqual(updatedData);
|
|
85
|
-
expect(ctx.columnManager.getColumns()).toHaveLength(2);
|
|
86
|
-
expect(ctx.actionManager.getActions()).toHaveLength(actions.length);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('exposes hook shorthands and utility helpers', async () => {
|
|
90
|
-
vi.useFakeTimers();
|
|
91
|
-
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
92
|
-
<DataTableProvider config={baseConfig} data={[{ id: '1', name: 'Alpha' }]} columns={columns} actions={actions}>
|
|
93
|
-
{children}
|
|
94
|
-
</DataTableProvider>
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const { result: managerResult } = renderHook(
|
|
98
|
-
() => ({
|
|
99
|
-
data: useDataManager<TestRecord>(),
|
|
100
|
-
columns: useColumnManager<TestRecord>(),
|
|
101
|
-
actions: useActionManager<TestRecord>(),
|
|
102
|
-
state: useStateManager<TestRecord>(),
|
|
103
|
-
plugins: usePluginRegistry<TestRecord>(),
|
|
104
|
-
context: useDataTableContext<TestRecord>(),
|
|
105
|
-
}),
|
|
106
|
-
{ wrapper }
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
expect(managerResult.current.data.getAdapter().name).toBe('local');
|
|
110
|
-
expect(managerResult.current.columns.getColumns()).toHaveLength(1);
|
|
111
|
-
expect(managerResult.current.actions.getActionCount()).toBe(1);
|
|
112
|
-
expect(managerResult.current.state.getObserverCount()).toBe(0);
|
|
113
|
-
expect(managerResult.current.plugins.getPluginCount()).toBe(0);
|
|
114
|
-
|
|
115
|
-
const debounced = managerResult.current.context.utils.debounce(vi.fn(), 50);
|
|
116
|
-
debounced();
|
|
117
|
-
debounced();
|
|
118
|
-
expect(managerResult.current.context.utils.getRowId?.({} as any, 3)).toBe('3');
|
|
119
|
-
|
|
120
|
-
await act(async () => {
|
|
121
|
-
vi.advanceTimersByTime(60);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(managerResult.current.context.utils.debounce).toBeDefined();
|
|
125
|
-
expect((managerResult.current.context.utils.debounce as any).mock).toBeUndefined();
|
|
126
|
-
vi.useRealTimers();
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
function TestConsumer({ onContext }: { onContext: (ctx: IDataTableContext<TestRecord>) => void }) {
|
|
131
|
-
const ctx = useDataTableContext<TestRecord>();
|
|
132
|
-
React.useEffect(() => {
|
|
133
|
-
onContext(ctx);
|
|
134
|
-
}, [ctx, onContext]);
|
|
135
|
-
return null;
|
|
136
|
-
}
|