@jmruthers/pace-core 0.6.6 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +240 -0
  4. package/audit-tool/audits/03-architecture.cjs +224 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +554 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +295 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +380 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-6RMSCQJ6.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
  28. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  29. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  30. package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
  31. package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
  32. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  33. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  34. package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
  35. package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
  36. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  37. package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
  38. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  39. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  40. package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
  41. package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
  42. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  43. package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
  44. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  45. package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
  46. package/dist/components.d.ts +5 -4
  47. package/dist/components.js +29 -34
  48. package/dist/eslint-rules/index.cjs +22 -9
  49. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  50. package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
  51. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  52. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
  53. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
  54. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  55. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  56. package/dist/hooks.d.ts +5 -5
  57. package/dist/hooks.js +8 -8
  58. package/dist/index.d.ts +7 -7
  59. package/dist/index.js +21 -20
  60. package/dist/providers.js +2 -2
  61. package/dist/rbac/index.d.ts +1 -1
  62. package/dist/rbac/index.js +8 -8
  63. package/dist/theming/runtime.d.ts +61 -1
  64. package/dist/theming/runtime.js +1 -1
  65. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  66. package/dist/types.d.ts +2 -2
  67. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  68. package/dist/utils.d.ts +2 -2
  69. package/dist/utils.js +8 -8
  70. package/docs/README.md +1 -1
  71. package/docs/api/modules.md +106 -41
  72. package/docs/api-reference/components.md +18 -20
  73. package/docs/api-reference/hooks.md +80 -80
  74. package/docs/api-reference/types.md +1 -1
  75. package/docs/api-reference/utilities.md +1 -1
  76. package/docs/architecture/README.md +1 -1
  77. package/docs/core-concepts/events.md +3 -3
  78. package/docs/core-concepts/organisations.md +6 -6
  79. package/docs/core-concepts/permissions.md +6 -6
  80. package/docs/documentation-index.md +12 -18
  81. package/docs/getting-started/dependencies.md +23 -0
  82. package/docs/getting-started/documentation-index.md +1 -1
  83. package/docs/getting-started/examples/README.md +4 -4
  84. package/docs/getting-started/examples/full-featured-app.md +1 -1
  85. package/docs/getting-started/faq.md +2 -2
  86. package/docs/getting-started/quick-reference.md +4 -4
  87. package/docs/implementation-guides/app-layout.md +1 -1
  88. package/docs/implementation-guides/authentication.md +15 -15
  89. package/docs/implementation-guides/component-styling.md +1 -1
  90. package/docs/implementation-guides/data-tables.md +127 -34
  91. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  92. package/docs/implementation-guides/dynamic-colors.md +3 -3
  93. package/docs/implementation-guides/file-upload-storage.md +2 -2
  94. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  95. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  96. package/docs/implementation-guides/large-datasets.md +3 -2
  97. package/docs/implementation-guides/organisation-security.md +2 -2
  98. package/docs/implementation-guides/performance.md +2 -2
  99. package/docs/implementation-guides/permission-enforcement.md +1 -1
  100. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  101. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  102. package/docs/rbac/README.md +5 -5
  103. package/docs/rbac/advanced-patterns.md +6 -6
  104. package/docs/rbac/api-reference.md +20 -20
  105. package/docs/rbac/event-based-apps.md +3 -3
  106. package/docs/rbac/examples.md +41 -41
  107. package/docs/rbac/getting-started.md +37 -37
  108. package/docs/rbac/performance.md +1 -1
  109. package/docs/rbac/quick-start.md +52 -52
  110. package/docs/rbac/secure-client-protection.md +1 -1
  111. package/docs/rbac/troubleshooting.md +1 -1
  112. package/docs/security/README.md +5 -5
  113. package/docs/standards/0-standards-overview.md +220 -0
  114. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
  115. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  116. package/docs/standards/3-architecture-standards.md +606 -0
  117. package/docs/standards/4-code-quality-standards.md +728 -0
  118. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  119. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  120. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  121. package/docs/standards/8-testing-documentation-standards.md +401 -0
  122. package/docs/standards/9-operations-standards.md +1102 -0
  123. package/docs/standards/README.md +203 -104
  124. package/docs/troubleshooting/README.md +4 -4
  125. package/docs/troubleshooting/common-issues.md +2 -2
  126. package/docs/troubleshooting/debugging.md +9 -9
  127. package/docs/troubleshooting/migration.md +4 -4
  128. package/eslint-config-pace-core.cjs +50 -20
  129. package/package.json +50 -19
  130. package/scripts/eslint-audit.cjs +123 -0
  131. package/scripts/install-cursor-rules.cjs +11 -243
  132. package/scripts/install-eslint-config.cjs +349 -0
  133. package/scripts/validate-dependencies.cjs +248 -0
  134. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  135. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  136. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
  137. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  138. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  139. package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
  140. package/src/__tests__/templates/component.test.template.tsx +18 -15
  141. package/src/components/AddressField/AddressField.tsx +26 -1
  142. package/src/components/Alert/Alert.test.tsx +86 -22
  143. package/src/components/Alert/Alert.tsx +19 -11
  144. package/src/components/Badge/Badge.tsx +1 -1
  145. package/src/components/Calendar/Calendar.tsx +201 -47
  146. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  147. package/src/components/ContextSelector/ContextSelector.tsx +108 -126
  148. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  149. package/src/components/DataTable/DataTable.tsx +1 -19
  150. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
  151. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
  152. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  153. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  154. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  155. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  156. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  157. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  158. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  159. package/src/components/DataTable/components/EmptyState.tsx +11 -10
  160. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  161. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  162. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  163. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  164. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  165. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  166. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  167. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  168. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  169. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
  170. package/src/components/DataTable/components/index.ts +2 -1
  171. package/src/components/DataTable/types.ts +0 -18
  172. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  173. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  174. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  175. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  176. package/src/components/Dialog/Dialog.test.tsx +1 -0
  177. package/src/components/Dialog/Dialog.tsx +25 -8
  178. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  179. package/src/components/FileUpload/FileUpload.test.tsx +45 -16
  180. package/src/components/FileUpload/FileUpload.tsx +141 -130
  181. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  182. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  183. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  184. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  185. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  186. package/src/components/Progress/Progress.tsx +2 -4
  187. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  188. package/src/components/Select/Select.tsx +86 -77
  189. package/src/components/Select/types.ts +3 -0
  190. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  191. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  192. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  193. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  194. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
  195. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  196. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  197. package/src/hooks/public/usePublicEvent.ts +5 -5
  198. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  199. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  200. package/src/hooks/public/usePublicRouteParams.ts +13 -9
  201. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  202. package/src/hooks/useAppConfig.ts +2 -2
  203. package/src/hooks/useEventTheme.test.ts +7 -7
  204. package/src/hooks/useEventTheme.ts +2 -1
  205. package/src/hooks/useFileDisplay.ts +2 -2
  206. package/src/hooks/useFileUrl.ts +52 -8
  207. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  208. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  209. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  210. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  211. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  212. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  213. package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
  214. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  215. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  216. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  217. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  218. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  219. package/src/rbac/api.test.ts +104 -0
  220. package/src/rbac/engine.ts +1 -1
  221. package/src/rbac/hooks/useCan.test.ts +2 -2
  222. package/src/rbac/secureClient.ts +1 -1
  223. package/src/rbac/types/functions.ts +1 -1
  224. package/src/styles/core.css +7 -0
  225. package/src/theming/__tests__/parseEventColours.test.ts +118 -3
  226. package/src/theming/parseEventColours.ts +77 -11
  227. package/src/types/supabase.ts +2 -3
  228. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  229. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  230. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  231. package/src/utils/formatting/formatDate.test.ts +3 -2
  232. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  233. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  234. package/src/utils/storage/README.md +1 -1
  235. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  236. package/src/utils/storage/helpers.test.ts +69 -3
  237. package/cursor-rules/01-standards-compliance.mdc +0 -285
  238. package/cursor-rules/04-testing-standards.mdc +0 -270
  239. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  240. package/cursor-rules/06-code-quality.mdc +0 -311
  241. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  242. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  243. package/cursor-rules/11-performance-optimization.mdc +0 -169
  244. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  245. package/dist/DataTable-LRJL4IRV.js +0 -15
  246. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  247. package/dist/eslint-rules/rules/components.cjs +0 -113
  248. package/dist/eslint-rules/rules/imports.cjs +0 -102
  249. package/docs/best-practices/README.md +0 -472
  250. package/docs/best-practices/accessibility.md +0 -604
  251. package/docs/best-practices/common-patterns.md +0 -516
  252. package/docs/best-practices/deployment.md +0 -1103
  253. package/docs/best-practices/performance.md +0 -1328
  254. package/docs/best-practices/security.md +0 -940
  255. package/docs/best-practices/testing.md +0 -1034
  256. package/docs/rbac/compliance/compliance-guide.md +0 -544
  257. package/docs/standards/01-standards-compliance.md +0 -188
  258. package/docs/standards/03-solid-principles.md +0 -39
  259. package/docs/standards/04-testing-standards.md +0 -36
  260. package/docs/standards/05-bug-reports-and-features.md +0 -27
  261. package/docs/standards/06-code-quality.md +0 -34
  262. package/docs/standards/07-tech-stack-compliance.md +0 -30
  263. package/docs/standards/10-error-handling-patterns.md +0 -401
  264. package/docs/standards/11-performance-optimization.md +0 -348
  265. package/docs/standards/12-ci-cd-integration.md +0 -370
  266. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  267. package/scripts/audit/audit-compliance.cjs +0 -1295
  268. package/scripts/audit/audit-components.cjs +0 -260
  269. package/scripts/audit/audit-rbac.cjs +0 -954
  270. package/scripts/audit/audit-standards.cjs +0 -1268
  271. package/scripts/audit/index.cjs +0 -1927
  272. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  273. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  274. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  275. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  276. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  277. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  278. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  279. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  280. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  281. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  282. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  284. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  285. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  286. package/src/components/DataTable/utils/debugTools.ts +0 -514
  287. package/src/eslint-rules/index.cjs +0 -22
  288. package/src/eslint-rules/rules/components.cjs +0 -113
  289. package/src/eslint-rules/rules/imports.cjs +0 -102
  290. package/src/eslint-rules/rules/rbac.cjs +0 -790
  291. package/src/eslint-rules/utils/helpers.cjs +0 -42
  292. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -112,20 +112,20 @@ const columns: DataTableColumn<Dish>[] = [
112
112
  header: 'Name',
113
113
  // Different rendering for parent vs child rows
114
114
  renderForParent: (row) => (
115
- <div className="flex items-center gap-2">
115
+ <section className="flex items-center gap-2">
116
116
  <span className="font-semibold text-main-800">{row.name}</span>
117
117
  <span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
118
118
  {row.type}
119
119
  </span>
120
- </div>
120
+ </section>
121
121
  ),
122
122
  renderForChild: (row) => (
123
- <div className="flex items-center gap-2 ml-4">
123
+ <section className="flex items-center gap-2 ml-4">
124
124
  <span className="text-sec-700">{row.name}</span>
125
125
  <span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
126
126
  {row.type}
127
127
  </span>
128
- </div>
128
+ </section>
129
129
  ),
130
130
  },
