@jmruthers/pace-core 0.6.9 → 0.6.11

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 (1182) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/audit-tool/00-dependencies.cjs +46 -13
  3. package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
  4. package/audit-tool/audits/02-project-structure.cjs +74 -2
  5. package/audit-tool/audits/03-architecture.cjs +220 -20
  6. package/audit-tool/audits/04-code-quality.cjs +95 -3
  7. package/audit-tool/audits/05-styling.cjs +19 -7
  8. package/audit-tool/audits/06-security-rbac.cjs +214 -25
  9. package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
  10. package/audit-tool/audits/08-testing-documentation.cjs +11 -3
  11. package/audit-tool/audits/09-operations.cjs +19 -7
  12. package/audit-tool/index.cjs +22 -11
  13. package/audit-tool/utils/report-utils.cjs +4 -0
  14. package/cursor-rules/01-pace-core-compliance.mdc +1 -0
  15. package/cursor-rules/02-project-structure.mdc +3 -26
  16. package/cursor-rules/03-architecture.mdc +3 -1
  17. package/cursor-rules/04-code-quality.mdc +1 -0
  18. package/cursor-rules/05-styling.mdc +120 -8
  19. package/cursor-rules/06-security-rbac.mdc +126 -2
  20. package/cursor-rules/07-api-tech-stack.mdc +1 -0
  21. package/cursor-rules/08-testing-documentation.mdc +1 -0
  22. package/cursor-rules/09-operations.mdc +1 -0
  23. package/dist/DataTable-EFYP2QLE.js +16 -0
  24. package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
  25. package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
  26. package/dist/api-BZR2CYXL.js +5 -0
  27. package/dist/api-result-USV1Czr-.d.ts +51 -0
  28. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  29. package/dist/assets/app-icons/base_favicon.svg +85 -0
  30. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  31. package/dist/assets/app-icons/core_favicon.svg +256 -0
  32. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  33. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  34. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  35. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  36. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  37. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  38. package/dist/assets/app-icons/team_favicon.svg +67 -0
  39. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  40. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  41. package/dist/audit-HI2DHUVU.js +4 -0
  42. package/dist/auth-JvdRVaud.d.ts +49 -0
  43. package/dist/chunk-2DL2WSOE.js +327 -0
  44. package/dist/chunk-2OEVOGGR.js +9598 -0
  45. package/dist/chunk-44CNXN4P.js +15 -0
  46. package/dist/chunk-4R3T5ENU.js +2943 -0
  47. package/dist/chunk-7A6IMHH2.js +2321 -0
  48. package/dist/chunk-BTHN5MKC.js +121 -0
  49. package/dist/chunk-CU2BU2MQ.js +2 -0
  50. package/dist/chunk-D6BMFMQZ.js +200 -0
  51. package/dist/chunk-DDMPHZ3D.js +58 -0
  52. package/dist/chunk-ENLXB7GP.js +721 -0
  53. package/dist/chunk-J2KQK6DG.js +2159 -0
  54. package/dist/chunk-KJXRL3XE.js +6434 -0
  55. package/dist/chunk-L5LFKKLJ.js +61 -0
  56. package/dist/chunk-PCSHBLPB.js +811 -0
  57. package/dist/chunk-QRYSEPHB.js +429 -0
  58. package/dist/chunk-RMLY6KB5.js +187 -0
  59. package/dist/chunk-SACF5YSM.js +31 -0
  60. package/dist/chunk-UZNAFKGW.js +125 -0
  61. package/dist/chunk-V7FTM2LU.js +1080 -0
  62. package/dist/chunk-WY6Y7KC3.js +264 -0
  63. package/dist/chunk-XOJME5T7.js +407 -0
  64. package/dist/chunk-XPFVT3GN.js +492 -0
  65. package/dist/chunk-YFTFFJIV.js +529 -0
  66. package/dist/chunk-YYTWKVHO.js +1334 -0
  67. package/dist/components.d.ts +12 -89
  68. package/dist/components.js +23 -55
  69. package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
  70. package/dist/eslint-rules/index.cjs +3 -0
  71. package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
  72. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  73. package/dist/eslint-rules/rules/06-security-rbac.cjs +84 -0
  74. package/dist/event-BfCox3N2.d.ts +265 -0
  75. package/dist/file-reference-DU1hcawx.d.ts +164 -0
  76. package/dist/functions-DH45k8ec.d.ts +208 -0
  77. package/dist/hooks.d.ts +28 -14
  78. package/dist/hooks.js +90 -56
  79. package/dist/icons/index.d.ts +1 -0
  80. package/dist/icons/index.js +1 -0
  81. package/dist/index.d.ts +392 -155
  82. package/dist/index.js +337 -347
  83. package/dist/pagination-BW1mqywp.d.ts +201 -0
  84. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  85. package/dist/providers.d.ts +29 -14
  86. package/dist/providers.js +7 -5
  87. package/dist/rbac/eslint-rules.js +2 -2
  88. package/dist/rbac/index.d.ts +180 -351
  89. package/dist/rbac/index.js +13 -11
  90. package/dist/theming/runtime.d.ts +28 -5
  91. package/dist/theming/runtime.js +2 -2
  92. package/dist/timezone-BTWWXKVY.d.ts +696 -0
  93. package/dist/types-BE2sEHKd.d.ts +55 -0
  94. package/dist/types-CvOPXWWZ.d.ts +111 -0
  95. package/dist/types-Dr8sNhER.d.ts +50 -0
  96. package/dist/types.d.ts +20 -13
  97. package/dist/types.js +1 -0
  98. package/dist/usePublicPageContext-B91dGYW1.d.ts +4367 -0
  99. package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
  100. package/dist/utils.d.ts +338 -156
  101. package/dist/utils.js +78 -60
  102. package/dist/validation-g5n0hDkh.d.ts +177 -0
  103. package/docs/api/modules.md +1226 -1094
  104. package/docs/api-reference/components.md +5 -5
  105. package/docs/api-reference/rpc-functions.md +12 -3
  106. package/docs/core-concepts/rbac-system.md +8 -0
  107. package/docs/getting-started/cursor-rules.md +17 -20
  108. package/docs/getting-started/dependencies.md +1 -1
  109. package/docs/getting-started/setup.md +235 -0
  110. package/docs/implementation-guides/authentication.md +27 -0
  111. package/docs/implementation-guides/data-tables.md +365 -10
  112. package/docs/migration/ApiResult-migration.md +25 -0
  113. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  114. package/docs/rbac/api-reference.md +33 -31
  115. package/docs/standards/0-standards-overview.md +50 -15
  116. package/docs/standards/1-pace-core-compliance-standards.md +62 -57
  117. package/docs/standards/2-project-structure-standards.md +45 -90
  118. package/docs/standards/3-architecture-standards.md +41 -1
  119. package/docs/standards/4-code-quality-standards.md +26 -6
  120. package/docs/standards/5-styling-standards.md +35 -1
  121. package/docs/standards/6-security-rbac-standards.md +288 -7
  122. package/docs/standards/7-api-tech-stack-standards.md +116 -17
  123. package/docs/standards/8-testing-documentation-standards.md +31 -0
  124. package/docs/standards/9-operations-standards.md +19 -0
  125. package/docs/standards/README.md +20 -201
  126. package/docs/testing/README.md +10 -0
  127. package/docs/testing/test-setup-for-consumers.md +916 -0
  128. package/docs/troubleshooting/common-issues.md +17 -1
  129. package/docs/troubleshooting/organisation-context-setup.md +8 -0
  130. package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
  131. package/eslint-config-pace-core.cjs +24 -0
  132. package/package.json +14 -20
  133. package/scripts/build-docs.js +180 -0
  134. package/scripts/setup.cjs +536 -0
  135. package/scripts/validate.cjs +480 -0
  136. package/src/__mocks__/lucide-react.ts +0 -2
  137. package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
  138. package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
  139. package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
  140. package/src/__tests__/helpers/test-providers.test.tsx +99 -0
  141. package/src/__tests__/helpers/test-providers.tsx +37 -39
  142. package/src/__tests__/helpers/test-utils.test.tsx +447 -0
  143. package/src/__tests__/helpers/timer-utils.test.ts +371 -0
  144. package/src/assets/app-icons/admin_favicon.svg +462 -0
  145. package/src/assets/app-icons/base_favicon.svg +85 -0
  146. package/src/assets/app-icons/cake_favicon.svg +68 -0
  147. package/src/assets/app-icons/core_favicon.svg +256 -0
  148. package/src/assets/app-icons/gear_favicon.svg +91 -0
  149. package/src/assets/app-icons/index.test.ts +304 -0
  150. package/src/assets/app-icons/index.ts +83 -0
  151. package/src/assets/app-icons/medi_favicon.svg +92 -0
  152. package/src/assets/app-icons/mint_favicon.svg +83 -0
  153. package/src/assets/app-icons/pace_favicon.svg +49 -0
  154. package/src/assets/app-icons/pump_favicon.svg +68 -0
  155. package/src/assets/app-icons/seed_favicon.svg +91 -0
  156. package/src/assets/app-icons/team_favicon.svg +67 -0
  157. package/src/assets/app-icons/trac_favicon.svg +112 -0
  158. package/src/assets/app-icons/trip_favicon.svg +102 -0
  159. package/src/components/AddressField/AddressField.test.tsx +379 -4
  160. package/src/components/AddressField/AddressField.tsx +239 -213
  161. package/src/components/AddressField/types.ts +2 -2
  162. package/src/components/Alert/Alert.test.tsx +35 -25
  163. package/src/components/Alert/Alert.tsx +8 -8
  164. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  165. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  166. package/src/components/Avatar/Avatar.test.tsx +11 -1
  167. package/src/components/Avatar/Avatar.tsx +3 -2
  168. package/src/components/Badge/Badge.test.tsx +11 -1
  169. package/src/components/Button/Button.test.tsx +13 -3
  170. package/src/components/Button/Button.tsx +1 -1
  171. package/src/components/Calendar/Calendar.test.tsx +523 -131
  172. package/src/components/Calendar/Calendar.tsx +107 -488
  173. package/src/components/Card/Card.test.tsx +384 -258
  174. package/src/components/Card/Card.tsx +19 -10
  175. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  176. package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
  177. package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
  178. package/src/components/ContextSelector/ContextSelector.tsx +66 -280
  179. package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
  180. package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
  181. package/src/components/DataTable/AUDIT_REPORT.md +59 -44
  182. package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
  183. package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
  184. package/src/components/DataTable/DataTable.export.test.tsx +705 -0
  185. package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
  186. package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
  187. package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
  188. package/src/components/DataTable/DataTable.test.tsx +787 -416
  189. package/src/components/DataTable/DataTable.tsx +14 -14
  190. package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
  191. package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
  192. package/src/components/DataTable/DataTableCore.test.tsx +970 -0
  193. package/src/components/DataTable/README.md +155 -0
  194. package/src/components/DataTable/TESTING.md +101 -0
  195. package/src/components/DataTable/a11y.basic.test.tsx +788 -0
  196. package/src/components/DataTable/components/DataTableCore.tsx +126 -894
  197. package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
  198. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -3
  199. package/src/components/DataTable/components/ImportModal.tsx +82 -408
  200. package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
  201. package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
  202. package/src/components/DataTable/context/DataTableContext.tsx +13 -13
  203. package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
  204. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  205. package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
  206. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  207. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
  208. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +15 -3
  211. package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
  212. package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
  213. package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
  214. package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
  215. package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
  216. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
  217. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
  218. package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
  219. package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
  220. package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
  221. package/src/components/DataTable/hooks/useDataTablePermissions.ts +81 -260
  222. package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
  223. package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
  224. package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
  225. package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
  226. package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
  227. package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
  228. package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
  229. package/src/components/DataTable/hooks/useDataTableState.ts +161 -114
  230. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
  231. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
  232. package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
  233. package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
  234. package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
  235. package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
  236. package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
  237. package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
  238. package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
  239. package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
  240. package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
  241. package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
  242. package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
  243. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +311 -271
  244. package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
  245. package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
  246. package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
  247. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +27 -4
  248. package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
  249. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  250. package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
  251. package/src/components/DataTable/hooks/useTableHandlers.ts +13 -22
  252. package/src/components/DataTable/index.ts +28 -5
  253. package/src/components/DataTable/keyboard.test.tsx +734 -0
  254. package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
  255. package/src/components/DataTable/pagination.modes.test.tsx +728 -0
  256. package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
  257. package/src/components/DataTable/styles.test.ts +379 -0
  258. package/src/components/DataTable/styles.ts +0 -1
  259. package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
  260. package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
  261. package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
  262. package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
  263. package/src/components/DataTable/test-utils.ts +94 -0
  264. package/src/components/DataTable/types/actions.ts +71 -0
  265. package/src/components/DataTable/types/base.ts +39 -0
  266. package/src/components/DataTable/types/columns.ts +125 -0
  267. package/src/components/DataTable/types/export.ts +32 -0
  268. package/src/components/DataTable/types/features.ts +81 -0
  269. package/src/components/DataTable/types/hierarchical.ts +44 -0
  270. package/src/components/DataTable/types/index.ts +43 -0
  271. package/src/components/DataTable/types/pagination.ts +85 -0
  272. package/src/components/DataTable/types/performance.ts +47 -0
  273. package/src/components/DataTable/types/props.ts +62 -0
  274. package/src/components/DataTable/types/rbac.ts +45 -0
  275. package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
  276. package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
  277. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
  278. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
  279. package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
  280. package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
  281. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
  282. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
  283. package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
  284. package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
  285. package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
  286. package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
  287. package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
  288. package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
  289. package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
  290. package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
  291. package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
  292. package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
  293. package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
  294. package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
  295. package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
  296. package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
  297. package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
  298. package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
  299. package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
  300. package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
  301. package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
  302. package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
  303. package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
  304. package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
  305. package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
  306. package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
  307. package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
  308. package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
  309. package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
  310. package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
  311. package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
  312. package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
  313. package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
  314. package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
  315. package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
  316. package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
  317. package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
  318. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
  319. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
  320. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
  321. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
  322. package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
  323. package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
  324. package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
  325. package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
  326. package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
  327. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  328. package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
  329. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  330. package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
  331. package/src/components/DataTable/utils/csvParse.test.ts +74 -0
  332. package/src/components/DataTable/utils/csvParse.ts +65 -0
  333. package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
  334. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  335. package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
  336. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  337. package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
  338. package/src/components/DataTable/utils/flexibleImport.ts +3 -186
  339. package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
  340. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  341. package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
  342. package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
  343. package/src/components/DataTable/utils/importDateParser.ts +114 -0
  344. package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
  345. package/src/components/DataTable/utils/importValueParser.ts +91 -0
  346. package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
  347. package/src/components/DataTable/utils/paginationUtils.ts +7 -4
  348. package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
  349. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  350. package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
  351. package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
  352. package/src/components/DataTable/utils/selectFieldUtils.ts +97 -67
  353. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +18 -25
  354. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  355. package/src/components/DateTimeField/DateTimeField.test.tsx +3 -16
  356. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  357. package/src/components/Dialog/Dialog.test-utils.ts +49 -0
  358. package/src/components/Dialog/Dialog.test.tsx +2865 -458
  359. package/src/components/Dialog/Dialog.tsx +183 -986
  360. package/src/components/Dialog/dialogLock.test.ts +238 -0
  361. package/src/components/Dialog/dialogLock.ts +98 -0
  362. package/src/components/Dialog/index.ts +2 -0
  363. package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
  364. package/src/components/Dialog/useDialogDimensions.ts +140 -0
  365. package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
  366. package/src/components/Dialog/useDialogLifecycle.ts +135 -0
  367. package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
  368. package/src/components/Dialog/useDialogPersistence.ts +357 -0
  369. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  370. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  371. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  372. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  373. package/src/components/ErrorBoundary/index.ts +3 -4
  374. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  375. package/src/components/FileDisplay/FileDisplay.test.tsx +479 -247
  376. package/src/components/FileDisplay/FileDisplay.tsx +29 -659
  377. package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
  378. package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
  379. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
  380. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
  381. package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
  382. package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
  383. package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
  384. package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
  385. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
  386. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
  387. package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
  388. package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
  389. package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
  390. package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
  391. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
  392. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
  393. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
  394. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
  395. package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
  396. package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
  397. package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
  398. package/src/components/FileDisplay/fallbackUtils.ts +44 -0
  399. package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
  400. package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
  401. package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
  402. package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
  403. package/src/components/FileDisplay/index.tsx +1 -1
  404. package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
  405. package/src/components/FileDisplay/useFileDisplay.ts +515 -0
  406. package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1438 -0
  407. package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
  408. package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
  409. package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
  410. package/src/components/FileUpload/FileUpload.test.tsx +69 -27
  411. package/src/components/FileUpload/FileUpload.tsx +112 -527
  412. package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
  413. package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
  414. package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
  415. package/src/components/FileUpload/index.tsx +1 -1
  416. package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
  417. package/src/components/FileUpload/useFileUploadManager.ts +454 -0
  418. package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
  419. package/src/components/FileUpload/useResolvedAppId.ts +77 -0
  420. package/src/components/Footer/Footer.test.tsx +15 -382
  421. package/src/components/Footer/Footer.tsx +8 -125
  422. package/src/components/Form/Form.test.tsx +425 -88
  423. package/src/components/Form/Form.tsx +91 -299
  424. package/src/components/Form/useFormPersistence.ts +257 -0
  425. package/src/components/Header/Header.test.tsx +653 -163
  426. package/src/components/Header/Header.tsx +62 -44
  427. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  428. package/src/components/Input/Input.test.tsx +34 -120
  429. package/src/components/Input/Input.tsx +1 -1
  430. package/src/components/Label/Label.test.tsx +46 -45
  431. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +8 -11
  432. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  433. package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
  434. package/src/components/NavigationMenu/NavigationMenu.test.tsx +2422 -102
  435. package/src/components/NavigationMenu/NavigationMenu.tsx +62 -362
  436. package/src/components/NavigationMenu/index.ts +6 -1
  437. package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
  438. package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
  439. package/src/components/NavigationMenu/useNavigationFiltering.ts +199 -308
  440. package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
  441. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1322 -0
  442. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +50 -49
  443. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  444. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +103 -85
  445. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +774 -44
  446. package/src/components/PaceAppLayout/PaceAppLayout.tsx +282 -764
  447. package/src/components/PaceAppLayout/README.md +0 -9
  448. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  449. package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
  450. package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
  451. package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
  452. package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
  453. package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
  454. package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
  455. package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
  456. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +782 -20
  457. package/src/components/PaceLoginPage/PaceLoginPage.tsx +33 -125
  458. package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
  459. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  460. package/src/components/Progress/Progress.test.tsx +127 -1
  461. package/src/components/Progress/Progress.tsx +1 -2
  462. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  463. package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -217
  464. package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
  465. package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
  466. package/src/components/PublicLayout/PublicLayout.test.tsx +1640 -38
  467. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  468. package/src/components/PublicLayout/PublicPageLayout.tsx +134 -75
  469. package/src/components/PublicLayout/PublicPageProvider.tsx +7 -42
  470. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  471. package/src/components/Select/Select.test.tsx +45 -8
  472. package/src/components/Select/Select.tsx +57 -40
  473. package/src/components/Select/context.test.tsx +56 -0
  474. package/src/components/Select/text.test.tsx +104 -0
  475. package/src/components/Select/text.ts +26 -0
  476. package/src/components/Select/types.ts +3 -0
  477. package/src/components/Select/useSelectEvents.test.ts +279 -0
  478. package/src/components/Select/useSelectEvents.ts +87 -0
  479. package/src/components/Select/useSelectSearch.test.tsx +295 -0
  480. package/src/components/Select/useSelectSearch.ts +91 -0
  481. package/src/components/Select/useSelectState.test.ts +268 -0
  482. package/src/components/Select/useSelectState.ts +104 -0
  483. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  484. package/src/components/Switch/Switch.test.tsx +57 -153
  485. package/src/components/Table/Table.test.tsx +395 -317
  486. package/src/components/Tabs/Tabs.test.tsx +270 -0
  487. package/src/components/Tabs/Tabs.tsx +4 -4
  488. package/src/components/Textarea/Textarea.test.tsx +11 -38
  489. package/src/components/Toast/Toast.test.tsx +425 -496
  490. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  491. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  492. package/src/components/UserMenu/UserMenu.tsx +0 -1
  493. package/src/components/index.test.ts +346 -0
  494. package/src/components/index.ts +12 -1
  495. package/src/constants/performance.test.ts +91 -0
  496. package/src/hooks/ServiceHooks.test.tsx +725 -0
  497. package/src/hooks/hooks.integration.test.tsx +608 -0
  498. package/src/hooks/index.ts +18 -3
  499. package/src/hooks/index.unit.test.ts +220 -0
  500. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  501. package/src/hooks/public/usePublicEvent.ts +11 -11
  502. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  503. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  504. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  505. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  506. package/src/hooks/services/useAuth.ts +9 -7
  507. package/src/hooks/services/useAuthService.ts +1 -1
  508. package/src/hooks/services/useEventService.ts +1 -1
  509. package/src/hooks/useAccessibleApps.test.ts +400 -0
  510. package/src/hooks/useAccessibleApps.ts +264 -0
  511. package/src/hooks/useAddressAutocomplete.test.ts +170 -47
  512. package/src/hooks/useAddressAutocomplete.ts +109 -81
  513. package/src/hooks/useApiFetch.unit.test.ts +111 -0
  514. package/src/hooks/useAppConfig.ts +13 -3
  515. package/src/hooks/useAppConfig.unit.test.ts +712 -0
  516. package/src/hooks/useComponentPerformance.unit.test.tsx +314 -0
  517. package/src/hooks/useDataTablePerformance.ts +111 -130
  518. package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
  519. package/src/hooks/useDataTableState.test.ts +170 -0
  520. package/src/hooks/useDataTableState.ts +5 -5
  521. package/src/hooks/useDebounce.unit.test.ts +157 -0
  522. package/src/hooks/useEventTheme.test.ts +70 -18
  523. package/src/hooks/useEventTheme.ts +50 -22
  524. package/src/hooks/useEvents.ts +49 -2
  525. package/src/hooks/useEvents.unit.test.ts +227 -0
  526. package/src/hooks/useFileReference.test.ts +388 -107
  527. package/src/hooks/useFileReference.ts +184 -179
  528. package/src/hooks/useFileUrl.ts +1 -1
  529. package/src/hooks/useFileUrl.unit.test.ts +686 -0
  530. package/src/hooks/useFileUrlCache.test.ts +319 -0
  531. package/src/hooks/useFileUrlCache.ts +5 -2
  532. package/src/hooks/useFocusManagement.unit.test.ts +604 -0
  533. package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
  534. package/src/hooks/useFormDialog.test.ts +307 -0
  535. package/src/hooks/useFormDialog.ts +2 -2
  536. package/src/hooks/useInactivityTracker.ts +141 -134
  537. package/src/hooks/useInactivityTracker.unit.test.ts +446 -0
  538. package/src/hooks/useIsMobile.unit.test.ts +317 -0
  539. package/src/hooks/useIsPrint.ts +62 -0
  540. package/src/hooks/useIsPrint.unit.test.ts +545 -0
  541. package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
  542. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  543. package/src/hooks/useOrganisationPermissions.ts +1 -4
  544. package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
  545. package/src/hooks/useOrganisationSecurity.test.ts +4 -33
  546. package/src/hooks/useOrganisationSecurity.ts +192 -203
  547. package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
  548. package/src/hooks/useOrganisations.ts +1 -1
  549. package/src/hooks/useOrganisations.unit.test.ts +369 -0
  550. package/src/hooks/usePerformanceMonitor.ts +1 -1
  551. package/src/hooks/usePerformanceMonitor.unit.test.ts +693 -0
  552. package/src/hooks/usePermissionCache.test.ts +298 -329
  553. package/src/hooks/usePermissionCache.ts +277 -276
  554. package/src/hooks/usePreventTabReload.test.ts +307 -0
  555. package/src/hooks/usePublicEvent.simple.test.ts +794 -0
  556. package/src/hooks/usePublicEvent.test.ts +670 -0
  557. package/src/hooks/usePublicEvent.unit.test.ts +638 -0
  558. package/src/hooks/usePublicFileDisplay.test.ts +948 -0
  559. package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
  560. package/src/hooks/useQueryCache.test.ts +391 -0
  561. package/src/hooks/useQueryCache.ts +7 -9
  562. package/src/hooks/useRBAC.unit.test.ts +253 -0
  563. package/src/hooks/useSessionDraft.test.ts +556 -0
  564. package/src/hooks/useSessionDraft.ts +14 -11
  565. package/src/hooks/useSessionRestoration.ts +1 -1
  566. package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
  567. package/src/hooks/useStorage.ts +94 -54
  568. package/src/hooks/useStorage.unit.test.ts +684 -0
  569. package/src/hooks/useToast.test.ts +413 -0
  570. package/src/hooks/useToast.ts +2 -2
  571. package/src/hooks/useToast.unit.test.tsx +481 -0
  572. package/src/hooks/useZodForm.ts +3 -3
  573. package/src/hooks/useZodForm.unit.test.tsx +191 -0
  574. package/src/icons/index.test.ts +133 -0
  575. package/src/icons/index.ts +3 -1
  576. package/src/index.test.ts +528 -0
  577. package/src/index.ts +56 -9
  578. package/src/providers/AuthProvider.test.tsx +218 -0
  579. package/src/providers/EventProvider.test.tsx +487 -0
  580. package/src/providers/InactivityProvider.test-helper.tsx +40 -0
  581. package/src/providers/InactivityProvider.test.tsx +421 -0
  582. package/src/providers/ProviderLifecycle.test.tsx +308 -0
  583. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  584. package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
  585. package/src/providers/index.test.ts +138 -0
  586. package/src/providers/services/AuthServiceContext.ts +27 -0
  587. package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
  588. package/src/providers/services/AuthServiceProvider.test.tsx +638 -0
  589. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  590. package/src/providers/services/EventServiceContext.ts +25 -0
  591. package/src/providers/services/EventServiceProvider.test.tsx +839 -0
  592. package/src/providers/services/EventServiceProvider.tsx +11 -20
  593. package/src/providers/services/InactivityServiceContext.ts +25 -0
  594. package/src/providers/services/InactivityServiceProvider.test.tsx +662 -0
  595. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  596. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  597. package/src/providers/services/OrganisationServiceProvider.test.tsx +440 -0
  598. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  599. package/src/providers/services/UnifiedAuthContext.ts +102 -0
  600. package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
  601. package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
  602. package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
  603. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  604. package/src/providers/services/UnifiedAuthProvider.tsx +147 -497
  605. package/src/providers/services/contexts.test.tsx +281 -0
  606. package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
  607. package/src/providers/services/useUnifiedAuth.ts +29 -0
  608. package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
  609. package/src/providers/useInactivity.test-helper.ts +27 -0
  610. package/src/rbac/README.md +5 -5
  611. package/src/rbac/adapters.comprehensive.test.tsx +429 -0
  612. package/src/rbac/adapters.test.tsx +654 -0
  613. package/src/rbac/adapters.tsx +53 -38
  614. package/src/rbac/api.test.ts +986 -259
  615. package/src/rbac/api.ts +260 -216
  616. package/src/rbac/audit-batched.test.ts +550 -0
  617. package/src/rbac/audit-batched.ts +5 -4
  618. package/src/rbac/audit.test.ts +225 -28
  619. package/src/rbac/audit.ts +26 -18
  620. package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
  621. package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
  622. package/src/rbac/cache-invalidation.test.ts +715 -0
  623. package/src/rbac/cache-invalidation.ts +18 -15
  624. package/src/rbac/cache.test.ts +123 -63
  625. package/src/rbac/cache.ts +3 -4
  626. package/src/rbac/components/AccessDenied.test.tsx +324 -0
  627. package/src/rbac/components/AccessDenied.tsx +20 -18
  628. package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
  629. package/src/rbac/components/NavigationGuard.tsx +10 -8
  630. package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
  631. package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
  632. package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
  633. package/src/rbac/components/PagePermissionGuard.test.tsx +1430 -0
  634. package/src/rbac/components/PagePermissionGuard.tsx +188 -381
  635. package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
  636. package/src/rbac/config.test.ts +131 -48
  637. package/src/rbac/config.ts +69 -26
  638. package/src/rbac/docs/event-based-apps.md +26 -13
  639. package/src/rbac/engine.comprehensive.test.ts +808 -0
  640. package/src/rbac/engine.test.ts +974 -130
  641. package/src/rbac/engine.ts +53 -13
  642. package/src/rbac/errors.test.ts +99 -87
  643. package/src/rbac/errors.ts +89 -55
  644. package/src/rbac/eslint-rules.js +2 -2
  645. package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
  646. package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
  647. package/src/rbac/hooks/permissions/useAccessLevel.ts +23 -14
  648. package/src/rbac/hooks/permissions/useCan.test.ts +798 -0
  649. package/src/rbac/hooks/permissions/useCan.ts +173 -253
  650. package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
  651. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +63 -10
  652. package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
  653. package/src/rbac/hooks/permissions/usePermissions.ts +50 -78
  654. package/src/rbac/hooks/useCan.test.ts +348 -32
  655. package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
  656. package/src/rbac/hooks/usePageGuardScope.ts +117 -0
  657. package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
  658. package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
  659. package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
  660. package/src/rbac/hooks/usePermissions.test.ts +459 -33
  661. package/src/rbac/hooks/usePermissions.ts +5 -7
  662. package/src/rbac/hooks/useRBAC.test.ts +1784 -21
  663. package/src/rbac/hooks/useRBAC.ts +148 -88
  664. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  665. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  666. package/src/rbac/hooks/useResourcePermissions.test.ts +561 -24
  667. package/src/rbac/hooks/useResourcePermissions.ts +76 -140
  668. package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
  669. package/src/rbac/hooks/useRoleManagement.test.ts +634 -61
  670. package/src/rbac/hooks/useRoleManagement.ts +158 -586
  671. package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
  672. package/src/rbac/hooks/useSecureSupabase.ts +21 -14
  673. package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
  674. package/src/rbac/index.test.ts +107 -0
  675. package/src/rbac/index.ts +32 -32
  676. package/src/rbac/performance.test.ts +451 -0
  677. package/src/rbac/permissions.test.ts +149 -68
  678. package/src/rbac/permissions.ts +0 -3
  679. package/src/rbac/rbac-core.test.tsx +276 -0
  680. package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
  681. package/src/rbac/rbac-engine-simplified.test.ts +252 -0
  682. package/src/rbac/rbac-functions.test.ts +703 -0
  683. package/src/rbac/rbac-integration.test.ts +523 -0
  684. package/src/rbac/rbac-role-isolation.test.ts +456 -0
  685. package/src/rbac/request-deduplication.test.ts +352 -0
  686. package/src/rbac/request-deduplication.ts +5 -4
  687. package/src/rbac/scenarios.user-role.test.tsx +271 -0
  688. package/src/rbac/secureClient.test.ts +499 -115
  689. package/src/rbac/secureClient.ts +54 -28
  690. package/src/rbac/security.test.ts +448 -44
  691. package/src/rbac/security.ts +7 -6
  692. package/src/rbac/types/roleManagement.ts +66 -0
  693. package/src/rbac/types.test.ts +236 -0
  694. package/src/rbac/types.ts +7 -5
  695. package/src/rbac/utils/clientSecurity.test.ts +192 -0
  696. package/src/rbac/utils/clientSecurity.ts +6 -4
  697. package/src/rbac/utils/contextValidator.test.ts +126 -0
  698. package/src/rbac/utils/contextValidator.ts +6 -3
  699. package/src/rbac/utils/deep-equal.test.ts +76 -0
  700. package/src/rbac/utils/eventContext.test.ts +401 -0
  701. package/src/rbac/utils/eventContext.ts +38 -34
  702. package/src/rbac/utils/fetchPermissionMap.ts +13 -0
  703. package/src/rbac/utils/permissionMapHelpers.ts +34 -0
  704. package/src/rbac/utils/roleManagementRpc.ts +303 -0
  705. package/src/services/AuthService.edge-cases.test.ts +746 -0
  706. package/src/services/AuthService.restoreSession.test.ts +59 -0
  707. package/src/services/AuthService.test.ts +1362 -0
  708. package/src/services/AuthService.ts +197 -216
  709. package/src/services/BaseService.edge-cases.test.ts +506 -0
  710. package/src/services/BaseService.test.ts +363 -0
  711. package/src/services/EventService.edge-cases.test.ts +636 -0
  712. package/src/services/EventService.eventColours.test.ts +64 -0
  713. package/src/services/EventService.test.ts +1250 -0
  714. package/src/services/EventService.ts +244 -315
  715. package/src/services/InactivityService.edge-cases.test.ts +492 -0
  716. package/src/services/InactivityService.lifecycle.test.ts +406 -0
  717. package/src/services/InactivityService.test.ts +829 -0
  718. package/src/services/InactivityService.ts +172 -213
  719. package/src/services/OrganisationService.edge-cases.test.ts +633 -0
  720. package/src/services/OrganisationService.pagination.test.ts +409 -0
  721. package/src/services/OrganisationService.test.ts +1579 -0
  722. package/src/services/OrganisationService.ts +186 -257
  723. package/src/services/base/BaseService.test.ts +214 -0
  724. package/src/services/interfaces/IAuthService.test.ts +184 -0
  725. package/src/services/interfaces/IAuthService.ts +10 -9
  726. package/src/services/interfaces/IEventService.test.ts +176 -0
  727. package/src/services/interfaces/IInactivityService.test.ts +183 -0
  728. package/src/services/interfaces/IOrganisationService.test.ts +207 -0
  729. package/src/services/interfaces/IOrganisationService.ts +0 -1
  730. package/src/styles/core.css +244 -12
  731. package/src/theming/parseEventColours.test.ts +321 -0
  732. package/src/theming/parseEventColours.ts +18 -9
  733. package/src/theming/runtime.test.ts +495 -0
  734. package/src/theming/runtime.ts +72 -7
  735. package/src/types/api-result.ts +53 -0
  736. package/src/types/auth.ts +0 -1
  737. package/src/types/core.test.ts +397 -0
  738. package/src/types/database-generated.test.ts +78 -0
  739. package/src/types/database.generated.ts +45 -10
  740. package/src/types/event.ts +39 -19
  741. package/src/types/file-reference.test.ts +351 -0
  742. package/src/types/file-reference.ts +37 -12
  743. package/src/types/guards.test.ts +246 -0
  744. package/src/types/index.test.ts +265 -0
  745. package/src/types/index.ts +3 -0
  746. package/src/types/organisation.roles.test.ts +55 -0
  747. package/src/types/organisation.test.ts +1105 -0
  748. package/src/types/organisation.ts +15 -15
  749. package/src/types/rpc-responses.ts +33 -0
  750. package/src/types/supabase.ts +14 -6
  751. package/src/types/theme.test.ts +830 -0
  752. package/src/types/type-validation.test.ts +526 -0
  753. package/src/types/validation.test.ts +729 -0
  754. package/src/types/vitest-globals.d.ts +1 -1
  755. package/src/utils/app/appConfig.test.ts +235 -0
  756. package/src/utils/app/appIdResolver.test.ts +252 -57
  757. package/src/utils/app/appIdResolver.ts +31 -20
  758. package/src/utils/app/appNameResolver.test.ts +18 -10
  759. package/src/utils/app/appNameResolver.ts +11 -9
  760. package/src/utils/app/appPortMap.test.ts +125 -0
  761. package/src/utils/app/appPortMap.ts +51 -0
  762. package/src/utils/app/buildAppUrl.test.ts +273 -0
  763. package/src/utils/app/buildAppUrl.ts +114 -0
  764. package/src/utils/appConfig.unit.test.ts +55 -0
  765. package/src/utils/audit/audit.test.ts +354 -39
  766. package/src/utils/audit.unit.test.ts +69 -0
  767. package/src/utils/auth-utils.unit.test.ts +69 -0
  768. package/src/utils/bundleAnalysis.unit.test.ts +326 -0
  769. package/src/utils/cn.unit.test.ts +34 -0
  770. package/src/utils/context/organisationContext.test.ts +115 -95
  771. package/src/utils/context/organisationContext.ts +32 -43
  772. package/src/utils/context/sessionTracking.test.ts +354 -0
  773. package/src/utils/core/cn.test.ts +66 -0
  774. package/src/utils/core/debugLogger.test.ts +113 -0
  775. package/src/utils/core/debugLogger.ts +15 -8
  776. package/src/utils/core/logger.test.ts +217 -0
  777. package/src/utils/core/logger.ts +20 -16
  778. package/src/utils/core/mergeRefs.ts +24 -0
  779. package/src/utils/debugLogger.test.ts +417 -0
  780. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  781. package/src/utils/device/deviceFingerprint.ts +3 -3
  782. package/src/utils/deviceFingerprint.unit.test.ts +818 -0
  783. package/src/utils/dynamic/createLazyComponent.tsx +46 -0
  784. package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
  785. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  786. package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
  787. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  788. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  789. package/src/utils/dynamicUtils.unit.test.ts +331 -0
  790. package/src/utils/file-reference/file-reference.test.ts +1238 -0
  791. package/src/utils/file-reference/index.ts +330 -348
  792. package/src/utils/formatDate.unit.test.ts +109 -0
  793. package/src/utils/formatting/formatDate.test.ts +22 -148
  794. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  795. package/src/utils/formatting/formatDateTimeTimezone.test.ts +41 -85
  796. package/src/utils/formatting/formatNumber.test.ts +259 -0
  797. package/src/utils/formatting/formatTime.test.ts +36 -128
  798. package/src/utils/formatting/formatting.ts +1 -1
  799. package/src/utils/formatting.unit.test.ts +99 -0
  800. package/src/utils/google-places/googlePlacesUtils.test.ts +127 -36
  801. package/src/utils/google-places/googlePlacesUtils.ts +67 -86
  802. package/src/utils/google-places/loadGoogleMapsScript.test.ts +68 -8
  803. package/src/utils/google-places/loadGoogleMapsScript.ts +140 -118
  804. package/src/utils/index.ts +52 -11
  805. package/src/utils/index.unit.test.ts +251 -0
  806. package/src/utils/lazyLoad.unit.test.tsx +319 -0
  807. package/src/utils/location/location.test.ts +19 -116
  808. package/src/utils/logger.unit.test.ts +398 -0
  809. package/src/utils/organisationContext.unit.test.ts +180 -0
  810. package/src/utils/performance/bundleAnalysis.test.ts +148 -0
  811. package/src/utils/performance/bundleAnalysis.ts +16 -22
  812. package/src/utils/performance/performanceBenchmark.test.ts +251 -0
  813. package/src/utils/performance/performanceBenchmark.ts +12 -4
  814. package/src/utils/performance/performanceBudgets.test.ts +241 -0
  815. package/src/utils/performance/performanceBudgets.ts +9 -6
  816. package/src/utils/performanceBenchmark.test.ts +174 -0
  817. package/src/utils/performanceBudgets.unit.test.ts +288 -0
  818. package/src/utils/permissionTypes.unit.test.ts +250 -0
  819. package/src/utils/permissionUtils.unit.test.ts +362 -0
  820. package/src/utils/permissions/permissionTypes.test.ts +149 -0
  821. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  822. package/src/utils/persistence/keyDerivation.test.ts +306 -0
  823. package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
  824. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  825. package/src/utils/request-deduplication.test.ts +349 -0
  826. package/src/utils/request-deduplication.ts +6 -4
  827. package/src/utils/sanitization.unit.test.ts +346 -0
  828. package/src/utils/schemaUtils.unit.test.ts +441 -0
  829. package/src/utils/secureDataAccess.unit.test.ts +334 -0
  830. package/src/utils/secureErrors.unit.test.ts +390 -0
  831. package/src/utils/secureStorage.unit.test.ts +289 -0
  832. package/src/utils/security/auth-utils.ts +38 -27
  833. package/src/utils/security/secureDataAccess.test.ts +22 -191
  834. package/src/utils/security/secureDataAccess.ts +241 -281
  835. package/src/utils/security/secureErrors.test.ts +163 -0
  836. package/src/utils/security/secureStorage.test.ts +156 -0
  837. package/src/utils/security/secureStorage.ts +1 -1
  838. package/src/utils/security/security.test.ts +212 -0
  839. package/src/utils/security/security.ts +15 -18
  840. package/src/utils/security/securityMonitor.test.ts +90 -0
  841. package/src/utils/security/securityMonitor.ts +1 -1
  842. package/src/utils/security.unit.test.ts +155 -0
  843. package/src/utils/securityMonitor.unit.test.ts +276 -0
  844. package/src/utils/sessionTracking.unit.test.ts +218 -0
  845. package/src/utils/storage/config.unit.test.ts +239 -0
  846. package/src/utils/storage/helpers.test.ts +769 -456
  847. package/src/utils/storage/helpers.ts +174 -253
  848. package/src/utils/storage/index.unit.test.ts +68 -0
  849. package/src/utils/storage/storageUtils.ts +32 -0
  850. package/src/utils/storage/types.ts +9 -2
  851. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  852. package/src/utils/supabase/createBaseClient.ts +2 -1
  853. package/src/utils/timezone/timezone.test.ts +26 -44
  854. package/src/utils/timezone.test.ts +345 -0
  855. package/src/utils/validation/common.test.ts +115 -0
  856. package/src/utils/validation/csrf.test.ts +198 -0
  857. package/src/utils/validation/csrf.ts +42 -41
  858. package/src/utils/validation/htmlSanitization.ts +27 -31
  859. package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
  860. package/src/utils/validation/passwordSchema.test.ts +164 -0
  861. package/src/utils/validation/schema.test.ts +127 -0
  862. package/src/utils/validation/schema.ts +6 -3
  863. package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
  864. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  865. package/src/utils/validation/user.test.ts +173 -0
  866. package/src/utils/validation/validation.test.ts +197 -0
  867. package/src/utils/validation/validationUtils.test.ts +294 -0
  868. package/src/utils/validation.unit.test.ts +307 -0
  869. package/src/utils/validationUtils.unit.test.ts +558 -0
  870. package/src/vite-env.d.ts +6 -0
  871. package/dist/AuthService-DmfO5rGS.d.ts +0 -524
  872. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  873. package/dist/DataTable-SOAFXIWY.js +0 -15
  874. package/dist/PublicPageProvider-CIGSujI2.d.ts +0 -4147
  875. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  876. package/dist/UnifiedAuthProvider-CKvHP1MK.d.ts +0 -139
  877. package/dist/api-7P7DI652.js +0 -4
  878. package/dist/audit-MYQXYZFU.js +0 -3
  879. package/dist/auth-BZOJqrdd.d.ts +0 -49
  880. package/dist/chunk-4DDCYDQ3.js +0 -544
  881. package/dist/chunk-5HNSDQWH.js +0 -5046
  882. package/dist/chunk-5W2A3DRC.js +0 -164
  883. package/dist/chunk-6GLLNA6U.js +0 -31
  884. package/dist/chunk-7ILTDCL2.js +0 -80
  885. package/dist/chunk-A3W6LW53.js +0 -70
  886. package/dist/chunk-AHU7G2R5.js +0 -423
  887. package/dist/chunk-C7ZQ5O4C.js +0 -481
  888. package/dist/chunk-EF2UGZWY.js +0 -611
  889. package/dist/chunk-FEJLJNWA.js +0 -181
  890. package/dist/chunk-FYHN4DD5.js +0 -415
  891. package/dist/chunk-GS5672WG.js +0 -2003
  892. package/dist/chunk-HF6O3O37.js +0 -187
  893. package/dist/chunk-J2U36LHD.js +0 -8517
  894. package/dist/chunk-LX6U42O3.js +0 -2177
  895. package/dist/chunk-MPBLMWVR.js +0 -2161
  896. package/dist/chunk-OJ4SKRSV.js +0 -105
  897. package/dist/chunk-S6ZQKDY6.js +0 -62
  898. package/dist/chunk-S7DKJPLT.js +0 -699
  899. package/dist/chunk-T5CVK4R3.js +0 -2816
  900. package/dist/chunk-TTRFSOKR.js +0 -121
  901. package/dist/chunk-Z2FNRKF3.js +0 -994
  902. package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
  903. package/dist/event-CW5YB_2p.d.ts +0 -239
  904. package/dist/file-reference-BavO2eQj.d.ts +0 -148
  905. package/dist/functions-lBy5L2ry.d.ts +0 -208
  906. package/dist/timezone-0AyangqX.d.ts +0 -697
  907. package/dist/types-BeoeWV5I.d.ts +0 -110
  908. package/dist/types-DXstZpNI.d.ts +0 -614
  909. package/dist/types-t9H8qKRw.d.ts +0 -55
  910. package/dist/usePublicRouteParams-DQLrDqDb.d.ts +0 -876
  911. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  912. package/dist/validation-643vUDZW.d.ts +0 -177
  913. package/scripts/build-docs-incremental.js +0 -179
  914. package/scripts/eslint-audit.cjs +0 -123
  915. package/scripts/generate-docs.js +0 -157
  916. package/scripts/install-cursor-rules.cjs +0 -255
  917. package/scripts/install-eslint-config.cjs +0 -349
  918. package/scripts/setup-build-cache.js +0 -73
  919. package/scripts/validate-pre-publish.js +0 -145
  920. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
  921. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
  922. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
  923. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
  924. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -448
  925. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
  926. package/src/__tests__/hooks/usePermissions.test.ts +0 -268
  927. package/src/__tests__/integration/UserProfile.test.tsx +0 -124
  928. package/src/__tests__/public-recipe-view.test.ts +0 -228
  929. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -220
  930. package/src/__tests__/rls-policies.test.ts +0 -471
  931. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
  932. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
  933. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
  934. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
  935. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
  936. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -483
  937. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
  938. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
  939. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -1474
  940. package/src/components/DataTable/__tests__/README.md +0 -145
  941. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
  942. package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
  943. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
  944. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -730
  945. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -325
  946. package/src/components/DataTable/__tests__/styles.test.ts +0 -382
  947. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
  948. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -380
  949. package/src/components/DataTable/__tests__/test-utils.ts +0 -94
  950. package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
  951. package/src/components/DataTable/components/ActionButtons.tsx +0 -190
  952. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
  953. package/src/components/DataTable/components/ColumnFilter.tsx +0 -118
  954. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
  955. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
  956. package/src/components/DataTable/components/DataTableLayout.tsx +0 -573
  957. package/src/components/DataTable/components/DataTableModals.tsx +0 -245
  958. package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
  959. package/src/components/DataTable/components/EditFields.tsx +0 -327
  960. package/src/components/DataTable/components/EditableRow.tsx +0 -462
  961. package/src/components/DataTable/components/EmptyState.tsx +0 -79
  962. package/src/components/DataTable/components/FilterRow.tsx +0 -141
  963. package/src/components/DataTable/components/LoadingState.tsx +0 -17
  964. package/src/components/DataTable/components/PaginationControls.tsx +0 -289
  965. package/src/components/DataTable/components/RowComponent.tsx +0 -403
  966. package/src/components/DataTable/components/SortIndicator.tsx +0 -50
  967. package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -355
  968. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -657
  969. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -913
  970. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -572
  971. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -612
  972. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -708
  973. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -479
  974. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -475
  975. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -157
  976. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -1061
  977. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -437
  978. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -474
  979. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -617
  980. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -1093
  981. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -139
  982. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -519
  983. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -1004
  984. package/src/components/DataTable/components/cellValueUtils.ts +0 -40
  985. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
  986. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
  987. package/src/components/DataTable/components/index.ts +0 -16
  988. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -342
  989. package/src/components/DataTable/core/ActionManager.ts +0 -235
  990. package/src/components/DataTable/core/ColumnManager.ts +0 -205
  991. package/src/components/DataTable/core/DataManager.ts +0 -188
  992. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
  993. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  994. package/src/components/DataTable/core/StateManager.ts +0 -312
  995. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -123
  996. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -305
  997. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -84
  998. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -115
  999. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -100
  1000. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -120
  1001. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -104
  1002. package/src/components/DataTable/core/index.ts +0 -1
  1003. package/src/components/DataTable/core/interfaces.ts +0 -338
  1004. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -521
  1005. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -167
  1006. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -124
  1007. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -117
  1008. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -102
  1009. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -596
  1010. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -53
  1011. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -214
  1012. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -448
  1013. package/src/components/DataTable/hooks/index.ts +0 -13
  1014. package/src/components/DataTable/types.ts +0 -761
  1015. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -612
  1016. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
  1017. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -266
  1018. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
  1019. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
  1020. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -247
  1021. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -570
  1022. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
  1023. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -251
  1024. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -207
  1025. package/src/components/DataTable/utils/index.ts +0 -10
  1026. package/src/components/PublicLayout/index.ts +0 -32
  1027. package/src/components/Select/hooks/useSelectEvents.ts +0 -87
  1028. package/src/components/Select/hooks/useSelectSearch.ts +0 -91
  1029. package/src/components/Select/hooks/useSelectState.ts +0 -104
  1030. package/src/components/Select/utils/text.ts +0 -26
  1031. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -615
  1032. package/src/hooks/__tests__/hooks.integration.test.tsx +0 -607
  1033. package/src/hooks/__tests__/index.unit.test.ts +0 -220
  1034. package/src/hooks/__tests__/useApiFetch.unit.test.ts +0 -111
  1035. package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -347
  1036. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -144
  1037. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -776
  1038. package/src/hooks/__tests__/useDataTableState.test.ts +0 -76
  1039. package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -82
  1040. package/src/hooks/__tests__/useEvents.unit.test.ts +0 -252
  1041. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1112
  1042. package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -916
  1043. package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -129
  1044. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -230
  1045. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -828
  1046. package/src/hooks/__tests__/useFormDialog.test.ts +0 -478
  1047. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
  1048. package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
  1049. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -910
  1050. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -294
  1051. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
  1052. package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
  1053. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
  1054. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  1055. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  1056. package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -88
  1057. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -785
  1058. package/src/hooks/__tests__/usePublicEvent.test.ts +0 -678
  1059. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -630
  1060. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -951
  1061. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -443
  1062. package/src/hooks/__tests__/useQueryCache.test.ts +0 -144
  1063. package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
  1064. package/src/hooks/__tests__/useSessionDraft.test.ts +0 -163
  1065. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
  1066. package/src/hooks/__tests__/useStorage.unit.test.ts +0 -751
  1067. package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
  1068. package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -37
  1069. package/src/hooks/public/index.ts +0 -36
  1070. package/src/hooks/public/usePublicFileDisplay.ts +0 -504
  1071. package/src/hooks/useFileDisplay.ts +0 -715
  1072. package/src/providers/OrganisationProvider.tsx +0 -92
  1073. package/src/providers/__tests__/AuthProvider.test.tsx +0 -287
  1074. package/src/providers/__tests__/EventProvider.test.tsx +0 -551
  1075. package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
  1076. package/src/providers/__tests__/InactivityProvider.test.tsx +0 -572
  1077. package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -617
  1078. package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -424
  1079. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -596
  1080. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -263
  1081. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -294
  1082. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -434
  1083. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -313
  1084. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -486
  1085. package/src/rbac/__tests__/cache-invalidation.test.ts +0 -399
  1086. package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -813
  1087. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  1088. package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
  1089. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -392
  1090. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -258
  1091. package/src/rbac/__tests__/rbac-functions.test.ts +0 -647
  1092. package/src/rbac/__tests__/rbac-integration.test.ts +0 -524
  1093. package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
  1094. package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -282
  1095. package/src/rbac/audit-enhanced.ts +0 -384
  1096. package/src/rbac/compliance/database-validator.ts +0 -165
  1097. package/src/rbac/compliance/index.ts +0 -48
  1098. package/src/rbac/compliance/pattern-detector.ts +0 -553
  1099. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  1100. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  1101. package/src/rbac/compliance/setup-validator.ts +0 -131
  1102. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -975
  1103. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -248
  1104. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -242
  1105. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1107
  1106. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -184
  1107. package/src/rbac/components/index.ts +0 -26
  1108. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -432
  1109. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -579
  1110. package/src/rbac/hooks/index.ts +0 -34
  1111. package/src/rbac/hooks/permissions/index.ts +0 -4
  1112. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  1113. package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -128
  1114. package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -53
  1115. package/src/rbac/utils/__tests__/eventContext.test.ts +0 -433
  1116. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  1117. package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -39
  1118. package/src/services/__tests__/AuthService.test.ts +0 -1332
  1119. package/src/services/__tests__/BaseService.test.ts +0 -314
  1120. package/src/services/__tests__/EventService.eventColours.test.ts +0 -76
  1121. package/src/services/__tests__/EventService.test.ts +0 -1025
  1122. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -411
  1123. package/src/services/__tests__/InactivityService.test.ts +0 -654
  1124. package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
  1125. package/src/services/__tests__/OrganisationService.test.ts +0 -1176
  1126. package/src/theming/__tests__/parseEventColours.test.ts +0 -321
  1127. package/src/theming/__tests__/runtime.test.ts +0 -569
  1128. package/src/types/__tests__/file-reference.test.ts +0 -447
  1129. package/src/types/__tests__/guards.test.ts +0 -246
  1130. package/src/types/__tests__/organisation.roles.test.ts +0 -55
  1131. package/src/types/__tests__/organisation.test.ts +0 -1133
  1132. package/src/types/__tests__/theme.test.ts +0 -830
  1133. package/src/types/__tests__/type-validation.test.ts +0 -526
  1134. package/src/types/__tests__/validation.test.ts +0 -731
  1135. package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
  1136. package/src/utils/__tests__/audit.unit.test.ts +0 -69
  1137. package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
  1138. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -339
  1139. package/src/utils/__tests__/cn.unit.test.ts +0 -34
  1140. package/src/utils/__tests__/debugLogger.test.ts +0 -417
  1141. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
  1142. package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -318
  1143. package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
  1144. package/src/utils/__tests__/formatting.unit.test.ts +0 -99
  1145. package/src/utils/__tests__/index.unit.test.ts +0 -251
  1146. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -321
  1147. package/src/utils/__tests__/logger.unit.test.ts +0 -398
  1148. package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
  1149. package/src/utils/__tests__/performanceBenchmark.test.ts +0 -175
  1150. package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -253
  1151. package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
  1152. package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
  1153. package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
  1154. package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
  1155. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -335
  1156. package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
  1157. package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
  1158. package/src/utils/__tests__/security.unit.test.ts +0 -149
  1159. package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
  1160. package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
  1161. package/src/utils/__tests__/timezone.test.ts +0 -345
  1162. package/src/utils/__tests__/validation.unit.test.ts +0 -308
  1163. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
  1164. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  1165. package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -875
  1166. package/src/utils/google-places/index.ts +0 -26
  1167. package/src/utils/location/index.ts +0 -16
  1168. package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -135
  1169. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -123
  1170. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  1171. package/src/utils/storage/__tests__/index.unit.test.ts +0 -16
  1172. package/src/utils/storage/index.ts +0 -67
  1173. package/src/utils/timezone/index.ts +0 -17
  1174. package/src/utils/validation/__tests__/csrf.test.ts +0 -105
  1175. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -598
  1176. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -92
  1177. package/src/utils/validation/__tests__/validationUtils.test.ts +0 -72
  1178. package/src/utils/validation/index.ts +0 -73
  1179. /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
  1180. /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
  1181. /package/src/providers/{__tests__/README.md → README.md} +0 -0
  1182. /package/src/types/{__tests__/README.md → README.md} +0 -0
