@jmruthers/pace-core 0.6.8 → 0.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (669) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/audit-tool/audits/02-project-structure.cjs +97 -32
  3. package/audit-tool/audits/03-architecture.cjs +145 -19
  4. package/audit-tool/audits/04-code-quality.cjs +86 -1
  5. package/audit-tool/audits/06-security-rbac.cjs +109 -11
  6. package/cursor-rules/02-project-structure.mdc +2 -26
  7. package/cursor-rules/05-styling.mdc +84 -6
  8. package/cursor-rules/06-security-rbac.mdc +124 -1
  9. package/dist/{DataTable-6RMSCQJ6.js → DataTable-SAXFG4XI.js} +11 -13
  10. package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
  11. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
  12. package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
  13. package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
  14. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  15. package/dist/assets/app-icons/base_favicon.svg +85 -0
  16. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  17. package/dist/assets/app-icons/core_favicon.svg +256 -0
  18. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  19. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  20. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  21. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  22. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  23. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  24. package/dist/assets/app-icons/team_favicon.svg +67 -0
  25. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  26. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  27. package/dist/audit-Z6ZZBWLU.js +3 -0
  28. package/dist/chunk-3GWSPISD.js +61 -0
  29. package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
  30. package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
  31. package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
  32. package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
  33. package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
  34. package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
  35. package/dist/chunk-FN52B75D.js +246 -0
  36. package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
  37. package/dist/chunk-KPYQWGFQ.js +183 -0
  38. package/dist/{chunk-IUBRCBSY.js → chunk-KSNLMI7N.js} +14 -8
  39. package/dist/chunk-KYURMOQM.js +977 -0
  40. package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
  41. package/dist/{chunk-NKHKXPI4.js → chunk-MPY44PWB.js} +683 -627
  42. package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
  43. package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
  44. package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
  45. package/dist/{chunk-EURB7QFZ.js → chunk-TFIPNIPE.js} +867 -534
  46. package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
  47. package/dist/chunk-W46INAVW.js +1216 -0
  48. package/dist/chunk-X5EAU5G7.js +793 -0
  49. package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
  50. package/dist/components.d.ts +8 -86
  51. package/dist/components.js +21 -55
  52. package/dist/{database.generated-CcnC_DRc.d.ts → database.generated-DT8JTZiP.d.ts} +12 -12
  53. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  54. package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
  55. package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
  56. package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
  57. package/dist/hooks.d.ts +12 -11
  58. package/dist/hooks.js +69 -44
  59. package/dist/index.d.ts +380 -32
  60. package/dist/index.js +46 -32
  61. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  62. package/dist/providers.d.ts +28 -14
  63. package/dist/providers.js +5 -5
  64. package/dist/rbac/eslint-rules.js +2 -2
  65. package/dist/rbac/index.d.ts +58 -214
  66. package/dist/rbac/index.js +11 -11
  67. package/dist/theming/runtime.d.ts +9 -3
  68. package/dist/theming/runtime.js +2 -2
  69. package/dist/{timezone-BZe_eUxx.d.ts → timezone-K-ptz3HO.d.ts} +22 -23
  70. package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
  71. package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
  72. package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
  73. package/dist/types-Dr8sNhER.d.ts +50 -0
  74. package/dist/types.d.ts +5 -5
  75. package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
  76. package/dist/{usePublicRouteParams-MamNgwqe.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +8 -7
  77. package/dist/utils.d.ts +301 -137
  78. package/dist/utils.js +42 -41
  79. package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
  80. package/docs/api/modules.md +542 -549
  81. package/docs/api-reference/components.md +5 -5
  82. package/docs/api-reference/rpc-functions.md +3 -3
  83. package/docs/implementation-guides/data-tables.md +256 -8
  84. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  85. package/docs/standards/2-project-structure-standards.md +12 -74
  86. package/docs/standards/6-security-rbac-standards.md +222 -7
  87. package/docs/standards/7-api-tech-stack-standards.md +91 -3
  88. package/docs/testing/README.md +10 -0
  89. package/docs/testing/test-setup-for-consumers.md +914 -0
  90. package/eslint-config-pace-core.cjs +4 -0
  91. package/package.json +1 -1
  92. package/scripts/eslint-audit.cjs +110 -11
  93. package/src/__mocks__/lucide-react.ts +0 -2
  94. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
  95. package/src/__tests__/index.test.ts +532 -0
  96. package/src/__tests__/integration/UserProfile.test.tsx +1 -1
  97. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
  98. package/src/__tests__/rls-policies.test.ts +3 -2
  99. package/src/assets/app-icons/admin_favicon.svg +462 -0
  100. package/src/assets/app-icons/base_favicon.svg +85 -0
  101. package/src/assets/app-icons/cake_favicon.svg +68 -0
  102. package/src/assets/app-icons/core_favicon.svg +256 -0
  103. package/src/assets/app-icons/gear_favicon.svg +91 -0
  104. package/src/assets/app-icons/index.ts +83 -0
  105. package/src/assets/app-icons/medi_favicon.svg +92 -0
  106. package/src/assets/app-icons/mint_favicon.svg +83 -0
  107. package/src/assets/app-icons/pace_favicon.svg +49 -0
  108. package/src/assets/app-icons/pump_favicon.svg +68 -0
  109. package/src/assets/app-icons/seed_favicon.svg +91 -0
  110. package/src/assets/app-icons/team_favicon.svg +67 -0
  111. package/src/assets/app-icons/trac_favicon.svg +112 -0
  112. package/src/assets/app-icons/trip_favicon.svg +102 -0
  113. package/src/components/AddressField/AddressField.test.tsx +378 -3
  114. package/src/components/AddressField/AddressField.tsx +2 -2
  115. package/src/components/AddressField/types.ts +2 -2
  116. package/src/components/Alert/Alert.test.tsx +35 -25
  117. package/src/components/Alert/Alert.tsx +8 -8
  118. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  119. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  120. package/src/components/Avatar/Avatar.test.tsx +11 -1
  121. package/src/components/Avatar/Avatar.tsx +3 -2
  122. package/src/components/Badge/Badge.test.tsx +11 -1
  123. package/src/components/Button/Button.test.tsx +13 -3
  124. package/src/components/Calendar/Calendar.test.tsx +523 -131
  125. package/src/components/Calendar/Calendar.tsx +107 -488
  126. package/src/components/Card/Card.test.tsx +220 -249
  127. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  128. package/src/components/ContextSelector/ContextSelector.tsx +3 -3
  129. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
  130. package/src/components/DataTable/DataTable.tsx +2 -2
  131. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
  132. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
  133. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
  134. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +485 -0
  135. package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
  136. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
  137. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
  138. package/src/components/DataTable/__tests__/README.md +1 -1
  139. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
  140. package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
  141. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
  142. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
  143. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
  144. package/src/components/DataTable/components/ActionButtons.tsx +9 -4
  145. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
  146. package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
  147. package/src/components/DataTable/components/DataTableCore.tsx +44 -52
  148. package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
  149. package/src/components/DataTable/components/DataTableModals.tsx +118 -30
  150. package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
  151. package/src/components/DataTable/components/EditFields.tsx +6 -47
  152. package/src/components/DataTable/components/EditableRow.tsx +8 -8
  153. package/src/components/DataTable/components/EmptyState.tsx +6 -3
  154. package/src/components/DataTable/components/FilterRow.tsx +18 -11
  155. package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
  156. package/src/components/DataTable/components/ImportModal.tsx +305 -133
  157. package/src/components/DataTable/components/LoadingState.tsx +2 -2
  158. package/src/components/DataTable/components/PaginationControls.tsx +0 -4
  159. package/src/components/DataTable/components/RowComponent.tsx +42 -22
  160. package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
  161. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
  162. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
  163. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
  164. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
  165. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
  166. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
  167. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
  168. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
  169. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
  170. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
  171. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
  172. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
  173. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
  174. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
  175. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
  176. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
  177. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
  178. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
  179. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
  180. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
  181. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
  182. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
  183. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
  184. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
  185. package/src/components/DataTable/context/DataTableContext.tsx +9 -10
  186. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
  187. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  188. package/src/components/DataTable/core/ColumnManager.ts +0 -1
  189. package/src/components/DataTable/core/DataManager.ts +4 -2
  190. package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
  191. package/src/components/DataTable/core/PluginRegistry.ts +2 -2
  192. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
  193. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
  194. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
  195. package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
  196. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
  197. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
  198. package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
  199. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
  200. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
  201. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
  202. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
  203. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
  204. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
  205. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
  206. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
  207. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
  208. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
  209. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +298 -23
  210. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
  211. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  212. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  213. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
  214. package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
  215. package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
  216. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
  217. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
  218. package/src/components/DataTable/hooks/useTableColumns.ts +36 -38
  219. package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
  220. package/src/components/DataTable/index.ts +24 -2
  221. package/src/components/DataTable/types.ts +6 -3
  222. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
  223. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
  224. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
  225. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
  226. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
  227. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
  228. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
  229. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
  230. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +208 -0
  231. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  232. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  233. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  234. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  235. package/src/components/DataTable/utils/flexibleImport.ts +2 -2
  236. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  237. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  238. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  239. package/src/components/DataTable/utils/selectFieldUtils.ts +127 -0
  240. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
  241. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  242. package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
  243. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  244. package/src/components/Dialog/Dialog.test.tsx +2007 -407
  245. package/src/components/Dialog/Dialog.tsx +97 -192
  246. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  247. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  248. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  249. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  250. package/src/components/ErrorBoundary/index.ts +3 -4
  251. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  252. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
  253. package/src/components/FileDisplay/FileDisplay.tsx +14 -12
  254. package/src/components/FileDisplay/index.tsx +1 -1
  255. package/src/components/FileUpload/FileUpload.test.tsx +54 -18
  256. package/src/components/FileUpload/FileUpload.tsx +10 -7
  257. package/src/components/FileUpload/index.tsx +1 -1
  258. package/src/components/Footer/Footer.test.tsx +33 -114
  259. package/src/components/Form/Form.test.tsx +388 -68
  260. package/src/components/Form/Form.tsx +57 -42
  261. package/src/components/Header/Header.test.tsx +645 -154
  262. package/src/components/Header/Header.tsx +52 -43
  263. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  264. package/src/components/Input/Input.test.tsx +34 -120
  265. package/src/components/Label/Label.test.tsx +47 -46
  266. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
  267. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  268. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
  269. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  270. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
  271. package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
  272. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
  273. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
  274. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  275. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
  276. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
  277. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
  278. package/src/components/PaceAppLayout/README.md +0 -9
  279. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  280. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
  281. package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
  282. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  283. package/src/components/Progress/Progress.test.tsx +127 -1
  284. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  285. package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
  286. package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
  287. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  288. package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
  289. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
  290. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  291. package/src/components/Select/Select.test.tsx +46 -9
  292. package/src/components/Select/Select.tsx +31 -24
  293. package/src/components/Select/__tests__/context.test.tsx +56 -0
  294. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
  295. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
  296. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
  297. package/src/components/Select/hooks/useSelectState.ts +16 -16
  298. package/src/components/Select/types.ts +3 -0
  299. package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
  300. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  301. package/src/components/Switch/Switch.test.tsx +57 -153
  302. package/src/components/Table/Table.test.tsx +47 -317
  303. package/src/components/Tabs/Tabs.tsx +3 -3
  304. package/src/components/Textarea/Textarea.test.tsx +11 -38
  305. package/src/components/Toast/Toast.test.tsx +78 -569
  306. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  307. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  308. package/src/components/UserMenu/UserMenu.tsx +3 -6
  309. package/src/components/__tests__/index.test.ts +346 -0
  310. package/src/components/index.ts +12 -1
  311. package/src/constants/__tests__/performance.test.ts +91 -0
  312. package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
  313. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
  314. package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
  315. package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
  316. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
  317. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
  318. package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
  319. package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
  320. package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
  321. package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
  322. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
  323. package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
  324. package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
  325. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
  326. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
  327. package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
  328. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
  329. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
  330. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
  331. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
  332. package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
  333. package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
  334. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
  335. package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
  336. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
  337. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
  338. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
  339. package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
  340. package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
  341. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
  342. package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
  343. package/src/hooks/__tests__/useToast.test.ts +413 -0
  344. package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
  345. package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
  346. package/src/hooks/index.ts +13 -1
  347. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  348. package/src/hooks/public/usePublicEvent.ts +11 -11
  349. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  350. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  351. package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
  352. package/src/hooks/public/usePublicFileDisplay.ts +79 -49
  353. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  354. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  355. package/src/hooks/services/useAuthService.ts +1 -1
  356. package/src/hooks/services/useEventService.ts +1 -1
  357. package/src/hooks/useAccessibleApps.test.ts +400 -0
  358. package/src/hooks/useAccessibleApps.ts +264 -0
  359. package/src/hooks/useAddressAutocomplete.test.ts +165 -42
  360. package/src/hooks/useAddressAutocomplete.ts +41 -28
  361. package/src/hooks/useAppConfig.ts +13 -3
  362. package/src/hooks/useDataTablePerformance.ts +13 -12
  363. package/src/hooks/useDataTableState.ts +5 -5
  364. package/src/hooks/useEventTheme.test.ts +66 -17
  365. package/src/hooks/useEventTheme.ts +1 -1
  366. package/src/hooks/useEvents.ts +8 -1
  367. package/src/hooks/useFileDisplay.ts +66 -33
  368. package/src/hooks/useFileReference.test.ts +365 -87
  369. package/src/hooks/useFileReference.ts +2 -6
  370. package/src/hooks/useFileUrlCache.ts +4 -1
  371. package/src/hooks/useFormDialog.ts +2 -2
  372. package/src/hooks/useInactivityTracker.ts +3 -3
  373. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  374. package/src/hooks/useOrganisationPermissions.ts +1 -4
  375. package/src/hooks/useOrganisationSecurity.test.ts +1 -30
  376. package/src/hooks/useOrganisationSecurity.ts +3 -3
  377. package/src/hooks/useOrganisations.ts +1 -1
  378. package/src/hooks/usePerformanceMonitor.ts +1 -1
  379. package/src/hooks/usePermissionCache.ts +2 -6
  380. package/src/hooks/useQueryCache.ts +7 -7
  381. package/src/hooks/useSessionDraft.ts +14 -11
  382. package/src/hooks/useSessionRestoration.ts +1 -1
  383. package/src/hooks/useStorage.ts +75 -40
  384. package/src/hooks/useToast.ts +2 -2
  385. package/src/hooks/useZodForm.ts +3 -3
  386. package/src/icons/__tests__/index.test.ts +133 -0
  387. package/src/icons/index.ts +1 -1
  388. package/src/index.ts +43 -4
  389. package/src/providers/OrganisationProvider.test.tsx +40 -0
  390. package/src/providers/OrganisationProvider.tsx +5 -5
  391. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  392. package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
  393. package/src/providers/__tests__/EventProvider.test.tsx +16 -80
  394. package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
  395. package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
  396. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
  397. package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
  398. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
  399. package/src/providers/__tests__/index.test.ts +138 -0
  400. package/src/providers/services/AuthServiceContext.ts +27 -0
  401. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  402. package/src/providers/services/EventServiceContext.ts +25 -0
  403. package/src/providers/services/EventServiceProvider.tsx +11 -20
  404. package/src/providers/services/InactivityServiceContext.ts +25 -0
  405. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  406. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  407. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  408. package/src/providers/services/UnifiedAuthContext.ts +99 -0
  409. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  410. package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
  411. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
  412. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
  413. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
  414. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
  415. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
  416. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
  417. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
  418. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
  419. package/src/providers/services/__tests__/contexts.test.tsx +281 -0
  420. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
  421. package/src/providers/services/useUnifiedAuth.ts +29 -0
  422. package/src/rbac/README.md +5 -5
  423. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
  424. package/src/rbac/__tests__/audit-batched.test.ts +550 -0
  425. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
  426. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
  427. package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
  428. package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
  429. package/src/rbac/__tests__/index.test.ts +107 -0
  430. package/src/rbac/__tests__/performance.test.ts +451 -0
  431. package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
  432. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
  433. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
  434. package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
  435. package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
  436. package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
  437. package/src/rbac/adapters.test.tsx +654 -0
  438. package/src/rbac/adapters.tsx +24 -9
  439. package/src/rbac/api.test.ts +13 -217
  440. package/src/rbac/api.ts +85 -16
  441. package/src/rbac/audit-batched.ts +5 -4
  442. package/src/rbac/audit.test.ts +225 -28
  443. package/src/rbac/audit.ts +22 -17
  444. package/src/rbac/cache-invalidation.ts +18 -15
  445. package/src/rbac/cache.test.ts +123 -63
  446. package/src/rbac/cache.ts +3 -4
  447. package/src/rbac/components/AccessDenied.tsx +20 -18
  448. package/src/rbac/components/NavigationGuard.tsx +10 -8
  449. package/src/rbac/components/PagePermissionGuard.tsx +27 -25
  450. package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
  451. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
  452. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
  453. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
  454. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
  455. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
  456. package/src/rbac/config.test.ts +131 -48
  457. package/src/rbac/config.ts +11 -8
  458. package/src/rbac/docs/event-based-apps.md +26 -13
  459. package/src/rbac/engine.test.ts +496 -146
  460. package/src/rbac/engine.ts +53 -13
  461. package/src/rbac/errors.test.ts +99 -87
  462. package/src/rbac/eslint-rules.js +2 -2
  463. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
  464. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
  465. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
  466. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
  467. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
  468. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
  469. package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
  470. package/src/rbac/hooks/permissions/useCan.ts +12 -10
  471. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
  472. package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
  473. package/src/rbac/hooks/useCan.test.ts +319 -3
  474. package/src/rbac/hooks/usePermissions.test.ts +426 -0
  475. package/src/rbac/hooks/usePermissions.ts +5 -7
  476. package/src/rbac/hooks/useRBAC.test.ts +1669 -2
  477. package/src/rbac/hooks/useRBAC.ts +7 -11
  478. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  479. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  480. package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
  481. package/src/rbac/hooks/useResourcePermissions.ts +9 -7
  482. package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
  483. package/src/rbac/hooks/useRoleManagement.ts +16 -12
  484. package/src/rbac/hooks/useSecureSupabase.ts +11 -12
  485. package/src/rbac/index.ts +32 -32
  486. package/src/rbac/permissions.test.ts +149 -68
  487. package/src/rbac/permissions.ts +0 -3
  488. package/src/rbac/request-deduplication.test.ts +347 -0
  489. package/src/rbac/secureClient.test.ts +112 -159
  490. package/src/rbac/secureClient.ts +46 -26
  491. package/src/rbac/security.test.ts +125 -44
  492. package/src/rbac/security.ts +7 -6
  493. package/src/rbac/types.test.ts +236 -0
  494. package/src/rbac/types.ts +7 -5
  495. package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
  496. package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
  497. package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
  498. package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
  499. package/src/rbac/utils/clientSecurity.ts +6 -4
  500. package/src/rbac/utils/contextValidator.ts +1 -2
  501. package/src/rbac/utils/eventContext.ts +2 -2
  502. package/src/services/AuthService.ts +13 -11
  503. package/src/services/EventService.ts +4 -5
  504. package/src/services/OrganisationService.ts +13 -30
  505. package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
  506. package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
  507. package/src/services/__tests__/AuthService.test.ts +4 -8
  508. package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
  509. package/src/services/__tests__/BaseService.test.ts +49 -0
  510. package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
  511. package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
  512. package/src/services/__tests__/EventService.test.ts +0 -7
  513. package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
  514. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
  515. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
  516. package/src/services/base/BaseService.test.ts +214 -0
  517. package/src/services/interfaces/IOrganisationService.ts +0 -1
  518. package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
  519. package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
  520. package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
  521. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
  522. package/src/styles/core.css +1 -0
  523. package/src/theming/__tests__/runtime.test.ts +29 -94
  524. package/src/theming/parseEventColours.ts +18 -9
  525. package/src/theming/runtime.ts +1 -5
  526. package/src/types/__tests__/core.test.ts +397 -0
  527. package/src/types/__tests__/database-generated.test.ts +78 -0
  528. package/src/types/__tests__/file-reference.test.ts +270 -366
  529. package/src/types/__tests__/guards.test.ts +26 -26
  530. package/src/types/__tests__/index.test.ts +265 -0
  531. package/src/types/__tests__/type-validation.test.ts +3 -3
  532. package/src/types/__tests__/validation.test.ts +0 -2
  533. package/src/types/auth.ts +0 -1
  534. package/src/types/database.generated.ts +9 -9
  535. package/src/types/event.ts +1 -1
  536. package/src/types/rpc-responses.ts +33 -0
  537. package/src/types/supabase.ts +1 -2
  538. package/src/types/vitest-globals.d.ts +1 -1
  539. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
  540. package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
  541. package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
  542. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
  543. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  544. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
  545. package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
  546. package/src/utils/__tests__/request-deduplication.test.ts +349 -0
  547. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
  548. package/src/utils/__tests__/timezone.test.ts +1 -1
  549. package/src/utils/__tests__/validation.unit.test.ts +1 -2
  550. package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
  551. package/src/utils/app/appConfig.test.ts +235 -0
  552. package/src/utils/app/appIdResolver.test.ts +188 -20
  553. package/src/utils/app/appNameResolver.test.ts +18 -10
  554. package/src/utils/app/appNameResolver.ts +11 -9
  555. package/src/utils/app/appPortMap.test.ts +125 -0
  556. package/src/utils/app/appPortMap.ts +51 -0
  557. package/src/utils/app/buildAppUrl.test.ts +273 -0
  558. package/src/utils/app/buildAppUrl.ts +114 -0
  559. package/src/utils/audit/audit.test.ts +354 -39
  560. package/src/utils/context/organisationContext.test.ts +10 -4
  561. package/src/utils/context/organisationContext.ts +5 -5
  562. package/src/utils/context/sessionTracking.test.ts +354 -0
  563. package/src/utils/core/__tests__/cn.test.ts +66 -0
  564. package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
  565. package/src/utils/core/__tests__/logger.test.ts +217 -0
  566. package/src/utils/core/debugLogger.ts +15 -8
  567. package/src/utils/core/logger.ts +20 -16
  568. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  569. package/src/utils/device/deviceFingerprint.ts +3 -3
  570. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
  571. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
  572. package/src/utils/dynamic/createLazyComponent.tsx +38 -0
  573. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  574. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  575. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  576. package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
  577. package/src/utils/file-reference/index.ts +0 -1
  578. package/src/utils/formatting/formatDate.test.ts +22 -148
  579. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  580. package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
  581. package/src/utils/formatting/formatNumber.test.ts +259 -0
  582. package/src/utils/formatting/formatTime.test.ts +36 -128
  583. package/src/utils/formatting/formatting.ts +1 -1
  584. package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
  585. package/src/utils/google-places/googlePlacesUtils.ts +15 -2
  586. package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
  587. package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
  588. package/src/utils/index.ts +52 -11
  589. package/src/utils/location/location.test.ts +18 -115
  590. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
  591. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
  592. package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
  593. package/src/utils/performance/bundleAnalysis.ts +16 -22
  594. package/src/utils/performance/performanceBenchmark.ts +12 -4
  595. package/src/utils/performance/performanceBudgets.ts +9 -6
  596. package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
  597. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  598. package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
  599. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
  600. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  601. package/src/utils/request-deduplication.ts +6 -4
  602. package/src/utils/security/auth-utils.ts +7 -7
  603. package/src/utils/security/secureDataAccess.test.ts +22 -191
  604. package/src/utils/security/secureErrors.test.ts +163 -0
  605. package/src/utils/security/secureStorage.test.ts +156 -0
  606. package/src/utils/security/secureStorage.ts +1 -1
  607. package/src/utils/security/security.test.ts +204 -0
  608. package/src/utils/security/securityMonitor.test.ts +90 -0
  609. package/src/utils/security/securityMonitor.ts +1 -1
  610. package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
  611. package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
  612. package/src/utils/storage/helpers.test.ts +757 -430
  613. package/src/utils/storage/helpers.ts +1 -2
  614. package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
  615. package/src/utils/storage/types.ts +2 -2
  616. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  617. package/src/utils/supabase/createBaseClient.ts +27 -8
  618. package/src/utils/timezone/timezone.test.ts +25 -43
  619. package/src/utils/validation/__tests__/common.test.ts +115 -0
  620. package/src/utils/validation/__tests__/csrf.test.ts +65 -0
  621. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
  622. package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
  623. package/src/utils/validation/__tests__/schema.test.ts +127 -0
  624. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
  625. package/src/utils/validation/__tests__/user.test.ts +173 -0
  626. package/src/utils/validation/__tests__/validation.test.ts +197 -0
  627. package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
  628. package/src/utils/validation/htmlSanitization.ts +27 -31
  629. package/src/utils/validation/schema.ts +6 -3
  630. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  631. package/src/vite-env.d.ts +6 -0
  632. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  633. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  634. package/dist/audit-MYQXYZFU.js +0 -3
  635. package/dist/chunk-7ILTDCL2.js +0 -80
  636. package/dist/chunk-EF2UGZWY.js +0 -611
  637. package/dist/chunk-FEJLJNWA.js +0 -181
  638. package/dist/chunk-GS5672WG.js +0 -2003
  639. package/dist/chunk-S6ZQKDY6.js +0 -62
  640. package/dist/chunk-Z2FNRKF3.js +0 -994
  641. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  642. package/src/components/DataTable/components/index.ts +0 -16
  643. package/src/components/DataTable/core/index.ts +0 -1
  644. package/src/components/DataTable/hooks/index.ts +0 -13
  645. package/src/components/DataTable/utils/index.ts +0 -9
  646. package/src/components/PublicLayout/index.ts +0 -32
  647. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  648. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  649. package/src/hooks/public/index.ts +0 -36
  650. package/src/hooks/usePermissionCache.test.ts +0 -536
  651. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  652. package/src/rbac/audit-enhanced.ts +0 -384
  653. package/src/rbac/compliance/database-validator.ts +0 -165
  654. package/src/rbac/compliance/index.ts +0 -48
  655. package/src/rbac/compliance/pattern-detector.ts +0 -553
  656. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  657. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  658. package/src/rbac/compliance/setup-validator.ts +0 -131
  659. package/src/rbac/components/index.ts +0 -26
  660. package/src/rbac/hooks/index.ts +0 -34
  661. package/src/rbac/hooks/permissions/index.ts +0 -4
  662. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  663. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  664. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  665. package/src/utils/google-places/index.ts +0 -26
  666. package/src/utils/location/index.ts +0 -16
  667. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  668. package/src/utils/timezone/index.ts +0 -17
  669. package/src/utils/validation/index.ts +0 -73
@@ -59,36 +59,10 @@ import * as React from 'react';
59
59
  import {
60
60
  DayPicker,
61
61
  type DayPickerProps,
62
- useDayPicker,
63
- type DayProps,
64
- type MonthsProps,
65
62
  type DateRange,
66
63
  } from 'react-day-picker';
67
64
  import { enAU } from 'date-fns/locale';
68
- import { format } from 'date-fns';
69
65
  import { cn } from '../../utils/core/cn';
70
- import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../Select';
71
-
72
- // Define custom types for components that don't have exported types
73
- type MonthGridProps = React.TableHTMLAttributes<HTMLTableElement>;
74
- type WeekdaysProps = React.HTMLAttributes<HTMLTableRowElement> & {
75
- children?: React.ReactNode;
76
- };
77
- type MonthProps = {
78
- calendarMonth: { date: Date };
79
- displayIndex: number;
80
- className?: string;
81
- children?: React.ReactNode;
82
- captionLayout?: DayPickerProps['captionLayout'];
83
- startMonth?: Date;
84
- endMonth?: Date;
85
- };
86
- type RootProps = {
87
- children?: React.ReactNode;
88
- rootRef?: React.Ref<HTMLDivElement>;
89
- className?: string;
90
- style?: React.CSSProperties;
91
- };
92
66
 
93
67
  // ============================================================================
94
68
  // CALENDAR COMPONENT
@@ -121,23 +95,6 @@ export interface CalendarProps extends Omit<DayPickerProps, 'className' | 'class
121
95
  onSelect?: ((date: Date | undefined) => void) | ((range: { from: Date; to?: Date } | undefined) => void) | ((dates: Date[]) => void);
122
96
  }
