@carlonicora/nextjs-jsonapi 1.0.3 → 1.0.5

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 (515) hide show
  1. package/dist/{AbstractService-BKlpJA61.d.mts → AbstractService-B2n_JdiC.d.mts} +1 -1
  2. package/dist/{AbstractService-D9eSVKNa.d.ts → AbstractService-DtQTYovo.d.ts} +1 -1
  3. package/dist/{content.interface-Dg2lt_An.d.mts → AuthComponent-CPLvEerw.d.mts} +11 -15
  4. package/dist/{content.interface-BhyAiOFq.d.ts → AuthComponent-m6Qp4Hz6.d.ts} +11 -15
  5. package/dist/{BlockNoteEditor-UVO3VZZE.mjs → BlockNoteEditor-BLVXQPXV.mjs} +14 -18
  6. package/dist/{BlockNoteEditor-UVO3VZZE.mjs.map → BlockNoteEditor-BLVXQPXV.mjs.map} +1 -1
  7. package/dist/{BlockNoteEditor-VFWG6LXI.js → BlockNoteEditor-ZTDHULFT.js} +15 -19
  8. package/dist/BlockNoteEditor-ZTDHULFT.js.map +1 -0
  9. package/dist/JsonApiRequest-O7BGUMFO.mjs +23 -0
  10. package/dist/JsonApiRequest-VARLNKAF.js +23 -0
  11. package/dist/JsonApiRequest-VARLNKAF.js.map +1 -0
  12. package/dist/chunk-2LM6LCJW.mjs +1 -0
  13. package/dist/chunk-3APORDYP.mjs +7783 -0
  14. package/dist/chunk-3APORDYP.mjs.map +1 -0
  15. package/dist/{chunk-TMVHSY3Y.js → chunk-5ZEADNNP.js} +36 -17
  16. package/dist/chunk-5ZEADNNP.js.map +1 -0
  17. package/dist/{chunk-ECDTZBYO.mjs → chunk-74F6BBHH.mjs} +21 -2
  18. package/dist/chunk-74F6BBHH.mjs.map +1 -0
  19. package/dist/{chunk-GYWPEPOH.mjs → chunk-7C5RAEBO.mjs} +72 -68
  20. package/dist/chunk-7C5RAEBO.mjs.map +1 -0
  21. package/dist/chunk-A5DDIABK.js +1 -0
  22. package/dist/{chunk-TEGF6ZWG.js → chunk-AGAJMJ4T.js} +47 -9
  23. package/dist/chunk-AGAJMJ4T.js.map +1 -0
  24. package/dist/{chunk-CXQOWQSY.js → chunk-AYHKQWHH.js} +15 -2
  25. package/dist/chunk-AYHKQWHH.js.map +1 -0
  26. package/dist/{chunk-I2REI7OA.js → chunk-HMHGLXWC.js} +33 -15
  27. package/dist/chunk-HMHGLXWC.js.map +1 -0
  28. package/dist/chunk-IWFGEPAA.mjs +1 -0
  29. package/dist/chunk-JC3WJK65.js +1 -0
  30. package/dist/{chunk-L6EQEAXU.mjs → chunk-PYF2U6WG.mjs} +25 -7
  31. package/dist/chunk-PYF2U6WG.mjs.map +1 -0
  32. package/dist/{chunk-YDVTFM7X.mjs → chunk-RBIVEH2K.mjs} +42 -4
  33. package/dist/chunk-RBIVEH2K.mjs.map +1 -0
  34. package/dist/{chunk-V2JJPI7N.js → chunk-RZO2LOW4.js} +237 -233
  35. package/dist/chunk-RZO2LOW4.js.map +1 -0
  36. package/dist/{chunk-X4BIHJ2B.mjs → chunk-SM63SZCP.mjs} +15 -2
  37. package/dist/chunk-SM63SZCP.mjs.map +1 -0
  38. package/dist/chunk-WEC4YMOS.js +7783 -0
  39. package/dist/chunk-WEC4YMOS.js.map +1 -0
  40. package/dist/client/index.d.mts +21 -2
  41. package/dist/client/index.d.ts +21 -2
  42. package/dist/client/index.js +18 -245
  43. package/dist/client/index.js.map +1 -1
  44. package/dist/client/index.mjs +28 -255
  45. package/dist/client/index.mjs.map +1 -1
  46. package/dist/components/index.d.mts +293 -8
  47. package/dist/components/index.d.ts +293 -8
  48. package/dist/components/index.js +78 -2323
  49. package/dist/components/index.js.map +1 -1
  50. package/dist/components/index.mjs +172 -2417
  51. package/dist/components/index.mjs.map +1 -1
  52. package/dist/{config-hXufftVS.d.ts → config-BmnK65TD.d.mts} +1 -0
  53. package/dist/{config-hXufftVS.d.mts → config-BmnK65TD.d.ts} +1 -0
  54. package/dist/config-DQeAo9Kf.d.mts +49 -0
  55. package/dist/config-DQeAo9Kf.d.ts +49 -0
  56. package/dist/contexts/index.d.mts +109 -21
  57. package/dist/contexts/index.d.ts +109 -21
  58. package/dist/contexts/index.js +39 -7
  59. package/dist/contexts/index.js.map +1 -1
  60. package/dist/contexts/index.mjs +40 -8
  61. package/dist/core/index.d.mts +3 -4
  62. package/dist/core/index.d.ts +3 -4
  63. package/dist/core/index.js +3 -7
  64. package/dist/core/index.js.map +1 -1
  65. package/dist/core/index.mjs +4 -8
  66. package/dist/{d3.link.interface-QMdB22bC.d.mts → d3.link.interface-ClC4Irqp.d.mts} +2 -1
  67. package/dist/{d3.link.interface-QMdB22bC.d.ts → d3.link.interface-ClC4Irqp.d.ts} +2 -1
  68. package/dist/features/index.d.mts +17 -86
  69. package/dist/features/index.d.ts +17 -86
  70. package/dist/features/index.js +7 -16
  71. package/dist/features/index.js.map +1 -1
  72. package/dist/features/index.mjs +10 -19
  73. package/dist/hooks/index.d.mts +18 -43
  74. package/dist/hooks/index.d.ts +18 -43
  75. package/dist/hooks/index.js +20 -7
  76. package/dist/hooks/index.js.map +1 -1
  77. package/dist/hooks/index.mjs +19 -6
  78. package/dist/index.d.mts +10 -6
  79. package/dist/index.d.ts +10 -6
  80. package/dist/index.js +13 -10
  81. package/dist/index.js.map +1 -1
  82. package/dist/index.mjs +22 -19
  83. package/dist/interfaces/index.d.mts +2 -1
  84. package/dist/interfaces/index.d.ts +2 -1
  85. package/dist/notification.interface-BBgMUdLR.d.mts +14 -0
  86. package/dist/notification.interface-gyvT-Z2F.d.ts +14 -0
  87. package/dist/permissions/index.d.mts +2 -3
  88. package/dist/permissions/index.d.ts +2 -3
  89. package/dist/server/index.d.mts +38 -18
  90. package/dist/server/index.d.ts +38 -18
  91. package/dist/server/index.js +70 -2
  92. package/dist/server/index.js.map +1 -1
  93. package/dist/server/index.mjs +68 -0
  94. package/dist/server/index.mjs.map +1 -1
  95. package/dist/types-BUAlgqqh.d.ts +39 -0
  96. package/dist/{types-DluCaP1I.d.ts → types-Bl61ob-7.d.mts} +19 -2
  97. package/dist/{types-lQVA8d_P.d.mts → types-Bl61ob-7.d.ts} +19 -2
  98. package/dist/types-iVdVY7ba.d.mts +39 -0
  99. package/dist/useSocket-Cn7fB_B1.d.mts +25 -0
  100. package/dist/useSocket-DzMKRKCA.d.ts +25 -0
  101. package/dist/user.fields-CbdObSmS.d.mts +18 -0
  102. package/dist/user.fields-CbdObSmS.d.ts +18 -0
  103. package/dist/utils/index.d.mts +1 -2
  104. package/dist/utils/index.d.ts +1 -2
  105. package/package.json +6 -3
  106. package/src/atoms/index.ts +1 -0
  107. package/src/atoms/recentPagesAtom.ts +10 -0
  108. package/src/client/context/JsonApiContext.ts +61 -0
  109. package/src/client/context/JsonApiProvider.tsx +27 -0
  110. package/src/client/context/index.ts +2 -0
  111. package/src/client/hooks/index.ts +3 -0
  112. package/src/client/hooks/useJsonApiGet.ts +188 -0
  113. package/src/client/hooks/useJsonApiMutation.ts +193 -0
  114. package/src/client/hooks/useRehydration.ts +47 -0
  115. package/src/client/index.ts +24 -0
  116. package/src/client/request.ts +97 -0
  117. package/src/client/token.ts +10 -0
  118. package/src/components/containers/PageContainer.tsx +15 -0
  119. package/src/components/containers/ReactMarkdownContainer.tsx +119 -0
  120. package/src/components/containers/TabsContainer.tsx +93 -0
  121. package/src/components/containers/index.ts +3 -0
  122. package/src/components/contents/AttributeElement.tsx +20 -0
  123. package/src/components/contents/index.ts +1 -0
  124. package/src/components/details/AllowedUsersDetails.tsx +23 -0
  125. package/src/components/details/index.ts +1 -0
  126. package/src/components/editors/BlockNoteDiffInlineContent.tsx +152 -0
  127. package/src/components/editors/BlockNoteEditor.tsx +404 -0
  128. package/src/components/editors/BlockNoteEditorContainer.tsx +13 -0
  129. package/src/components/editors/BlockNoteEditorFormattingToolbar.tsx +38 -0
  130. package/src/components/editors/index.ts +1 -0
  131. package/src/components/errors/ErrorDetails.tsx +41 -0
  132. package/src/components/errors/errorToast.ts +9 -0
  133. package/src/components/errors/index.ts +2 -0
  134. package/src/components/forms/CommonAssociationForm.tsx +162 -0
  135. package/src/components/forms/CommonDeleter.tsx +94 -0
  136. package/src/components/forms/CommonEditorButtons.tsx +30 -0
  137. package/src/components/forms/CommonEditorHeader.tsx +35 -0
  138. package/src/components/forms/CommonEditorTrigger.tsx +26 -0
  139. package/src/components/forms/DatePickerPopover.tsx +219 -0
  140. package/src/components/forms/DateRangeSelector.tsx +110 -0
  141. package/src/components/forms/FileUploader.tsx +324 -0
  142. package/src/components/forms/FormCheckbox.tsx +66 -0
  143. package/src/components/forms/FormContainerGeneric.tsx +39 -0
  144. package/src/components/forms/FormDate.tsx +247 -0
  145. package/src/components/forms/FormDateTime.tsx +231 -0
  146. package/src/components/forms/FormInput.tsx +110 -0
  147. package/src/components/forms/FormPassword.tsx +54 -0
  148. package/src/components/forms/FormPlaceAutocomplete.tsx +286 -0
  149. package/src/components/forms/FormSelect.tsx +72 -0
  150. package/src/components/forms/FormSlider.tsx +51 -0
  151. package/src/components/forms/FormSwitch.tsx +25 -0
  152. package/src/components/forms/FormTextarea.tsx +44 -0
  153. package/src/components/forms/MultiFileUploader.tsx +107 -0
  154. package/src/components/forms/PasswordInput.tsx +47 -0
  155. package/src/components/forms/index.ts +22 -0
  156. package/src/components/index.ts +16 -0
  157. package/src/components/navigations/Breadcrumb.tsx +83 -0
  158. package/src/components/navigations/ContentTitle.tsx +39 -0
  159. package/src/components/navigations/Header.tsx +27 -0
  160. package/src/components/navigations/ModeToggleSwitch.tsx +25 -0
  161. package/src/components/navigations/PageSection.tsx +64 -0
  162. package/src/components/navigations/RecentPagesNavigator.tsx +52 -0
  163. package/src/components/navigations/index.ts +6 -0
  164. package/src/components/pages/PageContainerContentDetails.tsx +76 -0
  165. package/src/components/pages/PageContentContainer.tsx +31 -0
  166. package/src/components/pages/index.ts +2 -0
  167. package/src/components/tables/ContentListTable.tsx +166 -0
  168. package/src/components/tables/ContentTableSearch.tsx +105 -0
  169. package/src/components/tables/cells/cell.component.tsx +18 -0
  170. package/src/components/tables/cells/cell.date.tsx +16 -0
  171. package/src/components/tables/cells/cell.id.tsx +27 -0
  172. package/src/components/tables/cells/cell.link.tsx +18 -0
  173. package/src/components/tables/cells/cell.text.tsx +12 -0
  174. package/src/components/tables/cells/cell.url.tsx +13 -0
  175. package/src/components/tables/cells/index.ts +5 -0
  176. package/src/components/tables/index.ts +3 -0
  177. package/src/contexts/CommonContext.tsx +52 -0
  178. package/src/contexts/SharedContext.tsx +37 -0
  179. package/src/contexts/SocketContext.tsx +65 -0
  180. package/src/contexts/index.ts +7 -0
  181. package/src/core/abstracts/AbstractApiData.ts +138 -0
  182. package/src/core/abstracts/AbstractService.ts +263 -0
  183. package/src/core/abstracts/index.ts +2 -0
  184. package/src/core/endpoint/EndpointCreator.ts +97 -0
  185. package/src/core/endpoint/index.ts +1 -0
  186. package/src/core/factories/JsonApiDataFactory.ts +12 -0
  187. package/src/core/factories/RehydrationFactory.ts +30 -0
  188. package/src/core/factories/index.ts +2 -0
  189. package/src/core/fields/FieldSelector.ts +15 -0
  190. package/src/core/fields/index.ts +1 -0
  191. package/src/core/index.ts +20 -0
  192. package/src/core/interfaces/ApiData.ts +8 -0
  193. package/src/core/interfaces/ApiDataInterface.ts +15 -0
  194. package/src/core/interfaces/ApiRequestDataTypeInterface.ts +14 -0
  195. package/src/core/interfaces/ApiResponseInterface.ts +17 -0
  196. package/src/core/interfaces/JsonApiHydratedDataInterface.ts +5 -0
  197. package/src/core/interfaces/index.ts +5 -0
  198. package/{dist/chunk-DO2HLAZO.js → src/core/registry/DataClassRegistry.ts} +20 -17
  199. package/src/core/registry/ModuleRegistrar.ts +43 -0
  200. package/src/core/registry/ModuleRegistry.ts +64 -0
  201. package/src/core/registry/index.ts +3 -0
  202. package/src/core/utils/index.ts +2 -0
  203. package/src/core/utils/rehydrate.ts +24 -0
  204. package/src/core/utils/translateResponse.ts +125 -0
  205. package/src/features/auth/auth.module.ts +9 -0
  206. package/src/features/auth/components/containers/AuthContainer.tsx +32 -0
  207. package/src/features/auth/components/containers/index.ts +1 -0
  208. package/src/features/auth/components/details/LandingComponent.tsx +39 -0
  209. package/src/features/auth/components/details/index.ts +1 -0
  210. package/src/features/auth/components/forms/AcceptInvitation.tsx +136 -0
  211. package/src/features/auth/components/forms/ActivateAccount.tsx +75 -0
  212. package/src/features/auth/components/forms/Cookies.tsx +32 -0
  213. package/src/features/auth/components/forms/ForgotPassword.tsx +108 -0
  214. package/src/features/auth/components/forms/Login.tsx +118 -0
  215. package/src/features/auth/components/forms/Logout.tsx +19 -0
  216. package/src/features/auth/components/forms/RefreshUser.tsx +39 -0
  217. package/src/features/auth/components/forms/Register.tsx +150 -0
  218. package/src/features/auth/components/forms/ResetPassword.tsx +126 -0
  219. package/src/features/auth/components/forms/index.ts +9 -0
  220. package/src/features/auth/components/index.ts +3 -0
  221. package/src/features/auth/config.ts +57 -0
  222. package/src/features/auth/contexts/AuthContext.tsx +77 -0
  223. package/src/features/auth/contexts/index.ts +1 -0
  224. package/src/features/auth/data/auth.interface.ts +31 -0
  225. package/src/features/auth/data/auth.service.ts +159 -0
  226. package/src/features/auth/data/auth.ts +54 -0
  227. package/src/features/auth/data/index.ts +3 -0
  228. package/src/features/auth/enums/AuthComponent.ts +9 -0
  229. package/src/features/auth/enums/index.ts +1 -0
  230. package/src/features/auth/index.ts +4 -0
  231. package/src/features/auth/utils/AuthCookies.ts +134 -0
  232. package/src/features/auth/utils/index.ts +1 -0
  233. package/src/features/company/company.module.ts +10 -0
  234. package/src/features/company/components/containers/AdminCompanyContainer.tsx +26 -0
  235. package/src/features/company/components/containers/CompanyContainer.tsx +17 -0
  236. package/src/features/company/components/containers/index.ts +2 -0
  237. package/src/features/company/components/details/CompanyDetails.tsx +26 -0
  238. package/src/features/company/components/details/index.ts +1 -0
  239. package/src/features/company/components/forms/CompanyConfigurationEditor.tsx +151 -0
  240. package/src/features/company/components/forms/CompanyConfigurationSecurityForm.tsx +97 -0
  241. package/src/features/company/components/forms/CompanyDeleter.tsx +121 -0
  242. package/src/features/company/components/forms/CompanyEditor.tsx +245 -0
  243. package/src/features/company/components/forms/CompanyLicense.tsx +213 -0
  244. package/src/features/company/components/forms/index.ts +5 -0
  245. package/src/features/company/components/index.ts +4 -0
  246. package/src/features/company/components/lists/CompaniesList.tsx +31 -0
  247. package/src/features/company/components/lists/index.ts +1 -0
  248. package/src/features/company/contexts/CompanyContext.tsx +99 -0
  249. package/src/features/company/contexts/index.ts +0 -0
  250. package/src/features/company/data/company.fields.ts +6 -0
  251. package/src/features/company/data/company.interface.ts +28 -0
  252. package/src/features/company/data/company.service.ts +73 -0
  253. package/src/features/company/data/company.ts +104 -0
  254. package/src/features/company/data/index.ts +4 -0
  255. package/src/features/company/hooks/index.ts +1 -0
  256. package/src/features/company/hooks/useCompanyTableStructure.tsx +82 -0
  257. package/src/features/company/index.ts +2 -0
  258. package/src/features/content/content.module.ts +20 -0
  259. package/src/features/content/data/content.fields.ts +13 -0
  260. package/src/features/content/data/content.interface.ts +23 -0
  261. package/src/features/content/data/content.service.ts +75 -0
  262. package/src/features/content/data/content.ts +85 -0
  263. package/src/features/content/data/index.ts +4 -0
  264. package/src/features/content/index.ts +2 -0
  265. package/src/features/feature/components/forms/FormFeatures.tsx +150 -0
  266. package/src/features/feature/components/forms/index.ts +1 -0
  267. package/src/features/feature/components/index.ts +1 -0
  268. package/src/features/feature/data/feature.interface.ts +9 -0
  269. package/src/features/feature/data/feature.service.ts +19 -0
  270. package/src/features/feature/data/feature.ts +33 -0
  271. package/src/features/feature/data/index.ts +3 -0
  272. package/src/features/feature/feature.module.ts +10 -0
  273. package/src/features/feature/index.ts +2 -0
  274. package/src/features/index.ts +12 -0
  275. package/src/features/module/data/index.ts +2 -0
  276. package/src/features/module/data/module.interface.ts +12 -0
  277. package/src/features/module/data/module.ts +42 -0
  278. package/src/features/module/index.ts +2 -0
  279. package/src/features/module/module.module.ts +10 -0
  280. package/src/features/notification/components/common/NotificationErrorBoundary.tsx +51 -0
  281. package/src/features/notification/components/common/index.ts +1 -0
  282. package/src/features/notification/components/containers/NotificationsListContainer.tsx +44 -0
  283. package/src/features/notification/components/containers/index.ts +1 -0
  284. package/src/features/notification/components/index.ts +5 -0
  285. package/src/features/notification/components/lists/NotificationsList.tsx +129 -0
  286. package/src/features/notification/components/lists/index.ts +1 -0
  287. package/src/features/notification/components/modals/NotificationModal.tsx +220 -0
  288. package/src/features/notification/components/modals/index.ts +1 -0
  289. package/src/features/notification/components/notifications/Notification.tsx +120 -0
  290. package/src/features/notification/components/notifications/PushNotificationProvider.tsx +9 -0
  291. package/src/features/notification/components/notifications/index.ts +2 -0
  292. package/src/features/notification/contexts/NotificationContext.tsx +187 -0
  293. package/src/features/notification/contexts/index.ts +1 -0
  294. package/src/features/notification/data/index.ts +4 -0
  295. package/src/features/notification/data/notification.fields.ts +8 -0
  296. package/src/features/notification/data/notification.interface.ts +14 -0
  297. package/src/features/notification/data/notification.service.ts +34 -0
  298. package/src/features/notification/data/notification.ts +51 -0
  299. package/src/features/notification/index.ts +2 -0
  300. package/src/features/notification/notification.module.ts +10 -0
  301. package/src/features/push/data/index.ts +3 -0
  302. package/src/features/push/data/push.interface.ts +8 -0
  303. package/src/features/push/data/push.service.ts +17 -0
  304. package/src/features/push/data/push.ts +18 -0
  305. package/src/features/push/index.ts +2 -0
  306. package/src/features/push/push.module.ts +10 -0
  307. package/src/features/role/components/containers/RoleContainer.tsx +18 -0
  308. package/src/features/role/components/containers/index.ts +1 -0
  309. package/src/features/role/components/details/RoleDetails.tsx +21 -0
  310. package/src/features/role/components/details/index.ts +1 -0
  311. package/src/features/role/components/forms/FormRoles.tsx +82 -0
  312. package/src/features/role/components/forms/RemoveUserFromRole.tsx +108 -0
  313. package/src/features/role/components/forms/UserRoleAdd.tsx +128 -0
  314. package/src/features/role/components/forms/index.ts +3 -0
  315. package/src/features/role/components/index.ts +4 -0
  316. package/src/features/role/components/lists/RolesList.tsx +27 -0
  317. package/src/features/role/components/lists/UserRolesList.tsx +31 -0
  318. package/src/features/role/components/lists/index.ts +2 -0
  319. package/src/features/role/contexts/RoleContext.tsx +84 -0
  320. package/src/features/role/contexts/index.ts +1 -0
  321. package/src/features/role/data/index.ts +4 -0
  322. package/src/features/role/data/role.fields.ts +8 -0
  323. package/src/features/role/data/role.interface.ts +16 -0
  324. package/src/features/role/data/role.service.ts +117 -0
  325. package/src/features/role/data/role.ts +62 -0
  326. package/src/features/role/hooks/index.ts +1 -0
  327. package/src/features/role/hooks/useRoleTableStructure.tsx +72 -0
  328. package/src/features/role/index.ts +2 -0
  329. package/src/features/role/role.module.ts +10 -0
  330. package/src/features/s3/data/index.ts +3 -0
  331. package/src/features/s3/data/s3.interface.ts +11 -0
  332. package/src/features/s3/data/s3.service.ts +30 -0
  333. package/src/features/s3/data/s3.ts +60 -0
  334. package/src/features/s3/index.ts +2 -0
  335. package/src/features/s3/s3.module.ts +10 -0
  336. package/src/features/search/index.ts +1 -0
  337. package/src/features/search/interfaces/index.ts +1 -0
  338. package/src/features/search/interfaces/search.result.interface.ts +3 -0
  339. package/src/features/user/author.module.ts +10 -0
  340. package/src/features/user/components/containers/UserContainer.tsx +23 -0
  341. package/src/features/user/components/containers/UserIndexContainer.tsx +12 -0
  342. package/src/features/user/components/containers/UsersListContainer.tsx +36 -0
  343. package/src/features/user/components/containers/index.ts +3 -0
  344. package/src/features/user/components/details/UserDetails.tsx +74 -0
  345. package/src/features/user/components/details/UserIndexDetails.tsx +28 -0
  346. package/src/features/user/components/details/index.ts +2 -0
  347. package/src/features/user/components/forms/RoleUserAdd.tsx +93 -0
  348. package/src/features/user/components/forms/UserAvatarEditor.tsx +78 -0
  349. package/src/features/user/components/forms/UserDeleter.tsx +49 -0
  350. package/src/features/user/components/forms/UserEditor.tsx +319 -0
  351. package/src/features/user/components/forms/UserMultiSelect.tsx +218 -0
  352. package/src/features/user/components/forms/UserReactivator.tsx +79 -0
  353. package/src/features/user/components/forms/UserResentInvitationEmail.tsx +88 -0
  354. package/src/features/user/components/forms/UserSelector.tsx +185 -0
  355. package/src/features/user/components/forms/index.ts +8 -0
  356. package/src/features/user/components/index.ts +5 -0
  357. package/src/features/user/components/lists/AdminUsersList.tsx +41 -0
  358. package/src/features/user/components/lists/CompanyUsersList.tsx +44 -0
  359. package/src/features/user/components/lists/ContributorsList.tsx +41 -0
  360. package/src/features/user/components/lists/RelevantUsersList.tsx +30 -0
  361. package/src/features/user/components/lists/RoleUsersList.tsx +31 -0
  362. package/src/features/user/components/lists/UserListInAdd.tsx +53 -0
  363. package/src/features/user/components/lists/UsersList.tsx +30 -0
  364. package/src/features/user/components/lists/UsersListByContentIds.tsx +30 -0
  365. package/src/features/user/components/lists/index.ts +8 -0
  366. package/src/features/user/components/widgets/UserAvatar.tsx +86 -0
  367. package/src/features/user/components/widgets/UserAvatarList.tsx +31 -0
  368. package/src/features/user/components/widgets/UserSearchPopover.tsx +89 -0
  369. package/src/features/user/components/widgets/index.ts +1 -0
  370. package/src/features/user/contexts/CurrentUserContext.tsx +156 -0
  371. package/src/features/user/contexts/UserContext.tsx +106 -0
  372. package/src/features/user/contexts/index.ts +2 -0
  373. package/src/features/user/data/index.ts +4 -0
  374. package/src/features/user/data/user.fields.ts +8 -0
  375. package/src/features/user/data/user.interface.ts +41 -0
  376. package/src/features/user/data/user.service.ts +246 -0
  377. package/src/features/user/data/user.ts +162 -0
  378. package/src/features/user/hooks/index.ts +2 -0
  379. package/src/features/user/hooks/useUserSearch.ts +53 -0
  380. package/src/features/user/hooks/useUserTableStructure.tsx +115 -0
  381. package/src/features/user/index.ts +3 -0
  382. package/src/features/user/user.module.ts +21 -0
  383. package/src/hooks/TableGeneratorRegistry.ts +53 -0
  384. package/src/hooks/index.ts +37 -0
  385. package/src/hooks/types.ts +35 -0
  386. package/src/hooks/url.rewriter.ts +22 -0
  387. package/src/hooks/useCustomD3Graph.tsx +707 -0
  388. package/src/hooks/useDataListRetriever.ts +349 -0
  389. package/src/hooks/useDebounce.ts +33 -0
  390. package/src/hooks/useNotificationSync.ts +20 -0
  391. package/src/hooks/usePageTracker.ts +69 -0
  392. package/src/hooks/usePageUrlGenerator.ts +50 -0
  393. package/src/hooks/usePushNotifications.ts +82 -0
  394. package/src/hooks/useSocket.ts +201 -0
  395. package/src/hooks/useTableGenerator.ts +20 -0
  396. package/src/i18n/config.ts +74 -0
  397. package/src/i18n/index.ts +18 -0
  398. package/src/index.ts +20 -0
  399. package/src/interfaces/breadcrumb.item.data.interface.ts +4 -0
  400. package/src/interfaces/d3.link.interface.ts +8 -0
  401. package/src/interfaces/d3.node.interface.ts +12 -0
  402. package/src/interfaces/index.ts +3 -0
  403. package/src/permissions/check.ts +127 -0
  404. package/src/permissions/index.ts +2 -0
  405. package/src/permissions/types.ts +109 -0
  406. package/src/roles/config.ts +46 -0
  407. package/src/roles/index.ts +1 -0
  408. package/src/server/ServerSession.ts +103 -0
  409. package/src/server/cache.ts +28 -0
  410. package/src/server/index.ts +4 -0
  411. package/src/server/request.ts +113 -0
  412. package/src/server/token.ts +10 -0
  413. package/src/shadcnui/custom/kanban.tsx +1001 -0
  414. package/src/shadcnui/custom/link.tsx +18 -0
  415. package/src/shadcnui/custom/multi-select.tsx +382 -0
  416. package/src/shadcnui/index.ts +49 -0
  417. package/src/shadcnui/ui/accordion.tsx +52 -0
  418. package/src/shadcnui/ui/alert-dialog.tsx +141 -0
  419. package/src/shadcnui/ui/alert.tsx +43 -0
  420. package/src/shadcnui/ui/avatar.tsx +50 -0
  421. package/src/shadcnui/ui/badge.tsx +40 -0
  422. package/src/shadcnui/ui/breadcrumb.tsx +115 -0
  423. package/src/shadcnui/ui/button.tsx +51 -0
  424. package/src/shadcnui/ui/calendar.tsx +73 -0
  425. package/src/shadcnui/ui/card.tsx +43 -0
  426. package/src/shadcnui/ui/carousel.tsx +225 -0
  427. package/src/shadcnui/ui/chart.tsx +320 -0
  428. package/src/shadcnui/ui/checkbox.tsx +29 -0
  429. package/src/shadcnui/ui/collapsible.tsx +11 -0
  430. package/src/shadcnui/ui/command.tsx +155 -0
  431. package/src/shadcnui/ui/context-menu.tsx +179 -0
  432. package/src/shadcnui/ui/dialog.tsx +96 -0
  433. package/src/shadcnui/ui/drawer.tsx +89 -0
  434. package/src/shadcnui/ui/dropdown-menu.tsx +205 -0
  435. package/src/shadcnui/ui/form.tsx +138 -0
  436. package/src/shadcnui/ui/hover-card.tsx +29 -0
  437. package/src/shadcnui/ui/input.tsx +21 -0
  438. package/src/shadcnui/ui/label.tsx +26 -0
  439. package/src/shadcnui/ui/navigation-menu.tsx +168 -0
  440. package/src/shadcnui/ui/popover.tsx +33 -0
  441. package/src/shadcnui/ui/progress.tsx +25 -0
  442. package/src/shadcnui/ui/radio-group.tsx +37 -0
  443. package/src/shadcnui/ui/resizable.tsx +47 -0
  444. package/src/shadcnui/ui/scroll-area.tsx +40 -0
  445. package/src/shadcnui/ui/select.tsx +164 -0
  446. package/src/shadcnui/ui/separator.tsx +28 -0
  447. package/src/shadcnui/ui/sheet.tsx +139 -0
  448. package/src/shadcnui/ui/sidebar.tsx +677 -0
  449. package/src/shadcnui/ui/skeleton.tsx +13 -0
  450. package/src/shadcnui/ui/slider.tsx +25 -0
  451. package/src/shadcnui/ui/sonner.tsx +25 -0
  452. package/src/shadcnui/ui/switch.tsx +31 -0
  453. package/src/shadcnui/ui/table.tsx +120 -0
  454. package/src/shadcnui/ui/tabs.tsx +55 -0
  455. package/src/shadcnui/ui/textarea.tsx +24 -0
  456. package/src/shadcnui/ui/toggle.tsx +39 -0
  457. package/src/shadcnui/ui/tooltip.tsx +61 -0
  458. package/src/unified/JsonApiRequest.ts +348 -0
  459. package/src/unified/index.ts +1 -0
  460. package/src/utils/blocknote-diff.util.ts +815 -0
  461. package/src/utils/blocknote-word-diff-renderer.util.ts +413 -0
  462. package/src/utils/cn.ts +6 -0
  463. package/src/utils/compose-refs.ts +61 -0
  464. package/src/utils/date-formatter.ts +53 -0
  465. package/src/utils/exists.ts +7 -0
  466. package/src/utils/index.ts +15 -0
  467. package/src/utils/schemas/entity.object.schema.ts +8 -0
  468. package/src/utils/schemas/index.ts +2 -0
  469. package/src/utils/schemas/user.object.schema.ts +9 -0
  470. package/src/utils/table-options.ts +67 -0
  471. package/src/utils/use-mobile.tsx +21 -0
  472. package/dist/ApiRequestDataTypeInterface-CUKFDBx2.d.mts +0 -20
  473. package/dist/ApiRequestDataTypeInterface-CUKFDBx2.d.ts +0 -20
  474. package/dist/BlockNoteEditor-VFWG6LXI.js.map +0 -1
  475. package/dist/JsonApiRequest-S3ICLM7B.mjs +0 -20
  476. package/dist/JsonApiRequest-ZZLSP26T.js +0 -20
  477. package/dist/JsonApiRequest-ZZLSP26T.js.map +0 -1
  478. package/dist/chunk-366S2JCC.mjs +0 -31
  479. package/dist/chunk-366S2JCC.mjs.map +0 -1
  480. package/dist/chunk-5W6AKZE6.mjs +0 -131
  481. package/dist/chunk-5W6AKZE6.mjs.map +0 -1
  482. package/dist/chunk-A3J3AAYM.mjs +0 -97
  483. package/dist/chunk-A3J3AAYM.mjs.map +0 -1
  484. package/dist/chunk-AWONBQQP.js +0 -97
  485. package/dist/chunk-AWONBQQP.js.map +0 -1
  486. package/dist/chunk-CXQOWQSY.js.map +0 -1
  487. package/dist/chunk-DKKMWBP4.mjs +0 -1
  488. package/dist/chunk-DKKMWBP4.mjs.map +0 -1
  489. package/dist/chunk-DO2HLAZO.js.map +0 -1
  490. package/dist/chunk-DZXDB3K2.mjs +0 -17
  491. package/dist/chunk-DZXDB3K2.mjs.map +0 -1
  492. package/dist/chunk-ECDTZBYO.mjs.map +0 -1
  493. package/dist/chunk-FY4SXJGU.js +0 -806
  494. package/dist/chunk-FY4SXJGU.js.map +0 -1
  495. package/dist/chunk-GYWPEPOH.mjs.map +0 -1
  496. package/dist/chunk-H6FMOA6B.js +0 -1
  497. package/dist/chunk-H6FMOA6B.js.map +0 -1
  498. package/dist/chunk-I2REI7OA.js.map +0 -1
  499. package/dist/chunk-J4Q36PMP.js +0 -31
  500. package/dist/chunk-J4Q36PMP.js.map +0 -1
  501. package/dist/chunk-L6EQEAXU.mjs.map +0 -1
  502. package/dist/chunk-MFO27OHB.mjs +0 -48
  503. package/dist/chunk-MFO27OHB.mjs.map +0 -1
  504. package/dist/chunk-RAF7PNLG.js +0 -131
  505. package/dist/chunk-RAF7PNLG.js.map +0 -1
  506. package/dist/chunk-RUR22SVM.js +0 -17
  507. package/dist/chunk-RUR22SVM.js.map +0 -1
  508. package/dist/chunk-TEGF6ZWG.js.map +0 -1
  509. package/dist/chunk-TMVHSY3Y.js.map +0 -1
  510. package/dist/chunk-V2JJPI7N.js.map +0 -1
  511. package/dist/chunk-WWWMJZEF.mjs +0 -806
  512. package/dist/chunk-WWWMJZEF.mjs.map +0 -1
  513. package/dist/chunk-X4BIHJ2B.mjs.map +0 -1
  514. package/dist/chunk-YDVTFM7X.mjs.map +0 -1
  515. /package/dist/{JsonApiRequest-S3ICLM7B.mjs.map → JsonApiRequest-O7BGUMFO.mjs.map} +0 -0
