@datalayer/lexical-loro 1.0.2 → 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 (402) hide show
  1. package/README.md +2 -2
  2. package/lib/App.d.ts +2 -0
  3. package/lib/App.js +141 -0
  4. package/lib/Editor.d.ts +2 -0
  5. package/lib/Editor.js +116 -0
  6. package/lib/Settings.d.ts +2 -0
  7. package/lib/Settings.js +57 -0
  8. package/lib/appSettings.d.ts +36 -0
  9. package/lib/appSettings.js +48 -0
  10. package/lib/collab/loro/Bindings.d.ts +41 -0
  11. package/lib/collab/loro/Bindings.js +99 -0
  12. package/lib/collab/loro/Debug.d.ts +33 -0
  13. package/lib/collab/loro/Debug.js +452 -0
  14. package/lib/collab/loro/LexicalCollaborationContext.d.ts +19 -0
  15. package/lib/collab/loro/LexicalCollaborationContext.js +52 -0
  16. package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +29 -0
  17. package/lib/collab/loro/LexicalCollaborationPlugin.js +111 -0
  18. package/lib/collab/loro/State.d.ts +53 -0
  19. package/lib/collab/loro/State.js +94 -0
  20. package/lib/collab/loro/components/LoroCollaborationUI.d.ts +13 -0
  21. package/lib/collab/loro/components/LoroCollaborationUI.js +9 -0
  22. package/lib/collab/loro/components/LoroCollaborators.d.ts +8 -0
  23. package/lib/collab/loro/components/LoroCollaborators.js +90 -0
  24. package/lib/collab/loro/components/index.d.ts +2 -0
  25. package/lib/collab/loro/components/index.js +6 -0
  26. package/lib/collab/loro/index.d.ts +6 -0
  27. package/lib/collab/loro/index.js +10 -0
  28. package/lib/collab/loro/integrators/BaseIntegrator.d.ts +14 -0
  29. package/lib/collab/loro/integrators/BaseIntegrator.js +5 -0
  30. package/lib/collab/loro/integrators/CounterIntegrator.d.ts +23 -0
  31. package/lib/collab/loro/integrators/CounterIntegrator.js +44 -0
  32. package/lib/collab/loro/integrators/ListIntegrator.d.ts +23 -0
  33. package/lib/collab/loro/integrators/ListIntegrator.js +53 -0
  34. package/lib/collab/loro/integrators/MapIntegrator.d.ts +24 -0
  35. package/lib/collab/loro/integrators/MapIntegrator.js +235 -0
  36. package/lib/collab/loro/integrators/TextIntegrator.d.ts +25 -0
  37. package/lib/collab/loro/integrators/TextIntegrator.js +55 -0
  38. package/lib/collab/loro/integrators/TreeIntegrator.d.ts +41 -0
  39. package/lib/collab/loro/integrators/TreeIntegrator.js +293 -0
  40. package/lib/collab/loro/nodes/NodeFactory.d.ts +15 -0
  41. package/lib/collab/loro/nodes/NodeFactory.js +80 -0
  42. package/lib/collab/loro/nodes/NodesMapper.d.ts +120 -0
  43. package/lib/collab/loro/nodes/NodesMapper.js +289 -0
  44. package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +60 -0
  45. package/lib/collab/loro/propagators/DecoratorNodePropagator.js +306 -0
  46. package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +62 -0
  47. package/lib/collab/loro/propagators/ElementNodePropagator.js +393 -0
  48. package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +57 -0
  49. package/lib/collab/loro/propagators/LineBreakNodePropagator.js +200 -0
  50. package/lib/collab/loro/propagators/RootNodePropagator.d.ts +55 -0
  51. package/lib/collab/loro/propagators/RootNodePropagator.js +174 -0
  52. package/lib/collab/loro/propagators/TextNodePropagator.d.ts +60 -0
  53. package/lib/collab/loro/propagators/TextNodePropagator.js +450 -0
  54. package/lib/collab/loro/propagators/index.d.ts +49 -0
  55. package/lib/collab/loro/propagators/index.js +30 -0
  56. package/lib/collab/loro/provider/websocket.d.ts +117 -0
  57. package/lib/collab/loro/provider/websocket.js +946 -0
  58. package/lib/collab/loro/servers/index.d.ts +0 -0
  59. package/lib/collab/loro/servers/index.js +4 -0
  60. package/lib/collab/loro/servers/ws/callback.d.ts +5 -0
  61. package/lib/collab/loro/servers/ws/callback.js +89 -0
  62. package/lib/collab/loro/servers/ws/server.d.ts +2 -0
  63. package/lib/collab/loro/servers/ws/server.js +29 -0
  64. package/lib/collab/loro/servers/ws/utils.d.ts +40 -0
  65. package/lib/collab/loro/servers/ws/utils.js +517 -0
  66. package/lib/collab/loro/sync/SyncCursors.d.ts +32 -0
  67. package/lib/collab/loro/sync/SyncCursors.js +501 -0
  68. package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +4 -0
  69. package/lib/collab/loro/sync/SyncLexicalToLoro.js +152 -0
  70. package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +5 -0
  71. package/lib/collab/loro/sync/SyncLoroToLexical.js +106 -0
  72. package/lib/collab/loro/types/LexicalNodeData.d.ts +32 -0
  73. package/lib/collab/loro/types/LexicalNodeData.js +75 -0
  74. package/lib/collab/loro/useCollaboration.d.ts +12 -0
  75. package/lib/collab/loro/useCollaboration.js +405 -0
  76. package/lib/collab/loro/utils/InitialContent.d.ts +64 -0
  77. package/lib/collab/loro/utils/InitialContent.js +113 -0
  78. package/lib/collab/loro/utils/Invariant.d.ts +15 -0
  79. package/lib/collab/loro/utils/Invariant.js +24 -0
  80. package/lib/collab/loro/utils/LexicalToLoro.d.ts +18 -0
  81. package/lib/collab/loro/utils/LexicalToLoro.js +100 -0
  82. package/lib/collab/loro/utils/Utils.d.ts +44 -0
  83. package/lib/collab/loro/utils/Utils.js +157 -0
  84. package/lib/collab/loro/wsProvider.d.ts +8 -0
  85. package/lib/collab/loro/wsProvider.js +52 -0
  86. package/lib/collab/utils/invariant.d.ts +1 -0
  87. package/lib/collab/utils/invariant.js +15 -0
  88. package/lib/collab/utils/simpleDiffWithCursor.d.ts +5 -0
  89. package/lib/collab/utils/simpleDiffWithCursor.js +35 -0
  90. package/lib/collab/yjs/Bindings.d.ts +23 -0
  91. package/lib/collab/yjs/Bindings.js +26 -0
  92. package/lib/collab/yjs/Debug.d.ts +23 -0
  93. package/lib/collab/yjs/Debug.js +213 -0
  94. package/lib/collab/yjs/LexicalCollaborationContext.d.ts +10 -0
  95. package/lib/collab/yjs/LexicalCollaborationContext.js +37 -0
  96. package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +21 -0
  97. package/lib/collab/yjs/LexicalCollaborationPlugin.js +63 -0
  98. package/lib/collab/yjs/State.d.ts +51 -0
  99. package/lib/collab/yjs/State.js +35 -0
  100. package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +5 -0
  101. package/lib/collab/yjs/nodes/AnyCollabNode.js +1 -0
  102. package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +22 -0
  103. package/lib/collab/yjs/nodes/CollabDecoratorNode.js +64 -0
  104. package/lib/collab/yjs/nodes/CollabElementNode.d.ts +40 -0
  105. package/lib/collab/yjs/nodes/CollabElementNode.js +462 -0
  106. package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +19 -0
  107. package/lib/collab/yjs/nodes/CollabLineBreakNode.js +44 -0
  108. package/lib/collab/yjs/nodes/CollabTextNode.d.ts +25 -0
  109. package/lib/collab/yjs/nodes/CollabTextNode.js +103 -0
  110. package/lib/collab/yjs/provider/websocket.d.ts +88 -0
  111. package/lib/collab/yjs/provider/websocket.js +415 -0
  112. package/lib/collab/yjs/servers/index.d.ts +0 -0
  113. package/lib/collab/yjs/servers/index.js +0 -0
  114. package/lib/collab/yjs/servers/ws/callback.d.ts +5 -0
  115. package/lib/collab/yjs/servers/ws/callback.js +72 -0
  116. package/lib/collab/yjs/servers/ws/server.d.ts +2 -0
  117. package/lib/collab/yjs/servers/ws/server.js +25 -0
  118. package/lib/collab/yjs/servers/ws/utils.d.ts +49 -0
  119. package/lib/collab/yjs/servers/ws/utils.js +284 -0
  120. package/lib/collab/yjs/sync/SyncCursors.d.ts +39 -0
  121. package/lib/collab/yjs/sync/SyncCursors.js +351 -0
  122. package/lib/collab/yjs/sync/SyncEditorStates.d.ts +10 -0
  123. package/lib/collab/yjs/sync/SyncEditorStates.js +200 -0
  124. package/lib/collab/yjs/useCollaboration.d.ts +12 -0
  125. package/lib/collab/yjs/useCollaboration.js +255 -0
  126. package/lib/collab/yjs/utils/Utils.d.ts +25 -0
  127. package/lib/collab/yjs/utils/Utils.js +402 -0
  128. package/lib/collab/yjs/wsProvider.d.ts +3 -0
  129. package/lib/collab/yjs/wsProvider.js +21 -0
  130. package/lib/commenting/index.d.ts +41 -0
  131. package/lib/commenting/index.js +328 -0
  132. package/lib/context/FlashMessageContext.d.ts +7 -0
  133. package/lib/context/FlashMessageContext.js +24 -0
  134. package/lib/context/SettingsContext.d.ts +12 -0
  135. package/lib/context/SettingsContext.js +38 -0
  136. package/lib/context/SharedHistoryContext.d.ts +11 -0
  137. package/lib/context/SharedHistoryContext.js +11 -0
  138. package/lib/context/ToolbarContext.d.ts +65 -0
  139. package/lib/context/ToolbarContext.js +84 -0
  140. package/lib/demo.d.ts +12 -0
  141. package/lib/demo.js +45 -0
  142. package/lib/hooks/useFlashMessage.d.ts +2 -0
  143. package/lib/hooks/useFlashMessage.js +8 -0
  144. package/lib/hooks/useModal.d.ts +5 -0
  145. package/lib/hooks/useModal.js +26 -0
  146. package/lib/hooks/useReport.d.ts +1 -0
  147. package/lib/hooks/useReport.js +50 -0
  148. package/lib/index.d.ts +1 -0
  149. package/lib/index.js +5 -0
  150. package/lib/nodes/AutocompleteNode.d.ts +27 -0
  151. package/lib/nodes/AutocompleteNode.js +60 -0
  152. package/lib/nodes/CounterComponent.d.ts +6 -0
  153. package/lib/nodes/CounterComponent.js +137 -0
  154. package/lib/nodes/CounterNode.d.ts +23 -0
  155. package/lib/nodes/CounterNode.js +47 -0
  156. package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +8 -0
  157. package/lib/nodes/DateTimeNode/DateTimeComponent.js +119 -0
  158. package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +27 -0
  159. package/lib/nodes/DateTimeNode/DateTimeNode.js +82 -0
  160. package/lib/nodes/EmojiNode.d.ts +18 -0
  161. package/lib/nodes/EmojiNode.js +54 -0
  162. package/lib/nodes/EquationComponent.d.ts +9 -0
  163. package/lib/nodes/EquationComponent.js +75 -0
  164. package/lib/nodes/EquationNode.d.ts +26 -0
  165. package/lib/nodes/EquationNode.js +109 -0
  166. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +8 -0
  167. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +110 -0
  168. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +50 -0
  169. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +55 -0
  170. package/lib/nodes/ExcalidrawNode/index.d.ts +32 -0
  171. package/lib/nodes/ExcalidrawNode/index.js +117 -0
  172. package/lib/nodes/FigmaNode.d.ts +20 -0
  173. package/lib/nodes/FigmaNode.js +52 -0
  174. package/lib/nodes/ImageComponent.d.ts +16 -0
  175. package/lib/nodes/ImageComponent.js +272 -0
  176. package/lib/nodes/ImageNode.d.ts +50 -0
  177. package/lib/nodes/ImageNode.js +151 -0
  178. package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +26 -0
  179. package/lib/nodes/InlineImageNode/InlineImageComponent.js +161 -0
  180. package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +59 -0
  181. package/lib/nodes/InlineImageNode/InlineImageNode.js +162 -0
  182. package/lib/nodes/KeywordNode.d.ts +14 -0
  183. package/lib/nodes/KeywordNode.js +37 -0
  184. package/lib/nodes/LayoutContainerNode.d.ts +24 -0
  185. package/lib/nodes/LayoutContainerNode.js +95 -0
  186. package/lib/nodes/LayoutItemNode.d.ts +16 -0
  187. package/lib/nodes/LayoutItemNode.js +69 -0
  188. package/lib/nodes/MentionNode.d.ts +20 -0
  189. package/lib/nodes/MentionNode.js +85 -0
  190. package/lib/nodes/PageBreakNode/index.d.ts +17 -0
  191. package/lib/nodes/PageBreakNode/index.js +83 -0
  192. package/lib/nodes/PlaygroundNodes.d.ts +3 -0
  193. package/lib/nodes/PlaygroundNodes.js +75 -0
  194. package/lib/nodes/PollComponent.d.ts +9 -0
  195. package/lib/nodes/PollComponent.js +85 -0
  196. package/lib/nodes/PollNode.d.ts +43 -0
  197. package/lib/nodes/PollNode.js +153 -0
  198. package/lib/nodes/SpecialTextNode.d.ts +24 -0
  199. package/lib/nodes/SpecialTextNode.js +54 -0
  200. package/lib/nodes/StickyComponent.d.ts +10 -0
  201. package/lib/nodes/StickyComponent.js +162 -0
  202. package/lib/nodes/StickyNode.d.ts +31 -0
  203. package/lib/nodes/StickyNode.js +76 -0
  204. package/lib/nodes/TweetNode.d.ts +21 -0
  205. package/lib/nodes/TweetNode.js +119 -0
  206. package/lib/nodes/YouTubeNode.d.ts +22 -0
  207. package/lib/nodes/YouTubeNode.js +84 -0
  208. package/lib/plugins/ActionsPlugin/index.d.ts +5 -0
  209. package/lib/plugins/ActionsPlugin/index.js +168 -0
  210. package/lib/plugins/AutoEmbedPlugin/index.d.ts +19 -0
  211. package/lib/plugins/AutoEmbedPlugin/index.js +158 -0
  212. package/lib/plugins/AutoLinkPlugin/index.d.ts +2 -0
  213. package/lib/plugins/AutoLinkPlugin/index.js +15 -0
  214. package/lib/plugins/AutocompletePlugin/index.d.ts +10 -0
  215. package/lib/plugins/AutocompletePlugin/index.js +2477 -0
  216. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +7 -0
  217. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +46 -0
  218. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +17 -0
  219. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +115 -0
  220. package/lib/plugins/CodeActionMenuPlugin/index.d.ts +5 -0
  221. package/lib/plugins/CodeActionMenuPlugin/index.js +104 -0
  222. package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +1 -0
  223. package/lib/plugins/CodeActionMenuPlugin/utils.js +22 -0
  224. package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +2 -0
  225. package/lib/plugins/CodeHighlightPrismPlugin/index.js +14 -0
  226. package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +2 -0
  227. package/lib/plugins/CodeHighlightShikiPlugin/index.js +14 -0
  228. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +25 -0
  229. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +135 -0
  230. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +16 -0
  231. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +83 -0
  232. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +16 -0
  233. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +85 -0
  234. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +2 -0
  235. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +12 -0
  236. package/lib/plugins/CollapsiblePlugin/index.d.ts +3 -0
  237. package/lib/plugins/CollapsiblePlugin/index.js +132 -0
  238. package/lib/plugins/CommentPlugin/index.d.ts +9 -0
  239. package/lib/plugins/CommentPlugin/index.js +460 -0
  240. package/lib/plugins/ComponentPickerPlugin/index.d.ts +2 -0
  241. package/lib/plugins/ComponentPickerPlugin/index.js +276 -0
  242. package/lib/plugins/ContextMenuPlugin/index.d.ts +2 -0
  243. package/lib/plugins/ContextMenuPlugin/index.js +112 -0
  244. package/lib/plugins/CounterPlugin/index.d.ts +3 -0
  245. package/lib/plugins/CounterPlugin/index.js +24 -0
  246. package/lib/plugins/DateTimePlugin/index.d.ts +8 -0
  247. package/lib/plugins/DateTimePlugin/index.js +28 -0
  248. package/lib/plugins/DebugPlugin/index.d.ts +3 -0
  249. package/lib/plugins/DebugPlugin/index.js +275 -0
  250. package/lib/plugins/DocsPlugin/index.d.ts +2 -0
  251. package/lib/plugins/DocsPlugin/index.js +4 -0
  252. package/lib/plugins/DragDropPastePlugin/index.d.ts +1 -0
  253. package/lib/plugins/DragDropPastePlugin/index.js +37 -0
  254. package/lib/plugins/DraggableBlockPlugin/index.d.ts +12 -0
  255. package/lib/plugins/DraggableBlockPlugin/index.js +36 -0
  256. package/lib/plugins/EmojiPickerPlugin/index.d.ts +1 -0
  257. package/lib/plugins/EmojiPickerPlugin/index.js +84 -0
  258. package/lib/plugins/EmojisPlugin/index.d.ts +2 -0
  259. package/lib/plugins/EmojisPlugin/index.js +56 -0
  260. package/lib/plugins/EquationsPlugin/index.d.ts +14 -0
  261. package/lib/plugins/EquationsPlugin/index.js +34 -0
  262. package/lib/plugins/ExcalidrawPlugin/index.d.ts +5 -0
  263. package/lib/plugins/ExcalidrawPlugin/index.js +44 -0
  264. package/lib/plugins/FigmaPlugin/index.d.ts +4 -0
  265. package/lib/plugins/FigmaPlugin/index.js +24 -0
  266. package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +15 -0
  267. package/lib/plugins/FloatingLinkEditorPlugin/index.js +280 -0
  268. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +7 -0
  269. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +219 -0
  270. package/lib/plugins/ImagesPlugin/index.d.ts +24 -0
  271. package/lib/plugins/ImagesPlugin/index.js +195 -0
  272. package/lib/plugins/InlineImagePlugin/index.d.ts +17 -0
  273. package/lib/plugins/InlineImagePlugin/index.js +180 -0
  274. package/lib/plugins/KeywordsPlugin/index.d.ts +2 -0
  275. package/lib/plugins/KeywordsPlugin/index.js +35 -0
  276. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +6 -0
  277. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +21 -0
  278. package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +7 -0
  279. package/lib/plugins/LayoutPlugin/LayoutPlugin.js +135 -0
  280. package/lib/plugins/LinkPlugin/index.d.ts +6 -0
  281. package/lib/plugins/LinkPlugin/index.js +11 -0
  282. package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +2 -0
  283. package/lib/plugins/MarkdownShortcutPlugin/index.js +6 -0
  284. package/lib/plugins/MarkdownTransformers/index.d.ts +8 -0
  285. package/lib/plugins/MarkdownTransformers/index.js +238 -0
  286. package/lib/plugins/MaxLengthPlugin/index.d.ts +3 -0
  287. package/lib/plugins/MaxLengthPlugin/index.js +41 -0
  288. package/lib/plugins/MentionsPlugin/index.d.ts +2 -0
  289. package/lib/plugins/MentionsPlugin/index.js +564 -0
  290. package/lib/plugins/PageBreakPlugin/index.d.ts +4 -0
  291. package/lib/plugins/PageBreakPlugin/index.js +31 -0
  292. package/lib/plugins/PasteLogPlugin/index.d.ts +2 -0
  293. package/lib/plugins/PasteLogPlugin/index.js +27 -0
  294. package/lib/plugins/PollPlugin/index.d.ts +8 -0
  295. package/lib/plugins/PollPlugin/index.js +38 -0
  296. package/lib/plugins/ShortcutsPlugin/index.d.ts +6 -0
  297. package/lib/plugins/ShortcutsPlugin/index.js +116 -0
  298. package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +59 -0
  299. package/lib/plugins/ShortcutsPlugin/shortcuts.js +173 -0
  300. package/lib/plugins/SpecialTextPlugin/index.d.ts +2 -0
  301. package/lib/plugins/SpecialTextPlugin/index.js +50 -0
  302. package/lib/plugins/SpeechToTextPlugin/index.d.ts +5 -0
  303. package/lib/plugins/SpeechToTextPlugin/index.js +86 -0
  304. package/lib/plugins/StickyPlugin/index.d.ts +2 -0
  305. package/lib/plugins/StickyPlugin/index.js +16 -0
  306. package/lib/plugins/TabFocusPlugin/index.d.ts +1 -0
  307. package/lib/plugins/TabFocusPlugin/index.js +38 -0
  308. package/lib/plugins/TableActionMenuPlugin/index.d.ts +5 -0
  309. package/lib/plugins/TableActionMenuPlugin/index.js +492 -0
  310. package/lib/plugins/TableCellResizer/index.d.ts +3 -0
  311. package/lib/plugins/TableCellResizer/index.js +297 -0
  312. package/lib/plugins/TableHoverActionsPlugin/index.d.ts +4 -0
  313. package/lib/plugins/TableHoverActionsPlugin/index.js +188 -0
  314. package/lib/plugins/TableOfContentsPlugin/index.d.ts +2 -0
  315. package/lib/plugins/TableOfContentsPlugin/index.js +116 -0
  316. package/lib/plugins/TablePlugin.d.ts +31 -0
  317. package/lib/plugins/TablePlugin.js +63 -0
  318. package/lib/plugins/TestRecorderPlugin/index.d.ts +3 -0
  319. package/lib/plugins/TestRecorderPlugin/index.js +346 -0
  320. package/lib/plugins/ToolbarPlugin/fontSize.d.ts +9 -0
  321. package/lib/plugins/ToolbarPlugin/fontSize.js +84 -0
  322. package/lib/plugins/ToolbarPlugin/index.d.ts +9 -0
  323. package/lib/plugins/ToolbarPlugin/index.js +500 -0
  324. package/lib/plugins/ToolbarPlugin/utils.d.ts +26 -0
  325. package/lib/plugins/ToolbarPlugin/utils.js +247 -0
  326. package/lib/plugins/TreeViewPlugin/index.d.ts +2 -0
  327. package/lib/plugins/TreeViewPlugin/index.js +7 -0
  328. package/lib/plugins/TwitterPlugin/index.d.ts +4 -0
  329. package/lib/plugins/TwitterPlugin/index.js +24 -0
  330. package/lib/plugins/TypingPerfPlugin/index.d.ts +2 -0
  331. package/lib/plugins/TypingPerfPlugin/index.js +97 -0
  332. package/lib/plugins/YouTubePlugin/index.d.ts +4 -0
  333. package/lib/plugins/YouTubePlugin/index.js +24 -0
  334. package/lib/server/validation.d.ts +1 -0
  335. package/lib/server/validation.js +115 -0
  336. package/lib/setupEnv.d.ts +2 -0
  337. package/lib/setupEnv.js +29 -0
  338. package/lib/themes/CommentEditorTheme.d.ts +4 -0
  339. package/lib/themes/CommentEditorTheme.js +11 -0
  340. package/lib/themes/PlaygroundEditorTheme.d.ts +4 -0
  341. package/lib/themes/PlaygroundEditorTheme.js +124 -0
  342. package/lib/themes/StickyEditorTheme.d.ts +4 -0
  343. package/lib/themes/StickyEditorTheme.js +11 -0
  344. package/lib/tyes.dt.d.ts +12 -0
  345. package/lib/tyes.dt.js +4 -0
  346. package/lib/ui/Button.d.ts +12 -0
  347. package/lib/ui/Button.js +6 -0
  348. package/lib/ui/ColorPicker.d.ts +14 -0
  349. package/lib/ui/ColorPicker.js +219 -0
  350. package/lib/ui/ContentEditable.d.ts +9 -0
  351. package/lib/ui/ContentEditable.js +6 -0
  352. package/lib/ui/Dialog.d.ts +10 -0
  353. package/lib/ui/Dialog.js +8 -0
  354. package/lib/ui/DropDown.d.ts +18 -0
  355. package/lib/ui/DropDown.js +133 -0
  356. package/lib/ui/DropdownColorPicker.d.ts +13 -0
  357. package/lib/ui/DropdownColorPicker.js +6 -0
  358. package/lib/ui/EquationEditor.d.ts +8 -0
  359. package/lib/ui/EquationEditor.js +11 -0
  360. package/lib/ui/ExcalidrawModal.d.ts +42 -0
  361. package/lib/ui/ExcalidrawModal.js +103 -0
  362. package/lib/ui/FileInput.d.ts +10 -0
  363. package/lib/ui/FileInput.js +5 -0
  364. package/lib/ui/FlashMessage.d.ts +7 -0
  365. package/lib/ui/FlashMessage.js +6 -0
  366. package/lib/ui/ImageResizer.d.ts +17 -0
  367. package/lib/ui/ImageResizer.js +171 -0
  368. package/lib/ui/KatexEquationAlterer.d.ts +8 -0
  369. package/lib/ui/KatexEquationAlterer.js +23 -0
  370. package/lib/ui/KatexRenderer.d.ts +6 -0
  371. package/lib/ui/KatexRenderer.js +24 -0
  372. package/lib/ui/Modal.d.ts +9 -0
  373. package/lib/ui/Modal.js +48 -0
  374. package/lib/ui/Select.d.ts +8 -0
  375. package/lib/ui/Select.js +5 -0
  376. package/lib/ui/Switch.d.ts +8 -0
  377. package/lib/ui/Switch.js +6 -0
  378. package/lib/ui/TextInput.d.ts +13 -0
  379. package/lib/ui/TextInput.js +7 -0
  380. package/lib/utils/docSerialization.d.ts +3 -0
  381. package/lib/utils/docSerialization.js +60 -0
  382. package/lib/utils/emoji-list.d.ts +20 -0
  383. package/lib/utils/emoji-list.js +16609 -0
  384. package/lib/utils/getDOMRangeRect.d.ts +8 -0
  385. package/lib/utils/getDOMRangeRect.js +26 -0
  386. package/lib/utils/getSelectedNode.d.ts +2 -0
  387. package/lib/utils/getSelectedNode.js +28 -0
  388. package/lib/utils/getThemeSelector.d.ts +2 -0
  389. package/lib/utils/getThemeSelector.js +14 -0
  390. package/lib/utils/isMobileWidth.d.ts +7 -0
  391. package/lib/utils/isMobileWidth.js +11 -0
  392. package/lib/utils/joinClasses.d.ts +1 -0
  393. package/lib/utils/joinClasses.js +7 -0
  394. package/lib/utils/setFloatingElemPosition.d.ts +1 -0
  395. package/lib/utils/setFloatingElemPosition.js +59 -0
  396. package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +1 -0
  397. package/lib/utils/setFloatingElemPositionForLinkEditor.js +36 -0
  398. package/lib/utils/swipe.d.ts +4 -0
  399. package/lib/utils/swipe.js +94 -0
  400. package/lib/utils/url.d.ts +2 -0
  401. package/lib/utils/url.js +31 -0
  402. package/package.json +4 -4