123
97
 
124
- type StoredRootProps = {
125
- className?: string;
126
- style?: React.CSSProperties;
127
- rootRef?: React.Ref<HTMLDivElement>;
128
- restProps?: React.HTMLAttributes<HTMLTableElement>;
129
- };
130
-
131
- const assignToRef = <T,>(ref: React.Ref<T | null> | undefined, value: T | null) => {
132
- if (!ref) {
133
- return;
134
- }
135
- if (typeof ref === 'function') {
136
- ref(value);
137
- return;
138
- }
139
- (ref as React.MutableRefObject<T | null>).current = value;
140
- };
141
98
 
142
99
  /**
143
100
  * Calendar component
@@ -196,35 +153,71 @@ const assignToRef = <T,>(ref: React.Ref<T | null> | undefined, value: T | null)
196
153
  */
197
154
  const Calendar = React.forwardRef<HTMLTableElement, CalendarProps>(
198
155
  ({ className, classNames, mode, components, locale, month: controlledMonth, onMonthChange: controlledOnMonthChange, onSelect, captionLayout, startMonth, endMonth, ...props }, ref) => {
199
- const tableRef = React.useRef<HTMLTableElement | null>(null);
200
- const setForwardedRef = React.useCallback(
201
- (node: HTMLTableElement | null) => {
202
- tableRef.current = node;
203
- if (!ref) {
204
- return;
205
- }
206
- if (typeof ref === 'function') {
207
- ref(node);
208
- } else {
209
- (ref as React.MutableRefObject<HTMLTableElement | null>).current = node;
156
+ // Ref callback to forward ref to the table element rendered by DayPicker
157
+ const dayPickerRef = React.useRef<HTMLDivElement>(null);
158
+
159
+ // Forward ref to the table element within DayPicker's rendered output
160
+ React.useEffect(() => {
161
+ if (ref && dayPickerRef.current) {
162
+ const tableElement = dayPickerRef.current.querySelector('table') as HTMLTableElement | null;
163
+ if (tableElement && typeof ref === 'function') {
164
+ ref(tableElement);
165
+ } else if (tableElement && ref && 'current' in ref) {
166
+ (ref as React.MutableRefObject<HTMLTableElement | null>).current = tableElement;
210
167
  }
211
- },
212
- [ref]
213
- );
168
+ }
169
+ }, [ref]);
214
170
 
215
- // Store root props so we can re-apply them to the table element
216
- const rootPropsRef = React.useRef<StoredRootProps | null>(null);
217
171
  // Get selected from props to avoid TypeScript union type issues
218
- const selected = (props as any).selected;
172
+ const selected = (props as CalendarProps).selected;
219
173
  // Determine if we're in controlled or uncontrolled mode for month
220
174
  const isMonthControlled = controlledMonth !== undefined;
221
175
 
222
- // Internal state for uncontrolled month mode - always default to current month
176
+ // Internal state for uncontrolled month mode
177
+ // Initialize to selected date's month if available, otherwise current month
223
178
  const [internalMonth, setInternalMonth] = React.useState<Date>(() => {
179
+ if (selected) {
180
+ if (selected instanceof Date) {
181
+ return new Date(selected.getFullYear(), selected.getMonth(), 1);
182
+ }
183
+ // Handle DateRange
184
+ if (typeof selected === 'object' && 'from' in selected && selected.from) {
185
+ return new Date(selected.from.getFullYear(), selected.from.getMonth(), 1);
186
+ }
187
+ // Handle Date[]
188
+ if (Array.isArray(selected) && selected.length > 0 && selected[0] instanceof Date) {
189
+ return new Date(selected[0].getFullYear(), selected[0].getMonth(), 1);
190
+ }
191
+ }
224
192
  const now = new Date();
225
193
  return new Date(now.getFullYear(), now.getMonth(), 1);
226
194
  });
227
195
 
196
+ // Sync internal month to selected date when selected changes (only in uncontrolled mode)
197
+ React.useEffect(() => {
198
+ if (!isMonthControlled && selected) {
199
+ let monthToSync: Date | null = null;
200
+ if (selected instanceof Date) {
201
+ monthToSync = new Date(selected.getFullYear(), selected.getMonth(), 1);
202
+ } else if (typeof selected === 'object' && 'from' in selected && selected.from) {
203
+ monthToSync = new Date(selected.from.getFullYear(), selected.from.getMonth(), 1);
204
+ } else if (Array.isArray(selected) && selected.length > 0 && selected[0] instanceof Date) {
205
+ monthToSync = new Date(selected[0].getFullYear(), selected[0].getMonth(), 1);
206
+ }
207
+
208
+ if (monthToSync) {
209
+ setInternalMonth(prevMonth => {
210
+ const currentMonth = new Date(prevMonth.getFullYear(), prevMonth.getMonth(), 1);
211
+ // Only update if the month is different to avoid unnecessary re-renders
212
+ if (monthToSync!.getTime() !== currentMonth.getTime()) {
213
+ return monthToSync!;
214
+ }
215
+ return prevMonth;
216
+ });
217
+ }
218
+ }
219
+ }, [selected, isMonthControlled]);
220
+
228
221
  // Use controlled month if provided, otherwise use internal state
229
222
  // Normalize month to first day of month to ensure consistency
230
223
  const month = React.useMemo(() => {
@@ -245,436 +238,62 @@ const Calendar = React.forwardRef<HTMLTableElement, CalendarProps>(
245
238
  }
246
239
  controlledOnMonthChange?.(newMonth);
247
240
  }, [isMonthControlled, controlledOnMonthChange]);
248
-
249
- // Create a wrapped handler to ensure it's always a function
250
- const wrappedHandleMonthChange = React.useCallback((newMonth: Date) => {
251
- handleMonthChange(newMonth);
252
- }, [handleMonthChange]);
253
-
254
- // Removed mount logging - was for debugging only
255
-
256
- // Custom Root: capture provided props so we can attach them to the table directly
257
- const CustomRoot = React.memo(({ children, rootRef: dayPickerRootRef, ...rootProps }: RootProps) => {
258
- const {
259
- className: rootClassName,
260
- style: rootStyle,
261
- children: _ignoredChildren,
262
- ...restProps
263
- } = rootProps as React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode };
264
-
265
- rootPropsRef.current = {
266
- className: rootClassName,
267
- style: rootStyle as React.CSSProperties | undefined,
268
- rootRef: dayPickerRootRef,
269
- restProps: restProps as React.HTMLAttributes<HTMLTableElement>,
270
- };
271
- return <>{children}</>;
272
- });
273
- CustomRoot.displayName = 'CustomRoot';
274
-
275
- // Custom Months: Remove wrapper div, filter out MonthCaption and Dropdown when dropdown layout is used
276
- const CustomMonths = React.memo(({ children }: MonthsProps) => {
277
- // When captionLayout="dropdown", react-day-picker may render MonthCaption or Dropdown components
278
- // Filter them out since we render our own dropdowns inside the table's <caption> element
279
- const childrenArray = React.Children.toArray(children);
280
- const filteredChildren = childrenArray.filter((child: any) => {
281
- if (!React.isValidElement(child)) return true;
282
- const childType = child.type as any;
283
- const displayName = childType?.displayName || childType?.name;
284
- // Filter out MonthCaption and any Dropdown-related components
285
- if (displayName === 'MonthCaption' ||
286
- displayName === 'Dropdown' ||
287
- displayName === 'DropdownMonth' ||
288
- displayName === 'DropdownYear' ||
289
- (typeof childType === 'string' && childType.includes('dropdown'))) {
290
- return false;
291
- }
292
- // Also check for the div wrapper that react-day-picker might render
293
- if (childType === 'div') {
294
- const childProps = child.props as { children?: React.ReactNode; [key: string]: unknown };
295
- if (childProps?.children) {
296
- const childChildren = React.Children.toArray(childProps.children);
297
- // If it contains a span with role="status" and aria-live="polite", it's likely the default caption
298
- const hasCaptionSpan = childChildren.some((cc: any) => {
299
- if (!React.isValidElement(cc) || cc.type !== 'span') return false;
300
- const spanProps = cc.props as { role?: string; 'aria-live'?: string; [key: string]: unknown };
301
- return spanProps?.role === 'status' && spanProps?.['aria-live'] === 'polite';
302
- });
303
- if (hasCaptionSpan) {
304
- return false;
305
- }
306
- }
307
- }
308
- return true;
309
- });
310
- return <>{filteredChildren}</>;
311
- });
312
- CustomMonths.displayName = 'CustomMonths';
313
-
314
- const CustomMonthGrid = React.forwardRef<HTMLTableElement, MonthGridProps>((props, forwardedRef) => {
315
- return <table ref={forwardedRef} {...props} />;
316
- });
317
- CustomMonthGrid.displayName = 'CustomMonthGrid';
318
-
319
- // Custom MonthCaption: renders dropdowns for month/year selection
320
- type MonthCaptionProps = {
321
- displayMonth: Date;
322
- startMonth?: Date;
323
- endMonth?: Date;
324
- locale?: DayPickerProps['locale'];
325
- };
326
- const CustomMonthCaption = React.memo(({ displayMonth, startMonth: captionStartMonth, endMonth: captionEndMonth, locale: captionLocale }: MonthCaptionProps) => {
327
- const { goToMonth } = useDayPicker();
328
- // Get locale from props (defaults to enAU)
329
- const calendarLocale = (captionLocale || enAU) as typeof enAU;
330
-
331
- // Get start and end months from props (passed via Calendar)
332
- const fromDate = captionStartMonth || new Date(1900, 0);
333
- const toDate = captionEndMonth || new Date(2100, 11);
334
-
335
- // Generate month options using date-fns format
336
- const monthOptions = React.useMemo(() => {
337
- const months: { value: string; label: string }[] = [];
338
- for (let i = 0; i < 12; i++) {
339
- const monthDate = new Date(displayMonth.getFullYear(), i, 1);
340
- const label = format(monthDate, 'MMMM', { locale: calendarLocale });
341
- months.push({ value: i.toString(), label });
342
- }
343
- return months;
344
- }, [calendarLocale, displayMonth]);
345
-
346
- // Generate year options based on startMonth and endMonth
347
- const yearOptions = React.useMemo(() => {
348
- const years: { value: string; label: string }[] = [];
349
- const startYear = fromDate.getFullYear();
350
- const endYear = toDate.getFullYear();
351
- for (let year = startYear; year <= endYear; year++) {
352
- years.push({ value: year.toString(), label: year.toString() });
353
- }
354
- return years;
355
- }, [fromDate, toDate]);
356
-
357
- const currentMonth = displayMonth.getMonth();
358
- const currentYear = displayMonth.getFullYear();
359
-
360
- const handleMonthChange = React.useCallback((value: string) => {
361
- const newMonth = parseInt(value, 10);
362
- const newDate = new Date(currentYear, newMonth, 1);
363
- goToMonth(newDate);
364
- }, [currentYear, goToMonth]);
365
-
366
- const handleYearChange = React.useCallback((value: string) => {
367
- const newYear = parseInt(value, 10);
368
- const newDate = new Date(newYear, currentMonth, 1);
369
- goToMonth(newDate);
370
- }, [currentMonth, goToMonth]);
371
-
372
- return (
373
- <nav className="relative flex items-center justify-center gap-2">
374
- <Select value={currentMonth.toString()} onValueChange={handleMonthChange}>
375
- <SelectTrigger className="w-auto min-w-[120px]">
376
- <SelectValue />
377
- </SelectTrigger>
378
- <SelectContent>
379
- {monthOptions.map((option) => (
380
- <SelectItem key={option.value} value={option.value}>
381
- {option.label}
382
- </SelectItem>
383
- ))}
384
- </SelectContent>
385
- </Select>
386
- <Select value={currentYear.toString()} onValueChange={handleYearChange}>
387
- <SelectTrigger className="w-auto min-w-[100px]">
388
- <SelectValue />
389
- </SelectTrigger>
390
- <SelectContent>
391
- {yearOptions.map((option) => (
392
- <SelectItem key={option.value} value={option.value}>
393
- {option.label}
394
- </SelectItem>
395
- ))}
396
- </SelectContent>
397
- </Select>
398
- </nav>
399
- );
400
- });
401
- CustomMonthCaption.displayName = 'CustomMonthCaption';
402
241
 
403
- // Custom Month: inject caption + navigation directly inside the <table>
404
- const CustomMonth = React.memo(({ calendarMonth, displayIndex, className, children, captionLayout: monthCaptionLayout, startMonth: monthStartMonth, endMonth: monthEndMonth }: MonthProps) => {
405
- const { formatters, components, labels, classNames, previousMonth, nextMonth, goToMonth } = useDayPicker();
406
- const caption = formatters.formatCaption(calendarMonth.date, {});
407
- const Chevron = components?.Chevron;
408
-
409
- const childrenArray = React.Children.toArray(children);
410
- const monthGridIndex = childrenArray.findIndex((child: any) => {
411
- if (!React.isValidElement(child)) return false;
412
- const childType = child.type as any;
413
- return (typeof childType === 'function' && childType.displayName === 'MonthGrid') ||
414
- child.type === 'table';
415
- });
416
-
417
- return (
418
- <>
419
- {childrenArray.map((child, index) => {
420
- if (React.isValidElement(child) && (child.type as any)?.displayName === 'MonthCaption') {
421
- return null;
422
- }
423
-
424
- if (index === monthGridIndex && React.isValidElement(child)) {
425
- const monthGridChild = child as React.ReactElement<MonthGridProps>;
426
- const applyRootProps = displayIndex === 0 && index === monthGridIndex;
427
- const storedRootProps = applyRootProps ? rootPropsRef.current : null;
428
-
429
- const { children: monthGridChildren, className: monthGridClassName, style: monthGridStyle, ...monthGridRest } =
430
- monthGridChild.props as React.TableHTMLAttributes<HTMLTableElement>;
431
-
432
- const mergedClassName = cn(
433
- 'w-full border-collapse rounded-md border border-sec-200 bg-background',
434
- applyRootProps ? storedRootProps?.className : undefined,
435
- className,
436
- monthGridClassName
437
- );
438
-
439
- const mergedStyle = {
440
- ...(applyRootProps ? storedRootProps?.style ?? {} : {}),
441
- ...(monthGridStyle ?? {}),
442
- };
443
-
444
- const tableProps: React.TableHTMLAttributes<HTMLTableElement> = {
445
- ...(applyRootProps && storedRootProps?.restProps ? storedRootProps.restProps : {}),
446
- ...monthGridRest,
447
- className: mergedClassName,
448
- ...(Object.keys(mergedStyle).length ? { style: mergedStyle } : {}),
449
- };
450
-
451
- if (mode && (tableProps as Record<string, unknown>)['data-mode'] === undefined) {
452
- (tableProps as Record<string, unknown>)['data-mode'] = mode;
453
- }
454
-
455
- const shouldAttachRef = applyRootProps || storedRootProps?.rootRef;
456
- const handleTableRef = shouldAttachRef
457
- ? (node: HTMLTableElement | null) => {
458
- if (applyRootProps) {
459
- setForwardedRef(node);
460
- }
461
- if (storedRootProps?.rootRef) {
462
- assignToRef(storedRootProps.rootRef as React.Ref<HTMLTableElement | null>, node);
463
- }
464
- }
465
- : undefined;
466
-
467
- const handlePreviousClick = (event: React.MouseEvent<HTMLButtonElement>) => {
468
- event.preventDefault();
469
- if (!previousMonth) return;
470
- goToMonth(previousMonth);
471
- };
472
-
473
- const handleNextClick = (event: React.MouseEvent<HTMLButtonElement>) => {
474
- event.preventDefault();
475
- if (!nextMonth) return;
476
- goToMonth(nextMonth);
477
- };
478
-
479
- const monthGridElement = monthGridChild as React.ReactElement<any> & {
480
- ref?: React.Ref<HTMLTableElement | null>;
481
- };
482
- const mergedRef =
483
- handleTableRef || monthGridElement.ref
484
- ? (node: HTMLTableElement | null) => {
485
- if (handleTableRef) {
486
- handleTableRef(node);
487
- }
488
- assignToRef(monthGridElement.ref as React.Ref<HTMLTableElement | null> | undefined, node);
489
- }
490
- : undefined;
491
-
492
- // Determine if we should render dropdowns or buttons
493
- const isDropdownLayout = monthCaptionLayout === 'dropdown';
494
-
495
- return React.cloneElement(
496
- monthGridElement,
497
- {
498
- key: child.key ?? `month-grid-${displayIndex}`,
499
- ...tableProps,
500
- ...(mergedRef ? { ref: mergedRef } : {}),
501
- },
502
- <>
503
- <caption className="relative">
504
- {isDropdownLayout ? (
505
- <CustomMonthCaption
506
- displayMonth={calendarMonth.date}
507
- startMonth={monthStartMonth}
508
- endMonth={monthEndMonth}
509
- locale={locale}
510
- />
511
- ) : (
512
- <nav className="relative flex items-center justify-center gap-1">
513
- <button
514
- type="button"
515
- className={cn(
516
- 'h-7 w-7 bg-transparent p-0',
517
- 'inline-flex items-center justify-center rounded-md',
518
- 'hover:bg-acc-100',
519
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2',
520
- 'disabled:opacity-50 disabled:pointer-events-none',
521
- classNames?.button_previous
522
- )}
523
- tabIndex={previousMonth ? undefined : -1}
524
- aria-disabled={previousMonth ? undefined : true}
525
- aria-label={previousMonth ? labels.labelPrevious(previousMonth) : undefined}
526
- onClick={handlePreviousClick}
527
- disabled={!previousMonth}
528
- >
529
- {Chevron ? <Chevron orientation="left" className="size-4" disabled={!previousMonth} /> : <span>‹</span>}
530
- </button>
531
- <span className="text-sm font-medium">{caption}</span>
532
- <button
533
- type="button"
534
- className={cn(
535
- 'h-7 w-7 bg-transparent p-0',
536
- 'inline-flex items-center justify-center rounded-md',
537
- 'hover:bg-acc-100',
538
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2',
539
- 'disabled:opacity-50 disabled:pointer-events-none',
540
- classNames?.button_next
541
- )}
542
- tabIndex={nextMonth ? undefined : -1}
543
- aria-disabled={nextMonth ? undefined : true}
544
- aria-label={nextMonth ? labels.labelNext(nextMonth) : undefined}
545
- onClick={handleNextClick}
546
- disabled={!nextMonth}
547
- >
548
- {Chevron ? <Chevron orientation="right" className="size-4" disabled={!nextMonth} /> : <span>›</span>}
549
- </button>
550
- </nav>
551
- )}
552
- </caption>
553
- {monthGridChildren}
554
- </>
555
- );
556
- }
557
-
558
- return React.isValidElement(child)
559
- ? React.cloneElement(child, { key: child.key ?? `calendar-child-${index}` })
560
- : child;
561
- })}
562
- </>
563
- );
564
- });
565
- CustomMonth.displayName = 'CustomMonth';
566
-
567
- // Custom Weekdays: render table head with semantic row
568
- const CustomWeekdays = React.memo(({ className, children, ...props }: WeekdaysProps) => {
569
- return (
570
- <thead>
571
- <tr className={cn('text-xs text-sec-500', className)} {...props}>
572
- {children}
573
- </tr>
574
- </thead>
575
- );
576
- });
577
- CustomWeekdays.displayName = 'CustomWeekdays';
578
-
579
- // Create a wrapper for CustomMonth that passes the required props
580
- const CustomMonthWithProps = React.useCallback((props: MonthProps) => {
581
- return (
582
- <CustomMonth
583
- {...props}
584
- captionLayout={captionLayout}
585
- startMonth={startMonth}
586
- endMonth={endMonth}
587
- />
588
- );
589
- }, [captionLayout, startMonth, endMonth]);
590
-
591
- // Custom MonthCaption wrapper: returns null to prevent default rendering
592
- // The actual caption is rendered inside CustomMonth within the table's <caption> element
593
- const CustomMonthCaptionWrapper = React.memo((_props: any) => {
594
- return null;
595
- });
596
- CustomMonthCaptionWrapper.displayName = 'CustomMonthCaptionWrapper';
597
-
598
- // Memoize components to ensure stable references
599
- const defaultComponents = React.useMemo(() => ({
600
- Root: CustomRoot,
601
- Months: CustomMonths,
602
- Month: CustomMonthWithProps,
603
- MonthGrid: CustomMonthGrid,
604
- // MonthCaption returns null - actual caption is rendered in CustomMonth inside <caption>
605
- MonthCaption: CustomMonthCaptionWrapper,
606
- Weekdays: CustomWeekdays,
607
- // Spread user components AFTER ours so ours take precedence
608
- ...(components || {}),
609
- }), [components, CustomRoot, CustomMonths, CustomMonthWithProps, CustomMonthCaptionWrapper, CustomWeekdays]);
242
+ // Type assertion needed because CalendarProps extends DayPickerProps with union types
243
+ // that don't perfectly match DayPicker's conditional types based on mode
244
+ // Extract captionLayout, startMonth, endMonth from props to ensure they're passed correctly
245
+ const {
246
+ captionLayout: _captionLayoutFromProps,
247
+ startMonth: _startMonthFromProps,
248
+ endMonth: _endMonthFromProps,
249
+ ...restProps
250
+ } = props as CalendarProps;
251
+
252
+ const dayPickerProps = {
253
+ ...(mode ? { mode } : {}),
254
+ locale: locale ?? enAU,
255
+ // Explicitly pass captionLayout, startMonth, endMonth to ensure they're not overridden
256
+ ...(captionLayout !== undefined ? { captionLayout } : {}),
257
+ ...(startMonth !== undefined ? { startMonth } : {}),
258
+ ...(endMonth !== undefined ? { endMonth } : {}),
259
+ ...(restProps as Omit<DayPickerProps, 'selected' | 'onSelect' | 'month' | 'onMonthChange' | 'className' | 'classNames' | 'components' | 'captionLayout' | 'startMonth' | 'endMonth'>),
260
+ ...(selected !== undefined ? { selected } : {}),
261
+ ...(onSelect !== undefined ? { onSelect } : {}),
262
+ month,
263
+ onMonthChange: handleMonthChange,
264
+ className,
265
+ classNames: {
266
+ // Basic spacing for calendar grid
267
+ month_grid: 'w-full border-collapse',
268
+ weekdays: 'text-xs text-sec-500',
269
+ weekday: 'w-9 p-0 font-normal text-center',
270
+ week: 'mt-2',
271
+ day: 'p-0 text-center',
272
+ day_button: cn(
273
+ 'h-9 w-9 p-0 font-normal',
274
+ 'hover:bg-acc-100 hover:text-main-600',
275
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2',
276
+ 'inline-flex items-center justify-center rounded-md'
277
+ ),
278
+ selected: 'bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50',
279
+ today: 'bg-sec-100 text-main-600 font-semibold',
280
+ disabled: 'text-sec-400 opacity-50 cursor-not-allowed',
281
+ // Caption and dropdown layout styling
282
+ month_caption: 'flex items-center justify-center gap-2 mb-2',
283
+ caption_label: captionLayout === 'dropdown' ? 'hidden' : 'text-sm font-medium', // Hide label when using dropdowns
284
+ dropdowns: 'flex items-center gap-2',
285
+ months_dropdown: 'px-2 py-1 text-sm border border-sec-300 rounded bg-background',
286
+ years_dropdown: 'px-2 py-1 text-sm border border-sec-300 rounded bg-background',
287
+ chevron: 'hidden', // Hide extra chevron icons
288
+ ...classNames,
289
+ },
290
+ ...(components ? { components } : {}),
291
+ } as DayPickerProps;
610
292
 
611
293
  return (
612
- <DayPicker
613
- {...(mode ? { mode } : {})}
614
- locale={locale ?? enAU}
615
- hideNavigation={true}
616
- {...(props as any)}
617
- // CRITICAL: Explicit props must come AFTER spread to ensure they override any props from spread
618
- // This ensures month, onMonthChange, selected, and onSelect are always correct
619
- selected={selected}
620
- onSelect={onSelect}
621
- month={month}
622
- onMonthChange={wrappedHandleMonthChange}
623
- className={className}
624
- classNames={{
625
- // v9 API: Updated for table-based structure
626
- months: '', // No wrapper - removed by CustomMonths
627
- month: '', // No wrapper - removed by CustomMonth
628
- month_caption: '', // Now handled by custom component (renders as <caption>)
629
- caption_label: 'text-sm font-medium',
630
- nav: 'relative flex items-center justify-center space-x-1',
631
- // v9: button_previous and button_next for navigation buttons
632
- button_previous: cn(
633
- 'absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
634
- 'border border-input hover:bg-acc-100',
635
- 'inline-flex items-center justify-center rounded-md',
636
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2'
637
- ),
638
- button_next: cn(
639
- 'absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
640
- 'border border-input hover:bg-acc-100',
641
- 'inline-flex items-center justify-center rounded-md',
642
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2'
643
- ),
644
- // v9: table -> month_grid (now a proper <table>)
645
- month_grid: '', // Styles applied directly to table in CustomMonth
646
- // v9: head_row -> weekdays (now wrapped in <thead> by custom component)
647
- weekdays: '', // Styles applied to <tr> inside <thead>
648
- weekday: 'text-sec-600 rounded-md w-9 font-normal text-[0.8rem]',
649
- // v9: row -> week (now a proper <tr>)
650
- week: 'mt-2',
651
- // v9: cell -> day (now a proper <td> by custom component)
652
- day: '', // Styles moved to <td> in custom component
653
- // v9: day -> day_button (the button inside the cell)
654
- day_button: cn(
655
- 'h-9 w-9 p-0 font-normal aria-selected:opacity-100',
656
- 'hover:bg-acc-100 hover:text-main-600',
657
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2',
658
- 'inline-flex items-center justify-center rounded-md'
659
- ),
660
- // v9: day_range_end -> range_end
661
- range_end: 'range-end',
662
- // v9: day_selected -> selected
663
- selected: 'bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50 focus:bg-main-600 focus:text-main-50',
664
- // v9: day_today -> today
665
- today: 'bg-sec-100 text-main-600 font-semibold',
666
- // v9: day_outside -> outside
667
- outside: 'outside text-sec-400 opacity-50 aria-selected:bg-acc-50/50 aria-selected:text-sec-400 aria-selected:opacity-30',
668
- // v9: day_disabled -> disabled
669
- disabled: 'text-sec-400 opacity-50 cursor-not-allowed',
670
- // v9: day_range_middle -> range_middle
671
- range_middle: 'aria-selected:bg-acc-100 aria-selected:text-main-600',
672
- // v9: day_hidden -> hidden
673
- hidden: 'invisible',
674
- ...classNames,
675
- }}
676
- components={defaultComponents}
677
- />
294
+ <div ref={dayPickerRef}>
295
+ <DayPicker {...dayPickerProps} />
296
+ </div>
678
297
  );
679
298
  }
680
299
  );