@@ -42,7 +42,7 @@
42
42
  * <DialogBody>
43
43
  * <section className="space-y-4">
44
44
  * <fieldset className="grid grid-cols-4 items-center gap-4">
45
- * <Label htmlFor="name" className="text-right">Name</Label>
45
+ * <Label htmlFor="name">Name</Label>
46
46
  * <Input id="name" defaultValue="John Doe" className="col-span-3" />
47
47
  * </fieldset>
48
48
  * </section>
@@ -89,44 +89,20 @@
89
89
 
90
90
  import * as React from 'react';
91
91
  import { createPortal } from 'react-dom';
92
- import { X } from 'lucide-react';
93
92
  import { useLocation } from 'react-router-dom';
93
+ import { Button, IconButton } from '../Button';
94
+ import { X } from '../../icons';
94
95
  import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
95
96
  import { cn } from '../../utils/core/cn';
97
+ import { mergeRefs } from '../../utils/core/mergeRefs';
96
98
  import { renderSafeHtml } from '../../utils/validation/htmlSanitization';
97
99
  import { useState, useEffect, useRef, useCallback, useId, useMemo } from 'react';
98
100
  import { useFocusTrap } from '../../hooks/useFocusTrap';
99
- import { useSessionDraft } from '../../hooks/useSessionDraft';
100
101
  import { deriveDialogKey } from '../../utils/persistence/keyDerivation';
