@jmruthers/pace-core 0.5.76 → 0.5.78

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 (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -13,7 +13,12 @@
13
13
  * - Data sanitization
14
14
  * - Custom filename support
15
15
  * - Browser download handling
16
- *
16
+ */
17
+
18
+ import { createLogger } from '../../../utils/logger';
19
+ import type { DataRecord } from '../types';
20
+
21
+ /**
17
22
  * @example
18
23
  * ```tsx
19
24
  * // Basic export
@@ -37,6 +42,73 @@
37
42
  * ```
38
43
  */
39
44
 
45
+ /**
46
+ * Column definition for export
47
+ */
48
+ export interface ExportColumn {
49
+ header?: string;
50
+ id?: string;
51
+ accessorKey?: string;
52
+ }
53
+
54
+ /**
55
+ * Escapes a value for CSV format according to RFC 4180
56
+ * - Encloses in quotes if value contains comma, newline, or quote
57
+ * - Escapes existing quotes by doubling them
58
+ * - Prevents CSV injection by sanitizing dangerous characters
59
+ */
60
+ function escapeCSVValue(value: unknown, sanitizeForSecurity: boolean = true): string {
61
+ if (value === null || value === undefined) {
62
+ return sanitizeForSecurity ? '""' : '';
63
+ }
64
+
65
+ let stringValue = String(value);
66
+
67
+ if (sanitizeForSecurity) {
68
+ // Sanitize to prevent CSV injection
69
+ // Check for dangerous patterns that could be interpreted as formulas
70
+ // If starts with =, +, -, @, or \t, it could be a formula
71
+ if (/^[=+\-@]/.test(stringValue) || stringValue.startsWith('\t')) {
72
+ // Prefix with single quote to prevent formula interpretation in Excel
73
+ stringValue = "'" + stringValue;
74
+ }
75
+
76
+ // Remove control characters except newline (which is handled below)
77
+ stringValue = stringValue.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F]/g, '');
78
+
79
+ // Always quote values for consistency and safety
80
+ const escaped = stringValue.replace(/"/g, '""');
81
+ return `"${escaped}"`;
82
+ } else {
83
+ // Minimal escaping - only escape quotes in quoted strings
84
+ const escaped = stringValue.replace(/"/g, '""');
85
+ return `"${escaped}"`;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Formats a value according to locale preferences
91
+ */
92
+ function formatLocaleValue(value: unknown, locale?: string): string {
93
+ if (value === null || value === undefined) {
94
+ return '';
95
+ }
96
+
97
+ if (typeof value === 'number') {
98
+ return new Intl.NumberFormat(locale).format(value);
99
+ }
100
+
101
+ if (value instanceof Date) {
102
+ return new Intl.DateTimeFormat(locale).format(value);
103
+ }
104
+
105
+ if (typeof value === 'boolean') {
106
+ return ''; // Don't format booleans in formatLocaleValue, let them pass through as-is
107
+ }
108
+
109
+ return String(value);
110
+ }
111
+
40
112
  /**
41
113
  * Generates CSV content from data without triggering download
42
114
  *
@@ -45,26 +117,42 @@
45
117
  * @param options - Export options
46
118
  * @returns CSV content as string
47
119
  */
48
- export function generateCSVContent<TData>(
120
+ export function generateCSVContent<TData extends DataRecord>(
49
121
  data: TData[],
50
- columns: any[],
51
- options: { includeHeaders?: boolean } = {}
122
+ columns: ExportColumn[],
123
+ options: {
124
+ includeHeaders?: boolean;
125
+ locale?: string;
126
+ sanitizeForSecurity?: boolean; // Default: true
127
+ } = {}
52
128
  ): string {
53
129
  if (!data.length) return '';
54
130
 
55
- const { includeHeaders = true } = options;
131
+ const {
132
+ includeHeaders = true,
133
+ locale,
134
+ sanitizeForSecurity = true
135
+ } = options;
56
136
 
57
137
  // Create CSV header row
58
- const headers = columns.map(col => col.header || col.id || "Column");
138
+ const headers = columns.map(col => {
139
+ const headerValue = col.header || col.id || "Column";
140
+ return escapeCSVValue(headerValue, sanitizeForSecurity);
141
+ });
59
142
 
60
143
  // Format data into CSV rows
61
144
  const csvData = data.map(row => {
62
145
  return columns.map(col => {
63
146
  const key = col.accessorKey || col.id;
64
- const value = (row as any)[key];
65
- // Escape commas and quotes
66
- const escapedValue = String(value || '').replace(/"/g, '""');
67
- return `"${escapedValue}"`;
147
+ let value = key ? row[key] : undefined;
148
+
149
+ // Format according to locale if provided
150
+ if (locale && (typeof value === 'number' || value instanceof Date || typeof value === 'boolean')) {
151
+ value = formatLocaleValue(value, locale);
152
+ }
153
+
154
+ // Escape the value for CSV
155
+ return escapeCSVValue(value, sanitizeForSecurity);
68
156
  }).join(",");
69
157
  });
70
158
 
@@ -82,6 +170,7 @@ export function generateCSVContent<TData>(
82
170
  * @param data - Array of data objects to export
83
171
  * @param columns - Column definitions for mapping
84
172
  * @param filename - Optional filename for download (default: "download.csv")
173
+ * @param options - Optional export configuration
85
174
  * @returns Promise that resolves when export is complete, rejects on error
86
175
  *
87
176
  * @example
@@ -98,7 +187,7 @@ export function generateCSVContent<TData>(
98
187
  * ];
99
188
  *
100
189
  * try {
101
- * await exportToCSV(users, columns, 'users.csv');
190
+ * await exportToCSV(users, columns, 'users.csv', { locale: 'en-US' });
102
191
  * showSuccessToast('Data exported successfully');
103
192
  * } catch (error) {
104
193
  * showErrorToast('Failed to export data');
@@ -112,13 +201,22 @@ export function generateCSVContent<TData>(
112
201
  * - Triggers browser download
113
202
  * - Throws error if export fails
114
203
  */
115
- export function exportToCSV<TData>(
204
+ export function exportToCSV<TData extends DataRecord>(
116
205
  data: TData[],
117
- columns: any[],
118
- filename: string = "download.csv"
206
+ columns: ExportColumn[],
207
+ filename: string = "download.csv",
208
+ options: {
209
+ locale?: string;
210
+ sanitizeForSecurity?: boolean;
211
+ } = {}
119
212
  ): Promise<void> {
213
+ const logger = createLogger('ExportUtils');
120
214
  return new Promise((resolve, reject) => {
121
215
  try {
216
+ if (typeof window === 'undefined') {
217
+ throw new Error('CSV export is only available in browser environments');
218
+ }
219
+
122
220
  if (!data || data.length === 0) {
123
221
  throw new Error('No data to export');
124
222
  }
@@ -127,7 +225,7 @@ export function exportToCSV<TData>(
127
225
  throw new Error('No columns defined for export');
128
226
  }
129
227
 
130
- const csvContent = generateCSVContent(data, columns);
228
+ const csvContent = generateCSVContent(data, columns, options);
131
229
 
132
230
  // Create and trigger download
133
231
  const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
@@ -150,7 +248,7 @@ export function exportToCSV<TData>(
150
248
  link.click();
151
249
  document.body.removeChild(link);
152
250
  } catch (error) {
153
- console.error('Failed to export data to CSV:', error);
251
+ logger.error('Failed to export data to CSV:', error);
154
252
  reject(error);
155
253
  }
156
254
  });
@@ -8,6 +8,9 @@
8
8
  * This utility can be used across different data tables with different column structures.
9
9
  */
10
10
 
11
+ import { createLogger } from '../../../utils/logger';
12
+ import type { CellValue } from '../types';
13
+
11
14
  export interface ColumnMapping {
12
15
  [targetField: string]: string[];
13
16
  }
@@ -16,9 +19,20 @@ export interface ImportOptions {
16
19
  columnMappings?: ColumnMapping;
17
20
  dateFormats?: readonly string[];
18
21
  dateFormatHints?: Record<string, readonly string[]>; // Field-specific date format hints
19
- defaultValues?: Record<string, any>;
22
+ defaultValues?: Record<string, CellValue>;
20
23
  timezone?: string; // Default timezone for date parsing
21
24
  strictDateParsing?: boolean; // Whether to be strict about date format matching
25
+ maxRows?: number; // Maximum number of rows to import (default: 10000)
26
+ maxStringLength?: number; // Maximum length for string values (default: 10000)
27
+ allowControlChars?: boolean; // Whether to allow control characters (default: false)
28
+ schemaValidation?: Record<string, {
29
+ required?: boolean;
30
+ type?: 'string' | 'number' | 'boolean' | 'date';
31
+ min?: number;
32
+ max?: number;
33
+ pattern?: RegExp;
34
+ allowEmpty?: boolean;
35
+ }>; // Schema validation rules
22
36
  }
23
37
 
24
38
  // Predefined date format sets for common use cases
@@ -140,15 +154,117 @@ export const DATE_FORMAT_SETS = {
140
154
  * });
141
155
  * ```
142
156
  */
143
- export function flexibleImport<T = any>(
144
- csvData: any[],
157
+ export interface ImportError {
158
+ row: number;
159
+ field: string;
160
+ message: string;
161
+ }
162
+
163
+ export interface ImportWarning {
164
+ row: number;
165
+ field: string;
166
+ message: string;
167
+ }
168
+
169
+ /**
170
+ * Sanitizes a string value by removing or escaping dangerous characters
171
+ */
172
+ function sanitizeString(value: string, options: ImportOptions): string {
173
+ const maxLength = options.maxStringLength || 10000;
174
+ let sanitized = value;
175
+
176
+ // Truncate to max length
177
+ if (sanitized.length > maxLength) {
178
+ sanitized = sanitized.substring(0, maxLength);
179
+ }
180
+
181
+ // Remove control characters if not allowed
182
+ if (!options.allowControlChars) {
183
+ // Keep tabs, newlines, carriage returns
184
+ sanitized = sanitized.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, '');
185
+ }
186
+
187
+ // Remove null bytes
188
+ sanitized = sanitized.replace(/\0/g, '');
189
+
190
+ // Remove SQL injection attempts
191
+ sanitized = sanitized.replace(/['";]/g, (char) => {
192
+ // Escape quotes and semicolons
193
+ return char === '"' ? '&quot;' : char === "'" ? '&apos;' : '&semi;';
194
+ });
195
+
196
+ return sanitized;
197
+ }
198
+
199
+ /**
200
+ * Validates a value against schema rules
201
+ */
202
+ function validateValue(field: string, value: unknown, rules: ImportOptions['schemaValidation']): {
203
+ valid: boolean;
204
+ message?: string;
205
+ } {
206
+ if (!rules || !rules[field]) {
207
+ return { valid: true };
208
+ }
209
+
210
+ const rule = rules[field];
211
+
212
+ // Check required
213
+ if (rule.required && (value === null || value === undefined || value === '')) {
214
+ return { valid: false, message: `Field '${field}' is required` };
215
+ }
216
+
217
+ // Check empty allowed
218
+ if (!rule.allowEmpty && value === '') {
219
+ return { valid: false, message: `Field '${field}' cannot be empty` };
220
+ }
221
+
222
+ // Check type
223
+ if (rule.type) {
224
+ if (rule.type === 'number') {
225
+ if (typeof value !== 'number' && (typeof value !== 'string' || isNaN(Number(value)))) {
226
+ return { valid: false, message: `Field '${field}' must be a number` };
227
+ }
228
+ const numValue = typeof value === 'number' ? value : Number(value);
229
+
230
+ if (rule.min !== undefined && numValue < rule.min) {
231
+ return { valid: false, message: `Field '${field}' must be at least ${rule.min}` };
232
+ }
233
+
234
+ if (rule.max !== undefined && numValue > rule.max) {
235
+ return { valid: false, message: `Field '${field}' must be at most ${rule.max}` };
236
+ }
237
+ } else if (rule.type === 'boolean') {
238
+ if (typeof value !== 'boolean' && value !== 'true' && value !== 'false') {
239
+ return { valid: false, message: `Field '${field}' must be a boolean` };
240
+ }
241
+ } else if (rule.type === 'date') {
242
+ const dateValue = typeof value === 'string' ? new Date(value) : value;
243
+ if (!(dateValue instanceof Date) || isNaN(dateValue.getTime())) {
244
+ return { valid: false, message: `Field '${field}' must be a valid date` };
245
+ }
246
+ }
247
+ }
248
+
249
+ // Check pattern
250
+ if (rule.pattern && typeof value === 'string') {
251
+ if (!rule.pattern.test(value)) {
252
+ return { valid: false, message: `Field '${field}' does not match required pattern` };
253
+ }
254
+ }
255
+
256
+ return { valid: true };
257
+ }
258
+
259
+ export function flexibleImport<T extends Record<string, unknown>>(
260
+ csvData: Record<string, unknown>[],
145
261
  targetFields: string[],
146
262
  options: ImportOptions = {}
147
263
  ): {
148
264
  mappedData: T[];
149
265
  mappings: Record<string, string | null>;
150
- errors: any[];
151
- warnings: any[];
266
+ errors: ImportError[];
267
+ warnings: ImportWarning[];
152
268
  stats: {
153
269
  totalRows: number;
154
270
  successfulRows: number;
@@ -156,9 +272,34 @@ export function flexibleImport<T = any>(
156
272
  warningRows: number;
157
273
  };
158
274
  } {
159
- console.log('🔄 Starting flexible import...');
160
- console.log('🔄 Available CSV columns:', Object.keys(csvData[0] || {}));
161
- console.log('🔄 Target fields:', targetFields);
275
+ const logger = createLogger('FlexibleImport');
276
+ logger.info('Starting flexible import...');
277
+ logger.debug('Available CSV columns:', Object.keys(csvData[0] || {}));
278
+ logger.debug('Target fields:', targetFields);
279
+
280
+ const maxRows = options.maxRows || 10000;
281
+
282
+ // Check row limit
283
+ if (csvData.length > maxRows) {
284
+ const error: ImportError = {
285
+ row: 0,
286
+ field: 'global',
287
+ message: `Import exceeds maximum row limit of ${maxRows}. Found ${csvData.length} rows.`
288
+ };
289
+ logger.error('Import exceeds row limit', { rowCount: csvData.length, limit: maxRows });
290
+ return {
291
+ mappedData: [],
292
+ mappings: {},
293
+ errors: [error],
294
+ warnings: [],
295
+ stats: {
296
+ totalRows: csvData.length,
297
+ successfulRows: 0,
298
+ errorRows: csvData.length,
299
+ warningRows: 0
300
+ }
301
+ };
302
+ }
162
303
 
163
304
  // Default column mappings
164
305
  const defaultMappings: ColumnMapping = {
@@ -192,11 +333,11 @@ export function flexibleImport<T = any>(
192
333
  possibleName.toLowerCase().includes(col.toLowerCase())
193
334
  );
194
335
  if (found) {
195
- console.log(`✅ Mapped ${targetField} -> ${found}`);
336
+ logger.debug(`Mapped ${targetField} -> ${found}`);
196
337
  return found;
197
338
  }
198
339
  }
199
- console.log(`❌ No mapping found for ${targetField}`);
340
+ logger.warn(`No mapping found for ${targetField}`);
200
341
  return null;
201
342
  };
202
343
 
@@ -206,7 +347,7 @@ export function flexibleImport<T = any>(
206
347
  mappings[field] = findColumn(field);
207
348
  });
208
349
 
209
- console.log('🔄 Column mappings:', mappings);
350
+ logger.debug('Column mappings:', mappings);
210
351
 
211
352
  // Enhanced date parsing with multiple format support
212
353
  const parseDate = (dateStr: string, fieldName?: string): Date | null => {
@@ -320,16 +461,19 @@ export function flexibleImport<T = any>(
320
461
 
321
462
 
322
463
  // Parse different data types
323
- const parseValue = (value: any, fieldName: string): any => {
464
+ const parseValue = (value: unknown, fieldName: string): unknown => {
324
465
  if (value === null || value === undefined || value === '') {
325
466
  return options.defaultValues?.[fieldName] || '';
326
467
  }
327
468
 
328
469
  // Auto-detect and parse different data types
329
470
  if (typeof value === 'string') {
471
+ // Sanitize string values
472
+ const sanitized = sanitizeString(value, options);
473
+
330
474
  // Try to parse as date first (for fields that might contain dates)
331
475
  if (fieldName.toLowerCase().includes('date') || fieldName.toLowerCase().includes('time')) {
332
- const dateValue = parseDate(value, fieldName);
476
+ const dateValue = parseDate(sanitized, fieldName);
333
477
  if (dateValue) {
334
478
  // Return ISO string for consistent date handling
335
479
  return dateValue.toISOString();
@@ -337,57 +481,83 @@ export function flexibleImport<T = any>(
337
481
  }
338
482
 
339
483
  // Try to parse as boolean
340
- if (value.toLowerCase() === 'true') return true;
341
- if (value.toLowerCase() === 'false') return false;
484
+ if (sanitized.toLowerCase() === 'true') return true;
485
+ if (sanitized.toLowerCase() === 'false') return false;
342
486
 
343
487
  // Try to parse as array (comma-separated)
344
- if (value.includes(',') && (fieldName.toLowerCase().includes('tag') || fieldName.toLowerCase().includes('category'))) {
345
- return value.split(',').map((item: string) => item.trim()).filter((item: string) => item);
488
+ if (sanitized.includes(',') && (fieldName.toLowerCase().includes('tag') || fieldName.toLowerCase().includes('category'))) {
489
+ return sanitized.split(',').map((item: string) => item.trim()).filter((item: string) => item);
346
490
  }
347
491
 
348
492
  // Try to parse as number (only if not a date field)
349
493
  if (!fieldName.toLowerCase().includes('date') && !fieldName.toLowerCase().includes('time')) {
350
- const numValue = parseFloat(value);
494
+ const numValue = parseFloat(sanitized);
351
495
  if (!isNaN(numValue) && isFinite(numValue)) {
352
496
  return numValue;
353
497
  }
354
498
  }
499
+
500
+ return sanitized;
355
501
  }
356
502
 
357
503
  return value;
358
504
  };
359
505
 
360
- const mappedData = csvData.map((row, index) => {
361
- console.log(`🔄 Processing row ${index + 1}:`, row);
506
+ const validationErrors: ImportError[] = [];
507
+ const validationWarnings: ImportWarning[] = [];
508
+ const mappedData: T[] = [];
509
+
510
+ for (let index = 0; index < csvData.length; index++) {
511
+ const row = csvData[index];
512
+ logger.debug(`Processing row ${index + 1}:`, row);
362
513
 
363
- const transformedRow: any = {};
514
+ const transformedRow: Record<string, unknown> = {};
515
+ let hasErrors = false;
364
516
 
365
517
  targetFields.forEach(field => {
366
518
  const sourceColumn = mappings[field];
519
+ let value: unknown;
520
+
367
521
  if (sourceColumn && row[sourceColumn] !== undefined) {
368
- transformedRow[field] = parseValue(row[sourceColumn], field);
522
+ value = parseValue(row[sourceColumn], field);
369
523
  } else {
370
- transformedRow[field] = options.defaultValues?.[field] || '';
524
+ value = options.defaultValues?.[field] || '';
525
+ }
526
+
527
+ transformedRow[field] = value;
528
+
529
+ // Validate against schema
530
+ const validation = validateValue(field, value, options.schemaValidation);
531
+ if (!validation.valid) {
532
+ validationErrors.push({
533
+ row: index + 1,
534
+ field,
535
+ message: validation.message || `Validation failed for field '${field}'`
536
+ });
537
+ hasErrors = true;
371
538
  }
372
539
  });
373
540
 
374
- console.log(`🔄 Transformed row ${index + 1}:`, transformedRow);
375
- return transformedRow;
376
- });
377
-
378
- // Validation and error handling
379
- const validationErrors: any[] = [];
380
- const validationWarnings: any[] = [];
541
+ // Only add row if validation passed (or if no validation rules)
542
+ if (!options.schemaValidation || !hasErrors) {
543
+ mappedData.push(transformedRow as T);
544
+ }
545
+
546
+ logger.debug(`Transformed row ${index + 1}:`, transformedRow);
547
+ }
381
548
 
549
+ // Calculate unique error rows (multiple errors per row still count as 1 error row)
550
+ const errorRowSet = new Set(validationErrors.map(e => e.row));
551
+
382
552
  return {
383
- mappedData,
553
+ mappedData: mappedData,
384
554
  mappings,
385
555
  errors: validationErrors,
386
556
  warnings: validationWarnings,
387
557
  stats: {
388
558
  totalRows: csvData.length,
389
559
  successfulRows: mappedData.length,
390
- errorRows: validationErrors.length,
560
+ errorRows: errorRowSet.size,
391
561
  warningRows: validationWarnings.length,
392
562
  }
393
563
  };
@@ -91,7 +91,7 @@ export function groupHierarchicalData<TData extends HierarchicalDataRow>(
91
91
  * Optimized depth cache to avoid recalculating depth for the same row
92
92
  * This prevents O(n²) behavior when calculating depths for all rows
93
93
  */
94
- const depthCache = new WeakMap<any[], Map<string, number>>();
94
+ const depthCache = new WeakMap<unknown[], Map<string, number>>();
95
95
 
96
96
  /**
97
97
  * Gets the depth level of a row in the hierarchy
@@ -2,5 +2,7 @@ export * from './exportUtils';
2
2
  export * from './rowUtils';
3
3
  export * from './hierarchicalUtils';
4
4
  export * from './hierarchicalSorting';
5
+ export * from './a11yUtils';
6
+ export * from './paginationUtils';
5
7
  // Stubs for legacy error handling (kept for useDataTablePerformance compatibility)
6
8
  export * from './errorHandling';