@peers-app/peers-ui 0.14.0 → 0.15.0

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 (438) hide show
  1. package/.github/workflows/publish.yml +8 -5
  2. package/babel.config.js +4 -4
  3. package/biome.json +191 -0
  4. package/dist/command-palette/command-palette-ui.d.ts +1 -2
  5. package/dist/command-palette/command-palette-ui.js +175 -244
  6. package/dist/command-palette/command-palette.js +65 -64
  7. package/dist/components/chat-overlay.d.ts +2 -2
  8. package/dist/components/chat-overlay.js +160 -217
  9. package/dist/components/checkbox.d.ts +5 -4
  10. package/dist/components/checkbox.js +4 -7
  11. package/dist/components/group-switcher.d.ts +1 -2
  12. package/dist/components/group-switcher.js +119 -159
  13. package/dist/components/input-date.d.ts +3 -3
  14. package/dist/components/input-date.js +6 -6
  15. package/dist/components/input-number.d.ts +7 -6
  16. package/dist/components/input-number.js +25 -20
  17. package/dist/components/input.d.ts +5 -4
  18. package/dist/components/input.js +4 -7
  19. package/dist/components/inverse-lazy-list.d.ts +3 -3
  20. package/dist/components/inverse-lazy-list.js +13 -47
  21. package/dist/components/io-schema-values.d.ts +5 -6
  22. package/dist/components/io-schema-values.js +28 -65
  23. package/dist/components/io-schema.d.ts +4 -5
  24. package/dist/components/io-schema.js +42 -79
  25. package/dist/components/lazy-list.d.ts +3 -3
  26. package/dist/components/lazy-list.js +38 -58
  27. package/dist/components/list-screen.d.ts +3 -8
  28. package/dist/components/list-screen.js +28 -23
  29. package/dist/components/loading-indicator.d.ts +1 -2
  30. package/dist/components/loading-indicator.js +2 -6
  31. package/dist/components/markdown-editor/autolink-plugin.js +5 -8
  32. package/dist/components/markdown-editor/editor-inline.d.ts +2 -3
  33. package/dist/components/markdown-editor/editor-inline.js +2 -6
  34. package/dist/components/markdown-editor/editor.d.ts +6 -6
  35. package/dist/components/markdown-editor/editor.js +9 -19
  36. package/dist/components/markdown-editor/markdown-plugin.d.ts +1 -1
  37. package/dist/components/markdown-editor/markdown-plugin.js +20 -21
  38. package/dist/components/markdown-editor/mention-node.d.ts +2 -2
  39. package/dist/components/markdown-editor/mention-node.js +24 -24
  40. package/dist/components/markdown-editor/mentions-plugin.d.ts +2 -2
  41. package/dist/components/markdown-editor/mentions-plugin.js +61 -62
  42. package/dist/components/markdown-editor/theme.js +28 -28
  43. package/dist/components/markdown-editor/toolbar.d.ts +2 -3
  44. package/dist/components/markdown-editor/toolbar.js +32 -49
  45. package/dist/components/markdown-with-mentions.d.ts +1 -1
  46. package/dist/components/markdown-with-mentions.js +43 -43
  47. package/dist/components/message-logs/message-logs.d.ts +1 -2
  48. package/dist/components/message-logs/message-logs.js +91 -116
  49. package/dist/components/messages/avatar.d.ts +3 -4
  50. package/dist/components/messages/avatar.js +37 -46
  51. package/dist/components/messages/channel-message-list.d.ts +5 -6
  52. package/dist/components/messages/channel-message-list.js +34 -34
  53. package/dist/components/messages/channel-view.d.ts +1 -2
  54. package/dist/components/messages/channel-view.js +23 -57
  55. package/dist/components/messages/message-compose.d.ts +3 -4
  56. package/dist/components/messages/message-compose.js +27 -38
  57. package/dist/components/messages/message-display.d.ts +2 -3
  58. package/dist/components/messages/message-display.js +42 -95
  59. package/dist/components/messages/thread-message-list.d.ts +4 -5
  60. package/dist/components/messages/thread-message-list.js +29 -29
  61. package/dist/components/router.d.ts +1 -2
  62. package/dist/components/router.js +58 -66
  63. package/dist/components/save-button.d.ts +3 -3
  64. package/dist/components/save-button.js +23 -33
  65. package/dist/components/sortable-list.d.ts +11 -12
  66. package/dist/components/sortable-list.js +42 -22
  67. package/dist/components/tabs.d.ts +3 -3
  68. package/dist/components/tabs.js +16 -47
  69. package/dist/components/tooltip.d.ts +4 -4
  70. package/dist/components/tooltip.js +4 -9
  71. package/dist/components/trust-level-badge.d.ts +2 -3
  72. package/dist/components/trust-level-badge.js +16 -16
  73. package/dist/components/trust-level-dropdown.d.ts +3 -4
  74. package/dist/components/trust-level-dropdown.js +32 -55
  75. package/dist/components/typeahead.d.ts +3 -3
  76. package/dist/components/typeahead.js +48 -89
  77. package/dist/components/voice-indicator.d.ts +2 -2
  78. package/dist/components/voice-indicator.js +93 -106
  79. package/dist/components/voice-subscribe-events.d.ts +32 -0
  80. package/dist/components/voice-subscribe-events.js +2 -0
  81. package/dist/globals.d.ts +3 -5
  82. package/dist/globals.js +22 -33
  83. package/dist/hooks.d.ts +5 -5
  84. package/dist/hooks.js +22 -12
  85. package/dist/hooks.test.js +129 -145
  86. package/dist/index.d.ts +9 -8
  87. package/dist/index.js +13 -12
  88. package/dist/mention-configs.d.ts +2 -2
  89. package/dist/mention-configs.js +55 -42
  90. package/dist/screens/assistants/assistant-config.d.ts +2 -3
  91. package/dist/screens/assistants/assistant-config.js +9 -22
  92. package/dist/screens/assistants/assistant-details.d.ts +1 -2
  93. package/dist/screens/assistants/assistant-details.js +13 -28
  94. package/dist/screens/assistants/assistant-info.d.ts +2 -3
  95. package/dist/screens/assistants/assistant-info.js +3 -17
  96. package/dist/screens/assistants/assistant-list.d.ts +1 -2
  97. package/dist/screens/assistants/assistant-list.js +15 -56
  98. package/dist/screens/assistants/assistant-tools.d.ts +2 -3
  99. package/dist/screens/assistants/assistant-tools.js +10 -24
  100. package/dist/screens/console-logs/console-logs-list.d.ts +1 -2
  101. package/dist/screens/console-logs/console-logs-list.js +130 -134
  102. package/dist/screens/console-logs/log-display.d.ts +2 -3
  103. package/dist/screens/console-logs/log-display.js +40 -42
  104. package/dist/screens/console-logs/log-filters.d.ts +1 -2
  105. package/dist/screens/console-logs/log-filters.js +2 -24
  106. package/dist/screens/console-logs/mobile-log-card.d.ts +2 -3
  107. package/dist/screens/console-logs/mobile-log-card.js +64 -67
  108. package/dist/screens/console-logs/resizable-table-header.d.ts +1 -2
  109. package/dist/screens/console-logs/resizable-table-header.js +31 -67
  110. package/dist/screens/contacts/contact-details.d.ts +1 -2
  111. package/dist/screens/contacts/contact-details.js +16 -46
  112. package/dist/screens/contacts/contact-list.d.ts +1 -2
  113. package/dist/screens/contacts/contact-list.js +44 -103
  114. package/dist/screens/contacts/index.d.ts +4 -4
  115. package/dist/screens/contacts/index.js +1 -1
  116. package/dist/screens/contacts/user-connect.d.ts +1 -2
  117. package/dist/screens/contacts/user-connect.js +85 -186
  118. package/dist/screens/data-explorer/data-explorer.d.ts +1 -2
  119. package/dist/screens/data-explorer/data-explorer.js +61 -181
  120. package/dist/screens/data-explorer/index.d.ts +2 -2
  121. package/dist/screens/data-explorer/query-executor.d.ts +1 -2
  122. package/dist/screens/data-explorer/query-executor.js +56 -166
  123. package/dist/screens/groups/group-details.d.ts +1 -2
  124. package/dist/screens/groups/group-details.js +27 -122
  125. package/dist/screens/groups/group-invite-listener.d.ts +2 -3
  126. package/dist/screens/groups/group-invite-listener.js +8 -104
  127. package/dist/screens/groups/group-list.d.ts +1 -2
  128. package/dist/screens/groups/group-list.js +56 -133
  129. package/dist/screens/groups/group-members.d.ts +2 -3
  130. package/dist/screens/groups/group-members.js +62 -132
  131. package/dist/screens/groups/index.d.ts +4 -4
  132. package/dist/screens/groups/index.js +1 -1
  133. package/dist/screens/join-group/index.d.ts +2 -2
  134. package/dist/screens/join-group/join-group.d.ts +1 -2
  135. package/dist/screens/join-group/join-group.js +9 -109
  136. package/dist/screens/network-viewer/connection-troubleshooter.d.ts +2 -3
  137. package/dist/screens/network-viewer/connection-troubleshooter.js +89 -193
  138. package/dist/screens/network-viewer/cpu-usage-graph.d.ts +1 -2
  139. package/dist/screens/network-viewer/cpu-usage-graph.js +60 -99
  140. package/dist/screens/network-viewer/device-details-modal.d.ts +1 -2
  141. package/dist/screens/network-viewer/device-details-modal.js +25 -177
  142. package/dist/screens/network-viewer/group-details-modal.d.ts +1 -2
  143. package/dist/screens/network-viewer/group-details-modal.js +31 -142
  144. package/dist/screens/network-viewer/index.d.ts +4 -4
  145. package/dist/screens/network-viewer/index.js +3 -3
  146. package/dist/screens/network-viewer/network-viewer-ipc.d.ts +22 -0
  147. package/dist/screens/network-viewer/network-viewer-ipc.js +6 -0
  148. package/dist/screens/network-viewer/network-viewer.d.ts +1 -2
  149. package/dist/screens/network-viewer/network-viewer.js +91 -296
  150. package/dist/screens/network-viewer/usage-graph.d.ts +1 -2
  151. package/dist/screens/network-viewer/usage-graph.js +78 -110
  152. package/dist/screens/packages/package-details.d.ts +1 -2
  153. package/dist/screens/packages/package-details.js +35 -41
  154. package/dist/screens/packages/package-info.d.ts +2 -2
  155. package/dist/screens/packages/package-info.js +33 -86
  156. package/dist/screens/packages/package-list.d.ts +1 -2
  157. package/dist/screens/packages/package-list.js +42 -106
  158. package/dist/screens/packages/package-new-local.d.ts +1 -2
  159. package/dist/screens/packages/package-new-local.js +13 -19
  160. package/dist/screens/packages/package-versions.d.ts +2 -3
  161. package/dist/screens/packages/package-versions.js +29 -96
  162. package/dist/screens/peer-types/peer-type-details.d.ts +3 -4
  163. package/dist/screens/peer-types/peer-type-details.js +26 -78
  164. package/dist/screens/peer-types/peer-type-list.d.ts +1 -2
  165. package/dist/screens/peer-types/peer-type-list.js +13 -24
  166. package/dist/screens/search/global-search.d.ts +1 -2
  167. package/dist/screens/search/global-search.js +104 -182
  168. package/dist/screens/settings/color-mode-dropdown.d.ts +3 -4
  169. package/dist/screens/settings/color-mode-dropdown.js +18 -37
  170. package/dist/screens/settings/settings-page.d.ts +1 -1
  171. package/dist/screens/settings/settings-page.js +86 -213
  172. package/dist/screens/settings/voice-settings-agent.d.ts +1 -1
  173. package/dist/screens/settings/voice-settings-agent.js +7 -44
  174. package/dist/screens/settings/voice-settings-api-keys.d.ts +2 -2
  175. package/dist/screens/settings/voice-settings-api-keys.js +2 -29
  176. package/dist/screens/settings/voice-settings-output.d.ts +2 -2
  177. package/dist/screens/settings/voice-settings-output.js +2 -40
  178. package/dist/screens/settings/voice-settings-providers.d.ts +2 -2
  179. package/dist/screens/settings/voice-settings-providers.js +2 -19
  180. package/dist/screens/settings/voice-settings-types.d.ts +4 -4
  181. package/dist/screens/settings/voice-settings-types.js +31 -31
  182. package/dist/screens/settings/voice-settings-wake-word.d.ts +2 -2
  183. package/dist/screens/settings/voice-settings-wake-word.js +2 -33
  184. package/dist/screens/settings/voice-settings.d.ts +1 -1
  185. package/dist/screens/settings/voice-settings.js +35 -112
  186. package/dist/screens/setup-user.d.ts +1 -2
  187. package/dist/screens/setup-user.js +38 -116
  188. package/dist/screens/tools/tool-code.d.ts +2 -3
  189. package/dist/screens/tools/tool-code.js +9 -13
  190. package/dist/screens/tools/tool-details.d.ts +1 -2
  191. package/dist/screens/tools/tool-details.js +26 -39
  192. package/dist/screens/tools/tool-info.d.ts +2 -3
  193. package/dist/screens/tools/tool-info.js +9 -48
  194. package/dist/screens/tools/tool-list.d.ts +1 -2
  195. package/dist/screens/tools/tool-list.js +33 -65
  196. package/dist/screens/tools/tool-schema.d.ts +2 -3
  197. package/dist/screens/tools/tool-schema.js +2 -13
  198. package/dist/screens/tools/tool-test-details.d.ts +1 -2
  199. package/dist/screens/tools/tool-test-details.js +12 -28
  200. package/dist/screens/tools/tool-test-list.d.ts +1 -2
  201. package/dist/screens/tools/tool-test-list.js +17 -56
  202. package/dist/screens/variables/variable-details.d.ts +1 -2
  203. package/dist/screens/variables/variable-details.js +19 -86
  204. package/dist/screens/variables/variable-list.d.ts +1 -2
  205. package/dist/screens/variables/variable-list.js +16 -27
  206. package/dist/screens/welcome-modal.d.ts +1 -2
  207. package/dist/screens/welcome-modal.js +44 -111
  208. package/dist/screens/workflows/workflow-details.d.ts +1 -2
  209. package/dist/screens/workflows/workflow-details.js +17 -31
  210. package/dist/screens/workflows/workflow-info.d.ts +2 -3
  211. package/dist/screens/workflows/workflow-info.js +2 -9
  212. package/dist/screens/workflows/workflow-instructions.d.ts +2 -3
  213. package/dist/screens/workflows/workflow-instructions.js +23 -55
  214. package/dist/screens/workflows/workflow-list.d.ts +1 -2
  215. package/dist/screens/workflows/workflow-list.js +23 -62
  216. package/dist/setupTests.d.ts +1 -1
  217. package/dist/setupTests.js +10 -11
  218. package/dist/system-apps/assistants.app.d.ts +1 -1
  219. package/dist/system-apps/assistants.app.js +3 -3
  220. package/dist/system-apps/console-logs.app.d.ts +1 -1
  221. package/dist/system-apps/console-logs.app.js +3 -3
  222. package/dist/system-apps/contacts.app.d.ts +1 -1
  223. package/dist/system-apps/contacts.app.js +4 -4
  224. package/dist/system-apps/data-explorer.app.d.ts +1 -1
  225. package/dist/system-apps/data-explorer.app.js +4 -4
  226. package/dist/system-apps/groups.app.d.ts +1 -1
  227. package/dist/system-apps/groups.app.js +4 -4
  228. package/dist/system-apps/index.d.ts +17 -17
  229. package/dist/system-apps/index.js +52 -52
  230. package/dist/system-apps/join-group.app.d.ts +1 -1
  231. package/dist/system-apps/join-group.app.js +4 -4
  232. package/dist/system-apps/mobile-settings.app.d.ts +1 -1
  233. package/dist/system-apps/mobile-settings.app.js +3 -3
  234. package/dist/system-apps/network-viewer.app.d.ts +1 -1
  235. package/dist/system-apps/network-viewer.app.js +4 -4
  236. package/dist/system-apps/packages.app.d.ts +1 -1
  237. package/dist/system-apps/packages.app.js +3 -3
  238. package/dist/system-apps/search.app.d.ts +1 -1
  239. package/dist/system-apps/search.app.js +4 -4
  240. package/dist/system-apps/settings.app.d.ts +1 -1
  241. package/dist/system-apps/settings.app.js +3 -3
  242. package/dist/system-apps/threads.app.d.ts +1 -1
  243. package/dist/system-apps/threads.app.js +3 -3
  244. package/dist/system-apps/tools.app.d.ts +1 -1
  245. package/dist/system-apps/tools.app.js +3 -3
  246. package/dist/system-apps/types.app.d.ts +1 -1
  247. package/dist/system-apps/types.app.js +3 -3
  248. package/dist/system-apps/variables.app.d.ts +1 -1
  249. package/dist/system-apps/variables.app.js +3 -3
  250. package/dist/system-apps/workflows.app.d.ts +1 -1
  251. package/dist/system-apps/workflows.app.js +3 -3
  252. package/dist/tabs-layout/tabs-layout.d.ts +2 -3
  253. package/dist/tabs-layout/tabs-layout.js +215 -246
  254. package/dist/tabs-layout/tabs-state.d.ts +2 -2
  255. package/dist/tabs-layout/tabs-state.js +73 -61
  256. package/dist/ui-defaults/index.d.ts +2 -2
  257. package/dist/ui-defaults/list-screen.d.ts +2 -3
  258. package/dist/ui-defaults/list-screen.js +33 -37
  259. package/dist/ui-defaults/markdown-field.js +24 -56
  260. package/dist/ui-router/routes-loader.d.ts +1 -1
  261. package/dist/ui-router/routes-loader.js +17 -13
  262. package/dist/ui-router/ui-loader.d.ts +6 -6
  263. package/dist/ui-router/ui-loader.js +172 -268
  264. package/dist/utils.js +49 -39
  265. package/jest.config.js +16 -16
  266. package/package.json +16 -14
  267. package/src/command-palette/command-palette-ui.tsx +261 -237
  268. package/src/command-palette/command-palette.ts +81 -78
  269. package/src/components/chat-overlay.tsx +366 -261
  270. package/src/components/checkbox.tsx +15 -12
  271. package/src/components/group-switcher.tsx +150 -105
  272. package/src/components/input-date.tsx +17 -16
  273. package/src/components/input-number.tsx +47 -31
  274. package/src/components/input.tsx +15 -12
  275. package/src/components/inverse-lazy-list.tsx +14 -13
  276. package/src/components/io-schema-values.tsx +51 -69
  277. package/src/components/io-schema.tsx +94 -69
  278. package/src/components/lazy-list.tsx +51 -34
  279. package/src/components/list-screen.tsx +51 -35
  280. package/src/components/loading-indicator.tsx +2 -4
  281. package/src/components/markdown-editor/autolink-plugin.tsx +4 -11
  282. package/src/components/markdown-editor/editor-inline.tsx +3 -4
  283. package/src/components/markdown-editor/editor.tsx +53 -51
  284. package/src/components/markdown-editor/markdown-plugin.tsx +48 -40
  285. package/src/components/markdown-editor/mention-node.ts +39 -38
  286. package/src/components/markdown-editor/mentions-plugin.tsx +99 -101
  287. package/src/components/markdown-editor/theme.ts +28 -29
  288. package/src/components/markdown-editor/toolbar.tsx +53 -47
  289. package/src/components/markdown-with-mentions.tsx +56 -46
  290. package/src/components/message-logs/message-logs.tsx +225 -165
  291. package/src/components/messages/avatar.tsx +70 -52
  292. package/src/components/messages/channel-message-list.tsx +80 -68
  293. package/src/components/messages/channel-view.tsx +34 -33
  294. package/src/components/messages/message-compose.tsx +84 -67
  295. package/src/components/messages/message-display.tsx +103 -89
  296. package/src/components/messages/thread-message-list.tsx +53 -44
  297. package/src/components/router.tsx +42 -43
  298. package/src/components/save-button.tsx +43 -39
  299. package/src/components/sortable-list.tsx +77 -49
  300. package/src/components/tabs.tsx +31 -31
  301. package/src/components/tooltip.tsx +21 -28
  302. package/src/components/trust-level-badge.tsx +15 -11
  303. package/src/components/trust-level-dropdown.tsx +49 -19
  304. package/src/components/typeahead.tsx +57 -59
  305. package/src/components/voice-indicator.tsx +158 -141
  306. package/src/components/voice-subscribe-events.ts +20 -0
  307. package/src/globals.tsx +42 -40
  308. package/src/hooks.test.tsx +141 -134
  309. package/src/hooks.ts +80 -48
  310. package/src/index.tsx +17 -10
  311. package/src/mention-configs.ts +122 -68
  312. package/src/screens/assistants/assistant-config.tsx +28 -18
  313. package/src/screens/assistants/assistant-details.tsx +35 -36
  314. package/src/screens/assistants/assistant-info.tsx +16 -11
  315. package/src/screens/assistants/assistant-list.tsx +37 -34
  316. package/src/screens/assistants/assistant-tools.tsx +41 -20
  317. package/src/screens/console-logs/console-logs-list.tsx +173 -140
  318. package/src/screens/console-logs/log-display.tsx +65 -38
  319. package/src/screens/console-logs/log-filters.tsx +4 -3
  320. package/src/screens/console-logs/mobile-log-card.tsx +78 -71
  321. package/src/screens/console-logs/resizable-table-header.tsx +29 -21
  322. package/src/screens/contacts/contact-details.tsx +29 -30
  323. package/src/screens/contacts/contact-list.tsx +71 -60
  324. package/src/screens/contacts/index.ts +5 -5
  325. package/src/screens/contacts/user-connect.tsx +177 -171
  326. package/src/screens/data-explorer/data-explorer.tsx +134 -98
  327. package/src/screens/data-explorer/index.ts +2 -3
  328. package/src/screens/data-explorer/query-executor.tsx +90 -80
  329. package/src/screens/groups/group-details.tsx +120 -101
  330. package/src/screens/groups/group-invite-listener.tsx +34 -37
  331. package/src/screens/groups/group-list.tsx +119 -103
  332. package/src/screens/groups/group-members.tsx +225 -164
  333. package/src/screens/groups/index.ts +5 -6
  334. package/src/screens/join-group/index.ts +2 -2
  335. package/src/screens/join-group/join-group.tsx +41 -39
  336. package/src/screens/network-viewer/connection-troubleshooter.tsx +145 -104
  337. package/src/screens/network-viewer/cpu-usage-graph.tsx +39 -43
  338. package/src/screens/network-viewer/device-details-modal.tsx +46 -59
  339. package/src/screens/network-viewer/group-details-modal.tsx +68 -49
  340. package/src/screens/network-viewer/index.ts +4 -5
  341. package/src/screens/network-viewer/network-viewer-ipc.ts +23 -0
  342. package/src/screens/network-viewer/network-viewer.tsx +261 -236
  343. package/src/screens/network-viewer/usage-graph.tsx +57 -49
  344. package/src/screens/packages/package-details.tsx +43 -35
  345. package/src/screens/packages/package-info.tsx +107 -66
  346. package/src/screens/packages/package-list.tsx +175 -98
  347. package/src/screens/packages/package-new-local.tsx +28 -26
  348. package/src/screens/packages/package-versions.tsx +102 -77
  349. package/src/screens/peer-types/peer-type-details.tsx +60 -50
  350. package/src/screens/peer-types/peer-type-list.tsx +20 -30
  351. package/src/screens/search/global-search.tsx +153 -137
  352. package/src/screens/settings/color-mode-dropdown.tsx +52 -35
  353. package/src/screens/settings/settings-page.tsx +215 -141
  354. package/src/screens/settings/voice-settings-agent.tsx +13 -12
  355. package/src/screens/settings/voice-settings-api-keys.tsx +14 -12
  356. package/src/screens/settings/voice-settings-output.tsx +12 -11
  357. package/src/screens/settings/voice-settings-providers.tsx +7 -3
  358. package/src/screens/settings/voice-settings-types.ts +52 -49
  359. package/src/screens/settings/voice-settings-wake-word.tsx +25 -9
  360. package/src/screens/settings/voice-settings.tsx +66 -43
  361. package/src/screens/setup-user.tsx +88 -41
  362. package/src/screens/tools/tool-code.tsx +12 -17
  363. package/src/screens/tools/tool-details.tsx +28 -28
  364. package/src/screens/tools/tool-info.tsx +14 -19
  365. package/src/screens/tools/tool-list.tsx +58 -40
  366. package/src/screens/tools/tool-schema.tsx +16 -9
  367. package/src/screens/tools/tool-test-details.tsx +11 -22
  368. package/src/screens/tools/tool-test-list.tsx +29 -30
  369. package/src/screens/variables/variable-details.tsx +63 -51
  370. package/src/screens/variables/variable-list.tsx +29 -30
  371. package/src/screens/welcome-modal.tsx +68 -48
  372. package/src/screens/workflows/workflow-details.tsx +40 -30
  373. package/src/screens/workflows/workflow-info.tsx +4 -11
  374. package/src/screens/workflows/workflow-instructions.tsx +35 -28
  375. package/src/screens/workflows/workflow-list.tsx +50 -40
  376. package/src/setupTests.ts +14 -13
  377. package/src/system-apps/assistants.app.ts +5 -5
  378. package/src/system-apps/console-logs.app.ts +4 -4
  379. package/src/system-apps/contacts.app.ts +6 -6
  380. package/src/system-apps/data-explorer.app.ts +5 -5
  381. package/src/system-apps/groups.app.ts +6 -6
  382. package/src/system-apps/index.ts +49 -49
  383. package/src/system-apps/join-group.app.ts +5 -5
  384. package/src/system-apps/mobile-settings.app.ts +4 -5
  385. package/src/system-apps/network-viewer.app.ts +5 -5
  386. package/src/system-apps/packages.app.ts +5 -5
  387. package/src/system-apps/search.app.ts +6 -6
  388. package/src/system-apps/settings.app.ts +5 -5
  389. package/src/system-apps/threads.app.ts +5 -5
  390. package/src/system-apps/tools.app.ts +5 -5
  391. package/src/system-apps/types.app.ts +5 -5
  392. package/src/system-apps/variables.app.ts +5 -5
  393. package/src/system-apps/workflows.app.ts +5 -5
  394. package/src/tabs-layout/tabs-layout.tsx +345 -254
  395. package/src/tabs-layout/tabs-state.ts +100 -81
  396. package/src/ui-defaults/index.ts +2 -3
  397. package/src/ui-defaults/list-screen.tsx +45 -40
  398. package/src/ui-defaults/markdown-field.tsx +22 -26
  399. package/src/ui-router/routes-loader.ts +40 -24
  400. package/src/ui-router/ui-loader.tsx +312 -214
  401. package/src/utils.ts +68 -81
  402. package/tsconfig.json +5 -10
  403. package/dist/components/input-datetime.d.ts +0 -7
  404. package/dist/components/input-datetime.js +0 -35
  405. package/dist/components/lazy-sortable-list.d.ts +0 -29
  406. package/dist/components/lazy-sortable-list.js +0 -12
  407. package/dist/components/left-bar.d.ts +0 -5
  408. package/dist/components/left-bar.js +0 -207
  409. package/dist/components/main-content-container.d.ts +0 -2
  410. package/dist/components/main-content-container.js +0 -92
  411. package/dist/components/messages/thread-view.d.ts +0 -6
  412. package/dist/components/messages/thread-view.js +0 -174
  413. package/dist/components/off-canvas.d.ts +0 -13
  414. package/dist/components/off-canvas.js +0 -89
  415. package/dist/components/text-list-editor.tsx/text-list-editor.d.ts +0 -6
  416. package/dist/components/text-list-editor.tsx/text-list-editor.js +0 -13
  417. package/dist/components/top-bar.d.ts +0 -2
  418. package/dist/components/top-bar.js +0 -51
  419. package/dist/components/typeahead/mentions-plugin.d.ts +0 -7
  420. package/dist/components/typeahead/mentions-plugin.js +0 -203
  421. package/dist/components/typeahead/typeahead-editor.d.ts +0 -15
  422. package/dist/components/typeahead/typeahead-editor.js +0 -134
  423. package/dist/components/typeahead/typeahead.d.ts +0 -12
  424. package/dist/components/typeahead/typeahead.js +0 -94
  425. package/dist/screens/profile.d.ts +0 -2
  426. package/dist/screens/profile.js +0 -76
  427. package/src/components/input-datetime.tsx +0 -41
  428. package/src/components/lazy-sortable-list.tsx +0 -51
  429. package/src/components/left-bar.tsx +0 -322
  430. package/src/components/main-content-container.tsx +0 -79
  431. package/src/components/messages/thread-view.tsx +0 -214
  432. package/src/components/off-canvas.tsx +0 -83
  433. package/src/components/text-list-editor.tsx/text-list-editor.tsx +0 -13
  434. package/src/components/top-bar.tsx +0 -119
  435. package/src/components/typeahead/mentions-plugin.tsx +0 -265
  436. package/src/components/typeahead/typeahead-editor.tsx +0 -140
  437. package/src/components/typeahead/typeahead.tsx +0 -77
  438. package/src/screens/profile.tsx +0 -75
