@datalayer/lexical-loro 0.2.3 → 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,174 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $getRoot } from 'lexical';
6
+ import { getNodeMapper } from '../nodes/NodesMapper';
7
+ /**
8
+ * Handle RootNode creation (typically only happens once during initialization)
9
+ */
10
+ export function createRootNodeInLoro(nodeKey, lexicalNodeJSON, // JSON object from exportJSON()
11
+ options) {
12
+ const { tree, peerId } = options;
13
+ const mapper = getNodeMapper();
14
+ // Use mapper to get or create the tree node (don't pass lexicalNode to avoid context issues)
15
+ // Root node has no parent (undefined) and is always at index 0
16
+ const rootTreeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, // don't pass lexicalNode to avoid context issues
17
+ undefined, // no parent for root
18
+ 0 // always at index 0
19
+ );
20
+ // Store complete lexical node data as clean JSON if provided
21
+ if (lexicalNodeJSON) {
22
+ try {
23
+ // Store complete lexical JSON without all key-related fields
24
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
25
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
26
+ rootTreeNode.data.set('lexical', cleanedData);
27
+ }
28
+ else {
29
+ const { children, ...cleanedData } = lexicalNodeJSON;
30
+ rootTreeNode.data.set('lexical', cleanedData);
31
+ }
32
+ }
33
+ catch (error) {
34
+ console.warn('Failed to store lexical node JSON for RootNode:', error);
35
+ }
36
+ }
37
+ // Store only essential metadata
38
+ rootTreeNode.data.set('elementType', 'root');
39
+ rootTreeNode.data.set('createdAt', Date.now());
40
+ // The exported Lexical node data is already propagated by the mapper
41
+ // Return the TreeID from the node's ID
42
+ return rootTreeNode.id;
43
+ }
44
+ /**
45
+ * Handle RootNode updates (rarely needed since root doesn't change much)
46
+ */
47
+ export function updateRootNodeInLoro(nodeKey, lexicalNodeJSON, // JSON object from exportJSON()
48
+ options) {
49
+ const mapper = getNodeMapper();
50
+ // Get the existing tree node using the mapper (don't pass lexicalNode to avoid context issues)
51
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
52
+ // Store complete lexical node data as clean JSON if provided
53
+ if (lexicalNodeJSON) {
54
+ try {
55
+ // Store complete lexical JSON without all key-related fields
56
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
57
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
58
+ treeNode.data.set('lexical', cleanedData);
59
+ }
60
+ else {
61
+ const { children, ...cleanedData } = lexicalNodeJSON;
62
+ treeNode.data.set('lexical', cleanedData);
63
+ }
64
+ }
65
+ catch (error) {
66
+ console.warn('Failed to store lexical node JSON for RootNode update:', error);
67
+ }
68
+ }
69
+ // Update only essential metadata
70
+ treeNode.data.set('elementType', 'root');
71
+ treeNode.data.set('lastUpdated', Date.now());
72
+ }
73
+ /**
74
+ * Handle RootNode deletion (should rarely happen, but included for completeness)
75
+ */
76
+ export function deleteRootNodeInLoro(nodeKey, options) {
77
+ const mapper = getNodeMapper();
78
+ // Note: Deleting root node should be done with extreme caution
79
+ // as it represents the entire editor content
80
+ mapper.deleteMapping(nodeKey);
81
+ }
82
+ /**
83
+ * Create RootNode in Lexical from Loro tree data
84
+ */
85
+ export function createRootNodeFromLoro(treeId, options) {
86
+ // In Lexical, there's always exactly one root node
87
+ // This function would typically be called during initialization
88
+ const root = $getRoot();
89
+ // Root node already exists, just return it
90
+ return root;
91
+ }
92
+ /**
93
+ * Update RootNode in Lexical from Loro tree data
94
+ */
95
+ export function updateRootNodeFromLoro(treeId, options) {
96
+ // Root node updates are typically propagated at the document level
97
+ // Most changes to root would be indirect (children changes)
98
+ console.log('Root node update from Loro:', treeId);
99
+ }
100
+ /**
101
+ * Delete RootNode in Lexical (should not happen in normal operation)
102
+ */
103
+ export function deleteRootNodeFromLoro(treeId, options) {
104
+ // Root node deletion should not happen in normal circumstances
105
+ // This would essentially clear the entire editor
106
+ console.warn('Attempting to delete root node - this should not happen:', treeId);
107
+ }
108
+ /**
109
+ * Utility to check if a tree node represents a RootNode
110
+ */
111
+ export function isRootNodeInTree(treeId, tree) {
112
+ if (!tree.has(treeId)) {
113
+ return false;
114
+ }
115
+ const treeNode = tree.getNodeByID(treeId);
116
+ return treeNode?.data.get('nodeType') === 'root';
117
+ }
118
+ /**
119
+ * Main propagate method for RootNode - propagates all mutation types
120
+ */
121
+ export function propagateRootNode(update, mutation, nodeKey, options) {
122
+ const { tree, peerId } = options;
123
+ switch (mutation) {
124
+ case 'created': {
125
+ // Get the current editor state to find the root node
126
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
127
+ if (currentNode) {
128
+ // Export node data as JSON object within editor context where node methods are available
129
+ let lexicalNodeJSON = undefined;
130
+ update.editorState.read(() => {
131
+ if (currentNode.getType() === 'root') {
132
+ try {
133
+ lexicalNodeJSON = currentNode.exportJSON();
134
+ }
135
+ catch (error) {
136
+ console.warn('Failed to export root node JSON:', error);
137
+ }
138
+ }
139
+ });
140
+ if (lexicalNodeJSON) {
141
+ createRootNodeInLoro(nodeKey, lexicalNodeJSON, options);
142
+ }
143
+ }
144
+ break;
145
+ }
146
+ case 'updated': {
147
+ // Root nodes typically don't change much, but we can update metadata
148
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
149
+ if (currentNode) {
150
+ // Export node data as JSON object within editor context where node methods are available
151
+ let lexicalNodeJSON = undefined;
152
+ update.editorState.read(() => {
153
+ if (currentNode.getType() === 'root') {
154
+ try {
155
+ lexicalNodeJSON = currentNode.exportJSON();
156
+ }
157
+ catch (error) {
158
+ console.warn('Failed to export root node JSON for update:', error);
159
+ }
160
+ }
161
+ });
162
+ if (lexicalNodeJSON) {
163
+ updateRootNodeInLoro(nodeKey, lexicalNodeJSON, options);
164
+ }
165
+ }
166
+ break;
167
+ }
168
+ case 'destroyed': {
169
+ // Delete the root node from Loro tree
170
+ deleteRootNodeInLoro(nodeKey, options);
171
+ break;
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,60 @@
1
+ import { TreeID, LoroTree } from 'loro-crdt';
2
+ import { TextNode, TextFormatType, UpdateListenerPayload, NodeKey, ElementNode } from 'lexical';
3
+ import { Binding } from '../Bindings';
4
+ /**
5
+ * TextNode Propagator for Loro Tree Collaboration
6
+ *
7
+ * TextNode characteristics:
8
+ * - Leaf nodes that represent text content
9
+ * - Can have formatting (bold, italic, underline, strikethrough, etc.)
10
+ * - Can have different modes: normal, token, segmented, inert
11
+ * - Cannot have children (always leaf nodes)
12
+ * - Support text content and format operations
13
+ */
14
+ export interface TextNodeMutatorOptions {
15
+ binding: Binding;
16
+ tree: LoroTree;
17
+ peerId: number;
18
+ }
19
+ /**
20
+ * Create TextNode in Loro tree
21
+ */
22
+ export declare function createTextNodeInLoro(nodeKey: NodeKey, textContent: string, format?: number, mode?: string, parentId?: TreeID, index?: number, lexicalNodeJSON?: any, // JSON object from exportJSON()
23
+ options?: TextNodeMutatorOptions): TreeID;
24
+ /**
25
+ * Update TextNode in Loro tree
26
+ */
27
+ export declare function updateTextNodeInLoro(nodeKey: NodeKey, newTextContent?: string, format?: number, mode?: string, lexicalNodeJSON?: any, // JSON object from exportJSON()
28
+ options?: TextNodeMutatorOptions): void;
29
+ /**
30
+ * Delete TextNode from Loro tree
31
+ */
32
+ export declare function deleteTextNodeInLoro(nodeKey: NodeKey, options: TextNodeMutatorOptions): void;
33
+ /**
34
+ * Create TextNode in Lexical from Loro tree data
35
+ */
36
+ export declare function createTextNodeFromLoro(treeId: TreeID, parentNode: ElementNode, index?: number, options?: TextNodeMutatorOptions): TextNode | null;
37
+ /**
38
+ * Update TextNode in Lexical from Loro tree data
39
+ */
40
+ export declare function updateTextNodeFromLoro(treeId: TreeID, textNode: TextNode, newParentNode?: ElementNode, newIndex?: number, options?: TextNodeMutatorOptions): void;
41
+ /**
42
+ * Delete TextNode from Lexical
43
+ */
44
+ export declare function deleteTextNodeFromLoro(treeId: TreeID, lexicalNode: TextNode, options?: TextNodeMutatorOptions): void;
45
+ /**
46
+ * Utility to check if a tree node represents a TextNode
47
+ */
48
+ export declare function isTextNodeInTree(treeId: TreeID, tree: LoroTree): boolean;
49
+ /**
50
+ * Get TextNode data from Loro tree
51
+ */
52
+ export declare function getTextNodeDataFromTree(treeId: TreeID, tree: LoroTree): any;
53
+ /**
54
+ * Apply text formatting operations (bold, italic, etc.)
55
+ */
56
+ export declare function applyTextFormatInLoro(nodeKey: NodeKey, formatType: TextFormatType, apply: boolean, options: TextNodeMutatorOptions): void;
57
+ /**
58
+ * Main propagate method for TextNode - propagates all mutation types
59
+ */
60
+ export declare function propagateTextNode(update: UpdateListenerPayload, mutation: 'created' | 'updated' | 'destroyed', nodeKey: NodeKey, options: TextNodeMutatorOptions): void;
@@ -0,0 +1,440 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $createTextNode, $isTextNode } from 'lexical';
6
+ import { getNodeMapper } from '../nodes/NodesMapper';
7
+ import { $diffTextContentAndApplyDelta } from '../utils/Utils';
8
+ /**
9
+ * Create TextNode in Loro tree
10
+ */
11
+ export function createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, // JSON object from exportJSON()
12
+ options) {
13
+ const mapper = getNodeMapper();
14
+ // Debug logging for text node creation issues
15
+ if (!parentId) {
16
+ console.warn(`❌ Creating TextNode ${nodeKey} without parent in Loro tree - THIS WILL FAIL`);
17
+ return null; // Return early to avoid creating orphaned nodes
18
+ }
19
+ // Use mapper to get or create the tree node
20
+ // Note: We can't pass lexicalNode directly due to context issues, but parentId should be sufficient
21
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, // don't pass lexicalNode to avoid context issues
22
+ parentId, index);
23
+ // Store complete lexical node data as clean JSON if provided
24
+ if (lexicalNodeJSON) {
25
+ try {
26
+ // Store complete lexical JSON without the key
27
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
28
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
29
+ treeNode.data.set('lexical', cleanedData);
30
+ }
31
+ else {
32
+ const { children, ...cleanedData } = lexicalNodeJSON;
33
+ treeNode.data.set('lexical', cleanedData);
34
+ }
35
+ }
36
+ catch (error) {
37
+ console.warn('Failed to store lexical node JSON for TextNode:', error);
38
+ }
39
+ }
40
+ // Store only essential metadata (elementType for debug panel)
41
+ treeNode.data.set('elementType', 'text');
42
+ treeNode.data.set('createdAt', Date.now());
43
+ // Return the TreeID from the node's ID
44
+ return treeNode.id;
45
+ }
46
+ /**
47
+ * Update TextNode in Loro tree
48
+ */
49
+ export function updateTextNodeInLoro(nodeKey, newTextContent, format, mode, lexicalNodeJSON, // JSON object from exportJSON()
50
+ options) {
51
+ const mapper = getNodeMapper();
52
+ // Get the existing tree node using the mapper
53
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
54
+ if (!treeNode) {
55
+ console.warn(`📝 TextNode ${nodeKey} not found in Loro, skipping update`);
56
+ return;
57
+ }
58
+ // Note: Container validation is done in each try-catch block below since
59
+ // the container can be deleted between operations
60
+ // Store complete lexical node data as clean JSON if provided
61
+ if (lexicalNodeJSON) {
62
+ try {
63
+ // Store complete lexical JSON without the key
64
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
65
+ const { key, __key, lexicalKey, children, ...cleanedData } = lexicalNodeJSON;
66
+ treeNode.data.set('lexical', cleanedData);
67
+ }
68
+ else {
69
+ const { children, ...cleanedData } = lexicalNodeJSON;
70
+ treeNode.data.set('lexical', cleanedData);
71
+ }
72
+ }
73
+ catch (error) {
74
+ // This is expected during text operations when nodes get deleted/recreated
75
+ console.warn(`📝 TextNode ${nodeKey} container was deleted during update, skipping (normal during text operations):`, error.message);
76
+ return;
77
+ }
78
+ }
79
+ // Update only essential metadata
80
+ try {
81
+ treeNode.data.set('elementType', 'text');
82
+ treeNode.data.set('updatedAt', Date.now());
83
+ }
84
+ catch (error) {
85
+ console.warn(`📝 TextNode ${nodeKey} container deleted during metadata update (normal during text operations):`, error.message);
86
+ return;
87
+ }
88
+ // The exported Lexical node data is already propagated by the mapper
89
+ // No additional JSON export needed since mapper propagates exportJSON automatically
90
+ }
91
+ /**
92
+ * Delete TextNode from Loro tree
93
+ */
94
+ export function deleteTextNodeInLoro(nodeKey, options) {
95
+ const mapper = getNodeMapper();
96
+ mapper.deleteMapping(nodeKey);
97
+ }
98
+ /**
99
+ * Create TextNode in Lexical from Loro tree data
100
+ */
101
+ export function createTextNodeFromLoro(treeId, parentNode, index, options) {
102
+ const { tree } = options;
103
+ if (!tree.has(treeId)) {
104
+ return null;
105
+ }
106
+ const treeNode = tree.getNodeByID(treeId);
107
+ if (!treeNode) {
108
+ return null;
109
+ }
110
+ // Get LexicalNodeData (JSON object format only)
111
+ const lexicalData = treeNode.data.get('lexical');
112
+ let textNode;
113
+ if (lexicalData && typeof lexicalData === 'object') {
114
+ try {
115
+ // lexicalData is a direct JSON object, use it to create a TextNode
116
+ const lexicalDataObj = lexicalData;
117
+ const textContent = lexicalDataObj.text || lexicalDataObj.__text || '';
118
+ const format = lexicalDataObj.format || lexicalDataObj.__format || 0;
119
+ const mode = lexicalDataObj.mode || lexicalDataObj.__mode || 0;
120
+ textNode = $createTextNode(textContent);
121
+ textNode.setFormat(format);
122
+ textNode.setMode(mode);
123
+ }
124
+ catch (error) {
125
+ console.warn('Failed to create TextNode from JSON data for TreeID:', treeId, error);
126
+ return null;
127
+ }
128
+ }
129
+ else {
130
+ // No lexical JSON data found - cannot create TextNode
131
+ console.warn('No lexical JSON data found for TextNode TreeID:', treeId);
132
+ return null;
133
+ }
134
+ // Apply mode if present (only for old format)
135
+ if (!lexicalData || typeof lexicalData !== 'string') {
136
+ // const mode = treeNode.data.get('mode');
137
+ // if (mode && typeof textNode.setMode === 'function') {
138
+ // textNode.setMode(mode);
139
+ // }
140
+ }
141
+ // Insert into the parent at the specified index
142
+ if (index !== undefined && index >= 0) {
143
+ parentNode.splice(index, 0, [textNode]);
144
+ }
145
+ else {
146
+ parentNode.append(textNode);
147
+ }
148
+ return textNode;
149
+ }
150
+ /**
151
+ * Update TextNode in Lexical from Loro tree data
152
+ */
153
+ export function updateTextNodeFromLoro(treeId, textNode, newParentNode, newIndex, options) {
154
+ const { tree } = options;
155
+ if (!tree.has(treeId)) {
156
+ return;
157
+ }
158
+ const treeNode = tree.getNodeByID(treeId);
159
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
160
+ return;
161
+ }
162
+ // Update text content if it has changed
163
+ const textContent = treeNode.data.get('textContent');
164
+ if (textContent !== undefined && typeof textContent === 'string' &&
165
+ textNode.getTextContent() !== textContent) {
166
+ const currentText = textNode.getTextContent();
167
+ $diffTextContentAndApplyDelta(textNode, textNode.getKey(), currentText, textContent);
168
+ }
169
+ // Update format if it has changed
170
+ const format = treeNode.data.get('format');
171
+ if (format !== undefined && typeof format === 'number') {
172
+ textNode.setFormat(format);
173
+ }
174
+ // Update mode if it has changed (skip for now due to type complexity)
175
+ // const mode = treeNode.data.get('mode');
176
+ // if (mode !== undefined && typeof lexicalNode.setMode === 'function') {
177
+ // lexicalNode.setMode(mode);
178
+ // }
179
+ // If parent or position changed, move the node
180
+ if (newParentNode && newIndex !== undefined) {
181
+ // Remove from current location
182
+ textNode.remove();
183
+ // Insert at new location
184
+ newParentNode.splice(newIndex, 0, [textNode]);
185
+ }
186
+ }
187
+ /**
188
+ * Delete TextNode from Lexical
189
+ */
190
+ export function deleteTextNodeFromLoro(treeId, lexicalNode, options) {
191
+ if ($isTextNode(lexicalNode)) {
192
+ lexicalNode.remove();
193
+ }
194
+ }
195
+ /**
196
+ * Utility to check if a tree node represents a TextNode
197
+ */
198
+ export function isTextNodeInTree(treeId, tree) {
199
+ if (!tree.has(treeId)) {
200
+ return false;
201
+ }
202
+ const treeNode = tree.getNodeByID(treeId);
203
+ return treeNode?.data.get('nodeType') === 'text';
204
+ }
205
+ /**
206
+ * Get TextNode data from Loro tree
207
+ */
208
+ export function getTextNodeDataFromTree(treeId, tree) {
209
+ if (!tree.has(treeId)) {
210
+ return null;
211
+ }
212
+ const treeNode = tree.getNodeByID(treeId);
213
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
214
+ return null;
215
+ }
216
+ return {
217
+ nodeType: 'text',
218
+ textContent: treeNode.data.get('textContent'),
219
+ format: treeNode.data.get('format'),
220
+ mode: treeNode.data.get('mode'),
221
+ createdAt: treeNode.data.get('createdAt'),
222
+ lastUpdated: treeNode.data.get('lastUpdated'),
223
+ };
224
+ }
225
+ /**
226
+ * Apply text formatting operations (bold, italic, etc.)
227
+ */
228
+ export function applyTextFormatInLoro(nodeKey, formatType, apply, options) {
229
+ const mapper = getNodeMapper();
230
+ // Get the existing Loro node from the mapper
231
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey);
232
+ if (!treeNode) {
233
+ return;
234
+ }
235
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
236
+ return;
237
+ }
238
+ // Check if the TreeNode's container is still valid
239
+ try {
240
+ // Try a simple read operation to verify the container is accessible
241
+ treeNode.data.get('format');
242
+ }
243
+ catch (error) {
244
+ console.warn(`📝 TextNode ${nodeKey} container deleted during format check (normal during text operations):`, error.message);
245
+ return;
246
+ }
247
+ let currentFormat = treeNode.data.get('format') || 0;
248
+ const formatNumber = formatType;
249
+ if (apply) {
250
+ // Add the format flag
251
+ currentFormat = currentFormat | formatNumber;
252
+ }
253
+ else {
254
+ // Remove the format flag
255
+ currentFormat = currentFormat & ~formatNumber;
256
+ }
257
+ try {
258
+ treeNode.data.set('format', currentFormat);
259
+ treeNode.data.set('lastUpdated', Date.now());
260
+ }
261
+ catch (error) {
262
+ console.warn(`📝 TextNode ${nodeKey} container deleted during format update (normal during text operations):`, error.message);
263
+ return;
264
+ }
265
+ }
266
+ /**
267
+ * Main propagate method for TextNode - propagates all mutation types
268
+ */
269
+ export function propagateTextNode(update, mutation, nodeKey, options) {
270
+ const { tree, peerId } = options;
271
+ switch (mutation) {
272
+ case 'created': {
273
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
274
+ // Check if this node already exists in Loro
275
+ const mapper = getNodeMapper();
276
+ const existingTreeID = mapper.getTreeIDByLexicalKey(nodeKey);
277
+ if (existingTreeID && currentNode && $isTextNode(currentNode)) {
278
+ // Check if the existing text node has the correct parent relationship
279
+ const { currentParentId, expectedParentId } = update.editorState.read(() => {
280
+ const parent = currentNode.getParent();
281
+ const expectedParentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
282
+ // Get the current parent from Loro tree
283
+ let currentParentId;
284
+ try {
285
+ const treeNode = tree.getNodeByID(existingTreeID);
286
+ if (treeNode) {
287
+ const parentNode = treeNode.parent();
288
+ currentParentId = parentNode ? parentNode.id.toString() : undefined;
289
+ }
290
+ }
291
+ catch (error) {
292
+ console.warn(`📝 Failed to get parent for existing TreeID ${existingTreeID}:`, error);
293
+ }
294
+ return { currentParentId, expectedParentId };
295
+ });
296
+ if (currentParentId === expectedParentId) {
297
+ return; // Skip creation since the parent relationship is correct
298
+ }
299
+ else {
300
+ // Get the actual TreeNode and its ID before deleting
301
+ let actualTreeID = existingTreeID;
302
+ try {
303
+ const treeNode = tree.getNodeByID(existingTreeID);
304
+ if (treeNode) {
305
+ actualTreeID = treeNode.id;
306
+ }
307
+ }
308
+ catch (error) {
309
+ console.warn(`📝 Could not get TreeNode for ${existingTreeID} during creation:`, error);
310
+ }
311
+ // Clear the old mapping first to avoid conflicts
312
+ mapper.deleteMapping(nodeKey);
313
+ // Then delete the TreeNode from Loro tree
314
+ try {
315
+ if (tree.has(actualTreeID)) {
316
+ tree.delete(actualTreeID);
317
+ }
318
+ }
319
+ catch (error) {
320
+ console.warn(`📝 Failed to delete TreeNode ${actualTreeID} during creation:`, error);
321
+ }
322
+ }
323
+ }
324
+ if (currentNode && $isTextNode(currentNode)) {
325
+ // Get parent, positioning, content, and serialized data using editor state context
326
+ const { parent, parentId, index, textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
327
+ const parent = currentNode.getParent();
328
+ // Get parentId from the mapper instead of constructing it manually
329
+ const mapper = getNodeMapper();
330
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
331
+ const index = currentNode.getIndexWithinParent();
332
+ const textContent = currentNode.getTextContent();
333
+ const format = currentNode.getFormat();
334
+ const mode = currentNode.getMode();
335
+ // Export node data as JSON object within editor context where node methods are available
336
+ let lexicalNodeJSON = undefined;
337
+ try {
338
+ lexicalNodeJSON = currentNode.exportJSON();
339
+ }
340
+ catch (error) {
341
+ console.warn('Failed to export node JSON in propagateTextNode created:', error);
342
+ }
343
+ return { parent, parentId, index, textContent, format, mode, lexicalNodeJSON };
344
+ });
345
+ createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, options);
346
+ }
347
+ break;
348
+ }
349
+ case 'updated': {
350
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
351
+ if (currentNode && $isTextNode(currentNode)) {
352
+ // First, check if this TextNode's parent has changed (like during double Enter)
353
+ const mapper = getNodeMapper();
354
+ const existingTreeID = mapper.getTreeIDByLexicalKey(nodeKey);
355
+ if (existingTreeID) {
356
+ const { currentParentId, expectedParentId, parent } = update.editorState.read(() => {
357
+ const parent = currentNode.getParent();
358
+ const expectedParentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
359
+ // Get the current parent from Loro tree
360
+ let currentParentId;
361
+ try {
362
+ const treeNode = tree.getNodeByID(existingTreeID);
363
+ if (treeNode) {
364
+ const parentNode = treeNode.parent();
365
+ currentParentId = parentNode ? parentNode.id.toString() : undefined;
366
+ }
367
+ }
368
+ catch (error) {
369
+ console.warn(`📝 Failed to get parent for existing TreeID ${existingTreeID} during update:`, error);
370
+ }
371
+ return { currentParentId, expectedParentId, parent };
372
+ });
373
+ if (currentParentId !== expectedParentId) {
374
+ // Get the actual TreeNode and its ID before deleting
375
+ let actualTreeID = existingTreeID;
376
+ try {
377
+ const treeNode = tree.getNodeByID(existingTreeID);
378
+ if (treeNode) {
379
+ actualTreeID = treeNode.id;
380
+ }
381
+ }
382
+ catch (error) {
383
+ console.warn(`📝 Could not get TreeNode for ${existingTreeID}:`, error);
384
+ }
385
+ // Clear the old mapping first to avoid conflicts
386
+ mapper.deleteMapping(nodeKey);
387
+ // Then delete the TreeNode from Loro tree
388
+ try {
389
+ if (tree.has(actualTreeID)) {
390
+ tree.delete(actualTreeID);
391
+ }
392
+ }
393
+ catch (error) {
394
+ console.warn(`📝 Failed to delete TreeNode ${actualTreeID} during update:`, error);
395
+ }
396
+ // Now recreate the TextNode with the new parent (treat as "created")
397
+ const { parentId, index, textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
398
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
399
+ const index = currentNode.getIndexWithinParent();
400
+ const textContent = currentNode.getTextContent();
401
+ const format = currentNode.getFormat();
402
+ const mode = currentNode.getMode();
403
+ let lexicalNodeJSON = undefined;
404
+ try {
405
+ lexicalNodeJSON = currentNode.exportJSON();
406
+ }
407
+ catch (error) {
408
+ console.warn('Failed to export node JSON during TextNode recreation:', error);
409
+ }
410
+ return { parentId, index, textContent, format, mode, lexicalNodeJSON };
411
+ });
412
+ createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, options);
413
+ return; // Exit early since we recreated the node
414
+ }
415
+ }
416
+ // Normal update case - parent hasn't changed
417
+ const { textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
418
+ const textContent = currentNode.getTextContent();
419
+ const format = currentNode.getFormat();
420
+ const mode = currentNode.getMode();
421
+ // Export node data as JSON object within editor context where node methods are available
422
+ let lexicalNodeJSON = undefined;
423
+ try {
424
+ lexicalNodeJSON = currentNode.exportJSON();
425
+ }
426
+ catch (error) {
427
+ console.warn('Failed to export node JSON in propagateTextNode updated:', error);
428
+ }
429
+ return { textContent, format, mode, lexicalNodeJSON };
430
+ });
431
+ updateTextNodeInLoro(nodeKey, textContent, format, mode, lexicalNodeJSON, options);
432
+ }
433
+ break;
434
+ }
435
+ case 'destroyed': {
436
+ deleteTextNodeInLoro(nodeKey, options);
437
+ break;
438
+ }
439
+ }
440
+ }