@jmruthers/pace-core 0.6.9 → 0.6.10

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 (665) hide show
  1. package/audit-tool/audits/02-project-structure.cjs +62 -0
  2. package/audit-tool/audits/03-architecture.cjs +145 -19
  3. package/audit-tool/audits/04-code-quality.cjs +86 -1
  4. package/audit-tool/audits/06-security-rbac.cjs +109 -11
  5. package/cursor-rules/02-project-structure.mdc +2 -26
  6. package/cursor-rules/05-styling.mdc +84 -6
  7. package/cursor-rules/06-security-rbac.mdc +124 -1
  8. package/dist/{DataTable-SOAFXIWY.js → DataTable-SAXFG4XI.js} +11 -13
  9. package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
  10. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
  11. package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
  12. package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
  13. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  14. package/dist/assets/app-icons/base_favicon.svg +85 -0
  15. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  16. package/dist/assets/app-icons/core_favicon.svg +256 -0
  17. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  18. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  19. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  20. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  21. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  22. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  23. package/dist/assets/app-icons/team_favicon.svg +67 -0
  24. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  25. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  26. package/dist/audit-Z6ZZBWLU.js +3 -0
  27. package/dist/chunk-3GWSPISD.js +61 -0
  28. package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
  29. package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
  30. package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
  31. package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
  32. package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
  33. package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
  34. package/dist/chunk-FN52B75D.js +246 -0
  35. package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
  36. package/dist/chunk-KPYQWGFQ.js +183 -0
  37. package/dist/{chunk-C7ZQ5O4C.js → chunk-KSNLMI7N.js} +3 -3
  38. package/dist/chunk-KYURMOQM.js +977 -0
  39. package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
  40. package/dist/{chunk-J2U36LHD.js → chunk-MPY44PWB.js} +620 -627
  41. package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
  42. package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
  43. package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
  44. package/dist/{chunk-5HNSDQWH.js → chunk-TFIPNIPE.js} +865 -532
  45. package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
  46. package/dist/chunk-W46INAVW.js +1216 -0
  47. package/dist/chunk-X5EAU5G7.js +793 -0
  48. package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
  49. package/dist/components.d.ts +8 -86
  50. package/dist/components.js +21 -55
  51. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  52. package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
  53. package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
  54. package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
  55. package/dist/hooks.d.ts +11 -10
  56. package/dist/hooks.js +69 -44
  57. package/dist/index.d.ts +379 -31
  58. package/dist/index.js +46 -32
  59. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  60. package/dist/providers.d.ts +28 -14
  61. package/dist/providers.js +5 -5
  62. package/dist/rbac/eslint-rules.js +2 -2
  63. package/dist/rbac/index.d.ts +57 -213
  64. package/dist/rbac/index.js +11 -11
  65. package/dist/theming/runtime.d.ts +9 -3
  66. package/dist/theming/runtime.js +2 -2
  67. package/dist/{timezone-0AyangqX.d.ts → timezone-K-ptz3HO.d.ts} +21 -22
  68. package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
  69. package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
  70. package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
  71. package/dist/types-Dr8sNhER.d.ts +50 -0
  72. package/dist/types.d.ts +4 -4
  73. package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
  74. package/dist/{usePublicRouteParams-DQLrDqDb.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +7 -6
  75. package/dist/utils.d.ts +300 -136
  76. package/dist/utils.js +42 -41
  77. package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
  78. package/docs/api/modules.md +542 -549
  79. package/docs/api-reference/components.md +5 -5
  80. package/docs/implementation-guides/data-tables.md +190 -8
  81. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  82. package/docs/standards/2-project-structure-standards.md +12 -74
  83. package/docs/standards/6-security-rbac-standards.md +222 -7
  84. package/docs/standards/7-api-tech-stack-standards.md +91 -3
  85. package/docs/testing/README.md +10 -0
  86. package/docs/testing/test-setup-for-consumers.md +914 -0
  87. package/eslint-config-pace-core.cjs +4 -0
  88. package/package.json +1 -1
  89. package/scripts/eslint-audit.cjs +110 -11
  90. package/src/__mocks__/lucide-react.ts +0 -2
  91. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
  92. package/src/__tests__/index.test.ts +532 -0
  93. package/src/__tests__/integration/UserProfile.test.tsx +1 -1
  94. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
  95. package/src/__tests__/rls-policies.test.ts +3 -2
  96. package/src/assets/app-icons/admin_favicon.svg +462 -0
  97. package/src/assets/app-icons/base_favicon.svg +85 -0
  98. package/src/assets/app-icons/cake_favicon.svg +68 -0
  99. package/src/assets/app-icons/core_favicon.svg +256 -0
  100. package/src/assets/app-icons/gear_favicon.svg +91 -0
  101. package/src/assets/app-icons/index.ts +83 -0
  102. package/src/assets/app-icons/medi_favicon.svg +92 -0
  103. package/src/assets/app-icons/mint_favicon.svg +83 -0
  104. package/src/assets/app-icons/pace_favicon.svg +49 -0
  105. package/src/assets/app-icons/pump_favicon.svg +68 -0
  106. package/src/assets/app-icons/seed_favicon.svg +91 -0
  107. package/src/assets/app-icons/team_favicon.svg +67 -0
  108. package/src/assets/app-icons/trac_favicon.svg +112 -0
  109. package/src/assets/app-icons/trip_favicon.svg +102 -0
  110. package/src/components/AddressField/AddressField.test.tsx +378 -3
  111. package/src/components/AddressField/AddressField.tsx +2 -2
  112. package/src/components/AddressField/types.ts +2 -2
  113. package/src/components/Alert/Alert.test.tsx +35 -25
  114. package/src/components/Alert/Alert.tsx +8 -8
  115. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  116. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  117. package/src/components/Avatar/Avatar.test.tsx +11 -1
  118. package/src/components/Avatar/Avatar.tsx +3 -2
  119. package/src/components/Badge/Badge.test.tsx +11 -1
  120. package/src/components/Button/Button.test.tsx +13 -3
  121. package/src/components/Calendar/Calendar.test.tsx +523 -131
  122. package/src/components/Calendar/Calendar.tsx +107 -488
  123. package/src/components/Card/Card.test.tsx +220 -249
  124. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  125. package/src/components/ContextSelector/ContextSelector.tsx +3 -3
  126. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
  127. package/src/components/DataTable/DataTable.tsx +2 -2
  128. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
  129. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
  130. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
  131. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +16 -14
  132. package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
  133. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
  134. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
  135. package/src/components/DataTable/__tests__/README.md +1 -1
  136. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
  138. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
  139. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
  140. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
  141. package/src/components/DataTable/components/ActionButtons.tsx +9 -4
  142. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
  143. package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
  144. package/src/components/DataTable/components/DataTableCore.tsx +44 -52
  145. package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
  146. package/src/components/DataTable/components/DataTableModals.tsx +118 -30
  147. package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
  148. package/src/components/DataTable/components/EditFields.tsx +6 -47
  149. package/src/components/DataTable/components/EditableRow.tsx +8 -8
  150. package/src/components/DataTable/components/EmptyState.tsx +6 -3
  151. package/src/components/DataTable/components/FilterRow.tsx +18 -11
  152. package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
  153. package/src/components/DataTable/components/ImportModal.tsx +305 -133
  154. package/src/components/DataTable/components/LoadingState.tsx +2 -2
  155. package/src/components/DataTable/components/PaginationControls.tsx +0 -4
  156. package/src/components/DataTable/components/RowComponent.tsx +42 -22
  157. package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
  158. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
  159. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
  160. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
  161. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
  162. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
  163. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
  164. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
  165. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
  166. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
  167. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
  168. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
  169. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
  170. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
  171. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
  172. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
  173. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
  174. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
  175. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
  176. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
  177. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
  178. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
  179. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
  180. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
  181. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
  182. package/src/components/DataTable/context/DataTableContext.tsx +9 -10
  183. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
  184. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  185. package/src/components/DataTable/core/ColumnManager.ts +0 -1
  186. package/src/components/DataTable/core/DataManager.ts +4 -2
  187. package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
  188. package/src/components/DataTable/core/PluginRegistry.ts +2 -2
  189. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
  190. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
  191. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
  192. package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
  193. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
  194. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
  195. package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
  196. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
  197. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
  198. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
  199. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
  200. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
  201. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
  202. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
  203. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
  204. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
  205. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
  206. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +128 -77
  207. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
  208. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
  212. package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
  213. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
  214. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
  215. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  216. package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
  217. package/src/components/DataTable/index.ts +24 -2
  218. package/src/components/DataTable/types.ts +6 -3
  219. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
  220. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
  221. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
  222. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
  223. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
  224. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
  225. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
  226. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
  227. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +1 -0
  228. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  229. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  230. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  231. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  232. package/src/components/DataTable/utils/flexibleImport.ts +2 -2
  233. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  234. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  235. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  236. package/src/components/DataTable/utils/selectFieldUtils.ts +0 -7
  237. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
  238. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  239. package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
  240. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  241. package/src/components/Dialog/Dialog.test.tsx +2007 -407
  242. package/src/components/Dialog/Dialog.tsx +97 -192
  243. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  244. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  245. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  246. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  247. package/src/components/ErrorBoundary/index.ts +3 -4
  248. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  249. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
  250. package/src/components/FileDisplay/FileDisplay.tsx +14 -12
  251. package/src/components/FileDisplay/index.tsx +1 -1
  252. package/src/components/FileUpload/FileUpload.test.tsx +54 -18
  253. package/src/components/FileUpload/FileUpload.tsx +10 -7
  254. package/src/components/FileUpload/index.tsx +1 -1
  255. package/src/components/Footer/Footer.test.tsx +33 -114
  256. package/src/components/Form/Form.test.tsx +388 -68
  257. package/src/components/Form/Form.tsx +57 -42
  258. package/src/components/Header/Header.test.tsx +645 -154
  259. package/src/components/Header/Header.tsx +52 -43
  260. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  261. package/src/components/Input/Input.test.tsx +34 -120
  262. package/src/components/Label/Label.test.tsx +47 -46
  263. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
  264. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  265. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
  266. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  267. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
  268. package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
  269. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
  270. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
  271. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  272. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
  273. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
  274. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
  275. package/src/components/PaceAppLayout/README.md +0 -9
  276. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  277. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
  278. package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
  279. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  280. package/src/components/Progress/Progress.test.tsx +127 -1
  281. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  282. package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
  283. package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
  284. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  285. package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
  286. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
  287. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  288. package/src/components/Select/Select.test.tsx +46 -9
  289. package/src/components/Select/Select.tsx +31 -24
  290. package/src/components/Select/__tests__/context.test.tsx +56 -0
  291. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
  292. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
  293. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
  294. package/src/components/Select/hooks/useSelectState.ts +16 -16
  295. package/src/components/Select/types.ts +3 -0
  296. package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
  297. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  298. package/src/components/Switch/Switch.test.tsx +57 -153
  299. package/src/components/Table/Table.test.tsx +47 -317
  300. package/src/components/Tabs/Tabs.tsx +3 -3
  301. package/src/components/Textarea/Textarea.test.tsx +11 -38
  302. package/src/components/Toast/Toast.test.tsx +78 -569
  303. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  304. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  305. package/src/components/UserMenu/UserMenu.tsx +0 -1
  306. package/src/components/__tests__/index.test.ts +346 -0
  307. package/src/components/index.ts +12 -1
  308. package/src/constants/__tests__/performance.test.ts +91 -0
  309. package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
  310. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
  311. package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
  312. package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
  313. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
  314. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
  315. package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
  316. package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
  317. package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
  318. package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
  319. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
  320. package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
  321. package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
  322. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
  323. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
  324. package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
  325. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
  326. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
  327. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
  328. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
  329. package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
  330. package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
  331. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
  332. package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
  333. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
  334. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
  335. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
  336. package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
  337. package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
  338. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
  339. package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
  340. package/src/hooks/__tests__/useToast.test.ts +413 -0
  341. package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
  342. package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
  343. package/src/hooks/index.ts +13 -1
  344. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  345. package/src/hooks/public/usePublicEvent.ts +11 -11
  346. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  347. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  348. package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
  349. package/src/hooks/public/usePublicFileDisplay.ts +79 -49
  350. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  351. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  352. package/src/hooks/services/useAuthService.ts +1 -1
  353. package/src/hooks/services/useEventService.ts +1 -1
  354. package/src/hooks/useAccessibleApps.test.ts +400 -0
  355. package/src/hooks/useAccessibleApps.ts +264 -0
  356. package/src/hooks/useAddressAutocomplete.test.ts +165 -42
  357. package/src/hooks/useAddressAutocomplete.ts +41 -28
  358. package/src/hooks/useAppConfig.ts +13 -3
  359. package/src/hooks/useDataTablePerformance.ts +13 -12
  360. package/src/hooks/useDataTableState.ts +5 -5
  361. package/src/hooks/useEventTheme.test.ts +66 -17
  362. package/src/hooks/useEventTheme.ts +1 -1
  363. package/src/hooks/useEvents.ts +8 -1
  364. package/src/hooks/useFileDisplay.ts +66 -33
  365. package/src/hooks/useFileReference.test.ts +365 -87
  366. package/src/hooks/useFileReference.ts +2 -6
  367. package/src/hooks/useFileUrlCache.ts +4 -1
  368. package/src/hooks/useFormDialog.ts +2 -2
  369. package/src/hooks/useInactivityTracker.ts +3 -3
  370. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  371. package/src/hooks/useOrganisationPermissions.ts +1 -4
  372. package/src/hooks/useOrganisationSecurity.test.ts +1 -30
  373. package/src/hooks/useOrganisationSecurity.ts +3 -3
  374. package/src/hooks/useOrganisations.ts +1 -1
  375. package/src/hooks/usePerformanceMonitor.ts +1 -1
  376. package/src/hooks/usePermissionCache.ts +2 -6
  377. package/src/hooks/useQueryCache.ts +7 -7
  378. package/src/hooks/useSessionDraft.ts +14 -11
  379. package/src/hooks/useSessionRestoration.ts +1 -1
  380. package/src/hooks/useStorage.ts +75 -40
  381. package/src/hooks/useToast.ts +2 -2
  382. package/src/hooks/useZodForm.ts +3 -3
  383. package/src/icons/__tests__/index.test.ts +133 -0
  384. package/src/icons/index.ts +1 -1
  385. package/src/index.ts +43 -4
  386. package/src/providers/OrganisationProvider.test.tsx +40 -0
  387. package/src/providers/OrganisationProvider.tsx +5 -5
  388. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  389. package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
  390. package/src/providers/__tests__/EventProvider.test.tsx +16 -80
  391. package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
  392. package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
  393. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
  394. package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
  395. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
  396. package/src/providers/__tests__/index.test.ts +138 -0
  397. package/src/providers/services/AuthServiceContext.ts +27 -0
  398. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  399. package/src/providers/services/EventServiceContext.ts +25 -0
  400. package/src/providers/services/EventServiceProvider.tsx +11 -20
  401. package/src/providers/services/InactivityServiceContext.ts +25 -0
  402. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  403. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  404. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  405. package/src/providers/services/UnifiedAuthContext.ts +99 -0
  406. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  407. package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
  408. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
  409. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
  410. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
  411. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
  412. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
  413. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
  414. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
  415. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
  416. package/src/providers/services/__tests__/contexts.test.tsx +281 -0
  417. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
  418. package/src/providers/services/useUnifiedAuth.ts +29 -0
  419. package/src/rbac/README.md +5 -5
  420. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
  421. package/src/rbac/__tests__/audit-batched.test.ts +550 -0
  422. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
  423. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
  424. package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
  425. package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
  426. package/src/rbac/__tests__/index.test.ts +107 -0
  427. package/src/rbac/__tests__/performance.test.ts +451 -0
  428. package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
  429. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
  430. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
  431. package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
  432. package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
  433. package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
  434. package/src/rbac/adapters.test.tsx +654 -0
  435. package/src/rbac/adapters.tsx +24 -9
  436. package/src/rbac/api.test.ts +13 -217
  437. package/src/rbac/api.ts +85 -16
  438. package/src/rbac/audit-batched.ts +5 -4
  439. package/src/rbac/audit.test.ts +225 -28
  440. package/src/rbac/audit.ts +22 -17
  441. package/src/rbac/cache-invalidation.ts +18 -15
  442. package/src/rbac/cache.test.ts +123 -63
  443. package/src/rbac/cache.ts +3 -4
  444. package/src/rbac/components/AccessDenied.tsx +20 -18
  445. package/src/rbac/components/NavigationGuard.tsx +10 -8
  446. package/src/rbac/components/PagePermissionGuard.tsx +27 -25
  447. package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
  448. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
  449. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
  450. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
  451. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
  452. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
  453. package/src/rbac/config.test.ts +131 -48
  454. package/src/rbac/config.ts +11 -8
  455. package/src/rbac/docs/event-based-apps.md +26 -13
  456. package/src/rbac/engine.test.ts +496 -146
  457. package/src/rbac/engine.ts +53 -13
  458. package/src/rbac/errors.test.ts +99 -87
  459. package/src/rbac/eslint-rules.js +2 -2
  460. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
  461. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
  462. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
  463. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
  464. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
  465. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
  466. package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
  467. package/src/rbac/hooks/permissions/useCan.ts +12 -10
  468. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
  469. package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
  470. package/src/rbac/hooks/useCan.test.ts +319 -3
  471. package/src/rbac/hooks/usePermissions.test.ts +426 -0
  472. package/src/rbac/hooks/usePermissions.ts +5 -7
  473. package/src/rbac/hooks/useRBAC.test.ts +1669 -2
  474. package/src/rbac/hooks/useRBAC.ts +7 -11
  475. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  476. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  477. package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
  478. package/src/rbac/hooks/useResourcePermissions.ts +9 -7
  479. package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
  480. package/src/rbac/hooks/useRoleManagement.ts +16 -12
  481. package/src/rbac/hooks/useSecureSupabase.ts +11 -12
  482. package/src/rbac/index.ts +32 -32
  483. package/src/rbac/permissions.test.ts +149 -68
  484. package/src/rbac/permissions.ts +0 -3
  485. package/src/rbac/request-deduplication.test.ts +347 -0
  486. package/src/rbac/secureClient.test.ts +112 -159
  487. package/src/rbac/secureClient.ts +46 -26
  488. package/src/rbac/security.test.ts +125 -44
  489. package/src/rbac/security.ts +7 -6
  490. package/src/rbac/types.test.ts +236 -0
  491. package/src/rbac/types.ts +7 -5
  492. package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
  493. package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
  494. package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
  495. package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
  496. package/src/rbac/utils/clientSecurity.ts +6 -4
  497. package/src/rbac/utils/contextValidator.ts +1 -2
  498. package/src/rbac/utils/eventContext.ts +2 -2
  499. package/src/services/AuthService.ts +13 -11
  500. package/src/services/EventService.ts +4 -5
  501. package/src/services/OrganisationService.ts +13 -30
  502. package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
  503. package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
  504. package/src/services/__tests__/AuthService.test.ts +4 -8
  505. package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
  506. package/src/services/__tests__/BaseService.test.ts +49 -0
  507. package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
  508. package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
  509. package/src/services/__tests__/EventService.test.ts +0 -7
  510. package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
  511. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
  512. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
  513. package/src/services/base/BaseService.test.ts +214 -0
  514. package/src/services/interfaces/IOrganisationService.ts +0 -1
  515. package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
  516. package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
  517. package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
  518. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
  519. package/src/styles/core.css +1 -0
  520. package/src/theming/__tests__/runtime.test.ts +29 -94
  521. package/src/theming/parseEventColours.ts +18 -9
  522. package/src/theming/runtime.ts +1 -5
  523. package/src/types/__tests__/core.test.ts +397 -0
  524. package/src/types/__tests__/database-generated.test.ts +78 -0
  525. package/src/types/__tests__/file-reference.test.ts +270 -366
  526. package/src/types/__tests__/guards.test.ts +26 -26
  527. package/src/types/__tests__/index.test.ts +265 -0
  528. package/src/types/__tests__/type-validation.test.ts +3 -3
  529. package/src/types/__tests__/validation.test.ts +0 -2
  530. package/src/types/auth.ts +0 -1
  531. package/src/types/event.ts +1 -1
  532. package/src/types/rpc-responses.ts +33 -0
  533. package/src/types/supabase.ts +1 -2
  534. package/src/types/vitest-globals.d.ts +1 -1
  535. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
  536. package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
  537. package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
  538. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
  539. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  540. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
  541. package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
  542. package/src/utils/__tests__/request-deduplication.test.ts +349 -0
  543. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
  544. package/src/utils/__tests__/timezone.test.ts +1 -1
  545. package/src/utils/__tests__/validation.unit.test.ts +1 -2
  546. package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
  547. package/src/utils/app/appConfig.test.ts +235 -0
  548. package/src/utils/app/appIdResolver.test.ts +188 -20
  549. package/src/utils/app/appNameResolver.test.ts +18 -10
  550. package/src/utils/app/appNameResolver.ts +11 -9
  551. package/src/utils/app/appPortMap.test.ts +125 -0
  552. package/src/utils/app/appPortMap.ts +51 -0
  553. package/src/utils/app/buildAppUrl.test.ts +273 -0
  554. package/src/utils/app/buildAppUrl.ts +114 -0
  555. package/src/utils/audit/audit.test.ts +354 -39
  556. package/src/utils/context/organisationContext.test.ts +10 -4
  557. package/src/utils/context/organisationContext.ts +5 -5
  558. package/src/utils/context/sessionTracking.test.ts +354 -0
  559. package/src/utils/core/__tests__/cn.test.ts +66 -0
  560. package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
  561. package/src/utils/core/__tests__/logger.test.ts +217 -0
  562. package/src/utils/core/debugLogger.ts +15 -8
  563. package/src/utils/core/logger.ts +20 -16
  564. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  565. package/src/utils/device/deviceFingerprint.ts +3 -3
  566. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
  567. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
  568. package/src/utils/dynamic/createLazyComponent.tsx +38 -0
  569. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  570. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  571. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  572. package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
  573. package/src/utils/file-reference/index.ts +0 -1
  574. package/src/utils/formatting/formatDate.test.ts +22 -148
  575. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  576. package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
  577. package/src/utils/formatting/formatNumber.test.ts +259 -0
  578. package/src/utils/formatting/formatTime.test.ts +36 -128
  579. package/src/utils/formatting/formatting.ts +1 -1
  580. package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
  581. package/src/utils/google-places/googlePlacesUtils.ts +15 -2
  582. package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
  583. package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
  584. package/src/utils/index.ts +52 -11
  585. package/src/utils/location/location.test.ts +18 -115
  586. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
  587. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
  588. package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
  589. package/src/utils/performance/bundleAnalysis.ts +16 -22
  590. package/src/utils/performance/performanceBenchmark.ts +12 -4
  591. package/src/utils/performance/performanceBudgets.ts +9 -6
  592. package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
  593. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  594. package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
  595. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
  596. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  597. package/src/utils/request-deduplication.ts +6 -4
  598. package/src/utils/security/auth-utils.ts +7 -7
  599. package/src/utils/security/secureDataAccess.test.ts +22 -191
  600. package/src/utils/security/secureErrors.test.ts +163 -0
  601. package/src/utils/security/secureStorage.test.ts +156 -0
  602. package/src/utils/security/secureStorage.ts +1 -1
  603. package/src/utils/security/security.test.ts +204 -0
  604. package/src/utils/security/securityMonitor.test.ts +90 -0
  605. package/src/utils/security/securityMonitor.ts +1 -1
  606. package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
  607. package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
  608. package/src/utils/storage/helpers.test.ts +757 -430
  609. package/src/utils/storage/helpers.ts +1 -2
  610. package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
  611. package/src/utils/storage/types.ts +2 -2
  612. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  613. package/src/utils/supabase/createBaseClient.ts +2 -1
  614. package/src/utils/timezone/timezone.test.ts +25 -43
  615. package/src/utils/validation/__tests__/common.test.ts +115 -0
  616. package/src/utils/validation/__tests__/csrf.test.ts +65 -0
  617. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
  618. package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
  619. package/src/utils/validation/__tests__/schema.test.ts +127 -0
  620. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
  621. package/src/utils/validation/__tests__/user.test.ts +173 -0
  622. package/src/utils/validation/__tests__/validation.test.ts +197 -0
  623. package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
  624. package/src/utils/validation/htmlSanitization.ts +27 -31
  625. package/src/utils/validation/schema.ts +6 -3
  626. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  627. package/src/vite-env.d.ts +6 -0
  628. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  629. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  630. package/dist/audit-MYQXYZFU.js +0 -3
  631. package/dist/chunk-7ILTDCL2.js +0 -80
  632. package/dist/chunk-EF2UGZWY.js +0 -611
  633. package/dist/chunk-FEJLJNWA.js +0 -181
  634. package/dist/chunk-GS5672WG.js +0 -2003
  635. package/dist/chunk-S6ZQKDY6.js +0 -62
  636. package/dist/chunk-Z2FNRKF3.js +0 -994
  637. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  638. package/src/components/DataTable/components/index.ts +0 -16
  639. package/src/components/DataTable/core/index.ts +0 -1
  640. package/src/components/DataTable/hooks/index.ts +0 -13
  641. package/src/components/DataTable/utils/index.ts +0 -10
  642. package/src/components/PublicLayout/index.ts +0 -32
  643. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  644. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  645. package/src/hooks/public/index.ts +0 -36
  646. package/src/hooks/usePermissionCache.test.ts +0 -536
  647. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  648. package/src/rbac/audit-enhanced.ts +0 -384
  649. package/src/rbac/compliance/database-validator.ts +0 -165
  650. package/src/rbac/compliance/index.ts +0 -48
  651. package/src/rbac/compliance/pattern-detector.ts +0 -553
  652. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  653. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  654. package/src/rbac/compliance/setup-validator.ts +0 -131
  655. package/src/rbac/components/index.ts +0 -26
  656. package/src/rbac/hooks/index.ts +0 -34
  657. package/src/rbac/hooks/permissions/index.ts +0 -4
  658. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  659. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  660. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  661. package/src/utils/google-places/index.ts +0 -26
  662. package/src/utils/location/index.ts +0 -16
  663. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  664. package/src/utils/timezone/index.ts +0 -17
  665. package/src/utils/validation/index.ts +0 -73
@@ -5,15 +5,14 @@
5
5
  * @since 0.1.0
6
6
  *
7
7
  * A comprehensive header component for application layouts with navigation,
8
- * user menu, organisation selector, event selector, and customizable branding.
8
+ * user menu, context selector, and customizable branding.
9
9
  *
10
10
  * Features:
11
- * - Customizable logo (URL or component)
11
+ * - Customizable logo via URL
12
12
  * - Clickable logo that routes to dashboard (configurable)
13
13
  * - Navigation menu integration
14
14
  * - User menu with authentication
15
- * - Organisation selector for multi-organisation applications
16
- * - Event selector for multi-tenant applications
15
+ * - Context selector for multi-organisation and multi-event applications
17
16
  * - Custom actions support
18
17
  * - Responsive design
19
18
  * - Accessibility compliant
@@ -33,7 +32,7 @@
33
32
  *
34
33
  * // Header with navigation and custom actions
35
34
  * <Header
36
- * logo={<CustomLogo />}
35
+ * logoUrl="/logo.svg"
37
36
  * logoHref="/home"
38
37
  * navItems={[
39
38
  * { id: 'dashboard', label: 'Dashboard', href: '/dashboard' },
@@ -83,17 +82,18 @@
83
82
  * - Tailwind CSS - Styling
84
83
  * - NavigationMenu component
85
84
  * - UserMenu component
86
- * - ContextSelector component (unified org/event selector)
85
+ * - ContextSelector component
87
86
  */
88
87
 
89
88
  import React from 'react';
90
89
  import { Link } from 'react-router-dom';
90
+ import { AppSwitcher } from '../AppSwitcher/AppSwitcher';
91
+ import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
91
92
  import { User } from '@supabase/supabase-js';
92
93
  import { cn } from '../../utils/core/cn';
93
94
  import { ContextSelector } from '../ContextSelector';
94
95
  import { UserMenu } from '../UserMenu';
95
- import { NavigationMenu } from '../NavigationMenu';
96
- import type { NavigationItem } from '../NavigationMenu';
96
+ import { NavigationMenu, type NavigationItem } from '../NavigationMenu';
97
97
  import type { PasswordChangeFormError } from '../PasswordChange/PasswordChangeForm';
98
98
  import { useOrganisations } from '../../hooks/useOrganisations';
99
99
  import { useEvents } from '../../hooks/useEvents';
@@ -107,8 +107,6 @@ export interface HeaderProps {
107
107
  logoUrl?: string;
108
108
  /** Alt text for the logo */
109
109
  logoAlt?: string;
110
- /** Custom logo component (overrides logoUrl) */
111
- logo?: React.ReactNode;
112
110
  /** Navigation items for the menu - uses NavigationItem interface */
113
111
  navItems?: NavigationItem[];
114
112
  /** Current user for the user menu */
@@ -117,13 +115,13 @@ export interface HeaderProps {
117
115
  onSignOut?: () => Promise<void>;
118
116
  /** Password change handler for user menu */
119
117
  onChangePassword?: (newPassword: string, confirmPassword: string) => Promise<{ error?: PasswordChangeFormError }>;
120
- /** Additional actions to display (will be placed between event selector and user menu) */
118
+ /** Additional actions to display (will be placed between context selector and user menu) */
121
119
  actions?: React.ReactNode;
122
120
  /** Custom user menu component (overrides default UserMenu) */
123
121
  userMenu?: React.ReactNode;
124
122
  /** Custom className */
125
123
  className?: string;
126
- /** Show/hide context selector (unified org/event selector) - default: true */
124
+ /** Show/hide context selector - default: true */
127
125
  showContextSelector?: boolean;
128
126
  /** Show organisations in context selector - default: true */
129
127
  showOrganisations?: boolean;
@@ -135,7 +133,7 @@ export interface HeaderProps {
135
133
  currentPath?: string;
136
134
  /** Custom navigation handler */
137
135
  onNavigate?: (item: NavigationItem) => void;
138
- /** URL to navigate to when logo is clicked (e.g., '/dashboard') */
136
+ /** URL to navigate to when logo is clicked (e.g., '/dashboard'). Defaults to '/' if not provided. */
139
137
  logoHref?: string;
140
138
  }
141
139
 
@@ -152,11 +150,11 @@ export interface HeaderProps {
152
150
  * authenticated and public pages.
153
151
  *
154
152
  * Features:
155
- * - Customizable logo (URL or custom component)
153
+ * - Customizable logo via URL
156
154
  * - Clickable logo that automatically routes to dashboard (configurable via logoHref)
157
155
  * - Navigation menu integration with highlighting
158
156
  * - User menu with authentication and password management
159
- * - Event selector for multi-tenant applications
157
+ * - Context selector for multi-organisation and multi-event applications
160
158
  * - Custom actions support
161
159
  * - Responsive design with mobile considerations
162
160
  * - Accessibility compliant with proper ARIA attributes
@@ -242,15 +240,17 @@ export interface HeaderProps {
242
240
  */
243
241
  /**
244
242
  * Header component for application layouts.
245
- * Provides navigation, user menu, organisation/event selectors, and customizable branding.
243
+ * Provides navigation, user menu, context selector, and customizable branding.
246
244
  *
247
245
  * @param props - Header configuration
248
246
  * @returns The rendered header
249
247
  */
248
+ // Default logo SVG data URL (simple white square 32x32)
249
+ const DEFAULT_LOGO_SRC = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmYiLz48L3N2Zz4=';
250
+
250
251
  export function Header({
251
252
  logoUrl,
252
253
  logoAlt = 'Logo',
253
- logo,
254
254
  navItems = [],
255
255
  user,
256
256
  onSignOut,
@@ -272,55 +272,68 @@ export function Header({
272
272
  // Get hooks for context selector
273
273
  const { switchOrganisation } = useOrganisations();
274
274
  const { events, setSelectedEvent } = useEvents();
275
+
276
+ // Get app name for app switcher (only if user is authenticated)
277
+ const authContext = useUnifiedAuth();
278
+ const isAuthenticated = authContext?.isAuthenticated ?? false;
279
+ const appName = authContext?.appName;
275
280
 
276
281
  return (
277
282
  <header className={cn(
278
283
  "w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
279
284
  className
280
285
  )} role="banner">
281
- <nav className="px-4 w-[min(var(--app-width),100%)] mx-auto grid grid-cols-[auto_1fr_auto_auto_auto_auto] items-center gap-4 h-full">
282
- {/* Logo */}
283
- {logo ? (
284
- logoHref ? (
285
- <Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity">
286
- {logo}
287
- </Link>
288
- ) : (
289
- logo
290
- )
291
- ) : logoUrl ? (
286
+ <nav className={cn(
287
+ "px-4 w-[min(var(--app-width),100%)] mx-auto grid items-center gap-4 h-full",
288
+ isAuthenticated && appName
289
+ ? "grid-cols-[auto_auto_1fr_auto_auto]"
290
+ : "grid-cols-[auto_1fr_auto_auto]"
291
+ )}>
292
+ {/* PACE Logo with App Switcher (if authenticated) */}
293
+ {isAuthenticated && appName && (
294
+ <AppSwitcher
295
+ currentAppName={appName}
296
+ className="w-9"
297
+ />
298
+ )}
299
+
300
+ {/* App Logo (regular link, not app switcher) */}
301
+ {logoUrl && (
292
302
  logoHref ? (
293
- <Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity">
303
+ <Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity flex items-center">
294
304
  <img
295
305
  src={logoUrl}
296
306
  alt={logoAlt || 'Logo'}
297
- className="h-[2.15rem] w-auto max-w-[200px] object-contain rounded-md shadow-md bg-transparent"
307
+ className="h-9 w-auto shadow-md"
298
308
  />
299
309
  </Link>
300
310
  ) : (
301
311
  <img
302
312
  src={logoUrl}
303
313
  alt={logoAlt || 'Logo'}
304
- className="h-[2.15rem] w-auto max-w-[200px] object-contain rounded-md shadow-md bg-transparent"
314
+ className="h-9 w-auto shadow-md"
305
315
  />
306
316
  )
307
- ) : (
317
+ )}
318
+ {!logoUrl && (
319
+ // Default logo when logoUrl is not provided
308
320
  logoHref ? (
309
- <Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity">
321
+ <Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity flex items-center">
310
322
  <img
311
- src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23000'/%3E%3Ctext x='16' y='20' text-anchor='middle' fill='white' font-family='Arial' font-size='14' font-weight='bold'%3EL%3C/text%3E%3C/svg%3E"
323
+ src={DEFAULT_LOGO_SRC}
312
324
  alt={logoAlt || 'Logo'}
313
- className="size-8 shadow-md"
325
+ className="h-9 w-auto shadow-md"
314
326
  />
315
327
  </Link>
316
328
  ) : (
317
329
  <img
318
- src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23000'/%3E%3Ctext x='16' y='20' text-anchor='middle' fill='white' font-family='Arial' font-size='14' font-weight='bold'%3EL%3C/text%3E%3C/svg%3E"
330
+ src={DEFAULT_LOGO_SRC}
319
331
  alt={logoAlt || 'Logo'}
320
- className="size-8 shadow-md"
332
+ className="h-9 w-auto shadow-md"
321
333
  />
322
334
  )
323
335
  )}
336
+
324
337
 
325
338
  {/* Navigation Menu */}
326
339
  {navItems && navItems.length > 0 && (
@@ -334,15 +347,11 @@ export function Header({
334
347
  />
335
348
  )}
336
349
 
337
- {/* Unified Context Selector - Shows all accessible orgs and events */}
350
+ {/* Context Selector - Shows all accessible orgs and events */}
338
351
  {shouldShowContextSelector ? (
339
352
  <ContextSelector
340
353
  placeholder="Select organisation or event"
341
- className={cn(
342
- "w-96",
343
- // Adjust width based on whether actions exist
344
- actions ? "col-span-1" : "col-span-2"
345
- )}
354
+ className="w-96"
346
355
  showOrganisations={showOrganisations}
347
356
  showEvents={showEvents}
348
357
  onOrganisationSelect={async (org) => {
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import React from 'react';
8
- import { screen, waitFor } from '@testing-library/react';
8
+ import { screen } from '@testing-library/react';
9
9
  import userEvent from '@testing-library/user-event';
10
10
  import { describe, it, expect, vi, beforeEach } from 'vitest';
11
11
  import { InactivityWarningModal } from './InactivityWarningModal';
@@ -13,7 +13,7 @@ import { renderWithProviders } from '../../__tests__/helpers/test-utils';
13
13
 
14
14
  // Mock the Dialog components to avoid complex modal behavior in tests
15
15
  vi.mock('../Dialog/Dialog', () => ({
16
- Dialog: ({ children, open, onOpenChange }: { children: React.ReactNode; open: boolean; onOpenChange: (open: boolean) => void }) =>
16
+ Dialog: ({ children, open, _onOpenChange }: { children: React.ReactNode; open: boolean; _onOpenChange: (open: boolean) => void }) =>
17
17
  open ? <div data-testid="dialog" role="dialog">{children}</div> : null,
18
18
  DialogContent: ({ children, className, preventCloseOnEscape, preventCloseOnOutsideClick, ...props }: any) => (
19
19
  <div
@@ -110,34 +110,16 @@ describe('InactivityWarningModal Component', () => {
110
110
  expect(modal).toHaveClass('custom-modal');
111
111
  });
112
112
 
113
- it('renders countdown timer with correct time format', () => {
114
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={125} />);
113
+ it.each([
114
+ { timeRemaining: 0, expected: '00:00' },
115
+ { timeRemaining: 5, expected: '00:05' },
116
+ { timeRemaining: 60, expected: '01:00' },
117
+ { timeRemaining: 65, expected: '01:05' },
118
+ { timeRemaining: 125, expected: '02:05' },
119
+ ])('renders countdown timer with correct format (timeRemaining: $timeRemaining)', ({ timeRemaining, expected }) => {
120
+ renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={timeRemaining} />);
115
121
 
116
- expect(screen.getByText('02:05')).toBeInTheDocument();
117
- });
118
-
119
- it('renders countdown timer with single digit minutes', () => {
120
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={65} />);
121
-
122
- expect(screen.getByText('01:05')).toBeInTheDocument();
123
- });
124
-
125
- it('renders countdown timer with zero seconds', () => {
126
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={60} />);
127
-
128
- expect(screen.getByText('01:00')).toBeInTheDocument();
129
- });
130
-
131
- it('renders countdown timer with single digit seconds', () => {
132
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={5} />);
133
-
134
- expect(screen.getByText('00:05')).toBeInTheDocument();
135
- });
136
-
137
- it('renders countdown timer with zero time', () => {
138
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={0} />);
139
-
140
- expect(screen.getByText('00:00')).toBeInTheDocument();
122
+ expect(screen.getByText(expected)).toBeInTheDocument();
141
123
  });
142
124
 
143
125
  it('renders action buttons with correct text', () => {
@@ -162,25 +144,20 @@ describe('InactivityWarningModal Component', () => {
162
144
  });
163
145
 
164
146
  describe('Time Formatting', () => {
165
- it('formats time correctly for various values', () => {
166
- const testCases = [
167
- { input: 0, expected: '00:00' },
168
- { input: 5, expected: '00:05' },
169
- { input: 30, expected: '00:30' },
170
- { input: 60, expected: '01:00' },
171
- { input: 90, expected: '01:30' },
172
- { input: 125, expected: '02:05' },
173
- { input: 3661, expected: '61:01' },
174
- ];
175
-
176
- testCases.forEach(({ input, expected }) => {
177
- const { unmount } = renderWithProviders(
178
- <InactivityWarningModal {...baseProps} timeRemaining={input} />
179
- );
180
-
181
- expect(screen.getByText(expected)).toBeInTheDocument();
182
- unmount();
183
- });
147
+ it.each([
148
+ { input: 0, expected: '00:00' },
149
+ { input: 5, expected: '00:05' },
150
+ { input: 30, expected: '00:30' },
151
+ { input: 60, expected: '01:00' },
152
+ { input: 90, expected: '01:30' },
153
+ { input: 125, expected: '02:05' },
154
+ { input: 3661, expected: '61:01' },
155
+ ])('formats time correctly (input: $input, expected: $expected)', ({ input, expected }) => {
156
+ renderWithProviders(
157
+ <InactivityWarningModal {...baseProps} timeRemaining={input} />
158
+ );
159
+
160
+ expect(screen.getByText(expected)).toBeInTheDocument();
184
161
  });
185
162
 
186
163
  it('updates display time when timeRemaining prop changes', () => {
@@ -318,20 +295,16 @@ describe('InactivityWarningModal Component', () => {
318
295
  });
319
296
 
320
297
  describe('Edge Cases', () => {
321
- it('handles negative time values gracefully', () => {
322
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={-5} />);
298
+ it.each([
299
+ { timeRemaining: -5, expected: '-1:-5', description: 'negative time' },
300
+ { timeRemaining: 999999, expected: '16666:39', description: 'very large time' },
301
+ ])('handles $description gracefully', ({ timeRemaining, expected }) => {
302
+ renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={timeRemaining} />);
323
303
 
324
- // Should still render, but with negative time formatted as the component actually does it
325
- expect(screen.getByText('-1:-5')).toBeInTheDocument();
304
+ expect(screen.getByText(expected)).toBeInTheDocument();
326
305
  });
327
306
 
328
- it('handles very large time values', () => {
329
- renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={999999} />);
330
-
331
- expect(screen.getByText('16666:39')).toBeInTheDocument();
332
- });
333
-
334
- it('handles undefined title and description', () => {
307
+ it('uses default title and description when undefined', () => {
335
308
  const propsWithoutDefaults = {
336
309
  isOpen: true,
337
310
  timeRemaining: 30,
@@ -343,12 +316,11 @@ describe('InactivityWarningModal Component', () => {
343
316
 
344
317
  renderWithProviders(<InactivityWarningModal {...propsWithoutDefaults} />);
345
318
 
346
- // Should use default values
347
319
  expect(screen.getByText('Session Timeout Warning')).toBeInTheDocument();
348
320
  expect(screen.getByText("You've been inactive for a while. Your session will expire soon for security reasons.")).toBeInTheDocument();
349
321
  });
350
322
 
351
- it('handles empty string title and description', () => {
323
+ it('renders empty strings when title and description are empty', () => {
352
324
  renderWithProviders(
353
325
  <InactivityWarningModal
354
326
  {...baseProps}
@@ -357,13 +329,8 @@ describe('InactivityWarningModal Component', () => {
357
329
  />
358
330
  );
359
331
 
360
- // Should render empty strings - title is h2, description is p in DialogHeader
361
332
  const title = screen.getByRole('heading', { level: 2 });
362
- const description = screen.getByText(/Time remaining/i).closest('div')?.previousElementSibling?.querySelector('p');
363
333
  expect(title).toHaveTextContent('');
364
- if (description) {
365
- expect(description).toHaveTextContent('');
366
- }
367
334
  });
368
335
  });
369
336
 
@@ -439,21 +406,14 @@ describe('InactivityWarningModal Component', () => {
439
406
 
440
407
  renderWithProviders(<InactivityWarningModal {...propsWithoutCallbacks} />);
441
408
 
442
- // Should render without errors
443
409
  expect(screen.getByTestId('dialog')).toBeInTheDocument();
444
410
  expect(screen.getByRole('button', { name: 'Stay Signed In' })).toBeInTheDocument();
445
411
  expect(screen.getByRole('button', { name: 'Sign Out Now' })).toBeInTheDocument();
446
412
  });
447
413
 
448
- it('handles invalid timeRemaining values', () => {
449
- const invalidTimeProps = {
450
- ...baseProps,
451
- timeRemaining: NaN,
452
- };
453
-
454
- renderWithProviders(<InactivityWarningModal {...invalidTimeProps} />);
414
+ it('handles invalid timeRemaining values (NaN)', () => {
415
+ renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={NaN} />);
455
416
 
456
- // Should render with NaN formatted as "NaN:NaN" or handle gracefully
457
417
  expect(screen.getByTestId('dialog')).toBeInTheDocument();
458
418
  });
459
419
  });
@@ -473,7 +433,6 @@ describe('InactivityWarningModal Component', () => {
473
433
  <InactivityWarningModal {...stableProps} />
474
434
  );
475
435
 
476
- const initialTime = screen.getByText('00:30');
477
436
 
478
437
  // Re-render with same props
479
438
  rerender(<InactivityWarningModal {...stableProps} />);
@@ -59,47 +59,25 @@ describe('Input Component', () => {
59
59
  });
60
60
 
61
61
  describe('Variants', () => {
62
- it('renders with default variant', () => {
63
- renderWithProviders(<Input variant="default" />);
62
+ it.each([
63
+ { variant: 'default' as const, description: 'default variant' },
64
+ { variant: 'destructive' as const, description: 'destructive variant' },
65
+ { error: true, description: 'error prop' },
66
+ ])('renders with $description', (props) => {
67
+ renderWithProviders(<Input {...props} />);
64
68
  const input = screen.getByRole('textbox');
65
69
  expect(input).toBeInTheDocument();
66
70
  expect(input).toBeVisible();
67
71
  });
68
-
69
- it('renders with destructive variant', () => {
70
- renderWithProviders(<Input variant="destructive" />);
71
- const input = screen.getByRole('textbox');
72
- // Verify destructive variant is rendered (behavior-based check)
73
- expect(input).toBeInTheDocument();
74
- expect(input).toBeVisible();
75
- });
76
-
77
- it('applies destructive styling when error is true', () => {
78
- renderWithProviders(<Input error={true} />);
79
- const input = screen.getByRole('textbox');
80
- // Verify error state is applied (behavior-based check)
81
- expect(input).toBeInTheDocument();
82
- expect(input).toBeVisible();
83
- });
84
72
  });
85
73
 
86
74
  describe('Sizes', () => {
87
- it('renders with small size', () => {
88
- renderWithProviders(<Input size="sm" />);
89
- const input = screen.getByRole('textbox');
90
- expect(input).toBeInTheDocument();
91
- expect(input).toBeVisible();
92
- });
93
-
94
- it('renders with medium size (default)', () => {
95
- renderWithProviders(<Input size="md" />);
96
- const input = screen.getByRole('textbox');
97
- expect(input).toBeInTheDocument();
98
- expect(input).toBeVisible();
99
- });
100
-
101
- it('renders with large size', () => {
102
- renderWithProviders(<Input size="lg" />);
75
+ it.each([
76
+ { size: 'sm' as const },
77
+ { size: 'md' as const },
78
+ { size: 'lg' as const },
79
+ ])('renders with $size size', ({ size }) => {
80
+ renderWithProviders(<Input size={size} />);
103
81
  const input = screen.getByRole('textbox');
104
82
  expect(input).toBeInTheDocument();
105
83
  expect(input).toBeVisible();
@@ -228,16 +206,22 @@ describe('Input Component', () => {
228
206
  it('handles error state styling', () => {
229
207
  renderWithProviders(<Input error={true} />);
230
208
  const input = screen.getByRole('textbox');
231
- // Verify error state is applied (behavior-based check)
232
209
  expect(input).toBeInTheDocument();
233
210
  expect(input).toBeVisible();
234
211
  });
235
212
 
236
- it('handles invalid input gracefully', () => {
213
+ it('handles invalid input values gracefully', () => {
237
214
  renderWithProviders(<Input type="email" value="invalid-email" />);
238
215
  const input = screen.getByRole('textbox');
239
216
  expect(input).toHaveValue('invalid-email');
240
217
  });
218
+
219
+ it('handles readOnly state', () => {
220
+ renderWithProviders(<Input readOnly value="readonly value" />);
221
+ const input = screen.getByRole('textbox');
222
+ expect(input).toHaveAttribute('readonly');
223
+ expect(input).toHaveValue('readonly value');
224
+ });
241
225
  });
242
226
 
243
227
  // Integration tests
@@ -310,108 +294,38 @@ describe('InputGroup Component', () => {
310
294
  });
311
295
 
312
296
  describe('Orientation', () => {
313
- it('renders with vertical orientation (default)', () => {
297
+ it.each([
298
+ { orientation: 'vertical' as const },
299
+ { orientation: 'horizontal' as const },
300
+ ])('renders with $orientation orientation', ({ orientation }) => {
314
301
  renderWithProviders(
315
- <InputGroup orientation="vertical">
302
+ <InputGroup orientation={orientation}>
316
303
  <Input placeholder="Input 1" />
317
304
  <Input placeholder="Input 2" />
318
305
  </InputGroup>
319
306
  );
320
307
 
321
- // Verify inputs are rendered (behavior-based check)
322
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
323
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
324
- });
325
-
326
- it('renders with horizontal orientation', () => {
327
- renderWithProviders(
328
- <InputGroup orientation="horizontal">
329
- <Input placeholder="Input 1" />
330
- <Input placeholder="Input 2" />
331
- </InputGroup>
332
- );
333
-
334
- // Verify inputs are rendered (behavior-based check)
335
308
  expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
336
309
  expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
337
310
  });
338
311
  });
339
312
 
340
313
  describe('Spacing', () => {
341
- it('applies small spacing for vertical orientation', () => {
342
- renderWithProviders(
343
- <InputGroup orientation="vertical" spacing="sm">
344
- <Input placeholder="Input 1" />
345
- <Input placeholder="Input 2" />
346
- </InputGroup>
347
- );
348
-
349
- // Verify inputs are rendered with spacing (behavior-based check)
350
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
351
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
352
- });
353
-
354
- it('applies medium spacing for vertical orientation (default)', () => {
355
- renderWithProviders(
356
- <InputGroup orientation="vertical" spacing="md">
357
- <Input placeholder="Input 1" />
358
- <Input placeholder="Input 2" />
359
- </InputGroup>
360
- );
361
-
362
- // Verify inputs are rendered with spacing (behavior-based check)
363
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
364
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
365
- });
366
-
367
- it('applies large spacing for vertical orientation', () => {
368
- renderWithProviders(
369
- <InputGroup orientation="vertical" spacing="lg">
370
- <Input placeholder="Input 1" />
371
- <Input placeholder="Input 2" />
372
- </InputGroup>
373
- );
374
-
375
- // Verify inputs are rendered with spacing (behavior-based check)
376
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
377
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
378
- });
379
-
380
- it('applies small spacing for horizontal orientation', () => {
381
- renderWithProviders(
382
- <InputGroup orientation="horizontal" spacing="sm">
383
- <Input placeholder="Input 1" />
384
- <Input placeholder="Input 2" />
385
- </InputGroup>
386
- );
387
-
388
- // Verify inputs are rendered with spacing (behavior-based check)
389
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
390
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
391
- });
392
-
393
- it('applies medium spacing for horizontal orientation (default)', () => {
394
- renderWithProviders(
395
- <InputGroup orientation="horizontal" spacing="md">
396
- <Input placeholder="Input 1" />
397
- <Input placeholder="Input 2" />
398
- </InputGroup>
399
- );
400
-
401
- // Verify inputs are rendered with spacing (behavior-based check)
402
- expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
403
- expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
404
- });
405
-
406
- it('applies large spacing for horizontal orientation', () => {
314
+ it.each([
315
+ { orientation: 'vertical' as const, spacing: 'sm' as const },
316
+ { orientation: 'vertical' as const, spacing: 'md' as const },
317
+ { orientation: 'vertical' as const, spacing: 'lg' as const },
318
+ { orientation: 'horizontal' as const, spacing: 'sm' as const },
319
+ { orientation: 'horizontal' as const, spacing: 'md' as const },
320
+ { orientation: 'horizontal' as const, spacing: 'lg' as const },
321
+ ])('applies $spacing spacing for $orientation orientation', ({ orientation, spacing }) => {
407
322
  renderWithProviders(
408
- <InputGroup orientation="horizontal" spacing="lg">
323
+ <InputGroup orientation={orientation} spacing={spacing}>
409
324
  <Input placeholder="Input 1" />
410
325
  <Input placeholder="Input 2" />
411
326
  </InputGroup>
412
327
  );
413
328
 
414
- // Verify inputs are rendered with spacing (behavior-based check)
415
329
  expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
416
330
  expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
417
331
  });