@@ -0,0 +1,393 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $createParagraphNode, $isElementNode } from 'lexical';
6
+ import { getNodeMapper } from '../nodes/NodesMapper';
7
+ import { invariant } from '../utils/Invariant';
8
+ /**
9
+ * Create ElementNode in Loro tree
10
+ */
11
+ export function createElementNodeInLoro(nodeKey, elementType, // 'paragraph', 'heading', 'quote', 'link', etc.
12
+ parentId, index, metadata, lexicalNodeJSON, // JSON object from exportJSON()
13
+ options) {
14
+ const mapper = getNodeMapper();
15
+ // Use mapper to get or create the tree node (don't pass lexicalNode to avoid context issues)
16
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, parentId, index);
17
+ // Store complete lexical node data as JSON object (without the key) if provided
18
+ if (lexicalNodeJSON) {
19
+ // Remove all key-related fields and children from lexical node data
20
+ const { key, __key, lexicalKey, children, ...cleanedLexicalData } = lexicalNodeJSON;
21
+ treeNode.data.set('lexical', cleanedLexicalData);
22
+ }
23
+ // Store only essential metadata (elementType for debug panel)
24
+ treeNode.data.set('elementType', elementType);
25
+ treeNode.data.set('createdAt', Date.now());
26
+ // Return the TreeID from the node's ID
27
+ return treeNode.id;
28
+ }
29
+ /**
30
+ * Update ElementNode in Loro tree
31
+ */
32
+ export function updateElementNodeInLoro(nodeKey, elementType, parentId, index, previousSiblingId, nextSiblingId, metadata, lexicalNodeJSON, // JSON object from exportJSON()
33
+ options) {
34
+ const mapper = getNodeMapper();
35
+ // Get the existing tree node using the mapper (don't pass lexicalNode to avoid context issues)
36
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
37
+ // Store the lexical node data if provided
38
+ if (lexicalNodeJSON) {
39
+ const { key, __key, lexicalKey, children, ...cleanedLexicalData } = lexicalNodeJSON;
40
+ treeNode.data.set('lexical', cleanedLexicalData);
41
+ }
42
+ // Update only essential metadata
43
+ if (elementType !== undefined) {
44
+ treeNode.data.set('elementType', elementType);
45
+ }
46
+ // Move the node only if its position in Loro actually differs from Lexical.
47
+ if (parentId !== undefined || index !== undefined) {
48
+ const { tree } = options;
49
+ // A node can never be its own parent — that indicates a wrong parent
50
+ // mapping upstream, not something to silently skip.
51
+ invariant(!(parentId && treeNode.id === parentId), 'updateElementNodeInLoro: cycle move (node is its own parent)', { nodeKey, treeId: treeNode.id });
52
+ // Where does the node currently sit in the Loro tree?
53
+ const currentParent = treeNode.parent();
54
+ const currentParentId = currentParent ? currentParent.id : undefined;
55
+ const siblings = currentParent ? (currentParent.children() ?? []) : tree.roots();
56
+ const currentIndex = siblings.findIndex(child => child.id === treeNode.id);
57
+ const sameParent = currentParentId === parentId;
58
+ // Re-issuing a move on every content edit is unnecessary and races with
59
+ // sibling creation (the classic source of "index out of range"). Only move
60
+ // when the parent or index genuinely changed. This is a real no-op check,
61
+ // not a masked failure.
62
+ const needsMove = !sameParent || (index !== undefined && index !== currentIndex);
63
+ if (needsMove) {
64
+ const parentNode = parentId ? tree.getNodeByID(parentId) : null;
65
+ const parentChildCount = parentNode
66
+ ? (parentNode.children()?.length ?? 0)
67
+ : tree.roots().length;
68
+ if (index !== undefined) {
69
+ // Loro move index bounds:
70
+ // same-parent reorder : [0, children.length - 1]
71
+ // cross-parent move : [0, children.length]
72
+ // An index outside this range means the position was computed against
73
+ // siblings that are not yet synced. Before failing, resolve index
74
+ // from mapped sibling anchors when available.
75
+ let targetIndex = index;
76
+ const maxIndex = sameParent
77
+ ? Math.max(parentChildCount - 1, 0)
78
+ : parentChildCount;
79
+ if (targetIndex < 0 || targetIndex > maxIndex) {
80
+ const targetSiblings = parentNode
81
+ ? (parentNode.children() ?? [])
82
+ : tree.roots();
83
+ if (previousSiblingId) {
84
+ const prevIndex = targetSiblings.findIndex(child => child.id === previousSiblingId);
85
+ if (prevIndex >= 0) {
86
+ targetIndex = prevIndex + 1;
87
+ }
88
+ }
89
+ if ((targetIndex < 0 || targetIndex > maxIndex) && nextSiblingId) {
90
+ const nextIndex = targetSiblings.findIndex(child => child.id === nextSiblingId);
91
+ if (nextIndex >= 0) {
92
+ targetIndex = nextIndex;
93
+ }
94
+ }
95
+ // A move can observe transiently sparse sibling mappings within one
96
+ // update batch (e.g. pressing Enter at the end of the document, where
97
+ // the sibling created in the same batch is not yet mapped). When the
98
+ // anchors cannot resolve the position, clamp into the valid Loro range
99
+ // instead of throwing: a hard failure rolls back the user's keystroke,
100
+ // whereas a bounded placement still converges via the CRDT and can be
101
+ // refined by subsequent updates.
102
+ if (targetIndex < 0 || targetIndex > maxIndex) {
103
+ const clamped = Math.min(Math.max(targetIndex, 0), maxIndex);
104
+ console.warn(`[loro-collab] updateElementNodeInLoro: clamping out-of-range move index`, {
105
+ nodeKey,
106
+ treeId: treeNode.id,
107
+ index,
108
+ targetIndex,
109
+ clamped,
110
+ maxIndex,
111
+ sameParent,
112
+ previousSiblingId,
113
+ nextSiblingId,
114
+ });
115
+ targetIndex = clamped;
116
+ }
117
+ }
118
+ tree.move(treeNode.id, parentId, targetIndex);
119
+ }
120
+ else {
121
+ tree.move(treeNode.id, parentId, parentChildCount);
122
+ }
123
+ }
124
+ }
125
+ // The exported Lexical node data is already propagated by the mapper.
126
+ treeNode.data.set('lastUpdated', Date.now());
127
+ }
128
+ /**
129
+ * Delete ElementNode from Loro tree
130
+ */
131
+ export function deleteElementNodeInLoro(nodeKey, options) {
132
+ const mapper = getNodeMapper();
133
+ mapper.deleteMapping(nodeKey);
134
+ }
135
+ /**
136
+ * Create ElementNode in Lexical from Loro tree data
137
+ */
138
+ export function createElementNodeFromLoro(treeId, parentNode, // The Lexical parent node where this should be inserted
139
+ index, options) {
140
+ const { tree } = options;
141
+ if (!tree.has(treeId)) {
142
+ return null;
143
+ }
144
+ const treeNode = tree.getNodeByID(treeId);
145
+ if (!treeNode) {
146
+ return null;
147
+ }
148
+ // Get LexicalNodeData (JSON object format only)
149
+ const lexicalData = treeNode.data.get('lexical');
150
+ let elementNode;
151
+ if (lexicalData && typeof lexicalData === 'object') {
152
+ try {
153
+ // lexicalData is a direct JSON object, create the appropriate node type
154
+ const lexicalDataObj = lexicalData;
155
+ const nodeType = lexicalDataObj.type || lexicalDataObj.__type;
156
+ if (nodeType === 'paragraph') {
157
+ elementNode = $createParagraphNode();
158
+ }
159
+ else {
160
+ // For other node types, fall back to paragraph for now
161
+ console.warn(`Unsupported ElementNode type: ${nodeType}, creating paragraph instead`);
162
+ elementNode = $createParagraphNode();
163
+ }
164
+ // Apply formatting if available
165
+ if (lexicalDataObj.format || lexicalDataObj.__format) {
166
+ elementNode.setFormat(lexicalDataObj.format || lexicalDataObj.__format);
167
+ }
168
+ }
169
+ catch (error) {
170
+ console.warn('Failed to create ElementNode from JSON data for TreeID:', treeId, error);
171
+ return null;
172
+ }
173
+ }
174
+ else {
175
+ // No lexical JSON data found - cannot create ElementNode
176
+ console.warn('No lexical JSON data found for ElementNode TreeID:', treeId);
177
+ return null;
178
+ }
179
+ // Insert into the parent at the specified index
180
+ if (index !== undefined && index >= 0) {
181
+ parentNode.splice(index, 0, [elementNode]);
182
+ }
183
+ else {
184
+ parentNode.append(elementNode);
185
+ }
186
+ return elementNode;
187
+ }
188
+ /**
189
+ * Update ElementNode in Lexical from Loro tree data
190
+ */
191
+ export function updateElementNodeFromLoro(treeId, lexicalNode, newParentNode, newIndex, options) {
192
+ const { tree } = options;
193
+ if (!tree.has(treeId)) {
194
+ return;
195
+ }
196
+ const treeNode = tree.getNodeByID(treeId);
197
+ if (!treeNode || treeNode.data.get('nodeType') !== 'element') {
198
+ return;
199
+ }
200
+ // Update formatting if it has changed
201
+ const format = treeNode.data.get('format');
202
+ if (format !== undefined && typeof lexicalNode.setFormat === 'function' && typeof format === 'number') {
203
+ lexicalNode.setFormat(format);
204
+ }
205
+ const style = treeNode.data.get('style');
206
+ if (style !== undefined && typeof lexicalNode.setStyle === 'function' && typeof style === 'string') {
207
+ lexicalNode.setStyle(style);
208
+ }
209
+ const direction = treeNode.data.get('direction');
210
+ if (direction !== undefined && typeof lexicalNode.setDirection === 'function' &&
211
+ (direction === 'ltr' || direction === 'rtl')) {
212
+ lexicalNode.setDirection(direction);
213
+ }
214
+ // If parent or position changed, move the node
215
+ if (newParentNode && newIndex !== undefined) {
216
+ // Remove from current location
217
+ lexicalNode.remove();
218
+ // Insert at new location
219
+ newParentNode.splice(newIndex, 0, [lexicalNode]);
220
+ }
221
+ }
222
+ /**
223
+ * Delete ElementNode from Lexical
224
+ */
225
+ export function deleteElementNodeFromLoro(treeId, lexicalNode, options) {
226
+ if ($isElementNode(lexicalNode)) {
227
+ lexicalNode.remove();
228
+ }
229
+ }
230
+ /**
231
+ * Utility to check if a tree node represents an ElementNode
232
+ */
233
+ export function isElementNodeInTree(treeId, tree) {
234
+ if (!tree.has(treeId)) {
235
+ return false;
236
+ }
237
+ const treeNode = tree.getNodeByID(treeId);
238
+ return treeNode?.data.get('nodeType') === 'element';
239
+ }
240
+ /**
241
+ * Get ElementNode data from Loro tree
242
+ */
243
+ export function getElementNodeDataFromTree(treeId, tree) {
244
+ if (!tree.has(treeId)) {
245
+ return null;
246
+ }
247
+ const treeNode = tree.getNodeByID(treeId);
248
+ if (!treeNode || treeNode.data.get('nodeType') !== 'element') {
249
+ return null;
250
+ }
251
+ return {
252
+ nodeType: 'element',
253
+ elementType: treeNode.data.get('elementType'),
254
+ format: treeNode.data.get('format'),
255
+ style: treeNode.data.get('style'),
256
+ direction: treeNode.data.get('direction'),
257
+ level: treeNode.data.get('level'), // For headings
258
+ createdAt: treeNode.data.get('createdAt'),
259
+ lastUpdated: treeNode.data.get('lastUpdated'),
260
+ };
261
+ }
262
+ /**
263
+ * Sync ElementNode children relationships in Loro tree
264
+ */
265
+ export function syncElementNodeChildrenInLoro(nodeKey, childKeys, options) {
266
+ const mapper = getNodeMapper();
267
+ const { tree } = options;
268
+ // Get the existing Loro node from the mapper
269
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey);
270
+ if (!treeNode || treeNode.data.get('nodeType') !== 'element') {
271
+ return;
272
+ }
273
+ // Store children relationships for collaborative editing
274
+ treeNode.data.set('childKeys', childKeys);
275
+ treeNode.data.set('childrenLastUpdated', Date.now());
276
+ }
277
+ /**
278
+ * Main propagate method for ElementNode - propagates all mutation types
279
+ */
280
+ export function propagateElementNode(update, mutation, nodeKey, options) {
281
+ const { tree, peerId } = options;
282
+ switch (mutation) {
283
+ case 'created': {
284
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
285
+ if (currentNode && $isElementNode(currentNode)) {
286
+ // Export node data and collect metadata within editor context
287
+ let parent, parentId, index;
288
+ let elementType;
289
+ const metadata = {};
290
+ let lexicalNodeJSON;
291
+ update.editorState.read(() => {
292
+ // Get parent and index for proper positioning within editor state context
293
+ parent = currentNode.getParent();
294
+ // Get parentId from the mapper instead of constructing it manually
295
+ const mapper = getNodeMapper();
296
+ parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
297
+ index = currentNode.getIndexWithinParent();
298
+ if (parentId) {
299
+ const ownTreeID = mapper.getTreeIDByLexicalKey(nodeKey);
300
+ if (ownTreeID === parentId) {
301
+ parentId = undefined; // Prevent cycle
302
+ }
303
+ }
304
+ // Determine element type
305
+ elementType = currentNode.getType(); // 'paragraph', 'heading', etc.
306
+ // If parent exists but doesn't have mapping yet, this shouldn't happen
307
+ // because SyncLexicalToLoro sorts element mutations by depth.
308
+ // But as a safety net, log a warning.
309
+ if (parent && !parentId) {
310
+ console.warn(` ElementNodePropagator: parent mapping missing for ${elementType} nodeKey=${nodeKey}, parentKey=${parent.getKey()}`);
311
+ }
312
+ // Collect metadata (format, style, direction, etc.)
313
+ if (typeof currentNode.getFormat === 'function') {
314
+ metadata.format = currentNode.getFormat();
315
+ }
316
+ if (typeof currentNode.getStyle === 'function') {
317
+ metadata.style = currentNode.getStyle();
318
+ }
319
+ if (typeof currentNode.getDirection === 'function') {
320
+ metadata.direction = currentNode.getDirection();
321
+ }
322
+ // Export node data within editor context where node methods are available
323
+ lexicalNodeJSON = currentNode.exportJSON();
324
+ });
325
+ // Create the node in Loro after safely reading from editor state
326
+ createElementNodeInLoro(nodeKey, elementType, parentId, index, metadata, lexicalNodeJSON, options);
327
+ }
328
+ break;
329
+ }
330
+ case 'updated': {
331
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
332
+ if (currentNode && $isElementNode(currentNode)) {
333
+ // Use editorState.read() to safely access node methods
334
+ let parent, parentId, index;
335
+ let previousSiblingId;
336
+ let nextSiblingId;
337
+ let elementType;
338
+ const metadata = {};
339
+ // Export node data and collect metadata within editor context
340
+ let lexicalNodeJSON;
341
+ update.editorState.read(() => {
342
+ // Get current position within editor state context
343
+ parent = currentNode.getParent();
344
+ // Get parentId from the mapper instead of constructing it manually
345
+ const mapper = getNodeMapper();
346
+ parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
347
+ index = currentNode.getIndexWithinParent();
348
+ // Resolve nearest mapped sibling anchors to stabilize target index
349
+ // when Lexical index includes siblings not yet represented in Loro.
350
+ if (parent) {
351
+ const siblings = parent.getChildren();
352
+ for (let i = index - 1; i >= 0; i--) {
353
+ const candidate = siblings[i];
354
+ const candidateTreeId = mapper.getTreeIDByLexicalKey(candidate.getKey());
355
+ if (candidateTreeId && tree.has(candidateTreeId)) {
356
+ previousSiblingId = candidateTreeId;
357
+ break;
358
+ }
359
+ }
360
+ for (let i = index + 1; i < siblings.length; i++) {
361
+ const candidate = siblings[i];
362
+ const candidateTreeId = mapper.getTreeIDByLexicalKey(candidate.getKey());
363
+ if (candidateTreeId && tree.has(candidateTreeId)) {
364
+ nextSiblingId = candidateTreeId;
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ // Get element type and metadata
370
+ elementType = currentNode.getType();
371
+ if (typeof currentNode.getFormat === 'function') {
372
+ metadata.format = currentNode.getFormat();
373
+ }
374
+ if (typeof currentNode.getStyle === 'function') {
375
+ metadata.style = currentNode.getStyle();
376
+ }
377
+ if (typeof currentNode.getDirection === 'function') {
378
+ metadata.direction = currentNode.getDirection();
379
+ }
380
+ // Export node data within editor context where node methods are available
381
+ lexicalNodeJSON = currentNode.exportJSON();
382
+ });
383
+ // Update the node in Loro after safely reading from editor state
384
+ updateElementNodeInLoro(nodeKey, elementType, parentId, index, previousSiblingId, nextSiblingId, metadata, lexicalNodeJSON, options);
385
+ }
386
+ break;
387
+ }
388
+ case 'destroyed': {
389
+ deleteElementNodeInLoro(nodeKey, options);
390
+ break;
391
+ }
392
+ }
393
+ }
@@ -0,0 +1,57 @@
1
+ import { TreeID, LoroTree } from 'loro-crdt';
2
+ import { LineBreakNode, UpdateListenerPayload, NodeKey, ElementNode } from 'lexical';
3
+ import { Binding } from '../Bindings';
4
+ /**
5
+ * LineBreakNode Propagator for Loro Tree Collaboration
6
+ *
7
+ * LineBreakNode characteristics:
8
+ * - Represents '\n' characters in the editor
9
+ * - Should never have '\n' in text nodes, use LineBreakNode instead
10
+ * - Works consistently across browsers and operating systems
11
+ * - Is a leaf node (cannot have children)
12
+ * - Cannot be extended/subclassed
13
+ */
14
+ export interface LineBreakNodeMutatorOptions {
15
+ binding: Binding;
16
+ tree: LoroTree;
17
+ peerId: number;
18
+ }
19
+ /**
20
+ * Create LineBreakNode in Loro tree
21
+ */
22
+ export declare function createLineBreakNodeInLoro(nodeKey: NodeKey, parentId?: TreeID, index?: number, lexicalNodeJSON?: any, // JSON object from exportJSON()
23
+ options?: LineBreakNodeMutatorOptions): TreeID;
24
+ /**
25
+ * Update LineBreakNode in Loro tree
26
+ * Note: LineBreakNodes typically don't change much since they represent '\n'
27
+ */
28
+ export declare function updateLineBreakNodeInLoro(nodeKey: NodeKey, parentId?: TreeID, index?: number, lexicalNodeJSON?: any, // JSON object from exportJSON()
29
+ options?: LineBreakNodeMutatorOptions): void;
30
+ /**
31
+ * Delete LineBreakNode from Loro tree
32
+ */
33
+ export declare function deleteLineBreakNodeInLoro(nodeKey: NodeKey, options: LineBreakNodeMutatorOptions): void;
34
+ /**
35
+ * Create LineBreakNode in Lexical from Loro tree data
36
+ */
37
+ export declare function createLineBreakNodeFromLoro(treeId: TreeID, parentNode: ElementNode, index?: number, options?: LineBreakNodeMutatorOptions): LineBreakNode;
38
+ /**
39
+ * Update LineBreakNode in Lexical from Loro tree data
40
+ */
41
+ export declare function updateLineBreakNodeFromLoro(treeId: TreeID, lexicalNode: LineBreakNode, newParentNode?: ElementNode, newIndex?: number, options?: LineBreakNodeMutatorOptions): void;
42
+ /**
43
+ * Delete LineBreakNode from Lexical
44
+ */
45
+ export declare function deleteLineBreakNodeFromLoro(treeId: TreeID, lexicalNode: LineBreakNode, options?: LineBreakNodeMutatorOptions): void;
46
+ /**
47
+ * Utility to check if a tree node represents a LineBreakNode
48
+ */
49
+ export declare function isLineBreakNodeInTree(treeId: TreeID, tree: LoroTree): boolean;
50
+ /**
51
+ * Get LineBreakNode data from Loro tree
52
+ */
53
+ export declare function getLineBreakNodeDataFromTree(treeId: TreeID, tree: LoroTree): any;
54
+ /**
55
+ * Main propagate method for LineBreakNode - propagates all mutation types
56
+ */
57
+ export declare function propagateLineBreakNode(update: UpdateListenerPayload, mutation: 'created' | 'updated' | 'destroyed', nodeKey: NodeKey, options: LineBreakNodeMutatorOptions): void;
@@ -0,0 +1,200 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $createLineBreakNode, $isLineBreakNode } from 'lexical';
6
+ import { getNodeMapper } from '../nodes/NodesMapper';
7
+ /**
8
+ * Create LineBreakNode in Loro tree
9
+ */
10
+ export function createLineBreakNodeInLoro(nodeKey, parentId, index, lexicalNodeJSON, // JSON object from exportJSON()
11
+ options) {
12
+ const mapper = getNodeMapper();
13
+ // Use mapper to get or create the tree node (don't pass lexicalNode to avoid context issues)
14
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, // don't pass lexicalNode to avoid context issues
15
+ parentId, index);
16
+ // Store complete lexical node data as clean JSON if provided
17
+ if (lexicalNodeJSON) {
18
+ // Store complete lexical JSON without all key-related fields and children
19
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
20
+ treeNode.data.set('lexical', cleanedData);
21
+ }
22
+ // Store only essential metadata
23
+ treeNode.data.set('elementType', 'linebreak');
24
+ treeNode.data.set('createdAt', Date.now());
25
+ // The exported Lexical node data is already propagated by the mapper
26
+ // Return the TreeID from the node's ID
27
+ return treeNode.id;
28
+ }
29
+ /**
30
+ * Update LineBreakNode in Loro tree
31
+ * Note: LineBreakNodes typically don't change much since they represent '\n'
32
+ */
33
+ export function updateLineBreakNodeInLoro(nodeKey, parentId, index, lexicalNodeJSON, // JSON object from exportJSON()
34
+ options) {
35
+ const mapper = getNodeMapper();
36
+ const { tree } = options;
37
+ // Get the existing Loro node from the mapper
38
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
39
+ if (!treeNode) {
40
+ return;
41
+ }
42
+ const treeId = treeNode.id;
43
+ // Store complete lexical node data as clean JSON if provided
44
+ if (lexicalNodeJSON) {
45
+ // Store complete lexical JSON without all key-related fields and children
46
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
47
+ treeNode.data.set('lexical', cleanedData);
48
+ }
49
+ // Move the node if parent or position changed
50
+ if (parentId !== undefined || index !== undefined) {
51
+ tree.move(treeId, parentId, index);
52
+ }
53
+ // Update only essential metadata
54
+ treeNode.data.set('elementType', 'linebreak');
55
+ treeNode.data.set('lastUpdated', Date.now());
56
+ }
57
+ /**
58
+ * Delete LineBreakNode from Loro tree
59
+ */
60
+ export function deleteLineBreakNodeInLoro(nodeKey, options) {
61
+ const mapper = getNodeMapper();
62
+ // Use the mapper's delete method which propagates TreeID lookup internally
63
+ mapper.deleteMapping(nodeKey);
64
+ }
65
+ /**
66
+ * Create LineBreakNode in Lexical from Loro tree data
67
+ */
68
+ export function createLineBreakNodeFromLoro(treeId, parentNode, index, options) {
69
+ const { tree } = options;
70
+ if (!tree.has(treeId)) {
71
+ return $createLineBreakNode(); // Fallback to empty line break
72
+ }
73
+ const treeNode = tree.getNodeByID(treeId);
74
+ let lineBreakNode;
75
+ // Get LexicalNodeData (JSON object format only)
76
+ const lexicalData = treeNode?.data.get('lexical');
77
+ if (lexicalData && typeof lexicalData === 'object') {
78
+ // lexicalData is a direct JSON object - LineBreak nodes are simple
79
+ lineBreakNode = $createLineBreakNode();
80
+ }
81
+ else {
82
+ // No lexical data - just create a new line break node
83
+ lineBreakNode = $createLineBreakNode();
84
+ }
85
+ // Insert into the parent at the specified index
86
+ if (index !== undefined && index >= 0) {
87
+ parentNode.splice(index, 0, [lineBreakNode]);
88
+ }
89
+ else {
90
+ parentNode.append(lineBreakNode);
91
+ }
92
+ return lineBreakNode;
93
+ }
94
+ /**
95
+ * Update LineBreakNode in Lexical from Loro tree data
96
+ */
97
+ export function updateLineBreakNodeFromLoro(treeId, lexicalNode, newParentNode, newIndex, options) {
98
+ // If parent or position changed, move the node
99
+ if (newParentNode && newIndex !== undefined) {
100
+ // Remove from current location
101
+ lexicalNode.remove();
102
+ // Insert at new location
103
+ newParentNode.splice(newIndex, 0, [lexicalNode]);
104
+ }
105
+ }
106
+ /**
107
+ * Delete LineBreakNode from Lexical
108
+ */
109
+ export function deleteLineBreakNodeFromLoro(treeId, lexicalNode, options) {
110
+ if ($isLineBreakNode(lexicalNode)) {
111
+ lexicalNode.remove();
112
+ }
113
+ }
114
+ /**
115
+ * Utility to check if a tree node represents a LineBreakNode
116
+ */
117
+ export function isLineBreakNodeInTree(treeId, tree) {
118
+ if (!tree.has(treeId)) {
119
+ return false;
120
+ }
121
+ const treeNode = tree.getNodeByID(treeId);
122
+ return treeNode?.data.get('nodeType') === 'linebreak';
123
+ }
124
+ /**
125
+ * Get LineBreakNode data from Loro tree
126
+ */
127
+ export function getLineBreakNodeDataFromTree(treeId, tree) {
128
+ if (!tree.has(treeId)) {
129
+ return null;
130
+ }
131
+ const treeNode = tree.getNodeByID(treeId);
132
+ if (!treeNode || treeNode.data.get('nodeType') !== 'linebreak') {
133
+ return null;
134
+ }
135
+ return {
136
+ nodeType: 'linebreak',
137
+ createdAt: treeNode.data.get('createdAt'),
138
+ lastUpdated: treeNode.data.get('lastUpdated'),
139
+ };
140
+ }
141
+ /**
142
+ * Main propagate method for LineBreakNode - propagates all mutation types
143
+ */
144
+ export function propagateLineBreakNode(update, mutation, nodeKey, options) {
145
+ const { tree, peerId } = options;
146
+ switch (mutation) {
147
+ case 'created': {
148
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
149
+ if (currentNode && $isLineBreakNode(currentNode)) {
150
+ // Get parent, positioning, and JSON data using editor state context
151
+ const { parentId, index, lexicalNodeJSON } = update.editorState.read(() => {
152
+ const parent = currentNode.getParent();
153
+ // Get parentId from the mapper instead of constructing it manually
154
+ const mapper = getNodeMapper();
155
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
156
+ const index = currentNode.getIndexWithinParent();
157
+ // Export node data as JSON object within editor context where node methods are available
158
+ let lexicalNodeJSON = undefined;
159
+ try {
160
+ lexicalNodeJSON = currentNode.exportJSON();
161
+ }
162
+ catch (error) {
163
+ console.warn('Failed to export node JSON in propagateLineBreakNode created:', error);
164
+ }
165
+ return { parentId, index, lexicalNodeJSON };
166
+ });
167
+ createLineBreakNodeInLoro(nodeKey, parentId, index, lexicalNodeJSON, options);
168
+ }
169
+ break;
170
+ }
171
+ case 'updated': {
172
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
173
+ if (currentNode && $isLineBreakNode(currentNode)) {
174
+ // Check if position changed and export data using editor state context
175
+ const { parentId, index, lexicalNodeJSON } = update.editorState.read(() => {
176
+ const parent = currentNode.getParent();
177
+ // Get parentId from the mapper instead of constructing it manually
178
+ const mapper = getNodeMapper();
179
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
180
+ const index = currentNode.getIndexWithinParent();
181
+ // Export node data within editor context where node methods are available
182
+ let lexicalNodeJSON = undefined;
183
+ try {
184
+ lexicalNodeJSON = currentNode.exportJSON();
185
+ }
186
+ catch (error) {
187
+ console.warn('Failed to export node data in propagateLineBreakNode updated:', error);
188
+ }
189
+ return { parentId, index, lexicalNodeJSON };
190
+ });
191
+ updateLineBreakNodeInLoro(nodeKey, parentId, index, lexicalNodeJSON, options);
192
+ }
193
+ break;
194
+ }
195
+ case 'destroyed': {
196
+ deleteLineBreakNodeInLoro(nodeKey, options);
197
+ break;
198
+ }
199
+ }
200
+ }