@jmruthers/pace-core 0.5.135 → 0.5.137

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (544) hide show
  1. package/dist/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
  2. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
  4. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  5. package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
  6. package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
  7. package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
  8. package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
  9. package/dist/chunk-22WKWKRX.js.map +1 -0
  10. package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
  11. package/dist/chunk-4C7EXCAR.js.map +1 -0
  12. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  13. package/dist/chunk-56XJ3TU6.js.map +1 -0
  14. package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
  15. package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
  16. package/dist/chunk-7QCC6MCP.js.map +1 -0
  17. package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
  18. package/dist/chunk-ANBQRTPX.js.map +1 -0
  19. package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
  20. package/dist/chunk-BCIBECNB.js.map +1 -0
  21. package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
  22. package/dist/chunk-BESYRHQM.js.map +1 -0
  23. package/dist/chunk-BJPBT3CU.js +21 -0
  24. package/dist/chunk-BJPBT3CU.js.map +1 -0
  25. package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
  26. package/dist/chunk-BLCXZEYF.js.map +1 -0
  27. package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  28. package/dist/chunk-BVYWGZVV.js.map +1 -0
  29. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  30. package/dist/chunk-ERISIBYU.js.map +1 -0
  31. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  32. package/dist/chunk-FMUCXFII.js.map +1 -0
  33. package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
  34. package/dist/chunk-HAWZXGR2.js.map +1 -0
  35. package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
  36. package/dist/chunk-JISYG63F.js +70 -0
  37. package/dist/chunk-JISYG63F.js.map +1 -0
  38. package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
  39. package/dist/chunk-KYRHUBIU.js.map +1 -0
  40. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  41. package/dist/chunk-LS353YLY.js.map +1 -0
  42. package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
  43. package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
  44. package/dist/chunk-OWAG3GSU.js +58 -0
  45. package/dist/chunk-OWAG3GSU.js.map +1 -0
  46. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  47. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  48. package/dist/chunk-S5OFRT4M.js +94 -0
  49. package/dist/chunk-S5OFRT4M.js.map +1 -0
  50. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  51. package/dist/chunk-SBVILCCA.js.map +1 -0
  52. package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
  53. package/dist/chunk-T6JN6LH6.js.map +1 -0
  54. package/dist/chunk-XDNLUEXI.js +138 -0
  55. package/dist/chunk-XDNLUEXI.js.map +1 -0
  56. package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
  57. package/dist/chunk-YCWDTTUK.js.map +1 -0
  58. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  59. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  60. package/dist/components.d.ts +7 -287
  61. package/dist/components.js +27 -157
  62. package/dist/components.js.map +1 -1
  63. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  64. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  65. package/dist/hooks.d.ts +3 -3
  66. package/dist/hooks.js +21 -16
  67. package/dist/hooks.js.map +1 -1
  68. package/dist/index.d.ts +101 -9
  69. package/dist/index.js +44 -31
  70. package/dist/index.js.map +1 -1
  71. package/dist/providers.d.ts +1 -1
  72. package/dist/providers.js +4 -4
  73. package/dist/rbac/index.js +12 -12
  74. package/dist/schema-DTDZQe2u.d.ts +28 -0
  75. package/dist/styles/index.js +2 -1
  76. package/dist/theming/runtime.d.ts +2 -19
  77. package/dist/theming/runtime.js +2 -1
  78. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  79. package/dist/types.d.ts +153 -4
  80. package/dist/types.js +51 -16
  81. package/dist/types.js.map +1 -1
  82. package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
  83. package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
  84. package/dist/utils.d.ts +221 -173
  85. package/dist/utils.js +185 -225
  86. package/dist/utils.js.map +1 -1
  87. package/dist/validation.d.ts +24 -115
  88. package/dist/validation.js +19 -474
  89. package/dist/validation.js.map +1 -1
  90. package/docs/api/classes/ColumnFactory.md +1 -1
  91. package/docs/api/classes/ErrorBoundary.md +6 -6
  92. package/docs/api/classes/InvalidScopeError.md +1 -1
  93. package/docs/api/classes/MissingUserContextError.md +1 -1
  94. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  95. package/docs/api/classes/PermissionDeniedError.md +1 -1
  96. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  97. package/docs/api/classes/RBACAuditManager.md +6 -6
  98. package/docs/api/classes/RBACCache.md +1 -1
  99. package/docs/api/classes/RBACEngine.md +7 -7
  100. package/docs/api/classes/RBACError.md +1 -1
  101. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  102. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  103. package/docs/api/classes/StorageUtils.md +1 -1
  104. package/docs/api/enums/FileCategory.md +1 -1
  105. package/docs/api/interfaces/AggregateConfig.md +4 -4
  106. package/docs/api/interfaces/BadgeProps.md +27 -0
  107. package/docs/api/interfaces/ButtonProps.md +1 -1
  108. package/docs/api/interfaces/CardProps.md +1 -1
  109. package/docs/api/interfaces/ColorPalette.md +1 -1
  110. package/docs/api/interfaces/ColorShade.md +29 -4
  111. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  112. package/docs/api/interfaces/DataRecord.md +1 -1
  113. package/docs/api/interfaces/DataTableAction.md +18 -18
  114. package/docs/api/interfaces/DataTableColumn.md +61 -1
  115. package/docs/api/interfaces/DataTableProps.md +1 -1
  116. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  117. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  118. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
  119. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  120. package/docs/api/interfaces/EventLogoProps.md +152 -0
  121. package/docs/api/interfaces/ExportColumn.md +1 -1
  122. package/docs/api/interfaces/ExportOptions.md +8 -8
  123. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  124. package/docs/api/interfaces/FileMetadata.md +1 -1
  125. package/docs/api/interfaces/FileReference.md +1 -1
  126. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  127. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  128. package/docs/api/interfaces/FileUploadProps.md +1 -1
  129. package/docs/api/interfaces/FooterProps.md +1 -1
  130. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  131. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  132. package/docs/api/interfaces/InputProps.md +1 -1
  133. package/docs/api/interfaces/LabelProps.md +1 -1
  134. package/docs/api/interfaces/LoginFormProps.md +1 -1
  135. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  136. package/docs/api/interfaces/NavigationContextType.md +9 -9
  137. package/docs/api/interfaces/NavigationGuardProps.md +10 -10
  138. package/docs/api/interfaces/NavigationItem.md +1 -1
  139. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  140. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  141. package/docs/api/interfaces/Organisation.md +1 -1
  142. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  143. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  144. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  145. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  146. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  147. package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
  148. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  149. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  150. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  151. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  152. package/docs/api/interfaces/PaletteData.md +4 -4
  153. package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
  154. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  155. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  156. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  157. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  158. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  159. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  160. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  161. package/docs/api/interfaces/RBACConfig.md +1 -1
  162. package/docs/api/interfaces/RBACLogger.md +1 -1
  163. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  164. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  165. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  166. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  167. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  168. package/docs/api/interfaces/RouteConfig.md +10 -10
  169. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  170. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  171. package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
  172. package/docs/api/interfaces/StorageConfig.md +1 -1
  173. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  174. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  175. package/docs/api/interfaces/StorageListOptions.md +1 -1
  176. package/docs/api/interfaces/StorageListResult.md +1 -1
  177. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  178. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  179. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  180. package/docs/api/interfaces/StyleImport.md +1 -1
  181. package/docs/api/interfaces/SwitchProps.md +1 -1
  182. package/docs/api/interfaces/ToastActionElement.md +1 -1
  183. package/docs/api/interfaces/ToastProps.md +1 -1
  184. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  185. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  186. package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
  187. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  188. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  189. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  190. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  191. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
  192. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  193. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  194. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  195. package/docs/api/interfaces/UserEventAccess.md +11 -11
  196. package/docs/api/interfaces/UserMenuProps.md +1 -1
  197. package/docs/api/interfaces/UserProfile.md +1 -1
  198. package/docs/api/modules.md +591 -220
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -3
  201. package/docs/implementation-guides/data-tables.md +277 -13
  202. package/docs/implementation-guides/forms.md +1 -16
  203. package/docs/implementation-guides/permission-enforcement.md +8 -2
  204. package/docs/styles/README.md +0 -2
  205. package/examples/README.md +30 -14
  206. package/examples/STRUCTURE.md +125 -0
  207. package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
  208. package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
  209. package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
  210. package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
  211. package/examples/components 2/DataTable/index.ts +13 -0
  212. package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
  213. package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
  214. package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
  215. package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
  216. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
  217. package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
  218. package/examples/components 2/Dialog/index.ts +15 -0
  219. package/examples/components 2/index.ts +11 -0
  220. package/examples/features/index.ts +12 -0
  221. package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
  222. package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
  223. package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
  224. package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
  225. package/examples/features/public-pages/index.ts +14 -0
  226. package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
  227. package/examples/features/rbac/EventBasedApp.tsx +239 -0
  228. package/examples/features/rbac/PermissionExample.tsx +151 -0
  229. package/examples/features/rbac/index.ts +13 -0
  230. package/examples/index.ts +11 -3
  231. package/package.json +30 -19
  232. package/src/__tests__/TEST_STANDARD.md +92 -0
  233. package/src/components/Alert/Alert.tsx +1 -1
  234. package/src/components/Avatar/Avatar.tsx +1 -1
  235. package/src/components/Badge/Badge.test.tsx +314 -0
  236. package/src/components/Badge/Badge.tsx +304 -0
  237. package/src/components/Badge/index.ts +3 -0
  238. package/src/components/Button/Button.tsx +1 -1
  239. package/src/components/Card/Card.tsx +1 -1
  240. package/src/components/Checkbox/Checkbox.tsx +1 -1
  241. package/src/components/DataTable/DataTable.test.tsx +1 -1
  242. package/src/components/DataTable/DataTable.tsx +1 -30
  243. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  244. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
  245. package/src/components/DataTable/__tests__/styles.test.ts +3 -3
  246. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  247. package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
  248. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  249. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  250. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  252. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  253. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  254. package/src/components/DataTable/components/FilterRow.tsx +9 -3
  255. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  256. package/src/components/DataTable/components/PaginationControls.tsx +2 -1
  257. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  258. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  259. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
  260. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  261. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
  262. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  263. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  264. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
  265. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  266. package/src/components/DataTable/core/ActionManager.ts +235 -0
  267. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  268. package/src/components/DataTable/core/DataManager.ts +188 -0
  269. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  270. package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
  271. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  272. package/src/components/DataTable/core/StateManager.ts +311 -0
  273. package/src/components/DataTable/core/interfaces.ts +338 -0
  274. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  275. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  276. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  277. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  278. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  280. package/src/components/DataTable/index.ts +4 -0
  281. package/src/components/DataTable/styles.ts +28 -7
  282. package/src/components/DataTable/types.ts +13 -0
  283. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
  284. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  285. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  286. package/src/components/DataTable/utils/columnUtils.ts +40 -0
  287. package/src/components/DataTable/utils/debugTools.ts +609 -0
  288. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  289. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  290. package/src/components/DataTable/utils/index.ts +2 -0
  291. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  292. package/src/components/Dialog/Dialog.tsx +2 -2
  293. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
  294. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  295. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  296. package/src/components/EventSelector/EventSelector.tsx +3 -2
  297. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  298. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  299. package/src/components/FileUpload/FileUpload.tsx +2 -2
  300. package/src/components/Footer/Footer.test.tsx +1 -1
  301. package/src/components/Footer/Footer.tsx +1 -1
  302. package/src/components/Form/Form.test.tsx +5 -510
  303. package/src/components/Form/Form.tsx +1 -1
  304. package/src/components/Form/FormField.tsx +1 -1
  305. package/src/components/Form/index.ts +0 -12
  306. package/src/components/Header/Header.tsx +1 -1
  307. package/src/components/Input/Input.tsx +1 -1
  308. package/src/components/Label/Label.tsx +1 -1
  309. package/src/components/LoginForm/LoginForm.test.tsx +1 -1
  310. package/src/components/LoginForm/LoginForm.tsx +1 -1
  311. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  312. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  313. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  314. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  315. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  316. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
  317. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  318. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  319. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  320. package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
  321. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  322. package/src/components/PasswordReset/index.ts +0 -2
  323. package/src/components/Progress/Progress.tsx +1 -1
  324. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  325. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  326. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  327. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  328. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  329. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  330. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  331. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  332. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  333. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
  334. package/src/components/PublicLayout/index.ts +4 -2
  335. package/src/components/Select/Select.test.tsx +1 -1
  336. package/src/components/Select/Select.tsx +21 -9
  337. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  338. package/src/components/SessionRestorationLoader/index.ts +3 -0
  339. package/src/components/Switch/Switch.tsx +1 -1
  340. package/src/components/Table/Table.tsx +1 -1
  341. package/src/components/Table/__tests__/Table.test.tsx +1 -1
  342. package/src/components/Toast/Toast.tsx +1 -1
  343. package/src/components/Tooltip/Tooltip.tsx +1 -1
  344. package/src/components/index.ts +7 -10
  345. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  346. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  347. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  348. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  349. package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
  350. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  351. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  352. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  353. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  354. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  355. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  356. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  357. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  358. package/src/hooks/public/usePublicEvent.ts +7 -6
  359. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  360. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  361. package/src/hooks/useComponentPerformance.ts +4 -1
  362. package/src/hooks/useDataTablePerformance.ts +4 -3
  363. package/src/hooks/useEventTheme.test.ts +18 -5
  364. package/src/hooks/useEventTheme.ts +4 -1
  365. package/src/hooks/useEvents.ts +2 -0
  366. package/src/hooks/useFileDisplay.ts +9 -8
  367. package/src/hooks/useFileReference.ts +4 -1
  368. package/src/hooks/useFileUrl.ts +4 -1
  369. package/src/hooks/useInactivityTracker.ts +5 -4
  370. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  371. package/src/hooks/useOrganisationSecurity.ts +8 -7
  372. package/src/hooks/usePerformanceMonitor.ts +6 -3
  373. package/src/hooks/usePermissionCache.ts +13 -6
  374. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  375. package/src/hooks/useSecureDataAccess.ts +9 -8
  376. package/src/hooks/useSessionRestoration.ts +4 -1
  377. package/src/hooks/useStorage.ts +4 -1
  378. package/src/index.ts +20 -7
  379. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  380. package/src/providers/services/EventServiceProvider.tsx +2 -1
  381. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  382. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  383. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  384. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  385. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  386. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  387. package/src/rbac/api.ts +5 -2
  388. package/src/rbac/audit-enhanced.ts +6 -6
  389. package/src/rbac/audit.test.ts +60 -38
  390. package/src/rbac/audit.ts +8 -8
  391. package/src/rbac/cache-invalidation.ts +7 -4
  392. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  393. package/src/rbac/components/NavigationGuard.tsx +7 -3
  394. package/src/rbac/components/NavigationProvider.tsx +6 -3
  395. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  396. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  397. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  398. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  399. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  400. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  401. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  402. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  403. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  404. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  405. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  406. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  407. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  408. package/src/rbac/engine.ts +15 -7
  409. package/src/rbac/hooks/usePermissions.ts +7 -3
  410. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  411. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  412. package/src/rbac/permissions.ts +5 -2
  413. package/src/rbac/security.test.ts +27 -16
  414. package/src/rbac/security.ts +5 -4
  415. package/src/services/AuthService.ts +22 -21
  416. package/src/services/EventService.ts +12 -12
  417. package/src/services/InactivityService.ts +5 -4
  418. package/src/services/OrganisationService.ts +26 -25
  419. package/src/services/__tests__/AuthService.test.ts +51 -19
  420. package/src/services/__tests__/EventService.test.ts +37 -5
  421. package/src/services/__tests__/InactivityService.test.ts +38 -4
  422. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  423. package/src/services/base/BaseService.ts +3 -1
  424. package/src/styles/core.css +3 -0
  425. package/src/theming/__tests__/runtime.test.ts +21 -12
  426. package/src/theming/parseEventColours.ts +5 -19
  427. package/src/theming/runtime.ts +8 -4
  428. package/src/types/validation.ts +2 -29
  429. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  430. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  431. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  432. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  433. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  434. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  435. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  436. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  437. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  438. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  439. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  440. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  441. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  442. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  443. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  444. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  445. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  446. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  447. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  448. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  449. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  450. package/src/utils/__tests__/security.unit.test.ts +40 -18
  451. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  452. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  453. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  454. package/src/utils/app/appConfig.ts +47 -0
  455. package/src/utils/app/appIdResolver.test.ts +497 -0
  456. package/src/utils/app/appIdResolver.ts +133 -0
  457. package/src/utils/app/appNameResolver.simple.test.ts +212 -0
  458. package/src/utils/app/appNameResolver.test.ts +121 -0
  459. package/src/utils/app/appNameResolver.ts +195 -0
  460. package/src/utils/audit/audit.ts +127 -0
  461. package/src/utils/context/organisationContext.test.ts +322 -0
  462. package/src/utils/context/organisationContext.ts +156 -0
  463. package/src/utils/context/sessionTracking.ts +125 -0
  464. package/src/utils/core/cn.ts +7 -0
  465. package/src/utils/core/debugLogger.ts +67 -0
  466. package/src/utils/core/logger.ts +181 -0
  467. package/src/utils/device/deviceFingerprint.ts +215 -0
  468. package/src/utils/dynamic/dynamicUtils.ts +105 -0
  469. package/src/utils/dynamic/lazyLoad.tsx +44 -0
  470. package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
  471. package/src/utils/file-reference/index.ts +501 -0
  472. package/src/utils/formatting/formatDate.test.ts +237 -0
  473. package/src/utils/formatting/formatting.ts +133 -0
  474. package/src/utils/index.ts +39 -54
  475. package/src/utils/performance/bundleAnalysis.ts +129 -0
  476. package/src/utils/performance/performanceBenchmark.ts +64 -0
  477. package/src/utils/performance/performanceBudgets.ts +110 -0
  478. package/src/utils/permissions/permissionTypes.ts +37 -0
  479. package/src/utils/permissions/permissionUtils.test.ts +393 -0
  480. package/src/utils/permissions/permissionUtils.ts +34 -0
  481. package/src/utils/security/auth-utils.ts +96 -0
  482. package/src/utils/security/secureDataAccess.test.ts +711 -0
  483. package/src/utils/security/secureDataAccess.ts +377 -0
  484. package/src/utils/security/secureErrors.ts +82 -0
  485. package/src/utils/security/secureStorage.ts +244 -0
  486. package/src/utils/security/security.ts +159 -0
  487. package/src/utils/security/securityMonitor.ts +45 -0
  488. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  489. package/src/utils/storage/helpers.ts +15 -8
  490. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
  491. package/src/{validation → utils/validation}/csrf.ts +1 -1
  492. package/src/utils/validation/htmlSanitization.ts +184 -0
  493. package/src/utils/validation/index.ts +79 -0
  494. package/src/utils/validation/sanitization.ts +333 -0
  495. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  496. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  497. package/src/utils/validation/validation.ts +111 -0
  498. package/src/utils/validation/validationUtils.ts +123 -0
  499. package/src/validation/index.ts +3 -34
  500. package/dist/chunk-24MKLB7U.js +0 -81
  501. package/dist/chunk-24MKLB7U.js.map +0 -1
  502. package/dist/chunk-3CG5L6RN.js.map +0 -1
  503. package/dist/chunk-3DBFLLLU.js.map +0 -1
  504. package/dist/chunk-5F3NDPJV.js.map +0 -1
  505. package/dist/chunk-66C4BSAY.js.map +0 -1
  506. package/dist/chunk-BDZUMRBD.js +0 -87
  507. package/dist/chunk-BDZUMRBD.js.map +0 -1
  508. package/dist/chunk-BYXRHAIF.js.map +0 -1
  509. package/dist/chunk-CDQ3PX7L.js +0 -18
  510. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  511. package/dist/chunk-CQZU6TFE.js.map +0 -1
  512. package/dist/chunk-F64FFPOZ.js.map +0 -1
  513. package/dist/chunk-GEVIB2UB.js.map +0 -1
  514. package/dist/chunk-GKHF54DI.js.map +0 -1
  515. package/dist/chunk-GVDR7WNV.js.map +0 -1
  516. package/dist/chunk-HMNOSGVA.js.map +0 -1
  517. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  518. package/dist/chunk-M6DDYFUD.js.map +0 -1
  519. package/dist/chunk-O3NWNXDY.js.map +0 -1
  520. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  521. package/dist/chunk-UJI6WSMD.js.map +0 -1
  522. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  523. package/dist/chunk-WP5I5GLN.js.map +0 -1
  524. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  525. package/dist/validation-DnhrNMju.d.ts +0 -159
  526. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  527. package/src/validation/__tests__/common.unit.test.ts +0 -101
  528. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  529. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  530. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  531. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  532. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  533. package/src/validation/__tests__/user.unit.test.ts +0 -440
  534. package/src/validation/sanitization.ts +0 -96
  535. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
  536. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
  537. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  538. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  539. /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
  540. /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
  541. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  542. /package/src/{validation → utils/validation}/common.ts +0 -0
  543. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  544. /package/src/{validation → utils/validation}/user.ts +0 -0
