@jmruthers/pace-core 0.5.181 → 0.5.183

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 (756) 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/usePublicEventLogo.test.ts +147 -0
  470. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  471. package/src/hooks/services/useAuth.ts +2 -4
  472. package/src/hooks/services/useCurrentEvent.ts +1 -1
  473. package/src/hooks/useAppConfig.ts +1 -1
  474. package/src/hooks/useDataTablePerformance.ts +2 -2
  475. package/src/hooks/useEventTheme.ts +1 -1
  476. package/src/hooks/useEvents.ts +51 -10
  477. package/src/hooks/useOrganisationPermissions.test.ts +3 -3
  478. package/src/hooks/useOrganisationPermissions.ts +1 -1
  479. package/src/hooks/useOrganisationSecurity.ts +2 -2
  480. package/src/hooks/usePermissionCache.test.ts +9 -9
  481. package/src/hooks/usePermissionCache.ts +2 -2
  482. package/src/index.ts +19 -12
  483. package/src/providers/OrganisationProvider.tsx +73 -9
  484. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
  485. package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
  486. package/src/providers/__tests__/EventProvider.test.tsx +24 -15
  487. package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
  488. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
  489. package/src/providers/index.ts +0 -3
  490. package/src/providers/services/AuthServiceProvider.tsx +2 -17
  491. package/src/providers/services/EventServiceProvider.tsx +11 -16
  492. package/src/providers/services/InactivityServiceProvider.tsx +9 -12
  493. package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
  494. package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
  495. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
  496. package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
  497. package/src/rbac/adapters.tsx +1 -1
  498. package/src/rbac/api.ts +20 -4
  499. package/src/rbac/audit-enhanced.ts +47 -2
  500. package/src/rbac/audit.ts +47 -2
  501. package/src/rbac/components/NavigationGuard.tsx +1 -1
  502. package/src/rbac/components/NavigationProvider.test.tsx +7 -6
  503. package/src/rbac/components/NavigationProvider.tsx +1 -1
  504. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  505. package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
  506. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  507. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  508. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  509. package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
  510. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  511. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
  512. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
  513. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
  514. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
  515. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
  516. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
  517. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
  518. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
  519. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
  520. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
  521. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
  522. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
  523. package/src/rbac/hooks/index.ts +3 -0
  524. package/src/rbac/hooks/usePermissions.ts +31 -85
  525. package/src/rbac/hooks/useRBAC.test.ts +13 -1
  526. package/src/rbac/hooks/useRBAC.ts +13 -67
  527. package/src/rbac/hooks/useResolvedScope.ts +11 -0
  528. package/src/rbac/hooks/useSecureSupabase.ts +308 -0
  529. package/src/rbac/index.ts +3 -0
  530. package/src/rbac/secureClient.ts +53 -6
  531. package/src/rbac/security.ts +37 -1
  532. package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
  533. package/src/rbac/types.ts +3 -2
  534. package/src/services/AuthService.ts +33 -25
  535. package/src/services/EventService.ts +56 -44
  536. package/src/services/InactivityService.ts +33 -53
  537. package/src/services/OrganisationService.ts +36 -40
  538. package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
  539. package/src/services/__tests__/EventService.test.ts +67 -33
  540. package/src/services/interfaces/IEventService.ts +1 -1
  541. package/src/styles/core.css +2 -2
  542. package/src/styles/index.test.ts +21 -0
  543. package/src/styles/index.ts +1 -5
  544. package/src/types/__tests__/guards.test.ts +1 -1
  545. package/src/types/__tests__/organisation.roles.test.ts +55 -0
  546. package/src/types/__tests__/type-validation.test.ts +0 -1
  547. package/src/types/auth.ts +42 -2
  548. package/src/types/core.ts +251 -0
  549. package/src/types/database.ts +11 -496
  550. package/src/types/event.ts +102 -0
  551. package/src/types/file-reference.ts +6 -4
  552. package/src/types/guards.ts +2 -1
  553. package/src/types/index.ts +48 -14
  554. package/src/types/lodash.debounce.d.ts +15 -0
  555. package/src/types/organisation.ts +14 -10
  556. package/src/types/supabase.ts +15 -17
  557. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
  558. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
  559. package/src/utils/app/appNameResolver.ts +1 -1
  560. package/src/utils/audit/audit.test.ts +65 -0
  561. package/src/utils/device/deviceFingerprint.test.ts +171 -0
  562. package/src/utils/dynamic/dynamicUtils.ts +3 -2
  563. package/src/utils/file-reference/index.ts +25 -6
  564. package/src/utils/security/secureErrors.ts +1 -1
  565. package/src/utils/validation/__tests__/validationUtils.test.ts +72 -0
  566. package/src/utils/validation/index.ts +6 -12
  567. package/src/utils/validation/validationUtils.ts +0 -13
  568. package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
  569. package/dist/auth-DReDSLq9.d.ts +0 -16
  570. package/dist/chunk-3JI76CYK.js +0 -2444
  571. package/dist/chunk-3JI76CYK.js.map +0 -1
  572. package/dist/chunk-56XJ3TU6.js +0 -11
  573. package/dist/chunk-56XJ3TU6.js.map +0 -1
  574. package/dist/chunk-5MT24GKJ.js.map +0 -1
  575. package/dist/chunk-7QCC6MCP.js +0 -288
  576. package/dist/chunk-BESYRHQM.js.map +0 -1
  577. package/dist/chunk-BJPBT3CU.js +0 -21
  578. package/dist/chunk-BJPBT3CU.js.map +0 -1
  579. package/dist/chunk-BVYWGZVV.js.map +0 -1
  580. package/dist/chunk-CX5M4ZAG.js.map +0 -1
  581. package/dist/chunk-D7LCGMVS.js.map +0 -1
  582. package/dist/chunk-EGI6MUL6.js +0 -27
  583. package/dist/chunk-EGI6MUL6.js.map +0 -1
  584. package/dist/chunk-ERISIBYU.js.map +0 -1
  585. package/dist/chunk-HRO5HWN2.js.map +0 -1
  586. package/dist/chunk-HZLDFOE4.js.map +0 -1
  587. package/dist/chunk-JISYG63F.js +0 -70
  588. package/dist/chunk-JISYG63F.js.map +0 -1
  589. package/dist/chunk-LIMSTKYD.js +0 -61
  590. package/dist/chunk-LIMSTKYD.js.map +0 -1
  591. package/dist/chunk-OWAG3GSU.js.map +0 -1
  592. package/dist/chunk-PPMP5J6T.js.map +0 -1
  593. package/dist/chunk-Q5QRDWKI.js.map +0 -1
  594. package/dist/chunk-S5OFRT4M.js.map +0 -1
  595. package/dist/chunk-SBVILCCA.js.map +0 -1
  596. package/dist/chunk-TUMEWN34.js +0 -15
  597. package/dist/chunk-TUMEWN34.js.map +0 -1
  598. package/dist/chunk-XDNLUEXI.js +0 -138
  599. package/dist/chunk-XJ2HZOBU.js.map +0 -1
  600. package/dist/chunk-ZYTYSTO5.js.map +0 -1
  601. package/dist/chunk-ZZ2SS7NI.js +0 -237
  602. package/dist/chunk-ZZ2SS7NI.js.map +0 -1
  603. package/dist/database-C6jy7EOu.d.ts +0 -500
  604. package/dist/organisation-D6qRDtbF.d.ts +0 -93
  605. package/dist/schema-DTDZQe2u.d.ts +0 -28
  606. package/dist/unified-DQ4VcT7H.d.ts +0 -198
  607. package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
  608. package/dist/validation.d.ts +0 -47
  609. package/dist/validation.js +0 -24
  610. package/dist/validation.js.map +0 -1
  611. package/docs/DOCUMENTATION_AUDIT.md +0 -172
  612. package/docs/DOCUMENTATION_STANDARD.md +0 -137
  613. package/docs/api/classes/PublicErrorBoundary.md +0 -132
  614. package/docs/api/interfaces/EventLogoProps.md +0 -152
  615. package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
  616. package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
  617. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
  618. package/docs/architecture/rpc-function-standards.md +0 -1106
  619. package/docs/getting-started/consuming-app-vite-config.md +0 -239
  620. package/docs/implementation-guides/event-theming-summary.md +0 -226
  621. package/docs/implementation-guides/public-pages-advanced.md +0 -1038
  622. package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
  623. package/docs/migration/v0.4.16-css-first-approach.md +0 -312
  624. package/docs/migration/v0.4.17-source-path-fix.md +0 -235
  625. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
  626. package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
  627. package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
  628. package/docs/rbac/README-rbac-rls-integration.md +0 -374
  629. package/docs/styles/usage.md +0 -227
  630. package/docs/testing/visual-testing.md +0 -120
  631. package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
  632. package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
  633. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
  634. package/docs/troubleshooting/database-view-compatibility.md +0 -125
  635. package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
  636. package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
  637. package/examples/RBAC/EventBasedApp.tsx +0 -239
  638. package/examples/RBAC/PermissionExample.tsx +0 -151
  639. package/examples/STRUCTURE.md +0 -125
  640. package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
  641. package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
  642. package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
  643. package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
  644. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
  645. package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
  646. package/examples/components 2/index.ts +0 -11
  647. package/examples/features/index.ts +0 -12
  648. package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
  649. package/examples/features/rbac/index.ts +0 -13
  650. package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
  651. package/examples/public-pages/PublicEventPage.tsx +0 -274
  652. package/examples/public-pages/PublicPageApp.tsx +0 -308
  653. package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
  654. package/examples/public-pages/index.ts +0 -14
  655. package/src/__tests__/TEST_STANDARD.md +0 -1008
  656. package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
  657. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
  658. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
  659. package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
  660. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
  661. package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
  662. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
  663. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
  664. package/src/components/Dialog/README.md +0 -804
  665. package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
  666. package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
  667. package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
  668. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
  669. package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
  670. package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
  671. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
  672. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
  673. package/src/components/Dialog/utils/safeHtml.ts +0 -185
  674. package/src/components/EventSelector/types.ts +0 -79
  675. package/src/components/Form/FormErrorSummary.tsx +0 -113
  676. package/src/components/Form/FormField.tsx +0 -249
  677. package/src/components/Form/FormFieldset.tsx +0 -127
  678. package/src/components/Form/FormLiveRegion.tsx +0 -198
  679. package/src/components/Input/__mocks__/Input.tsx +0 -2
  680. package/src/components/NavigationMenu/types.ts +0 -85
  681. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
  682. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
  683. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  684. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  685. package/src/components/PasswordReset/index.ts +0 -2
  686. package/src/components/ProtectedRoute/README.md +0 -164
  687. package/src/components/PublicLayout/EventLogo.tsx +0 -175
  688. package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
  689. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
  690. package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
  691. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  692. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  693. package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
  694. package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
  695. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
  696. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
  697. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
  698. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
  699. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
  700. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
  701. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
  702. package/src/components/Select/hooks.ts +0 -289
  703. package/src/hooks/useCounter.test.ts +0 -131
  704. package/src/hooks/useDebounce.test.ts +0 -375
  705. package/src/providers/AuthProvider.tsx +0 -15
  706. package/src/providers/EventProvider.tsx +0 -16
  707. package/src/providers/InactivityProvider.tsx +0 -15
  708. package/src/providers/OrganisationProvider.context.test.tsx +0 -169
  709. package/src/providers/UnifiedAuthProvider.tsx +0 -15
  710. package/src/types/theme.ts +0 -6
  711. package/src/types/unified.ts +0 -265
  712. package/src/utils/appConfig.ts +0 -47
  713. package/src/utils/appIdResolver.test.ts +0 -499
  714. package/src/utils/appIdResolver.ts +0 -130
  715. package/src/utils/appNameResolver.simple.test.ts +0 -212
  716. package/src/utils/appNameResolver.test.ts +0 -121
  717. package/src/utils/appNameResolver.ts +0 -191
  718. package/src/utils/audit.ts +0 -127
  719. package/src/utils/auth-utils.ts +0 -96
  720. package/src/utils/bundleAnalysis.ts +0 -129
  721. package/src/utils/debugLogger.ts +0 -67
  722. package/src/utils/deviceFingerprint.ts +0 -215
  723. package/src/utils/dynamicUtils.ts +0 -105
  724. package/src/utils/file-reference.test.ts +0 -788
  725. package/src/utils/file-reference.ts +0 -519
  726. package/src/utils/formatDate.test.ts +0 -237
  727. package/src/utils/formatting.ts +0 -170
  728. package/src/utils/lazyLoad.tsx +0 -44
  729. package/src/utils/logger.ts +0 -179
  730. package/src/utils/organisationContext.test.ts +0 -322
  731. package/src/utils/organisationContext.ts +0 -153
  732. package/src/utils/performanceBenchmark.ts +0 -64
  733. package/src/utils/performanceBudgets.ts +0 -110
  734. package/src/utils/permissionTypes.ts +0 -37
  735. package/src/utils/permissionUtils.test.ts +0 -393
  736. package/src/utils/permissionUtils.ts +0 -34
  737. package/src/utils/sanitization.ts +0 -264
  738. package/src/utils/schemaUtils.ts +0 -37
  739. package/src/utils/secureDataAccess.test.ts +0 -711
  740. package/src/utils/secureDataAccess.ts +0 -377
  741. package/src/utils/secureErrors.ts +0 -79
  742. package/src/utils/security.ts +0 -156
  743. package/src/utils/securityMonitor.ts +0 -45
  744. package/src/utils/sessionTracking.ts +0 -126
  745. package/src/utils/validation.ts +0 -111
  746. package/src/utils/validationUtils.ts +0 -120
  747. package/src/validation/index.ts +0 -12
  748. /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
  749. /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
  750. /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
  751. /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
  752. /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
  753. /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
  754. /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
  755. /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
  756. /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