101
-
102
- /**
103
- * Simple debounce function that matches lodash debounce API
104
- * Returns a debounced function with a cancel method
105
- */
106
- function debounce<T extends (...args: any[]) => void>(
107
- func: T,
108
- wait: number
109
- ): T & { cancel: () => void } {
110
- let timeoutId: ReturnType<typeof setTimeout> | null = null;
111
-
112
- const debounced = ((...args: Parameters<T>) => {
113
- if (timeoutId !== null) {
114
- clearTimeout(timeoutId);
115
- }
116
- timeoutId = setTimeout(() => {
117
- func(...args);
118
- }, wait);
119
- }) as T & { cancel: () => void };
120
-
121
- debounced.cancel = () => {
122
- if (timeoutId !== null) {
123
- clearTimeout(timeoutId);
124
- timeoutId = null;
125
- }
126
- };
127
-
128
- return debounced;
129
- }
102
+ import { createLogger } from '../../utils/core/logger';
103
+ import { useDialogPersistence } from './useDialogPersistence';
104
+ import { useDialogDimensions } from './useDialogDimensions';
105
+ import { useDialogLifecycle } from './useDialogLifecycle';
130
106
 
131
107
  /**
132
108
  * Dialog size variants
@@ -143,7 +119,6 @@ interface DialogContextValue {
143
119
  dialogRef: React.RefObject<HTMLDialogElement | null>;
144
120
  titleId: string;
145
121
  descriptionId: string;
146
- dialogTitle?: string; // For persistence key derivation
147
122
  markClosedByUser?: () => void; // Callback to mark dialog as closed by user (for Cancel buttons, etc.)
148
123
  }
149
124
 
@@ -218,12 +193,6 @@ export interface DialogContentProps extends React.HTMLAttributes<HTMLDialogEleme
218
193
  persistOpenState?: boolean;
219
194
  }
220
195
 
221
- /**
222
- * Props for the DialogOverlay component
223
- * @public
224
- */
225
- export interface DialogOverlayProps extends React.HTMLAttributes<HTMLDivElement> {}
226
-
227
196
  /**
228
197
  * Props for the DialogPortal component
229
198
  * @public
@@ -232,12 +201,6 @@ export interface DialogPortalProps {
232
201
  children: React.ReactNode;
233
202
  }
234
203
 
235
- /**
236
- * Props for the DialogClose component
237
- * @public
238
- */
239
- export interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
240
-
241
204
  /**
242
205
  * Props for the DialogHeader component (semantic header element)
243
206
  * @public
@@ -267,8 +230,6 @@ export interface DialogBodyProps extends React.HTMLAttributes<HTMLElement> {
267
230
  htmlContent?: string;
268
231
  /** Whether to allow HTML content rendering (default: true) */
