@datalayer/lexical-loro 0.2.4 β†’ 0.2.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 (399) hide show
  1. package/lib/App.d.ts +2 -0
  2. package/lib/App.js +141 -0
  3. package/lib/Editor.d.ts +2 -0
  4. package/lib/Editor.js +115 -0
  5. package/lib/Settings.d.ts +2 -0
  6. package/lib/Settings.js +57 -0
  7. package/lib/appSettings.d.ts +36 -0
  8. package/lib/appSettings.js +48 -0
  9. package/lib/collab/loro/Bindings.d.ts +41 -0
  10. package/lib/collab/loro/Bindings.js +99 -0
  11. package/lib/collab/loro/Debug.d.ts +33 -0
  12. package/lib/collab/loro/Debug.js +452 -0
  13. package/lib/collab/loro/LexicalCollaborationContext.d.ts +19 -0
  14. package/lib/collab/loro/LexicalCollaborationContext.js +52 -0
  15. package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +24 -0
  16. package/lib/collab/loro/LexicalCollaborationPlugin.js +83 -0
  17. package/lib/collab/loro/State.d.ts +53 -0
  18. package/lib/collab/loro/State.js +94 -0
  19. package/lib/collab/loro/components/LoroCollaborationUI.d.ts +13 -0
  20. package/lib/collab/loro/components/LoroCollaborationUI.js +9 -0
  21. package/lib/collab/loro/components/LoroCollaborators.d.ts +8 -0
  22. package/lib/collab/loro/components/LoroCollaborators.js +102 -0
  23. package/lib/collab/loro/components/index.d.ts +2 -0
  24. package/lib/collab/loro/components/index.js +6 -0
  25. package/lib/collab/loro/index.d.ts +6 -0
  26. package/lib/collab/loro/index.js +10 -0
  27. package/lib/collab/loro/integrators/BaseIntegrator.d.ts +14 -0
  28. package/lib/collab/loro/integrators/BaseIntegrator.js +5 -0
  29. package/lib/collab/loro/integrators/CounterIntegrator.d.ts +23 -0
  30. package/lib/collab/loro/integrators/CounterIntegrator.js +44 -0
  31. package/lib/collab/loro/integrators/ListIntegrator.d.ts +23 -0
  32. package/lib/collab/loro/integrators/ListIntegrator.js +53 -0
  33. package/lib/collab/loro/integrators/MapIntegrator.d.ts +24 -0
  34. package/lib/collab/loro/integrators/MapIntegrator.js +235 -0
  35. package/lib/collab/loro/integrators/TextIntegrator.d.ts +25 -0
  36. package/lib/collab/loro/integrators/TextIntegrator.js +55 -0
  37. package/lib/collab/loro/integrators/TreeIntegrator.d.ts +36 -0
  38. package/lib/collab/loro/integrators/TreeIntegrator.js +251 -0
  39. package/lib/collab/loro/nodes/NodeFactory.d.ts +15 -0
  40. package/lib/collab/loro/nodes/NodeFactory.js +101 -0
  41. package/lib/collab/loro/nodes/NodesMapper.d.ts +120 -0
  42. package/lib/collab/loro/nodes/NodesMapper.js +277 -0
  43. package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +60 -0
  44. package/lib/collab/loro/propagators/DecoratorNodePropagator.js +306 -0
  45. package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +62 -0
  46. package/lib/collab/loro/propagators/ElementNodePropagator.js +326 -0
  47. package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +57 -0
  48. package/lib/collab/loro/propagators/LineBreakNodePropagator.js +200 -0
  49. package/lib/collab/loro/propagators/RootNodePropagator.d.ts +55 -0
  50. package/lib/collab/loro/propagators/RootNodePropagator.js +174 -0
  51. package/lib/collab/loro/propagators/TextNodePropagator.d.ts +60 -0
  52. package/lib/collab/loro/propagators/TextNodePropagator.js +440 -0
  53. package/lib/collab/loro/propagators/index.d.ts +49 -0
  54. package/lib/collab/loro/propagators/index.js +30 -0
  55. package/lib/collab/loro/provider/websocket.d.ts +116 -0
  56. package/lib/collab/loro/provider/websocket.js +911 -0
  57. package/lib/collab/loro/servers/index.d.ts +0 -0
  58. package/lib/collab/loro/servers/index.js +4 -0
  59. package/lib/collab/loro/servers/ws/callback.d.ts +5 -0
  60. package/lib/collab/loro/servers/ws/callback.js +89 -0
  61. package/lib/collab/loro/servers/ws/server.d.ts +2 -0
  62. package/lib/collab/loro/servers/ws/server.js +29 -0
  63. package/lib/collab/loro/servers/ws/utils.d.ts +40 -0
  64. package/lib/collab/loro/servers/ws/utils.js +517 -0
  65. package/lib/collab/loro/sync/SyncCursors.d.ts +32 -0
  66. package/lib/collab/loro/sync/SyncCursors.js +475 -0
  67. package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +4 -0
  68. package/lib/collab/loro/sync/SyncLexicalToLoro.js +113 -0
  69. package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +5 -0
  70. package/lib/collab/loro/sync/SyncLoroToLexical.js +100 -0
  71. package/lib/collab/loro/types/LexicalNodeData.d.ts +32 -0
  72. package/lib/collab/loro/types/LexicalNodeData.js +75 -0
  73. package/lib/collab/loro/useCollaboration.d.ts +12 -0
  74. package/lib/collab/loro/useCollaboration.js +260 -0
  75. package/lib/collab/loro/utils/InitialContent.d.ts +64 -0
  76. package/lib/collab/loro/utils/InitialContent.js +113 -0
  77. package/lib/collab/loro/utils/LexicalToLoro.d.ts +18 -0
  78. package/lib/collab/loro/utils/LexicalToLoro.js +100 -0
  79. package/lib/collab/loro/utils/Utils.d.ts +44 -0
  80. package/lib/collab/loro/utils/Utils.js +157 -0
  81. package/lib/collab/loro/wsProvider.d.ts +8 -0
  82. package/lib/collab/loro/wsProvider.js +35 -0
  83. package/lib/collab/utils/invariant.d.ts +1 -0
  84. package/lib/collab/utils/invariant.js +15 -0
  85. package/lib/collab/utils/simpleDiffWithCursor.d.ts +5 -0
  86. package/lib/collab/utils/simpleDiffWithCursor.js +35 -0
  87. package/lib/collab/yjs/Bindings.d.ts +23 -0
  88. package/lib/collab/yjs/Bindings.js +26 -0
  89. package/lib/collab/yjs/Debug.d.ts +23 -0
  90. package/lib/collab/yjs/Debug.js +213 -0
  91. package/lib/collab/yjs/LexicalCollaborationContext.d.ts +10 -0
  92. package/lib/collab/yjs/LexicalCollaborationContext.js +37 -0
  93. package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +21 -0
  94. package/lib/collab/yjs/LexicalCollaborationPlugin.js +63 -0
  95. package/lib/collab/yjs/State.d.ts +51 -0
  96. package/lib/collab/yjs/State.js +35 -0
  97. package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +5 -0
  98. package/lib/collab/yjs/nodes/AnyCollabNode.js +1 -0
  99. package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +22 -0
  100. package/lib/collab/yjs/nodes/CollabDecoratorNode.js +64 -0
  101. package/lib/collab/yjs/nodes/CollabElementNode.d.ts +40 -0
  102. package/lib/collab/yjs/nodes/CollabElementNode.js +462 -0
  103. package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +19 -0
  104. package/lib/collab/yjs/nodes/CollabLineBreakNode.js +44 -0
  105. package/lib/collab/yjs/nodes/CollabTextNode.d.ts +25 -0
  106. package/lib/collab/yjs/nodes/CollabTextNode.js +103 -0
  107. package/lib/collab/yjs/provider/websocket.d.ts +88 -0
  108. package/lib/collab/yjs/provider/websocket.js +415 -0
  109. package/lib/collab/yjs/servers/index.d.ts +0 -0
  110. package/lib/collab/yjs/servers/index.js +0 -0
  111. package/lib/collab/yjs/servers/ws/callback.d.ts +5 -0
  112. package/lib/collab/yjs/servers/ws/callback.js +72 -0
  113. package/lib/collab/yjs/servers/ws/server.d.ts +2 -0
  114. package/lib/collab/yjs/servers/ws/server.js +25 -0
  115. package/lib/collab/yjs/servers/ws/utils.d.ts +49 -0
  116. package/lib/collab/yjs/servers/ws/utils.js +284 -0
  117. package/lib/collab/yjs/sync/SyncCursors.d.ts +39 -0
  118. package/lib/collab/yjs/sync/SyncCursors.js +351 -0
  119. package/lib/collab/yjs/sync/SyncEditorStates.d.ts +10 -0
  120. package/lib/collab/yjs/sync/SyncEditorStates.js +200 -0
  121. package/lib/collab/yjs/useCollaboration.d.ts +12 -0
  122. package/lib/collab/yjs/useCollaboration.js +255 -0
  123. package/lib/collab/yjs/utils/Utils.d.ts +25 -0
  124. package/lib/collab/yjs/utils/Utils.js +402 -0
  125. package/lib/collab/yjs/wsProvider.d.ts +3 -0
  126. package/lib/collab/yjs/wsProvider.js +21 -0
  127. package/lib/commenting/index.d.ts +41 -0
  128. package/lib/commenting/index.js +328 -0
  129. package/lib/context/FlashMessageContext.d.ts +7 -0
  130. package/lib/context/FlashMessageContext.js +24 -0
  131. package/lib/context/SettingsContext.d.ts +12 -0
  132. package/lib/context/SettingsContext.js +38 -0
  133. package/lib/context/SharedHistoryContext.d.ts +11 -0
  134. package/lib/context/SharedHistoryContext.js +11 -0
  135. package/lib/context/ToolbarContext.d.ts +65 -0
  136. package/lib/context/ToolbarContext.js +84 -0
  137. package/lib/demo.d.ts +12 -0
  138. package/lib/demo.js +45 -0
  139. package/lib/hooks/useFlashMessage.d.ts +2 -0
  140. package/lib/hooks/useFlashMessage.js +8 -0
  141. package/lib/hooks/useModal.d.ts +5 -0
  142. package/lib/hooks/useModal.js +26 -0
  143. package/lib/hooks/useReport.d.ts +1 -0
  144. package/lib/hooks/useReport.js +50 -0
  145. package/lib/index.d.ts +1 -0
  146. package/lib/index.js +5 -0
  147. package/lib/nodes/AutocompleteNode.d.ts +27 -0
  148. package/lib/nodes/AutocompleteNode.js +60 -0
  149. package/lib/nodes/CounterComponent.d.ts +6 -0
  150. package/lib/nodes/CounterComponent.js +137 -0
  151. package/lib/nodes/CounterNode.d.ts +23 -0
  152. package/lib/nodes/CounterNode.js +47 -0
  153. package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +8 -0
  154. package/lib/nodes/DateTimeNode/DateTimeComponent.js +119 -0
  155. package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +27 -0
  156. package/lib/nodes/DateTimeNode/DateTimeNode.js +82 -0
  157. package/lib/nodes/EmojiNode.d.ts +18 -0
  158. package/lib/nodes/EmojiNode.js +54 -0
  159. package/lib/nodes/EquationComponent.d.ts +9 -0
  160. package/lib/nodes/EquationComponent.js +75 -0
  161. package/lib/nodes/EquationNode.d.ts +26 -0
  162. package/lib/nodes/EquationNode.js +109 -0
  163. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +8 -0
  164. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +110 -0
  165. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +50 -0
  166. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +55 -0
  167. package/lib/nodes/ExcalidrawNode/index.d.ts +32 -0
  168. package/lib/nodes/ExcalidrawNode/index.js +117 -0
  169. package/lib/nodes/FigmaNode.d.ts +20 -0
  170. package/lib/nodes/FigmaNode.js +52 -0
  171. package/lib/nodes/ImageComponent.d.ts +16 -0
  172. package/lib/nodes/ImageComponent.js +272 -0
  173. package/lib/nodes/ImageNode.d.ts +50 -0
  174. package/lib/nodes/ImageNode.js +151 -0
  175. package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +26 -0
  176. package/lib/nodes/InlineImageNode/InlineImageComponent.js +161 -0
  177. package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +59 -0
  178. package/lib/nodes/InlineImageNode/InlineImageNode.js +162 -0
  179. package/lib/nodes/KeywordNode.d.ts +14 -0
  180. package/lib/nodes/KeywordNode.js +37 -0
  181. package/lib/nodes/LayoutContainerNode.d.ts +24 -0
  182. package/lib/nodes/LayoutContainerNode.js +95 -0
  183. package/lib/nodes/LayoutItemNode.d.ts +16 -0
  184. package/lib/nodes/LayoutItemNode.js +69 -0
  185. package/lib/nodes/MentionNode.d.ts +20 -0
  186. package/lib/nodes/MentionNode.js +85 -0
  187. package/lib/nodes/PageBreakNode/index.d.ts +17 -0
  188. package/lib/nodes/PageBreakNode/index.js +83 -0
  189. package/lib/nodes/PlaygroundNodes.d.ts +3 -0
  190. package/lib/nodes/PlaygroundNodes.js +75 -0
  191. package/lib/nodes/PollComponent.d.ts +9 -0
  192. package/lib/nodes/PollComponent.js +85 -0
  193. package/lib/nodes/PollNode.d.ts +43 -0
  194. package/lib/nodes/PollNode.js +153 -0
  195. package/lib/nodes/SpecialTextNode.d.ts +24 -0
  196. package/lib/nodes/SpecialTextNode.js +54 -0
  197. package/lib/nodes/StickyComponent.d.ts +10 -0
  198. package/lib/nodes/StickyComponent.js +162 -0
  199. package/lib/nodes/StickyNode.d.ts +31 -0
  200. package/lib/nodes/StickyNode.js +76 -0
  201. package/lib/nodes/TweetNode.d.ts +21 -0
  202. package/lib/nodes/TweetNode.js +119 -0
  203. package/lib/nodes/YouTubeNode.d.ts +22 -0
  204. package/lib/nodes/YouTubeNode.js +84 -0
  205. package/lib/plugins/ActionsPlugin/index.d.ts +5 -0
  206. package/lib/plugins/ActionsPlugin/index.js +168 -0
  207. package/lib/plugins/AutoEmbedPlugin/index.d.ts +19 -0
  208. package/lib/plugins/AutoEmbedPlugin/index.js +158 -0
  209. package/lib/plugins/AutoLinkPlugin/index.d.ts +2 -0
  210. package/lib/plugins/AutoLinkPlugin/index.js +15 -0
  211. package/lib/plugins/AutocompletePlugin/index.d.ts +10 -0
  212. package/lib/plugins/AutocompletePlugin/index.js +2477 -0
  213. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +7 -0
  214. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +46 -0
  215. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +17 -0
  216. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +115 -0
  217. package/lib/plugins/CodeActionMenuPlugin/index.d.ts +5 -0
  218. package/lib/plugins/CodeActionMenuPlugin/index.js +104 -0
  219. package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +1 -0
  220. package/lib/plugins/CodeActionMenuPlugin/utils.js +22 -0
  221. package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +2 -0
  222. package/lib/plugins/CodeHighlightPrismPlugin/index.js +14 -0
  223. package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +2 -0
  224. package/lib/plugins/CodeHighlightShikiPlugin/index.js +14 -0
  225. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +25 -0
  226. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +135 -0
  227. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +16 -0
  228. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +83 -0
  229. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +16 -0
  230. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +85 -0
  231. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +2 -0
  232. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +12 -0
  233. package/lib/plugins/CollapsiblePlugin/index.d.ts +3 -0
  234. package/lib/plugins/CollapsiblePlugin/index.js +132 -0
  235. package/lib/plugins/CommentPlugin/index.d.ts +9 -0
  236. package/lib/plugins/CommentPlugin/index.js +460 -0
  237. package/lib/plugins/ComponentPickerPlugin/index.d.ts +2 -0
  238. package/lib/plugins/ComponentPickerPlugin/index.js +276 -0
  239. package/lib/plugins/ContextMenuPlugin/index.d.ts +2 -0
  240. package/lib/plugins/ContextMenuPlugin/index.js +112 -0
  241. package/lib/plugins/CounterPlugin/index.d.ts +3 -0
  242. package/lib/plugins/CounterPlugin/index.js +24 -0
  243. package/lib/plugins/DateTimePlugin/index.d.ts +8 -0
  244. package/lib/plugins/DateTimePlugin/index.js +28 -0
  245. package/lib/plugins/DebugPlugin/index.d.ts +3 -0
  246. package/lib/plugins/DebugPlugin/index.js +219 -0
  247. package/lib/plugins/DocsPlugin/index.d.ts +2 -0
  248. package/lib/plugins/DocsPlugin/index.js +4 -0
  249. package/lib/plugins/DragDropPastePlugin/index.d.ts +1 -0
  250. package/lib/plugins/DragDropPastePlugin/index.js +37 -0
  251. package/lib/plugins/DraggableBlockPlugin/index.d.ts +12 -0
  252. package/lib/plugins/DraggableBlockPlugin/index.js +36 -0
  253. package/lib/plugins/EmojiPickerPlugin/index.d.ts +1 -0
  254. package/lib/plugins/EmojiPickerPlugin/index.js +84 -0
  255. package/lib/plugins/EmojisPlugin/index.d.ts +2 -0
  256. package/lib/plugins/EmojisPlugin/index.js +56 -0
  257. package/lib/plugins/EquationsPlugin/index.d.ts +14 -0
  258. package/lib/plugins/EquationsPlugin/index.js +34 -0
  259. package/lib/plugins/ExcalidrawPlugin/index.d.ts +5 -0
  260. package/lib/plugins/ExcalidrawPlugin/index.js +44 -0
  261. package/lib/plugins/FigmaPlugin/index.d.ts +4 -0
  262. package/lib/plugins/FigmaPlugin/index.js +24 -0
  263. package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +15 -0
  264. package/lib/plugins/FloatingLinkEditorPlugin/index.js +280 -0
  265. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +7 -0
  266. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +219 -0
  267. package/lib/plugins/ImagesPlugin/index.d.ts +24 -0
  268. package/lib/plugins/ImagesPlugin/index.js +195 -0
  269. package/lib/plugins/InlineImagePlugin/index.d.ts +17 -0
  270. package/lib/plugins/InlineImagePlugin/index.js +180 -0
  271. package/lib/plugins/KeywordsPlugin/index.d.ts +2 -0
  272. package/lib/plugins/KeywordsPlugin/index.js +35 -0
  273. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +6 -0
  274. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +21 -0
  275. package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +7 -0
  276. package/lib/plugins/LayoutPlugin/LayoutPlugin.js +135 -0
  277. package/lib/plugins/LinkPlugin/index.d.ts +6 -0
  278. package/lib/plugins/LinkPlugin/index.js +11 -0
  279. package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +2 -0
  280. package/lib/plugins/MarkdownShortcutPlugin/index.js +6 -0
  281. package/lib/plugins/MarkdownTransformers/index.d.ts +8 -0
  282. package/lib/plugins/MarkdownTransformers/index.js +238 -0
  283. package/lib/plugins/MaxLengthPlugin/index.d.ts +3 -0
  284. package/lib/plugins/MaxLengthPlugin/index.js +41 -0
  285. package/lib/plugins/MentionsPlugin/index.d.ts +2 -0
  286. package/lib/plugins/MentionsPlugin/index.js +564 -0
  287. package/lib/plugins/PageBreakPlugin/index.d.ts +4 -0
  288. package/lib/plugins/PageBreakPlugin/index.js +31 -0
  289. package/lib/plugins/PasteLogPlugin/index.d.ts +2 -0
  290. package/lib/plugins/PasteLogPlugin/index.js +27 -0
  291. package/lib/plugins/PollPlugin/index.d.ts +8 -0
  292. package/lib/plugins/PollPlugin/index.js +38 -0
  293. package/lib/plugins/ShortcutsPlugin/index.d.ts +6 -0
  294. package/lib/plugins/ShortcutsPlugin/index.js +116 -0
  295. package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +59 -0
  296. package/lib/plugins/ShortcutsPlugin/shortcuts.js +173 -0
  297. package/lib/plugins/SpecialTextPlugin/index.d.ts +2 -0
  298. package/lib/plugins/SpecialTextPlugin/index.js +50 -0
  299. package/lib/plugins/SpeechToTextPlugin/index.d.ts +5 -0
  300. package/lib/plugins/SpeechToTextPlugin/index.js +86 -0
  301. package/lib/plugins/StickyPlugin/index.d.ts +2 -0
  302. package/lib/plugins/StickyPlugin/index.js +16 -0
  303. package/lib/plugins/TabFocusPlugin/index.d.ts +1 -0
  304. package/lib/plugins/TabFocusPlugin/index.js +38 -0
  305. package/lib/plugins/TableActionMenuPlugin/index.d.ts +5 -0
  306. package/lib/plugins/TableActionMenuPlugin/index.js +492 -0
  307. package/lib/plugins/TableCellResizer/index.d.ts +3 -0
  308. package/lib/plugins/TableCellResizer/index.js +297 -0
  309. package/lib/plugins/TableHoverActionsPlugin/index.d.ts +4 -0
  310. package/lib/plugins/TableHoverActionsPlugin/index.js +188 -0
  311. package/lib/plugins/TableOfContentsPlugin/index.d.ts +2 -0
  312. package/lib/plugins/TableOfContentsPlugin/index.js +116 -0
  313. package/lib/plugins/TablePlugin.d.ts +31 -0
  314. package/lib/plugins/TablePlugin.js +63 -0
  315. package/lib/plugins/TestRecorderPlugin/index.d.ts +3 -0
  316. package/lib/plugins/TestRecorderPlugin/index.js +346 -0
  317. package/lib/plugins/ToolbarPlugin/fontSize.d.ts +9 -0
  318. package/lib/plugins/ToolbarPlugin/fontSize.js +84 -0
  319. package/lib/plugins/ToolbarPlugin/index.d.ts +9 -0
  320. package/lib/plugins/ToolbarPlugin/index.js +500 -0
  321. package/lib/plugins/ToolbarPlugin/utils.d.ts +26 -0
  322. package/lib/plugins/ToolbarPlugin/utils.js +247 -0
  323. package/lib/plugins/TreeViewPlugin/index.d.ts +2 -0
  324. package/lib/plugins/TreeViewPlugin/index.js +7 -0
  325. package/lib/plugins/TwitterPlugin/index.d.ts +4 -0
  326. package/lib/plugins/TwitterPlugin/index.js +24 -0
  327. package/lib/plugins/TypingPerfPlugin/index.d.ts +2 -0
  328. package/lib/plugins/TypingPerfPlugin/index.js +97 -0
  329. package/lib/plugins/YouTubePlugin/index.d.ts +4 -0
  330. package/lib/plugins/YouTubePlugin/index.js +24 -0
  331. package/lib/server/validation.d.ts +1 -0
  332. package/lib/server/validation.js +115 -0
  333. package/lib/setupEnv.d.ts +2 -0
  334. package/lib/setupEnv.js +29 -0
  335. package/lib/themes/CommentEditorTheme.d.ts +4 -0
  336. package/lib/themes/CommentEditorTheme.js +11 -0
  337. package/lib/themes/PlaygroundEditorTheme.d.ts +4 -0
  338. package/lib/themes/PlaygroundEditorTheme.js +124 -0
  339. package/lib/themes/StickyEditorTheme.d.ts +4 -0
  340. package/lib/themes/StickyEditorTheme.js +11 -0
  341. package/lib/tyes.dt.d.ts +12 -0
  342. package/lib/tyes.dt.js +4 -0
  343. package/lib/ui/Button.d.ts +12 -0
  344. package/lib/ui/Button.js +6 -0
  345. package/lib/ui/ColorPicker.d.ts +14 -0
  346. package/lib/ui/ColorPicker.js +219 -0
  347. package/lib/ui/ContentEditable.d.ts +9 -0
  348. package/lib/ui/ContentEditable.js +6 -0
  349. package/lib/ui/Dialog.d.ts +10 -0
  350. package/lib/ui/Dialog.js +8 -0
  351. package/lib/ui/DropDown.d.ts +18 -0
  352. package/lib/ui/DropDown.js +133 -0
  353. package/lib/ui/DropdownColorPicker.d.ts +13 -0
  354. package/lib/ui/DropdownColorPicker.js +6 -0
  355. package/lib/ui/EquationEditor.d.ts +8 -0
  356. package/lib/ui/EquationEditor.js +11 -0
  357. package/lib/ui/ExcalidrawModal.d.ts +42 -0
  358. package/lib/ui/ExcalidrawModal.js +103 -0
  359. package/lib/ui/FileInput.d.ts +10 -0
  360. package/lib/ui/FileInput.js +5 -0
  361. package/lib/ui/FlashMessage.d.ts +7 -0
  362. package/lib/ui/FlashMessage.js +6 -0
  363. package/lib/ui/ImageResizer.d.ts +17 -0
  364. package/lib/ui/ImageResizer.js +171 -0
  365. package/lib/ui/KatexEquationAlterer.d.ts +8 -0
  366. package/lib/ui/KatexEquationAlterer.js +23 -0
  367. package/lib/ui/KatexRenderer.d.ts +6 -0
  368. package/lib/ui/KatexRenderer.js +24 -0
  369. package/lib/ui/Modal.d.ts +9 -0
  370. package/lib/ui/Modal.js +48 -0
  371. package/lib/ui/Select.d.ts +8 -0
  372. package/lib/ui/Select.js +5 -0
  373. package/lib/ui/Switch.d.ts +8 -0
  374. package/lib/ui/Switch.js +6 -0
  375. package/lib/ui/TextInput.d.ts +13 -0
  376. package/lib/ui/TextInput.js +7 -0
  377. package/lib/utils/docSerialization.d.ts +3 -0
  378. package/lib/utils/docSerialization.js +60 -0
  379. package/lib/utils/emoji-list.d.ts +20 -0
  380. package/lib/utils/emoji-list.js +16609 -0
  381. package/lib/utils/getDOMRangeRect.d.ts +8 -0
  382. package/lib/utils/getDOMRangeRect.js +26 -0
  383. package/lib/utils/getSelectedNode.d.ts +2 -0
  384. package/lib/utils/getSelectedNode.js +28 -0
  385. package/lib/utils/getThemeSelector.d.ts +2 -0
  386. package/lib/utils/getThemeSelector.js +14 -0
  387. package/lib/utils/isMobileWidth.d.ts +7 -0
  388. package/lib/utils/isMobileWidth.js +11 -0
  389. package/lib/utils/joinClasses.d.ts +1 -0
  390. package/lib/utils/joinClasses.js +7 -0
  391. package/lib/utils/setFloatingElemPosition.d.ts +1 -0
  392. package/lib/utils/setFloatingElemPosition.js +59 -0
  393. package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +1 -0
  394. package/lib/utils/setFloatingElemPositionForLinkEditor.js +36 -0
  395. package/lib/utils/swipe.d.ts +4 -0
  396. package/lib/utils/swipe.js +94 -0
  397. package/lib/utils/url.d.ts +2 -0
  398. package/lib/utils/url.js +31 -0
  399. package/package.json +1 -1