@@ -1,17 +1,18 @@
1
- import React, { useState, useEffect, useRef } from 'react';
2
- import InfiniteScroll from 'react-infinite-scroll-component';
3
- import { useObservable } from '../hooks';
4
1
  import { observable } from "@peers-app/peers-sdk";
2
+ import type React from "react";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import InfiniteScroll from "react-infinite-scroll-component";
5
+ import { useObservable } from "../hooks";
5
6
 
6
7
  interface IProps<T> {
7
- loadMore: (existingItems: T[]) => Promise<T[]>
8
- renderItems: (items: T[]) => React.ReactNode
9
- filterItems?:(existingItems: T[]) => T[]
10
- endOfList?: React.ReactNode
11
- loadingIndicator?: React.ReactNode
12
- scrollThreshold?: number | string
13
- lazyListStyle?: React.CSSProperties
14
- resetTrigger?: any
8
+ loadMore: (existingItems: T[]) => Promise<T[]>;
9
+ renderItems: (items: T[]) => React.ReactNode;
10
+ filterItems?: (existingItems: T[]) => T[];
11
+ endOfList?: React.ReactNode;
12
+ loadingIndicator?: React.ReactNode;
13
+ scrollThreshold?: number | string;
14
+ lazyListStyle?: React.CSSProperties;
15
+ resetTrigger?: unknown;
15
16
  }
