@jmruthers/pace-core 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/README.md +231 -229
  3. package/dist/{DataTable-2LB6HI6V.js → DataTable-GX3XERFJ.js} +14 -17
  4. package/dist/{DataTable-BDBqkU-i.d.ts → DataTable-ltTFXHS3.d.ts} +25 -51
  5. package/dist/{Table-CIm9IWqk.d.ts → PublicLoadingSpinner-DztrzuJr.d.ts} +635 -122
  6. package/dist/UnifiedAuthProvider-w66zSCUf.d.ts +160 -0
  7. package/dist/{api-AIJ3IJX3.js → api-ETQ6YJ3C.js} +6 -4
  8. package/dist/{appConfig-fB1pP_v3.d.ts → appConfig-BVGyuvI7.d.ts} +1 -1
  9. package/dist/appNameResolver-7GHF5ED2.js +22 -0
  10. package/dist/{audit-PD5L5ZSC.js → audit-BUW3LMJB.js} +3 -3
  11. package/dist/chunk-5EL3KHOQ.js +388 -0
  12. package/dist/chunk-5EL3KHOQ.js.map +1 -0
  13. package/dist/{chunk-4MCJAK7J.js → chunk-6CR3MRZN.js} +1827 -4886
  14. package/dist/chunk-6CR3MRZN.js.map +1 -0
  15. package/dist/{chunk-YNU5QJ4S.js → chunk-7BNPOCLL.js} +22 -5
  16. package/dist/chunk-7BNPOCLL.js.map +1 -0
  17. package/dist/chunk-AUE24LVR.js +268 -0
  18. package/dist/chunk-AUE24LVR.js.map +1 -0
  19. package/dist/chunk-C5G2A4PO.js +1349 -0
  20. package/dist/chunk-C5G2A4PO.js.map +1 -0
  21. package/dist/{chunk-4ZTIEYU2.js → chunk-CDQ3PX7L.js} +1 -1
  22. package/dist/chunk-CDQ3PX7L.js.map +1 -0
  23. package/dist/chunk-COBPIXXQ.js +379 -0
  24. package/dist/chunk-COBPIXXQ.js.map +1 -0
  25. package/dist/chunk-GSNM5D6H.js +5441 -0
  26. package/dist/chunk-GSNM5D6H.js.map +1 -0
  27. package/dist/chunk-MZBUOP4P.js +119 -0
  28. package/dist/chunk-MZBUOP4P.js.map +1 -0
  29. package/dist/chunk-N2EUGZRW.js +98 -0
  30. package/dist/chunk-N2EUGZRW.js.map +1 -0
  31. package/dist/chunk-NQ4TOOO6.js +20 -0
  32. package/dist/chunk-NQ4TOOO6.js.map +1 -0
  33. package/dist/{chunk-KK6WIDK6.js → chunk-OEGRKULD.js} +12 -2
  34. package/dist/{chunk-KK6WIDK6.js.map → chunk-OEGRKULD.js.map} +1 -1
  35. package/dist/chunk-OYRY44Q2.js +62 -0
  36. package/dist/chunk-OYRY44Q2.js.map +1 -0
  37. package/dist/{chunk-DC5AMYBS.js → chunk-PLDDJCW6.js} +15 -5
  38. package/dist/chunk-PLDDJCW6.js.map +1 -0
  39. package/dist/{chunk-WHLSWC6W.js → chunk-SS3E6QLB.js} +16 -61
  40. package/dist/chunk-SS3E6QLB.js.map +1 -0
  41. package/dist/chunk-T3XIA4AJ.js +3295 -0
  42. package/dist/chunk-T3XIA4AJ.js.map +1 -0
  43. package/dist/{chunk-H4PZ4B3Y.js → chunk-TGDCLPP2.js} +129 -28
  44. package/dist/chunk-TGDCLPP2.js.map +1 -0
  45. package/dist/{chunk-IOX76PSM.js → chunk-U6JDHVC2.js} +273 -29
  46. package/dist/chunk-U6JDHVC2.js.map +1 -0
  47. package/dist/{chunk-JUUNUW3O.js → chunk-XJK2J4N6.js} +17 -6
  48. package/dist/chunk-XJK2J4N6.js.map +1 -0
  49. package/dist/chunk-YDJW5XTN.js +84 -0
  50. package/dist/chunk-YDJW5XTN.js.map +1 -0
  51. package/dist/components.d.ts +906 -10
  52. package/dist/components.js +3263 -84
  53. package/dist/components.js.map +1 -1
  54. package/dist/{database-CAMsquLm.d.ts → database-C3Szpi5J.d.ts} +28 -11
  55. package/dist/hooks.d.ts +7 -6
  56. package/dist/hooks.js +35 -11
  57. package/dist/hooks.js.map +1 -1
  58. package/dist/index.d.ts +245 -111
  59. package/dist/index.js +195 -185
  60. package/dist/index.js.map +1 -1
  61. package/dist/{organisation-DLNNQhPB.d.ts → organisation-CO3Sh3_D.d.ts} +1 -1
  62. package/dist/providers.d.ts +4 -4
  63. package/dist/providers.js +21 -6
  64. package/dist/rbac/index.d.ts +862 -806
  65. package/dist/rbac/index.js +953 -1032
  66. package/dist/rbac/index.js.map +1 -1
  67. package/dist/styles/core.css +422 -0
  68. package/dist/styles/fonts/georama-italic.woff2 +0 -0
  69. package/dist/styles/fonts/georama.woff2 +0 -0
  70. package/dist/styles/fonts/open-sans-italic.woff2 +0 -0
  71. package/dist/styles/fonts/open-sans.woff2 +0 -0
  72. package/dist/styles/fonts/reddit-mono.woff2 +0 -0
  73. package/dist/styles/index.d.ts +36 -0
  74. package/dist/styles/index.js +24 -0
  75. package/dist/styles/index.js.map +1 -0
  76. package/dist/theming/runtime.d.ts +73 -0
  77. package/dist/theming/runtime.js +16 -0
  78. package/dist/theming/runtime.js.map +1 -0
  79. package/dist/{types-Bavn44NW.d.ts → types-BRDU7N6w.d.ts} +79 -33
  80. package/dist/types.d.ts +5 -5
  81. package/dist/types.js +7 -2
  82. package/dist/types.js.map +1 -1
  83. package/dist/{unified-BtRpPbmp.d.ts → unified-CM7T0aTK.d.ts} +1 -2
  84. package/dist/usePublicRouteParams-B6i0KtXW.d.ts +477 -0
  85. package/dist/utils.d.ts +83 -60
  86. package/dist/utils.js +301 -55657
  87. package/dist/utils.js.map +1 -1
  88. package/dist/validation.d.ts +1 -1
  89. package/dist/validation.js +1 -1
  90. package/docs/INDEX.md +192 -0
  91. package/docs/README.md +46 -32
  92. package/docs/api/README.md +231 -229
  93. package/docs/api/classes/ErrorBoundary.md +1 -1
  94. package/docs/api/classes/PublicErrorBoundary.md +132 -0
  95. package/docs/api/interfaces/AggregateConfig.md +4 -4
  96. package/docs/api/interfaces/ButtonProps.md +2 -2
  97. package/docs/api/interfaces/CardProps.md +2 -2
  98. package/docs/api/interfaces/ColorPalette.md +1 -1
  99. package/docs/api/interfaces/ColorShade.md +1 -1
  100. package/docs/api/interfaces/DataTableAction.md +98 -7
  101. package/docs/api/interfaces/DataTableColumn.md +131 -12
  102. package/docs/api/interfaces/DataTableProps.md +77 -274
  103. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  104. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  105. package/docs/api/interfaces/EventContextType.md +7 -7
  106. package/docs/api/interfaces/EventLogoProps.md +152 -0
  107. package/docs/api/interfaces/EventProviderProps.md +2 -2
  108. package/docs/api/interfaces/FileSizeLimits.md +7 -0
  109. package/docs/api/interfaces/FileUploadProps.md +154 -0
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/InactivityWarningModalProps.md +115 -0
  112. package/docs/api/interfaces/InputProps.md +2 -2
  113. package/docs/api/interfaces/LabelProps.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationItem.md +1 -1
  116. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  117. package/docs/api/interfaces/Organisation.md +1 -1
  118. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  119. package/docs/api/interfaces/OrganisationMembership.md +2 -2
  120. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  121. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  122. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -26
  123. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  124. package/docs/api/interfaces/PaletteData.md +1 -1
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +94 -0
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +68 -0
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +86 -0
  128. package/docs/api/interfaces/PublicPageFooterProps.md +112 -0
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +138 -0
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +138 -0
  131. package/docs/api/interfaces/StorageConfig.md +41 -0
  132. package/docs/api/interfaces/StorageFileInfo.md +74 -0
  133. package/docs/api/interfaces/StorageFileMetadata.md +140 -0
  134. package/docs/api/interfaces/StorageListOptions.md +86 -0
  135. package/docs/api/interfaces/StorageListResult.md +41 -0
  136. package/docs/api/interfaces/StorageUploadOptions.md +88 -0
  137. package/docs/api/interfaces/StorageUploadResult.md +63 -0
  138. package/docs/api/interfaces/StorageUrlOptions.md +47 -0
  139. package/docs/api/interfaces/StyleImport.md +2 -2
  140. package/docs/api/interfaces/ToastActionElement.md +1 -1
  141. package/docs/api/interfaces/ToastProps.md +1 -1
  142. package/docs/api/interfaces/UnifiedAuthContextType.md +447 -46
  143. package/docs/api/interfaces/UnifiedAuthProviderProps.md +95 -9
  144. package/docs/api/interfaces/UseInactivityTrackerOptions.md +136 -0
  145. package/docs/api/interfaces/UseInactivityTrackerReturn.md +123 -0
  146. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  147. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  148. package/docs/api/interfaces/UsePublicEventOptions.md +34 -0
  149. package/docs/api/interfaces/UsePublicEventReturn.md +68 -0
  150. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +94 -0
  151. package/docs/api/interfaces/UserEventAccess.md +14 -14
  152. package/docs/api/interfaces/UserMenuProps.md +6 -6
  153. package/docs/api/interfaces/UserProfile.md +1 -1
  154. package/docs/api/modules.md +1626 -768
  155. package/docs/api-reference/components.md +761 -43
  156. package/docs/api-reference/hooks.md +126 -0
  157. package/docs/api-reference/providers.md +141 -65
  158. package/docs/api-reference/types.md +66 -36
  159. package/docs/api-reference/utilities.md +1 -1
  160. package/docs/architecture/README.md +1 -2
  161. package/docs/best-practices/README.md +400 -0
  162. package/docs/consuming-app-example.md +42 -96
  163. package/docs/consuming-app-vite-config.md +233 -0
  164. package/docs/core-concepts/events.md +3 -3
  165. package/docs/core-concepts/organisations.md +0 -1
  166. package/docs/core-concepts/rbac-system.md +23 -10
  167. package/docs/documentation-style-checklist.md +8 -2
  168. package/docs/examples/navigation-menu-auth-fix.md +344 -0
  169. package/docs/getting-started/examples/README.md +15 -1
  170. package/docs/getting-started/examples/basic-auth-app.md +444 -119
  171. package/docs/getting-started/examples/full-featured-app.md +6 -6
  172. package/docs/getting-started/installation.md +231 -52
  173. package/docs/getting-started/quick-start.md +121 -24
  174. package/docs/implementation-guides/app-layout.md +133 -108
  175. package/docs/implementation-guides/data-tables.md +1011 -29
  176. package/docs/implementation-guides/forms.md +3 -3
  177. package/docs/implementation-guides/hierarchical-datatable.md +850 -0
  178. package/docs/implementation-guides/large-datasets.md +2 -2
  179. package/docs/implementation-guides/navigation.md +1 -1
  180. package/docs/implementation-guides/permission-enforcement.md +4 -4
  181. package/docs/implementation-guides/public-pages.md +752 -0
  182. package/docs/migration/README.md +18 -8
  183. package/docs/migration/quick-migration-guide.md +320 -0
  184. package/docs/migration/rbac-migration.md +50 -0
  185. package/docs/migration/v0.4.15-tailwind-scanning.md +272 -0
  186. package/docs/migration/v0.4.16-css-first-approach.md +306 -0
  187. package/docs/migration/v0.4.17-source-path-fix.md +229 -0
  188. package/docs/migration-guide.md +51 -104
  189. package/docs/performance/README.md +1 -4
  190. package/docs/print-components/README.md +258 -0
  191. package/docs/print-components/api-reference.md +636 -0
  192. package/docs/print-components/examples/README.md +204 -0
  193. package/docs/print-components/examples/basic-report.tsx +92 -0
  194. package/docs/print-components/examples/card-catalog.tsx +149 -0
  195. package/docs/print-components/examples/cover-page-report.tsx +163 -0
  196. package/docs/print-components/quick-start.md +363 -0
  197. package/docs/quick-reference.md +53 -36
  198. package/docs/rbac/README.md +136 -69
  199. package/docs/rbac/api-reference.md +39 -8
  200. package/docs/rbac/examples.md +237 -66
  201. package/docs/rbac/getting-started.md +131 -16
  202. package/docs/rbac/quick-start.md +499 -323
  203. package/docs/rbac/troubleshooting.md +240 -262
  204. package/docs/security/README.md +50 -1
  205. package/docs/styles/README.md +143 -117
  206. package/docs/testing/README.md +6 -10
  207. package/docs/troubleshooting/README.md +497 -0
  208. package/docs/troubleshooting/common-issues.md +604 -14
  209. package/docs/troubleshooting/styling-issues.md +219 -0
  210. package/docs/troubleshooting/tailwind-content-scanning.md +213 -0
  211. package/docs/usage.md +28 -90
  212. package/docs/visual-testing.md +0 -7
  213. package/package.json +46 -24
  214. package/src/__mocks__/lucide-react.ts +181 -0
  215. package/src/__tests__/REBUILD_PLAN.md +223 -0
  216. package/src/__tests__/TESTING_GUIDELINES.md +341 -0
  217. package/src/__tests__/fixtures/mocks.ts +93 -0
  218. package/src/__tests__/helpers/component-test-utils.tsx +145 -0
  219. package/src/__tests__/helpers/test-utils.tsx +117 -0
  220. package/src/__tests__/integration/UserProfile.test.tsx +128 -0
  221. package/src/__tests__/setup.ts +71 -0
  222. package/src/__tests__/templates/accessibility.test.template.tsx +279 -0
  223. package/src/__tests__/templates/component.test.template.tsx +144 -0
  224. package/src/__tests__/templates/hook.test.template.ts +173 -0
  225. package/src/__tests__/templates/integration.test.template.tsx +199 -0
  226. package/src/__tests__/types/test.types.ts +106 -0
  227. package/src/components/Alert/Alert.test.tsx +496 -0
  228. package/src/components/Alert/Alert.tsx +134 -0
  229. package/src/components/Alert/index.ts +2 -0
  230. package/src/components/Avatar/Avatar.test.tsx +484 -0
  231. package/src/components/Avatar/Avatar.tsx +84 -0
  232. package/src/components/Avatar/index.ts +2 -0
  233. package/src/components/Button/Button.test.tsx +662 -0
  234. package/src/components/Button/Button.tsx +270 -0
  235. package/src/components/Button/index.ts +2 -0
  236. package/src/components/Card/Card.test.tsx +593 -0
  237. package/src/components/Card/Card.tsx +271 -0
  238. package/src/components/Card/index.ts +1 -0
  239. package/src/components/Checkbox/Checkbox.test.tsx +461 -0
  240. package/src/components/Checkbox/Checkbox.tsx +75 -0
  241. package/src/components/Checkbox/__mocks__/Checkbox.tsx +2 -0
  242. package/src/components/Checkbox/index.ts +2 -0
  243. package/src/components/DataTable/DataTable.tsx +446 -0
  244. package/src/components/DataTable/__tests__/README.md +145 -0
  245. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +66 -0
  246. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +103 -0
  247. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +381 -0
  248. package/src/components/DataTable/__tests__/test-utils.ts +94 -0
  249. package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
  250. package/src/components/DataTable/components/ActionButtons.tsx +194 -0
  251. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +160 -0
  252. package/src/components/DataTable/components/ColumnFilter.tsx +114 -0
  253. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +100 -0
  254. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  255. package/src/components/DataTable/components/DataTableCore.tsx +1027 -0
  256. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +214 -0
  257. package/src/components/DataTable/components/DataTableModals.tsx +87 -0
  258. package/src/components/DataTable/components/DataTableToolbar.tsx +262 -0
  259. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  260. package/src/components/DataTable/components/EditableRow.tsx +159 -0
  261. package/src/components/DataTable/components/EmptyState.tsx +64 -0
  262. package/src/components/DataTable/components/ExpandButton.tsx +113 -0
  263. package/src/components/DataTable/components/FilterRow.tsx +100 -0
  264. package/src/components/DataTable/components/GroupHeader.tsx +42 -0
  265. package/src/components/DataTable/components/GroupingDropdown.tsx +96 -0
  266. package/src/components/DataTable/components/ImportModal.tsx +345 -0
  267. package/src/components/DataTable/components/LoadingState.tsx +12 -0
  268. package/src/components/DataTable/components/PaginationControls.tsx +332 -0
  269. package/src/components/DataTable/components/UnifiedTableBody.tsx +742 -0
  270. package/src/components/DataTable/components/ViewRowModal.tsx +68 -0
  271. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  272. package/src/components/DataTable/components/index.ts +16 -0
  273. package/src/components/DataTable/context/DataTableContext.tsx +97 -0
  274. package/src/components/DataTable/core/ActionManager.ts +235 -0
  275. package/src/components/DataTable/core/ColumnFactory.ts +268 -0
  276. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  277. package/src/components/DataTable/core/DataManager.ts +188 -0
  278. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  279. package/src/components/DataTable/core/LocalDataAdapter.ts +264 -0
  280. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  281. package/src/components/DataTable/core/StateManager.ts +311 -0
  282. package/src/components/DataTable/core/index.ts +8 -0
  283. package/src/components/DataTable/core/interfaces.ts +338 -0
  284. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +419 -0
  285. package/src/components/DataTable/examples/HierarchicalExample.tsx +475 -0
  286. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +176 -0
  287. package/src/components/DataTable/examples/PerformanceExample.tsx +505 -0
  288. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +95 -0
  289. package/src/components/DataTable/hooks/useColumnReordering.ts +110 -0
  290. package/src/components/DataTable/hooks/useDataTableState.ts +325 -0
  291. package/src/components/DataTable/hooks/useHierarchicalState.ts +174 -0
  292. package/src/components/DataTable/index.ts +68 -0
  293. package/src/components/DataTable/styles.ts +171 -0
  294. package/src/components/DataTable/types.ts +511 -0
  295. package/src/components/DataTable/utils/debugTools.ts +583 -0
  296. package/src/components/DataTable/utils/errorHandling.ts +494 -0
  297. package/src/components/DataTable/utils/exportUtils.ts +126 -0
  298. package/src/components/DataTable/utils/flexibleImport.ts +510 -0
  299. package/src/components/DataTable/utils/hierarchicalSorting.ts +151 -0
  300. package/src/components/DataTable/utils/hierarchicalUtils.ts +218 -0
  301. package/src/components/DataTable/utils/index.ts +1 -0
  302. package/src/components/DataTable/utils/performanceUtils.ts +351 -0
  303. package/src/components/Dialog/Dialog.test.tsx +1139 -0
  304. package/src/components/Dialog/Dialog.tsx +782 -0
  305. package/src/components/Dialog/README.md +804 -0
  306. package/src/components/Dialog/examples/BasicHtmlTest.tsx +55 -0
  307. package/src/components/Dialog/examples/DebugHtmlExample.tsx +68 -0
  308. package/src/components/Dialog/examples/HtmlDialogExample.tsx +202 -0
  309. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +61 -0
  310. package/src/components/Dialog/examples/SmartDialogExample.tsx +322 -0
  311. package/src/components/Dialog/index.ts +12 -0
  312. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  313. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
  314. package/src/components/ErrorBoundary/ErrorBoundary.tsx +312 -0
  315. package/src/components/ErrorBoundary/index.ts +8 -0
  316. package/src/components/EventSelector/EventSelector.tsx +360 -0
  317. package/src/components/EventSelector/index.ts +3 -0
  318. package/src/components/EventSelector/types.ts +79 -0
  319. package/src/components/FileUpload/FileUpload.example.tsx +218 -0
  320. package/src/components/FileUpload/FileUpload.test.tsx +665 -0
  321. package/src/components/FileUpload/FileUpload.tsx +237 -0
  322. package/src/components/FileUpload/index.ts +6 -0
  323. package/src/components/Footer/Footer.tsx +197 -0
  324. package/src/components/Footer/index.ts +17 -0
  325. package/src/components/Form/Form.tsx +166 -0
  326. package/src/components/Form/FormErrorSummary.tsx +113 -0
  327. package/src/components/Form/FormField.tsx +249 -0
  328. package/src/components/Form/FormFieldset.tsx +127 -0
  329. package/src/components/Form/FormLiveRegion.tsx +198 -0
  330. package/src/components/Form/index.ts +26 -0
  331. package/src/components/Header/Header.tsx +301 -0
  332. package/src/components/Header/index.ts +4 -0
  333. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +164 -0
  334. package/src/components/InactivityWarningModal/index.ts +9 -0
  335. package/src/components/Input/Input.tsx +201 -0
  336. package/src/components/Input/__mocks__/Input.tsx +2 -0
  337. package/src/components/Input/index.ts +9 -0
  338. package/src/components/Label/Label.tsx +186 -0
  339. package/src/components/Label/index.ts +2 -0
  340. package/src/components/LoadingSpinner/LoadingSpinner.tsx +98 -0
  341. package/src/components/LoadingSpinner/index.ts +3 -0
  342. package/src/components/LoginForm/LoginForm.tsx +273 -0
  343. package/src/components/LoginForm/index.ts +3 -0
  344. package/src/components/NavigationMenu/NavigationMenu.tsx +698 -0
  345. package/src/components/NavigationMenu/index.ts +10 -0
  346. package/src/components/NavigationMenu/types.ts +85 -0
  347. package/src/components/OrganisationSelector/OrganisationSelector.tsx +304 -0
  348. package/src/components/OrganisationSelector/index.ts +9 -0
  349. package/src/components/PaceAppLayout/PaceAppLayout.tsx +699 -0
  350. package/src/components/PaceAppLayout/README.md +278 -0
  351. package/src/components/PaceAppLayout/index.ts +1 -0
  352. package/src/components/PaceLoginPage/PaceLoginPage.tsx +221 -0
  353. package/src/components/PaceLoginPage/index.ts +1 -0
  354. package/src/components/PasswordReset/PasswordChangeForm.tsx +186 -0
  355. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  356. package/src/components/PasswordReset/index.ts +4 -0
  357. package/src/components/PrintButton/PrintButton.tsx +321 -0
  358. package/src/components/PrintButton/PrintButtonGroup.tsx +84 -0
  359. package/src/components/PrintButton/PrintToolbar.tsx +94 -0
  360. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +438 -0
  361. package/src/components/PrintButton/index.ts +33 -0
  362. package/src/components/PrintButton/types.ts +173 -0
  363. package/src/components/PrintCard/PrintCard.tsx +154 -0
  364. package/src/components/PrintCard/PrintCardContent.tsx +57 -0
  365. package/src/components/PrintCard/PrintCardFooter.tsx +60 -0
  366. package/src/components/PrintCard/PrintCardGrid.tsx +91 -0
  367. package/src/components/PrintCard/PrintCardHeader.tsx +78 -0
  368. package/src/components/PrintCard/PrintCardImage.tsx +81 -0
  369. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +239 -0
  370. package/src/components/PrintCard/index.ts +34 -0
  371. package/src/components/PrintCard/types.ts +171 -0
  372. package/src/components/PrintDataTable/PrintDataTable.tsx +215 -0
  373. package/src/components/PrintDataTable/PrintTableGroup.tsx +90 -0
  374. package/src/components/PrintDataTable/PrintTableRow.tsx +76 -0
  375. package/src/components/PrintDataTable/index.ts +25 -0
  376. package/src/components/PrintDataTable/types.ts +67 -0
  377. package/src/components/PrintFooter/PrintFooter.tsx +183 -0
  378. package/src/components/PrintFooter/PrintFooterContent.tsx +71 -0
  379. package/src/components/PrintFooter/PrintFooterInfo.tsx +86 -0
  380. package/src/components/PrintFooter/PrintPageNumber.tsx +90 -0
  381. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +390 -0
  382. package/src/components/PrintFooter/index.ts +30 -0
  383. package/src/components/PrintFooter/types.ts +149 -0
  384. package/src/components/PrintGrid/PrintGrid.tsx +180 -0
  385. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +109 -0
  386. package/src/components/PrintGrid/PrintGridContainer.tsx +128 -0
  387. package/src/components/PrintGrid/PrintGridItem.tsx +220 -0
  388. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +359 -0
  389. package/src/components/PrintGrid/index.ts +31 -0
  390. package/src/components/PrintGrid/types.ts +159 -0
  391. package/src/components/PrintHeader/PrintCoverHeader.tsx +230 -0
  392. package/src/components/PrintHeader/PrintHeader.tsx +150 -0
  393. package/src/components/PrintHeader/index.ts +17 -0
  394. package/src/components/PrintHeader/types.ts +42 -0
  395. package/src/components/PrintLayout/PrintLayout.tsx +122 -0
  396. package/src/components/PrintLayout/PrintLayoutContext.tsx +66 -0
  397. package/src/components/PrintLayout/PrintPageBreak.tsx +52 -0
  398. package/src/components/PrintLayout/examples/PrintShowcase.tsx +230 -0
  399. package/src/components/PrintLayout/index.ts +19 -0
  400. package/src/components/PrintLayout/types.ts +37 -0
  401. package/src/components/PrintPageBreak/PrintPageBreak.tsx +120 -0
  402. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +90 -0
  403. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +112 -0
  404. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +279 -0
  405. package/src/components/PrintPageBreak/index.ts +23 -0
  406. package/src/components/PrintPageBreak/types.ts +94 -0
  407. package/src/components/PrintSection/PrintColumn.tsx +104 -0
  408. package/src/components/PrintSection/PrintDivider.tsx +101 -0
  409. package/src/components/PrintSection/PrintSection.tsx +129 -0
  410. package/src/components/PrintSection/PrintSectionContent.tsx +75 -0
  411. package/src/components/PrintSection/PrintSectionHeader.tsx +97 -0
  412. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +258 -0
  413. package/src/components/PrintSection/index.ts +33 -0
  414. package/src/components/PrintSection/types.ts +155 -0
  415. package/src/components/PrintText/PrintText.tsx +116 -0
  416. package/src/components/PrintText/index.ts +16 -0
  417. package/src/components/PrintText/types.ts +24 -0
  418. package/src/components/Progress/Progress.tsx +116 -0
  419. package/src/components/Progress/index.ts +3 -0
  420. package/src/components/PublicLayout/EventLogo.tsx +287 -0
  421. package/src/components/PublicLayout/PublicErrorBoundary.tsx +279 -0
  422. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +208 -0
  423. package/src/components/PublicLayout/PublicPageContextChecker.tsx +130 -0
  424. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  425. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  426. package/src/components/PublicLayout/PublicPageFooter.tsx +124 -0
  427. package/src/components/PublicLayout/PublicPageHeader.tsx +178 -0
  428. package/src/components/PublicLayout/PublicPageLayout.tsx +232 -0
  429. package/src/components/PublicLayout/PublicPageProvider.tsx +137 -0
  430. package/src/components/PublicLayout/index.ts +51 -0
  431. package/src/components/RBAC/PagePermissionGuard.tsx +287 -0
  432. package/src/components/RBAC/RBACGuard.tsx +143 -0
  433. package/src/components/RBAC/RBACProvider.tsx +186 -0
  434. package/src/components/RBAC/RoleBasedContent.tsx +129 -0
  435. package/src/components/RBAC/index.ts +23 -0
  436. package/src/components/Select/Select.tsx +660 -0
  437. package/src/components/Select/index.ts +1 -0
  438. package/src/components/SuperAdminGuard.tsx +116 -0
  439. package/src/components/Table/Table.tsx +222 -0
  440. package/src/components/Table/index.ts +11 -0
  441. package/src/components/Toast/Toast.tsx +339 -0
  442. package/src/components/Toast/index.ts +14 -0
  443. package/src/components/Tooltip/Tooltip.tsx +167 -0
  444. package/src/components/Tooltip/index.ts +7 -0
  445. package/src/components/UserMenu/UserMenu.tsx +243 -0
  446. package/src/components/UserMenu/index.ts +3 -0
  447. package/src/components/examples/PermissionExample.tsx +150 -0
  448. package/src/components/index.ts +434 -0
  449. package/src/components.ts +19 -0
  450. package/src/constants/performance.ts +14 -0
  451. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  452. package/src/examples/PublicEventPage.tsx +274 -0
  453. package/src/examples/PublicPageApp.tsx +308 -0
  454. package/src/examples/PublicPageUsageExample.tsx +216 -0
  455. package/src/hooks/index.ts +56 -0
  456. package/src/hooks/public/index.ts +34 -0
  457. package/src/hooks/public/usePublicEvent.ts +261 -0
  458. package/src/hooks/public/usePublicEventLogo.ts +285 -0
  459. package/src/hooks/public/usePublicRouteParams.ts +259 -0
  460. package/src/hooks/useAppConfig.ts +94 -0
  461. package/src/hooks/useComponentPerformance.ts +39 -0
  462. package/src/hooks/useCounter.test.ts +135 -0
  463. package/src/hooks/useDataTablePerformance.ts +387 -0
  464. package/src/hooks/useDataTableState.ts +110 -0
  465. package/src/hooks/useDebounce.ts +18 -0
  466. package/src/hooks/useFocusManagement.ts +161 -0
  467. package/src/hooks/useFocusTrap.ts +155 -0
  468. package/src/hooks/useInactivityTracker.ts +372 -0
  469. package/src/hooks/useIsMobile.ts +42 -0
  470. package/src/hooks/useKeyboardShortcuts.ts +237 -0
  471. package/src/hooks/useOrganisationPermissions.ts +208 -0
  472. package/src/hooks/useOrganisationSecurity.ts +262 -0
  473. package/src/hooks/usePerformanceMonitor.ts +128 -0
  474. package/src/hooks/usePermissionCache.ts +455 -0
  475. package/src/hooks/useRBAC.ts +262 -0
  476. package/src/hooks/useSecureDataAccess.ts +586 -0
  477. package/src/hooks/useStorage.ts +274 -0
  478. package/src/hooks/useToast.ts +242 -0
  479. package/src/hooks/useZodForm.ts +28 -0
  480. package/src/index.ts +200 -0
  481. package/src/providers/AuthProvider.tsx +369 -0
  482. package/src/providers/EventProvider.tsx +324 -0
  483. package/src/providers/InactivityProvider.tsx +238 -0
  484. package/src/providers/OrganisationProvider.tsx +588 -0
  485. package/src/providers/RBACProvider.tsx +634 -0
  486. package/src/providers/UnifiedAuthProvider.tsx +327 -0
  487. package/src/providers/index.ts +15 -0
  488. package/src/rbac/README.md +885 -0
  489. package/src/rbac/adapters.tsx +726 -0
  490. package/src/rbac/api.ts +339 -0
  491. package/src/rbac/audit-enhanced.ts +339 -0
  492. package/src/rbac/audit.ts +338 -0
  493. package/src/rbac/cache.ts +215 -0
  494. package/src/rbac/components/EnhancedNavigationMenu.tsx +294 -0
  495. package/src/rbac/components/NavigationGuard.tsx +294 -0
  496. package/src/rbac/components/NavigationProvider.tsx +314 -0
  497. package/src/rbac/components/PagePermissionGuard.tsx +430 -0
  498. package/src/rbac/components/PagePermissionProvider.tsx +274 -0
  499. package/src/rbac/components/PermissionEnforcer.tsx +307 -0
  500. package/src/rbac/components/RoleBasedRouter.tsx +425 -0
  501. package/src/rbac/components/SecureDataProvider.tsx +319 -0
  502. package/src/rbac/components/index.ts +64 -0
  503. package/src/rbac/config.ts +133 -0
  504. package/src/rbac/docs/event-based-apps.md +285 -0
  505. package/src/rbac/engine.ts +1026 -0
  506. package/src/rbac/eslint-rules.js +285 -0
  507. package/src/rbac/examples/CompleteRBACExample.tsx +323 -0
  508. package/src/rbac/examples/EventBasedApp.tsx +238 -0
  509. package/src/rbac/hooks.ts +570 -0
  510. package/src/rbac/index.ts +114 -0
  511. package/src/rbac/permissions.ts +293 -0
  512. package/src/rbac/secureClient.ts +244 -0
  513. package/src/rbac/security.ts +346 -0
  514. package/src/rbac/testing/index.tsx +340 -0
  515. package/src/rbac/types.ts +343 -0
  516. package/src/rbac/utils/eventContext.ts +83 -0
  517. package/src/styles/core.css +422 -0
  518. package/src/styles/index.ts +51 -0
  519. package/src/theming/runtime.ts +187 -0
  520. package/src/types/database.ts +472 -0
  521. package/src/types/guards.ts +30 -0
  522. package/src/types/index.ts +25 -0
  523. package/src/types/organisation.ts +184 -0
  524. package/src/types/security.ts +70 -0
  525. package/src/types/supabase.ts +166 -0
  526. package/src/types/theme.ts +6 -0
  527. package/src/types/unified.ts +262 -0
  528. package/src/types/validation.ts +164 -0
  529. package/src/types/vitest-globals.d.ts +43 -0
  530. package/src/utils/__mocks__/supabaseMock.ts +75 -0
  531. package/src/utils/__mocks__/supabaseMock.tsx +198 -0
  532. package/src/utils/appConfig.ts +47 -0
  533. package/src/utils/appIdResolver.ts +130 -0
  534. package/src/utils/appNameResolver.ts +190 -0
  535. package/src/utils/audit.ts +127 -0
  536. package/src/utils/auth-utils.ts +96 -0
  537. package/src/utils/bundleAnalysis.ts +129 -0
  538. package/src/utils/cn.ts +7 -0
  539. package/src/utils/debugLogger.ts +46 -0
  540. package/src/utils/deviceFingerprint.ts +215 -0
  541. package/src/utils/dynamicUtils.ts +105 -0
  542. package/src/utils/formatting.ts +77 -0
  543. package/src/utils/index.ts +145 -0
  544. package/src/utils/lazyLoad.tsx +44 -0
  545. package/src/utils/organisationContext.ts +135 -0
  546. package/src/utils/performanceBenchmark.ts +64 -0
  547. package/src/utils/performanceBudgets.ts +111 -0
  548. package/src/utils/permissionTypes.ts +37 -0
  549. package/src/utils/permissionUtils.ts +31 -0
  550. package/src/utils/print/PrintDataProcessor.ts +390 -0
  551. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +397 -0
  552. package/src/utils/print/index.ts +29 -0
  553. package/src/utils/print/types.ts +196 -0
  554. package/src/utils/print/usePrintOptimization.ts +272 -0
  555. package/src/utils/sanitization.ts +264 -0
  556. package/src/utils/schemaUtils.ts +37 -0
  557. package/src/utils/secureDataAccess.ts +361 -0
  558. package/src/utils/secureErrors.ts +79 -0
  559. package/src/utils/secureStorage.ts +244 -0
  560. package/src/utils/security.ts +156 -0
  561. package/src/utils/securityMonitor.ts +45 -0
  562. package/src/utils/sessionTracking.ts +170 -0
  563. package/src/utils/storage/README.md +348 -0
  564. package/src/utils/storage/config.ts +100 -0
  565. package/src/utils/storage/helpers.ts +359 -0
  566. package/src/utils/storage/index.ts +36 -0
  567. package/src/utils/storage/types.ts +90 -0
  568. package/src/utils/validation.ts +111 -0
  569. package/src/utils/validationUtils.ts +120 -0
  570. package/src/validation/common.ts +53 -0
  571. package/src/validation/csrf.ts +214 -0
  572. package/src/validation/index.ts +43 -0
  573. package/src/validation/passwordSchema.ts +125 -0
  574. package/src/validation/sanitization.ts +96 -0
  575. package/src/validation/schemaUtils.ts +42 -0
  576. package/src/validation/sqlInjectionProtection.ts +242 -0
  577. package/src/validation/user.ts +34 -0
  578. package/dist/UnifiedAuthProvider-V7y63NjT.d.ts +0 -88
  579. package/dist/chunk-4MCJAK7J.js.map +0 -1
  580. package/dist/chunk-4ZTIEYU2.js.map +0 -1
  581. package/dist/chunk-H4PZ4B3Y.js.map +0 -1
  582. package/dist/chunk-IOX76PSM.js.map +0 -1
  583. package/dist/chunk-JUUNUW3O.js.map +0 -1
  584. package/dist/chunk-U7DY5T33.js +0 -11
  585. package/dist/chunk-U7DY5T33.js.map +0 -1
  586. package/dist/chunk-WHLSWC6W.js.map +0 -1
  587. package/dist/chunk-XI7QFSSC.js +0 -790
  588. package/dist/chunk-XI7QFSSC.js.map +0 -1
  589. package/dist/chunk-XIJMMBDD.js +0 -73
  590. package/dist/chunk-XIJMMBDD.js.map +0 -1
  591. package/dist/chunk-YNU5QJ4S.js.map +0 -1
  592. package/dist/chunk-YWYCNGWH.js +0 -2070
  593. package/dist/chunk-YWYCNGWH.js.map +0 -1
  594. package/dist/chunk-ZJ3UKPIW.js +0 -952
  595. package/dist/chunk-ZJ3UKPIW.js.map +0 -1
  596. package/dist/useAppConfig-CZNJJsT_.d.ts +0 -148
  597. package/dist/{DataTable-2LB6HI6V.js.map → DataTable-GX3XERFJ.js.map} +0 -0
  598. package/dist/{api-AIJ3IJX3.js.map → api-ETQ6YJ3C.js.map} +0 -0
  599. package/dist/{audit-PD5L5ZSC.js.map → appNameResolver-7GHF5ED2.js.map} +0 -0
  600. package/dist/{chunk-DC5AMYBS.js.map → audit-BUW3LMJB.js.map} +0 -0
  601. package/dist/{validation-D2-NNCCE.d.ts → validation-PM_iOaTI.d.ts} +6 -6