131
131
  {
@@ -133,14 +133,14 @@ const columns: DataTableColumn<Dish>[] = [
133
133
  accessorKey: 'cost',
134
134
  header: 'Cost',
135
135
  renderForParent: (row) => (
136
- <div className="text-right font-semibold text-main-800">
136
+ <p className="text-right font-semibold text-main-800">
137
137
  ${row.cost?.toFixed(2)}
138
- </div>
138
+ </p>
139
139
  ),
140
140
  renderForChild: (row) => (
141
- <div className="text-right text-sec-600 ml-4">
141
+ <p className="text-right text-sec-600 ml-4">
142
142
  ${row.cost?.toFixed(2)}
143
- </div>
143
+ </p>
144
144
  ),
145
145
  },
146
146
  {
@@ -150,10 +150,10 @@ const columns: DataTableColumn<Dish>[] = [
150
150
  // Only show for child rows
151
151
  renderForParent: () => null,
152
152
  renderForChild: (row) => (
153
- <div className="text-sm ml-4">
153
+ <p className="text-sm ml-4">
154
154
  <span className="font-medium">{row.quantity}</span>
155
155
  {row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
156
- </div>
156
+ </p>
157
157
  ),
158
158
  hideForParent: true, // Hide this column for parent rows
159
159
  }
@@ -193,7 +193,7 @@ hierarchical={{
193
193
  onExpandedChange: (expandedIds) => {
194
194
  console.log('Expanded rows:', expandedIds);
195
195
  },
196
- expandButton: CustomExpandButton, // Optional custom expand button
196
+ // Note: Custom expand button functionality has been removed. Expand/collapse is handled inline by RowComponent.
197
197
  indentSize: 24, // Indentation for child rows in pixels
198
198
  parentRowClassName: 'bg-main-50 font-medium', // CSS classes for parent rows
199
199
  childRowClassName: 'bg-sec-25', // CSS classes for child rows
@@ -207,7 +207,7 @@ hierarchical={{
207
207
  | `enabled` | `boolean` | `false` | Enable/disable hierarchical functionality |
208
208
  | `defaultExpanded` | `boolean \| string[]` | `false` | Initial expansion state |
209
209
  | `onExpandedChange` | `(expandedIds: string[]) => void` | `undefined` | Callback when expansion changes |
210
- | `expandButton` | `React.ComponentType` | `ExpandButton` | Custom expand/collapse button |
210
+ | `expandButton` | ~~`React.ComponentType`~~ | ~~`ExpandButton`~~ | ~~Custom expand/collapse button~~ **DEPRECATED - Removed** |
211
211
  | `indentSize` | `number` | `24` | Indentation for child rows in pixels |
212
212
  | `parentRowClassName` | `string` | `''` | CSS classes for parent rows |
213
213
  | `childRowClassName` | `string` | `''` | CSS classes for child rows |
@@ -240,16 +240,16 @@ const column: DataTableColumn<YourType> = {
240
240
  id: 'actions',
241
241
  header: 'Actions',
242
242
  renderForParent: (row) => (
243
- <div className="flex gap-2">
243
+ <section className="flex gap-2">
244
244
  <Button size="sm">Edit Recipe</Button>
245
245
  <Button size="sm" variant="outline">Add Ingredient</Button>
246
- </div>
246
+ </section>
247
247
  ),
248
248
  renderForChild: (row) => (
249
- <div className="flex gap-2">
249
+ <section className="flex gap-2">
250
250
  <Button size="sm" variant="ghost">Edit</Button>
251
251
  <Button size="sm" variant="destructive">Remove</Button>
252
- </div>
252
+ </section>
253
253
  ),
254
254
  }
255
255
  ```
@@ -277,29 +277,9 @@ The DataTable automatically adds an expand/collapse all button in the header whe
277
277
  You can provide a custom expand button component:
278
278
 
279
279
  ```tsx
280
- import { ChevronRight, ChevronDown } from 'lucide-react';
281
-
282
- const CustomExpandButton = ({ isExpanded, onClick, ...props }) => (
283
- <button
284
- onClick={onClick}
285
- className="p-1 hover:bg-sec-100 rounded"
286
- {...props}
287
- >
288
- {isExpanded ? (
289
- <ChevronDown className="h-4 w-4" />
290
- ) : (
291
- <ChevronRight className="h-4 w-4" />
292
- )}
293
- </button>
294
- );
295
-
296
- // Use in DataTable
297
- <DataTable
298
- hierarchical={{
299
- enabled: true,
300
- expandButton: CustomExpandButton,
301
- }}
302
- />
280
+ // Note: Custom expand button functionality has been removed.
281
+ // Expand/collapse buttons are now handled inline by RowComponent.
282
+ // The expandButton prop is no longer available in HierarchicalConfig.
303
283
  ```
304
284
 
305
285
  ## Hierarchical Actions
@@ -510,20 +490,20 @@ function HierarchicalDishTable() {
510
490
  enableSorting: true,
511
491
  size: 200,
512
492
  renderForParent: (row) => (
513
- <div className="flex items-center gap-2">
493
+ <section className="flex items-center gap-2">
514
494
  <span className="font-semibold text-main-800">{row.name}</span>
515
495
  <span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
516
496
  {row.type}
517
497
  </span>
518
- </div>
498
+ </section>
519
499
  ),
520
500
  renderForChild: (row) => (
521
- <div className="flex items-center gap-2 ml-4">
501
+ <section className="flex items-center gap-2 ml-4">
522
502
  <span className="text-sec-700">{row.name}</span>
523
503
  <span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
524
504
  {row.type}
525
505
  </span>
526
- </div>
506
+ </section>
527
507
  ),
528
508
  },
529
509
  {
@@ -533,14 +513,14 @@ function HierarchicalDishTable() {
533
513
  enableSorting: true,
534
514
  size: 250,
535
515
  renderForParent: (row) => (
536
- <div className="text-sm text-sec-600">
516
+ <p className="text-sm text-sec-600">
537
517
  {row.description}
538
- </div>
518
+ </p>
539
519
  ),
540
520
  renderForChild: (row) => (
541
- <div className="text-sm text-sec-500 ml-4">
521
+ <p className="text-sm text-sec-500 ml-4">
542
522
  {row.description}
543
- </div>
523
+ </p>
544
524
  ),
545
525
  },
546
526
  {
@@ -551,10 +531,10 @@ function HierarchicalDishTable() {
551
531
  size: 120,
552
532
  renderForParent: () => null,
553
533
  renderForChild: (row) => (
554
- <div className="text-sm ml-4">
534
+ <p className="text-sm ml-4">
555
535
  <span className="font-medium">{row.quantity}</span>
556
536
  {row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
557
- </div>
537
+ </p>
558
538
  ),
559
539
  hideForParent: true,
560
540
  },
@@ -565,14 +545,14 @@ function HierarchicalDishTable() {
565
545
  enableSorting: true,
566
546
  size: 100,
567
547
  renderForParent: (row) => (
568
- <div className="text-right font-semibold text-main-800">
548
+ <p className="text-right font-semibold text-main-800">
569
549
  ${row.cost?.toFixed(2)}
570
- </div>
550
+ </p>
571
551
  ),
572
552
  renderForChild: (row) => (
573
- <div className="text-right text-sec-600 ml-4">
553
+ <p className="text-right text-sec-600 ml-4">
574
554
  ${row.cost?.toFixed(2)}
575
- </div>
555
+ </p>
576
556
  ),
577
557
  },
578
558
  {
@@ -583,9 +563,9 @@ function HierarchicalDishTable() {
583
563
  size: 150,
584
564
  renderForParent: () => null,
585
565
  renderForChild: (row) => (
586
- <div className="text-sm text-sec-600 ml-4">
566
+ <p className="text-sm text-sec-600 ml-4">
587
567
  {row.supplier}
588
- </div>
568
+ </p>
589
569
  ),
590
570
  hideForParent: true,
591
571
  },
@@ -596,11 +576,11 @@ function HierarchicalDishTable() {
596
576
  enableSorting: true,
597
577
  size: 100,
598
578
  renderForParent: (row) => (
599
- <div className="text-center">
579
+ <section className="text-center">
600
580
  <span className="inline-flex items-center px-2 py-1 rounded text-xs font-medium bg-sec-100 text-sec-800">
601
581
  {row.prepTime} min
602
582
  </span>
603
- </div>
583
+ </section>
604
584
  ),
605
585
  renderForChild: () => null,
606
586
  hideForChild: true,
@@ -618,11 +598,11 @@ function HierarchicalDishTable() {
618
598
  Hard: 'bg-acc-100 text-acc-800'
619
599
  };
620
600
  return (
621
- <div className="text-center">
601
+ <section className="text-center">
622
602
  <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${colors[row.difficulty as keyof typeof colors] || 'bg-sec-100 text-sec-800'}`}>
623
603
  {row.difficulty}
624
604
  </span>
625
- </div>
605
+ </section>
626
606
  );
627
607
  },
628
608
  renderForChild: () => null,
@@ -812,7 +792,7 @@ interface HierarchicalConfig {
812
792
  enabled: boolean;
813
793
  defaultExpanded?: boolean | string[];
814
794
  onExpandedChange?: (expandedIds: string[]) => void;
815
- expandButton?: React.ComponentType<ExpandButtonProps>;
795
+ // expandButton prop has been removed - expand/collapse is handled inline by RowComponent
816
796
  indentSize?: number;
817
797
  parentRowClassName?: string;
818
798
  childRowClassName?: string;
@@ -449,7 +449,7 @@ function AuthenticatedApp() {
449
449
 
450
450
  // Don't track inactivity if not authenticated
451
451
  if (loading || !user) {
452
- return <div>Loading...</div>;
452
+ return <p>Loading...</p>;
453
453
  }
454
454
 
455
455
  return (
@@ -831,5 +831,5 @@ When user extends session during warning:
831
831
 
832
832
  - **[Authentication Integration](./permission-enforcement.md)** - Security patterns
833
833
  - **[Performance Optimization](./performance.md)** - Large application considerations
834
- - **[Accessibility Guidelines](../best-practices/accessibility.md)** - Accessibility best practices
835
- - **[Security Best Practices](../best-practices/security.md)** - Security considerations
834
+ - **[Accessibility Requirements](../standards/4-code-quality-standards.md#accessibility-requirements)** - Accessibility requirements
835
+ - **[Security & RBAC Standards](../standards/6-security-rbac-standards.md)** - Security considerations
@@ -10,11 +10,12 @@ This guide addresses the common issues when working with large datasets (9,000+
10
10
 
11
11
  **Problem**: Header and body columns were misaligned in virtualized mode due to separate table layouts.
12
12
 
13
- **Solution**: Enhanced `VirtualizedDataTable` component with:
13
+ **Solution**: `UnifiedTableBody` component automatically handles virtualization with:
14
14
  - Synchronized column sizing between header and body tables
15
15
  - `table-fixed` layout for consistent column widths
16
16
  - Dynamic column width calculation and synchronization
17
- - Proper `useLayoutEffect` for measuring actual column widths
17
+ - Automatic virtualization when data exceeds 1000 records
18
+ - Proper virtualization handling for optimal performance
18
19
 
19
20
  ```tsx
20
21
  // ✅ Now properly aligned
@@ -819,5 +819,5 @@ When invalid organisation IDs are provided:
819
819
 
820
820
  - **[RBAC System](../rbac/README.md)** - Role-based access control
821
821
  - **[Permission Enforcement](./permission-enforcement.md)** - UI permission patterns
822
- - **[Security Best Practices](../best-practices/security.md)** - Security guidelines
823
- - **[Audit Logging](../best-practices/audit-logging.md)** - Comprehensive audit patterns
822
+ - **[Security & RBAC Standards](../standards/6-security-rbac-standards.md)** - Security guidelines
823
+ - **[Operations Standards](../standards/9-operations-standards.md)** - Error handling and monitoring
@@ -299,9 +299,9 @@ EnhancedDataTable
299
299
  │ ├── SearchIndex
300
300
  │ ├── PerformanceMonitor
301
301
  │ └── VisibilityTracker
302
- ├── VirtualizedDataTable (when enabled)
302
+ ├── UnifiedTableBody (with automatic virtualization)
303
303
  │ ├── MemoizedRow
304
- │ └── MemoizedCell
304
+ │ └── Virtualized rows (when data > 1000 records)
305
305
  └── EnhancedPaginationControls
306
306
  ├── Performance metrics display
307
307
  ├── Jump to page functionality
@@ -701,7 +701,7 @@ useEffect(() => {
701
701
  ```tsx
702
702
  const { selectedOrganisationId } = useUnifiedAuth();
703
703
  if (!selectedOrganisationId) {
704
- return <div>Please select an organisation first</div>;
704
+ return <p>Please select an organisation first</p>;
705
705
  }
706
706
  ```
707
707
 
@@ -60,7 +60,7 @@ function OrganisationContextGuard({ children }) {
60
60
  }, [selectedOrganisation, supabase]);
61
61
 
62
62
  if (!contextReady) {
63
- return <div>Setting up organisation context...</div>;
63
+ return <p>Setting up organisation context...</p>;
64
64
  }
65
65
 
66
66
  return <>{children}</>;
@@ -239,7 +239,7 @@ function UserActions() {
239
239
  'delete:users'
240
240
  );
241
241
 
242
- if (isLoadingEdit || isLoadingDelete) return <div>Loading permissions...</div>;
242
+ if (isLoadingEdit || isLoadingDelete) return <p>Loading permissions...</p>;
243
243
 
244
244
  return (
245
245
  <div>
@@ -375,7 +375,7 @@ const { can: canEdit, isLoading } = useCan(
375
375
  'update:users'
376
376
  );
377
377
 
378
- if (isLoading) return <div>Loading...</div>;
378
+ if (isLoading) return <p>Loading...</p>;
379
379
  return canEdit ? <EditButton /> : null;
380
380
  ```
381
381
 
@@ -406,7 +406,7 @@ const canCreate = hasPermission('create:users');
406
406
  const canUpdate = hasPermission('update:users');
407
407
  const canDelete = hasPermission('delete:users');
408
408
 
409
- if (isLoading) return <div>Loading permissions...</div>;
409
+ if (isLoading) return <p>Loading permissions...</p>;
410
410
  ```
411
411
 
412
412
  ### Pattern 3: Component Guards
@@ -504,8 +504,8 @@ function UserActions({ userId, scope }) {
504
504
  checkPermission();
505
505
  }, [hasPermission, isLoading, userId, scope]);
506
506
 
507
- if (error) return <div>Error checking permissions</div>;
508
- if (isLoading) return <div>Loading...</div>;
507
+ if (error) return <p>Error checking permissions</p>;
508
+ if (isLoading) return <p>Loading...</p>;
509
509
 
510
510
  return (
511
511
  <div>
@@ -595,7 +595,7 @@ const canEdit = await hasPermission('update:users', { userId, scope });
595
595
  ```tsx
596
596
  const { hasPermission, isLoading } = useCan();
597
597
 
598
- if (isLoading) return <div>Loading permissions...</div>;
598
+ if (isLoading) return <p>Loading permissions...</p>;
599
599
  ```
600
600
 
601
601
  ### Getting Help
@@ -56,7 +56,7 @@ function MyComponent() {
56
56
  <PagePermissionGuard
57
57
  pageName="users"
58
58
  operation="read"
59
- fallback={<div>Access Denied</div>}
59
+ fallback={<p>Access Denied</p>}
60
60
  >
61
61
  <UserList />
62
62
  </PagePermissionGuard>
@@ -232,9 +232,9 @@ function UsersPage() {
232
232
  <PagePermissionGuard
233
233
  pageName="users"
234
234
  operation="read"
235
- fallback={<div>You don't have permission to view this page</div>}
235
+ fallback={<p>You don't have permission to view this page</p>}
236
236
  >
237
- <div>
237
+ <section>
238
238
  <h1>User Management</h1>
239
239
 
240
240
  {/* Multiple operations on same page */}
@@ -261,7 +261,7 @@ function UsersPage() {
261
261
  >
262
262
  <DeleteUserButtons />
263
263
  </PagePermissionGuard>
264
- </div>
264
+ </section>
265
265
  </PagePermissionGuard>
266
266
  );
267
267
  }
@@ -282,7 +282,7 @@ function AdminPanel() {
282
282
  <PagePermissionGuard
283
283
  pageName="admin"
284
284
  operation="read"
285
- fallback={<div>Access denied</div>}
285
+ fallback={<p>Access denied</p>}
286
286
  >
287
287
  <UserManagement />
288
288
  </PagePermissionGuard>
@@ -379,7 +379,7 @@ export function withPermission(permission: string, fallback?: React.ComponentTyp
379
379
 
380
380
  // Usage
381
381
  const ProtectedUserList = withPermission('read:users', () => (
382
- <div>Access denied to user list</div>
382
+ <p>Access denied to user list</p>
383
383
  ))(UserList);
384
384
 
385
385
  // In component
@@ -436,16 +436,16 @@ export const useOrganisationPermissions = createPermissionHook('organisations');
436
436
  function UserManagement({ userId, scope }) {
437
437
  const { permissions, isLoading } = useUserPermissions(userId, scope);
438
438
 
439
- if (isLoading) return <div>Loading permissions...</div>;
439
+ if (isLoading) return <p>Loading permissions...</p>;
440
440
 
441
441
  return (
442
- <div>
442
+ <section>
443
443
  {permissions.read && <UserList />}
444
444
  {permissions.create && <CreateUserButton />}
445
445
  {permissions.update && <EditUserButton />}
446
446
  {permissions.delete && <DeleteUserButton />}
447
447
  {permissions.manage && <UserManagementPanel />}
448
- </div>
448
+ </section>
449
449
  );
450
450
  }
451
451
  ```
@@ -647,7 +647,7 @@ import { withPermission } from './permission-decorators';
647
647
 
648
648
  // Mock component
649
649
  const TestComponent = ({ data }: { data: string }) => (
650
- <div>Test Component: {data}</div>
650
+ <p>Test Component: {data}</p>
651
651
  );
652
652
 
653
653
  describe('Permission Decorators', () => {
@@ -684,7 +684,7 @@ describe('Permission Decorators', () => {
684
684
  })
685
685
  }));
686
686
 
687
- const FallbackComponent = () => <div>Access Denied</div>;
687
+ const FallbackComponent = () => <p>Access Denied</p>;
688
688
  const ProtectedComponent = withPermission('read:users', FallbackComponent)(TestComponent);
689
689
 
690
690
  render(
@@ -44,13 +44,13 @@ function UserActions() {
44
44
  undefined // No pageId for event-app permissions
45
45
  );
46
46
 
47
- if (error) return <div>Error: {error.message}</div>;
48
- if (isLoading) return <div>Checking permissions...</div>;
47
+ if (error) return <p>Error: {error.message}</p>;
48
+ if (isLoading) return <p>Checking permissions...</p>;
49
49
 
50
50
  return (
51
- <div>
51
+ <section>
52
52
  {can && <EventActions />}
53
- </div>
53
+ </section>
54
54
  );
55
55
  }
56
56
  ```
@@ -87,19 +87,19 @@ function PermissionDisplay() {
87
87
  }
88
88
  );
89
89
 
90
- if (isLoading) return <div>Loading permissions...</div>;
91
- if (error) return <div>Error: {error.message}</div>;
90
+ if (isLoading) return <p>Loading permissions...</p>;
91
+ if (error) return <p>Error: {error.message}</p>;
92
92
 
93
93
  return (
94
- <div>
94
+ <section>
95
95
  <h3>User Permissions</h3>
96
96
  {Object.entries(permissions).map(([pageId, operations]) => (
97
- <div key={pageId}>
97
+ <p key={pageId}>
98
98
  <strong>{pageId}:</strong> {operations.join(', ')}
99
- </div>
99
+ </p>
100
100
  ))}
101
101
  <button onClick={refetch}>Refresh</button>
102
- </div>
102
+ </section>
103
103
  );
104
104
  }
105
105
  ```
@@ -128,13 +128,13 @@ function AccessLevelDisplay({ userId, scope }) {
128
128
  scope
129
129
  });
130
130
 
131
- if (isLoading) return <div>Loading access level...</div>;
132
- if (error) return <div>Error: {error.message}</div>;
131
+ if (isLoading) return <p>Loading access level...</p>;
132
+ if (error) return <p>Error: {error.message}</p>;
133
133
 
134
134
  return (
135
- <div>
135
+ <section>
136
136
  <p>Access Level: {accessLevel || 'None'}</p>
137
- </div>
137
+ </section>
138
138
  );
139
139
  }
140
140
  ```
@@ -183,12 +183,12 @@ function UserManagement({ userId, scope }) {
183
183
  }, [checkMultiple, isLoading, userId, scope]);
184
184
 
185
185
  return (
186
- <div>
186
+ <section>
187
187
  {permissions['read:users'] && <UserList />}
188
188
  {permissions['create:users'] && <CreateUserButton />}
189
189
  {permissions['update:users'] && <EditUserButton />}
190
190
  {permissions['delete:users'] && <DeleteUserButton />}
191
- </div>
191
+ </section>
192
192
  );
193
193
  }
194
194
  ```
@@ -221,12 +221,12 @@ import { PermissionEnforcer } from '@jmruthers/pace-core/rbac';
221
221
 
222
222
  function UserActions() {
223
223
  return (
224
- <div>
224
+ <section>
225
225
  {/* Pattern 1: PermissionEnforcer - automatic scope resolution */}
226
226
  <PermissionEnforcer
227
227
  permissions={['read:users']}
228
228
  operation="user-management"
229
- fallback={<div>Access Denied</div>}
229
+ fallback={<p>Access Denied</p>}
230
230
  >
231
231
  <UserList />
232
232
  </PermissionEnforcer>
@@ -236,11 +236,11 @@ function UserActions() {
236
236
  permissions={['create:users', 'update:users']}
237
237
  operation="user-crud"
238
238
  requireAll={true} // User needs ALL permissions
239
- fallback={<div>You need create and update permissions</div>}
239
+ fallback={<p>You need create and update permissions</p>}
240
240
  >
241
241
  <UserManagementPanel />
242
242
  </PermissionEnforcer>
243
- </div>
243
+ </section>
244
244
  );
245
245
  }
246
246
  ```
@@ -491,7 +491,7 @@ export function Dashboard() {
491
491
  const { user, selectedEventId, selectedOrganisationId } = useUnifiedAuth()
492
492
 
493
493
  if (!user) {
494
- return <div>Please log in</div>
494
+ return <p>Please log in</p>
495
495
  }
496
496
 
497
497
  return (
@@ -580,7 +580,7 @@ export function Participants() {
580
580
  const { user, selectedEventId, selectedOrganisationId } = useUnifiedAuth()
581
581
 
582
582
  if (!user) {
583
- return <div>Please log in</div>
583
+ return <p>Please log in</p>
584
584
  }
585
585
 
586
586
  return (
@@ -748,7 +748,7 @@ setupRBAC(supabase) // Must be called BEFORE rendering app
748
748
  setSelectedEventId('your-event-id');
749
749
  }, []);
750
750
 
751
- return <div>...</div>;
751
+ return <p>...</p>;
752
752
  }
753
753
  ```
754
754