16
17
 
17
18
  export function LazyList<T>(props: IProps<T>) {
@@ -21,39 +22,57 @@ export function LazyList<T>(props: IProps<T>) {
21
22
  const [loading] = useState(() => observable(false));
22
23
  useObservable(loading);
23
24
  const isLoadingSync = useRef(false); // Synchronous loading flag
25
+ // Bumped whenever resetTrigger changes so in-flight loadMore calls can discard stale results.
26
+ const loadGenRef = useRef(0);
24
27
 
25
- async function loadMore() {
28
+ const loadMore = useCallback(async () => {
26
29
  if (loading() || isLoadingSync.current) {
27
30
  return;
28
31
  }
29
32
  isLoadingSync.current = true;
30
33
  loading(true);
31
- const moreItems = await props.loadMore(items);
32
- if (!moreItems.length) {
33
- setAllLoaded(true);
34
- } else {
35
- itemsObsAry([...itemsObsAry(), ...moreItems]);
34
+ const gen = loadGenRef.current;
35
+ try {
36
+ const moreItems = await props.loadMore(itemsObsAry());
37
+ if (gen !== loadGenRef.current) {
38
+ // Reset happened while we were awaiting — discard to avoid mixing old + new results.
39
+ return;
40
+ }
41
+ if (!moreItems.length) {
42
+ setAllLoaded(true);
43
+ } else {
44
+ itemsObsAry([...itemsObsAry(), ...moreItems]);
45
+ }
46
+ } finally {
47
+ if (gen === loadGenRef.current) {
48
+ loading(false);
49
+ isLoadingSync.current = false;
50
+ }
36
51
  }
37
- loading(false);
38
- isLoadingSync.current = false;
39
- }
52
+ }, [props.loadMore, itemsObsAry, loading]);
40
53
 
41
54
  let renderItems = items;
42
55
  if (props.filterItems) {
43
56
  renderItems = props.filterItems(items);
44
57
  }
45
58
 
59
+ // Must run before the preload effect below: on mount / when `resetTrigger` changes we bump
60
+ // the generation and clear items first. Otherwise preload starts `loadMore` at gen N, then
61
+ // this effect runs and increments to N+1, the awaited result is discarded, and nothing
62
+ // retriggers a fetch (empty list forever — e.g. Groups).
63
+ useEffect(() => {
64
+ loadGenRef.current += 1;
65
+ itemsObsAry([]);
66
+ setAllLoaded(false);
67
+ isLoadingSync.current = false;
68
+ loading(false);
69
+ }, [itemsObsAry, loading, props.resetTrigger]);
70
+
46
71
  useEffect(() => {
47
72
  if (renderItems.length < 50 && !allLoaded && !loading() && !isLoadingSync.current) {
48
73
  loadMore();
49
74
  }
50
- }, [renderItems.length, allLoaded]);
51
-
52
- useEffect(() => {
53
- itemsObsAry([]);
54
- setAllLoaded(false);
55
- isLoadingSync.current = false; // Reset sync loading flag when resetting
56
- }, [props.resetTrigger]);
75
+ }, [renderItems.length, allLoaded, loadMore, loading]);
57
76
  // console.log('existing tasks', items.length);
58
77
  // console.log('rendering tasks', renderItems.length);
59
78
 
@@ -75,24 +94,22 @@ export function LazyList<T>(props: IProps<T>) {
75
94
  hasMore={!allLoaded}
76
95
  scrollThreshold={props.scrollThreshold}
77
96
  loader={
78
- props.loadingIndicator ??
79
- <>
97
+ props.loadingIndicator ?? (
80
98
  <div className="d-flex justify-content-center">
81
99
  <div>loading...</div>
82
100
  </div>
83
- </>
101
+ )
84
102
  }
85
103
  endMessage={
86
- props.endOfList ??
87
- <>
104
+ props.endOfList ?? (
88
105
  <div className="d-flex justify-content-center">
89
106
  <i>end of list</i>
90
107
  </div>
91
- </>
108
+ )
92
109
  }
93
110
  >
94
111
  {props.renderItems(renderItems)}
95
112
  </InfiniteScroll>
96
113
  </div>
97
- )
114
+ );
98
115
  }
