@jmruthers/pace-core 0.6.9 → 0.6.11

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