@jmruthers/pace-core 0.5.181 → 0.5.182

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 (750) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +16 -2
  3. package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
  4. package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
  5. package/dist/{DataTable-UA6CL4JI.js → DataTable-QAB34V6K.js} +14 -15
  6. package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
  7. package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
  8. package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
  9. package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
  10. package/dist/auth-BZOJqrdd.d.ts +49 -0
  11. package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
  12. package/dist/chunk-5DRSZLL2.js.map +1 -0
  13. package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
  14. package/dist/chunk-6C4YBBJM.js.map +1 -0
  15. package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
  16. package/dist/{chunk-HRO5HWN2.js → chunk-CSOFYHAG.js} +55 -162
  17. package/dist/chunk-CSOFYHAG.js.map +1 -0
  18. package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
  19. package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
  20. package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
  21. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  22. package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
  23. package/dist/chunk-FSFQFJCU.js.map +1 -0
  24. package/dist/chunk-FUEYYMX5.js +2296 -0
  25. package/dist/chunk-FUEYYMX5.js.map +1 -0
  26. package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
  27. package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
  28. package/dist/chunk-KQCRWDSA.js +1 -0
  29. package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
  30. package/dist/chunk-KUEN3HFB.js.map +1 -0
  31. package/dist/chunk-LMC26NLJ.js +84 -0
  32. package/dist/chunk-LMC26NLJ.js.map +1 -0
  33. package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
  34. package/dist/chunk-M7W4CP3M.js.map +1 -0
  35. package/dist/{chunk-HZLDFOE4.js → chunk-MI7HBHN3.js} +164 -243
  36. package/dist/chunk-MI7HBHN3.js.map +1 -0
  37. package/dist/{chunk-PPMP5J6T.js → chunk-PWAHJW4G.js} +180 -29
  38. package/dist/chunk-PWAHJW4G.js.map +1 -0
  39. package/dist/chunk-PWLANIRT.js +127 -0
  40. package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
  41. package/dist/chunk-QCDXODCA.js +75 -0
  42. package/dist/chunk-QCDXODCA.js.map +1 -0
  43. package/dist/{chunk-D7LCGMVS.js → chunk-QETLRQI6.js} +526 -887
  44. package/dist/chunk-QETLRQI6.js.map +1 -0
  45. package/dist/{chunk-5MT24GKJ.js → chunk-QUVSNGIP.js} +264 -262
  46. package/dist/chunk-QUVSNGIP.js.map +1 -0
  47. package/dist/chunk-QXHPKYJV.js +113 -0
  48. package/dist/chunk-QXHPKYJV.js.map +1 -0
  49. package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
  50. package/dist/chunk-R77UEZ4E.js.map +1 -0
  51. package/dist/{chunk-ZYTYSTO5.js → chunk-RA3JUFMW.js} +314 -161
  52. package/dist/chunk-RA3JUFMW.js.map +1 -0
  53. package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
  54. package/dist/chunk-SQGMNID3.js.map +1 -0
  55. package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
  56. package/dist/chunk-UHNYIBXL.js.map +1 -0
  57. package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
  58. package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
  59. package/dist/{chunk-VZ4VDGTB.js → chunk-W22JP75J.js} +5 -13
  60. package/dist/{chunk-VZ4VDGTB.js.map → chunk-W22JP75J.js.map} +1 -1
  61. package/dist/components.d.ts +12 -93
  62. package/dist/components.js +23 -106
  63. package/dist/components.js.map +1 -1
  64. package/dist/core-CUElvH_C.d.ts +164 -0
  65. package/dist/database.generated-CBmg2950.d.ts +8284 -0
  66. package/dist/event-CW5YB_2p.d.ts +239 -0
  67. package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
  68. package/dist/functions-D_kgHktt.d.ts +208 -0
  69. package/dist/hooks.d.ts +54 -7
  70. package/dist/hooks.js +204 -17
  71. package/dist/hooks.js.map +1 -1
  72. package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
  73. package/dist/index.d.ts +94 -261
  74. package/dist/index.js +314 -126
  75. package/dist/index.js.map +1 -1
  76. package/dist/providers.d.ts +7 -8
  77. package/dist/providers.js +6 -13
  78. package/dist/rbac/index.d.ts +171 -101
  79. package/dist/rbac/index.js +23 -17
  80. package/dist/styles/index.d.ts +1 -3
  81. package/dist/styles/index.js +2 -17
  82. package/dist/theming/runtime.js +3 -3
  83. package/dist/types-UU913iLA.d.ts +102 -0
  84. package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
  85. package/dist/types.d.ts +88 -227
  86. package/dist/types.js +64 -112
  87. package/dist/types.js.map +1 -1
  88. package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
  89. package/dist/utils.d.ts +299 -13
  90. package/dist/utils.js +481 -55
  91. package/dist/utils.js.map +1 -1
  92. package/dist/validation-643vUDZW.d.ts +177 -0
  93. package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
  94. package/docs/README.md +9 -8
  95. package/docs/api/README.md +16 -2
  96. package/docs/api/classes/ColumnFactory.md +1 -1
  97. package/docs/api/classes/ErrorBoundary.md +1 -1
  98. package/docs/api/classes/InvalidScopeError.md +4 -4
  99. package/docs/api/classes/MissingUserContextError.md +4 -4
  100. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  101. package/docs/api/classes/PermissionDeniedError.md +4 -4
  102. package/docs/api/classes/RBACAuditManager.md +14 -14
  103. package/docs/api/classes/RBACCache.md +1 -1
  104. package/docs/api/classes/RBACEngine.md +2 -2
  105. package/docs/api/classes/RBACError.md +4 -4
  106. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  107. package/docs/api/classes/SecureSupabaseClient.md +29 -9
  108. package/docs/api/classes/StorageUtils.md +1 -1
  109. package/docs/api/enums/FileCategory.md +17 -17
  110. package/docs/api/enums/RBACErrorCode.md +228 -0
  111. package/docs/api/enums/RPCFunction.md +118 -0
  112. package/docs/api/interfaces/AggregateConfig.md +1 -1
  113. package/docs/api/interfaces/BadgeProps.md +1 -1
  114. package/docs/api/interfaces/ButtonProps.md +2 -2
  115. package/docs/api/interfaces/CalendarProps.md +1 -1
  116. package/docs/api/interfaces/CardProps.md +29 -3
  117. package/docs/api/interfaces/ColorPalette.md +1 -1
  118. package/docs/api/interfaces/ColorShade.md +1 -1
  119. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  120. package/docs/api/interfaces/DataRecord.md +1 -1
  121. package/docs/api/interfaces/DataTableAction.md +2 -2
  122. package/docs/api/interfaces/DataTableColumn.md +6 -6
  123. package/docs/api/interfaces/DataTableProps.md +1 -1
  124. package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
  125. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  126. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  127. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  128. package/docs/api/interfaces/ExportColumn.md +5 -5
  129. package/docs/api/interfaces/ExportOptions.md +4 -4
  130. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  131. package/docs/api/interfaces/FileMetadata.md +13 -13
  132. package/docs/api/interfaces/FileReference.md +12 -12
  133. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  134. package/docs/api/interfaces/FileUploadOptions.md +10 -10
  135. package/docs/api/interfaces/FileUploadProps.md +19 -19
  136. package/docs/api/interfaces/FooterProps.md +1 -1
  137. package/docs/api/interfaces/FormFieldProps.md +166 -0
  138. package/docs/api/interfaces/FormProps.md +113 -0
  139. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  140. package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
  141. package/docs/api/interfaces/InputProps.md +2 -2
  142. package/docs/api/interfaces/LabelProps.md +8 -8
  143. package/docs/api/interfaces/LoginFormProps.md +1 -1
  144. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  145. package/docs/api/interfaces/NavigationContextType.md +1 -1
  146. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  147. package/docs/api/interfaces/NavigationItem.md +17 -73
  148. package/docs/api/interfaces/NavigationMenuProps.md +38 -53
  149. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  150. package/docs/api/interfaces/Organisation.md +13 -13
  151. package/docs/api/interfaces/OrganisationContextType.md +21 -21
  152. package/docs/api/interfaces/OrganisationMembership.md +15 -15
  153. package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
  154. package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
  155. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
  156. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  157. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  158. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  159. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  160. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  161. package/docs/api/interfaces/PaletteData.md +1 -1
  162. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  163. package/docs/api/interfaces/ProgressProps.md +50 -0
  164. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  165. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  166. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  167. package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
  168. package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
  169. package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
  170. package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
  171. package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
  172. package/docs/api/interfaces/RBACConfig.md +2 -2
  173. package/docs/api/interfaces/RBACContext.md +52 -0
  174. package/docs/api/interfaces/RBACLogger.md +1 -1
  175. package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
  176. package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
  177. package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
  178. package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
  179. package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
  180. package/docs/api/interfaces/RBACResult.md +58 -0
  181. package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
  182. package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
  183. package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
  184. package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
  185. package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
  186. package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
  187. package/docs/api/interfaces/RBACRolesListParams.md +52 -0
  188. package/docs/api/interfaces/RBACRolesListResult.md +74 -0
  189. package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
  190. package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
  191. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  192. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  193. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  194. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  195. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  196. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  197. package/docs/api/interfaces/RouteConfig.md +1 -1
  198. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  199. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  200. package/docs/api/interfaces/SessionRestorationLoaderProps.md +15 -2
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +43 -2
  215. package/docs/api/interfaces/TextareaProps.md +2 -2
  216. package/docs/api/interfaces/ToastActionElement.md +1 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  220. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  221. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  222. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  223. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  224. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  225. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  226. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  227. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  228. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  229. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  230. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  231. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  232. package/docs/api/interfaces/UserEventAccess.md +1 -1
  233. package/docs/api/interfaces/UserMenuProps.md +4 -4
  234. package/docs/api/interfaces/UserProfile.md +7 -7
  235. package/docs/api/modules.md +484 -462
  236. package/docs/api-reference/components.md +186 -15
  237. package/docs/api-reference/deprecated.md +376 -0
  238. package/docs/api-reference/hooks.md +149 -19
  239. package/docs/api-reference/providers.md +61 -6
  240. package/docs/api-reference/rpc-functions.md +397 -0
  241. package/docs/api-reference/types.md +135 -78
  242. package/docs/api-reference/utilities.md +51 -380
  243. package/docs/architecture/README.md +49 -3
  244. package/docs/architecture/database-schema-requirements.md +40 -3
  245. package/docs/architecture/rbac-security-architecture.md +41 -4
  246. package/docs/architecture/services.md +127 -42
  247. package/docs/best-practices/README.md +51 -5
  248. package/docs/best-practices/accessibility.md +32 -3
  249. package/docs/best-practices/common-patterns.md +50 -3
  250. package/docs/best-practices/deployment.md +50 -4
  251. package/docs/best-practices/performance.md +50 -3
  252. package/docs/best-practices/security.md +94 -41
  253. package/docs/best-practices/testing.md +33 -4
  254. package/docs/core-concepts/authentication.md +5 -5
  255. package/docs/core-concepts/events.md +3 -3
  256. package/docs/core-concepts/organisations.md +3 -3
  257. package/docs/core-concepts/permissions.md +3 -3
  258. package/docs/core-concepts/rbac-system.md +5 -5
  259. package/docs/documentation-index.md +30 -8
  260. package/docs/getting-started/documentation-index.md +1 -1
  261. package/docs/getting-started/examples/README.md +7 -5
  262. package/docs/getting-started/examples/basic-auth-app.md +3 -0
  263. package/docs/getting-started/examples/full-featured-app.md +5 -3
  264. package/docs/getting-started/faq.md +6 -6
  265. package/docs/getting-started/installation-guide.md +192 -13
  266. package/docs/getting-started/local-development.md +303 -0
  267. package/docs/getting-started/quick-reference.md +3 -3
  268. package/docs/getting-started/quick-start.md +517 -0
  269. package/docs/implementation-guides/app-layout.md +45 -3
  270. package/docs/implementation-guides/authentication.md +66 -7
  271. package/docs/implementation-guides/component-styling.md +53 -3
  272. package/docs/implementation-guides/data-tables.md +76 -7
  273. package/docs/implementation-guides/datatable-filtering.md +1 -2
  274. package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
  275. package/docs/implementation-guides/dynamic-colors.md +155 -4
  276. package/docs/implementation-guides/file-reference-system.md +72 -3
  277. package/docs/implementation-guides/file-upload-storage.md +72 -3
  278. package/docs/implementation-guides/forms.md +53 -3
  279. package/docs/implementation-guides/inactivity-tracking.md +53 -3
  280. package/docs/implementation-guides/large-datasets.md +1 -1
  281. package/docs/implementation-guides/navigation.md +55 -5
  282. package/docs/implementation-guides/organisation-security.md +72 -3
  283. package/docs/implementation-guides/performance.md +57 -1
  284. package/docs/implementation-guides/permission-enforcement.md +81 -8
  285. package/docs/implementation-guides/public-pages.md +560 -14
  286. package/docs/migration/MIGRATION_GUIDE.md +409 -50
  287. package/docs/migration/README.md +37 -3
  288. package/docs/migration/organisation-context-timing-fix.md +39 -4
  289. package/docs/migration/quick-migration-guide.md +41 -5
  290. package/docs/migration/rbac-migration.md +59 -3
  291. package/docs/migration/service-architecture.md +77 -14
  292. package/docs/rbac/README.md +79 -3
  293. package/docs/rbac/advanced-patterns.md +47 -3
  294. package/docs/rbac/api-reference.md +77 -8
  295. package/docs/rbac/event-based-apps.md +50 -5
  296. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  297. package/docs/rbac/examples.md +39 -3
  298. package/docs/rbac/getting-started.md +63 -4
  299. package/docs/rbac/quick-start.md +57 -5
  300. package/docs/rbac/rbac-rls-integration.md +68 -6
  301. package/docs/rbac/super-admin-guide.md +47 -3
  302. package/docs/rbac/troubleshooting.md +3 -3
  303. package/docs/security/README.md +68 -3
  304. package/docs/security/checklist.md +50 -3
  305. package/docs/standards/01-architecture-standard.md +39 -0
  306. package/docs/standards/02-api-and-rpc-standard.md +39 -0
  307. package/docs/standards/03-component-standard.md +32 -0
  308. package/docs/standards/04-code-style-standard.md +32 -0
  309. package/docs/standards/05-security-standard.md +30 -0
  310. package/docs/standards/06-testing-and-docs-standard.md +29 -0
  311. package/docs/standards/README.md +35 -0
  312. package/docs/styles/README.md +89 -8
  313. package/docs/testing/README.md +175 -24
  314. package/docs/troubleshooting/README.md +50 -3
  315. package/docs/troubleshooting/common-issues.md +271 -5
  316. package/docs/troubleshooting/debugging.md +54 -1
  317. package/docs/troubleshooting/migration.md +54 -1
  318. package/docs/troubleshooting/organisation-context-setup.md +29 -3
  319. package/docs/troubleshooting/styling-issues.md +246 -4
  320. package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
  321. package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
  322. package/{src/components/DataTable/examples → examples/DataTable}/HierarchicalExample.tsx +8 -6
  323. package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
  324. package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
  325. package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
  326. package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
  327. package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
  328. package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
  329. package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
  330. package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
  331. package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
  332. package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
  333. package/examples/README.md +81 -33
  334. package/examples/index.ts +14 -12
  335. package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
  336. package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
  337. package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
  338. package/package.json +21 -27
  339. package/src/__tests__/helpers/test-utils.tsx +29 -3
  340. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
  341. package/src/components/Alert/Alert.test.tsx +2 -2
  342. package/src/components/Alert/Alert.tsx +4 -4
  343. package/src/components/Avatar/Avatar.test.tsx +17 -6
  344. package/src/components/Badge/Badge.test.tsx +1 -1
  345. package/src/components/Badge/Badge.tsx +2 -2
  346. package/src/components/Button/Button.test.tsx +2 -2
  347. package/src/components/Button/Button.tsx +11 -7
  348. package/src/components/Calendar/Calendar.test.tsx +41 -8
  349. package/src/components/Calendar/Calendar.tsx +39 -36
  350. package/src/components/Card/Card.tsx +51 -13
  351. package/src/components/Checkbox/Checkbox.test.tsx +36 -12
  352. package/src/components/DataTable/DataTable.test.tsx +1 -1
  353. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
  354. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
  355. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
  356. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
  357. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
  358. package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
  359. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
  360. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
  361. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
  362. package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
  363. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
  364. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
  365. package/src/components/DataTable/components/DataTableBody.tsx +10 -25
  366. package/src/components/DataTable/components/DataTableCore.tsx +1 -1
  367. package/src/components/DataTable/components/FilterRow.tsx +3 -1
  368. package/src/components/DataTable/components/ImportModal.tsx +1 -1
  369. package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
  370. package/src/components/DataTable/core/ColumnFactory.ts +6 -6
  371. package/src/components/DataTable/core/DataTableContext.tsx +14 -10
  372. package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
  373. package/src/components/DataTable/core/PluginRegistry.ts +3 -3
  374. package/src/components/DataTable/core/StateManager.ts +12 -11
  375. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
  376. package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
  377. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
  378. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
  379. package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
  380. package/src/components/DataTable/core/interfaces.ts +17 -17
  381. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
  382. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
  383. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
  384. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
  385. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
  386. package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
  387. package/src/components/DataTable/types.ts +5 -5
  388. package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
  389. package/src/components/DataTable/utils/columnUtils.ts +3 -2
  390. package/src/components/DataTable/utils/debugTools.ts +1 -1
  391. package/src/components/DataTable/utils/exportUtils.ts +6 -6
  392. package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
  393. package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
  394. package/src/components/DataTable/utils/index.ts +0 -1
  395. package/src/components/DataTable/utils/performanceUtils.ts +9 -4
  396. package/src/components/Dialog/Dialog.test.tsx +49 -27
  397. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
  398. package/src/components/EventSelector/EventSelector.test.tsx +60 -12
  399. package/src/components/EventSelector/EventSelector.tsx +38 -15
  400. package/src/components/EventSelector/index.ts +2 -2
  401. package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
  402. package/src/components/FileDisplay/FileDisplay.tsx +1 -0
  403. package/src/components/FileUpload/FileUpload.test.tsx +532 -152
  404. package/src/components/FileUpload/FileUpload.tsx +43 -8
  405. package/src/components/Footer/Footer.test.tsx +19 -14
  406. package/src/components/Form/Form.test.tsx +96 -14
  407. package/src/components/Form/Form.tsx +210 -1
  408. package/src/components/Form/index.ts +3 -7
  409. package/src/components/Header/Header.test.tsx +24 -17
  410. package/src/components/Header/Header.tsx +3 -1
  411. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
  412. package/src/components/Input/Input.test.tsx +61 -36
  413. package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
  414. package/src/components/Label/Label.tsx +2 -3
  415. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
  416. package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
  417. package/src/components/LoginForm/LoginForm.test.tsx +14 -13
  418. package/src/components/LoginForm/LoginForm.tsx +1 -1
  419. package/src/components/LoginForm/index.ts +7 -0
  420. package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
  421. package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
  422. package/src/components/NavigationMenu/index.ts +1 -1
  423. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
  424. package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
  425. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
  426. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
  427. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
  428. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
  429. package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
  430. package/src/components/PaceAppLayout/test-setup.tsx +192 -0
  431. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
  432. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
  433. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
  434. package/src/components/PasswordChange/index.ts +2 -0
  435. package/src/components/Progress/Progress.test.tsx +11 -0
  436. package/src/components/Progress/Progress.tsx +1 -1
  437. package/src/components/Progress/index.ts +10 -0
  438. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
  439. package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
  440. package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
  441. package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
  442. package/src/components/PublicLayout/index.ts +10 -28
  443. package/src/components/Select/Select.test.tsx +7 -7
  444. package/src/components/Select/Select.tsx +277 -11
  445. package/src/components/Select/index.ts +1 -2
  446. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
  447. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
  448. package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
  449. package/src/components/Tabs/Tabs.test.tsx +10 -9
  450. package/src/components/Tabs/Tabs.tsx +61 -33
  451. package/src/components/Textarea/Textarea.test.tsx +31 -18
  452. package/src/components/Toast/Toast.tsx +2 -2
  453. package/src/components/Tooltip/Tooltip.test.tsx +1 -1
  454. package/src/components/UserMenu/UserMenu.test.tsx +7 -6
  455. package/src/components/UserMenu/UserMenu.tsx +2 -2
  456. package/src/components/index.ts +5 -4
  457. package/src/constants/performance.ts +19 -8
  458. package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
  459. package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
  460. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
  461. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
  462. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
  463. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
  464. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
  465. package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
  466. package/src/hooks/index.ts +4 -0
  467. package/src/hooks/public/index.ts +2 -0
  468. package/src/hooks/public/usePublicEvent.ts +4 -6
  469. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  470. package/src/hooks/services/useAuth.ts +2 -4
  471. package/src/hooks/services/useCurrentEvent.ts +1 -1
  472. package/src/hooks/useAppConfig.ts +1 -1
  473. package/src/hooks/useDataTablePerformance.ts +2 -2
  474. package/src/hooks/useEventTheme.ts +1 -1
  475. package/src/hooks/useEvents.ts +51 -10
  476. package/src/hooks/useOrganisationPermissions.test.ts +3 -3
  477. package/src/hooks/useOrganisationPermissions.ts +1 -1
  478. package/src/hooks/useOrganisationSecurity.ts +2 -2
  479. package/src/hooks/usePermissionCache.test.ts +9 -9
  480. package/src/hooks/usePermissionCache.ts +2 -2
  481. package/src/index.ts +19 -12
  482. package/src/providers/OrganisationProvider.tsx +73 -9
  483. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
  484. package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
  485. package/src/providers/__tests__/EventProvider.test.tsx +24 -15
  486. package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
  487. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
  488. package/src/providers/index.ts +0 -3
  489. package/src/providers/services/AuthServiceProvider.tsx +2 -17
  490. package/src/providers/services/EventServiceProvider.tsx +11 -16
  491. package/src/providers/services/InactivityServiceProvider.tsx +9 -12
  492. package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
  493. package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
  494. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
  495. package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
  496. package/src/rbac/adapters.tsx +1 -1
  497. package/src/rbac/api.ts +20 -4
  498. package/src/rbac/audit-enhanced.ts +47 -2
  499. package/src/rbac/audit.ts +47 -2
  500. package/src/rbac/components/NavigationGuard.tsx +1 -1
  501. package/src/rbac/components/NavigationProvider.test.tsx +7 -6
  502. package/src/rbac/components/NavigationProvider.tsx +1 -1
  503. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  504. package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
  505. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  506. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  507. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  508. package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
  509. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  510. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
  511. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
  512. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
  513. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
  514. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
  515. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
  516. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
  517. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
  518. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
  519. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
  520. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
  521. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
  522. package/src/rbac/hooks/index.ts +3 -0
  523. package/src/rbac/hooks/usePermissions.ts +31 -85
  524. package/src/rbac/hooks/useRBAC.test.ts +13 -1
  525. package/src/rbac/hooks/useRBAC.ts +13 -67
  526. package/src/rbac/hooks/useResolvedScope.ts +11 -0
  527. package/src/rbac/hooks/useSecureSupabase.ts +308 -0
  528. package/src/rbac/index.ts +3 -0
  529. package/src/rbac/secureClient.ts +53 -6
  530. package/src/rbac/security.ts +37 -1
  531. package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
  532. package/src/rbac/types.ts +3 -2
  533. package/src/services/AuthService.ts +33 -25
  534. package/src/services/EventService.ts +56 -44
  535. package/src/services/InactivityService.ts +33 -53
  536. package/src/services/OrganisationService.ts +36 -40
  537. package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
  538. package/src/services/__tests__/EventService.test.ts +67 -33
  539. package/src/services/interfaces/IEventService.ts +1 -1
  540. package/src/styles/core.css +2 -2
  541. package/src/styles/index.ts +1 -5
  542. package/src/types/__tests__/guards.test.ts +1 -1
  543. package/src/types/__tests__/type-validation.test.ts +0 -1
  544. package/src/types/auth.ts +42 -2
  545. package/src/types/core.ts +251 -0
  546. package/src/types/database.ts +11 -496
  547. package/src/types/event.ts +102 -0
  548. package/src/types/file-reference.ts +6 -4
  549. package/src/types/guards.ts +2 -1
  550. package/src/types/index.ts +48 -14
  551. package/src/types/lodash.debounce.d.ts +15 -0
  552. package/src/types/organisation.ts +14 -10
  553. package/src/types/supabase.ts +15 -17
  554. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
  555. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
  556. package/src/utils/app/appNameResolver.ts +1 -1
  557. package/src/utils/dynamic/dynamicUtils.ts +3 -2
  558. package/src/utils/file-reference/index.ts +25 -6
  559. package/src/utils/security/secureErrors.ts +1 -1
  560. package/src/utils/validation/index.ts +6 -12
  561. package/src/utils/validation/validationUtils.ts +0 -13
  562. package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
  563. package/dist/auth-DReDSLq9.d.ts +0 -16
  564. package/dist/chunk-3JI76CYK.js +0 -2444
  565. package/dist/chunk-3JI76CYK.js.map +0 -1
  566. package/dist/chunk-56XJ3TU6.js +0 -11
  567. package/dist/chunk-56XJ3TU6.js.map +0 -1
  568. package/dist/chunk-5MT24GKJ.js.map +0 -1
  569. package/dist/chunk-7QCC6MCP.js +0 -288
  570. package/dist/chunk-BESYRHQM.js.map +0 -1
  571. package/dist/chunk-BJPBT3CU.js +0 -21
  572. package/dist/chunk-BJPBT3CU.js.map +0 -1
  573. package/dist/chunk-BVYWGZVV.js.map +0 -1
  574. package/dist/chunk-CX5M4ZAG.js.map +0 -1
  575. package/dist/chunk-D7LCGMVS.js.map +0 -1
  576. package/dist/chunk-EGI6MUL6.js +0 -27
  577. package/dist/chunk-EGI6MUL6.js.map +0 -1
  578. package/dist/chunk-ERISIBYU.js.map +0 -1
  579. package/dist/chunk-HRO5HWN2.js.map +0 -1
  580. package/dist/chunk-HZLDFOE4.js.map +0 -1
  581. package/dist/chunk-JISYG63F.js +0 -70
  582. package/dist/chunk-JISYG63F.js.map +0 -1
  583. package/dist/chunk-LIMSTKYD.js +0 -61
  584. package/dist/chunk-LIMSTKYD.js.map +0 -1
  585. package/dist/chunk-OWAG3GSU.js.map +0 -1
  586. package/dist/chunk-PPMP5J6T.js.map +0 -1
  587. package/dist/chunk-Q5QRDWKI.js.map +0 -1
  588. package/dist/chunk-S5OFRT4M.js.map +0 -1
  589. package/dist/chunk-SBVILCCA.js.map +0 -1
  590. package/dist/chunk-TUMEWN34.js +0 -15
  591. package/dist/chunk-TUMEWN34.js.map +0 -1
  592. package/dist/chunk-XDNLUEXI.js +0 -138
  593. package/dist/chunk-XJ2HZOBU.js.map +0 -1
  594. package/dist/chunk-ZYTYSTO5.js.map +0 -1
  595. package/dist/chunk-ZZ2SS7NI.js +0 -237
  596. package/dist/chunk-ZZ2SS7NI.js.map +0 -1
  597. package/dist/database-C6jy7EOu.d.ts +0 -500
  598. package/dist/organisation-D6qRDtbF.d.ts +0 -93
  599. package/dist/schema-DTDZQe2u.d.ts +0 -28
  600. package/dist/unified-DQ4VcT7H.d.ts +0 -198
  601. package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
  602. package/dist/validation.d.ts +0 -47
  603. package/dist/validation.js +0 -24
  604. package/dist/validation.js.map +0 -1
  605. package/docs/DOCUMENTATION_AUDIT.md +0 -172
  606. package/docs/DOCUMENTATION_STANDARD.md +0 -137
  607. package/docs/api/classes/PublicErrorBoundary.md +0 -132
  608. package/docs/api/interfaces/EventLogoProps.md +0 -152
  609. package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
  610. package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
  611. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
  612. package/docs/architecture/rpc-function-standards.md +0 -1106
  613. package/docs/getting-started/consuming-app-vite-config.md +0 -239
  614. package/docs/implementation-guides/event-theming-summary.md +0 -226
  615. package/docs/implementation-guides/public-pages-advanced.md +0 -1038
  616. package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
  617. package/docs/migration/v0.4.16-css-first-approach.md +0 -312
  618. package/docs/migration/v0.4.17-source-path-fix.md +0 -235
  619. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
  620. package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
  621. package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
  622. package/docs/rbac/README-rbac-rls-integration.md +0 -374
  623. package/docs/styles/usage.md +0 -227
  624. package/docs/testing/visual-testing.md +0 -120
  625. package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
  626. package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
  627. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
  628. package/docs/troubleshooting/database-view-compatibility.md +0 -125
  629. package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
  630. package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
  631. package/examples/RBAC/EventBasedApp.tsx +0 -239
  632. package/examples/RBAC/PermissionExample.tsx +0 -151
  633. package/examples/STRUCTURE.md +0 -125
  634. package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
  635. package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
  636. package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
  637. package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
  638. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
  639. package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
  640. package/examples/components 2/index.ts +0 -11
  641. package/examples/features/index.ts +0 -12
  642. package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
  643. package/examples/features/rbac/index.ts +0 -13
  644. package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
  645. package/examples/public-pages/PublicEventPage.tsx +0 -274
  646. package/examples/public-pages/PublicPageApp.tsx +0 -308
  647. package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
  648. package/examples/public-pages/index.ts +0 -14
  649. package/src/__tests__/TEST_STANDARD.md +0 -1008
  650. package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
  651. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
  652. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
  653. package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
  654. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
  655. package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
  656. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
  657. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
  658. package/src/components/Dialog/README.md +0 -804
  659. package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
  660. package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
  661. package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
  662. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
  663. package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
  664. package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
  665. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
  666. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
  667. package/src/components/Dialog/utils/safeHtml.ts +0 -185
  668. package/src/components/EventSelector/types.ts +0 -79
  669. package/src/components/Form/FormErrorSummary.tsx +0 -113
  670. package/src/components/Form/FormField.tsx +0 -249
  671. package/src/components/Form/FormFieldset.tsx +0 -127
  672. package/src/components/Form/FormLiveRegion.tsx +0 -198
  673. package/src/components/Input/__mocks__/Input.tsx +0 -2
  674. package/src/components/NavigationMenu/types.ts +0 -85
  675. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
  676. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
  677. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  678. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  679. package/src/components/PasswordReset/index.ts +0 -2
  680. package/src/components/ProtectedRoute/README.md +0 -164
  681. package/src/components/PublicLayout/EventLogo.tsx +0 -175
  682. package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
  683. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
  684. package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
  685. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  686. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  687. package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
  688. package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
  689. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
  690. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
  691. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
  692. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
  693. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
  694. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
  695. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
  696. package/src/components/Select/hooks.ts +0 -289
  697. package/src/hooks/useCounter.test.ts +0 -131
  698. package/src/hooks/useDebounce.test.ts +0 -375
  699. package/src/providers/AuthProvider.tsx +0 -15
  700. package/src/providers/EventProvider.tsx +0 -16
  701. package/src/providers/InactivityProvider.tsx +0 -15
  702. package/src/providers/OrganisationProvider.context.test.tsx +0 -169
  703. package/src/providers/UnifiedAuthProvider.tsx +0 -15
  704. package/src/types/theme.ts +0 -6
  705. package/src/types/unified.ts +0 -265
  706. package/src/utils/appConfig.ts +0 -47
  707. package/src/utils/appIdResolver.test.ts +0 -499
  708. package/src/utils/appIdResolver.ts +0 -130
  709. package/src/utils/appNameResolver.simple.test.ts +0 -212
  710. package/src/utils/appNameResolver.test.ts +0 -121
  711. package/src/utils/appNameResolver.ts +0 -191
  712. package/src/utils/audit.ts +0 -127
  713. package/src/utils/auth-utils.ts +0 -96
  714. package/src/utils/bundleAnalysis.ts +0 -129
  715. package/src/utils/debugLogger.ts +0 -67
  716. package/src/utils/deviceFingerprint.ts +0 -215
  717. package/src/utils/dynamicUtils.ts +0 -105
  718. package/src/utils/file-reference.test.ts +0 -788
  719. package/src/utils/file-reference.ts +0 -519
  720. package/src/utils/formatDate.test.ts +0 -237
  721. package/src/utils/formatting.ts +0 -170
  722. package/src/utils/lazyLoad.tsx +0 -44
  723. package/src/utils/logger.ts +0 -179
  724. package/src/utils/organisationContext.test.ts +0 -322
  725. package/src/utils/organisationContext.ts +0 -153
  726. package/src/utils/performanceBenchmark.ts +0 -64
  727. package/src/utils/performanceBudgets.ts +0 -110
  728. package/src/utils/permissionTypes.ts +0 -37
  729. package/src/utils/permissionUtils.test.ts +0 -393
  730. package/src/utils/permissionUtils.ts +0 -34
  731. package/src/utils/sanitization.ts +0 -264
  732. package/src/utils/schemaUtils.ts +0 -37
  733. package/src/utils/secureDataAccess.test.ts +0 -711
  734. package/src/utils/secureDataAccess.ts +0 -377
  735. package/src/utils/secureErrors.ts +0 -79
  736. package/src/utils/security.ts +0 -156
  737. package/src/utils/securityMonitor.ts +0 -45
  738. package/src/utils/sessionTracking.ts +0 -126
  739. package/src/utils/validation.ts +0 -111
  740. package/src/utils/validationUtils.ts +0 -120
  741. package/src/validation/index.ts +0 -12
  742. /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
  743. /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
  744. /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
  745. /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
  746. /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
  747. /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
  748. /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
  749. /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
  750. /package/examples/{RBAC → rbac}/index.ts +0 -0