@@ -1,13 +1,20 @@
1
- import { DataFilter, ICursorIterable, observable, SortBy, Table } from "@peers-app/peers-sdk";
2
- import * as _ from 'lodash';
3
- import React, { useEffect, useState } from 'react';
4
- import { isDesktop } from '../globals';
1
+ import {
2
+ type DataFilter,
3
+ type ICursorIterable,
4
+ observable,
5
+ type SortBy,
6
+ type Table,
7
+ } from "@peers-app/peers-sdk";
8
+ import * as _ from "lodash";
9
+ import type React from "react";
10
+ import { useCallback, useEffect, useState } from "react";
11
+ import { isDesktop } from "../globals";
5
12
  import { useObservable } from "../hooks";
6
- import { Input } from './input';
7
- import { LazyList } from './lazy-list';
8
- import { LoadingIndicator } from './loading-indicator';
13
+ import { Input } from "./input";
14
+ import { LazyList } from "./lazy-list";
15
+ import { LoadingIndicator } from "./loading-indicator";
9
16
 
10
- interface IProps<T extends { [key: string]: any; }> {
17
+ interface IProps<T extends Record<string, unknown>> {
11
18
  table: Table<T>;
12
19
  newRecord: (text: string) => Promise<T>;
13
20
  getFilter?: (text: string) => DataFilter<T>;
@@ -16,36 +23,35 @@ interface IProps<T extends { [key: string]: any; }> {
16
23
  placeholderName?: string;
17
24
  }
18
25
 
19
- export function ListScreen<T extends { [key: string]: any; }>(props: IProps<T>) {
20
- const {
21
- table,
22
- newRecord,
23
- sortBy,
24
- } = props;
26
+ export function ListScreen<T extends Record<string, unknown>>(props: IProps<T>) {
27
+ const { table, newRecord, sortBy } = props;
25
28
 
26
- const [searchTextObs] = useState(() => observable(''));
29
+ const [searchTextObs] = useState(() => observable(""));
27
30
  const [searchText] = useObservable(searchTextObs);
28
31
 
29
32
  const [cursorObs] = useState(() => observable<ICursorIterable<T> | undefined>());
30
-
31
- async function newCursor() {
33
+
34
+ const newCursor = useCallback(async () => {
32
35
  const filter = props.getFilter ? props.getFilter(searchText) : null;
33
- const cursor = await table.cursor(filter || {}, { sortBy, ...(filter ? {} : { textSearch: searchText }) });
36
+ const cursor = await table.cursor(filter || {}, {
37
+ sortBy,
38
+ ...(filter ? {} : { textSearch: searchText }),
39
+ });
34
40
  cursorObs(cursor);
35
41
  return cursor;
36
- }
42
+ }, [table, searchText, props.getFilter, sortBy, cursorObs]);
37
43
 
38
44
  useEffect(() => {
39
- newCursor();
40
- }, [searchText]);
45
+ void newCursor();
46
+ }, [newCursor]);
41
47
 
42
48
  const idFieldName = table.metaData.primaryKeyName;
43
49
 
44
50
  async function loadMore(existing: T[]): Promise<T[]> {
45
51
  let moreMatches: T[] = [];
46
- let cursor = cursorObs() || await newCursor();
52
+ const cursor = cursorObs() || (await newCursor());
47
53
  for await (const nextRecord of cursor) {
48
- if (existing.find(e => e[idFieldName] === nextRecord[idFieldName])) continue;
54
+ if (existing.find((e) => e[idFieldName] === nextRecord[idFieldName])) continue;
49
55
  moreMatches.push(nextRecord);
50
56
  if (searchText.length && moreMatches.length > 5) break;
51
57
  if (moreMatches.length >= 10) break;
@@ -54,29 +60,39 @@ export function ListScreen<T extends { [key: string]: any; }>(props: IProps<T>)
54
60
  cursorObs(undefined);
55
61
  }
56
62
  // if we're using default textSearch, list items with the most words matched in the name first
57
- if (!props.getFilter && moreMatches && searchText && table.metaData.fields.find(f => f.name === 'name')) {
58
- const words = searchText.toLowerCase().split(' ');
59
- moreMatches = _.sortBy(moreMatches, r => words.filter(w => r.name.toLowerCase().includes(w)).length).reverse();
63
+ if (
64
+ !props.getFilter &&
65
+ moreMatches &&
66
+ searchText &&
67
+ table.metaData.fields.find((f) => f.name === "name")
68
+ ) {
69
+ const words = searchText.toLowerCase().split(" ");
70
+ moreMatches = _.sortBy(moreMatches, (r) => {
71
+ const nameVal = r.name;
72
+ const nameStr = typeof nameVal === "string" ? nameVal : String(nameVal ?? "");
73
+ return words.filter((w) => nameStr.toLowerCase().includes(w)).length;
74
+ }).reverse();
60
75
  }
61
76
  return moreMatches;
62
77
  }
63
78
 
64
-
65
79
  async function searchSubmit(evt: React.KeyboardEvent<HTMLInputElement>) {
66
80
  if (evt.key !== "Enter") return;
67
81
  const name = searchText.trim();
68
82
  if (!name) return;
69
- searchTextObs('');
83
+ searchTextObs("");
70
84
  await newRecord(name);
71
85
  }
72
86
 
73
87
  return (
74
- <div className='container-fluid'>
75
-
88
+ <div className="container-fluid">
76
89
  <div className="input-group mt-3 mb-3">
77
- <Input value={searchTextObs} className="form-control" placeholder={`Search or create ${props.placeholderName || table.metaData.name}`}
78
- autoFocus={isDesktop() ? true : false}
79
- onKeyUp={evt => searchSubmit(evt)}
90
+ <Input
91
+ value={searchTextObs}
92
+ className="form-control"
93
+ placeholder={`Search or create ${props.placeholderName || table.metaData.name}`}
94
+ autoFocus={!!isDesktop()}
95
+ onKeyUp={(evt) => searchSubmit(evt)}
80
96
  />
81
97
  </div>
82
98
 
@@ -84,7 +100,7 @@ export function ListScreen<T extends { [key: string]: any; }>(props: IProps<T>)
84
100
  <LazyList
85
101
  resetTrigger={searchText}
86
102
  loadMore={loadMore}
87
- scrollThreshold={0.6}
103
+ scrollThreshold={0.6}
88
104
  renderItems={(notes) => {
89
105
  return notes.map(props.renderItem);
90
106
  }}
@@ -102,4 +118,4 @@ export function ListScreen<T extends { [key: string]: any; }>(props: IProps<T>)
102
118
  </div>
103
119
  </div>
104
120
  );
105
- };
121
+ }
@@ -1,9 +1,7 @@
1
- import React from 'react';
2
-
3
1
  export const LoadingIndicator = () => {
4
2
  return (
5
3
  <span className="spinner-grow spinner-grow-sm text-secondary m-4" role="status">
6
4
  <span className="visually-hidden">Loading...</span>
7
5
  </span>
8
- )
9
- }
6
+ );
7
+ };
@@ -1,9 +1,4 @@
1
- import React from 'react';
2
- import {
3
- AutoLinkPlugin,
4
- createLinkMatcherWithRegExp,
5
- } from '@lexical/react/LexicalAutoLinkPlugin';
6
-
1
+ import { AutoLinkPlugin, createLinkMatcherWithRegExp } from "@lexical/react/LexicalAutoLinkPlugin";
7
2
 
