@jmruthers/pace-core 0.5.76 → 0.5.78

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 (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -0,0 +1,447 @@
1
+ /**
2
+ * @file Keyboard Navigation Hook for DataTable
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/DataTable/Hooks
5
+ * @since 0.4.0
6
+ *
7
+ * Comprehensive keyboard navigation and focus management for DataTable.
8
+ * Implements roving tabindex pattern for efficient keyboard navigation.
9
+ */
10
+
11
+ import { useCallback, useEffect, useRef, useState } from 'react';
12
+ import { announce } from '../utils/a11yUtils';
13
+
14
+ export interface KeyboardNavigationOptions {
15
+ /** Whether keyboard navigation is enabled */
16
+ enabled?: boolean;
17
+ /** Whether to announce navigation changes */
18
+ announceNavigation?: boolean;
19
+ /** Whether column reordering is supported */
20
+ supportsColumnReorder?: boolean;
21
+ /** Whether column resizing is supported */
22
+ supportsColumnResize?: boolean;
23
+ /** Callback when focus moves to a new cell */
24
+ onFocusChange?: (rowIndex: number, columnIndex: number) => void;
25
+ /** Table ref for DOM queries */
26
+ tableRef?: React.RefObject<HTMLTableElement>;
27
+ }
28
+
29
+ export interface KeyboardNavigationState {
30
+ /** Current focused row index */
31
+ focusedRowIndex: number;
32
+ /** Current focused column index */
33
+ focusedColumnIndex: number;
34
+ /** Whether keyboard navigation is active */
35
+ isNavigating: boolean;
36
+ }
37
+
38
+ export interface UseKeyboardNavigationReturn {
39
+ /** Current navigation state */
40
+ state: KeyboardNavigationState;
41
+ /** Focus a specific cell */
42
+ focusCell: (rowIndex: number, columnIndex: number) => void;
43
+ /** Move focus to next cell */
44
+ focusNext: () => void;
45
+ /** Move focus to previous cell */
46
+ focusPrevious: () => void;
47
+ /** Move focus up one row */
48
+ focusUp: () => void;
49
+ /** Move focus down one row */
50
+ focusDown: () => void;
51
+ /** Move focus to first cell in row */
52
+ focusRowStart: () => void;
53
+ /** Move focus to last cell in row */
54
+ focusRowEnd: () => void;
55
+ /** Move focus to first row */
56
+ focusTableStart: () => void;
57
+ /** Move focus to last row */
58
+ focusTableEnd: () => void;
59
+ /** Get tabindex for a cell */
60
+ getCellTabIndex: (rowIndex: number, columnIndex: number) => number;
61
+ /** Get keyboard event handlers for a cell */
62
+ getCellKeyboardHandlers: (rowIndex: number, columnIndex: number) => {
63
+ onKeyDown: (event: React.KeyboardEvent) => void;
64
+ onFocus: (event: React.FocusEvent) => void;
65
+ onBlur: (event: React.FocusEvent) => void;
66
+ };
67
+ /** Get keyboard event handlers for headers */
68
+ getHeaderKeyboardHandlers: (columnIndex: number, onSort?: () => void) => {
69
+ onKeyDown: (event: React.KeyboardEvent) => void;
70
+ onFocus: (event: React.FocusEvent) => void;
71
+ };
72
+ /** Reset focus state */
73
+ resetFocus: () => void;
74
+ /** Store focus for restoration */
75
+ storeFocus: () => void;
76
+ /** Restore previously stored focus */
77
+ restoreFocus: () => void;
78
+ }
79
+
80
+ /**
81
+ * Hook for managing keyboard navigation in DataTable
82
+ */
83
+ export function useKeyboardNavigation(
84
+ rowCount: number,
85
+ columnCount: number,
86
+ options: KeyboardNavigationOptions = {}
87
+ ): UseKeyboardNavigationReturn {
88
+ const {
89
+ enabled = true,
90
+ announceNavigation = true,
91
+ supportsColumnReorder = false,
92
+ supportsColumnResize = false,
93
+ onFocusChange,
94
+ tableRef: externalTableRef,
95
+ } = options;
96
+
97
+ // Navigation state
98
+ const [state, setState] = useState<KeyboardNavigationState>({
99
+ focusedRowIndex: 0,
100
+ focusedColumnIndex: 0,
101
+ isNavigating: false,
102
+ });
103
+
104
+ // Refs for focus management
105
+ const internalTableRef = useRef<HTMLTableElement>(null);
106
+ const tableRef = externalTableRef || internalTableRef;
107
+ const storedFocusRef = useRef<{ rowIndex: number; columnIndex: number } | null>(null);
108
+ const navigationTimeoutRef = useRef<NodeJS.Timeout>();
109
+
110
+ // Helper to get cell element
111
+ const getCellElement = useCallback((rowIndex: number, columnIndex: number): HTMLElement | null => {
112
+ if (!tableRef.current) return null;
113
+
114
+ const tbody = tableRef.current.querySelector('tbody');
115
+ if (!tbody) return null;
116
+
117
+ const rows = tbody.querySelectorAll('tr[role="row"]');
118
+ const row = rows[rowIndex];
119
+ if (!row) return null;
120
+
121
+ const cells = row.querySelectorAll('td[role="cell"], th[role="columnheader"]');
122
+ return cells[columnIndex] as HTMLElement || null;
123
+ }, []);
124
+
125
+ // Helper to get header element
126
+ const getHeaderElement = useCallback((columnIndex: number): HTMLElement | null => {
127
+ if (!tableRef.current) return null;
128
+
129
+ const thead = tableRef.current.querySelector('thead');
130
+ if (!thead) return null;
131
+
132
+ const headerRow = thead.querySelector('tr[role="row"]');
133
+ if (!headerRow) return null;
134
+
135
+ const headers = headerRow.querySelectorAll('th[role="columnheader"]');
136
+ return headers[columnIndex] as HTMLElement || null;
137
+ }, []);
138
+
139
+ // Focus a specific cell
140
+ const focusCell = useCallback((rowIndex: number, columnIndex: number) => {
141
+ if (!enabled) return;
142
+
143
+ // Clamp values to valid range
144
+ const clampedRowIndex = Math.max(0, Math.min(rowIndex, rowCount - 1));
145
+ const clampedColumnIndex = Math.max(0, Math.min(columnIndex, columnCount - 1));
146
+
147
+ setState(prev => ({
148
+ ...prev,
149
+ focusedRowIndex: clampedRowIndex,
150
+ focusedColumnIndex: clampedColumnIndex,
151
+ isNavigating: true,
152
+ }));
153
+
154
+ // Focus the actual element
155
+ const cellElement = getCellElement(clampedRowIndex, clampedColumnIndex);
156
+ if (cellElement) {
157
+ cellElement.focus();
158
+ }
159
+
160
+ // Notify callback
161
+ onFocusChange?.(clampedRowIndex, clampedColumnIndex);
162
+
163
+ // Announce navigation if enabled
164
+ if (announceNavigation) {
165
+ announce(`Row ${clampedRowIndex + 1}, Column ${clampedColumnIndex + 1}`);
166
+ }
167
+ }, [enabled, rowCount, columnCount, getCellElement, onFocusChange, announceNavigation]);
168
+
169
+ // Navigation functions
170
+ const focusNext = useCallback(() => {
171
+ const { focusedRowIndex, focusedColumnIndex } = state;
172
+ if (focusedColumnIndex < columnCount - 1) {
173
+ focusCell(focusedRowIndex, focusedColumnIndex + 1);
174
+ } else if (focusedRowIndex < rowCount - 1) {
175
+ focusCell(focusedRowIndex + 1, 0);
176
+ }
177
+ }, [state, columnCount, rowCount, focusCell]);
178
+
179
+ const focusPrevious = useCallback(() => {
180
+ const { focusedRowIndex, focusedColumnIndex } = state;
181
+ if (focusedColumnIndex > 0) {
182
+ focusCell(focusedRowIndex, focusedColumnIndex - 1);
183
+ } else if (focusedRowIndex > 0) {
184
+ focusCell(focusedRowIndex - 1, columnCount - 1);
185
+ }
186
+ }, [state, columnCount, focusCell]);
187
+
188
+ const focusUp = useCallback(() => {
189
+ const { focusedRowIndex, focusedColumnIndex } = state;
190
+ if (focusedRowIndex > 0) {
191
+ focusCell(focusedRowIndex - 1, focusedColumnIndex);
192
+ }
193
+ }, [state, focusCell]);
194
+
195
+ const focusDown = useCallback(() => {
196
+ const { focusedRowIndex, focusedColumnIndex } = state;
197
+ if (focusedRowIndex < rowCount - 1) {
198
+ focusCell(focusedRowIndex + 1, focusedColumnIndex);
199
+ }
200
+ }, [state, rowCount, focusCell]);
201
+
202
+ const focusRowStart = useCallback(() => {
203
+ const { focusedRowIndex } = state;
204
+ focusCell(focusedRowIndex, 0);
205
+ }, [state, focusCell]);
206
+
207
+ const focusRowEnd = useCallback(() => {
208
+ const { focusedRowIndex } = state;
209
+ focusCell(focusedRowIndex, columnCount - 1);
210
+ }, [state, columnCount, focusCell]);
211
+
212
+ const focusTableStart = useCallback(() => {
213
+ focusCell(0, 0);
214
+ }, [focusCell]);
215
+
216
+ const focusTableEnd = useCallback(() => {
217
+ focusCell(rowCount - 1, columnCount - 1);
218
+ }, [rowCount, columnCount, focusCell]);
219
+
220
+ // Get tabindex for roving tabindex pattern
221
+ const getCellTabIndex = useCallback((rowIndex: number, columnIndex: number): number => {
222
+ if (!enabled) return -1;
223
+
224
+ // Only the focused cell should be tabbable
225
+ return (state.focusedRowIndex === rowIndex && state.focusedColumnIndex === columnIndex) ? 0 : -1;
226
+ }, [enabled, state.focusedRowIndex, state.focusedColumnIndex]);
227
+
228
+ // Cell keyboard handlers
229
+ const getCellKeyboardHandlers = useCallback((rowIndex: number, columnIndex: number) => {
230
+ const onKeyDown = (event: React.KeyboardEvent) => {
231
+ if (!enabled) return;
232
+
233
+ switch (event.key) {
234
+ case 'ArrowRight':
235
+ event.preventDefault();
236
+ if (event.ctrlKey || event.metaKey) {
237
+ focusRowEnd();
238
+ } else {
239
+ focusNext();
240
+ }
241
+ break;
242
+
243
+ case 'ArrowLeft':
244
+ event.preventDefault();
245
+ if (event.ctrlKey || event.metaKey) {
246
+ focusRowStart();
247
+ } else {
248
+ focusPrevious();
249
+ }
250
+ break;
251
+
252
+ case 'ArrowDown':
253
+ event.preventDefault();
254
+ if (event.ctrlKey || event.metaKey) {
255
+ focusTableEnd();
256
+ } else {
257
+ focusDown();
258
+ }
259
+ break;
260
+
261
+ case 'ArrowUp':
262
+ event.preventDefault();
263
+ if (event.ctrlKey || event.metaKey) {
264
+ focusTableStart();
265
+ } else {
266
+ focusUp();
267
+ }
268
+ break;
269
+
270
+ case 'Home':
271
+ event.preventDefault();
272
+ if (event.ctrlKey || event.metaKey) {
273
+ focusTableStart();
274
+ } else {
275
+ focusRowStart();
276
+ }
277
+ break;
278
+
279
+ case 'End':
280
+ event.preventDefault();
281
+ if (event.ctrlKey || event.metaKey) {
282
+ focusTableEnd();
283
+ } else {
284
+ focusRowEnd();
285
+ }
286
+ break;
287
+
288
+ case 'Tab':
289
+ // Let Tab work normally for accessibility
290
+ break;
291
+
292
+ default:
293
+ // Don't prevent default for other keys
294
+ break;
295
+ }
296
+ };
297
+
298
+ const onFocus = (event: React.FocusEvent) => {
299
+ setState(prev => ({
300
+ ...prev,
301
+ focusedRowIndex: rowIndex,
302
+ focusedColumnIndex: columnIndex,
303
+ isNavigating: true,
304
+ }));
305
+
306
+ onFocusChange?.(rowIndex, columnIndex);
307
+ };
308
+
309
+ const onBlur = (event: React.FocusEvent) => {
310
+ // Clear navigation state after a delay to allow for focus transitions
311
+ if (navigationTimeoutRef.current) {
312
+ clearTimeout(navigationTimeoutRef.current);
313
+ }
314
+
315
+ navigationTimeoutRef.current = setTimeout(() => {
316
+ setState(prev => ({
317
+ ...prev,
318
+ isNavigating: false,
319
+ }));
320
+ }, 100);
321
+ };
322
+
323
+ return { onKeyDown, onFocus, onBlur };
324
+ }, [enabled, focusNext, focusPrevious, focusUp, focusDown, focusRowStart, focusRowEnd, focusTableStart, focusTableEnd, onFocusChange]);
325
+
326
+ // Header keyboard handlers
327
+ const getHeaderKeyboardHandlers = useCallback((columnIndex: number, onSort?: () => void) => {
328
+ const onKeyDown = (event: React.KeyboardEvent) => {
329
+ if (!enabled) return;
330
+
331
+ switch (event.key) {
332
+ case 'Enter':
333
+ case ' ':
334
+ event.preventDefault();
335
+ onSort?.();
336
+ break;
337
+
338
+ case 'ArrowRight':
339
+ event.preventDefault();
340
+ const nextHeader = getHeaderElement(columnIndex + 1);
341
+ if (nextHeader) {
342
+ nextHeader.focus();
343
+ }
344
+ break;
345
+
346
+ case 'ArrowLeft':
347
+ event.preventDefault();
348
+ const prevHeader = getHeaderElement(columnIndex - 1);
349
+ if (prevHeader) {
350
+ prevHeader.focus();
351
+ }
352
+ break;
353
+
354
+ case 'Home':
355
+ event.preventDefault();
356
+ const firstHeader = getHeaderElement(0);
357
+ if (firstHeader) {
358
+ firstHeader.focus();
359
+ }
360
+ break;
361
+
362
+ case 'End':
363
+ event.preventDefault();
364
+ const lastHeader = getHeaderElement(columnCount - 1);
365
+ if (lastHeader) {
366
+ lastHeader.focus();
367
+ }
368
+ break;
369
+
370
+ // Disable unsupported keyboard operations
371
+ case 'r':
372
+ if (!supportsColumnReorder && (event.ctrlKey || event.metaKey)) {
373
+ event.preventDefault();
374
+ announce('Column reordering is not supported');
375
+ }
376
+ break;
377
+
378
+ case '=':
379
+ case '+':
380
+ case '-':
381
+ if (!supportsColumnResize && (event.ctrlKey || event.metaKey)) {
382
+ event.preventDefault();
383
+ announce('Column resizing is not supported');
384
+ }
385
+ break;
386
+ }
387
+ };
388
+
389
+ const onFocus = (event: React.FocusEvent) => {
390
+ // Headers don't participate in cell navigation state
391
+ };
392
+
393
+ return { onKeyDown, onFocus };
394
+ }, [enabled, getHeaderElement, columnCount, supportsColumnReorder, supportsColumnResize]);
395
+
396
+ // Focus management functions
397
+ const resetFocus = useCallback(() => {
398
+ setState({
399
+ focusedRowIndex: 0,
400
+ focusedColumnIndex: 0,
401
+ isNavigating: false,
402
+ });
403
+ }, []);
404
+
405
+ const storeFocus = useCallback(() => {
406
+ storedFocusRef.current = {
407
+ rowIndex: state.focusedRowIndex,
408
+ columnIndex: state.focusedColumnIndex,
409
+ };
410
+ }, [state.focusedRowIndex, state.focusedColumnIndex]);
411
+
412
+ const restoreFocus = useCallback(() => {
413
+ if (storedFocusRef.current) {
414
+ const { rowIndex, columnIndex } = storedFocusRef.current;
415
+ focusCell(rowIndex, columnIndex);
416
+ storedFocusRef.current = null;
417
+ }
418
+ }, [focusCell]);
419
+
420
+ // Cleanup on unmount
421
+ useEffect(() => {
422
+ return () => {
423
+ if (navigationTimeoutRef.current) {
424
+ clearTimeout(navigationTimeoutRef.current);
425
+ }
426
+ };
427
+ }, []);
428
+
429
+ return {
430
+ state,
431
+ focusCell,
432
+ focusNext,
433
+ focusPrevious,
434
+ focusUp,
435
+ focusDown,
436
+ focusRowStart,
437
+ focusRowEnd,
438
+ focusTableStart,
439
+ focusTableEnd,
440
+ getCellTabIndex,
441
+ getCellKeyboardHandlers,
442
+ getHeaderKeyboardHandlers,
443
+ resetFocus,
444
+ storeFocus,
445
+ restoreFocus,
446
+ };
447
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @file Server-side data coordination hook
3
+ */
4
+
5
+ import { useCallback, useEffect } from 'react';
6
+ import type {
7
+ DataRecord,
8
+ PaginationMode,
9
+ ServerSideConfig,
10
+ ServerSideParams,
11
+ } from '../types';
12
+ import type {
13
+ SortingState,
14
+ ColumnFiltersState,
15
+ GroupingState,
16
+ PaginationState,
17
+ } from '@tanstack/react-table';
18
+
19
+ export interface UseServerSideDataEffectParams<TData extends DataRecord> {
20
+ finalPaginationMode: PaginationMode;
21
+ serverSide?: ServerSideConfig<TData>;
22
+ pagination: PaginationState;
23
+ sorting: SortingState;
24
+ columnFilters: ColumnFiltersState;
25
+ grouping: GroupingState;
26
+ searchQuery: string;
27
+ tableDataLength: number;
28
+ fetchServerData: (params: ServerSideParams) => Promise<void>;
29
+ cleanup?: () => void;
30
+ }
31
+
32
+ export function useServerSideDataEffect<TData extends DataRecord>({
33
+ finalPaginationMode,
34
+ serverSide,
35
+ pagination,
36
+ sorting,
37
+ columnFilters,
38
+ grouping,
39
+ searchQuery,
40
+ tableDataLength,
41
+ fetchServerData,
42
+ cleanup,
43
+ }: UseServerSideDataEffectParams<TData>) {
44
+ const handleServerSideChange = useCallback(async () => {
45
+ if (finalPaginationMode !== 'server' || !serverSide) {
46
+ return;
47
+ }
48
+
49
+ const params: ServerSideParams = {
50
+ pageIndex: pagination.pageIndex,
51
+ pageSize: pagination.pageSize,
52
+ sorting,
53
+ columnFilters,
54
+ globalFilter: searchQuery,
55
+ grouping,
56
+ };
57
+
58
+ await fetchServerData(params);
59
+ }, [
60
+ finalPaginationMode,
61
+ serverSide,
62
+ pagination.pageIndex,
63
+ pagination.pageSize,
64
+ sorting,
65
+ columnFilters,
66
+ searchQuery,
67
+ grouping,
68
+ fetchServerData,
69
+ ]);
70
+
71
+ useEffect(() => {
72
+ if (finalPaginationMode !== 'server' || !serverSide) {
73
+ return;
74
+ }
75
+
76
+ if (tableDataLength > 0) {
77
+ return;
78
+ }
79
+
80
+ handleServerSideChange();
81
+ }, [
82
+ finalPaginationMode,
83
+ serverSide,
84
+ tableDataLength,
85
+ handleServerSideChange,
86
+ ]);
87
+
88
+ useEffect(() => () => {
89
+ cleanup?.();
90
+ }, [cleanup]);
91
+
92
+ return handleServerSideChange;
93
+ }
94
+
@@ -12,9 +12,9 @@
12
12
  import React, { useMemo } from 'react';
13
13
  import { Checkbox } from '../../Checkbox/Checkbox';
14
14
  import { ColumnFactory } from '../core/ColumnFactory';
15
- import type {
16
- DataTableFeatureConfig,
17
- DataTableColumn,
15
+ import type {
16
+ NormalizedDataTableFeatureConfig,
17
+ DataTableColumn,
18
18
  DataTableAction,
19
19
  DataRecord
20
20
  } from '../types';
@@ -23,7 +23,7 @@ import type { HeaderContext, CellContext } from '@tanstack/react-table';
23
23
 
24
24
  export interface UseTableColumnsOptions<TData extends DataRecord> {
25
25
  columns: DataTableColumn<TData>[];
26
- features: DataTableFeatureConfig;
26
+ features: NormalizedDataTableFeatureConfig;
27
27
  effectiveActions: DataTableAction<TData>[];
28
28
  columnOrder: string[];
29
29
  }
@@ -65,14 +65,14 @@ export function useTableColumns<TData extends DataRecord>({
65
65
  const isSomeSelected = table.getIsSomePageRowsSelected();
66
66
  return React.createElement(Checkbox, {
67
67
  checked: isAllSelected ? true : isSomeSelected ? 'indeterminate' : false,
68
- onCheckedChange: (value: any) => table.toggleAllPageRowsSelected(!!value),
68
+ onCheckedChange: (value: boolean | 'indeterminate') => table.toggleAllPageRowsSelected(!!value),
69
69
  'aria-label': "Select all"
70
70
  });
71
71
  },
72
72
  cell: ({ row }: CellContext<TData, unknown>) => {
73
73
  return React.createElement(Checkbox, {
74
74
  checked: row.getIsSelected(),
75
- onCheckedChange: (value: any) => row.toggleSelected(!!value),
75
+ onCheckedChange: (value: boolean | 'indeterminate') => row.toggleSelected(!!value),
76
76
  'aria-label': "Select row"
77
77
  });
78
78
  },
@@ -89,7 +89,10 @@ export function useTableColumns<TData extends DataRecord>({
89
89
  const actionsColumn: ColumnDef<TData> | null = effectiveActions.length > 0 ?
90
90
  ColumnFactory.createActionColumn(effectiveActions, {
91
91
  header: 'Actions',
92
- size: 120,
92
+ size: 1, // Shrink to fit content
93
+ minSize: 0,
94
+ maxSize: 0,
95
+ meta: { align: 'right' },
93
96
  }) : null;
94
97
 
95
98
  // Build final columns array respecting columnOrder