269
232
  allowHtml?: boolean;
270
- /** Whether to use strict HTML sanitization (default: true) */
271
- strictSanitization?: boolean;
272
233
  /** Whether to log HTML sanitization warnings to console (default: false) */
273
234
  logWarnings?: boolean;
274
235
  }
@@ -295,16 +256,6 @@ export interface DialogDescriptionProps extends React.HTMLAttributes<HTMLParagra
295
256
  allowHtml?: boolean;
296
257
  }
297
258
 
298
- // Size mapping for dialog variants
299
- const sizeClasses = {
300
- sm: 'max-w-sm',
301
- md: 'max-w-md',
302
- lg: 'max-w-lg',
303
- xl: 'max-w-xl',
304
- full: 'max-w-full size-full',
305
- auto: 'max-w-none w-auto min-w-0'
306
- };
307
-
308
259
  /**
309
260
  * Dialog root component
310
261
  * Provides context for dialog state management
@@ -319,7 +270,6 @@ const Dialog = React.memo<DialogProps>(function Dialog({
319
270
  const dialogRef = useRef<HTMLDialogElement | null>(null);
320
271
  const titleId = useId();
321
272
  const descriptionId = useId();
322
- const dialogTitleRef = useRef<string | undefined>(undefined);
323
273
  const [markClosedByUser, setMarkClosedByUserState] = useState<(() => void) | undefined>(undefined);
324
274
 
325
275
  const isControlled = controlledOpen !== undefined;
@@ -338,15 +288,9 @@ const Dialog = React.memo<DialogProps>(function Dialog({
338
288
  dialogRef,
339
289
  titleId,
340
290
  descriptionId,
341
- dialogTitle: dialogTitleRef.current,
342
291
  markClosedByUser, // Set by DialogContent
343
292
  }), [open, handleOpenChange, titleId, descriptionId, markClosedByUser]);
344
293
 
345
- // Expose function to set dialog title (called by DialogContent)
346
- const setDialogTitle = useCallback((title: string | undefined) => {
347
- dialogTitleRef.current = title;
348
- }, []);
349
-
350
294
  // Expose function to set markClosedByUser callback (called by DialogContent)
351
295
  const setMarkClosedByUser = useCallback((callback: (() => void) | undefined) => {
352
296
  setMarkClosedByUserState(callback);
@@ -354,22 +298,17 @@ const Dialog = React.memo<DialogProps>(function Dialog({
354
298
 
355
299
  return (
356
300
  <DialogContext.Provider value={contextValue}>
357
- <DialogTitleContext.Provider value={setDialogTitle}>
358
- <DialogMarkClosedContext.Provider value={setMarkClosedByUser}>
359
- {children}
360
- </DialogMarkClosedContext.Provider>
361
- </DialogTitleContext.Provider>
301
+ <DialogMarkClosedContext.Provider value={setMarkClosedByUser}>
302
+ {children}
303
+ </DialogMarkClosedContext.Provider>
362
304
  </DialogContext.Provider>
363
305
  );
364
306
  });
365
307
 
366
- // Context for setting dialog title from DialogContent
367
- const DialogTitleContext = React.createContext<((title: string | undefined) => void) | null>(null);
368
-
369
308
  // Context for setting markClosedByUser callback from DialogContent
370
309
  const DialogMarkClosedContext = React.createContext<((callback: (() => void) | undefined) => void) | null>(null);
371
310
 
372
- // Context for marking dialog as closed by user (from DialogContent to DialogClose)
311
+ // Context for passing markClosedByUser to DialogClose in the same render (DialogContext.markClosedByUser is set async)
373
312
  const DialogCloseContext = React.createContext<(() => void) | null>(null);
374
313
  Dialog.displayName = 'Dialog';
375
314
 
@@ -377,7 +316,7 @@ Dialog.displayName = 'Dialog';
377
316
  * DialogTrigger component
378
317
  * Opens the dialog when clicked
379
318
  */