8
3
  const URL_REGEX =
9
4
  /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)(?<![-.+():%])/;
@@ -13,7 +8,7 @@ const EMAIL_REGEX =
13
8
 
14
9
  const MATCHERS = [
15
10
  createLinkMatcherWithRegExp(URL_REGEX, (text) => {
16
- return text.startsWith('http') ? text : `https://${text}`;
11
+ return text.startsWith("http") ? text : `https://${text}`;
17
12
  }),
18
13
  createLinkMatcherWithRegExp(EMAIL_REGEX, (text) => {
19
14
  return `mailto:${text}`;
@@ -24,13 +19,11 @@ export function LexicalAutoLinkPlugin(): JSX.Element {
24
19
  return <AutoLinkPlugin matchers={MATCHERS} />;
25
20
  }
26
21
 
27
-
28
-
29
- import { LinkPlugin as LexicalLinkPlugin } from '@lexical/react/LexicalLinkPlugin';
22
+ import { LinkPlugin as LexicalLinkPlugin } from "@lexical/react/LexicalLinkPlugin";
30
23
 
31
24
  export default function LinkPlugin(): JSX.Element {
32
25
  const validateUrl = (url: string) => {
33
- return url.startsWith('http://') || url.startsWith('https://') || url.startsWith('mailto:');
26
+ return url.startsWith("http://") || url.startsWith("https://") || url.startsWith("mailto:");
34
27
  };
35
28
  return <LexicalLinkPlugin validateUrl={validateUrl} />;
36
29
  }
@@ -1,10 +1,9 @@
1
- import React from "react";
2
- import { IMarkdownEditorProps, MarkdownEditor } from "./editor";
1
+ import { type IMarkdownEditorProps, MarkdownEditor } from "./editor";
3
2
 
4
3
  export const MarkdownEditorInline = (props: IMarkdownEditorProps) => {
5
4
  return (
6
5
  <div className="border rounded border-dark-subtle">
7
6
  <MarkdownEditor {...props} />
8
7
  </div>
9
- )
10
- }
8
+ );
9
+ };
@@ -1,32 +1,31 @@
1
- import { CodeNode } from '@lexical/code';
2
- import { AutoLinkNode, LinkNode } from '@lexical/link';
3
- import { ListItemNode, ListNode } from '@lexical/list';
4
- import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
5
- import { CheckListPlugin, } from '@lexical/react/LexicalCheckListPlugin';
6
- import { LexicalComposer } from '@lexical/react/LexicalComposer';
7
- import { ContentEditable } from '@lexical/react/LexicalContentEditable';
8
- import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
9
- import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
10
- import { ListPlugin } from '@lexical/react/LexicalListPlugin';
11
- import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin';
12
- import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
13
- import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin';
14
- import { HeadingNode, QuoteNode } from '@lexical/rich-text';
15
- import { observable, Observable } from "@peers-app/peers-sdk";
16
- import React, { useEffect, useState } from 'react';
17
- import { LexicalAutoLinkPlugin } from './autolink-plugin';
18
- import { customMarkdownTransformers, MarkdownPlugin } from './markdown-plugin';
19
- import { MentionNode } from './mention-node';
20
- import { MentionsPlugin } from './mentions-plugin';
21
- import theme from './theme';
22
- import { IToolbarControl, ToolbarPlugin } from './toolbar';
23
- import { COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND } from 'lexical';
24
- import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
25
- import { IMentionConfig, mentionConfigs } from '../../mention-configs';
26
-
1
+ import { CodeNode } from "@lexical/code";
2
+ import { AutoLinkNode, LinkNode } from "@lexical/link";
3
+ import { ListItemNode, ListNode } from "@lexical/list";
4
+ import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
5
+ import { CheckListPlugin } from "@lexical/react/LexicalCheckListPlugin";
6
+ import { LexicalComposer } from "@lexical/react/LexicalComposer";
7
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
8
+ import { ContentEditable } from "@lexical/react/LexicalContentEditable";
9
+ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
10
+ import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
11
+ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
12
+ import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
13
+ import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
14
+ import { TabIndentationPlugin } from "@lexical/react/LexicalTabIndentationPlugin";
15
+ import { HeadingNode, QuoteNode } from "@lexical/rich-text";
16
+ import { type Observable, observable } from "@peers-app/peers-sdk";
17
+ import { COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND } from "lexical";
18
+ import React, { useEffect, useState } from "react";
19
+ import { type IMentionConfig, mentionConfigs } from "../../mention-configs";
20
+ import { LexicalAutoLinkPlugin } from "./autolink-plugin";
21
+ import { customMarkdownTransformers, MarkdownPlugin } from "./markdown-plugin";
22
+ import { MentionNode } from "./mention-node";
23
+ import { MentionsPlugin } from "./mentions-plugin";
24
+ import theme from "./theme";
25
+ import { type IToolbarControl, ToolbarPlugin } from "./toolbar";
27
26
 
28
27
  const editorConfig = {
29
- namespace: 'PeersEditor',
28
+ namespace: "PeersEditor",
30
29
  nodes: [
31
30
  HeadingNode,
32
31
  QuoteNode,
@@ -34,6 +33,7 @@ const editorConfig = {
34
33
  ListNode,
35
34
  ListItemNode,
36
35
  MentionNode,
36
+ // biome-ignore lint/suspicious/noExplicitAny: Lexical node registry typing is narrower than runtime; AutoLinkNode is required for links.
37
37
  AutoLinkNode as any,
38
38
  LinkNode,
39
39
  ],
@@ -46,7 +46,7 @@ const editorConfig = {
46
46
  };
47
47
 
48
48
  export interface IEditorEffects {
49
- onKeyDown?: (e: React.KeyboardEvent) => (boolean | void);
49
+ onKeyDown?: (e: React.KeyboardEvent) => boolean | undefined;
50
50
  focus?: () => void;
51
51
  }
52
52
 
@@ -86,7 +86,7 @@ export function MarkdownEditor(props: IMarkdownEditorProps) {
86
86
  }
87
87
  }, 10);
88
88
  }