@@ -1,214 +1,594 @@
1
+ /**
2
+ * @file FileUpload Component Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/FileUpload/__tests__
5
+ *
6
+ * Comprehensive test suite for FileUpload component following testing standards.
7
+ * Tests cover file selection, validation, upload workflows, error handling, and accessibility.
8
+ */
9
+
1
10
  import React from 'react';
2
- import { renderWithProviders, screen, fireEvent, userEvent, act } from '../../__tests__/helpers/test-utils';
11
+ import { renderWithProviders, screen, fireEvent, act, waitFor } from '../../__tests__/helpers/test-utils';
3
12
  import { FileUpload } from './FileUpload';
4
13
  import { createMockSupabaseClient } from '../../__tests__/helpers/test-utils';
5
14
  import { FileCategory } from '../../types/file-reference';
15
+ import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
6
16
 
7
- vi.mock('../../hooks/useFileReference', () => {
8
- return {
9
- useFileReference: () => ({
10
- isLoading: false,
11
- error: null,
12
- uploadFile: vi.fn(async () => ({
13
- file_reference: {
14
- id: 'file-ref-1',
15
- table_name: 'person',
16
- record_id: 'rec-1',
17
- organisation_id: 'org-1',
18
- file_path: 'bucket/path/file.png',
19
- is_public: false,
20
- file_metadata: {
21
- fileName: 'file.png',
22
- fileSize: 1024,
23
- fileType: 'image/png',
24
- category: FileCategory.PROFILE_PHOTOS,
25
- },
26
- },
27
- })),
28
- }),
29
- };
17
+ // Mock dependencies
18
+ import * as useFileReferenceModule from '../../hooks/useFileReference';
19
+ import * as appNameResolver from '../../utils/app/appNameResolver';
20
+ import * as appIdResolver from '../../utils/app/appIdResolver';
21
+
22
+ const mockUseFileReference = vi.fn();
23
+ const mockGetCurrentAppName = vi.fn();
24
+ const mockGetAppId = vi.fn();
25
+
26
+ const createMockUploadResult = () => ({
27
+ file_reference: {
28
+ id: 'file-ref-1',
29
+ table_name: 'person',
30
+ record_id: 'rec-1',
31
+ organisation_id: 'org-1',
32
+ file_path: 'bucket/path/file.png',
33
+ is_public: false,
34
+ file_metadata: {
35
+ fileName: 'file.png',
36
+ fileSize: 1024,
37
+ fileType: 'image/png',
38
+ category: FileCategory.PROFILE_PHOTOS,
39
+ },
40
+ },
41
+ file_url: 'https://example.com/file.png',
42
+ });
43
+
44
+ beforeEach(() => {
45
+ vi.clearAllMocks();
46
+
47
+ mockUseFileReference.mockReturnValue({
48
+ uploadFile: vi.fn(async () => createMockUploadResult()),
49
+ isLoading: false,
50
+ error: null,
51
+ });
52
+
53
+ mockGetCurrentAppName.mockReturnValue('test-app');
54
+ mockGetAppId.mockResolvedValue('test-app-id');
55
+
56
+ vi.spyOn(useFileReferenceModule, 'useFileReference').mockImplementation(mockUseFileReference);
57
+ vi.spyOn(appNameResolver, 'getCurrentAppName').mockImplementation(mockGetCurrentAppName);
58
+ vi.spyOn(appIdResolver, 'getAppId').mockImplementation(mockGetAppId);
59
+ });
60
+
61
+ afterEach(() => {
62
+ vi.restoreAllMocks();
30
63
  });
31
64
 
32
65
  describe('[component] FileUpload', () => {
33
- const supabase = createMockSupabaseClient() as any;
66
+ const supabase = createMockSupabaseClient();
34
67
  const baseProps = {
35
68
  supabase,
36
69
  table_name: 'person',
37
70
  record_id: 'rec-1',
38
71
  organisation_id: 'org-1',
39
- app_id: 'app-123', // pass app_id to avoid async resolution
72
+ app_id: 'app-123',
40
73
  category: FileCategory.PROFILE_PHOTOS,
41
74
  accept: 'image/*',
42
75
  } as const;
43
76
 
44
- it('renders call-to-action text by default', () => {
45
- renderWithProviders(<FileUpload {...baseProps} />);
46
- expect(screen.getByText(/Click to upload/i)).toBeInTheDocument();
47
- expect(screen.getByText(/drag and drop/i)).toBeInTheDocument();
77
+ const createTestFile = (name = 'test.png', type = 'image/png', size = 1024): File => {
78
+ return new File([new Uint8Array(size)], name, { type, size });
79
+ };
80
+
81
+ describe('Rendering', () => {
82
+ it('renders call-to-action text by default', () => {
83
+ renderWithProviders(<FileUpload {...baseProps} />);
84
+ expect(screen.getByText(/Click to upload/i)).toBeInTheDocument();
85
+ expect(screen.getByText(/drag and drop/i)).toBeInTheDocument();
86
+ });
87
+
88
+ it('renders with custom children', () => {
89
+ renderWithProviders(
90
+ <FileUpload {...baseProps}>
91
+ <div>Custom upload area</div>
92
+ </FileUpload>
93
+ );
94
+ expect(screen.getByText('Custom upload area')).toBeInTheDocument();
95
+ expect(screen.queryByText(/Click to upload/i)).not.toBeInTheDocument();
96
+ });
97
+
98
+ it('shows accepted formats when accept prop is provided', () => {
99
+ renderWithProviders(<FileUpload {...baseProps} accept="image/*" />);
100
+ expect(screen.getByText(/Accepted formats: image\/\*/i)).toBeInTheDocument();
101
+ });
102
+
103
+ it('shows max size information when provided', () => {
104
+ renderWithProviders(<FileUpload {...baseProps} maxSize={5 * 1024 * 1024} />);
105
+ expect(screen.getByText(/Max size: 5MB/i)).toBeInTheDocument();
106
+ });
107
+
108
+ it('shows multiple files allowed message when multiple is true', () => {
109
+ renderWithProviders(<FileUpload {...baseProps} multiple />);
110
+ expect(screen.getByText(/Multiple files allowed/i)).toBeInTheDocument();
111
+ });
48
112
  });
49
113
 
50
- it('shows drag state message on dragover and resets on dragleave', async () => {
51
- const user = userEvent.setup();
52
- renderWithProviders(<FileUpload {...baseProps} />);
114
+ describe('Drag and Drop', () => {
115
+ it('shows drag state message on dragover', () => {
116
+ renderWithProviders(<FileUpload {...baseProps} />);
117
+ const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
118
+
119
+ fireEvent.dragOver(dropArea);
120
+ expect(screen.getByText(/Drop files here/i)).toBeInTheDocument();
121
+ });
122
+
123
+ it('resets drag state on dragleave', () => {
124
+ renderWithProviders(<FileUpload {...baseProps} />);
125
+ const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
126
+
127
+ fireEvent.dragOver(dropArea);
128
+ expect(screen.getByText(/Drop files here/i)).toBeInTheDocument();
129
+
130
+ fireEvent.dragLeave(dropArea);
131
+ expect(screen.getByText(/Click to upload/i)).toBeInTheDocument();
132
+ });
53
133
 
54
- const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
134
+ it('handles file drop', async () => {
135
+ const onUploadSuccess = vi.fn();
136
+ renderWithProviders(
137
+ <FileUpload {...baseProps} onUploadSuccess={onUploadSuccess} showProgress />
138
+ );
55
139
 
56
- fireEvent.dragOver(dropArea);
57
- expect(screen.getByText(/Drop files here/i)).toBeInTheDocument();
140
+ const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
141
+ const file = createTestFile('test.png', 'image/png');
58
142
 
59
- fireEvent.dragLeave(dropArea);
60
- expect(screen.getByText(/Click to upload/i)).toBeInTheDocument();
143
+ await act(async () => {
144
+ fireEvent.drop(dropArea, {
145
+ dataTransfer: {
146
+ files: [file],
147
+ },
148
+ });
149
+ });
150
+
151
+ await waitFor(() => {
152
+ expect(onUploadSuccess).toHaveBeenCalled();
153
+ });
154
+ });
155
+
156
+ it('does not handle drop when disabled', () => {
157
+ renderWithProviders(<FileUpload {...baseProps} disabled />);
158
+ const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
159
+
160
+ fireEvent.dragOver(dropArea);
161
+ expect(screen.queryByText(/Drop files here/i)).not.toBeInTheDocument();
162
+ });
61
163
  });
62
164
 
63
- it('handles upload failure and shows error', async () => {
64
- // Override the mocked hook just for this test to simulate a failed upload
65
- const { useFileReference } = await import('../../hooks/useFileReference');
66
- const hookSpy = vi.spyOn({ useFileReference }, 'useFileReference' as any).mockReturnValue({
67
- isLoading: false,
68
- error: null,
69
- uploadFile: vi.fn(async () => undefined),
70
- } as any);
165
+ describe('File Selection', () => {
166
+ it('handles file input change', async () => {
167
+ const onUploadSuccess = vi.fn();
168
+ renderWithProviders(
169
+ <FileUpload {...baseProps} onUploadSuccess={onUploadSuccess} showProgress />
170
+ );
171
+
172
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
173
+ const file = createTestFile('test.png', 'image/png');
174
+
175
+ await act(async () => {
176
+ fireEvent.change(input, { target: { files: [file] } });
177
+ });
71
178
 
72
- const onUploadError = vi.fn();
73
- renderWithProviders(
74
- <FileUpload {...baseProps} onUploadError={onUploadError} showProgress />
75
- );
179
+ await waitFor(() => {
180
+ expect(onUploadSuccess).toHaveBeenCalled();
181
+ });
182
+ });
183
+
184
+ it('handles multiple file selection when multiple is true', async () => {
185
+ const onUploadSuccess = vi.fn();
186
+ renderWithProviders(
187
+ <FileUpload {...baseProps} multiple onUploadSuccess={onUploadSuccess} showProgress />
188
+ );
76
189
 
77
- const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
78
- fireEvent.click(dropArea);
190
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
191
+ const file1 = createTestFile('test1.png', 'image/png');
192
+ const file2 = createTestFile('test2.png', 'image/png');
79
193
 
80
- const input = screen.getByTestId('file-input') as HTMLInputElement;
81
- const file = new File([new Uint8Array([1, 2, 3])], 'avatar.png', { type: 'image/png' });
82
- await act(async () => {
83
- fireEvent.change(input, { target: { files: [file] } });
194
+ await act(async () => {
195
+ fireEvent.change(input, { target: { files: [file1, file2] } });
196
+ });
197
+
198
+ await waitFor(() => {
199
+ expect(onUploadSuccess).toHaveBeenCalledTimes(2);
200
+ });
84
201
  });
85
202
 
86
- // Expect error UI and error callback
87
- await screen.findByText(/Upload failed/i);
88
- expect(onUploadError).toHaveBeenCalled();
203
+ it('triggers file input click when drop area is clicked', () => {
204
+ renderWithProviders(<FileUpload {...baseProps} />);
205
+ const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
206
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
207
+ const clickSpy = vi.spyOn(input, 'click');
89
208
 
90
- hookSpy.mockRestore();
209
+ fireEvent.click(dropArea);
210
+ expect(clickSpy).toHaveBeenCalled();
211
+ });
91
212
  });
92
213
 
93
- it('rejects files that do not match accept filter and calls onUploadError', async () => {
94
- const onUploadError = vi.fn();
95
- renderWithProviders(
96
- <FileUpload {...baseProps} onUploadError={onUploadError} accept={'.pdf'} />
97
- );
214
+ describe('File Validation', () => {
215
+ it('rejects files that do not match accept filter', async () => {
216
+ const onUploadError = vi.fn();
217
+ renderWithProviders(
218
+ <FileUpload {...baseProps} onUploadError={onUploadError} accept=".pdf" />
219
+ );
220
+
221
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
222
+ const badFile = createTestFile('avatar.png', 'image/png');
223
+
224
+ await act(async () => {
225
+ fireEvent.change(input, { target: { files: [badFile] } });
226
+ });
227
+
228
+ expect(onUploadError).toHaveBeenCalledTimes(1);
229
+ expect(onUploadError.mock.calls[0][0]).toMatch(/not an accepted format/i);
230
+ });
231
+
232
+ it('rejects files over max size', async () => {
233
+ const onUploadError = vi.fn();
234
+ renderWithProviders(
235
+ <FileUpload {...baseProps} onUploadError={onUploadError} maxSize={1} />
236
+ );
237
+
238
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
239
+ const bigFile = createTestFile('big.bin', 'application/octet-stream', 5 * 1024);
98
240
 
99
- const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
100
- const input = screen.getByTestId('file-input') as HTMLInputElement;
101
- const badFile = new File([new Uint8Array([1, 2, 3])], 'avatar.png', { type: 'image/png' });
241
+ await act(async () => {
242
+ fireEvent.change(input, { target: { files: [bigFile] } });
243
+ });
102
244
 
103
- await act(async () => {
104
- fireEvent.change(input, { target: { files: [badFile] } });
245
+ expect(onUploadError).toHaveBeenCalledTimes(1);
246
+ expect(onUploadError.mock.calls[0][0]).toMatch(/exceeds maximum size/i);
105
247
  });
106
248
 
107
- expect(onUploadError).toHaveBeenCalledTimes(1);
108
- expect(onUploadError.mock.calls[0][0]).toMatch(/not an accepted format/i);
249
+ it('accepts files matching MIME type wildcard', async () => {
250
+ const onUploadSuccess = vi.fn();
251
+ renderWithProviders(
252
+ <FileUpload {...baseProps} accept="image/*" onUploadSuccess={onUploadSuccess} showProgress />
253
+ );
254
+
255
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
256
+ const file = createTestFile('test.jpg', 'image/jpeg');
257
+
258
+ await act(async () => {
259
+ fireEvent.change(input, { target: { files: [file] } });
260
+ });
261
+
262
+ await waitFor(() => {
263
+ expect(onUploadSuccess).toHaveBeenCalled();
264
+ });
265
+ });
266
+
267
+ it('accepts files matching exact MIME type', async () => {
268
+ const onUploadSuccess = vi.fn();
269
+ renderWithProviders(
270
+ <FileUpload {...baseProps} accept="image/png" onUploadSuccess={onUploadSuccess} showProgress />
271
+ );
272
+
273
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
274
+ const file = createTestFile('test.png', 'image/png');
275
+
276
+ await act(async () => {
277
+ fireEvent.change(input, { target: { files: [file] } });
278
+ });
279
+
280
+ await waitFor(() => {
281
+ expect(onUploadSuccess).toHaveBeenCalled();
282
+ });
283
+ });
109
284
  });
110
285
 
111
- it('rejects files over max size and shows error', async () => {
112
- const onUploadError = vi.fn();
113
- renderWithProviders(
114
- <FileUpload {...baseProps} onUploadError={onUploadError} maxSize={1} />
115
- );
286
+ describe('Upload Workflow', () => {
287
+ it('handles successful upload', async () => {
288
+ const onUploadSuccess = vi.fn();
289
+ const onProgress = vi.fn();
290
+ renderWithProviders(
291
+ <FileUpload
292
+ {...baseProps}
293
+ onUploadSuccess={onUploadSuccess}
294
+ onProgress={onProgress}
295
+ showProgress
296
+ />
297
+ );
298
+
299
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
300
+ const file = createTestFile('test.png', 'image/png');
301
+
302
+ await act(async () => {
303
+ fireEvent.change(input, { target: { files: [file] } });
304
+ });
305
+
306
+ await waitFor(() => {
307
+ expect(onUploadSuccess).toHaveBeenCalled();
308
+ expect(onProgress).toHaveBeenCalled();
309
+ });
310
+ });
311
+
312
+ it('handles upload failure', async () => {
313
+ mockUseFileReference.mockReturnValue({
314
+ uploadFile: vi.fn(async () => null),
315
+ isLoading: false,
316
+ error: null,
317
+ });
116
318
 
117
- const dropArea = screen.getByText(/Click to upload/i).closest('div') as HTMLElement;
118
- const input = screen.getByTestId('file-input') as HTMLInputElement;
119
- const big = new File([new Uint8Array(5)], 'big.bin', { type: 'application/octet-stream' });
319
+ const onUploadError = vi.fn();
320
+ renderWithProviders(
321
+ <FileUpload {...baseProps} onUploadError={onUploadError} showProgress />
322
+ );
323
+
324
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
325
+ const file = createTestFile('test.png', 'image/png');
326
+
327
+ await act(async () => {
328
+ fireEvent.change(input, { target: { files: [file] } });
329
+ });
330
+
331
+ await waitFor(() => {
332
+ expect(onUploadError).toHaveBeenCalled();
333
+ });
334
+ });
120
335
 
121
- await act(async () => {
122
- fireEvent.change(input, { target: { files: [big] } });
336
+ it('handles upload error exception', async () => {
337
+ mockUseFileReference.mockReturnValue({
338
+ uploadFile: vi.fn(async () => {
339
+ throw new Error('Network error');
340
+ }),
341
+ isLoading: false,
342
+ error: null,
343
+ });
344
+
345
+ const onUploadError = vi.fn();
346
+ renderWithProviders(
347
+ <FileUpload {...baseProps} onUploadError={onUploadError} showProgress />
348
+ );
349
+
350
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
351
+ const file = createTestFile('test.png', 'image/png');
352
+
353
+ await act(async () => {
354
+ fireEvent.change(input, { target: { files: [file] } });
355
+ });
356
+
357
+ await waitFor(() => {
358
+ expect(onUploadError).toHaveBeenCalledWith('Network error', file);
359
+ });
123
360
  });
124
361
 
125
- expect(onUploadError).toHaveBeenCalledTimes(1);
126
- expect(onUploadError.mock.calls[0][0]).toMatch(/exceeds maximum size/i);
362
+ it('shows progress when showProgress is true', async () => {
363
+ const onUploadSuccess = vi.fn();
364
+ renderWithProviders(
365
+ <FileUpload {...baseProps} onUploadSuccess={onUploadSuccess} showProgress />
366
+ );
367
+
368
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
369
+ const file = createTestFile('test.png', 'image/png', 10240);
370
+
371
+ await act(async () => {
372
+ fireEvent.change(input, { target: { files: [file] } });
373
+ });
374
+
375
+ await waitFor(() => {
376
+ expect(screen.getByText('test.png')).toBeInTheDocument();
377
+ });
378
+ });
379
+
380
+ it('shows file icon when preview is not available', async () => {
381
+ const onUploadSuccess = vi.fn();
382
+ renderWithProviders(
383
+ <FileUpload
384
+ {...baseProps}
385
+ accept="application/pdf,image/*"
386
+ onUploadSuccess={onUploadSuccess}
387
+ showProgress
388
+ showPreview={false}
389
+ />
390
+ );
391
+
392
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
393
+ const file = createTestFile('test.pdf', 'application/pdf', 1024);
394
+
395
+ await act(async () => {
396
+ fireEvent.change(input, { target: { files: [file] } });
397
+ });
398
+
399
+ await waitFor(() => {
400
+ expect(screen.getByText('test.pdf')).toBeInTheDocument();
401
+ // File icon should be shown (emoji or icon)
402
+ const fileIcon = document.querySelector('.w-12.h-12');
403
+ expect(fileIcon).toBeInTheDocument();
404
+ });
405
+ });
406
+
407
+ it('shows loading spinner when showProgress is false', async () => {
408
+ // Mock a slow upload to ensure spinner appears
409
+ let resolveUpload: (value: ReturnType<typeof createMockUploadResult>) => void;
410
+ const slowUploadPromise = new Promise<ReturnType<typeof createMockUploadResult>>((resolve) => {
411
+ resolveUpload = resolve;
412
+ });
413
+
414
+ mockUseFileReference.mockReturnValue({
415
+ uploadFile: vi.fn(() => slowUploadPromise),
416
+ isLoading: false,
417
+ error: null,
418
+ });
419
+
420
+ renderWithProviders(<FileUpload {...baseProps} showProgress={false} />);
421
+
422
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
423
+ const file = createTestFile('test.png', 'image/png');
424
+
425
+ await act(async () => {
426
+ fireEvent.change(input, { target: { files: [file] } });
427
+ });
428
+
429
+ // Wait for spinner to appear
430
+ await waitFor(() => {
431
+ const spinnerContainer = screen.getByRole('status', { name: 'Uploading file' });
432
+ const spinner = spinnerContainer.querySelector('.animate-spin');
433
+ expect(spinner).toBeInTheDocument();
434
+ });
435
+
436
+ // Resolve upload to clean up
437
+ resolveUpload!(createMockUploadResult());
438
+ });
127
439
  });
128
440
 
129
- it('shows app ID resolution error when app_id is not provided and cannot be resolved', async () => {
130
- // Force resolver failure for this test
131
- mockGetCurrentAppName.mockReturnValueOnce(undefined as any);
132
- mockGetAppId.mockResolvedValueOnce(null as any);
441
+ describe('App ID Resolution', () => {
442
+ it('uses provided app_id directly', () => {
443
+ renderWithProviders(<FileUpload {...baseProps} app_id="provided-app-id" />);
444
+ expect(screen.queryByText(/Resolving app configuration/i)).not.toBeInTheDocument();
445
+ });
446
+
447
+ it('resolves app_id from app name when not provided', async () => {
448
+ renderWithProviders(
449
+ <FileUpload
450
+ {...baseProps}
451
+ app_id={undefined as unknown as string}
452
+ />
453
+ );
454
+
455
+ await waitFor(() => {
456
+ expect(mockGetCurrentAppName).toHaveBeenCalled();
457
+ expect(mockGetAppId).toHaveBeenCalled();
458
+ });
459
+ });
460
+
461
+ it('shows error when app_id cannot be resolved', async () => {
462
+ mockGetCurrentAppName.mockReturnValueOnce(undefined);
463
+ mockGetAppId.mockResolvedValueOnce(null);
133
464
 
134
- const { rerender } = renderWithProviders(
135
- <FileUpload
136
- {...baseProps}
137
- // force resolution path
138
- app_id={undefined as unknown as string}
139
- />
140
- );
465
+ renderWithProviders(
466
+ <FileUpload
467
+ {...baseProps}
468
+ app_id={undefined as unknown as string}
469
+ />
470
+ );
141
471
 
142
- // Error should appear when app id cannot be resolved
143
- await screen.findByText(/App ID is required/i);
472
+ await waitFor(() => {
473
+ expect(screen.getByText(/App ID is required/i)).toBeInTheDocument();
474
+ });
475
+ });
476
+
477
+ it('shows error when app name is not set', async () => {
478
+ mockGetCurrentAppName.mockReturnValueOnce(undefined);
479
+ mockGetAppId.mockResolvedValueOnce(null);
144
480
 
145
- // cleanup mock side-effects and re-render with explicit app_id to avoid impact on other tests
146
- rerender(<FileUpload {...baseProps} />);
481
+ renderWithProviders(
482
+ <FileUpload
483
+ {...baseProps}
484
+ app_id={undefined as unknown as string}
485
+ />
486
+ );
487
+
488
+ await waitFor(() => {
489
+ expect(screen.getByText(/App ID is required/i)).toBeInTheDocument();
490
+ });
491
+ });
147
492
  });
148
- });
149
493
 
150
- /**
151
- * @file FileUpload Component Tests (moved into component directory)
152
- */
494
+ describe('Keyboard Navigation', () => {
495
+ it('triggers file input click on Enter key', () => {
496
+ renderWithProviders(<FileUpload {...baseProps} />);
497
+ const dropArea = screen.getByRole('button', { name: 'File upload area' });
498
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
499
+ const clickSpy = vi.spyOn(input, 'click');
153
500
 
154
- import React from 'react';
155
- import { screen, waitFor, fireEvent } from '@testing-library/react';
156
- import userEvent from '@testing-library/user-event';
157
- import { vi } from 'vitest';
158
- import { FileUpload } from './index';
159
- import { FileCategory } from '../../types/file-reference';
160
- import { renderWithProviders, createMockSupabaseClient } from '../../__tests__/helpers/test-utils';
501
+ fireEvent.keyDown(dropArea, { key: 'Enter' });
502
+ expect(clickSpy).toHaveBeenCalled();
503
+ });
161
504
 
162
- // Mock dependencies
163
- import * as useFileReferenceModule from '../../hooks/useFileReference';
164
- import * as appNameResolver from '../../utils/app/appNameResolver';
165
- import * as appIdResolver from '../../utils/app/appIdResolver';
505
+ it('triggers file input click on Space key', () => {
506
+ renderWithProviders(<FileUpload {...baseProps} />);
507
+ const dropArea = screen.getByRole('button', { name: 'File upload area' });
508
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
509
+ const clickSpy = vi.spyOn(input, 'click');
166
510
 
167
- const mockUseFileReference = vi.fn();
168
- const mockGetCurrentAppName = vi.fn();
169
- const mockGetAppId = vi.fn();
511
+ fireEvent.keyDown(dropArea, { key: ' ' });
512
+ expect(clickSpy).toHaveBeenCalled();
513
+ });
170
514
 
171
- beforeEach(() => {
172
- vi.clearAllMocks();
515
+ it('does not trigger click when disabled', () => {
516
+ renderWithProviders(<FileUpload {...baseProps} disabled />);
517
+ const dropArea = screen.getByRole('button', { name: 'File upload area' });
518
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
519
+ const clickSpy = vi.spyOn(input, 'click');
173
520
 
174
- mockUseFileReference.mockReturnValue({
175
- uploadFile: vi.fn(),
176
- isLoading: false,
177
- error: null
521
+ fireEvent.keyDown(dropArea, { key: 'Enter' });
522
+ expect(clickSpy).not.toHaveBeenCalled();
523
+ });
178
524
  });
179
525
 
180
- mockGetCurrentAppName.mockReturnValue('test-app');
181
- mockGetAppId.mockResolvedValue('test-app-id');
526
+ describe('Disabled State', () => {
527
+ it('disables file input when disabled prop is true', () => {
528
+ renderWithProviders(<FileUpload {...baseProps} disabled />);
529
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
530
+ expect(input.disabled).toBe(true);
531
+ });
182
532
 
183
- vi.spyOn(useFileReferenceModule, 'useFileReference').mockImplementation(mockUseFileReference as any);
184
- vi.spyOn(appNameResolver, 'getCurrentAppName').mockImplementation(mockGetCurrentAppName as any);
185
- vi.spyOn(appIdResolver, 'getAppId').mockImplementation(mockGetAppId as any);
186
- });
533
+ it('disables interaction when uploading', async () => {
534
+ // Mock a slow upload to ensure disabled state is visible
535
+ let resolveUpload: (value: ReturnType<typeof createMockUploadResult>) => void;
536
+ const slowUploadPromise = new Promise<ReturnType<typeof createMockUploadResult>>((resolve) => {
537
+ resolveUpload = resolve;
538
+ });
539
+
540
+ mockUseFileReference.mockReturnValue({
541
+ uploadFile: vi.fn(() => slowUploadPromise),
542
+ isLoading: false,
543
+ error: null,
544
+ });
545
+
546
+ renderWithProviders(<FileUpload {...baseProps} showProgress />);
547
+ const input = screen.getByTestId('file-input') as HTMLInputElement;
548
+ const file = createTestFile('test.png', 'image/png');
549
+
550
+ await act(async () => {
551
+ fireEvent.change(input, { target: { files: [file] } });
552
+ });
553
+
554
+ // Check that input is disabled during upload
555
+ await waitFor(() => {
556
+ const updatedInput = screen.getByTestId('file-input') as HTMLInputElement;
557
+ expect(updatedInput.disabled).toBe(true);
558
+ });
559
+
560
+ // Resolve upload to clean up
561
+ resolveUpload!(createMockUploadResult());
562
+ });
563
+ });
187
564
 
188
- afterEach(() => {
189
- vi.restoreAllMocks();
190
- });
565
+ describe('Error Display', () => {
566
+ it('displays hook error when present', () => {
567
+ mockUseFileReference.mockReturnValue({
568
+ uploadFile: vi.fn(),
569
+ isLoading: false,
570
+ error: 'Hook error message',
571
+ });
572
+
573
+ renderWithProviders(<FileUpload {...baseProps} />);
574
+ expect(screen.getByText('Hook error message')).toBeInTheDocument();
575
+ });
576
+
577
+ it('displays app ID resolution error', async () => {
578
+ mockGetCurrentAppName.mockReturnValueOnce(undefined);
579
+ mockGetAppId.mockResolvedValueOnce(null);
191
580
 
192
- const defaultProps = {
193
- supabase: createMockSupabaseClient(),
194
- table_name: 'test_table',
195
- record_id: 'test-record-123',
196
- organisation_id: 'test-org-123',
197
- category: FileCategory.GENERAL_DOCUMENTS
198
- };
199
-
200
- const createTestFile = (name = 'test.pdf', type = 'application/pdf', size = 1024) => {
201
- return new File(['test content'], name, { type, size });
202
- };
203
-
204
- // Reuse the original test suite by importing the same test logic here would be ideal,
205
- // but for brevity we rely on the existing tests that were already validated at the previous path.
206
- // This file exists to ensure path relocation works; full assertions remain identical to original.
207
-
208
- describe('FileUpload Component (relocated)', () => {
209
- it('renders with default props', () => {
210
- renderWithProviders(<FileUpload {...defaultProps} app_id="test-app-id" />);
211
- expect(screen.getByText((txt) => txt.includes('Click to upload'))).toBeInTheDocument();
581
+ renderWithProviders(
582
+ <FileUpload
583
+ {...baseProps}
584
+ app_id={undefined as unknown as string}
585
+ />
586
+ );
587
+
588
+ await waitFor(() => {
589
+ expect(screen.getByText(/App ID is required/i)).toBeInTheDocument();
590
+ });
591
+ });
212
592
  });
213
593
  });
214
594