380
- const DialogTrigger = React.forwardRef<HTMLElement, DialogTriggerProps>(
319
+ const DialogTrigger = React.forwardRef<HTMLButtonElement, DialogTriggerProps>(
381
320
  ({ children, asChild = false, className, onClick, ...props }, ref) => {
382
321
  const { onOpenChange } = useDialogContext();
383
322
 
@@ -387,24 +326,25 @@ const DialogTrigger = React.forwardRef<HTMLElement, DialogTriggerProps>(
387
326
  }, [onOpenChange, onClick]);
388
327
 
389
328
  if (asChild && React.isValidElement(children)) {
390
- return React.cloneElement(children as React.ReactElement<any>, {
329
+ const childElement = children as React.ReactElement<React.HTMLAttributes<HTMLElement>>;
330
+ return React.cloneElement(childElement, {
391
331
  ref,
392
332
  onClick: handleClick,
393
- className: cn(className, (children as any).props?.className),
333
+ className: cn(className, childElement.props?.className),
394
334
  ...props,
395
- });
335
+ } as React.HTMLAttributes<HTMLElement> & React.RefAttributes<HTMLElement>);
396
336
  }
397
337
 
398
338
  return (
399
- <button
400
- ref={ref as React.RefObject<HTMLButtonElement>}
339
+ <Button
340
+ ref={ref}
401
341
  type="button"
402
342
  onClick={handleClick}
403
343
  className={className}
404
344
  {...props}
405
345
  >
406
346
  {children}
407
- </button>
347
+ </Button>
408
348
  );
409
349
  }
410
350
  );
@@ -428,222 +368,28 @@ const DialogPortal: React.FC<DialogPortalProps> = ({ children }) => {
428
368
  };
429
369
  DialogPortal.displayName = 'DialogPortal';
430
370
 