89
- }
89
+ };
90
90
  }
91
91
 
92
92
  const _mentionConfigs = props.mentionConfigs ?? mentionConfigs;
@@ -99,26 +99,19 @@ export function MarkdownEditor(props: IMarkdownEditorProps) {
99
99
  <div
100
100
  className="editor-inner"
101
101
  ref={editorRef}
102
- style={{ maxHeight: props.maxHeight, overflowY: 'auto' }}
102
+ style={{ maxHeight: props.maxHeight, overflowY: "auto" }}
103
103
  >
104
104
  <RichTextPlugin
105
- contentEditable={
106
- <ContentEditable
107
- className="editor-input p-2"
108
- />
109
- }
105
+ contentEditable={<ContentEditable className="editor-input p-2" />}
110
106
  placeholder={null}
111
107
  ErrorBoundary={LexicalErrorBoundary}
112
108
  />
113
109
  <HistoryPlugin />
114
- {props.autoFocus && <AutoFocusPlugin defaultSelection='rootEnd' />}
110
+ {props.autoFocus && <AutoFocusPlugin defaultSelection="rootEnd" />}
115
111
  <ListPlugin />
116
112
 
117
113
  {_mentionConfigs.length > 0 && (
118
- <MentionsPlugin
119
- mentionConfigs={_mentionConfigs}
120
- mentionsOpen={mentionsOpen}
121
- />
114
+ <MentionsPlugin mentionConfigs={_mentionConfigs} mentionsOpen={mentionsOpen} />
122
115
  )}
123
116
 
124
117
  <LexicalAutoLinkPlugin />
@@ -133,20 +126,29 @@ export function MarkdownEditor(props: IMarkdownEditorProps) {
133
126
  );
134
127
  }