@@ -0,0 +1,815 @@
1
+ import { PartialBlock } from "@blocknote/core";
2
+
3
+ export interface WordDiff {
4
+ type: "added" | "removed" | "unchanged";
5
+ text: string;
6
+ diffId: string;
7
+ accepted?: boolean;
8
+ rejected?: boolean;
9
+ }
10
+
11
+ export interface DiffBlock {
12
+ id?: string;
13
+ type?: string;
14
+ props?: any;
15
+ content?: any;
16
+ children?: DiffBlock[];
17
+ diffType?: "added" | "removed" | "modified" | "unchanged";
18
+ originalContent?: any;
19
+ diffId?: string;
20
+ wordDiffs?: WordDiff[];
21
+ accepted?: boolean;
22
+ rejected?: boolean;
23
+ }
24
+
25
+ export interface DiffResult {
26
+ blocks: DiffBlock[];
27
+ hasChanges: boolean;
28
+ }
29
+
30
+ export interface BlockDiffOptions {
31
+ ignoreIds?: boolean;
32
+ compareContent?: boolean;
33
+ similarityThreshold?: number;
34
+ }
35
+
36
+ /**
37
+ * BlockNote Diff Utility
38
+ * Implements a sophisticated diff algorithm for BlockNote document structures
39
+ */
40
+ export class BlockNoteDiffUtil {
41
+ private static readonly DEFAULT_OPTIONS: BlockDiffOptions = {
42
+ ignoreIds: false,
43
+ compareContent: true,
44
+ similarityThreshold: 0.8,
45
+ };
46
+
47
+ /**
48
+ * Compare two BlockNote documents and return diff result
49
+ */
50
+ static diff(
51
+ originalBlocks: PartialBlock[] = [],
52
+ newBlocks: PartialBlock[] = [],
53
+ options: BlockDiffOptions = {},
54
+ ): DiffResult {
55
+ const opts = { ...this.DEFAULT_OPTIONS, ...options };
56
+
57
+ // Create a map for efficient lookups
58
+ const originalMap = new Map<string, PartialBlock>();
59
+ const newMap = new Map<string, PartialBlock>();
60
+
61
+ // Build maps based on block IDs
62
+ originalBlocks.forEach((block) => {
63
+ if (block.id) {
64
+ originalMap.set(block.id, block);
65
+ }
66
+ });
67
+
68
+ newBlocks.forEach((block) => {
69
+ if (block.id) {
70
+ newMap.set(block.id, block);
71
+ }
72
+ });
73
+
74
+ const diffBlocks: DiffBlock[] = [];
75
+ const processedNewIds = new Set<string>();
76
+
77
+ // Process original blocks to find removed and modified blocks
78
+ for (const originalBlock of originalBlocks) {
79
+ const blockId = originalBlock.id;
80
+
81
+ // Generate ID if missing
82
+ const processId = blockId || crypto.randomUUID();
83
+ const newBlock = blockId ? newMap.get(blockId) : null;
84
+
85
+ if (!newBlock) {
86
+ // Block was removed
87
+ const removedBlock: DiffBlock = {
88
+ ...originalBlock,
89
+ id: processId,
90
+ diffType: "removed",
91
+ diffId: `removed-${processId}`,
92
+ };
93
+ diffBlocks.push(removedBlock);
94
+ } else {
95
+ // Block exists in both, check for modifications
96
+ if (blockId) {
97
+ processedNewIds.add(blockId);
98
+ }
99
+
100
+ if (this.areBlocksEqual(originalBlock, newBlock, opts)) {
101
+ // Block is unchanged
102
+ const unchangedBlock: DiffBlock = {
103
+ ...newBlock,
104
+ diffType: "unchanged",
105
+ };
106
+ diffBlocks.push(unchangedBlock);
107
+ } else {
108
+ // Block was modified - perform word-level diff
109
+ const wordDiffs = this.generateWordDiffs(originalBlock.content, newBlock.content, processId);
110
+ const modifiedBlock: DiffBlock = {
111
+ ...newBlock,
112
+ diffType: "modified",
113
+ originalContent: originalBlock.content as any,
114
+ diffId: `modified-${processId}`,
115
+ wordDiffs: wordDiffs,
116
+ };
117
+ diffBlocks.push(modifiedBlock);
118
+ }
119
+ }
120
+ }
121
+
122
+ // Process new blocks to find added blocks
123
+ for (const newBlock of newBlocks) {
124
+ const blockId = newBlock.id;
125
+
126
+ // Skip if block was already processed (has ID and was found in original)
127
+ if (blockId && processedNewIds.has(blockId)) continue;
128
+
129
+ // This is a new block (either no ID or ID not found in original)
130
+ const generatedId = blockId || crypto.randomUUID();
131
+ const addedBlock: DiffBlock = {
132
+ ...newBlock,
133
+ id: generatedId,
134
+ diffType: "added",
135
+ diffId: `added-${generatedId}`,
136
+ };
137
+ diffBlocks.push(addedBlock);
138
+ }
139
+
140
+ // Sort blocks to maintain original order as much as possible
141
+ const sortedDiffBlocks = this.sortDiffBlocks(diffBlocks, originalBlocks, newBlocks);
142
+
143
+ return {
144
+ blocks: sortedDiffBlocks,
145
+ hasChanges: sortedDiffBlocks.some((block) => block.diffType !== "unchanged"),
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Compare two blocks for equality
151
+ */
152
+ private static areBlocksEqual(block1: PartialBlock, block2: PartialBlock, options: BlockDiffOptions): boolean {
153
+ // Compare block type
154
+ if (block1.type !== block2.type) {
155
+ return false;
156
+ }
157
+
158
+ // Compare props (excluding diffType specific props)
159
+ if (!this.deepEqual(block1.props, block2.props)) {
160
+ return false;
161
+ }
162
+
163
+ // Compare content if enabled
164
+ if (options.compareContent) {
165
+ if (!this.deepEqual(block1.content, block2.content)) {
166
+ return false;
167
+ }
168
+ }
169
+
170
+ // Compare children recursively
171
+ const children1 = block1.children || [];
172
+ const children2 = block2.children || [];
173
+
174
+ if (children1.length !== children2.length) {
175
+ return false;
176
+ }
177
+
178
+ for (let i = 0; i < children1.length; i++) {
179
+ if (!this.areBlocksEqual(children1[i], children2[i], options)) {
180
+ return false;
181
+ }
182
+ }
183
+
184
+ return true;
185
+ }
186
+
187
+ /**
188
+ * Deep equality comparison for objects
189
+ */
190
+ private static deepEqual(obj1: any, obj2: any): boolean {
191
+ if (obj1 === obj2) return true;
192
+
193
+ if (obj1 == null || obj2 == null) return obj1 === obj2;
194
+
195
+ if (typeof obj1 !== typeof obj2) return false;
196
+
197
+ if (typeof obj1 !== "object") return obj1 === obj2;
198
+
199
+ if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;
200
+
201
+ if (Array.isArray(obj1)) {
202
+ if (obj1.length !== obj2.length) return false;
203
+ for (let i = 0; i < obj1.length; i++) {
204
+ if (!this.deepEqual(obj1[i], obj2[i])) return false;
205
+ }
206
+ return true;
207
+ }
208
+
209
+ const keys1 = Object.keys(obj1);
210
+ const keys2 = Object.keys(obj2);
211
+
212
+ if (keys1.length !== keys2.length) return false;
213
+
214
+ for (const key of keys1) {
215
+ if (!keys2.includes(key)) return false;
216
+ if (!this.deepEqual(obj1[key], obj2[key])) return false;
217
+ }
218
+
219
+ return true;
220
+ }
221
+
222
+ /**
223
+ * Sort diff blocks to maintain logical order
224
+ */
225
+ private static sortDiffBlocks(
226
+ diffBlocks: DiffBlock[],
227
+ originalBlocks: PartialBlock[],
228
+ newBlocks: PartialBlock[],
229
+ ): DiffBlock[] {
230
+ // Create position maps
231
+ const originalPositions = new Map<string, number>();
232
+ const newPositions = new Map<string, number>();
233
+
234
+ originalBlocks.forEach((block, index) => {
235
+ if (block.id) {
236
+ originalPositions.set(block.id, index);
237
+ }
238
+ });
239
+
240
+ newBlocks.forEach((block, index) => {
241
+ if (block.id) {
242
+ newPositions.set(block.id, index);
243
+ }
244
+ });
245
+
246
+ return diffBlocks.sort((a, b) => {
247
+ const aId = a.id;
248
+ const bId = b.id;
249
+
250
+ if (!aId || !bId) return 0;
251
+
252
+ // Prioritize by new positions, fallback to original positions
253
+ const aPos = newPositions.get(aId) ?? originalPositions.get(aId) ?? Infinity;
254
+ const bPos = newPositions.get(bId) ?? originalPositions.get(bId) ?? Infinity;
255
+
256
+ return aPos - bPos;
257
+ });
258
+ }
259
+
260
+ /**
261
+ * Calculate similarity between two text contents
262
+ */
263
+ private static calculateSimilarity(content1: any[], content2: any[]): number {
264
+ if (!content1 || !content2) return 0;
265
+
266
+ const text1 = this.extractTextFromContent(content1);
267
+ const text2 = this.extractTextFromContent(content2);
268
+
269
+ if (text1 === text2) return 1;
270
+ if (!text1 || !text2) return 0;
271
+
272
+ // Simple Levenshtein distance-based similarity
273
+ const maxLength = Math.max(text1.length, text2.length);
274
+ const distance = this.levenshteinDistance(text1, text2);
275
+
276
+ return 1 - distance / maxLength;
277
+ }
278
+
279
+ /**
280
+ * Extract plain text from BlockNote content array
281
+ */
282
+ private static extractTextFromContent(content: any[]): string {
283
+ if (!Array.isArray(content)) return "";
284
+
285
+ return content
286
+ .map((item) => {
287
+ if (item.type === "text") {
288
+ return item.text || "";
289
+ }
290
+ return "";
291
+ })
292
+ .join("");
293
+ }
294
+
295
+ /**
296
+ * Calculate Levenshtein distance between two strings
297
+ */
298
+ private static levenshteinDistance(str1: string, str2: string): number {
299
+ const matrix = Array(str2.length + 1)
300
+ .fill(null)
301
+ .map(() => Array(str1.length + 1).fill(null));
302
+
303
+ for (let i = 0; i <= str1.length; i++) {
304
+ matrix[0][i] = i;
305
+ }
306
+
307
+ for (let j = 0; j <= str2.length; j++) {
308
+ matrix[j][0] = j;
309
+ }
310
+
311
+ for (let j = 1; j <= str2.length; j++) {
312
+ for (let i = 1; i <= str1.length; i++) {
313
+ const substitutionCost = str1[i - 1] === str2[j - 1] ? 0 : 1;
314
+ matrix[j][i] = Math.min(
315
+ matrix[j][i - 1] + 1, // deletion
316
+ matrix[j - 1][i] + 1, // insertion
317
+ matrix[j - 1][i - 1] + substitutionCost, // substitution
318
+ );
319
+ }
320
+ }
321
+
322
+ return matrix[str2.length][str1.length];
323
+ }
324
+
325
+ /**
326
+ * Generate word-level diffs between two content arrays
327
+ */
328
+ static generateWordDiffs(originalContent: any, newContent: any, blockId: string): WordDiff[] {
329
+ const originalText = this.extractTextFromContent(originalContent || []);
330
+ const newText = this.extractTextFromContent(newContent || []);
331
+
332
+ if (!originalText && !newText) return [];
333
+ if (!originalText) {
334
+ return newText
335
+ .split(/\s+/)
336
+ .filter((word) => word.trim())
337
+ .map((word, index) => ({
338
+ type: "added" as const,
339
+ text: word,
340
+ diffId: `${blockId}-add-${index}`,
341
+ accepted: false,
342
+ rejected: false,
343
+ }));
344
+ }
345
+ if (!newText) {
346
+ return originalText
347
+ .split(/\s+/)
348
+ .filter((word) => word.trim())
349
+ .map((word, index) => ({
350
+ type: "removed" as const,
351
+ text: word,
352
+ diffId: `${blockId}-remove-${index}`,
353
+ accepted: false,
354
+ rejected: false,
355
+ }));
356
+ }
357
+
358
+ return this.diffWords(originalText, newText, blockId);
359
+ }
360
+
361
+ /**
362
+ * Perform word-level diff using word-only approach (no space tokenization)
363
+ */
364
+ private static diffWords(text1: string, text2: string, blockId: string): WordDiff[] {
365
+ const words1 = text1.split(/\s+/).filter((word) => word.length > 0);
366
+ const words2 = text2.split(/\s+/).filter((word) => word.length > 0);
367
+
368
+ const diffs = this.myersDiff(words1, words2);
369
+
370
+ // Consolidate adjacent changes to reduce fragmentation
371
+ const consolidatedDiffs = this.consolidateAdjacentChanges(diffs);
372
+
373
+ const result: WordDiff[] = [];
374
+ let diffIndex = 0;
375
+
376
+ for (let i = 0; i < consolidatedDiffs.length; i++) {
377
+ const diff = consolidatedDiffs[i];
378
+ const isLastDiff = i === consolidatedDiffs.length - 1;
379
+
380
+ switch (diff.type) {
381
+ case "equal":
382
+ result.push({
383
+ type: "unchanged",
384
+ text: diff.value,
385
+ diffId: `${blockId}-unchanged-${diffIndex++}`,
386
+ accepted: true,
387
+ rejected: false,
388
+ });
389
+
390
+ // Add space after word if not the last diff
391
+ if (!isLastDiff) {
392
+ result.push({
393
+ type: "unchanged",
394
+ text: " ",
395
+ diffId: `${blockId}-space-${diffIndex++}`,
396
+ accepted: true,
397
+ rejected: false,
398
+ });
399
+ }
400
+ break;
401
+
402
+ case "delete":
403
+ // Check if this is a consolidated change or regular change
404
+ if ((diff as any).consolidated) {
405
+ // This is a consolidated deletion - check if next is consolidated insertion
406
+ const nextDiff = i + 1 < consolidatedDiffs.length ? consolidatedDiffs[i + 1] : null;
407
+ const isConsolidatedReplacement = nextDiff && nextDiff.type === "insert" && (nextDiff as any).consolidated;
408
+
409
+ if (isConsolidatedReplacement) {
410
+ // Use single shared diff ID for the entire consolidated change
411
+ const replacementId = `${blockId}-replace-${diffIndex++}`;
412
+
413
+ // Add the removed text
414
+ result.push({
415
+ type: "removed",
416
+ text: diff.value,
417
+ diffId: replacementId,
418
+ accepted: false,
419
+ rejected: false,
420
+ });
421
+
422
+ // Add the new text with same diff ID
423
+ result.push({
424
+ type: "added",
425
+ text: nextDiff.value,
426
+ diffId: replacementId,
427
+ accepted: false,
428
+ rejected: false,
429
+ });
430
+
431
+ // Skip the next insert since we handled it
432
+ i++;
433
+
434
+ // Add space after replacement if not the last
435
+ if (i < consolidatedDiffs.length - 1) {
436
+ result.push({
437
+ type: "unchanged",
438
+ text: " ",
439
+ diffId: `${blockId}-space-${diffIndex++}`,
440
+ accepted: true,
441
+ rejected: false,
442
+ });
443
+ }
444
+ } else {
445
+ // Consolidated deletion without replacement
446
+ result.push({
447
+ type: "removed",
448
+ text: diff.value,
449
+ diffId: `${blockId}-remove-${diffIndex++}`,
450
+ accepted: false,
451
+ rejected: false,
452
+ });
453
+
454
+ // Add space after deletion if not the last
455
+ if (!isLastDiff) {
456
+ result.push({
457
+ type: "unchanged",
458
+ text: " ",
459
+ diffId: `${blockId}-space-${diffIndex++}`,
460
+ accepted: true,
461
+ rejected: false,
462
+ });
463
+ }
464
+ }
465
+ } else {
466
+ // Regular single-word processing
467
+ const nextDiff = i + 1 < consolidatedDiffs.length ? consolidatedDiffs[i + 1] : null;
468
+ const isReplacement =
469
+ nextDiff && nextDiff.type === "insert" && this.areWordsSimilar(diff.value, nextDiff.value);
470
+
471
+ if (isReplacement) {
472
+ // Use single shared diff ID for both operations
473
+ const replacementId = `${blockId}-replace-${diffIndex++}`;
474
+
475
+ // Add the removed word
476
+ result.push({
477
+ type: "removed",
478
+ text: diff.value,
479
+ diffId: replacementId,
480
+ accepted: false,
481
+ rejected: false,
482
+ });
483
+
484
+ // Add the new word with same diff ID (no space between them)
485
+ result.push({
486
+ type: "added",
487
+ text: nextDiff.value,
488
+ diffId: replacementId,
489
+ accepted: false,
490
+ rejected: false,
491
+ });
492
+
493
+ // Skip the next insert since we handled it
494
+ i++;
495
+
496
+ // Add space after replacement if not the last
497
+ if (i < consolidatedDiffs.length - 1) {
498
+ result.push({
499
+ type: "unchanged",
500
+ text: " ",
501
+ diffId: `${blockId}-space-${diffIndex++}`,
502
+ accepted: true,
503
+ rejected: false,
504
+ });
505
+ }
506
+ } else {
507
+ // Regular deletion
508
+ result.push({
509
+ type: "removed",
510
+ text: diff.value,
511
+ diffId: `${blockId}-remove-${diffIndex++}`,
512
+ accepted: false,
513
+ rejected: false,
514
+ });
515
+
516
+ // Add space after deletion if not the last
517
+ if (!isLastDiff) {
518
+ result.push({
519
+ type: "unchanged",
520
+ text: " ",
521
+ diffId: `${blockId}-space-${diffIndex++}`,
522
+ accepted: true,
523
+ rejected: false,
524
+ });
525
+ }
526
+ }
527
+ }
528
+ break;
529
+
530
+ case "insert":
531
+ // Only handle if not already processed as part of replacement or consolidation
532
+ if ((diff as any).consolidated) {
533
+ // This should have been handled in the delete case above
534
+ const prevDiff = i > 0 ? consolidatedDiffs[i - 1] : null;
535
+ const wasProcessedAsConsolidatedReplacement =
536
+ prevDiff && prevDiff.type === "delete" && (prevDiff as any).consolidated;
537
+
538
+ if (!wasProcessedAsConsolidatedReplacement) {
539
+ // Standalone consolidated insertion
540
+ result.push({
541
+ type: "added",
542
+ text: diff.value,
543
+ diffId: `${blockId}-add-${diffIndex++}`,
544
+ accepted: false,
545
+ rejected: false,
546
+ });
547
+
548
+ // Add space after insertion if not the last
549
+ if (!isLastDiff) {
550
+ result.push({
551
+ type: "unchanged",
552
+ text: " ",
553
+ diffId: `${blockId}-space-${diffIndex++}`,
554
+ accepted: true,
555
+ rejected: false,
556
+ });
557
+ }
558
+ }
559
+ } else {
560
+ // Regular single-word processing
561
+ const prevDiff = i > 0 ? consolidatedDiffs[i - 1] : null;
562
+ const wasProcessedAsReplacement =
563
+ prevDiff && prevDiff.type === "delete" && this.areWordsSimilar(prevDiff.value, diff.value);
564
+
565
+ if (!wasProcessedAsReplacement) {
566
+ result.push({
567
+ type: "added",
568
+ text: diff.value,
569
+ diffId: `${blockId}-add-${diffIndex++}`,
570
+ accepted: false,
571
+ rejected: false,
572
+ });
573
+
574
+ // Add space after insertion if not the last
575
+ if (!isLastDiff) {
576
+ result.push({
577
+ type: "unchanged",
578
+ text: " ",
579
+ diffId: `${blockId}-space-${diffIndex++}`,
580
+ accepted: true,
581
+ rejected: false,
582
+ });
583
+ }
584
+ }
585
+ }
586
+ break;
587
+ }
588
+ }
589
+
590
+ return result;
591
+ } /**
592
+ * Improved diff algorithm that better handles word insertions
593
+ * Uses a combination of LCS and heuristics to minimize false changes
594
+ */
595
+ private static myersDiff(a: string[], b: string[]): Array<{ type: "equal" | "delete" | "insert"; value: string }> {
596
+ if (a.length === 0) {
597
+ return b.map((value) => ({ type: "insert" as const, value }));
598
+ }
599
+ if (b.length === 0) {
600
+ return a.map((value) => ({ type: "delete" as const, value }));
601
+ }
602
+
603
+ // Use dynamic programming for optimal diff
604
+ const dp = this.computeEditScript(a, b);
605
+ return this.reconstructDiff(a, b, dp);
606
+ }
607
+
608
+ /**
609
+ * Compute edit script using dynamic programming
610
+ */
611
+ private static computeEditScript(a: string[], b: string[]): number[][] {
612
+ const m = a.length;
613
+ const n = b.length;
614
+ const dp: number[][] = Array(m + 1)
615
+ .fill(null)
616
+ .map(() => Array(n + 1).fill(0));
617
+
618
+ // Initialize base cases
619
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
620
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
621
+
622
+ // Fill the DP table
623
+ for (let i = 1; i <= m; i++) {
624
+ for (let j = 1; j <= n; j++) {
625
+ if (a[i - 1] === b[j - 1]) {
626
+ dp[i][j] = dp[i - 1][j - 1]; // No operation needed
627
+ } else {
628
+ dp[i][j] =
629
+ 1 +
630
+ Math.min(
631
+ dp[i - 1][j], // Delete from a
632
+ dp[i][j - 1], // Insert into a
633
+ dp[i - 1][j - 1], // Replace
634
+ );
635
+ }
636
+ }
637
+ }
638
+
639
+ return dp;
640
+ }
641
+
642
+ /**
643
+ * Reconstruct the actual diff from the DP table
644
+ */
645
+ private static reconstructDiff(
646
+ a: string[],
647
+ b: string[],
648
+ dp: number[][],
649
+ ): Array<{ type: "equal" | "delete" | "insert"; value: string; sharedDiffId?: boolean }> {
650
+ const result: Array<{ type: "equal" | "delete" | "insert"; value: string; sharedDiffId?: boolean }> = [];
651
+ let i = a.length;
652
+ let j = b.length;
653
+
654
+ while (i > 0 || j > 0) {
655
+ if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {
656
+ // Equal
657
+ result.unshift({ type: "equal", value: a[i - 1] });
658
+ i--;
659
+ j--;
660
+ } else {
661
+ // Determine the best operation with preference for insert/delete over replace
662
+ const deleteCost = i > 0 ? dp[i - 1][j] : Infinity;
663
+ const insertCost = j > 0 ? dp[i][j - 1] : Infinity;
664
+ const replaceCost = i > 0 && j > 0 ? dp[i - 1][j - 1] : Infinity;
665
+
666
+ const minCost = Math.min(deleteCost, insertCost, replaceCost);
667
+
668
+ // Prefer insertions and deletions over replacements when costs are equal
669
+ if (minCost === insertCost && j > 0) {
670
+ // Insert
671
+ result.unshift({ type: "insert", value: b[j - 1] });
672
+ j--;
673
+ } else if (minCost === deleteCost && i > 0) {
674
+ // Delete
675
+ result.unshift({ type: "delete", value: a[i - 1] });
676
+ i--;
677
+ } else if (minCost === replaceCost && i > 0 && j > 0) {
678
+ // Only use replace for similar words, otherwise prefer separate operations
679
+ if (this.areWordsSimilar(a[i - 1], b[j - 1])) {
680
+ // Similar words - treat as replacement with shared diffId
681
+ result.unshift({ type: "insert", value: b[j - 1], sharedDiffId: true });
682
+ result.unshift({ type: "delete", value: a[i - 1], sharedDiffId: true });
683
+ i--;
684
+ j--;
685
+ } else {
686
+ // Different words - prefer insert over delete when costs are equal
687
+ result.unshift({ type: "insert", value: b[j - 1] });
688
+ j--;
689
+ }
690
+ }
691
+ }
692
+ }
693
+
694
+ return result;
695
+ }
696
+
697
+ /**
698
+ * Consolidate adjacent changes to reduce fragmentation
699
+ * e.g., if we have: delete "Key", insert "Key!", delete "Challenges"
700
+ * We can consolidate this into: replace ["Key", "Challenges"] with ["Key!"]
701
+ */
702
+ private static consolidateAdjacentChanges(
703
+ diffs: Array<{ type: "equal" | "delete" | "insert"; value: string }>,
704
+ ): Array<{ type: "equal" | "delete" | "insert"; value: string; consolidated?: boolean }> {
705
+ const result = [];
706
+ let i = 0;
707
+
708
+ while (i < diffs.length) {
709
+ const current = diffs[i];
710
+
711
+ if (current.type === "equal") {
712
+ result.push(current);
713
+ i++;
714
+ continue;
715
+ }
716
+
717
+ // Look for patterns of adjacent changes that can be consolidated
718
+ const changeSequence = [];
719
+ let j = i;
720
+
721
+ // Collect adjacent non-equal changes
722
+ while (j < diffs.length && diffs[j].type !== "equal") {
723
+ changeSequence.push(diffs[j]);
724
+ j++;
725
+ }
726
+
727
+ if (changeSequence.length <= 1) {
728
+ // Single change, no consolidation needed
729
+ result.push(current);
730
+ i++;
731
+ continue;
732
+ }
733
+
734
+ // Check if we should consolidate this sequence
735
+ const shouldConsolidate = this.shouldConsolidateChanges(
736
+ changeSequence as Array<{ type: "delete" | "insert"; value: string }>,
737
+ );
738
+
739
+ if (shouldConsolidate) {
740
+ // Create consolidated changes
741
+ const deletedWords = changeSequence.filter((c) => c.type === "delete").map((c) => c.value);
742
+ const insertedWords = changeSequence.filter((c) => c.type === "insert").map((c) => c.value);
743
+
744
+ if (deletedWords.length > 0) {
745
+ result.push({
746
+ type: "delete" as const,
747
+ value: deletedWords.join(" "),
748
+ consolidated: true,
749
+ });
750
+ }
751
+
752
+ if (insertedWords.length > 0) {
753
+ result.push({
754
+ type: "insert" as const,
755
+ value: insertedWords.join(" "),
756
+ consolidated: true,
757
+ });
758
+ }
759
+ } else {
760
+ // Don't consolidate, add individual changes
761
+ changeSequence.forEach((change) => result.push(change));
762
+ }
763
+
764
+ i = j;
765
+ }
766
+
767
+ return result;
768
+ }
769
+
770
+ /**
771
+ * Determine if a sequence of changes should be consolidated
772
+ */
773
+ private static shouldConsolidateChanges(changes: Array<{ type: "delete" | "insert"; value: string }>): boolean {
774
+ // Consolidate if we have both deletions and insertions in the same sequence
775
+ const hasDeletes = changes.some((c) => c.type === "delete");
776
+ const hasInserts = changes.some((c) => c.type === "insert");
777
+
778
+ // Only consolidate if we have both types of changes (replacements/modifications)
779
+ // Pure additions or pure deletions are fine as separate changes
780
+ return hasDeletes && hasInserts;
781
+ }
782
+
783
+ /**
784
+ * Check if two words are similar enough to be considered a replacement
785
+ */
786
+ private static areWordsSimilar(word1: string, word2: string): boolean {
787
+ // If words are exactly the same, they're similar
788
+ if (word1 === word2) return true;
789
+
790
+ // Consider words similar if they share more than 70% of their characters
791
+ const maxLen = Math.max(word1.length, word2.length);
792
+ const minLen = Math.min(word1.length, word2.length);
793
+
794
+ // If one word is much longer than the other, they're not similar
795
+ if (maxLen > minLen * 2) {
796
+ return false;
797
+ }
798
+
799
+ // Special case: if one word is just the other plus punctuation, treat as separate changes
800
+ // e.g., "Key" and "Key!" should not be considered similar for replacement
801
+ const word1Clean = word1.replace(/[^\w]/g, "");
802
+ const word2Clean = word2.replace(/[^\w]/g, "");
803
+
804
+ if (word1Clean === word2Clean && word1 !== word2) {
805
+ // One word is just the other with added punctuation - don't treat as replacement
806
+ return false;
807
+ }
808
+
809
+ // Calculate character overlap using Levenshtein distance
810
+ const distance = this.levenshteinDistance(word1, word2);
811
+ const similarity = 1 - distance / maxLen;
812
+
813
+ return similarity > 0.7; // Increased threshold to be more conservative
814
+ }
815
+ }