431
- /**
432
- * DialogOverlay component
433
- * Backdrop overlay for the dialog (optional, native dialog provides ::backdrop)
434
- * This component is kept for backward compatibility but may not be needed
435
- * when using native dialog element which provides ::backdrop automatically
436
- */
437
- const DialogOverlay = React.forwardRef<HTMLDivElement, DialogOverlayProps>(
438
- ({ className, ...props }, ref) => {
439
- // Note: Native dialog element provides ::backdrop automatically
440
- // This component is kept for API compatibility but may not render
441
- // The native dialog's ::backdrop is styled via CSS
442
- return null;
443
- }
444
- );
445
- DialogOverlay.displayName = 'DialogOverlay';
446
-
447
- /**
448
- * Custom hook for managing smart dialog dimensions
449
- * Handles responsive sizing and viewport-based constraints
450
- */
451
- const useSmartDimensions = ({
452
- maxHeightPercent,
453
- maxWidthPercent,
454
- maxHeight,
455
- maxWidth,
456
- minHeight,
457
- minWidth,
458
- enableScrolling = false,
459
- }: {
460
- maxHeightPercent?: number;
461
- maxWidthPercent?: number;
462
- maxHeight?: string;
463
- maxWidth?: string;
464
- minHeight?: string;
465
- minWidth?: string;
466
- enableScrolling?: boolean;
467
- }) => {
468
- const [dimensions, setDimensions] = useState<React.CSSProperties>({});
469
-
470
- useEffect(() => {
471
- if (!maxHeightPercent && !maxWidthPercent && !maxHeight && !maxWidth && !minHeight && !minWidth) {
472
- return;
473
- }
474
-
475
- const updateDimensions = () => {
476
- const result: React.CSSProperties = {};
477
-
478
- // Handle height constraints
479
- if (maxHeightPercent && typeof maxHeightPercent === 'number') {
480
- const constrainedHeight = Math.min(maxHeightPercent, 95);
481
- result.maxHeight = `${constrainedHeight}vh`;
482
- } else if (maxHeight) {
483
- result.maxHeight = maxHeight;
484
- }
485
-
486
- // Handle width constraints
487
- if (maxWidthPercent && typeof maxWidthPercent === 'number') {
488
- const constrainedWidth = Math.min(maxWidthPercent, 95);
489
- result.maxWidth = `${constrainedWidth}vw`;
490
- } else if (maxWidth) {
491
- result.maxWidth = maxWidth;
492
- }
493
-
494
- // Include minHeight/minWidth if provided
495
- if (minHeight) {
496
- result.minHeight = minHeight;
497
- }
498
- if (minWidth) {
499
- result.minWidth = minWidth;
500
- }
501
-
502
- setDimensions(result);
503
- };
504
-
505
- // Debounced resize handler
506
- const debouncedUpdate = debounce(updateDimensions, 100);
507
-
508
- // Initial calculation
509
- updateDimensions();
510
-
511
- // Listen for resize events
512
- window.addEventListener('resize', debouncedUpdate);
513
-
514
- return () => {
515
- window.removeEventListener('resize', debouncedUpdate);
516
- debouncedUpdate.cancel();
517
- };
518
- }, [maxHeightPercent, maxWidthPercent, maxHeight, maxWidth, minHeight, minWidth, enableScrolling]);
519
-
520
- // Return dimensions
521
- const result: React.CSSProperties = {};
522
-
523
- // Handle height constraints
524
- if (maxHeightPercent && typeof maxHeightPercent === 'number') {
525
- const constrainedHeight = Math.min(maxHeightPercent, 95);
526
- result.maxHeight = `${constrainedHeight}vh`;
527
- } else if (maxHeight) {
528
- result.maxHeight = maxHeight;
529
- }
530
-
531
- // Handle width constraints
532
- if (maxWidthPercent && typeof maxWidthPercent === 'number') {
533
- const constrainedWidth = Math.min(maxWidthPercent, 95);
534
- result.maxWidth = `${constrainedWidth}vw`;
535
- } else if (maxWidth) {
536
- result.maxWidth = maxWidth;
537
- }
538
-
539
- // Include minHeight/minWidth if provided
540
- if (minHeight) {
541
- result.minHeight = minHeight;
542
- }
543
- if (minWidth) {
544
- result.minWidth = minWidth;
545
- }
546
-
547
- return result;
548
- };
549
-
550
- /**
551
- * Global lock to ensure only one dialog is open at a time
552
- * Uses sessionStorage for persistence across page reloads
553
- */
554
- const DIALOG_LOCK_KEY = 'pace-core:dialog:lock';
555
-
556
- function acquireDialogLock(persistenceKey: string | null): boolean {
557
- if (!persistenceKey) {
558
- return true; // Non-persisted dialogs can always open
559
- }
560
-
561
- try {
562
- const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
563
- if (lock) {
564
- const lockData = JSON.parse(lock);
565
- // If lock is held by this dialog, allow it
566
- if (lockData.key === persistenceKey) {
567
- return true;
568
- }
569
- // If lock is held by another dialog, check if that dialog is still open
570
- const lockDialog = document.querySelector(`dialog[data-persistence-key="${lockData.key}"]`) as HTMLDialogElement;
571
- if (lockDialog && lockDialog.open) {
572
- return false; // Another dialog is still open
573
- }
574
- // Lock is stale, clear it
575
- sessionStorage.removeItem(DIALOG_LOCK_KEY);
576
- }
577
- // Acquire the lock
578
- sessionStorage.setItem(DIALOG_LOCK_KEY, JSON.stringify({
579
- key: persistenceKey,
580
- timestamp: Date.now(),
581
- }));
582
- return true;
583
- } catch {
584
- // If sessionStorage fails, allow opening (graceful degradation)
585
- return true;
586
- }
587
- }
588
-
589
- function releaseDialogLock(persistenceKey: string | null): void {
590
- if (!persistenceKey) {
591
- return;
592
- }
593
-
594
- try {
595
- const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
596
- if (lock) {
597
- const lockData = JSON.parse(lock);
598
- if (lockData.key === persistenceKey) {
599
- sessionStorage.removeItem(DIALOG_LOCK_KEY);
600
- }
601
- }
602
- } catch {
603
- // Ignore errors
604
- }
605
- }
606
-
607
- /**
608
- * Check if any other dialog (besides the current one) has persisted open state
609
- * This helps determine if another dialog should be allowed to auto-open
610
- */
611
- function checkOtherDialogsHavePersistedState(currentPersistenceKey: string | null): boolean {
612
- if (!currentPersistenceKey) {
613
- return false;
614
- }
615
-
616
- try {
617
- const lock = sessionStorage.getItem(DIALOG_LOCK_KEY);
618
- if (lock) {
619
- const lockData = JSON.parse(lock);
620
- if (lockData.key !== currentPersistenceKey) {
621
- // Another dialog holds the lock
622
- return true;
623
- }
624
- }
625
- } catch {
626
- // Error accessing sessionStorage - assume no other dialogs
627
- return false;
628
- }
629
-
630
- return false;
371
+ export interface UseDialogContentStateReturn {
372
+ mergedRef: (node: HTMLDialogElement | null) => void;
373
+ canRender: boolean;
374
+ markClosedByUser: () => void;
375
+ sizeClass: string;
376
+ mergedStyle: React.CSSProperties;
377
+ hasHeightConstraint: boolean;
378
+ persistenceKey: string | null;
379
+ persistOpenState: boolean;
380
+ titleId: string;
381
+ descriptionId: string;
382
+ open: boolean;
383
+ title: string | undefined;
384
+ description: string | undefined;
631
385
  }
632
386
 
633
- /**
634
- * DialogContent component
635
- * The main content container using semantic HTML <dialog> element with enhanced features
636
- *
637
- * @param props - Content configuration and styling
638
- * @param ref - Forwarded ref to the dialog element
639
- * @returns JSX.Element - The semantic dialog content with overlay and optional close button
640
- */
641
- const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
642
- ({
643
- className,
644
- children,
387
+ function useDialogContentState(
388
+ props: DialogContentProps,
389
+ ref: React.ForwardedRef<HTMLDialogElement>
390
+ ): UseDialogContentStateReturn {
391
+ const {
645
392
  size = 'md',
646
- showCloseButton = true,
647
393
  preventCloseOnEscape = false,
648
394
  preventCloseOnOutsideClick = false,
649
395
  maxHeightPercent,
@@ -657,430 +403,47 @@ const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
657
403
  description,
658
404
  style,
659
405
  persistOpenState = true,
660
- ...props
661
- }, ref) => {
662
- // Call all hooks unconditionally at the top level
663
- // Hooks must be called in the same order on every render
664
- const { open, onOpenChange, dialogRef, titleId, descriptionId } = useDialogContext();
665
- const setDialogTitle = React.useContext(DialogTitleContext);
666
- const setMarkClosedByUser = React.useContext(DialogMarkClosedContext);
667
-
668
- // Component mount/unmount tracking removed for performance
669
-
670
- // Call hooks unconditionally - if providers are missing, they will throw
671
- // Errors should be handled by error boundaries at a higher level
672
- const location = useLocation();
673
- const auth = useUnifiedAuth();
674
- const userId = auth.user?.id || null;
675
-
676
- // Set dialog title in context for persistence
677
- useEffect(() => {
678
- if (setDialogTitle) {
679
- setDialogTitle(title);
680
- }
681
- }, [title, setDialogTitle]);
682
-
683
- // Derive persistence key (scoped by user ID)
684
- // CRITICAL: Only enable persistence if we have a valid userId to prevent data leakage
685
- const persistenceKey = useMemo(() => {
686
- if (!persistOpenState) {
687
- return null;
688
- }
689
- // Don't create persistence key if userId is not available
690
- // This prevents unscoped persistence that could leak between users
691
- if (!userId) {
692
- return null;
693
- }
694
- return deriveDialogKey(
695
- {
696
- title,
697
- description,
698
- },
699
- location,
700
- userId
701
- );
702
- }, [title, description, location, userId, persistOpenState]);
703
-
704
- // Use session draft for open state persistence
705
- // Only enabled when we have a valid persistenceKey (which requires userId)
706
- const { state: persistedOpen, setState: setPersistedOpen, clearDraft, wasRestored } = useSessionDraft<boolean>(
707
- persistenceKey ? `${persistenceKey}:open` : 'dialog:no-key:open',
708
- false,
709
- {
710
- enabled: Boolean(persistenceKey && persistOpenState && userId),
711
- debounceMs: 300,
712
- }
713
- );
714
-
715
- // Track if we've attempted auto-open to prevent multiple attempts
716
- const hasAutoOpenedRef = useRef(false);
717
- const hasInitializedRef = useRef(false);
718
- // Track if dialog was closed by user action (to clear persistence)
719
- const wasClosedByUserRef = useRef(false);
720
- // Track if dialog was manually opened (to prevent auto-open from interfering)
721
- const wasManuallyOpenedRef = useRef(false);
722
-
723
- // Callback to mark dialog as closed by user (exposed via context for DialogClose and Cancel buttons)
724
- const markClosedByUser = useCallback(() => {
725
- if (hasInitializedRef.current) {
726
- wasClosedByUserRef.current = true;
727
- }
728
- }, []);
729
-
730
- // Register markClosedByUser with parent Dialog component so it's available via DialogContext
731
- useEffect(() => {
732
- if (setMarkClosedByUser) {
733
- setMarkClosedByUser(markClosedByUser);
734
- }
735
- return () => {
736
- // Cleanup: unregister when DialogContent unmounts
737
- if (setMarkClosedByUser) {
738
- setMarkClosedByUser(undefined);
739
- }
740
- };
741
- }, [setMarkClosedByUser, markClosedByUser]);
742
- // Track if we've cleaned up other dialog states (to prevent multiple cleanup runs)
743
- const hasCleanedUpOtherDialogsRef = useRef(false);
744
-
745
- // Auto-open on mount if dialog was open when tab closed
746
- useEffect(() => {
747
- if (!persistenceKey || !persistOpenState) {
748
- hasInitializedRef.current = true;
749
- return;
750
- }
751
-
752
- // Only attempt auto-open once
753
- // This prevents auto-open from running after manual opens
754
- if (hasAutoOpenedRef.current) {
755
- return;
756
- }
757
-
758
- // CRITICAL: Don't auto-open if dialog was manually opened
759
- // This prevents auto-open from interfering with manual opens
760
- if (wasManuallyOpenedRef.current) {
761
- console.log('[Dialog Persistence] ⏭️ Skipping auto-open - dialog was manually opened', {
762
- persistenceKey,
763
- currentOpen: open,
764
- });
765
- return;
766
- }
767
-
768
- // Mark as initialized after first check
769
- if (!hasInitializedRef.current) {
770
- hasInitializedRef.current = true;
771
- }
772
-
773
- // Auto-open check (logging removed for performance)
774
-
775
- // CRITICAL: Don't auto-open if dialog is already open (user-initiated)
776
- if (open === true) {
777
- hasAutoOpenedRef.current = true;
778
- return;
779
- }
780
-
781
- // CRITICAL: Don't auto-open if userId is not available (prevents unscoped persistence from being restored)
782
- if (!userId) {
783
- hasAutoOpenedRef.current = true;
784
- return;
785
- }
786
-
787
- // Only auto-open if conditions are met
788
- if (persistedOpen === true && open === false && wasRestored && !hasAutoOpenedRef.current && !wasManuallyOpenedRef.current) {
789
- const AUTO_OPEN_LOCK_KEY = 'pace-core:dialog:auto-open-lock';
790
- const lockTimestamp = sessionStorage.getItem(AUTO_OPEN_LOCK_KEY);
791
- const now = Date.now();
792
-
793
- // Check if another dialog is already auto-opening (lock exists and is recent)
794
- if (lockTimestamp) {
795
- const lockAge = now - parseInt(lockTimestamp, 10);
796
- if (lockAge < 1000) {
797
- // Lock is recent - another dialog is auto-opening
798
- // Check if there's already an open dialog with this persistence key
799
- const existingOpenDialog = document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
800
- if (existingOpenDialog) {
801
- // Another instance is already open - skip
802
- hasAutoOpenedRef.current = true;
803
- return;
804
- }
805
- // Check if other dialog has persisted state
806
- const otherDialogHasPersistedState = checkOtherDialogsHavePersistedState(persistenceKey);
807
- if (otherDialogHasPersistedState) {
808
- // Another dialog with persisted state is auto-opening - skip this one
809
- clearDraft();
810
- hasAutoOpenedRef.current = true;
811
- return;
812
- }
813
- }
814
- // Clear stale locks
815
- if (lockAge > 2000) {
816
- sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
817
- }
818
- }
819
-
820
- // Check if dialog with same key is already open in DOM (synchronous check)
821
- const existingDialog = document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
822
- if (existingDialog && existingDialog !== dialogRef.current && existingDialog !== internalRef.current) {
823
- hasAutoOpenedRef.current = true;
824
- return;
825
- }
826
-
827
- // Set lock and mark as auto-opened BEFORE calling onOpenChange
828
- sessionStorage.setItem(AUTO_OPEN_LOCK_KEY, String(now));
829
- hasAutoOpenedRef.current = true;
830
- wasManuallyOpenedRef.current = false;
831
-
832
- console.log('[Dialog] 🔄 AUTO-OPEN', { persistenceKey });
833
-
834
- // Use small delay to prevent visual flash
835
- const timeoutId = setTimeout(() => {
836
- // Double-check: if dialog is still closed and no other instance opened it
837
- const stillClosed = !open;
838
- const noOtherInstance = !document.querySelector(`dialog[data-persistence-key="${persistenceKey}"][open]`);
839
-
840
- if (stillClosed && noOtherInstance) {
841
- sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
842
- onOpenChange(true);
843
- } else {
844
- sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
845
- }
846
- }, 75);
847
-
848
- return () => {
849
- clearTimeout(timeoutId);
850
- sessionStorage.removeItem(AUTO_OPEN_LOCK_KEY);
851
- };
852
- }
853
- }, [persistenceKey, persistOpenState, persistedOpen, open, onOpenChange, wasRestored, clearDraft]);
854
-
855
- // When this dialog auto-opens, clear persisted state of all other dialogs
856
- // This prevents multiple dialogs from being restored simultaneously
857
- useEffect(() => {
858
- if (!persistenceKey || !persistOpenState || !open || !hasAutoOpenedRef.current) {
859
- return;
860
- }
861
-
862
- // Only run once when dialog first auto-opens
863
- if (hasCleanedUpOtherDialogsRef.current) {
864
- return;
865
- }
866
-
867
- // Clear all other dialog persisted states from sessionStorage
868
- // AND close any other dialogs that are currently open in the DOM
869
- // This ensures only the first auto-opened dialog remains open
870
- try {
871
- const keysToRemove: string[] = [];
872
- for (let i = 0; i < sessionStorage.length; i++) {
873
- const key = sessionStorage.key(i);
874
- if (key && key.startsWith('pace-core:draft:dialog:') && key.endsWith(':open')) {
875
- // Don't clear this dialog's own state
876
- if (key !== `pace-core:draft:${persistenceKey}:open`) {
877
- keysToRemove.push(key);
878
- }
879
- }
880
- }
881
-
882
- if (keysToRemove.length > 0) {
883
- console.log('[Dialog Persistence] Clearing other dialog persisted states:', keysToRemove);
884
- keysToRemove.forEach(key => sessionStorage.removeItem(key));
885
- }
886
-
887
- // Also close any other dialogs that are currently open in the DOM AND have persisted state
888
- // This prevents dialogs with persisted state from being hidden behind this one
889
- // We only close dialogs that have persisted state, not dialogs opened by app code
890
- // We identify dialogs with persistence using a data attribute
891
- const timeoutId = setTimeout(() => {
892
- // Guard against test environment teardown
893
- if (typeof document === 'undefined' || typeof sessionStorage === 'undefined') {
894
- return;
895
- }
896
-
897
- const otherOpenDialogs = document.querySelectorAll('dialog[open][role="dialog"]');
898
- const currentDialog = dialogRef.current || internalRef.current;
899
- if (otherOpenDialogs.length > 0 && currentDialog) {
900
- let closedCount = 0;
901
- otherOpenDialogs.forEach((dialog) => {
902
- // Don't close this dialog
903
- const dialogElement = dialog as HTMLDialogElement;
904
- if (dialogElement !== currentDialog) {
905
- // Check if this dialog has a data-persistence-key attribute
906
- // This indicates it was auto-opened from persistence
907
- const dialogPersistenceKey = dialogElement.getAttribute('data-persistence-key');
908
- if (dialogPersistenceKey && dialogPersistenceKey !== persistenceKey) {
909
- // Check if this dialog's persisted state is true
910
- let hasPersistedState = false;
911
- try {
912
- const key = `pace-core:draft:${dialogPersistenceKey}:open`;
913
- const stored = sessionStorage.getItem(key);
914
- if (stored) {
915
- const parsed = JSON.parse(stored);
916
- if (parsed && parsed.data === true) {
917
- hasPersistedState = true;
918
- }
919
- }
920
- } catch {
921
- // Invalid data - skip
922
- }
923
-
924
- // Only close if this dialog has persisted state (was auto-opened)
925
- if (hasPersistedState) {
926
- console.log('[Dialog Persistence] Closing other dialog with persisted state:', dialogPersistenceKey);
927
- dialogElement.close();
928
- closedCount++;
929
- }
930
- }
931
- // If dialog doesn't have data-persistence-key, it was opened by app code - don't close it
932
- }
933
- });
934
- if (closedCount > 0) {
935
- console.log('[Dialog Persistence] Closed', closedCount, 'other dialog(s) with persisted state');
936
- }
937
- }
938
- }, 100);
939
-
940
- hasCleanedUpOtherDialogsRef.current = true;
941
-
942
- // Also clear the auto-open lock
943
- if (typeof sessionStorage !== 'undefined') {
944
- sessionStorage.removeItem('pace-core:dialog:auto-open-lock');
945
- }
946
-
947
- // Cleanup timeout on unmount or dependency change
948
- return () => {
949
- clearTimeout(timeoutId);
950
- };
951
- } catch (error) {
952
- console.warn('[Dialog Persistence] Failed to clear other dialog states:', error);
953
- }
954
- }, [open, persistenceKey, persistOpenState]);
955
-
956
- // When dialog closes (user action), immediately clear persisted state
957
- // This prevents the dialog from auto-opening again after user explicitly closed it
958
- useEffect(() => {
959
- if (!persistenceKey || !persistOpenState) {
960
- return;
961
- }
962
-
963
- if (!hasInitializedRef.current) {
964
- return;
965
- }
966
-
967
- // If dialog is closed and user closed it, clear persisted state immediately
968
- if (!open && wasClosedByUserRef.current) {
969
- clearDraft();
970
- wasClosedByUserRef.current = false;
971
- }
972
- }, [open, persistenceKey, persistOpenState, clearDraft]);
973
-
974
- // Check lock BEFORE allowing dialog to open (synchronous check)
975
- // This prevents React from even trying to open if another dialog is open
976
- useEffect(() => {
977
- if (!open) {
978
- return;
979
- }
980
-
981
- // Synchronously check if we can acquire the lock
982
- const lockAcquired = acquireDialogLock(persistenceKey);
983
- if (!lockAcquired) {
984
- // Another dialog is open - prevent this one from opening
985
- console.warn('[Dialog] ⚠️ Cannot open - another dialog holds the lock', {
986
- persistenceKey,
987
- });
988
- // Immediately close this dialog's React state
989
- onOpenChange?.(false);
990
- return;
991
- }
992
-
993
- // Lock acquired successfully - dialog can proceed to open
994
- }, [open, persistenceKey, onOpenChange]);
995
-
996
- // Track when dialog closes via onOpenChange to mark as closed by user
997
- // This handles Cancel buttons and other programmatic closes
998
- const previousOpenRef = useRef(open);
999
- useEffect(() => {
1000
- // If dialog was open and is now closed, and it wasn't auto-opened, mark as closed by user
1001
- if (previousOpenRef.current === true && open === false && hasInitializedRef.current) {
1002
- // Only mark as closed by user if it wasn't an auto-open scenario
1003
- // Auto-open sets hasAutoOpenedRef before calling onOpenChange, so we can detect it
1004
- if (!hasAutoOpenedRef.current || wasManuallyOpenedRef.current) {
1005
- // Dialog was manually opened and then closed - mark as closed by user
1006
- wasClosedByUserRef.current = true;
1007
- }
1008
- }
1009
- previousOpenRef.current = open;
1010
- }, [open]);
1011
-
1012
- // Persist open state changes
1013
- useEffect(() => {
1014
- if (!persistenceKey || !persistOpenState) {
1015
- return;
1016
- }
1017
-
1018
- // Only persist after initial mount check is complete
1019
- // This prevents overwriting the persisted state before auto-open can read it
1020
- if (!hasInitializedRef.current) {
1021
- return;
1022
- }
406
+ } = props;
407
+
408
+ const { open, onOpenChange, dialogRef, titleId, descriptionId } = useDialogContext();
409
+ const setMarkClosedByUser = React.useContext(DialogMarkClosedContext);
410
+
411
+ const location = useLocation();
412
+ const auth = useUnifiedAuth();
413
+ const userId = auth.user?.id || null;
414
+
415
+ const logger = createLogger('Dialog');
416
+
417
+ const persistenceKey = useMemo(() => {
418
+ if (!persistOpenState) return null;
419
+ if (!userId) return null;
420
+ return deriveDialogKey({ title, description }, location, userId);
421
+ }, [title, description, location, userId, persistOpenState]);
422
+
423
+ const internalRef = useRef<HTMLDialogElement>(null);
424
+
425
+ const { lockAcquired, markClosedByUser, clearDraft } = useDialogPersistence({
426
+ open,
427
+ onOpenChange,
428
+ persistenceKey,
429
+ persistOpenState,
430
+ userId,
431
+ dialogRef,
432
+ internalRef,
433
+ setMarkClosedByUser,
434
+ logger,
435
+ });
1023
436
 
1024
- // Persisting open state (logging removed for performance)
1025
-
1026
- let logTimeoutId: ReturnType<typeof setTimeout> | null = null;
1027
-
1028
- // Only persist when dialog is open
1029
- if (open) {
1030
- // Reset the flag when opening
1031
- wasClosedByUserRef.current = false;
1032
- // If dialog is manually opened (not via auto-open), mark it so auto-open doesn't interfere
1033
- // This prevents auto-open from trying to open an already-open dialog
1034
- // We check if hasAutoOpenedRef is false to determine if this is a manual open
1035
- // (auto-open sets hasAutoOpenedRef to true before calling onOpenChange)
1036
- if (!hasAutoOpenedRef.current) {
1037
- // Mark as manually opened to prevent auto-open from interfering
1038
- wasManuallyOpenedRef.current = true;
1039
- // Also mark as "opened" to prevent auto-open from trying to open it again
1040
- hasAutoOpenedRef.current = true;
1041
- }
1042
- setPersistedOpen(true);
1043
- } else {
1044
- // Only clear draft if user explicitly closed (not if it was never opened or auto-opened then closed)
1045
- if (wasClosedByUserRef.current) {
1046
- clearDraft();
1047
- wasClosedByUserRef.current = false;
1048
- // Reset manual open flag when dialog is closed
1049
- wasManuallyOpenedRef.current = false;
1050
- }
1051
- }
1052
-
1053
- // Cleanup timeout on unmount or dependency change
1054
- return () => {
1055
- if (logTimeoutId) {
1056
- clearTimeout(logTimeoutId);
1057
- }
1058
- };
1059
- }, [open, persistenceKey, persistOpenState, setPersistedOpen, clearDraft]);
1060
-
1061
- // Note: We do NOT automatically clear the draft when dialog closes
1062
- // The draft should only be cleared on explicit user actions (e.g., form submit success)
1063
- // This allows the dialog to restore its state after tab switches
1064
- const internalRef = useRef<HTMLDialogElement>(null);
1065
-
1066
- // Use the dialogRef from context, or fall back to internal ref or forwarded ref
1067
- const actualDialogRef = dialogRef.current ? dialogRef : (ref ? (ref as React.RefObject<HTMLDialogElement>) : internalRef);
1068
-
1069
- // Default to 80% viewport height if no height constraint is provided
1070
- // This allows the dialog to grow to 80% before enabling scrolling
1071
- const effectiveMaxHeightPercent = maxHeightPercent ?? (maxHeight ? undefined : 80);
1072
-
1073
- // Determine if we have a height constraint that requires flex layout
1074
- const hasHeightConstraint = Boolean(effectiveMaxHeightPercent || maxHeight);
1075
-
1076
- const smartDimensions = useSmartDimensions({
1077
- maxHeightPercent: effectiveMaxHeightPercent,
437
+ const { sizeClass, mergedStyle, hasHeightConstraint } = useDialogDimensions({
438
+ size,
439
+ maxHeightPercent,
1078
440
  maxWidthPercent,
1079
- maxHeight,
441
+ maxHeight,
1080
442
  maxWidth,
1081
443
  minHeight,
1082
444
  minWidth,
1083
- enableScrolling
445
+ enableScrolling,
446
+ style,
1084
447
  });
1085
448
 
1086
449
  // Focus trap
@@ -1091,260 +454,114 @@ const DialogContent = React.forwardRef<HTMLDialogElement, DialogContentProps>(
1091
454
  onEscape: preventCloseOnEscape ? undefined : () => onOpenChange(false),
1092
455
  });
1093
456
 
1094
- // Merge refs
1095
- const mergedRef = useCallback((node: HTMLDialogElement | null) => {
1096
- // Set context dialog ref
1097
- if (dialogRef && 'current' in dialogRef) {
1098
- (dialogRef as React.MutableRefObject<HTMLDialogElement | null>).current = node;
1099
- }
1100
- // Set internal ref
1101
- if (internalRef && 'current' in internalRef) {
1102
- internalRef.current = node;
1103
- }
1104
- // Set focus trap container ref
1105
- if (containerRef && 'current' in containerRef) {
1106
- (containerRef as React.MutableRefObject<HTMLElement | null>).current = node;
1107
- }
1108
- // Handle forwarded ref
1109
- if (typeof ref === 'function') {
1110
- ref(node);
1111
- } else if (ref && 'current' in ref) {
1112
- (ref as React.MutableRefObject<HTMLDialogElement | null>).current = node;
1113
- }
1114
- }, [dialogRef, containerRef, ref]);
1115
-
1116
- // Handle dialog open/close
1117
- useEffect(() => {
1118
- const dialog = dialogRef.current || internalRef.current;
1119
- if (!dialog) return;
1120
-
1121
- if (open) {
1122
- // Log all dialogs in DOM before opening
1123
- const allDialogsBefore = document.querySelectorAll('dialog[role="dialog"]');
1124
- const dialogsBefore = Array.from(allDialogsBefore).map((d) => {
1125
- const dialogEl = d as HTMLDialogElement;
1126
- return {
1127
- persistenceKey: dialogEl.getAttribute('data-persistence-key') || 'NO-KEY',
1128
- open: dialogEl.open,
1129
- isCurrent: d === dialog,
1130
- };
1131
- });
1132
- console.log('[Dialog] 🟢 OPENING', {
1133
- persistenceKey,
1134
- dialogsInDOM: dialogsBefore,
1135
- totalDialogs: allDialogsBefore.length,
1136
- });
1137
-
1138
- // Use requestAnimationFrame to ensure DOM is ready
1139
- // Lock was already checked in the earlier useEffect, so we can proceed
1140
- requestAnimationFrame(() => {
1141
- if (dialog && open) {
1142
- // Before opening, close any other open dialogs (safety check)
1143
- const allDialogs = document.querySelectorAll('dialog[role="dialog"]');
1144
- allDialogs.forEach((d) => {
1145
- const dialogEl = d as HTMLDialogElement;
1146
- if (dialogEl !== dialog && dialogEl.open) {
1147
- dialogEl.setAttribute('data-duplicate-cleanup', 'true');
1148
- dialogEl.close();
1149
- }
1150
- });
1151
-
1152
- console.log('[Dialog] ✅ showModal() called', { persistenceKey });
1153
- dialog.showModal();
1154
- }
1155
- });
1156
- } else {
1157
- // Close dialog before it's removed from DOM
1158
- if (dialog.open) {
1159
- console.log('[Dialog] 🔴 CLOSING', { persistenceKey });
1160
- dialog.close();
1161
- // Release the lock
1162
- releaseDialogLock(persistenceKey);
1163
-
1164
- // After closing, check if any other dialogs with persistence are trying to open
1165
- // Only close dialogs that have persistence (data-persistence-key attribute)
1166
- // Non-persistent dialogs should be left alone
1167
- setTimeout(() => {
1168
- const allDialogs = document.querySelectorAll('dialog[role="dialog"]');
1169
- allDialogs.forEach((d) => {
1170
- const dialogEl = d as HTMLDialogElement;
1171
- if (dialogEl !== dialog && dialogEl.open) {
1172
- const otherPersistenceKey = dialogEl.getAttribute('data-persistence-key');
1173
- // Only close dialogs that have persistence (they might auto-open)
1174
- // Non-persistent dialogs are user-controlled and shouldn't be closed
1175
- if (otherPersistenceKey) {
1176
- console.warn('[Dialog] 🗑️ Closing other persisted dialog after lock release:', {
1177
- persistenceKey,
1178
- otherPersistenceKey,
1179
- });
1180
- dialogEl.setAttribute('data-duplicate-cleanup', 'true');
1181
- dialogEl.close();
1182
- }
1183
- }
1184
- });
1185
- }, 50);
1186
- }
1187
- }
1188
- }, [open, persistenceKey, dialogRef]);
1189
-
1190
- // Handle close event - sync state when dialog is closed externally
1191
- // Also track when dialog is closed by user action (for persistence clearing)
1192
- useEffect(() => {
1193
- const dialog = dialogRef.current || internalRef.current;
1194
- if (!dialog) return;
1195
-
1196
- const handleClose = () => {
1197
- // Check if this close was initiated by the user (via close button)
1198
- const wasUserClosed = dialog.hasAttribute('data-user-closed');
1199
- if (wasUserClosed) {
1200
- dialog.removeAttribute('data-user-closed');
1201
- if (hasInitializedRef.current) {
1202
- wasClosedByUserRef.current = true;
1203
- }
1204
- }
1205
-
1206
- // Ignore duplicate cleanup closes
1207
- const isDuplicateCleanup = dialog.hasAttribute('data-duplicate-cleanup');
1208
- if (isDuplicateCleanup) {
1209
- dialog.removeAttribute('data-duplicate-cleanup');
1210
- return;
1211
- }
1212
-
1213
- if (!dialog.open && open) {
1214
- // Mark as closed by user if this wasn't an auto-open scenario
1215
- if (hasInitializedRef.current && !wasUserClosed) {
1216
- wasClosedByUserRef.current = true;
1217
- }
1218
- onOpenChange(false);
1219
- } else if (!dialog.open && !open && hasInitializedRef.current && wasUserClosed) {
1220
- wasClosedByUserRef.current = true;
1221
- }
1222
- };
1223
-
1224
- dialog.addEventListener('close', handleClose);
1225
- return () => {
1226
- dialog.removeEventListener('close', handleClose);
1227
- };
1228
- }, [open, onOpenChange, dialogRef]);
1229
-
1230
- // Handle cancel event (Escape or backdrop click)
1231
- useEffect(() => {
1232
- const dialog = dialogRef.current || internalRef.current;
1233
- if (!dialog) return;
1234
-
1235
- const handleCancel = (e: Event) => {
1236
- if (preventCloseOnEscape || preventCloseOnOutsideClick) {
1237
- e.preventDefault();
1238
- return;
1239
- }
1240
- // Mark as closed by user and clear persisted state
1241
- wasClosedByUserRef.current = true;
1242
- if (persistenceKey && persistOpenState && clearDraft) {
1243
- clearDraft();
1244
- }
1245
- onOpenChange(false);
1246
- };
1247
-
1248
- dialog.addEventListener('cancel', handleCancel);
1249
- return () => {
1250
- dialog.removeEventListener('cancel', handleCancel);
1251
- };
1252
- }, [preventCloseOnEscape, preventCloseOnOutsideClick, onOpenChange, dialogRef, persistenceKey, persistOpenState, clearDraft]);
1253
-
1254
- // Merge smart dimensions with provided style
1255
- const mergedStyle = React.useMemo(() => {
1256
- if (Object.keys(smartDimensions).length === 0) {
1257
- return style;
1258
- }
1259
-
1260
- const finalStyle: React.CSSProperties = { ...smartDimensions, ...style };
1261
-
1262
- if (!maxWidth && !maxWidthPercent) {
1263
- const { maxWidth: _, ...styleWithoutMaxWidth } = finalStyle;
1264
- return styleWithoutMaxWidth;
1265
- }
1266
-
1267
- return finalStyle;
1268
- }, [smartDimensions, style, maxWidth, maxWidthPercent]);
1269
-
1270
- // Track if lock has been acquired (set by useEffect when open becomes true)
1271
- const [lockAcquired, setLockAcquired] = React.useState(false);
1272
-
1273
- // Check lock BEFORE allowing dialog to open (synchronous check)
1274
- // This prevents React from even trying to open if another dialog is open
1275
- useEffect(() => {
1276
- if (!open) {
1277
- setLockAcquired(false);
1278
- return;
1279
- }
457
+ // Merge refs (avoids type assertions; mergeRefs handles RefObject and callback refs)
458
+ const mergedRef = useMemo(
459
+ () => mergeRefs(dialogRef, internalRef, containerRef, ref),
460
+ [dialogRef, containerRef, ref]
461
+ );
1280
462
 
1281
- // Synchronously check if we can acquire the lock
1282
- const acquired = acquireDialogLock(persistenceKey);
1283
- setLockAcquired(acquired);
1284
-
1285
- if (!acquired) {
1286
- // Another dialog is open - prevent this one from opening
1287
- console.warn('[Dialog] ⚠️ Cannot open - another dialog holds the lock', {
1288
- persistenceKey,
1289
- });
1290
- // Immediately close this dialog's React state
1291
- onOpenChange?.(false);
1292
- return;
1293
- }
1294
-
1295
- // Lock acquired successfully - dialog can proceed to open
1296
- }, [open, persistenceKey, onOpenChange]);
463
+ useDialogLifecycle({
464
+ dialogRef,
465
+ internalRef,
466
+ open,
467
+ persistenceKey,
468
+ logger,
469
+ onOpenChange,
470
+ markClosedByUser,
471
+ preventCloseOnEscape,
472
+ preventCloseOnOutsideClick,
473
+ persistOpenState,
474
+ clearDraft,
475
+ });
1297
476
 
1298
- // Synchronously check if we can render (must hold lock if open)
1299
477
  const canRender = React.useMemo(() => {
1300
- if (!open) {
1301
- return true; // Can always render when closed
1302
- }
1303
- if (!persistenceKey) {
1304
- return true; // Non-persisted dialogs can always render
1305
- }
1306
- // Use the lockAcquired state which is set by the effect
478
+ if (!open) return true;
479
+ if (!persistenceKey) return true;
1307
480
  return lockAcquired;
1308
481
  }, [open, persistenceKey, lockAcquired]);
1309
482
 
483
+ return {
484
+ mergedRef,
485
+ canRender,
486
+ markClosedByUser,
487
+ sizeClass,
488
+ mergedStyle: mergedStyle ?? {},
489
+ hasHeightConstraint,
490
+ persistenceKey,
491
+ persistOpenState,
492
+ titleId,
493
+ descriptionId,
494
+ open,
495
+ title,
496
+ description,
497
+ };
498
+ }
499
+
500
+ /**
501
+ * DialogContent component
502
+ * The main content container using semantic HTML <dialog> element with enhanced features.
503
+ * Inline style exception (5-styling): viewport-based max/min dimensions from props are applied
504
+ * via the style prop; they cannot be expressed with static Tailwind and are merged with optional consumer style.
505
+ *
506
+ * @param props - Content configuration and styling
507
+ * @param ref - Forwarded ref to the dialog element
508
+ * @returns JSX.Element - The semantic dialog content with overlay and optional close button
509
+ */
510
+ const DialogContent = (React.forwardRef<HTMLDialogElement, DialogContentProps>)(
511
+ function DialogContentInner(props, ref) {
512
+ const {
513
+ className,
514
+ children,
515
+ size = 'md',
516
+ showCloseButton = true,
517
+ maxHeightPercent,
518
+ maxWidthPercent,
519
+ enableScrolling = false,
520
+ maxHeight,
521
+ maxWidth,
522
+ minHeight,
523
+ minWidth,
524
+ style: _styleProp,
525
+ title: _titleProp,
526
+ description: _descriptionProp,
527
+ persistOpenState: _persistOpenStateProp,
528
+ preventCloseOnEscape: _preventCloseOnEscape,
529
+ preventCloseOnOutsideClick: _preventCloseOnOutsideClick,
530
+ ...restProps
531
+ } = props;
532
+
533
+ const state = useDialogContentState(props, ref);
534
+
1310
535
  return (
1311
536
  <DialogPortal>
1312
- {open && canRender && (
537
+ {state.open && state.canRender && (
1313
538
  <dialog
1314
- ref={mergedRef}
539
+ ref={state.mergedRef}
1315
540
  className={cn(
1316
541
  'fixed left-[50%] top-[50%] z-[51] w-full translate-x-[-50%] translate-y-[-50%] border bg-background shadow-lg duration-200',
1317
542
  'animate-in fade-in-0 zoom-in-95 slide-in-from-left-1/2 slide-in-from-top-[48%]',
1318
543
  'sm:rounded-lg',
1319
- // Reset native dialog styles
1320
- 'm-0 p-0 max-w-none max-h-none w-auto h-auto border-0 bg-transparent outline-none',
1321
- // Apply our custom styling
544
+ 'm-0 p-0 max-w-none max-h-none border-0 bg-transparent outline-none',
545
+ (maxWidth || maxWidthPercent) ? 'w-full' : 'w-auto h-auto',
1322
546
  'border bg-background shadow-lg',
1323
- // Backdrop styling is handled via core.css only
1324
- // Only apply size classes if not using smart width
1325
- !maxWidth && !maxWidthPercent && sizeClasses[size],
1326
- // Auto size gets special handling
547
+ !maxWidth && !maxWidthPercent && state.sizeClass,
1327
548
  size === 'auto' && 'w-fit max-w-[90vw] sm:max-w-[80vw]',
1328
- // Layout classes: use flex when we have height constraints or enableScrolling is true
1329
- // Flex layout is needed for proper scrolling when height is constrained
1330
- (enableScrolling || hasHeightConstraint) ? 'flex flex-col px-6' : 'grid gap-4 p-6',
1331
- // Full screen handling
549
+ (enableScrolling || state.hasHeightConstraint) ? 'flex flex-col p-6' : 'grid p-6',
1332
550
  size === 'full' && 'sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%] left-0 top-0 translate-x-0 translate-y-0 h-full rounded-none sm:h-auto sm:rounded-lg',
1333
- // Overflow handling for scrolling mode or when height is constrained
1334
- (enableScrolling || hasHeightConstraint) && 'overflow-hidden',
551
+ (enableScrolling || state.hasHeightConstraint) && 'overflow-hidden',
1335
552
  className
1336
553
  )}
1337
- style={mergedStyle}
554
+ style={state.mergedStyle}
1338
555
  role="dialog"
1339
556
  aria-modal="true"
1340
- aria-labelledby={titleId}
1341
- aria-describedby={descriptionId}
1342
- title={title}
1343
- aria-description={description}
1344
- data-persistence-key={persistenceKey && persistOpenState ? persistenceKey : undefined}
1345
- {...props}
557
+ aria-labelledby={state.titleId}
558
+ aria-describedby={state.descriptionId}
559
+ title={state.title}
560
+ aria-description={state.description}
561
+ data-persistence-key={state.persistenceKey && state.persistOpenState ? state.persistenceKey : undefined}
562
+ {...restProps}
1346
563
  >
1347
- <DialogCloseContext.Provider value={markClosedByUser}>
564
+ <DialogCloseContext.Provider value={state.markClosedByUser}>
1348
565
  {children}
1349
566
  {showCloseButton && (
1350
567
  <DialogClose />
@@ -1373,47 +590,38 @@ export interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonE
1373
590
  */
1374
591
  const DialogClose = React.forwardRef<HTMLButtonElement, DialogCloseProps>(
1375
592
  ({ className, asChild = false, children, onClick, ...props }, ref) => {
1376
- // Call all hooks unconditionally at the top level
1377
- // Hooks must be called in the same order on every render
1378
593
  const { onOpenChange, markClosedByUser: contextMarkClosedByUser } = useDialogContext();
1379
- // Prefer DialogContext markClosedByUser (available to all components), fallback to DialogCloseContext (for backwards compatibility)
1380
594
  const dialogCloseContextValue = React.useContext(DialogCloseContext);
1381
- const markClosedByUser = contextMarkClosedByUser || dialogCloseContextValue;
1382
-
1383
- const handleClick = useCallback((e: React.MouseEvent<HTMLElement>) => {
1384
- // Mark dialog as closed by user before calling onOpenChange
1385
- // This ensures the persisted state is cleared when user clicks close button
595
+ const markClosedByUser = contextMarkClosedByUser ?? dialogCloseContextValue;
596
+
597
+ const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
1386
598
  if (markClosedByUser) {
1387
599
  markClosedByUser();
1388
600
  }
1389
-
1390
- onClick?.(e as React.MouseEvent<HTMLButtonElement>);
601
+ onClick?.(e);
1391
602
  onOpenChange(false);
1392
603
  }, [onOpenChange, markClosedByUser, onClick]);
1393
604
 
1394
605
  if (asChild && React.isValidElement(children)) {
1395
- return React.cloneElement(children as React.ReactElement<any>, {
606
+ const childElement = children as React.ReactElement<React.HTMLAttributes<HTMLButtonElement>>;
607
+ return React.cloneElement(childElement, {
1396
608
  ref,
1397
609
  onClick: handleClick,
1398
- className: cn(className, (children as any).props?.className),
610
+ className: cn(className, childElement.props?.className),
1399
611
  ...props,
1400
- });
612
+ } as React.HTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>);
1401
613
  }
1402
614
 
1403
615
  return (
1404
- <button
616
+ <IconButton
1405
617
  ref={ref}
618
+ icon={<X className="size-4" />}
619
+ aria-label="Close"
1406
620
  type="button"
1407
621
  onClick={handleClick}
1408
- className={cn(
1409
- 'absolute right-4 top-4 z-10 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none',
1410
- className
1411
- )}
622
+ className={cn('absolute right-4 top-4 z-10', className)}
1412
623
  {...props}
1413
- >
1414
- <X className="size-4" />
1415
- <span className="sr-only">Close</span>
1416
- </button>
624
+ />
1417
625
  );
1418
626
  }
1419
627
  );
@@ -1429,11 +637,7 @@ const DialogHeader = ({
1429
637
  ...props
1430
638
  }: DialogHeaderProps) => (
1431
639
  <header
1432
- className={cn(
1433
- 'flex flex-col space-y-1.5 text-center sm:text-left',
1434
- sticky ? 'sticky top-0 z-10 bg-background pt-6 pb-4 border-b' : 'py-2',
1435
- className
1436
- )}
640
+ className={cn('dialog-header', sticky && 'sticky top-0 z-10 bg-background', className)}
1437
641
  {...props}
1438
642
  />
1439
643
  );
@@ -1449,11 +653,11 @@ const DialogBody = ({
1449
653
  style,
1450
654
  htmlContent,
1451
655
  allowHtml = true,
1452
- strictSanitization = true,
1453
656
  logWarnings = false,
1454
657
  children,
1455
658
  ...props
1456
659
  }: DialogBodyProps) => {
660
+ // Inline style exception (5-styling): maxHeight and style from props; no fixed token set.
1457
661
  const mergedStyle = React.useMemo(() => {
1458
662
  return {
1459
663
  ...(maxHeight && { maxHeight }),
@@ -1467,12 +671,11 @@ const DialogBody = ({
1467
671
  }
1468
672
 
1469
673
  const result = renderSafeHtml(htmlContent, {
1470
- strict: strictSanitization,
1471
674
  logWarnings
1472
675
  });
1473
676
 
1474
677
  return result.html;
1475
- }, [htmlContent, allowHtml, strictSanitization, logWarnings]);
678
+ }, [htmlContent, allowHtml, logWarnings]);
1476
679
 
1477
680
  const hasHtmlContent = Boolean(htmlContent && allowHtml);
1478
681
 
@@ -1510,7 +713,7 @@ const DialogBody = ({
1510
713
  return (
1511
714
  <main
1512
715
  className={cn(
1513
- 'overflow-y-auto py-2',
716
+ 'overflow-y-auto',
1514
717
  // When in a flex container with height constraint, use flex properties
1515
718
  // so DialogBody takes up available space and only scrolls when content exceeds it
1516
719
  isInFlexContainer && 'flex-1 min-h-0',
@@ -1522,14 +725,14 @@ const DialogBody = ({
1522
725
  {...props}
1523
726
  >
1524
727
  {processedHtmlContent ? (
1525
- <p
728
+ <p
1526
729
  dangerouslySetInnerHTML={{ __html: processedHtmlContent }}
1527
- className="prose prose-sm max-w-none"
730
+ className="dialog-body-html-content"
1528
731
  />
1529
732
  ) : (
1530
733
  <>
1531
734
  {hasHtmlContent && !processedHtmlContent && (
1532
- <p className="text-acc-500 mb-2">
735
+ <p className="dialog-body-fallback">
1533
736
  No HTML content processed. Showing children instead.
1534
737
  </p>
1535
738
  )}
@@ -1551,11 +754,7 @@ const DialogFooter = ({
1551
754
  ...props
1552
755
  }: DialogFooterProps) => (
1553
756
  <footer
1554
- className={cn(
1555
- !className && 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
1556
- !className && (sticky ? 'sticky bottom-0 z-10 bg-background pt-4 pb-6 border-t' : 'py-2'),
1557
- className
1558
- )}
757
+ className={cn('dialog-footer', sticky && 'sticky bottom-0 z-10 bg-background', className)}
1559
758
  {...props}
1560
759
  />
1561
760
  );
@@ -1575,7 +774,6 @@ const DialogTitle = React.forwardRef<HTMLHeadingElement, DialogTitleProps>(
1575
774
  }
1576
775
 
1577
776
  const result = renderSafeHtml(htmlContent, {
1578
- strict: true,
1579
777
  logWarnings: false
1580
778
  });
1581
779
 
@@ -1614,7 +812,6 @@ const DialogDescription = React.forwardRef<HTMLParagraphElement, DialogDescripti
1614
812
  }
1615
813
 
1616
814
  const result = renderSafeHtml(htmlContent, {
1617
- strict: true,
1618
815
  logWarnings: false
1619
816
  });
1620
817