135
128
 
136
- const OnKeyDownPlugin = (props: { effects?: IEditorEffects, mentionsOpen: Observable<boolean> }) => {
129
+ const OnKeyDownPlugin = (props: {
130
+ effects?: IEditorEffects;
131
+ mentionsOpen: Observable<boolean>;
132
+ }) => {
137
133
  const [editor] = useLexicalComposerContext();
134
+ // Intentionally `[editor]` only: `props.effects` is a stable object ref whose `onKeyDown` is
135
+ // imperatively reassigned by callers each render; the closure reads the latest value at event time.
138
136
  useEffect(() => {
139
- const removeListener = editor.registerCommand(KEY_DOWN_COMMAND, (event: KeyboardEvent) => {
140
- if (props.mentionsOpen()) {
137
+ const removeListener = editor.registerCommand(
138
+ KEY_DOWN_COMMAND,
139
+ (event: KeyboardEvent) => {
140
+ if (props.mentionsOpen()) {
141
+ return false;
142
+ }
143
+ if (props.effects?.onKeyDown) {
144
+ const result = props.effects.onKeyDown(event as unknown as React.KeyboardEvent);
145
+ return !!result;
146
+ }
141
147
  return false;
142
- }
143
- if (props.effects?.onKeyDown) {
144
- const result = props.effects.onKeyDown(event as any);
145
- return !!result;
146
- }
147
- return false;
148
- }, COMMAND_PRIORITY_LOW);
148
+ },
149
+ COMMAND_PRIORITY_LOW,
150
+ );
149
151
  return removeListener;
150
152
  }, [editor]);
151
153
  return null;
152
- }
154
+ };
@@ -1,9 +1,28 @@
1
- import { $createListItemNode, $createListNode, $isListItemNode, $isListNode, ListItemNode, ListNode, ListType } from '@lexical/list';
2
- import { $convertFromMarkdownString, $convertToMarkdownString, ElementTransformer, TextMatchTransformer, TRANSFORMERS } from "@lexical/markdown";
3
- import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
4
- import { formatMention, IMentionData, mentionRegex, Observable } from "@peers-app/peers-sdk";
5
- import { useEffect } from 'react';
6
- import { $createMentionNode, $isMentionNode, MentionNode } from './mention-node';
1
+ import {
2
+ $createListItemNode,
3
+ $createListNode,
4
+ $isListItemNode,
5
+ $isListNode,
6
+ ListItemNode,
7
+ ListNode,
8
+ type ListType,
9
+ } from "@lexical/list";
10
+ import {
11
+ $convertFromMarkdownString,
12
+ $convertToMarkdownString,
13
+ type ElementTransformer,
14
+ type TextMatchTransformer,
15
+ TRANSFORMERS,
16
+ } from "@lexical/markdown";
17
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
18
+ import {
19
+ formatMention,
20
+ type IMentionData,
21
+ mentionRegex,
22
+ type Observable,
23
+ } from "@peers-app/peers-sdk";
24
+ import { useEffect } from "react";
25
+ import { $createMentionNode, $isMentionNode, MentionNode } from "./mention-node";
7
26
 