@@ -0,0 +1,273 @@
1
+ /**
2
+ * @file Grouping Aggregation Example
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/DataTable/Examples
5
+ * @since 0.6.0
6
+ *
7
+ * Complete example demonstrating grouped row aggregation in DataTable.
8
+ * This example shows how to use aggregation functions to display
9
+ * totals and averages in grouped rows, similar to the pace-cake diners table use case.
10
+ */
11
+
12
+ import React from 'react';
13
+ import { DataTable, sum, average, count, type DataTableColumn, type DataRecord } from '../index';
14
+
15
+ // ============================================================================
16
+ // DATA INTERFACE
17
+ // ============================================================================
18
+
19
+ interface DinerData extends DataRecord {
20
+ id: string;
21
+ unit_number: string;
22
+ unit_name: string;
23
+ diet: string;
24
+ youth: number;
25
+ adults: number;
26
+ cost: number;
27
+ [key: string]: unknown; // Index signature to satisfy DataRecord constraint
28
+ }
29
+
30
+ // ============================================================================
31
+ // SAMPLE DATA
32
+ // ============================================================================
33
+
34
+ const dinerData: DinerData[] = [
35
+ { id: '1', unit_number: '101', unit_name: 'Alpha Unit', diet: 'Standard', youth: 10, adults: 5, cost: 100.50 },
36
+ { id: '2', unit_number: '101', unit_name: 'Alpha Unit', diet: 'Standard', youth: 15, adults: 8, cost: 150.75 },
37
+ { id: '3', unit_number: '101', unit_name: 'Alpha Unit', diet: 'Gluten Free', youth: 5, adults: 3, cost: 75.25 },
38
+ { id: '4', unit_number: '102', unit_name: 'Beta Unit', diet: 'Standard', youth: 20, adults: 10, cost: 200.00 },
39
+ { id: '5', unit_number: '102', unit_name: 'Beta Unit', diet: 'Standard', youth: 12, adults: 6, cost: 120.50 },
40
+ { id: '6', unit_number: '102', unit_name: 'Beta Unit', diet: 'Vegetarian', youth: 8, adults: 4, cost: 90.00 },
41
+ { id: '7', unit_number: '103', unit_name: 'Gamma Unit', diet: 'Standard', youth: 18, adults: 9, cost: 180.25 },
42
+ { id: '8', unit_number: '103', unit_name: 'Gamma Unit', diet: 'Gluten Free', youth: 6, adults: 3, cost: 80.50 },
43
+ ];
44
+
45
+ // ============================================================================
46
+ // COLUMN DEFINITIONS
47
+ // ============================================================================
48
+
49
+ const columns: DataTableColumn<DinerData>[] = [
50
+ {
51
+ accessorKey: 'unit_number',
52
+ header: 'Unit #',
53
+ sortable: true,
54
+ enableGrouping: true,
55
+ size: 100,
56
+ },
57
+ {
58
+ accessorKey: 'unit_name',
59
+ header: 'Unit Name',
60
+ sortable: true,
61
+ enableGrouping: true,
62
+ size: 150,
63
+ },
64
+ {
65
+ accessorKey: 'diet',
66
+ header: 'Diet',
67
+ sortable: true,
68
+ enableGrouping: true,
69
+ size: 120,
70
+ cell: ({ row }: { row: { original: DinerData } }) => (
71
+ <span className="px-2 py-1 rounded text-xs font-medium bg-main-100 text-main-800 border border-main-300">
72
+ {row.original.diet}
73
+ </span>
74
+ ),
75
+ },
76
+ {
77
+ accessorKey: 'youth',
78
+ header: 'Youth',
79
+ sortable: true,
80
+ fieldType: 'number',
81
+ size: 100,
82
+ aggregateFn: sum('youth'),
83
+ aggregateCell: (value: any) => (
84
+ <div className="text-right font-semibold">
85
+ {typeof value === 'number' ? value.toLocaleString() : '0'}
86
+ </div>
87
+ ),
88
+ cell: ({ row }: { row: { original: DinerData } }) => (
89
+ <div className="text-right">
90
+ {row.original.youth.toLocaleString()}
91
+ </div>
92
+ ),
93
+ },
94
+ {
95
+ accessorKey: 'adults',
96
+ header: 'Adults',
97
+ sortable: true,
98
+ fieldType: 'number',
99
+ size: 100,
100
+ aggregateFn: sum('adults'),
101
+ aggregateCell: (value: any) => (
102
+ <div className="text-right font-semibold">
103
+ {typeof value === 'number' ? value.toLocaleString() : '0'}
104
+ </div>
105
+ ),
106
+ cell: ({ row }: { row: { original: DinerData } }) => (
107
+ <div className="text-right">
108
+ {row.original.adults.toLocaleString()}
109
+ </div>
110
+ ),
111
+ },
112
+ {
113
+ accessorKey: 'cost',
114
+ header: 'Total Cost',
115
+ sortable: true,
116
+ fieldType: 'number',
117
+ size: 120,
118
+ aggregateFn: sum('cost'),
119
+ aggregateCell: (value: any) => (
120
+ <div className="text-right font-semibold font-mono">
121
+ ${typeof value === 'number' ? value.toFixed(2) : '0.00'}
122
+ </div>
123
+ ),
124
+ cell: ({ row }: { row: { original: DinerData } }) => (
125
+ <div className="text-right font-mono">
126
+ ${row.original.cost.toFixed(2)}
127
+ </div>
128
+ ),
129
+ },
130
+ {
131
+ accessorKey: 'id',
132
+ header: 'Count',
133
+ sortable: false,
134
+ size: 80,
135
+ aggregateFn: count(),
136
+ aggregateCell: (value: any) => (
137
+ <div className="text-center font-semibold">
138
+ {typeof value === 'number' ? value : '0'}
139
+ </div>
140
+ ),
141
+ cell: () => null as React.ReactNode, // Hide count for individual rows
142
+ },
143
+ ];
144
+
145
+ // ============================================================================
146
+ // EXAMPLE COMPONENT
147
+ // ============================================================================
148
+
149
+ export function GroupingAggregationExample() {
150
+ return (
151
+ <div className="p-6 space-y-6">
152
+ <div>
153
+ <h1 className="text-2xl font-bold text-main-900 mb-2">
154
+ Grouped Row Aggregation Example
155
+ </h1>
156
+ <p className="text-sec-600">
157
+ This example demonstrates how to use aggregation functions in grouped DataTable rows.
158
+ When rows are grouped by Unit or Diet, the Youth, Adults, and Cost columns show
159
+ aggregated totals, and the Count column shows the number of records in each group.
160
+ </p>
161
+ </div>
162
+
163
+ <div className="bg-main-50 border border-main-200 rounded-md p-4 space-y-2">
164
+ <p className="font-medium text-sm">How to use:</p>
165
+ <ol className="list-decimal list-inside text-sm space-y-1 text-sec-700">
166
+ <li>Use the grouping dropdown to group by Unit #, Unit Name, or Diet</li>
167
+ <li>Notice how the Youth, Adults, and Cost columns show aggregated totals in grouped rows</li>
168
+ <li>The Count column shows the number of records in each group</li>
169
+ <li>Click the expand/collapse arrows to see individual rows within each group</li>
170
+ </ol>
171
+ </div>
172
+
173
+ <DataTable<DinerData>
174
+ data={dinerData}
175
+ columns={columns}
176
+ title="Diners by Unit and Diet"
177
+ description="Example showing aggregated values in grouped rows"
178
+ rbac={{ pageName: 'diners-example' }}
179
+ features={{
180
+ search: true,
181
+ pagination: true,
182
+ sorting: true,
183
+ filtering: true,
184
+ grouping: true,
185
+ columnVisibility: true,
186
+ columnReordering: false,
187
+ selection: false,
188
+ creation: false,
189
+ editing: false,
190
+ deletion: false,
191
+ deleteSelected: false,
192
+ import: false,
193
+ export: true,
194
+ }}
195
+ getRowId={(row: DinerData) => row.id}
196
+ variant="default"
197
+ className="border border-sec-200 rounded-lg"
198
+ />
199
+ </div>
200
+ );
201
+ }
202
+
203
+ // ============================================================================
204
+ // ALTERNATIVE EXAMPLES
205
+ // ============================================================================
206
+
207
+ /**
208
+ * Example with custom aggregation function
209
+ */
210
+ export function CustomAggregationExample() {
211
+ const customColumns: DataTableColumn<DinerData>[] = [
212
+ {
213
+ accessorKey: 'diet',
214
+ header: 'Diet',
215
+ enableGrouping: true,
216
+ },
217
+ {
218
+ accessorKey: 'youth',
219
+ header: 'Total Diners',
220
+ aggregateFn: (rows: DinerData[]) => {
221
+ // Custom: sum of youth + adults
222
+ return rows.reduce((total: number, row: DinerData) => total + (row.youth || 0) + (row.adults || 0), 0);
223
+ },
224
+ aggregateCell: (value: any) => (
225
+ <div className="text-right font-semibold">
226
+ {typeof value === 'number' ? value.toLocaleString() : '0'} total diners
227
+ </div>
228
+ ),
229
+ },
230
+ {
231
+ accessorKey: 'cost',
232
+ header: 'Avg Cost per Diner',
233
+ aggregateFn: (rows: DinerData[]) => {
234
+ const totalCost = rows.reduce((sum: number, row: DinerData) => sum + (row.cost || 0), 0);
235
+ const totalDiners = rows.reduce((sum: number, row: DinerData) => sum + (row.youth || 0) + (row.adults || 0), 0);
236
+ return totalDiners > 0 ? totalCost / totalDiners : 0;
237
+ },
238
+ aggregateCell: (value: any) => (
239
+ <div className="text-right font-semibold font-mono">
240
+ ${typeof value === 'number' ? value.toFixed(2) : '0.00'} per diner
241
+ </div>
242
+ ),
243
+ },
244
+ ];
245
+
246
+ return (
247
+ <div className="p-6 space-y-6">
248
+ <div>
249
+ <h2 className="text-xl font-bold text-main-900 mb-2">
250
+ Custom Aggregation Example
251
+ </h2>
252
+ <p className="text-sec-600">
253
+ This example shows custom aggregation functions that calculate
254
+ total diners and average cost per diner.
255
+ </p>
256
+ </div>
257
+
258
+ <DataTable<DinerData>
259
+ data={dinerData}
260
+ columns={customColumns}
261
+ rbac={{ pageName: 'diners-custom' }}
262
+ features={{
263
+ grouping: true,
264
+ sorting: true,
265
+ pagination: true,
266
+ }}
267
+ defaultGrouping={['diet']}
268
+ getRowId={(row: DinerData) => row.id}
269
+ />
270
+ </div>
271
+ );
272
+ }
273
+
@@ -12,7 +12,7 @@ import React from 'react';
12
12
  import { DataTable } from '../DataTable';