@@ -0,0 +1,345 @@
1
+ /**
2
+ * @file Import Modal Component
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/DataTable/Components
5
+ * @since 0.2.0
6
+ *
7
+ * A modal dialog for importing CSV data into the DataTable component.
8
+ * Provides file selection, data preview, and validation functionality.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <ImportModal
13
+ * isOpen={showModal}
14
+ * onClose={() => setShowModal(false)}
15
+ * onImport={(data) => handleImportedData(data)}
16
+ * title="Import Users"
17
+ * description="Upload a CSV file containing user data to import multiple users at once."
18
+ * uploadText="Choose a user CSV file to upload"
19
+ * selectFileButtonText="Select User File"
20
+ * />
21
+ * ```
22
+ *
23
+ * @accessibility
24
+ * - Uses pace-core Dialog component with full accessibility support
25
+ * - Proper ARIA labels and descriptions
26
+ * - Keyboard navigation support
27
+ * - Screen reader compatible file input
28
+ * - Error messages are announced to screen readers
29
+ *
30
+ * @features
31
+ * - CSV file validation and parsing
32
+ * - Data preview (first 5 rows)
33
+ * - Total row count display
34
+ * - Error handling and user feedback
35
+ * - Processing state management
36
+ * - Customizable text content
37
+ */
38
+ import React, { useState, useRef, useEffect } from 'react';
39
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../Dialog';
40
+ import { Button } from '../../Button/Button';
41
+ import { Input } from '../../Input/Input';
42
+ import { Upload, FileText, AlertCircle } from 'lucide-react';
43
+
44
+ /**
45
+ * Configuration interface for customizing ImportModal text content
46
+ * @public
47
+ */
48
+ export interface ImportModalConfig {
49
+ /** Custom title for the import modal */
50
+ title?: string;
51
+ /** Custom description text shown below the title */
52
+ description?: string;
53
+ /** Custom text shown in the file upload area when no file is selected */
54
+ uploadText?: string;
55
+ /** Custom text for the file selection button */
56
+ selectFileButtonText?: string;
57
+ /** Custom text for the import button */
58
+ importButtonText?: string;
59
+ /** Custom text for the import button when processing */
60
+ importButtonProcessingText?: string;
61
+ /** Custom text for the cancel button */
62
+ cancelButtonText?: string;
63
+ /** Custom text for the preview section header */
64
+ previewHeaderText?: string;
65
+ /** Custom text pattern for total rows display. Use {count} as placeholder for the actual count */
66
+ totalRowsText?: string;
67
+ }
68
+
69
+ /**
70
+ * Props interface for the ImportModal component
71
+ * @public
72
+ */
73
+ interface ImportModalProps {
74
+ /** Whether the modal is open */
75
+ isOpen: boolean;
76
+ /** Callback function when the modal is closed */
77
+ onClose: () => void;
78
+ /** Callback function when data is imported successfully */
79
+ onImport: (data: any[]) => void | Promise<void>;
80
+ /** Configuration object for customizing modal text content */
81
+ config?: ImportModalConfig;
82
+ }
83
+
84
+ /**
85
+ * ImportModal component for handling CSV data import
86
+ *
87
+ * @param props - The component props
88
+ * @returns JSX.Element - The import modal dialog
89
+ *
90
+ * @example
91
+ * ```tsx
92
+ * const importConfig = {
93
+ * title: "Import Customer Data",
94
+ * description: "Upload a CSV file with customer information to import multiple records.",
95
+ * uploadText: "Choose a customer CSV file",
96
+ * selectFileButtonText: "Browse Files",
97
+ * importButtonText: "Import Customers",
98
+ * totalRowsText: "Found {count} customer records to import"
99
+ * };
100
+ *
101
+ * <ImportModal
102
+ * isOpen={isImportModalOpen}
103
+ * onClose={() => setIsImportModalOpen(false)}
104
+ * onImport={handleDataImport}
105
+ * config={importConfig}
106
+ * />
107
+ * ```
108
+ */
109
+ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportModalProps) {
110
+ const [file, setFile] = useState<File | null>(null);
111
+ const [isProcessing, setIsProcessing] = useState(false);
112
+ const [error, setError] = useState<string | null>(null);
113
+ const [previewData, setPreviewData] = useState<any[] | null>(null);
114
+ const [totalCount, setTotalCount] = useState<number>(0);
115
+ const fileInputRef = useRef<HTMLInputElement>(null);
116
+ const isMountedRef = useRef(true);
117
+
118
+ // Cleanup effect to prevent state updates after unmount
119
+ useEffect(() => {
120
+ return () => {
121
+ isMountedRef.current = false;
122
+ };
123
+ }, []);
124
+
125
+ // Extract config with defaults
126
+ const {
127
+ title = 'Import Data',
128
+ description = 'Upload a CSV file to import multiple records at once.',
129
+ uploadText = 'Choose a CSV file to upload',
130
+ selectFileButtonText = 'Select File',
131
+ importButtonText = 'Import',
132
+ importButtonProcessingText = 'Processing...',
133
+ cancelButtonText = 'Cancel',
134
+ previewHeaderText = 'Preview (first 5 rows)',
135
+ totalRowsText = 'Total rows to import: {count}'
136
+ } = config;
137
+
138
+ const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {
139
+ const selectedFile = event.target.files?.[0];
140
+ console.log('📁 File selected:', selectedFile?.name);
141
+ if (selectedFile) {
142
+ setFile(selectedFile);
143
+ setError(null);
144
+
145
+ // Generate preview
146
+ try {
147
+ const text = await selectedFile.text();
148
+ console.log('📄 File content length:', text.length);
149
+ const data = processCSV(text);
150
+ console.log('📊 Parsed CSV data:', data.length, 'rows');
151
+ console.log('👀 Setting preview data:', data.slice(0, 5));
152
+ setPreviewData(data.slice(0, 5)); // Show first 5 rows as preview
153
+ setTotalCount(data.length); // Store total count
154
+ console.log('👀 Preview data state should be updated');
155
+ } catch (err) {
156
+ console.error('❌ CSV parsing error:', err);
157
+ setError(err instanceof Error ? err.message : 'Failed to preview file');
158
+ setPreviewData(null);
159
+ setTotalCount(0);
160
+ }
161
+ }
162
+ };
163
+
164
+ const processCSV = (csvText: string): any[] => {
165
+ console.log('📄 Raw CSV text:', csvText.substring(0, 200) + '...');
166
+
167
+ const lines = csvText.split('\n').filter(line => line.trim());
168
+ console.log('📄 CSV lines count:', lines.length);
169
+ console.log('📄 First few lines:', lines.slice(0, 3));
170
+
171
+ if (lines.length < 2) {
172
+ throw new Error('CSV must have at least a header row and one data row');
173
+ }
174
+
175
+ // Better CSV parsing that handles quotes and commas within values
176
+ const parseCSVLine = (line: string): string[] => {
177
+ const result: string[] = [];
178
+ let current = '';
179
+ let inQuotes = false;
180
+
181
+ for (let i = 0; i < line.length; i++) {
182
+ const char = line[i];
183
+
184
+ if (char === '"') {
185
+ inQuotes = !inQuotes;
186
+ } else if (char === ',' && !inQuotes) {
187
+ result.push(current.trim());
188
+ current = '';
189
+ } else {
190
+ current += char;
191
+ }
192
+ }
193
+ result.push(current.trim());
194
+ return result;
195
+ };
196
+
197
+ const headers = parseCSVLine(lines[0]).map(h => h.replace(/"/g, '').trim());
198
+ console.log('📄 Parsed headers:', headers);
199
+
200
+ const data = lines.slice(1).map((line, index) => {
201
+ const values = parseCSVLine(line).map(v => v.replace(/"/g, '').trim());
202
+ const row: any = {};
203
+ headers.forEach((header, colIndex) => {
204
+ row[header] = values[colIndex] || '';
205
+ });
206
+ console.log(`📄 Row ${index + 1}:`, row);
207
+ return row;
208
+ });
209
+
210
+ console.log('📄 Final parsed data:', data);
211
+ return data;
212
+ };
213
+
214
+ const handleImport = async () => {
215
+ if (!file) return;
216
+
217
+ setIsProcessing(true);
218
+ setError(null);
219
+
220
+ try {
221
+ const text = await file.text();
222
+ const data = processCSV(text);
223
+
224
+ // Await the onImport callback in case it returns a promise
225
+ const result = onImport(data);
226
+ if (result && typeof result.then === 'function') {
227
+ await result;
228
+ }
229
+
230
+ onClose();
231
+ setFile(null);
232
+ } catch (err) {
233
+ setError(err instanceof Error ? err.message : 'Failed to process file');
234
+ } finally {
235
+ if (isMountedRef.current) {
236
+ setIsProcessing(false);
237
+ }
238
+ }
239
+ };
240
+
241
+ const handleClose = () => {
242
+ setFile(null);
243
+ setError(null);
244
+ setPreviewData(null);
245
+ setTotalCount(0);
246
+ onClose();
247
+ };
248
+
249
+ return (
250
+ <Dialog open={isOpen} onOpenChange={handleClose}>
251
+ <DialogContent className="sm:max-w-2xl bg-main-50">
252
+ <DialogHeader>
253
+ <DialogTitle>{title}</DialogTitle>
254
+ <DialogDescription>
255
+ {description}
256
+ </DialogDescription>
257
+ </DialogHeader>
258
+
259
+ <div className="space-y-4">
260
+ <div className="border-2 border-dashed border-sec-200 rounded-lg p-6 text-center">
261
+ <FileText className="h-8 w-8 mx-auto text-sec-400 mb-2" />
262
+ <p className="text-sec-600 mb-2">
263
+ {file ? `Selected: ${file.name}` : uploadText}
264
+ </p>
265
+ {file && (
266
+ <p className="text-xs text-sec-500">
267
+ File selected, processing preview...
268
+ </p>
269
+ )}
270
+ <Button
271
+ variant="outline"
272
+ size="sm"
273
+ onClick={() => fileInputRef.current?.click()}
274
+ >
275
+ <Upload className="h-4 w-4 mr-2" />
276
+ {selectFileButtonText}
277
+ </Button>
278
+ <Input
279
+ ref={fileInputRef}
280
+ type="file"
281
+ accept=".csv"
282
+ onChange={handleFileSelect}
283
+ className="hidden"
284
+ />
285
+ </div>
286
+
287
+ {error && (
288
+ <div className="flex items-center gap-2 p-3 bg-acc-50 border border-acc-200 rounded text-acc-700">
289
+ <AlertCircle className="h-4 w-4" />
290
+ <span className="text-sm">{error}</span>
291
+ </div>
292
+ )}
293
+
294
+
295
+ {previewData && previewData.length > 0 && (
296
+ <div className="space-y-3">
297
+ <h4 className="text-sec-900">{previewHeaderText}</h4>
298
+ <div className="border rounded-lg overflow-hidden">
299
+ <div className="overflow-x-auto max-h-48">
300
+ <table className="min-w-full text-xs">
301
+ <thead className="bg-sec-50">
302
+ <tr>
303
+ {Object.keys(previewData[0]).map((header) => (
304
+ <th key={header} className="px-2 py-1 text-left font-medium text-sec-900 border-b">
305
+ {header}
306
+ </th>
307
+ ))}
308
+ </tr>
309
+ </thead>
310
+ <tbody>
311
+ {previewData.map((row, index) => (
312
+ <tr key={index} className={index % 2 === 0 ? 'bg-app-main-50' : 'bg-sec-50'}>
313
+ {Object.values(row).map((value: any, cellIndex) => (
314
+ <td key={cellIndex} className="px-2 py-1 text-sec-700 border-b">
315
+ {String(value)}
316
+ </td>
317
+ ))}
318
+ </tr>
319
+ ))}
320
+ </tbody>
321
+ </table>
322
+ </div>
323
+ </div>
324
+ <p className="text-sec-500">
325
+ {totalRowsText.replace('{count}', totalCount.toString())}
326
+ </p>
327
+ </div>
328
+ )}
329
+
330
+ <div className="flex justify-end gap-2">
331
+ <Button variant="outline" onClick={handleClose}>
332
+ {cancelButtonText}
333
+ </Button>
334
+ <Button
335
+ onClick={handleImport}
336
+ disabled={!file || isProcessing}
337
+ >
338
+ {isProcessing ? importButtonProcessingText : importButtonText}
339
+ </Button>
340
+ </div>
341
+ </div>
342
+ </DialogContent>
343
+ </Dialog>
344
+ );
345
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ export function LoadingState() {
4
+ return (
5
+ <div className="p-8 text-center">
6
+ <div className="flex items-center justify-center space-x-2">
7
+ <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary"></div>
8
+ <span aria-live="polite" className="text-muted-foreground">Loading...</span>
9
+ </div>
10
+ </div>
11
+ );
12
+ }
@@ -0,0 +1,332 @@
1
+ import React from 'react';
2
+ import { Table } from '@tanstack/react-table';
3
+ import { Button } from '../../Button/Button';
4
+ import {
5
+ ChevronLeft,
6
+ ChevronRight,
7
+ ChevronsLeft,
8
+ ChevronsRight,
9
+ Loader2,
10
+ Server,
11
+ Database,
12
+ Zap
13
+ } from 'lucide-react';
14
+ import { cn } from '../../../utils/cn';
15
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../Select/Select';
16
+ import type { PaginationMode, ServerSideResponse, DataRecord } from '../types';
17
+
18
+ interface PaginationControlsProps<TData extends DataRecord> {
19
+ table: Table<TData>;
20
+ pageSizeOptions?: number[];
21
+ paginationMode?: PaginationMode;
22
+ serverData?: ServerSideResponse<TData> | null;
23
+ isLoading?: boolean;
24
+ onPageChange?: (pageIndex: number) => void;
25
+ onPageSizeChange?: (pageSize: number) => void;
26
+ showPerformanceInfo?: boolean;
27
+ totalCount?: number;
28
+ }
29
+
30
+ export function PaginationControls<TData extends DataRecord>({
31
+ table,
32
+ pageSizeOptions = [10, 20, 30, 40, 50],
33
+ paginationMode = 'client',
34
+ serverData,
35
+ isLoading = false,
36
+ onPageChange,
37
+ onPageSizeChange,
38
+ showPerformanceInfo = false,
39
+ totalCount
40
+ }: PaginationControlsProps<TData>) {
41
+
42
+ // Get pagination state based on mode
43
+ const getPaginationState = () => {
44
+ if (paginationMode === 'server' && serverData) {
45
+ return {
46
+ currentPageSize: serverData.pageSize,
47
+ currentPageIndex: serverData.pageIndex,
48
+ pageCount: serverData.pageCount,
49
+ totalRows: serverData.totalCount,
50
+ canPreviousPage: serverData.hasPreviousPage,
51
+ canNextPage: serverData.hasNextPage,
52
+ };
53
+ }
54
+
55
+ // Client or hybrid mode
56
+ const state = table.getState().pagination;
57
+ return {
58
+ currentPageSize: state.pageSize,
59
+ currentPageIndex: state.pageIndex,
60
+ pageCount: table.getPageCount(),
61
+ totalRows: totalCount ?? table.getRowCount(),
62
+ canPreviousPage: table.getCanPreviousPage(),
63
+ canNextPage: table.getCanNextPage(),
64
+ };
65
+ };
66
+
67
+ const {
68
+ currentPageSize,
69
+ currentPageIndex,
70
+ pageCount,
71
+ totalRows,
72
+ canPreviousPage,
73
+ canNextPage,
74
+ } = getPaginationState();
75
+
76
+ // Handle page size changes
77
+ const handlePageSizeChange = (newPageSize: number) => {
78
+ if (paginationMode === 'server') {
79
+ onPageSizeChange?.(newPageSize);
80
+ } else {
81
+ table.setPageSize(newPageSize);
82
+ }
83
+ };
84
+
85
+ // Handle page navigation
86
+ const handleFirstPage = () => {
87
+ if (paginationMode === 'server') {
88
+ onPageChange?.(0);
89
+ } else {
90
+ table.setPageIndex(0);
91
+ }
92
+ };
93
+
94
+ const handlePreviousPage = () => {
95
+ if (paginationMode === 'server') {
96
+ onPageChange?.(Math.max(0, currentPageIndex - 1));
97
+ } else {
98
+ table.previousPage();
99
+ }
100
+ };
101
+
102
+ const handleNextPage = () => {
103
+ if (paginationMode === 'server') {
104
+ onPageChange?.(Math.min(pageCount - 1, currentPageIndex + 1));
105
+ } else {
106
+ table.nextPage();
107
+ }
108
+ };
109
+
110
+ const handleLastPage = () => {
111
+ if (paginationMode === 'server') {
112
+ onPageChange?.(pageCount - 1);
113
+ } else {
114
+ table.setPageIndex(pageCount - 1);
115
+ }
116
+ };
117
+
118
+ // Calculate display range
119
+ const startRow = currentPageIndex * currentPageSize + 1;
120
+ const endRow = Math.min((currentPageIndex + 1) * currentPageSize, totalRows);
121
+
122
+ // Get mode-specific page size options
123
+ const getPageSizeOptions = () => {
124
+ switch (paginationMode) {
125
+ case 'server':
126
+ return pageSizeOptions.filter(size => size <= 250); // Limit server-side page sizes
127
+ case 'hybrid':
128
+ return pageSizeOptions.filter(size => size >= 50); // Hybrid mode prefers larger pages
129
+ default:
130
+ return pageSizeOptions;
131
+ }
132
+ };
133
+
134
+ const availablePageSizes = getPageSizeOptions();
135
+
136
+ // Performance mode indicator
137
+ const getModeIcon = () => {
138
+ switch (paginationMode) {
139
+ case 'server':
140
+ return <Server className="h-3 w-3" />;
141
+ case 'hybrid':
142
+ return <Database className="h-3 w-3" />;
143
+ default:
144
+ return <Zap className="h-3 w-3" />;
145
+ }
146
+ };
147
+
148
+ const getModeLabel = () => {
149
+ switch (paginationMode) {
150
+ case 'server':
151
+ return 'Server-side';
152
+ case 'hybrid':
153
+ return 'Hybrid';
154
+ default:
155
+ return 'Client-side';
156
+ }
157
+ };
158
+
159
+
160
+ return (
161
+ <footer
162
+ aria-label="pagination"
163
+ className="mx-auto grid grid-cols-[auto_auto_1fr_auto_auto_auto_auto] gap-4"
164
+ >
165
+ {/* Left side - Page Size Selector */}
166
+
167
+ <p className="text-sm text-sec-600">Rows per page</p>
168
+ <Select
169
+ value={currentPageSize?.toString() || '10'}
170
+ selectedText={currentPageSize?.toString() || '10'}
171
+ onValueChange={(value) => handlePageSizeChange(Number(value))}
172
+ disabled={isLoading}
173
+ className="w-36 h-8"
174
+ >
175
+ <SelectTrigger
176
+ className={cn(
177
+
178
+ isLoading && "opacity-50 cursor-not-allowed"
179
+ )}
180
+ aria-label="Rows per page"
181
+ >
182
+ <SelectValue />
183
+ </SelectTrigger>
184
+ <SelectContent>
185
+ {pageSizeOptions.map((pageSize) => (
186
+ <SelectItem key={pageSize} value={pageSize?.toString() || '10'}>
187
+ {pageSize}
188
+ </SelectItem>
189
+ ))}
190
+ </SelectContent>
191
+ </Select>
192
+
193
+
194
+ {/* Performance Mode Indicator */}
195
+ {showPerformanceInfo && (
196
+ <>
197
+ {getModeIcon()}
198
+ <span>{getModeLabel()}</span>
199
+ </>
200
+ )}
201
+
202
+
203
+ {/* Row Count Display - Removed as per user request, keeping only "Page X of Y" */}
204
+
205
+
206
+ {/* Center - Page Navigation */}
207
+
208
+ <p className="justify-self-center text-sm text-sec-600">
209
+ Page {currentPageIndex + 1} of {pageCount || 1}
210
+ </p>
211
+
212
+
213
+ {/* Right side - Navigation Buttons */}
214
+
215
+
216
+ <Button
217
+ variant="outline"
218
+ size="sm"
219
+ className="h-8 w-8 p-0"
220
+ onClick={handleFirstPage}
221
+ disabled={!canPreviousPage || isLoading}
222
+ aria-label="Go to first page"
223
+ tabIndex={0}
224
+ >
225
+ <ChevronsLeft className="h-4 w-4" />
226
+ </Button>
227
+
228
+ <Button
229
+ variant="outline"
230
+ size="sm"
231
+ className="h-8 w-8 p-0"
232
+ onClick={handlePreviousPage}
233
+ disabled={!canPreviousPage || isLoading}
234
+ aria-label="Go to previous page"
235
+ tabIndex={0}
236
+ >
237
+ <ChevronLeft className="h-4 w-4" />
238
+ </Button>
239
+
240
+ <Button
241
+ variant="outline"
242
+ size="sm"
243
+ className="h-8 w-8 p-0"
244
+ onClick={handleNextPage}
245
+ disabled={!canNextPage || isLoading}
246
+ aria-label="Go to next page"
247
+ tabIndex={0}
248
+ >
249
+ <ChevronRight className="h-4 w-4" />
250
+ </Button>
251
+
252
+ <Button
253
+ variant="outline"
254
+ size="sm"
255
+ className="h-8 w-8 p-0"
256
+ onClick={handleLastPage}
257
+ disabled={!canNextPage || isLoading}
258
+ aria-label="Go to last page"
259
+ tabIndex={0}
260
+ >
261
+ <ChevronsRight className="h-4 w-4" />
262
+ </Button>
263
+ </footer>
264
+ );
265
+ }
266
+
267
+ /**
268
+ * Enhanced pagination controls with additional features
269
+ * Provides jump-to-page functionality for improved navigation
270
+ */
271
+ interface EnhancedPaginationControlsProps<TData extends DataRecord>
272
+ extends PaginationControlsProps<TData> {
273
+ showJumpToPage?: boolean;
274
+ }
275
+
276
+ export function EnhancedPaginationControls<TData extends DataRecord>({
277
+ showJumpToPage = false,
278
+ ...props
279
+ }: EnhancedPaginationControlsProps<TData>) {
280
+ const [jumpToPage, setJumpToPage] = React.useState('');
281
+
282
+ const { table, paginationMode = 'client', serverData, onPageChange } = props;
283
+
284
+ const { pageCount } = (() => {
285
+ if (paginationMode === 'server' && serverData) {
286
+ return { pageCount: serverData.pageCount };
287
+ }
288
+ return { pageCount: table.getPageCount() };
289
+ })();
290
+
291
+ const handleJumpToPage = (e: React.FormEvent) => {
292
+ e.preventDefault();
293
+ const pageNumber = parseInt(jumpToPage, 10);
294
+ if (pageNumber >= 1 && pageNumber <= pageCount) {
295
+ const pageIndex = pageNumber - 1;
296
+ if (paginationMode === 'server') {
297
+ onPageChange?.(pageIndex);
298
+ } else {
299
+ table.setPageIndex(pageIndex);
300
+ }
301
+ setJumpToPage('');
302
+ }
303
+ };
304
+
305
+ return (
306
+ <>
307
+ <PaginationControls {...props} />
308
+
309
+ {/* Additional Controls */}
310
+ {showJumpToPage && (
311
+ <>
312
+ {/* Jump to Page */}
313
+ <form onSubmit={handleJumpToPage} className="flex items-center space-x-2">
314
+ <span>Jump to page:</span>
315
+ <input
316
+ type="number"
317
+ min="1"
318
+ max={pageCount}
319
+ value={jumpToPage}
320
+ onChange={(e) => setJumpToPage(e.target.value)}
321
+ className="w-16 h-6 px-2 border rounded text-xs"
322
+ placeholder="1"
323
+ />
324
+ <Button type="submit" size="sm" variant="outline" className="h-6 px-2 text-xs">
325
+ Go
326
+ </Button>
327
+ </form>
328
+ </>
329
+ )}
330
+ </>
331
+ );
332
+ }