@@ -0,0 +1,235 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $getNodeByKey, $isDecoratorNode } from 'lexical';
6
+ import { $diffTextContentAndApplyDelta } from '../utils/Utils';
7
+ /**
8
+ * Handles map data changes (node properties, metadata updates)
9
+ */
10
+ export class MapIntegrator {
11
+ integrate(diff, binding, provider) {
12
+ // Handle updated properties
13
+ if (diff.updated) {
14
+ Object.entries(diff.updated).forEach(([key, value]) => {
15
+ this.integratePropertyUpdate(key, value, binding, provider);
16
+ });
17
+ }
18
+ // Handle deleted properties
19
+ if (diff.deleted) {
20
+ diff.deleted.forEach((key) => {
21
+ this.integratePropertyDelete(key, binding, provider);
22
+ });
23
+ }
24
+ }
25
+ // Enhanced integrate method with TreeID context
26
+ integrateWithContext(diff, treeId, binding, provider) {
27
+ this.integrateWithContextInternal(diff, treeId, binding, provider);
28
+ }
29
+ // Internal method for use when already inside editor.update()
30
+ integrateInternal(diff, binding, provider) {
31
+ // Handle updated properties
32
+ if (diff.updated) {
33
+ Object.entries(diff.updated).forEach(([key, value]) => {
34
+ this.integratePropertyUpdate(key, value, binding, provider);
35
+ });
36
+ }
37
+ // Handle deleted properties
38
+ if (diff.deleted) {
39
+ diff.deleted.forEach((key) => {
40
+ this.integratePropertyDelete(key, binding, provider);
41
+ });
42
+ }
43
+ }
44
+ // Internal method for use when already inside editor.update() with context
45
+ integrateWithContextInternal(diff, treeId, binding, provider) {
46
+ // Handle updated properties with TreeID context
47
+ if (diff.updated) {
48
+ Object.entries(diff.updated).forEach(([key, value]) => {
49
+ this.integratePropertyUpdateWithContextInternal(key, value, treeId, binding, provider);
50
+ });
51
+ }
52
+ // Handle deleted properties
53
+ if (diff.deleted) {
54
+ diff.deleted.forEach((key) => {
55
+ this.integratePropertyDelete(key, binding, provider);
56
+ });
57
+ }
58
+ }
59
+ integratePropertyUpdateWithContext(key, value, treeId, binding, provider) {
60
+ // Handle specific property updates with TreeID context
61
+ switch (key) {
62
+ case 'lexical':
63
+ this.integrateLexicalDataUpdateWithContext(value, treeId, binding);
64
+ break;
65
+ case 'textContent':
66
+ // Text content updates should be integrated via lexical data updates
67
+ break;
68
+ case 'elementType':
69
+ // Element type changes are rare, mostly for debugging
70
+ break;
71
+ default:
72
+ //
73
+ }
74
+ }
75
+ // Internal version for use when already inside editor.update()
76
+ integratePropertyUpdateWithContextInternal(key, value, treeId, binding, provider) {
77
+ // Handle specific property updates with TreeID context
78
+ switch (key) {
79
+ case 'lexical':
80
+ // Extract TreeID and call internal method directly (already inside editor.update())
81
+ let actualTreeID = treeId;
82
+ if (typeof treeId === 'string' && treeId.startsWith('cid:')) {
83
+ const parts = treeId.split(':');
84
+ if (parts.length >= 3) {
85
+ actualTreeID = parts[1];
86
+ }
87
+ }
88
+ const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(actualTreeID);
89
+ if (lexicalKey) {
90
+ this.integrateLexicalDataUpdateInternal(value, lexicalKey, actualTreeID, binding);
91
+ }
92
+ break;
93
+ case 'textContent':
94
+ // Text content updates should be integrated via lexical data updates
95
+ break;
96
+ case 'elementType':
97
+ // Element type changes are rare, mostly for debugging
98
+ break;
99
+ default:
100
+ // Generic property update with context
101
+ break;
102
+ }
103
+ }
104
+ integratePropertyUpdate(key, value, binding, provider) {
105
+ // Handle specific property updates
106
+ switch (key) {
107
+ case 'lexical':
108
+ // Use targeted update only - the broad heuristic causes scrambling
109
+ break;
110
+ case 'textContent':
111
+ // Text content updates should be integrated via lexical data updates
112
+ break;
113
+ case 'elementType':
114
+ // Element type changes are rare, mostly for debugging
115
+ break;
116
+ default:
117
+ // Generic property update
118
+ break;
119
+ }
120
+ }
121
+ integratePropertyDelete(key, binding, provider) {
122
+ // Handle specific property deletions
123
+ switch (key) {
124
+ case 'lexical':
125
+ break;
126
+ default:
127
+ // Generic property deleted
128
+ break;
129
+ }
130
+ }
131
+ integrateLexicalDataUpdateWithContext(lexicalData, treeId, binding) {
132
+ // Extract the actual TreeID from container ID format
133
+ // Container ID format: "cid:6@7648424808278730813:Map"
134
+ // TreeID format: "6@7648424808278730813"
135
+ let actualTreeID = treeId;
136
+ if (typeof treeId === 'string' && treeId.startsWith('cid:')) {
137
+ const parts = treeId.split(':');
138
+ if (parts.length >= 3) {
139
+ actualTreeID = parts[1]; // Extract "6@7648424808278730813" from "cid:6@7648424808278730813:Map"
140
+ }
141
+ }
142
+ // Use the TreeID to find the specific Lexical node
143
+ const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(actualTreeID);
144
+ if (!lexicalKey) {
145
+ return;
146
+ }
147
+ if (lexicalData && typeof lexicalData === 'object') {
148
+ binding.editor.update(() => {
149
+ this.integrateLexicalDataUpdateInternal(lexicalData, lexicalKey, actualTreeID, binding);
150
+ });
151
+ }
152
+ }
153
+ // Internal method for use when already inside editor.update()
154
+ integrateLexicalDataUpdateInternal(lexicalData, lexicalKey, treeId, binding) {
155
+ // Handle Loro container objects that need conversion to plain JS
156
+ let data = lexicalData;
157
+ if (data && typeof data === 'object' && typeof data.toJSON === 'function') {
158
+ data = data.toJSON();
159
+ }
160
+ const targetNode = $getNodeByKey(lexicalKey);
161
+ if (!targetNode) {
162
+ return;
163
+ }
164
+ const targetType = targetNode.getType();
165
+ const textContent = data.__text || data.text || data.textContent;
166
+ if (targetType === 'text' && textContent !== undefined) {
167
+ // Text nodes: use diff approach to preserve cursor position
168
+ const textNode = targetNode;
169
+ const currentText = textNode.getTextContent();
170
+ if (currentText !== textContent) {
171
+ $diffTextContentAndApplyDelta(textNode, lexicalKey, currentText, textContent);
172
+ }
173
+ // Apply text-specific properties
174
+ if (data.format !== undefined) {
175
+ textNode.setFormat(data.format);
176
+ }
177
+ if (data.style !== undefined) {
178
+ textNode.setStyle(data.style);
179
+ }
180
+ }
181
+ else if ($isDecoratorNode(targetNode)) {
182
+ // Decorator nodes (excalidraw, images, counters, JupyterCellNode, …):
183
+ // Many decorator implementations do NOT override `updateFromJSON` for
184
+ // their custom properties β€” they only set them in the constructor via
185
+ // `importJSON`. Since decorators are leaf nodes (no children), it is
186
+ // safe to replace the whole node with a fresh `importJSON` instance.
187
+ try {
188
+ const registeredNodes = binding.editor._nodes;
189
+ const nodeInfo = registeredNodes.get(targetType);
190
+ if (!nodeInfo) {
191
+ console.warn(`πŸ—ΊοΈ MapIntegrator: Node type '${targetType}' not registered`);
192
+ return;
193
+ }
194
+ const serializedData = { ...data };
195
+ if (!serializedData.type)
196
+ serializedData.type = targetType;
197
+ if (serializedData.version === undefined)
198
+ serializedData.version = 1;
199
+ if (!('children' in serializedData))
200
+ serializedData.children = [];
201
+ const newNode = nodeInfo.klass.importJSON(serializedData);
202
+ targetNode.replace(newNode);
203
+ // Update bidirectional mapping: old key β†’ remove, new key β†’ treeId
204
+ // Use removeMappingForKey (not deleteMapping) because we are on the
205
+ // integration side β€” the Loro tree node must NOT be deleted; we are
206
+ // only swapping which Lexical key points to it.
207
+ binding.nodeMapper.removeMappingForKey(lexicalKey);
208
+ binding.nodeMapper.setMapping(newNode.getKey(), treeId);
209
+ }
210
+ catch (error) {
211
+ console.warn(`πŸ—ΊοΈ MapIntegrator: importJSON+replace failed for decorator ${targetType} node ${lexicalKey}:`, error);
212
+ }
213
+ }
214
+ else {
215
+ try {
216
+ const serializedData = { ...data };
217
+ if (!serializedData.type) {
218
+ serializedData.type = targetType;
219
+ }
220
+ if (serializedData.version === undefined) {
221
+ serializedData.version = 1;
222
+ }
223
+ // Provide empty children (TreeIntegrator manages children separately)
224
+ if (!('children' in serializedData)) {
225
+ serializedData.children = [];
226
+ }
227
+ const writable = targetNode.getWritable();
228
+ writable.updateFromJSON(serializedData);
229
+ }
230
+ catch (error) {
231
+ console.warn(`πŸ—ΊοΈ MapIntegrator: updateFromJSON failed for ${targetType} node ${lexicalKey}:`, error);
232
+ }
233
+ }
234
+ }
235
+ }
@@ -0,0 +1,25 @@
1
+ import { BaseIntegrator } from './BaseIntegrator';
2
+ import { Binding } from '../Bindings';
3
+ import { Provider } from '../State';
4
+ interface TextDiff {
5
+ type: 'text';
6
+ diff?: Array<{
7
+ type: 'insert' | 'delete' | 'retain';
8
+ index?: number;
9
+ length?: number;
10
+ value?: string;
11
+ attributes?: any;
12
+ }>;
13
+ }
14
+ /**
15
+ * Handles text changes (character insertions, deletions, formatting)
16
+ */
17
+ export declare class TextIntegrator implements BaseIntegrator<TextDiff> {
18
+ integrate(diff: TextDiff, binding: Binding, provider: Provider): void;
19
+ integrateInternal(diff: TextDiff, binding: Binding, provider: Provider): void;
20
+ private integrateTextInsert;
21
+ private integrateTextDelete;
22
+ private integrateTextRetain;
23
+ private applyTextFormatting;
24
+ }
25
+ export {};
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ /**
6
+ * Handles text changes (character insertions, deletions, formatting)
7
+ */
8
+ export class TextIntegrator {
9
+ integrate(diff, binding, provider) {
10
+ this.integrateInternal(diff, binding, provider);
11
+ }
12
+ // Internal method for use when already inside editor.update()
13
+ integrateInternal(diff, binding, provider) {
14
+ if (diff.diff) {
15
+ diff.diff.forEach((change) => {
16
+ switch (change.type) {
17
+ case 'insert':
18
+ this.integrateTextInsert(change, binding, provider);
19
+ break;
20
+ case 'delete':
21
+ this.integrateTextDelete(change, binding, provider);
22
+ break;
23
+ case 'retain':
24
+ this.integrateTextRetain(change, binding, provider);
25
+ break;
26
+ default:
27
+ console.warn(`πŸ“ Unknown text change type: ${change.type}`);
28
+ }
29
+ });
30
+ }
31
+ }
32
+ integrateTextInsert(change, binding, provider) {
33
+ // To integrate text insertion, we need to know which TextNode this applies to
34
+ // This information should come from the event context or be tracked separately
35
+ // For now, this is a placeholder - in a complete implementation,
36
+ // we would need to identify the target TextNode and update it
37
+ }
38
+ integrateTextDelete(change, binding, provider) {
39
+ // Similar to insert, we need target node context for text deletion
40
+ }
41
+ integrateTextRetain(change, binding, provider) {
42
+ if (change.attributes) {
43
+ // Handle text formatting changes
44
+ this.applyTextFormatting({ ...change, attributes: change.attributes }, binding, provider);
45
+ }
46
+ }
47
+ applyTextFormatting(change, binding, provider) {
48
+ // Text formatting in Lexical is typically integrated through TextNode format property
49
+ // This would need to be coordinated with the specific TextNode being modified
50
+ // Example formatting attributes might include:
51
+ // - bold, italic, underline
52
+ // - font size, color
53
+ // - etc.
54
+ }
55
+ }
@@ -0,0 +1,36 @@
1
+ import { TreeID } from 'loro-crdt';
2
+ import { BaseIntegrator } from './BaseIntegrator';
3
+ import { Binding } from '../Bindings';
4
+ import { Provider } from '../State';
5
+ interface TreeDiff {
6
+ type: 'tree';
7
+ diff: Array<{
8
+ action: 'create' | 'move' | 'delete';
9
+ target: TreeID;
10
+ parent?: TreeID;
11
+ index?: number;
12
+ }>;
13
+ }
14
+ /**
15
+ * Simplified tree diff integrater that trusts Loro's CRDT conflict resolution
16
+ * and applies operations directly without complex filtering or context classification
17
+ */
18
+ export declare class TreeIntegrator implements BaseIntegrator<TreeDiff> {
19
+ integrate(diff: TreeDiff, binding: Binding, provider: Provider): void;
20
+ integrateInternal(diff: TreeDiff, binding: Binding, provider: Provider): void;
21
+ private integrateCreate;
22
+ private integrateMove;
23
+ private integrateDelete;
24
+ /**
25
+ * Topologically sort create operations so that parent nodes are created
26
+ * before their children.
27
+ *
28
+ * Computes depth using the `parent` field from the diff operations
29
+ * themselves rather than querying the Loro tree API (which may behave
30
+ * unexpectedly during event processing). For each create op, we count
31
+ * how many of its ancestors are also being created in this same batch.
32
+ * Ties at the same depth preserve the original diff order (stable sort).
33
+ */
34
+ private topologicalSortCreates;
35
+ }
36
+ export {};
@@ -0,0 +1,251 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $getRoot, $getNodeByKey, $isElementNode } from 'lexical';
6
+ import { parseTreeID } from '../utils/Utils';
7
+ import { createLexicalNodeFromLoro } from '../nodes/NodeFactory';
8
+ /**
9
+ * Simplified tree diff integrater that trusts Loro's CRDT conflict resolution
10
+ * and applies operations directly without complex filtering or context classification
11
+ */
12
+ export class TreeIntegrator {
13
+ integrate(diff, binding, provider) {
14
+ // Batch all changes in a single editor update
15
+ binding.editor.update(() => {
16
+ this.integrateInternal(diff, binding, provider);
17
+ });
18
+ }
19
+ // Internal method that can be called when already inside editor.update()
20
+ integrateInternal(diff, binding, provider) {
21
+ // Separate operations by action type
22
+ const deletes = [];
23
+ const creates = [];
24
+ const moves = [];
25
+ for (const op of diff.diff) {
26
+ switch (op.action) {
27
+ case 'delete':
28
+ deletes.push(op);
29
+ break;
30
+ case 'create':
31
+ creates.push(op);
32
+ break;
33
+ case 'move':
34
+ moves.push(op);
35
+ break;
36
+ }
37
+ }
38
+ // Topologically sort create operations so parents are created before children.
39
+ // Without this, a TableCellNode may arrive before its parent TableRowNode,
40
+ // causing the cell to fall back to $getRoot() and appear on one flat line.
41
+ const sortedCreates = this.topologicalSortCreates(creates, binding);
42
+ // Execute: deletes β†’ creates (parent-first) β†’ moves
43
+ const operations = [...deletes, ...sortedCreates, ...moves];
44
+ operations.forEach(operation => {
45
+ switch (operation.action) {
46
+ case 'create':
47
+ this.integrateCreate(operation, binding, provider);
48
+ break;
49
+ case 'move':
50
+ this.integrateMove(operation, binding, provider);
51
+ break;
52
+ case 'delete':
53
+ this.integrateDelete(operation, binding, provider);
54
+ break;
55
+ default:
56
+ console.warn(`🌳 Unknown tree operation: ${operation.action}`);
57
+ }
58
+ });
59
+ }
60
+ integrateCreate(operation, binding, provider) {
61
+ try {
62
+ let { nodeKey } = parseTreeID(operation.target);
63
+ // Skip root node creation - root is integrated during initial setup
64
+ // But ensure the root mapping exists
65
+ // Only treat as root if it's actually a root-type node in Loro
66
+ if (nodeKey === "0") {
67
+ const treeNode = binding.tree.getNodeByID(operation.target);
68
+ const elementType = treeNode?.data.get('elementType');
69
+ if (elementType === 'root' || !elementType) {
70
+ const root = $getRoot();
71
+ binding.nodeMapper.setMapping(root.getKey(), operation.target);
72
+ return;
73
+ }
74
+ // If nodeKey is "0" but it's not actually a root element, continue with normal processing
75
+ }
76
+ // Check if node already exists and if it's the same TreeID
77
+ const existingNode = $getNodeByKey(nodeKey);
78
+ if (existingNode) {
79
+ const existingTreeID = binding.nodeMapper.getTreeIDByLexicalKey(nodeKey);
80
+ if (existingTreeID === operation.target) {
81
+ return;
82
+ }
83
+ else {
84
+ // Don't reuse existing keys for different TreeIDs - let Lexical generate a fresh one
85
+ nodeKey = undefined; // Let createLexicalNodeFromLoro generate a fresh key
86
+ }
87
+ }
88
+ // Create Lexical node from Loro data
89
+ const lexicalNode = createLexicalNodeFromLoro(operation.target, binding.tree, binding);
90
+ if (!lexicalNode) {
91
+ return;
92
+ }
93
+ // Find parent node
94
+ let parentNode;
95
+ if (operation.parent) {
96
+ const parentKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.parent);
97
+ const parentLexicalNode = parentKey ? $getNodeByKey(parentKey) : null;
98
+ if (parentLexicalNode && $isElementNode(parentLexicalNode)) {
99
+ parentNode = parentLexicalNode;
100
+ }
101
+ else {
102
+ console.warn(`🌳 Parent NOT found for ${lexicalNode.getType()} target=${operation.target} parent=${operation.parent} parentKey=${parentKey} parentFound=${!!parentLexicalNode} isElement=${parentLexicalNode ? $isElementNode(parentLexicalNode) : 'N/A'}`);
103
+ // For text nodes, we MUST have a proper parent element
104
+ if (lexicalNode.getType() === 'text') {
105
+ return;
106
+ }
107
+ parentNode = $getRoot();
108
+ }
109
+ }
110
+ else {
111
+ parentNode = $getRoot();
112
+ }
113
+ // Normal insertion
114
+ if (operation.index !== undefined) {
115
+ parentNode.splice(operation.index, 0, [lexicalNode]);
116
+ }
117
+ else {
118
+ parentNode.append(lexicalNode);
119
+ }
120
+ // Set up mapping
121
+ binding.nodeMapper.setMapping(lexicalNode.getKey(), operation.target);
122
+ }
123
+ catch (error) {
124
+ console.warn(`🌳 Error creating node for ${operation.target}:`, error);
125
+ }
126
+ }
127
+ integrateMove(operation, binding, provider) {
128
+ try {
129
+ const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.target);
130
+ if (!lexicalKey) {
131
+ console.warn(`🌳 No Lexical key found for move target ${operation.target}`);
132
+ return;
133
+ }
134
+ const nodeToMove = $getNodeByKey(lexicalKey);
135
+ if (!nodeToMove) {
136
+ console.warn(`🌳 Node to move not found: ${lexicalKey}`);
137
+ return;
138
+ }
139
+ // Find new parent
140
+ let newParent;
141
+ if (operation.parent) {
142
+ const parentKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.parent);
143
+ const parentNode = parentKey ? $getNodeByKey(parentKey) : null;
144
+ if (parentNode && $isElementNode(parentNode)) {
145
+ newParent = parentNode;
146
+ }
147
+ else {
148
+ // For text nodes, we can't move them to root - skip this move operation
149
+ // The node is already in the correct position from our create fix
150
+ if (nodeToMove.getType() === 'text') {
151
+ return;
152
+ }
153
+ newParent = $getRoot();
154
+ }
155
+ }
156
+ else {
157
+ // For text nodes without a parent, skip the move
158
+ if (nodeToMove.getType() === 'text') {
159
+ return;
160
+ }
161
+ newParent = $getRoot();
162
+ }
163
+ // Remove from current position and insert at new position
164
+ nodeToMove.remove();
165
+ if (operation.index !== undefined) {
166
+ newParent.splice(operation.index, 0, [nodeToMove]);
167
+ }
168
+ else {
169
+ newParent.append(nodeToMove);
170
+ }
171
+ }
172
+ catch (error) {
173
+ console.warn(`🌳 Error moving node ${operation.target}:`, error);
174
+ }
175
+ }
176
+ integrateDelete(operation, binding, provider) {
177
+ try {
178
+ const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.target);
179
+ if (!lexicalKey) {
180
+ console.warn(`🌳 No Lexical key found for delete target ${operation.target}`);
181
+ return;
182
+ }
183
+ const nodeToDelete = $getNodeByKey(lexicalKey);
184
+ if (!nodeToDelete) {
185
+ console.warn(`🌳 Node to delete not found: ${lexicalKey}`);
186
+ return;
187
+ }
188
+ // Remove from Lexical tree
189
+ nodeToDelete.remove();
190
+ // Clean up mapping only β€” do NOT call deleteMapping() here because
191
+ // the Loro tree has already processed this deletion from the remote
192
+ // peer. Calling tree.delete() again would throw "is deleted or does
193
+ // not exist".
194
+ binding.nodeMapper.removeMappingForKey(lexicalKey);
195
+ }
196
+ catch (error) {
197
+ console.warn(`🌳 Error deleting node ${operation.target}:`, error);
198
+ }
199
+ }
200
+ /**
201
+ * Topologically sort create operations so that parent nodes are created
202
+ * before their children.
203
+ *
204
+ * Computes depth using the `parent` field from the diff operations
205
+ * themselves rather than querying the Loro tree API (which may behave
206
+ * unexpectedly during event processing). For each create op, we count
207
+ * how many of its ancestors are also being created in this same batch.
208
+ * Ties at the same depth preserve the original diff order (stable sort).
209
+ */
210
+ topologicalSortCreates(creates, binding) {
211
+ if (creates.length <= 1)
212
+ return creates;
213
+ // Build lookup: target β†’ parent (only for operations in this batch)
214
+ const batchTargets = new Set(creates.map(op => String(op.target)));
215
+ const parentOf = new Map();
216
+ for (const op of creates) {
217
+ if (op.parent) {
218
+ parentOf.set(String(op.target), String(op.parent));
219
+ }
220
+ }
221
+ const depthCache = new Map();
222
+ const getDepth = (targetStr) => {
223
+ if (depthCache.has(targetStr))
224
+ return depthCache.get(targetStr);
225
+ let depth = 0;
226
+ let current = targetStr;
227
+ const visited = new Set();
228
+ // Walk up the parent chain; count only ancestors that are also being
229
+ // created in this batch (i.e. don't exist yet and must come first).
230
+ while (parentOf.has(current)) {
231
+ const parent = parentOf.get(current);
232
+ if (visited.has(parent))
233
+ break; // cycle guard
234
+ visited.add(parent);
235
+ if (batchTargets.has(parent)) {
236
+ depth++;
237
+ current = parent;
238
+ }
239
+ else {
240
+ break; // parent already exists locally β€” stop counting
241
+ }
242
+ }
243
+ depthCache.set(targetStr, depth);
244
+ return depth;
245
+ };
246
+ // Tag each operation with its original index (for stable tie-breaking)
247
+ const tagged = creates.map((op, i) => ({ op, depth: getDepth(String(op.target)), idx: i }));
248
+ tagged.sort((a, b) => a.depth - b.depth || a.idx - b.idx);
249
+ return tagged.map(t => t.op);
250
+ }
251
+ }
@@ -0,0 +1,15 @@
1
+ import { TreeID, LoroTree } from 'loro-crdt';
2
+ import { LexicalNode, NodeKey } from 'lexical';
3
+ import { Binding } from '../Bindings';
4
+ /**
5
+ * Factory function to create Lexical nodes from Loro TreeID.
6
+ *
7
+ * Uses the registered node's static `importJSON()` method, which is the
8
+ * canonical Lexical API for restoring nodes from serialized data. This works
9
+ * generically for ALL node types β€” built-in (paragraph, heading, table,
10
+ * list, quote, code…), decorator (excalidraw, image, counter…), and any
11
+ * externally-defined custom nodes (e.g. JupyterCellNode) as long as they
12
+ * are registered with the editor and implement the standard `importJSON`
13
+ * static method required by Lexical's serialization contract.
14
+ */
15
+ export declare function createLexicalNodeFromLoro(treeId: TreeID, loroTree: LoroTree, binding: Binding, parentKey?: NodeKey, nodeDataFromDiff?: any): LexicalNode | null;