13
13
  import type { DataTableColumn, DataTableAction } from '../types';
14
14
  import { Button } from '../../Button';
15
- import { createLogger } from '../../../utils/logger';
15
+ import { createLogger } from '../../../utils/core/logger';
16
16
  import {
17
17
  PlusIcon,
18
18
  PencilIcon,
@@ -93,7 +93,7 @@ vi.mock('../../../../rbac/hooks', () => ({
93
93
  }));
94
94
 
95
95
  // Mock logger
96
- vi.mock('../../../utils/logger', () => ({
96
+ vi.mock('../../../utils/core/logger', () => ({
97
97
  createLogger: () => ({
98
98
  debug: vi.fn(),
99
99
  info: vi.fn(),
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect, useCallback } from 'react';
2
- import { createLogger } from '../../../utils/logger';
2
+ import { createLogger } from '../../../utils/core/logger';
3
3
 
4
4
  interface UseColumnOrderPersistenceProps {
5
5
  tableId?: string;
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect, useCallback } from 'react';
2
- import { createLogger } from '../../../utils/logger';
2
+ import { createLogger } from '../../../utils/core/logger';
3
3
 
4
4
  interface UseColumnVisibilityPersistenceProps {
5
5
  tableId?: string;
@@ -12,7 +12,7 @@ import { useMemo, useRef } from 'react';
12
12
  import { useUnifiedAuth } from '../../../providers/UnifiedAuthProvider';
13
13
  import { useCan, useResolvedScope } from '../../../rbac/hooks';
14
14
  import { useToast } from '../../../hooks/useToast';
15
- import { createLogger } from '../../../utils/logger';
15
+ import { createLogger } from '../../../utils/core/logger';
16
16
  import {
17
17
  normalizeDataTableFeatures,
18
18
  type DataTableFeatureConfig,
@@ -69,16 +69,7 @@ export function useDataTablePermissions<TData extends Record<string, any>>(
69
69
  */
70
70
 
71
71
  // Use shared scope resolution hook for consistent RBAC scoping
72
- const { selectedOrganisation, selectedEvent, supabase, organisations } = useUnifiedAuth();
73
-
74
- // Debug logging to understand organisation context
75
- logger.debug('Organisation context:', {
76
- hasSelectedOrg: !!selectedOrganisation,
77
- selectedOrgId: selectedOrganisation?.id,
78
- hasOrganisations: organisations?.length > 0,
79
- organisationCount: organisations?.length,
80
- selectedEvent: selectedEvent?.event_id
81
- });
72
+ const { selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
82
73
 
83
74
  const { resolvedScope: rawResolvedScope, isLoading: scopeLoading } = useResolvedScope({
84
75
  supabase,
@@ -155,18 +146,6 @@ export function useDataTablePermissions<TData extends Record<string, any>>(
155
146
  canExport: useCan(userId, consistentScope, readPermission, effectivePageId, true), // Use read permission for export
156
147
  canImport: useCan(userId, consistentScope, createPermission, effectivePageId, true), // Use create permission for import
157
148
  };
158
-
159
- // Debug logging for permissions
160
- logger.debug('Permission check results:', {
161
- canRead: permissions.canRead.can,
162
- canReadLoading: permissions.canRead.isLoading,
163
- canReadError: permissions.canRead.error?.message,
164
- canCreate: permissions.canCreate.can,
165
- pageName: effectivePageId,
166
- scope: consistentScope,
167
- hasValidScope: !!effectiveScope,
168
- scopeLoading: scopeLoading
169
- });
170
149
 
171
150
  // MANDATORY: Features are automatically filtered by permissions
172
151
  const normalizedFeatures = useMemo(
@@ -29,6 +29,7 @@ export type { UseDataTablePerformanceOptions, UseDataTablePerformanceReturn } fr
29
29
 
30
30
  // Type definitions
31
31
  export type {
32
+ DataRecord,
32
33
  DataTableColumn,
33
34
  DataTableAction,
34
35
  DataTableToolbarButton,
@@ -66,6 +67,9 @@ export * from './components';
66
67
  // Utility functions
67
68
  export * from './utils';
68
69
 
70
+ // Aggregation utilities (explicitly exported for convenience)
71
+ export { sum, average, count, min, max } from './utils/aggregationUtils';
72
+
69
73
  // Accessibility utilities
70
74
  export { announce } from './utils/a11yUtils';
71
75
 
@@ -8,7 +8,7 @@
8
8
  * This ensures consistent styling across regular and virtualized tables.
9
9
  */
10
10
 
11
- import { cn } from '../../utils/cn';
11
+ import { cn } from '../../utils/core/cn';
12
12
 
13
13
  // ============================================================================
14
14
  // TABLE BASE STYLES
@@ -148,12 +148,33 @@ export const getTableClasses = (options: {
148
148
  } = {}) => {
149
149
  const { isFixed = false, variant = 'default', className } = options;
150
150
 
151
- return cn(
152
- isFixed ? tableStyles.tableFixed : tableStyles.table,
153
- variant === 'compact' && 'text-sm',
154
- variant === 'spacious' && 'text-base',
155
- className
156
- );
151
+ if (isFixed) {
152
+ // For fixed tables, use tableFixed and add variant-specific text size
153
+ return cn(
154
+ tableStyles.tableFixed,
155
+ variant === 'compact' && 'text-sm',
156
+ variant === 'spacious' && 'text-base',
157
+ className
158
+ );
159
+ }
160
+
161
+ // For regular tables, build classes based on variant
162
+ // tableStyles.table includes 'text-sm', so we need to handle variants carefully
163
+ if (variant === 'compact') {
164
+ // Compact uses text-sm (same as default), so just use base table styles
165
+ return cn(tableStyles.table, className);
166
+ }
167
+
168
+ if (variant === 'spacious') {
169
+ // Spacious uses text-base, so replace text-sm with text-base
170
+ return cn(
171
+ tableStyles.table.replace('text-sm', 'text-base'),
172
+ className
173
+ );
174
+ }
175
+
176
+ // Default variant
177
+ return cn(tableStyles.table, className);
157
178
  };
158
179
 
159
180
  /**
@@ -328,6 +328,19 @@ export interface DataTableColumn<TData extends DataRecord = DataRecord> extends
328
328
  hideForParent?: boolean;
329
329
  /** Hide this column for child rows */
330
330
  hideForChild?: boolean;
331
+
332
+ // Grouped row aggregation
333
+ /**
334
+ * Aggregation function for grouped rows.
335
+ * Receives all rows in the group and returns the aggregated value.
336
+ * If not provided, grouped rows will show empty/undefined for this column.
337
+ */
338
+ aggregateFn?: (rows: TData[], column: DataTableColumn<TData>) => any;
339
+ /**
340
+ * Optional: Custom cell renderer for aggregated values in grouped rows.
341
+ * If not provided, uses the column's regular cell renderer.
342
+ */
343
+ aggregateCell?: (value: any, rows: TData[], column: DataTableColumn<TData>) => React.ReactNode;
331
344
  }
332
345
 
333
346
  /**
@@ -0,0 +1,94 @@
1
+ /**
2
+ * @file Column Utils Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/DataTable/Utils/__tests__
5
+ * @since 0.4.0
6
+ *
7
+ * Test suite for column utility functions.
8
+ */
9
+
10
+ import { describe, it, expect } from 'vitest';
11
+ import React from 'react';
12
+ import { getColumnHeaderText } from '../columnUtils';
13
+ import type { Column } from '@tanstack/react-table';
14
+
15
+ const createMockColumn = (overrides: Partial<Column<any, unknown>> = {}): Column<any, unknown> => ({
16
+ id: 'test-column',
17
+ columnDef: {
18
+ header: undefined,
19
+ accessorKey: undefined,
20
+ },
21
+ ...overrides,
22
+ } as unknown as Column<any, unknown>);
23
+
24
+ describe('getColumnHeaderText', () => {
25
+ it('returns header text when header is a string', () => {
26
+ const column = createMockColumn({
27
+ columnDef: {
28
+ header: 'Bulk Distribution',
29
+ accessorKey: 'item_bulkdistribution',
30
+ },
31
+ });
32
+
33
+ expect(getColumnHeaderText(column)).toBe('Bulk Distribution');
34
+ });
35
+
36
+ it('returns accessorKey when header is not provided', () => {
37
+ const column = createMockColumn({
38
+ columnDef: {
39
+ header: undefined,
40
+ accessorKey: 'logistics_name',
41
+ },
42
+ });
43
+
44
+ expect(getColumnHeaderText(column)).toBe('logistics_name');
45
+ });
46
+
47
+ it('returns column id when header and accessorKey are not provided', () => {
48
+ const column = createMockColumn({
49
+ id: 'fallback-column',
50
+ columnDef: {
51
+ header: undefined,
52
+ accessorKey: undefined,
53
+ },
54
+ });
55
+
56
+ expect(getColumnHeaderText(column)).toBe('fallback-column');
57
+ });
58
+
59
+ it('returns accessorKey when header is a function', () => {
60
+ const column = createMockColumn({
61
+ columnDef: {
62
+ header: () => 'Function Header',
63
+ accessorKey: 'unit_name',
64
+ },
65
+ });
66
+
67
+ expect(getColumnHeaderText(column)).toBe('unit_name');
68
+ });
69
+
70
+ it('returns accessorKey when header is a React component', () => {
71
+ const HeaderComponent = () => React.createElement('div', null, 'Header Component');
72
+ const column = createMockColumn({
73
+ columnDef: {
74
+ header: React.createElement(HeaderComponent),
75
+ accessorKey: 'component_column',
76
+ },
77
+ });
78
+
79
+ expect(getColumnHeaderText(column)).toBe('component_column');
80
+ });
81
+
82
+ it('falls back to column id when header is function and accessorKey is not provided', () => {
83
+ const column = createMockColumn({
84
+ id: 'function-header-column',
85
+ columnDef: {
86
+ header: () => 'Function Header',
87
+ accessorKey: undefined,
88
+ },
89
+ });
90
+
91
+ expect(getColumnHeaderText(column)).toBe('function-header-column');
92
+ });
93
+ });
94
+
@@ -17,7 +17,7 @@ const mockLogger = {
17
17
  info: vi.fn(),
18
18
  };
19
19
 
20
- vi.mock('../../../utils/logger', () => ({
20
+ vi.mock('../../../utils/core/logger', () => ({
21
21
  createLogger: () => mockLogger,
22
22
  }));
23
23