@jmruthers/pace-core 0.6.6 → 0.6.8

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.
Files changed (292) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +240 -0
  4. package/audit-tool/audits/03-architecture.cjs +224 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +554 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +295 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +380 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-6RMSCQJ6.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
  28. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  29. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  30. package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
  31. package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
  32. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  33. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  34. package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
  35. package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
  36. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  37. package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
  38. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  39. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  40. package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
  41. package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
  42. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  43. package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
  44. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  45. package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
  46. package/dist/components.d.ts +5 -4
  47. package/dist/components.js +29 -34
  48. package/dist/eslint-rules/index.cjs +22 -9
  49. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  50. package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
  51. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  52. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
  53. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
  54. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  55. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  56. package/dist/hooks.d.ts +5 -5
  57. package/dist/hooks.js +8 -8
  58. package/dist/index.d.ts +7 -7
  59. package/dist/index.js +21 -20
  60. package/dist/providers.js +2 -2
  61. package/dist/rbac/index.d.ts +1 -1
  62. package/dist/rbac/index.js +8 -8
  63. package/dist/theming/runtime.d.ts +61 -1
  64. package/dist/theming/runtime.js +1 -1
  65. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  66. package/dist/types.d.ts +2 -2
  67. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  68. package/dist/utils.d.ts +2 -2
  69. package/dist/utils.js +8 -8
  70. package/docs/README.md +1 -1
  71. package/docs/api/modules.md +106 -41
  72. package/docs/api-reference/components.md +18 -20
  73. package/docs/api-reference/hooks.md +80 -80
  74. package/docs/api-reference/types.md +1 -1
  75. package/docs/api-reference/utilities.md +1 -1
  76. package/docs/architecture/README.md +1 -1
  77. package/docs/core-concepts/events.md +3 -3
  78. package/docs/core-concepts/organisations.md +6 -6
  79. package/docs/core-concepts/permissions.md +6 -6
  80. package/docs/documentation-index.md +12 -18
  81. package/docs/getting-started/dependencies.md +23 -0
  82. package/docs/getting-started/documentation-index.md +1 -1
  83. package/docs/getting-started/examples/README.md +4 -4
  84. package/docs/getting-started/examples/full-featured-app.md +1 -1
  85. package/docs/getting-started/faq.md +2 -2
  86. package/docs/getting-started/quick-reference.md +4 -4
  87. package/docs/implementation-guides/app-layout.md +1 -1
  88. package/docs/implementation-guides/authentication.md +15 -15
  89. package/docs/implementation-guides/component-styling.md +1 -1
  90. package/docs/implementation-guides/data-tables.md +127 -34
  91. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  92. package/docs/implementation-guides/dynamic-colors.md +3 -3
  93. package/docs/implementation-guides/file-upload-storage.md +2 -2
  94. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  95. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  96. package/docs/implementation-guides/large-datasets.md +3 -2
  97. package/docs/implementation-guides/organisation-security.md +2 -2
  98. package/docs/implementation-guides/performance.md +2 -2
  99. package/docs/implementation-guides/permission-enforcement.md +1 -1
  100. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  101. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  102. package/docs/rbac/README.md +5 -5
  103. package/docs/rbac/advanced-patterns.md +6 -6
  104. package/docs/rbac/api-reference.md +20 -20
  105. package/docs/rbac/event-based-apps.md +3 -3
  106. package/docs/rbac/examples.md +41 -41
  107. package/docs/rbac/getting-started.md +37 -37
  108. package/docs/rbac/performance.md +1 -1
  109. package/docs/rbac/quick-start.md +52 -52
  110. package/docs/rbac/secure-client-protection.md +1 -1
  111. package/docs/rbac/troubleshooting.md +1 -1
  112. package/docs/security/README.md +5 -5
  113. package/docs/standards/0-standards-overview.md +220 -0
  114. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
  115. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  116. package/docs/standards/3-architecture-standards.md +606 -0
  117. package/docs/standards/4-code-quality-standards.md +728 -0
  118. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  119. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  120. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  121. package/docs/standards/8-testing-documentation-standards.md +401 -0
  122. package/docs/standards/9-operations-standards.md +1102 -0
  123. package/docs/standards/README.md +203 -104
  124. package/docs/troubleshooting/README.md +4 -4
  125. package/docs/troubleshooting/common-issues.md +2 -2
  126. package/docs/troubleshooting/debugging.md +9 -9
  127. package/docs/troubleshooting/migration.md +4 -4
  128. package/eslint-config-pace-core.cjs +50 -20
  129. package/package.json +50 -19
  130. package/scripts/eslint-audit.cjs +123 -0
  131. package/scripts/install-cursor-rules.cjs +11 -243
  132. package/scripts/install-eslint-config.cjs +349 -0
  133. package/scripts/validate-dependencies.cjs +248 -0
  134. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  135. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  136. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
  137. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  138. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  139. package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
  140. package/src/__tests__/templates/component.test.template.tsx +18 -15
  141. package/src/components/AddressField/AddressField.tsx +26 -1
  142. package/src/components/Alert/Alert.test.tsx +86 -22
  143. package/src/components/Alert/Alert.tsx +19 -11
  144. package/src/components/Badge/Badge.tsx +1 -1
  145. package/src/components/Calendar/Calendar.tsx +201 -47
  146. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  147. package/src/components/ContextSelector/ContextSelector.tsx +108 -126
  148. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  149. package/src/components/DataTable/DataTable.tsx +1 -19
  150. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
  151. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
  152. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  153. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  154. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  155. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  156. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  157. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  158. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  159. package/src/components/DataTable/components/EmptyState.tsx +11 -10
  160. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  161. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  162. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  163. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  164. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  165. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  166. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  167. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  168. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  169. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
  170. package/src/components/DataTable/components/index.ts +2 -1
  171. package/src/components/DataTable/types.ts +0 -18
  172. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  173. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  174. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  175. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  176. package/src/components/Dialog/Dialog.test.tsx +1 -0
  177. package/src/components/Dialog/Dialog.tsx +25 -8
  178. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  179. package/src/components/FileUpload/FileUpload.test.tsx +45 -16
  180. package/src/components/FileUpload/FileUpload.tsx +141 -130
  181. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  182. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  183. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  184. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  185. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  186. package/src/components/Progress/Progress.tsx +2 -4
  187. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  188. package/src/components/Select/Select.tsx +86 -77
  189. package/src/components/Select/types.ts +3 -0
  190. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  191. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  192. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  193. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  194. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
  195. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  196. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  197. package/src/hooks/public/usePublicEvent.ts +5 -5
  198. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  199. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  200. package/src/hooks/public/usePublicRouteParams.ts +13 -9
  201. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  202. package/src/hooks/useAppConfig.ts +2 -2
  203. package/src/hooks/useEventTheme.test.ts +7 -7
  204. package/src/hooks/useEventTheme.ts +2 -1
  205. package/src/hooks/useFileDisplay.ts +2 -2
  206. package/src/hooks/useFileUrl.ts +52 -8
  207. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  208. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  209. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  210. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  211. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  212. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  213. package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
  214. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  215. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  216. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  217. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  218. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  219. package/src/rbac/api.test.ts +104 -0
  220. package/src/rbac/engine.ts +1 -1
  221. package/src/rbac/hooks/useCan.test.ts +2 -2
  222. package/src/rbac/secureClient.ts +1 -1
  223. package/src/rbac/types/functions.ts +1 -1
  224. package/src/styles/core.css +7 -0
  225. package/src/theming/__tests__/parseEventColours.test.ts +118 -3
  226. package/src/theming/parseEventColours.ts +77 -11
  227. package/src/types/supabase.ts +2 -3
  228. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  229. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  230. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  231. package/src/utils/formatting/formatDate.test.ts +3 -2
  232. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  233. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  234. package/src/utils/storage/README.md +1 -1
  235. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  236. package/src/utils/storage/helpers.test.ts +69 -3
  237. package/cursor-rules/01-standards-compliance.mdc +0 -285
  238. package/cursor-rules/04-testing-standards.mdc +0 -270
  239. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  240. package/cursor-rules/06-code-quality.mdc +0 -311
  241. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  242. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  243. package/cursor-rules/11-performance-optimization.mdc +0 -169
  244. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  245. package/dist/DataTable-LRJL4IRV.js +0 -15
  246. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  247. package/dist/eslint-rules/rules/components.cjs +0 -113
  248. package/dist/eslint-rules/rules/imports.cjs +0 -102
  249. package/docs/best-practices/README.md +0 -472
  250. package/docs/best-practices/accessibility.md +0 -604
  251. package/docs/best-practices/common-patterns.md +0 -516
  252. package/docs/best-practices/deployment.md +0 -1103
  253. package/docs/best-practices/performance.md +0 -1328
  254. package/docs/best-practices/security.md +0 -940
  255. package/docs/best-practices/testing.md +0 -1034
  256. package/docs/rbac/compliance/compliance-guide.md +0 -544
  257. package/docs/standards/01-standards-compliance.md +0 -188
  258. package/docs/standards/03-solid-principles.md +0 -39
  259. package/docs/standards/04-testing-standards.md +0 -36
  260. package/docs/standards/05-bug-reports-and-features.md +0 -27
  261. package/docs/standards/06-code-quality.md +0 -34
  262. package/docs/standards/07-tech-stack-compliance.md +0 -30
  263. package/docs/standards/10-error-handling-patterns.md +0 -401
  264. package/docs/standards/11-performance-optimization.md +0 -348
  265. package/docs/standards/12-ci-cd-integration.md +0 -370
  266. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  267. package/scripts/audit/audit-compliance.cjs +0 -1295
  268. package/scripts/audit/audit-components.cjs +0 -260
  269. package/scripts/audit/audit-rbac.cjs +0 -954
  270. package/scripts/audit/audit-standards.cjs +0 -1268
  271. package/scripts/audit/index.cjs +0 -1927
  272. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  273. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  274. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  275. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  276. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  277. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  278. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  279. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  280. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  281. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  282. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  284. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  285. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  286. package/src/components/DataTable/utils/debugTools.ts +0 -514
  287. package/src/eslint-rules/index.cjs +0 -22
  288. package/src/eslint-rules/rules/components.cjs +0 -113
  289. package/src/eslint-rules/rules/imports.cjs +0 -102
  290. package/src/eslint-rules/rules/rbac.cjs +0 -790
  291. package/src/eslint-rules/utils/helpers.cjs +0 -42
  292. 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
- }