@jmruthers/pace-core 0.4.1 → 0.5.1

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 (601) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +231 -229
  3. package/dist/{DataTable-2LB6HI6V.js → DataTable-GX3XERFJ.js} +14 -17
  4. package/dist/{DataTable-BDBqkU-i.d.ts → DataTable-ltTFXHS3.d.ts} +25 -51
  5. package/dist/{Table-CIm9IWqk.d.ts → PublicLoadingSpinner-DztrzuJr.d.ts} +635 -122
  6. package/dist/UnifiedAuthProvider-w66zSCUf.d.ts +160 -0
  7. package/dist/{api-AIJ3IJX3.js → api-ETQ6YJ3C.js} +6 -4
  8. package/dist/{appConfig-fB1pP_v3.d.ts → appConfig-BVGyuvI7.d.ts} +1 -1
  9. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  10. package/dist/{audit-PD5L5ZSC.js → audit-BUW3LMJB.js} +3 -3
  11. package/dist/chunk-5EL3KHOQ.js +388 -0
  12. package/dist/chunk-5EL3KHOQ.js.map +1 -0
  13. package/dist/{chunk-4MCJAK7J.js → chunk-6CR3MRZN.js} +1827 -4886
  14. package/dist/chunk-6CR3MRZN.js.map +1 -0
  15. package/dist/{chunk-YNU5QJ4S.js → chunk-7BNPOCLL.js} +22 -5
  16. package/dist/chunk-7BNPOCLL.js.map +1 -0
  17. package/dist/chunk-AUE24LVR.js +268 -0
  18. package/dist/chunk-AUE24LVR.js.map +1 -0
  19. package/dist/chunk-C5G2A4PO.js +1349 -0
  20. package/dist/chunk-C5G2A4PO.js.map +1 -0
  21. package/dist/{chunk-4ZTIEYU2.js → chunk-CDQ3PX7L.js} +1 -1
  22. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  23. package/dist/chunk-COBPIXXQ.js +379 -0
  24. package/dist/chunk-COBPIXXQ.js.map +1 -0
  25. package/dist/chunk-GSNM5D6H.js +5441 -0
  26. package/dist/chunk-GSNM5D6H.js.map +1 -0
  27. package/dist/chunk-MZBUOP4P.js +119 -0
  28. package/dist/chunk-MZBUOP4P.js.map +1 -0
  29. package/dist/chunk-N2EUGZRW.js +98 -0
  30. package/dist/chunk-N2EUGZRW.js.map +1 -0
  31. package/dist/chunk-NQ4TOOO6.js +20 -0
  32. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  33. package/dist/{chunk-KK6WIDK6.js → chunk-OEGRKULD.js} +12 -2
  34. package/dist/{chunk-KK6WIDK6.js.map → chunk-OEGRKULD.js.map} +1 -1
  35. package/dist/chunk-OYRY44Q2.js +62 -0
  36. package/dist/chunk-OYRY44Q2.js.map +1 -0
  37. package/dist/{chunk-DC5AMYBS.js → chunk-PLDDJCW6.js} +15 -5
  38. package/dist/chunk-PLDDJCW6.js.map +1 -0
  39. package/dist/{chunk-WHLSWC6W.js → chunk-SS3E6QLB.js} +16 -61
  40. package/dist/chunk-SS3E6QLB.js.map +1 -0
  41. package/dist/chunk-T3XIA4AJ.js +3295 -0
  42. package/dist/chunk-T3XIA4AJ.js.map +1 -0
  43. package/dist/{chunk-H4PZ4B3Y.js → chunk-TGDCLPP2.js} +129 -28
  44. package/dist/chunk-TGDCLPP2.js.map +1 -0
  45. package/dist/{chunk-IOX76PSM.js → chunk-U6JDHVC2.js} +273 -29
  46. package/dist/chunk-U6JDHVC2.js.map +1 -0
  47. package/dist/{chunk-JUUNUW3O.js → chunk-XJK2J4N6.js} +17 -6
  48. package/dist/chunk-XJK2J4N6.js.map +1 -0
  49. package/dist/chunk-YDJW5XTN.js +84 -0
  50. package/dist/chunk-YDJW5XTN.js.map +1 -0
  51. package/dist/components.d.ts +906 -10
  52. package/dist/components.js +3263 -84
  53. package/dist/components.js.map +1 -1
  54. package/dist/{database-CAMsquLm.d.ts → database-C3Szpi5J.d.ts} +28 -11
  55. package/dist/hooks.d.ts +7 -6
  56. package/dist/hooks.js +35 -11
  57. package/dist/hooks.js.map +1 -1
  58. package/dist/index.d.ts +245 -111
  59. package/dist/index.js +195 -185
  60. package/dist/index.js.map +1 -1
  61. package/dist/{organisation-DLNNQhPB.d.ts → organisation-CO3Sh3_D.d.ts} +1 -1
  62. package/dist/providers.d.ts +4 -4
  63. package/dist/providers.js +21 -6
  64. package/dist/rbac/index.d.ts +862 -806
  65. package/dist/rbac/index.js +953 -1032
  66. package/dist/rbac/index.js.map +1 -1
  67. package/dist/styles/core.css +422 -0
  68. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  69. package/dist/styles/fonts/georama.woff2 +0 -0
  70. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  71. package/dist/styles/fonts/open-sans.woff2 +0 -0
  72. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  73. package/dist/styles/index.d.ts +36 -0
  74. package/dist/styles/index.js +24 -0
  75. package/dist/styles/index.js.map +1 -0
  76. package/dist/theming/runtime.d.ts +73 -0
  77. package/dist/theming/runtime.js +16 -0
  78. package/dist/theming/runtime.js.map +1 -0
  79. package/dist/{types-Bavn44NW.d.ts → types-BRDU7N6w.d.ts} +79 -33
  80. package/dist/types.d.ts +5 -5
  81. package/dist/types.js +7 -2
  82. package/dist/types.js.map +1 -1
  83. package/dist/{unified-BtRpPbmp.d.ts → unified-CM7T0aTK.d.ts} +1 -2
  84. package/dist/usePublicRouteParams-B6i0KtXW.d.ts +477 -0
  85. package/dist/utils.d.ts +83 -60
  86. package/dist/utils.js +301 -55657
  87. package/dist/utils.js.map +1 -1
  88. package/dist/validation.d.ts +1 -1
  89. package/dist/validation.js +1 -1
  90. package/docs/INDEX.md +192 -0
  91. package/docs/README.md +46 -32
  92. package/docs/api/README.md +231 -229
  93. package/docs/api/classes/ErrorBoundary.md +1 -1
  94. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  95. package/docs/api/interfaces/AggregateConfig.md +4 -4
  96. package/docs/api/interfaces/ButtonProps.md +2 -2
  97. package/docs/api/interfaces/CardProps.md +2 -2
  98. package/docs/api/interfaces/ColorPalette.md +1 -1
  99. package/docs/api/interfaces/ColorShade.md +1 -1
  100. package/docs/api/interfaces/DataTableAction.md +98 -7
  101. package/docs/api/interfaces/DataTableColumn.md +131 -12
  102. package/docs/api/interfaces/DataTableProps.md +77 -274
  103. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  104. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  105. package/docs/api/interfaces/EventContextType.md +7 -7
  106. package/docs/api/interfaces/EventLogoProps.md +152 -0
  107. package/docs/api/interfaces/EventProviderProps.md +2 -2
  108. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  109. package/docs/api/interfaces/FileUploadProps.md +154 -0
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  112. package/docs/api/interfaces/InputProps.md +2 -2
  113. package/docs/api/interfaces/LabelProps.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationItem.md +1 -1
  116. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  117. package/docs/api/interfaces/Organisation.md +1 -1
  118. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  119. package/docs/api/interfaces/OrganisationMembership.md +2 -2
  120. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  121. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  122. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -26
  123. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  124. package/docs/api/interfaces/PaletteData.md +1 -1
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  128. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  131. package/docs/api/interfaces/StorageConfig.md +41 -0
  132. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  133. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  134. package/docs/api/interfaces/StorageListOptions.md +86 -0
  135. package/docs/api/interfaces/StorageListResult.md +41 -0
  136. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  137. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  138. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  139. package/docs/api/interfaces/StyleImport.md +2 -2
  140. package/docs/api/interfaces/ToastActionElement.md +1 -1
  141. package/docs/api/interfaces/ToastProps.md +1 -1
  142. package/docs/api/interfaces/UnifiedAuthContextType.md +447 -46
  143. package/docs/api/interfaces/UnifiedAuthProviderProps.md +95 -9
  144. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  145. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  146. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  147. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  148. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  149. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  150. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  151. package/docs/api/interfaces/UserEventAccess.md +14 -14
  152. package/docs/api/interfaces/UserMenuProps.md +6 -6
  153. package/docs/api/interfaces/UserProfile.md +1 -1
  154. package/docs/api/modules.md +1626 -768
  155. package/docs/api-reference/components.md +761 -43
  156. package/docs/api-reference/hooks.md +126 -0
  157. package/docs/api-reference/providers.md +141 -65
  158. package/docs/api-reference/types.md +66 -36
  159. package/docs/api-reference/utilities.md +1 -1
  160. package/docs/architecture/README.md +1 -2
  161. package/docs/best-practices/README.md +400 -0
  162. package/docs/consuming-app-example.md +42 -96
  163. package/docs/consuming-app-vite-config.md +233 -0
  164. package/docs/core-concepts/events.md +3 -3
  165. package/docs/core-concepts/organisations.md +0 -1
  166. package/docs/core-concepts/rbac-system.md +23 -10
  167. package/docs/documentation-style-checklist.md +8 -2
  168. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  169. package/docs/getting-started/examples/README.md +15 -1
  170. package/docs/getting-started/examples/basic-auth-app.md +444 -119
  171. package/docs/getting-started/examples/full-featured-app.md +6 -6
  172. package/docs/getting-started/installation.md +231 -52
  173. package/docs/getting-started/quick-start.md +121 -24
  174. package/docs/implementation-guides/app-layout.md +133 -108
  175. package/docs/implementation-guides/data-tables.md +1011 -29
  176. package/docs/implementation-guides/forms.md +3 -3
  177. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  178. package/docs/implementation-guides/large-datasets.md +2 -2
  179. package/docs/implementation-guides/navigation.md +1 -1
  180. package/docs/implementation-guides/permission-enforcement.md +4 -4
  181. package/docs/implementation-guides/public-pages.md +752 -0
  182. package/docs/migration/README.md +18 -8
  183. package/docs/migration/quick-migration-guide.md +320 -0
  184. package/docs/migration/rbac-migration.md +50 -0
  185. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  186. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  187. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  188. package/docs/migration-guide.md +51 -104
  189. package/docs/performance/README.md +1 -4
  190. package/docs/print-components/README.md +258 -0
  191. package/docs/print-components/api-reference.md +636 -0
  192. package/docs/print-components/examples/README.md +204 -0
  193. package/docs/print-components/examples/basic-report.tsx +92 -0
  194. package/docs/print-components/examples/card-catalog.tsx +149 -0
  195. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  196. package/docs/print-components/quick-start.md +363 -0
  197. package/docs/quick-reference.md +53 -36
  198. package/docs/rbac/README.md +136 -69
  199. package/docs/rbac/api-reference.md +39 -8
  200. package/docs/rbac/examples.md +237 -66
  201. package/docs/rbac/getting-started.md +131 -16
  202. package/docs/rbac/quick-start.md +499 -323
  203. package/docs/rbac/troubleshooting.md +240 -262
  204. package/docs/security/README.md +50 -1
  205. package/docs/styles/README.md +143 -117
  206. package/docs/testing/README.md +6 -10
  207. package/docs/troubleshooting/README.md +497 -0
  208. package/docs/troubleshooting/common-issues.md +604 -14
  209. package/docs/troubleshooting/styling-issues.md +219 -0
  210. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  211. package/docs/usage.md +28 -90
  212. package/docs/visual-testing.md +0 -7
  213. package/package.json +46 -24
  214. package/src/__mocks__/lucide-react.ts +181 -0
  215. package/src/__tests__/REBUILD_PLAN.md +223 -0
  216. package/src/__tests__/TESTING_GUIDELINES.md +341 -0
  217. package/src/__tests__/fixtures/mocks.ts +93 -0
  218. package/src/__tests__/helpers/component-test-utils.tsx +145 -0
  219. package/src/__tests__/helpers/test-utils.tsx +117 -0
  220. package/src/__tests__/integration/UserProfile.test.tsx +128 -0
  221. package/src/__tests__/setup.ts +71 -0
  222. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  223. package/src/__tests__/templates/component.test.template.tsx +144 -0
  224. package/src/__tests__/templates/hook.test.template.ts +173 -0
  225. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  226. package/src/__tests__/types/test.types.ts +106 -0
  227. package/src/components/Alert/Alert.test.tsx +496 -0
  228. package/src/components/Alert/Alert.tsx +134 -0
  229. package/src/components/Alert/index.ts +2 -0
  230. package/src/components/Avatar/Avatar.test.tsx +484 -0
  231. package/src/components/Avatar/Avatar.tsx +84 -0
  232. package/src/components/Avatar/index.ts +2 -0
  233. package/src/components/Button/Button.test.tsx +662 -0
  234. package/src/components/Button/Button.tsx +270 -0
  235. package/src/components/Button/index.ts +2 -0
  236. package/src/components/Card/Card.test.tsx +593 -0
  237. package/src/components/Card/Card.tsx +271 -0
  238. package/src/components/Card/index.ts +1 -0
  239. package/src/components/Checkbox/Checkbox.test.tsx +461 -0
  240. package/src/components/Checkbox/Checkbox.tsx +75 -0
  241. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  242. package/src/components/Checkbox/index.ts +2 -0
  243. package/src/components/DataTable/DataTable.tsx +446 -0
  244. package/src/components/DataTable/__tests__/README.md +145 -0
  245. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  246. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  247. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +381 -0
  248. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  249. package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
  250. package/src/components/DataTable/components/ActionButtons.tsx +194 -0
  251. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  252. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  253. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  254. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  255. package/src/components/DataTable/components/DataTableCore.tsx +1027 -0
  256. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  257. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  258. package/src/components/DataTable/components/DataTableToolbar.tsx +262 -0
  259. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  260. package/src/components/DataTable/components/EditableRow.tsx +159 -0
  261. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  262. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  263. package/src/components/DataTable/components/FilterRow.tsx +100 -0
  264. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  265. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  266. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  267. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  268. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  269. package/src/components/DataTable/components/UnifiedTableBody.tsx +742 -0
  270. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  271. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  272. package/src/components/DataTable/components/index.ts +16 -0
  273. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  274. package/src/components/DataTable/core/ActionManager.ts +235 -0
  275. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  276. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  277. package/src/components/DataTable/core/DataManager.ts +188 -0
  278. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  279. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  280. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  281. package/src/components/DataTable/core/StateManager.ts +311 -0
  282. package/src/components/DataTable/core/index.ts +8 -0
  283. package/src/components/DataTable/core/interfaces.ts +338 -0
  284. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +419 -0
  285. package/src/components/DataTable/examples/HierarchicalExample.tsx +475 -0
  286. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +176 -0
  287. package/src/components/DataTable/examples/PerformanceExample.tsx +505 -0
  288. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  289. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  290. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  291. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  292. package/src/components/DataTable/index.ts +68 -0
  293. package/src/components/DataTable/styles.ts +171 -0
  294. package/src/components/DataTable/types.ts +511 -0
  295. package/src/components/DataTable/utils/debugTools.ts +583 -0
  296. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  297. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  298. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  299. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  300. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  301. package/src/components/DataTable/utils/index.ts +1 -0
  302. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  303. package/src/components/Dialog/Dialog.test.tsx +1139 -0
  304. package/src/components/Dialog/Dialog.tsx +782 -0
  305. package/src/components/Dialog/README.md +804 -0
  306. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  307. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  308. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  309. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  310. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  311. package/src/components/Dialog/index.ts +12 -0
  312. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  313. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
  314. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  315. package/src/components/ErrorBoundary/index.ts +8 -0
  316. package/src/components/EventSelector/EventSelector.tsx +360 -0
  317. package/src/components/EventSelector/index.ts +3 -0
  318. package/src/components/EventSelector/types.ts +79 -0
  319. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  320. package/src/components/FileUpload/FileUpload.test.tsx +665 -0
  321. package/src/components/FileUpload/FileUpload.tsx +237 -0
  322. package/src/components/FileUpload/index.ts +6 -0
  323. package/src/components/Footer/Footer.tsx +197 -0
  324. package/src/components/Footer/index.ts +17 -0
  325. package/src/components/Form/Form.tsx +166 -0
  326. package/src/components/Form/FormErrorSummary.tsx +113 -0
  327. package/src/components/Form/FormField.tsx +249 -0
  328. package/src/components/Form/FormFieldset.tsx +127 -0
  329. package/src/components/Form/FormLiveRegion.tsx +198 -0
  330. package/src/components/Form/index.ts +26 -0
  331. package/src/components/Header/Header.tsx +301 -0
  332. package/src/components/Header/index.ts +4 -0
  333. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  334. package/src/components/InactivityWarningModal/index.ts +9 -0
  335. package/src/components/Input/Input.tsx +201 -0
  336. package/src/components/Input/__mocks__/Input.tsx +2 -0
  337. package/src/components/Input/index.ts +9 -0
  338. package/src/components/Label/Label.tsx +186 -0
  339. package/src/components/Label/index.ts +2 -0
  340. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  341. package/src/components/LoadingSpinner/index.ts +3 -0
  342. package/src/components/LoginForm/LoginForm.tsx +273 -0
  343. package/src/components/LoginForm/index.ts +3 -0
  344. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  345. package/src/components/NavigationMenu/index.ts +10 -0
  346. package/src/components/NavigationMenu/types.ts +85 -0
  347. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  348. package/src/components/OrganisationSelector/index.ts +9 -0
  349. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  350. package/src/components/PaceAppLayout/README.md +278 -0
  351. package/src/components/PaceAppLayout/index.ts +1 -0
  352. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  353. package/src/components/PaceLoginPage/index.ts +1 -0
  354. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  355. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  356. package/src/components/PasswordReset/index.ts +4 -0
  357. package/src/components/PrintButton/PrintButton.tsx +321 -0
  358. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  359. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  360. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  361. package/src/components/PrintButton/index.ts +33 -0
  362. package/src/components/PrintButton/types.ts +173 -0
  363. package/src/components/PrintCard/PrintCard.tsx +154 -0
  364. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  365. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  366. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  367. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  368. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  369. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  370. package/src/components/PrintCard/index.ts +34 -0
  371. package/src/components/PrintCard/types.ts +171 -0
  372. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  373. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  374. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  375. package/src/components/PrintDataTable/index.ts +25 -0
  376. package/src/components/PrintDataTable/types.ts +67 -0
  377. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  378. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  379. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  380. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  381. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  382. package/src/components/PrintFooter/index.ts +30 -0
  383. package/src/components/PrintFooter/types.ts +149 -0
  384. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  385. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  386. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  387. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  388. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  389. package/src/components/PrintGrid/index.ts +31 -0
  390. package/src/components/PrintGrid/types.ts +159 -0
  391. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  392. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  393. package/src/components/PrintHeader/index.ts +17 -0
  394. package/src/components/PrintHeader/types.ts +42 -0
  395. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  396. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  397. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  398. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  399. package/src/components/PrintLayout/index.ts +19 -0
  400. package/src/components/PrintLayout/types.ts +37 -0
  401. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  402. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  403. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  404. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  405. package/src/components/PrintPageBreak/index.ts +23 -0
  406. package/src/components/PrintPageBreak/types.ts +94 -0
  407. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  408. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  409. package/src/components/PrintSection/PrintSection.tsx +129 -0
  410. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  411. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  412. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  413. package/src/components/PrintSection/index.ts +33 -0
  414. package/src/components/PrintSection/types.ts +155 -0
  415. package/src/components/PrintText/PrintText.tsx +116 -0
  416. package/src/components/PrintText/index.ts +16 -0
  417. package/src/components/PrintText/types.ts +24 -0
  418. package/src/components/Progress/Progress.tsx +116 -0
  419. package/src/components/Progress/index.ts +3 -0
  420. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  421. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  422. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  423. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  424. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  425. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  426. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  427. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  428. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  429. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  430. package/src/components/PublicLayout/index.ts +51 -0
  431. package/src/components/RBAC/PagePermissionGuard.tsx +287 -0
  432. package/src/components/RBAC/RBACGuard.tsx +143 -0
  433. package/src/components/RBAC/RBACProvider.tsx +186 -0
  434. package/src/components/RBAC/RoleBasedContent.tsx +129 -0
  435. package/src/components/RBAC/index.ts +23 -0
  436. package/src/components/Select/Select.tsx +660 -0
  437. package/src/components/Select/index.ts +1 -0
  438. package/src/components/SuperAdminGuard.tsx +116 -0
  439. package/src/components/Table/Table.tsx +222 -0
  440. package/src/components/Table/index.ts +11 -0
  441. package/src/components/Toast/Toast.tsx +339 -0
  442. package/src/components/Toast/index.ts +14 -0
  443. package/src/components/Tooltip/Tooltip.tsx +167 -0
  444. package/src/components/Tooltip/index.ts +7 -0
  445. package/src/components/UserMenu/UserMenu.tsx +243 -0
  446. package/src/components/UserMenu/index.ts +3 -0
  447. package/src/components/examples/PermissionExample.tsx +150 -0
  448. package/src/components/index.ts +434 -0
  449. package/src/components.ts +19 -0
  450. package/src/constants/performance.ts +14 -0
  451. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  452. package/src/examples/PublicEventPage.tsx +274 -0
  453. package/src/examples/PublicPageApp.tsx +308 -0
  454. package/src/examples/PublicPageUsageExample.tsx +216 -0
  455. package/src/hooks/index.ts +56 -0
  456. package/src/hooks/public/index.ts +34 -0
  457. package/src/hooks/public/usePublicEvent.ts +261 -0
  458. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  459. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  460. package/src/hooks/useAppConfig.ts +94 -0
  461. package/src/hooks/useComponentPerformance.ts +39 -0
  462. package/src/hooks/useCounter.test.ts +135 -0
  463. package/src/hooks/useDataTablePerformance.ts +387 -0
  464. package/src/hooks/useDataTableState.ts +110 -0
  465. package/src/hooks/useDebounce.ts +18 -0
  466. package/src/hooks/useFocusManagement.ts +161 -0
  467. package/src/hooks/useFocusTrap.ts +155 -0
  468. package/src/hooks/useInactivityTracker.ts +372 -0
  469. package/src/hooks/useIsMobile.ts +42 -0
  470. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  471. package/src/hooks/useOrganisationPermissions.ts +208 -0
  472. package/src/hooks/useOrganisationSecurity.ts +262 -0
  473. package/src/hooks/usePerformanceMonitor.ts +128 -0
  474. package/src/hooks/usePermissionCache.ts +455 -0
  475. package/src/hooks/useRBAC.ts +262 -0
  476. package/src/hooks/useSecureDataAccess.ts +586 -0
  477. package/src/hooks/useStorage.ts +274 -0
  478. package/src/hooks/useToast.ts +242 -0
  479. package/src/hooks/useZodForm.ts +28 -0
  480. package/src/index.ts +200 -0
  481. package/src/providers/AuthProvider.tsx +369 -0
  482. package/src/providers/EventProvider.tsx +324 -0
  483. package/src/providers/InactivityProvider.tsx +238 -0
  484. package/src/providers/OrganisationProvider.tsx +588 -0
  485. package/src/providers/RBACProvider.tsx +634 -0
  486. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  487. package/src/providers/index.ts +15 -0
  488. package/src/rbac/README.md +885 -0
  489. package/src/rbac/adapters.tsx +726 -0
  490. package/src/rbac/api.ts +339 -0
  491. package/src/rbac/audit-enhanced.ts +339 -0
  492. package/src/rbac/audit.ts +338 -0
  493. package/src/rbac/cache.ts +215 -0
  494. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  495. package/src/rbac/components/NavigationGuard.tsx +294 -0
  496. package/src/rbac/components/NavigationProvider.tsx +314 -0
  497. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  498. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  499. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  500. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  501. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  502. package/src/rbac/components/index.ts +64 -0
  503. package/src/rbac/config.ts +133 -0
  504. package/src/rbac/docs/event-based-apps.md +285 -0
  505. package/src/rbac/engine.ts +1026 -0
  506. package/src/rbac/eslint-rules.js +285 -0
  507. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  508. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  509. package/src/rbac/hooks.ts +570 -0
  510. package/src/rbac/index.ts +114 -0
  511. package/src/rbac/permissions.ts +293 -0
  512. package/src/rbac/secureClient.ts +244 -0
  513. package/src/rbac/security.ts +346 -0
  514. package/src/rbac/testing/index.tsx +340 -0
  515. package/src/rbac/types.ts +343 -0
  516. package/src/rbac/utils/eventContext.ts +83 -0
  517. package/src/styles/core.css +422 -0
  518. package/src/styles/index.ts +51 -0
  519. package/src/theming/runtime.ts +187 -0
  520. package/src/types/database.ts +472 -0
  521. package/src/types/guards.ts +30 -0
  522. package/src/types/index.ts +25 -0
  523. package/src/types/organisation.ts +184 -0
  524. package/src/types/security.ts +70 -0
  525. package/src/types/supabase.ts +166 -0
  526. package/src/types/theme.ts +6 -0
  527. package/src/types/unified.ts +262 -0
  528. package/src/types/validation.ts +164 -0
  529. package/src/types/vitest-globals.d.ts +43 -0
  530. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  531. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  532. package/src/utils/appConfig.ts +47 -0
  533. package/src/utils/appIdResolver.ts +130 -0
  534. package/src/utils/appNameResolver.ts +190 -0
  535. package/src/utils/audit.ts +127 -0
  536. package/src/utils/auth-utils.ts +96 -0
  537. package/src/utils/bundleAnalysis.ts +129 -0
  538. package/src/utils/cn.ts +7 -0
  539. package/src/utils/debugLogger.ts +46 -0
  540. package/src/utils/deviceFingerprint.ts +215 -0
  541. package/src/utils/dynamicUtils.ts +105 -0
  542. package/src/utils/formatting.ts +77 -0
  543. package/src/utils/index.ts +145 -0
  544. package/src/utils/lazyLoad.tsx +44 -0
  545. package/src/utils/organisationContext.ts +135 -0
  546. package/src/utils/performanceBenchmark.ts +64 -0
  547. package/src/utils/performanceBudgets.ts +111 -0
  548. package/src/utils/permissionTypes.ts +37 -0
  549. package/src/utils/permissionUtils.ts +31 -0
  550. package/src/utils/print/PrintDataProcessor.ts +390 -0
  551. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  552. package/src/utils/print/index.ts +29 -0
  553. package/src/utils/print/types.ts +196 -0
  554. package/src/utils/print/usePrintOptimization.ts +272 -0
  555. package/src/utils/sanitization.ts +264 -0
  556. package/src/utils/schemaUtils.ts +37 -0
  557. package/src/utils/secureDataAccess.ts +361 -0
  558. package/src/utils/secureErrors.ts +79 -0
  559. package/src/utils/secureStorage.ts +244 -0
  560. package/src/utils/security.ts +156 -0
  561. package/src/utils/securityMonitor.ts +45 -0
  562. package/src/utils/sessionTracking.ts +170 -0
  563. package/src/utils/storage/README.md +348 -0
  564. package/src/utils/storage/config.ts +100 -0
  565. package/src/utils/storage/helpers.ts +359 -0
  566. package/src/utils/storage/index.ts +36 -0
  567. package/src/utils/storage/types.ts +90 -0
  568. package/src/utils/validation.ts +111 -0
  569. package/src/utils/validationUtils.ts +120 -0
  570. package/src/validation/common.ts +53 -0
  571. package/src/validation/csrf.ts +214 -0
  572. package/src/validation/index.ts +43 -0
  573. package/src/validation/passwordSchema.ts +125 -0
  574. package/src/validation/sanitization.ts +96 -0
  575. package/src/validation/schemaUtils.ts +42 -0
  576. package/src/validation/sqlInjectionProtection.ts +242 -0
  577. package/src/validation/user.ts +34 -0
  578. package/dist/UnifiedAuthProvider-V7y63NjT.d.ts +0 -88
  579. package/dist/chunk-4MCJAK7J.js.map +0 -1
  580. package/dist/chunk-4ZTIEYU2.js.map +0 -1
  581. package/dist/chunk-H4PZ4B3Y.js.map +0 -1
  582. package/dist/chunk-IOX76PSM.js.map +0 -1
  583. package/dist/chunk-JUUNUW3O.js.map +0 -1
  584. package/dist/chunk-U7DY5T33.js +0 -11
  585. package/dist/chunk-U7DY5T33.js.map +0 -1
  586. package/dist/chunk-WHLSWC6W.js.map +0 -1
  587. package/dist/chunk-XI7QFSSC.js +0 -790
  588. package/dist/chunk-XI7QFSSC.js.map +0 -1
  589. package/dist/chunk-XIJMMBDD.js +0 -73
  590. package/dist/chunk-XIJMMBDD.js.map +0 -1
  591. package/dist/chunk-YNU5QJ4S.js.map +0 -1
  592. package/dist/chunk-YWYCNGWH.js +0 -2070
  593. package/dist/chunk-YWYCNGWH.js.map +0 -1
  594. package/dist/chunk-ZJ3UKPIW.js +0 -952
  595. package/dist/chunk-ZJ3UKPIW.js.map +0 -1
  596. package/dist/useAppConfig-CZNJJsT_.d.ts +0 -148
  597. package/dist/{DataTable-2LB6HI6V.js.map → DataTable-GX3XERFJ.js.map} +0 -0
  598. package/dist/{api-AIJ3IJX3.js.map → api-ETQ6YJ3C.js.map} +0 -0
  599. package/dist/{audit-PD5L5ZSC.js.map → appNameResolver-7GHF5ED2.js.map} +0 -0
  600. package/dist/{chunk-DC5AMYBS.js.map → audit-BUW3LMJB.js.map} +0 -0
  601. package/dist/{validation-D2-NNCCE.d.ts → validation-PM_iOaTI.d.ts} +6 -6
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @file User Profile Integration Tests
3
+ * @description Example integration test patterns
4
+ */
5
+
6
+ import React from 'react';
7
+ import { screen, waitFor } from '@testing-library/react';
8
+ import userEvent from '@testing-library/user-event';
9
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
10
+ import { renderWithProviders } from '../helpers/test-utils';
11
+ import { testData } from '../fixtures/mocks';
12
+
13
+ // Mock components for demonstration
14
+ const UserProfile = ({ userId }: { userId: string }) => {
15
+ const [user, setUser] = React.useState<any>(null);
16
+ const [loading, setLoading] = React.useState(true);
17
+ const [error, setError] = React.useState<string | null>(null);
18
+
19
+ React.useEffect(() => {
20
+ // Simulate API call
21
+ const fetchUser = async () => {
22
+ try {
23
+ setLoading(true);
24
+ const userData = testData.users.find(u => u.id === userId);
25
+ if (userData) {
26
+ setUser(userData);
27
+ } else {
28
+ setError('User not found');
29
+ }
30
+ } catch (err) {
31
+ setError('Failed to fetch user');
32
+ } finally {
33
+ setLoading(false);
34
+ }
35
+ };
36
+
37
+ fetchUser();
38
+ }, [userId]);
39
+
40
+ if (loading) return <div>Loading...</div>;
41
+ if (error) return <div>Error: {error}</div>;
42
+ if (!user) return <div>No user found</div>;
43
+
44
+ return (
45
+ <div data-testid="user-profile">
46
+ <h1>{user.name}</h1>
47
+ <p>{user.email}</p>
48
+ <button onClick={() => setUser({ ...user, name: 'Updated Name' })}>
49
+ Update Name
50
+ </button>
51
+ </div>
52
+ );
53
+ };
54
+
55
+ describe('User Profile Integration Tests', () => {
56
+ beforeEach(() => {
57
+ vi.clearAllMocks();
58
+ });
59
+
60
+ describe('Data Loading', () => {
61
+ it('loads and displays user data', async () => {
62
+ renderWithProviders(<UserProfile userId="1" />);
63
+
64
+ // The component loads data synchronously in this mock, so we just check the final state
65
+ await waitFor(() => {
66
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
67
+ });
68
+
69
+ expect(screen.getByText('john@example.com')).toBeInTheDocument();
70
+ });
71
+
72
+ it('handles user not found', async () => {
73
+ renderWithProviders(<UserProfile userId="999" />);
74
+
75
+ await waitFor(() => {
76
+ expect(screen.getByText('Error: User not found')).toBeInTheDocument();
77
+ });
78
+ });
79
+ });
80
+
81
+ describe('User Interactions', () => {
82
+ it('allows updating user name', async () => {
83
+ const user = userEvent.setup();
84
+ renderWithProviders(<UserProfile userId="1" />);
85
+
86
+ await waitFor(() => {
87
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
88
+ });
89
+
90
+ await user.click(screen.getByText('Update Name'));
91
+
92
+ expect(screen.getByText('Updated Name')).toBeInTheDocument();
93
+ expect(screen.queryByText('John Doe')).not.toBeInTheDocument();
94
+ });
95
+ });
96
+
97
+ describe('Component State Management', () => {
98
+ it('maintains state across re-renders', async () => {
99
+ const { rerender } = renderWithProviders(<UserProfile userId="1" />);
100
+
101
+ await waitFor(() => {
102
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
103
+ });
104
+
105
+ rerender(<UserProfile userId="1" />);
106
+
107
+ expect(screen.getByText('John Doe')).toBeInTheDocument();
108
+ });
109
+ });
110
+ });
111
+
112
+ // Example of testing with different user IDs
113
+ describe('User Profile - Different Users', () => {
114
+ const testCases = [
115
+ { userId: '1', expectedName: 'John Doe' },
116
+ { userId: '2', expectedName: 'Jane Smith' },
117
+ ];
118
+
119
+ testCases.forEach(({ userId, expectedName }) => {
120
+ it(`displays correct data for user ${userId}`, async () => {
121
+ renderWithProviders(<UserProfile userId={userId} />);
122
+
123
+ await waitFor(() => {
124
+ expect(screen.getByText(expectedName)).toBeInTheDocument();
125
+ });
126
+ });
127
+ });
128
+ });
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @file Test Setup Configuration
3
+ * @description Global test setup, mocks, and utilities
4
+ */
5
+
6
+ import '@testing-library/jest-dom';
7
+ import { vi } from 'vitest';
8
+ import { cleanup } from '@testing-library/react';
9
+
10
+ // Global test setup
11
+ beforeEach(() => {
12
+ // Clear all mocks before each test
13
+ vi.clearAllMocks();
14
+ });
15
+
16
+ afterEach(() => {
17
+ // Clean up DOM after each test
18
+ cleanup();
19
+ });
20
+
21
+ // Mock console methods to reduce noise in tests
22
+ global.console = {
23
+ ...console,
24
+ // Uncomment to suppress console.log in tests
25
+ // log: vi.fn(),
26
+ // warn: vi.fn(),
27
+ // error: vi.fn(),
28
+ };
29
+
30
+ // Mock IntersectionObserver
31
+ global.IntersectionObserver = vi.fn().mockImplementation(() => ({
32
+ observe: vi.fn(),
33
+ unobserve: vi.fn(),
34
+ disconnect: vi.fn(),
35
+ }));
36
+
37
+ // Mock ResizeObserver
38
+ global.ResizeObserver = vi.fn().mockImplementation(() => ({
39
+ observe: vi.fn(),
40
+ unobserve: vi.fn(),
41
+ disconnect: vi.fn(),
42
+ }));
43
+
44
+ // Mock matchMedia
45
+ Object.defineProperty(window, 'matchMedia', {
46
+ writable: true,
47
+ value: vi.fn().mockImplementation(query => ({
48
+ matches: false,
49
+ media: query,
50
+ onchange: null,
51
+ addListener: vi.fn(),
52
+ removeListener: vi.fn(),
53
+ addEventListener: vi.fn(),
54
+ removeEventListener: vi.fn(),
55
+ dispatchEvent: vi.fn(),
56
+ })),
57
+ });
58
+
59
+ // Mock scrollTo
60
+ Object.defineProperty(window, 'scrollTo', {
61
+ writable: true,
62
+ value: vi.fn(),
63
+ });
64
+
65
+ // Mock getComputedStyle
66
+ Object.defineProperty(window, 'getComputedStyle', {
67
+ writable: true,
68
+ value: vi.fn().mockImplementation(() => ({
69
+ getPropertyValue: vi.fn().mockReturnValue(''),
70
+ })),
71
+ });
@@ -0,0 +1,279 @@
1
+
2
+ /**
3
+ * @file Template for accessibility tests
4
+ * Copy this file and replace ComponentName with your actual component
5
+ *
6
+ * Instructions:
7
+ * 1. Copy this file to your component's __tests__ folder
8
+ * 2. Rename to YourComponent.accessibility.test.tsx
9
+ * 3. Replace all instances of "ComponentName" with your actual component name
10
+ * 4. Uncomment and fix the import paths below
11
+ * 5. Customize the tests for your component's accessibility requirements
12
+ */
13
+
14
+ // Uncomment and update these imports for your component:
15
+ // import React from 'react';
16
+ // import { render, screen, within } from '@testing-library/react';
17
+ // import userEvent from '@testing-library/user-event';
18
+ // import { describe, it, expect, vi, beforeEach } from 'vitest';
19
+ // import { ComponentName } from '../ComponentName';
20
+ // import { renderWithProviders } from '../../utils/renderHelpers';
21
+
22
+ /*
23
+ describe('ComponentName Accessibility Tests', () => {
24
+ const user = userEvent.setup();
25
+
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ });
29
+
30
+ describe('Semantic Structure', () => {
31
+ it('has proper semantic HTML', () => {
32
+ renderWithProviders(<ComponentName>Content</ComponentName>);
33
+
34
+ // Check for proper semantic elements
35
+ expect(screen.getByRole('main')).toBeInTheDocument();
36
+ // or: expect(screen.getByRole('button')).toBeInTheDocument();
37
+ // or: expect(screen.getByRole('textbox')).toBeInTheDocument();
38
+ });
39
+
40
+ it('has proper heading hierarchy', () => {
41
+ renderWithProviders(<ComponentName title="Main Title" subtitle="Subtitle" />);
42
+
43
+ const mainHeading = screen.getByRole('heading', { level: 1 });
44
+ const subHeading = screen.getByRole('heading', { level: 2 });
45
+
46
+ expect(mainHeading).toHaveTextContent('Main Title');
47
+ expect(subHeading).toHaveTextContent('Subtitle');
48
+ });
49
+ });
50
+
51
+ describe('ARIA Attributes', () => {
52
+ it('has proper ARIA labels', () => {
53
+ renderWithProviders(<ComponentName aria-label="Component description" />);
54
+
55
+ const component = screen.getByLabelText('Component description');
56
+ expect(component).toBeInTheDocument();
57
+ });
58
+
59
+ it('has proper ARIA roles', () => {
60
+ renderWithProviders(<ComponentName role="dialog" />);
61
+
62
+ expect(screen.getByRole('dialog')).toBeInTheDocument();
63
+ });
64
+
65
+ it('uses ARIA describedby for additional information', () => {
66
+ renderWithProviders(
67
+ <ComponentName
68
+ aria-describedby="help-text"
69
+ helperText="This is helpful information"
70
+ />
71
+ );
72
+
73
+ const component = screen.getByRole('main'); // adjust role as needed
74
+ const helpText = screen.getByText('This is helpful information');
75
+
76
+ expect(component).toHaveAttribute('aria-describedby', 'help-text');
77
+ expect(helpText).toHaveAttribute('id', 'help-text');
78
+ });
79
+
80
+ it('announces state changes', async () => {
81
+ renderWithProviders(<ComponentName />);
82
+
83
+ const button = screen.getByRole('button');
84
+ await user.click(button);
85
+
86
+ // Check for live region announcements
87
+ const status = screen.getByRole('status');
88
+ expect(status).toHaveAttribute('aria-live', 'polite');
89
+ });
90
+ });
91
+
92
+ describe('Keyboard Navigation', () => {
93
+ it('supports tab navigation', async () => {
94
+ renderWithProviders(
95
+ <div>
96
+ <ComponentName />
97
+ <button>Next focusable element</button>
98
+ </div>
99
+ );
100
+
101
+ const firstElement = screen.getByRole('button', { name: /component/i });
102
+ const secondElement = screen.getByRole('button', { name: /next focusable/i });
103
+
104
+ firstElement.focus();
105
+ expect(firstElement).toHaveFocus();
106
+
107
+ await user.tab();
108
+ expect(secondElement).toHaveFocus();
109
+ });
110
+
111
+ it('supports Enter and Space key activation', async () => {
112
+ const handleClick = vi.fn();
113
+ renderWithProviders(<ComponentName onClick={handleClick} />);
114
+
115
+ const element = screen.getByRole('button');
116
+ element.focus();
117
+
118
+ await user.keyboard('[Enter]');
119
+ expect(handleClick).toHaveBeenCalledTimes(1);
120
+
121
+ await user.keyboard('[Space]');
122
+ expect(handleClick).toHaveBeenCalledTimes(2);
123
+ });
124
+
125
+ it('supports arrow key navigation for menus', async () => {
126
+ renderWithProviders(<ComponentName type="menu" />);
127
+
128
+ const menu = screen.getByRole('menu');
129
+ const menuItems = within(menu).getAllByRole('menuitem');
130
+
131
+ menuItems[0].focus();
132
+ expect(menuItems[0]).toHaveFocus();
133
+
134
+ await user.keyboard('[ArrowDown]');
135
+ expect(menuItems[1]).toHaveFocus();
136
+
137
+ await user.keyboard('[ArrowUp]');
138
+ expect(menuItems[0]).toHaveFocus();
139
+ });
140
+
141
+ it('traps focus in modal dialogs', async () => {
142
+ renderWithProviders(<ComponentName isModal open />);
143
+
144
+ const dialog = screen.getByRole('dialog');
145
+ const focusableElements = within(dialog).getAllByRole('button');
146
+
147
+ // Focus should be trapped within modal
148
+ focusableElements[0].focus();
149
+
150
+ // Tab through all focusable elements
151
+ for (let i = 1; i < focusableElements.length; i++) {
152
+ await user.tab();
153
+ expect(focusableElements[i]).toHaveFocus();
154
+ }
155
+
156
+ // Should wrap back to first element
157
+ await user.tab();
158
+ expect(focusableElements[0]).toHaveFocus();
159
+ });
160
+
161
+ it('supports Escape key to close modals', async () => {
162
+ const handleClose = vi.fn();
163
+ renderWithProviders(<ComponentName isModal open onClose={handleClose} />);
164
+
165
+ await user.keyboard('[Escape]');
166
+ expect(handleClose).toHaveBeenCalled();
167
+ });
168
+ });
169
+
170
+ describe('Screen Reader Support', () => {
171
+ it('provides meaningful text alternatives for images', () => {
172
+ renderWithProviders(<ComponentName image="/test.jpg" alt="Descriptive alt text" />);
173
+
174
+ const image = screen.getByRole('img');
175
+ expect(image).toHaveAttribute('alt', 'Descriptive alt text');
176
+ });
177
+
178
+ it('uses proper form labels', () => {
179
+ renderWithProviders(<ComponentName type="form" />);
180
+
181
+ const input = screen.getByLabelText('Input Label');
182
+ expect(input).toBeInTheDocument();
183
+ });
184
+
185
+ it('announces loading states', () => {
186
+ renderWithProviders(<ComponentName isLoading />);
187
+
188
+ const loadingIndicator = screen.getByRole('status');
189
+ expect(loadingIndicator).toHaveAttribute('aria-live', 'polite');
190
+ expect(loadingIndicator).toHaveTextContent(/loading/i);
191
+ });
192
+
193
+ it('announces error states', () => {
194
+ renderWithProviders(<ComponentName error="Something went wrong" />);
195
+
196
+ const errorAlert = screen.getByRole('alert');
197
+ expect(errorAlert).toHaveAttribute('aria-live', 'assertive');
198
+ expect(errorAlert).toHaveTextContent('Something went wrong');
199
+ });
200
+ });
201
+
202
+ describe('Color and Contrast', () => {
203
+ it('does not rely solely on color for information', () => {
204
+ renderWithProviders(<ComponentName status="error" />);
205
+
206
+ // Should have text indicator, not just color
207
+ expect(screen.getByText(/error/i)).toBeInTheDocument();
208
+ });
209
+
210
+ it('maintains focus indicators', async () => {
211
+ renderWithProviders(<ComponentName />);
212
+
213
+ const element = screen.getByRole('button');
214
+ element.focus();
215
+
216
+ // Focus should be visible (actual contrast testing would require visual testing tools)
217
+ expect(element).toHaveFocus();
218
+ });
219
+ });
220
+
221
+ describe('Form Accessibility', () => {
222
+ it('associates form controls with labels', () => {
223
+ renderWithProviders(<ComponentName type="form" />);
224
+
225
+ const input = screen.getByLabelText('Required Field');
226
+ expect(input).toHaveAttribute('required');
227
+ expect(input).toHaveAttribute('aria-required', 'true');
228
+ });
229
+
230
+ it('provides validation feedback', async () => {
231
+ renderWithProviders(<ComponentName type="form" />);
232
+
233
+ const input = screen.getByLabelText('Email');
234
+ await user.type(input, 'invalid-email');
235
+
236
+ const errorMessage = await screen.findByRole('alert');
237
+ expect(errorMessage).toHaveTextContent(/invalid email/i);
238
+ expect(input).toHaveAttribute('aria-describedby', expect.stringContaining('error'));
239
+ });
240
+
241
+ it('groups related form controls', () => {
242
+ renderWithProviders(<ComponentName type="form" />);
243
+
244
+ const fieldset = screen.getByRole('group');
245
+ const legend = within(fieldset).getByText('Contact Information');
246
+
247
+ expect(fieldset).toContainElement(legend);
248
+ });
249
+ });
250
+
251
+ describe('Dynamic Content', () => {
252
+ it('announces dynamic content changes', async () => {
253
+ renderWithProviders(<ComponentName />);
254
+
255
+ const button = screen.getByRole('button', { name: /load more/i });
256
+ await user.click(button);
257
+
258
+ // Check for announcement of new content
259
+ const announcement = await screen.findByRole('status');
260
+ expect(announcement).toHaveTextContent(/content loaded/i);
261
+ });
262
+
263
+ it('maintains focus after content updates', async () => {
264
+ renderWithProviders(<ComponentName />);
265
+
266
+ const trigger = screen.getByRole('button');
267
+ trigger.focus();
268
+
269
+ await user.click(trigger);
270
+
271
+ // Focus should remain on trigger or move to logical next element
272
+ expect(document.activeElement).toBe(trigger);
273
+ });
274
+ });
275
+ });
276
+ */
277
+
278
+ // This file is a template - copy and uncomment the code above to use it
279
+ export {};
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @file Component Test Template
3
+ * @description Template for creating component tests
4
+ * @usage Copy this template and replace ComponentName with your component
5
+ */
6
+
7
+ import React from 'react';
8
+ import { screen } from '@testing-library/react';
9
+ import userEvent from '@testing-library/user-event';
10
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
11
+ import { ComponentName } from '../../components/ComponentName/ComponentName';
12
+ import { renderWithProviders } from '../helpers/test-utils';
13
+
14
+ describe('ComponentName Component', () => {
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+ });
18
+
19
+ // Basic rendering tests
20
+ describe('Rendering', () => {
21
+ it('renders with default props', () => {
22
+ renderWithProviders(<ComponentName />);
23
+ expect(screen.getByRole('generic')).toBeInTheDocument();
24
+ });
25
+
26
+ it('renders with custom props', () => {
27
+ renderWithProviders(<ComponentName customProp="value" />);
28
+ expect(screen.getByRole('generic')).toBeInTheDocument();
29
+ });
30
+
31
+ it('renders with children', () => {
32
+ renderWithProviders(
33
+ <ComponentName>
34
+ <span>Child content</span>
35
+ </ComponentName>
36
+ );
37
+ expect(screen.getByText('Child content')).toBeInTheDocument();
38
+ });
39
+ });
40
+
41
+ // Event handling tests
42
+ describe('Event Handling', () => {
43
+ it('handles click events', async () => {
44
+ const handleClick = vi.fn();
45
+ const user = userEvent.setup();
46
+
47
+ renderWithProviders(<ComponentName onClick={handleClick} />);
48
+
49
+ await user.click(screen.getByRole('generic'));
50
+ expect(handleClick).toHaveBeenCalledTimes(1);
51
+ });
52
+
53
+ it('handles keyboard events', async () => {
54
+ const handleKeyDown = vi.fn();
55
+ const user = userEvent.setup();
56
+
57
+ renderWithProviders(<ComponentName onKeyDown={handleKeyDown} />);
58
+
59
+ screen.getByRole('generic').focus();
60
+ await user.keyboard('{Enter}');
61
+ expect(handleKeyDown).toHaveBeenCalledTimes(1);
62
+ });
63
+ });
64
+
65
+ // State management tests
66
+ describe('State Management', () => {
67
+ it('handles controlled state', () => {
68
+ const { rerender } = renderWithProviders(
69
+ <ComponentName value="initial" />
70
+ );
71
+
72
+ expect(screen.getByDisplayValue('initial')).toBeInTheDocument();
73
+
74
+ rerender(<ComponentName value="updated" />);
75
+ expect(screen.getByDisplayValue('updated')).toBeInTheDocument();
76
+ });
77
+
78
+ it('handles uncontrolled state', () => {
79
+ renderWithProviders(<ComponentName defaultValue="default" />);
80
+ expect(screen.getByDisplayValue('default')).toBeInTheDocument();
81
+ });
82
+ });
83
+
84
+ // Accessibility tests
85
+ describe('Accessibility', () => {
86
+ it('has proper ARIA attributes', () => {
87
+ renderWithProviders(<ComponentName aria-label="Test component" />);
88
+ expect(screen.getByRole('generic')).toHaveAttribute('aria-label', 'Test component');
89
+ });
90
+
91
+ it('is keyboard accessible', () => {
92
+ renderWithProviders(<ComponentName />);
93
+ expect(screen.getByRole('generic')).not.toHaveAttribute('tabindex', '-1');
94
+ });
95
+
96
+ it('supports screen readers', () => {
97
+ renderWithProviders(<ComponentName />);
98
+ // Add specific screen reader tests here
99
+ });
100
+ });
101
+
102
+ // Error handling tests
103
+ describe('Error Handling', () => {
104
+ it('handles invalid props gracefully', () => {
105
+ // @ts-expect-error Testing invalid prop
106
+ renderWithProviders(<ComponentName invalidProp="test" />);
107
+ expect(screen.getByRole('generic')).toBeInTheDocument();
108
+ });
109
+
110
+ it('displays error states', () => {
111
+ renderWithProviders(<ComponentName error="Something went wrong" />);
112
+ expect(screen.getByText('Something went wrong')).toBeInTheDocument();
113
+ });
114
+ });
115
+
116
+ // Integration tests
117
+ describe('Integration', () => {
118
+ it('works with other components', () => {
119
+ renderWithProviders(
120
+ <div>
121
+ <ComponentName />
122
+ <ComponentName />
123
+ </div>
124
+ );
125
+
126
+ expect(screen.getAllByRole('generic')).toHaveLength(2);
127
+ });
128
+
129
+ it('works with forms', async () => {
130
+ const handleSubmit = vi.fn((e) => e.preventDefault());
131
+ const user = userEvent.setup();
132
+
133
+ renderWithProviders(
134
+ <form onSubmit={handleSubmit}>
135
+ <ComponentName />
136
+ <button type="submit">Submit</button>
137
+ </form>
138
+ );
139
+
140
+ await user.click(screen.getByRole('button', { name: 'Submit' }));
141
+ expect(handleSubmit).toHaveBeenCalledTimes(1);
142
+ });
143
+ });
144
+ });