8
27
  // Amount of spaces that define indentation level
9
28
  const LIST_INDENT_SIZE = 4;
@@ -21,13 +40,11 @@ function getIndent(whitespaces: string): number {
21
40
  return indent;
22
41
  }
23
42
 
24
- const listReplace = (listType: ListType): ElementTransformer['replace'] => {
43
+ const listReplace = (listType: ListType): ElementTransformer["replace"] => {
25
44
  return (parentNode, children, match) => {
26
45
  const previousNode = parentNode.getPreviousSibling();
27
46
  const nextNode = parentNode.getNextSibling();
28
- const listItem = $createListItemNode(
29
- listType === 'check' ? match[3] === 'x' : undefined,
30
- );
47
+ const listItem = $createListItemNode(listType === "check" ? match[3] === "x" : undefined);
31
48
  if ($isListNode(nextNode) && nextNode.getListType() === listType) {
32
49
  const firstChild = nextNode.getFirstChild();
33
50
  if (firstChild !== null) {
@@ -37,17 +54,11 @@ const listReplace = (listType: ListType): ElementTransformer['replace'] => {
37
54
  nextNode.append(listItem);
38
55
  }
39
56
  parentNode.remove();
40
- } else if (
41
- $isListNode(previousNode) &&
42
- previousNode.getListType() === listType
43
- ) {
57
+ } else if ($isListNode(previousNode) && previousNode.getListType() === listType) {
44
58
  previousNode.append(listItem);
45
59
  parentNode.remove();
46
60
  } else {
47
- const list = $createListNode(
48
- listType,
49
- listType === 'number' ? Number(match[2]) : undefined,
50
- );
61
+ const list = $createListNode(listType, listType === "number" ? Number(match[2]) : undefined);
51
62
  list.append(listItem);
52
63
  parentNode.replace(list);
53
64
  }
@@ -77,20 +88,20 @@ const listExport = (
77
88
  continue;
78
89
  }
79
90
  }
80
- const indent = ' '.repeat(depth * LIST_INDENT_SIZE);
91
+ const indent = " ".repeat(depth * LIST_INDENT_SIZE);
81
92
  const listType = listNode.getListType();
82
93
  const prefix =
83
- listType === 'number'
94
+ listType === "number"
84
95
  ? `${listNode.getStart() + index}. `
85
- : listType === 'check'
86
- ? `- [${listItemNode.getChecked() ? 'x' : ' '}] `
87
- : '- ';
96
+ : listType === "check"
97
+ ? `- [${listItemNode.getChecked() ? "x" : " "}] `
98
+ : "- ";
88
99
  output.push(indent + prefix + exportChildren(listItemNode));
89
100
  index++;
90
101
  }
91
102
  }
92
103
 
93
- return output.join('\n');
104
+ return output.join("\n");
94
105
  };
95
106
 
96
107
  const CHECK_LIST_TRANSFORMER: ElementTransformer = {
@@ -99,13 +110,13 @@ const CHECK_LIST_TRANSFORMER: ElementTransformer = {
99
110
  return $isListNode(node) ? listExport(node, exportChildren, 0) : null;
100
111
  },
101
112
  regExp: /^(\s*)(?:-\s)?\s?(\[(\s|x)?\])\s/i,
102
- replace: listReplace('check'),
103
- type: 'element',
113
+ replace: listReplace("check"),
114
+ type: "element",
104
115
  };
105
116
 
106
117
  const MENTION_TRANSFORMER: TextMatchTransformer = {
107
- type: 'text-match',
108
- trigger: '<',
118
+ type: "text-match",
119
+ trigger: "<",
109
120
  dependencies: [MentionNode],
110
121
  importRegExp: mentionRegex(),
111
122
  regExp: mentionRegex(),
@@ -117,10 +128,10 @@ const MENTION_TRANSFORMER: TextMatchTransformer = {
117
128
  },
118
129
  replace: (textNode, match) => {
119
130
  const kind = match[2];
120
- const name = match[3].replace(/_/g, ' ');
131
+ const name = match[3].replace(/_/g, " ");
121
132
  const id = match[4];
122
133
  const data: IMentionData = {
123
- kind: kind as any,
134
+ kind,
124
135
  name,
125
136
  id,
126
137
  clickable: false,
@@ -133,10 +144,10 @@ const MENTION_TRANSFORMER: TextMatchTransformer = {
133
144
  export const customMarkdownTransformers = [
134
145
  MENTION_TRANSFORMER,
135
146
  CHECK_LIST_TRANSFORMER, // This needs to be first or checklists will be treated as unordered lists
136
- ...TRANSFORMERS.filter(transformer => {
137
- const t = transformer as any;
147
+ ...TRANSFORMERS.filter((transformer) => {
148
+ const t = transformer as { dependencies?: { name?: string }[] };
138
149
  // disable headings for this markdown since these are inline messages
139
- if (t.dependencies?.[0]?.name === 'HeadingNode') {
150
+ if (t.dependencies?.[0]?.name === "HeadingNode") {
140
151
  return false;
141
152
  }
142
153
  return true;
@@ -152,11 +163,10 @@ export function MarkdownPlugin(props: IProps) {
152
163
  const { markdownObs } = props;
153
164
 
154
165
  useEffect(() => {
155
-
156
- let markdown = '';
166
+ let markdown = "";
157
167
 
158
168
  function setMarkdown() {
159
- const newMarkdown = markdownObs() || '';
169
+ const newMarkdown = markdownObs() || "";
160
170
  if (newMarkdown === markdown) {
161
171
  return;
162
172
  }
@@ -185,10 +195,8 @@ export function MarkdownPlugin(props: IProps) {
185
195
  return () => {
186
196
  sub.dispose();
187
197
  sub2Dispose();
188
- }
189
- }, [editor]);
198
+ };
199
+ }, [editor, markdownObs]);
190
200
 
191
201
  return null;
192
202
  }
193
-
194
-