@datalayer/lexical-loro 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (406) hide show
  1. package/README.md +24 -137
  2. package/lib/App.d.ts +2 -0
  3. package/lib/App.js +141 -0
  4. package/lib/Editor.d.ts +2 -0
  5. package/lib/Editor.js +111 -0
  6. package/lib/Settings.d.ts +2 -0
  7. package/lib/Settings.js +57 -0
  8. package/lib/appSettings.d.ts +36 -0
  9. package/lib/appSettings.js +44 -0
  10. package/lib/collab/loro/Bindings.d.ts +41 -0
  11. package/lib/collab/loro/Bindings.js +95 -0
  12. package/lib/collab/loro/Debug.d.ts +33 -0
  13. package/lib/collab/loro/Debug.js +448 -0
  14. package/lib/collab/loro/LexicalCollaborationContext.d.ts +19 -0
  15. package/lib/collab/loro/LexicalCollaborationContext.js +48 -0
  16. package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +24 -0
  17. package/lib/collab/loro/LexicalCollaborationPlugin.js +83 -0
  18. package/lib/collab/loro/State.d.ts +53 -0
  19. package/lib/collab/loro/State.js +90 -0
  20. package/lib/collab/loro/components/LoroCollaborationUI.d.ts +13 -0
  21. package/lib/collab/loro/components/LoroCollaborationUI.js +9 -0
  22. package/lib/collab/loro/components/LoroCollaborators.d.ts +8 -0
  23. package/lib/collab/loro/components/LoroCollaborators.js +97 -0
  24. package/lib/collab/loro/components/index.d.ts +2 -0
  25. package/lib/collab/loro/components/index.js +2 -0
  26. package/lib/collab/loro/index.d.ts +6 -0
  27. package/lib/collab/loro/index.js +6 -0
  28. package/lib/collab/loro/integrators/BaseIntegrator.d.ts +14 -0
  29. package/lib/collab/loro/integrators/BaseIntegrator.js +1 -0
  30. package/lib/collab/loro/integrators/CounterIntegrator.d.ts +23 -0
  31. package/lib/collab/loro/integrators/CounterIntegrator.js +40 -0
  32. package/lib/collab/loro/integrators/ListIntegrator.d.ts +23 -0
  33. package/lib/collab/loro/integrators/ListIntegrator.js +49 -0
  34. package/lib/collab/loro/integrators/MapIntegrator.d.ts +24 -0
  35. package/lib/collab/loro/integrators/MapIntegrator.js +177 -0
  36. package/lib/collab/loro/integrators/TextIntegrator.d.ts +25 -0
  37. package/lib/collab/loro/integrators/TextIntegrator.js +51 -0
  38. package/lib/collab/loro/integrators/TreeIntegrator.d.ts +25 -0
  39. package/lib/collab/loro/integrators/TreeIntegrator.js +201 -0
  40. package/lib/collab/loro/nodes/NodeFactory.d.ts +8 -0
  41. package/lib/collab/loro/nodes/NodeFactory.js +105 -0
  42. package/lib/collab/loro/nodes/NodesMapper.d.ts +111 -0
  43. package/lib/collab/loro/nodes/NodesMapper.js +258 -0
  44. package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +60 -0
  45. package/lib/collab/loro/propagators/DecoratorNodePropagator.js +302 -0
  46. package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +62 -0
  47. package/lib/collab/loro/propagators/ElementNodePropagator.js +335 -0
  48. package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +57 -0
  49. package/lib/collab/loro/propagators/LineBreakNodePropagator.js +196 -0
  50. package/lib/collab/loro/propagators/RootNodePropagator.d.ts +55 -0
  51. package/lib/collab/loro/propagators/RootNodePropagator.js +168 -0
  52. package/lib/collab/loro/propagators/TextNodePropagator.d.ts +60 -0
  53. package/lib/collab/loro/propagators/TextNodePropagator.js +434 -0
  54. package/lib/collab/loro/propagators/index.d.ts +49 -0
  55. package/lib/collab/loro/propagators/index.js +32 -0
  56. package/lib/collab/loro/provider/websocket.d.ts +116 -0
  57. package/lib/collab/loro/provider/websocket.js +907 -0
  58. package/lib/collab/loro/servers/index.d.ts +0 -0
  59. package/lib/collab/loro/servers/index.js +0 -0
  60. package/lib/collab/loro/servers/ws/callback.d.ts +5 -0
  61. package/lib/collab/loro/servers/ws/callback.js +85 -0
  62. package/lib/collab/loro/servers/ws/server.d.ts +2 -0
  63. package/lib/collab/loro/servers/ws/server.js +25 -0
  64. package/lib/collab/loro/servers/ws/utils.d.ts +40 -0
  65. package/lib/collab/loro/servers/ws/utils.js +513 -0
  66. package/lib/collab/loro/sync/SyncCursors.d.ts +32 -0
  67. package/lib/collab/loro/sync/SyncCursors.js +435 -0
  68. package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +4 -0
  69. package/lib/collab/loro/sync/SyncLexicalToLoro.js +80 -0
  70. package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +5 -0
  71. package/lib/collab/loro/sync/SyncLoroToLexical.js +96 -0
  72. package/lib/collab/loro/types/LexicalNodeData.d.ts +32 -0
  73. package/lib/collab/loro/types/LexicalNodeData.js +71 -0
  74. package/lib/collab/loro/useCollaboration.d.ts +12 -0
  75. package/lib/collab/loro/useCollaboration.js +248 -0
  76. package/lib/collab/loro/utils/InitialContent.d.ts +64 -0
  77. package/lib/collab/loro/utils/InitialContent.js +109 -0
  78. package/lib/collab/loro/utils/LexicalToLoro.d.ts +18 -0
  79. package/lib/collab/loro/utils/LexicalToLoro.js +96 -0
  80. package/lib/collab/loro/utils/Utils.d.ts +44 -0
  81. package/lib/collab/loro/utils/Utils.js +153 -0
  82. package/lib/collab/loro/wsProvider.d.ts +8 -0
  83. package/lib/collab/loro/wsProvider.js +31 -0
  84. package/lib/collab/utils/invariant.d.ts +1 -0
  85. package/lib/collab/utils/invariant.js +11 -0
  86. package/lib/collab/utils/simpleDiffWithCursor.d.ts +5 -0
  87. package/lib/collab/utils/simpleDiffWithCursor.js +31 -0
  88. package/lib/collab/yjs/Bindings.d.ts +23 -0
  89. package/lib/collab/yjs/Bindings.js +26 -0
  90. package/lib/collab/yjs/Debug.d.ts +23 -0
  91. package/lib/collab/yjs/Debug.js +213 -0
  92. package/lib/collab/yjs/LexicalCollaborationContext.d.ts +10 -0
  93. package/lib/collab/yjs/LexicalCollaborationContext.js +37 -0
  94. package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +21 -0
  95. package/lib/collab/yjs/LexicalCollaborationPlugin.js +63 -0
  96. package/lib/collab/yjs/State.d.ts +51 -0
  97. package/lib/collab/yjs/State.js +35 -0
  98. package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +5 -0
  99. package/lib/collab/yjs/nodes/AnyCollabNode.js +1 -0
  100. package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +22 -0
  101. package/lib/collab/yjs/nodes/CollabDecoratorNode.js +64 -0
  102. package/lib/collab/yjs/nodes/CollabElementNode.d.ts +40 -0
  103. package/lib/collab/yjs/nodes/CollabElementNode.js +462 -0
  104. package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +19 -0
  105. package/lib/collab/yjs/nodes/CollabLineBreakNode.js +44 -0
  106. package/lib/collab/yjs/nodes/CollabTextNode.d.ts +25 -0
  107. package/lib/collab/yjs/nodes/CollabTextNode.js +103 -0
  108. package/lib/collab/yjs/provider/websocket.d.ts +88 -0
  109. package/lib/collab/yjs/provider/websocket.js +415 -0
  110. package/lib/collab/yjs/servers/index.d.ts +0 -0
  111. package/lib/collab/yjs/servers/index.js +0 -0
  112. package/lib/collab/yjs/servers/ws/callback.d.ts +5 -0
  113. package/lib/collab/yjs/servers/ws/callback.js +72 -0
  114. package/lib/collab/yjs/servers/ws/server.d.ts +2 -0
  115. package/lib/collab/yjs/servers/ws/server.js +25 -0
  116. package/lib/collab/yjs/servers/ws/utils.d.ts +49 -0
  117. package/lib/collab/yjs/servers/ws/utils.js +284 -0
  118. package/lib/collab/yjs/sync/SyncCursors.d.ts +39 -0
  119. package/lib/collab/yjs/sync/SyncCursors.js +351 -0
  120. package/lib/collab/yjs/sync/SyncEditorStates.d.ts +10 -0
  121. package/lib/collab/yjs/sync/SyncEditorStates.js +200 -0
  122. package/lib/collab/yjs/useCollaboration.d.ts +12 -0
  123. package/lib/collab/yjs/useCollaboration.js +255 -0
  124. package/lib/collab/yjs/utils/Utils.d.ts +25 -0
  125. package/lib/collab/yjs/utils/Utils.js +402 -0
  126. package/lib/collab/yjs/wsProvider.d.ts +3 -0
  127. package/lib/collab/yjs/wsProvider.js +21 -0
  128. package/lib/commenting/index.d.ts +41 -0
  129. package/lib/commenting/index.js +324 -0
  130. package/lib/context/FlashMessageContext.d.ts +7 -0
  131. package/lib/context/FlashMessageContext.js +24 -0
  132. package/lib/context/SettingsContext.d.ts +12 -0
  133. package/lib/context/SettingsContext.js +38 -0
  134. package/lib/context/SharedHistoryContext.d.ts +11 -0
  135. package/lib/context/SharedHistoryContext.js +11 -0
  136. package/lib/context/ToolbarContext.d.ts +65 -0
  137. package/lib/context/ToolbarContext.js +84 -0
  138. package/lib/demo.d.ts +12 -0
  139. package/lib/demo.js +41 -0
  140. package/lib/hooks/useFlashMessage.d.ts +2 -0
  141. package/lib/hooks/useFlashMessage.js +4 -0
  142. package/lib/hooks/useModal.d.ts +5 -0
  143. package/lib/hooks/useModal.js +26 -0
  144. package/lib/hooks/useReport.d.ts +1 -0
  145. package/lib/hooks/useReport.js +46 -0
  146. package/lib/index.d.ts +1 -1
  147. package/lib/index.js +1 -5
  148. package/lib/nodes/AutocompleteNode.d.ts +27 -0
  149. package/lib/nodes/AutocompleteNode.js +56 -0
  150. package/lib/nodes/CounterComponent.d.ts +6 -0
  151. package/lib/nodes/CounterComponent.js +137 -0
  152. package/lib/nodes/CounterNode.d.ts +23 -0
  153. package/lib/nodes/CounterNode.js +47 -0
  154. package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +8 -0
  155. package/lib/nodes/DateTimeNode/DateTimeComponent.js +119 -0
  156. package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +27 -0
  157. package/lib/nodes/DateTimeNode/DateTimeNode.js +82 -0
  158. package/lib/nodes/EmojiNode.d.ts +18 -0
  159. package/lib/nodes/EmojiNode.js +50 -0
  160. package/lib/nodes/EquationComponent.d.ts +9 -0
  161. package/lib/nodes/EquationComponent.js +75 -0
  162. package/lib/nodes/EquationNode.d.ts +26 -0
  163. package/lib/nodes/EquationNode.js +109 -0
  164. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +8 -0
  165. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +110 -0
  166. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +50 -0
  167. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +55 -0
  168. package/lib/nodes/ExcalidrawNode/index.d.ts +32 -0
  169. package/lib/nodes/ExcalidrawNode/index.js +117 -0
  170. package/lib/nodes/FigmaNode.d.ts +20 -0
  171. package/lib/nodes/FigmaNode.js +52 -0
  172. package/lib/nodes/ImageComponent.d.ts +16 -0
  173. package/lib/nodes/ImageComponent.js +272 -0
  174. package/lib/nodes/ImageNode.d.ts +50 -0
  175. package/lib/nodes/ImageNode.js +151 -0
  176. package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +26 -0
  177. package/lib/nodes/InlineImageNode/InlineImageComponent.js +161 -0
  178. package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +59 -0
  179. package/lib/nodes/InlineImageNode/InlineImageNode.js +162 -0
  180. package/lib/nodes/KeywordNode.d.ts +14 -0
  181. package/lib/nodes/KeywordNode.js +33 -0
  182. package/lib/nodes/LayoutContainerNode.d.ts +24 -0
  183. package/lib/nodes/LayoutContainerNode.js +91 -0
  184. package/lib/nodes/LayoutItemNode.d.ts +16 -0
  185. package/lib/nodes/LayoutItemNode.js +65 -0
  186. package/lib/nodes/MentionNode.d.ts +20 -0
  187. package/lib/nodes/MentionNode.js +81 -0
  188. package/lib/nodes/PageBreakNode/index.d.ts +17 -0
  189. package/lib/nodes/PageBreakNode/index.js +83 -0
  190. package/lib/nodes/PlaygroundNodes.d.ts +3 -0
  191. package/lib/nodes/PlaygroundNodes.js +71 -0
  192. package/lib/nodes/PollComponent.d.ts +9 -0
  193. package/lib/nodes/PollComponent.js +85 -0
  194. package/lib/nodes/PollNode.d.ts +43 -0
  195. package/lib/nodes/PollNode.js +153 -0
  196. package/lib/nodes/SpecialTextNode.d.ts +24 -0
  197. package/lib/nodes/SpecialTextNode.js +50 -0
  198. package/lib/nodes/StickyComponent.d.ts +10 -0
  199. package/lib/nodes/StickyComponent.js +162 -0
  200. package/lib/nodes/StickyNode.d.ts +31 -0
  201. package/lib/nodes/StickyNode.js +76 -0
  202. package/lib/nodes/TweetNode.d.ts +21 -0
  203. package/lib/nodes/TweetNode.js +119 -0
  204. package/lib/nodes/YouTubeNode.d.ts +22 -0
  205. package/lib/nodes/YouTubeNode.js +84 -0
  206. package/lib/plugins/ActionsPlugin/index.d.ts +5 -0
  207. package/lib/plugins/ActionsPlugin/index.js +168 -0
  208. package/lib/plugins/AutoEmbedPlugin/index.d.ts +19 -0
  209. package/lib/plugins/AutoEmbedPlugin/index.js +158 -0
  210. package/lib/plugins/AutoLinkPlugin/index.d.ts +2 -0
  211. package/lib/plugins/AutoLinkPlugin/index.js +15 -0
  212. package/lib/plugins/AutocompletePlugin/index.d.ts +10 -0
  213. package/lib/plugins/AutocompletePlugin/index.js +2473 -0
  214. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +7 -0
  215. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +42 -0
  216. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +17 -0
  217. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +111 -0
  218. package/lib/plugins/CodeActionMenuPlugin/index.d.ts +5 -0
  219. package/lib/plugins/CodeActionMenuPlugin/index.js +104 -0
  220. package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +1 -0
  221. package/lib/plugins/CodeActionMenuPlugin/utils.js +18 -0
  222. package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +2 -0
  223. package/lib/plugins/CodeHighlightPrismPlugin/index.js +10 -0
  224. package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +2 -0
  225. package/lib/plugins/CodeHighlightShikiPlugin/index.js +10 -0
  226. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +25 -0
  227. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +131 -0
  228. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +16 -0
  229. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +79 -0
  230. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +16 -0
  231. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +81 -0
  232. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +2 -0
  233. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +8 -0
  234. package/lib/plugins/CollapsiblePlugin/index.d.ts +3 -0
  235. package/lib/plugins/CollapsiblePlugin/index.js +128 -0
  236. package/lib/plugins/CommentPlugin/index.d.ts +9 -0
  237. package/lib/plugins/CommentPlugin/index.js +460 -0
  238. package/lib/plugins/ComponentPickerPlugin/index.d.ts +2 -0
  239. package/lib/plugins/ComponentPickerPlugin/index.js +276 -0
  240. package/lib/plugins/ContextMenuPlugin/index.d.ts +2 -0
  241. package/lib/plugins/ContextMenuPlugin/index.js +112 -0
  242. package/lib/plugins/CounterPlugin/index.d.ts +3 -0
  243. package/lib/plugins/CounterPlugin/index.js +20 -0
  244. package/lib/plugins/DatalayerPlugin/index.d.ts +2 -0
  245. package/lib/plugins/DatalayerPlugin/index.js +218 -0
  246. package/lib/plugins/DateTimePlugin/index.d.ts +8 -0
  247. package/lib/plugins/DateTimePlugin/index.js +24 -0
  248. package/lib/plugins/DocsPlugin/index.d.ts +2 -0
  249. package/lib/plugins/DocsPlugin/index.js +4 -0
  250. package/lib/plugins/DragDropPastePlugin/index.d.ts +1 -0
  251. package/lib/plugins/DragDropPastePlugin/index.js +33 -0
  252. package/lib/plugins/DraggableBlockPlugin/index.d.ts +12 -0
  253. package/lib/plugins/DraggableBlockPlugin/index.js +36 -0
  254. package/lib/plugins/EmojiPickerPlugin/index.d.ts +1 -0
  255. package/lib/plugins/EmojiPickerPlugin/index.js +80 -0
  256. package/lib/plugins/EmojisPlugin/index.d.ts +2 -0
  257. package/lib/plugins/EmojisPlugin/index.js +52 -0
  258. package/lib/plugins/EquationsPlugin/index.d.ts +14 -0
  259. package/lib/plugins/EquationsPlugin/index.js +34 -0
  260. package/lib/plugins/ExcalidrawPlugin/index.d.ts +5 -0
  261. package/lib/plugins/ExcalidrawPlugin/index.js +44 -0
  262. package/lib/plugins/FigmaPlugin/index.d.ts +4 -0
  263. package/lib/plugins/FigmaPlugin/index.js +20 -0
  264. package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +15 -0
  265. package/lib/plugins/FloatingLinkEditorPlugin/index.js +280 -0
  266. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +7 -0
  267. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +219 -0
  268. package/lib/plugins/ImagesPlugin/index.d.ts +24 -0
  269. package/lib/plugins/ImagesPlugin/index.js +195 -0
  270. package/lib/plugins/InlineImagePlugin/index.d.ts +17 -0
  271. package/lib/plugins/InlineImagePlugin/index.js +180 -0
  272. package/lib/plugins/KeywordsPlugin/index.d.ts +2 -0
  273. package/lib/plugins/KeywordsPlugin/index.js +31 -0
  274. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +6 -0
  275. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +21 -0
  276. package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +7 -0
  277. package/lib/plugins/LayoutPlugin/LayoutPlugin.js +131 -0
  278. package/lib/plugins/LinkPlugin/index.d.ts +6 -0
  279. package/lib/plugins/LinkPlugin/index.js +11 -0
  280. package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +2 -0
  281. package/lib/plugins/MarkdownShortcutPlugin/index.js +6 -0
  282. package/lib/plugins/MarkdownTransformers/index.d.ts +8 -0
  283. package/lib/plugins/MarkdownTransformers/index.js +234 -0
  284. package/lib/plugins/MaxLengthPlugin/index.d.ts +3 -0
  285. package/lib/plugins/MaxLengthPlugin/index.js +37 -0
  286. package/lib/plugins/MentionsPlugin/index.d.ts +2 -0
  287. package/lib/plugins/MentionsPlugin/index.js +564 -0
  288. package/lib/plugins/PageBreakPlugin/index.d.ts +4 -0
  289. package/lib/plugins/PageBreakPlugin/index.js +27 -0
  290. package/lib/plugins/PasteLogPlugin/index.d.ts +2 -0
  291. package/lib/plugins/PasteLogPlugin/index.js +27 -0
  292. package/lib/plugins/PollPlugin/index.d.ts +8 -0
  293. package/lib/plugins/PollPlugin/index.js +38 -0
  294. package/lib/plugins/ShortcutsPlugin/index.d.ts +6 -0
  295. package/lib/plugins/ShortcutsPlugin/index.js +112 -0
  296. package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +59 -0
  297. package/lib/plugins/ShortcutsPlugin/shortcuts.js +169 -0
  298. package/lib/plugins/SpecialTextPlugin/index.d.ts +2 -0
  299. package/lib/plugins/SpecialTextPlugin/index.js +46 -0
  300. package/lib/plugins/SpeechToTextPlugin/index.d.ts +5 -0
  301. package/lib/plugins/SpeechToTextPlugin/index.js +82 -0
  302. package/lib/plugins/StickyPlugin/index.d.ts +2 -0
  303. package/lib/plugins/StickyPlugin/index.js +12 -0
  304. package/lib/plugins/TabFocusPlugin/index.d.ts +1 -0
  305. package/lib/plugins/TabFocusPlugin/index.js +34 -0
  306. package/lib/plugins/TableActionMenuPlugin/index.d.ts +5 -0
  307. package/lib/plugins/TableActionMenuPlugin/index.js +492 -0
  308. package/lib/plugins/TableCellResizer/index.d.ts +3 -0
  309. package/lib/plugins/TableCellResizer/index.js +297 -0
  310. package/lib/plugins/TableHoverActionsPlugin/index.d.ts +4 -0
  311. package/lib/plugins/TableHoverActionsPlugin/index.js +188 -0
  312. package/lib/plugins/TableOfContentsPlugin/index.d.ts +2 -0
  313. package/lib/plugins/TableOfContentsPlugin/index.js +116 -0
  314. package/lib/plugins/TablePlugin.d.ts +31 -0
  315. package/lib/plugins/TablePlugin.js +63 -0
  316. package/lib/plugins/TestRecorderPlugin/index.d.ts +3 -0
  317. package/lib/plugins/TestRecorderPlugin/index.js +346 -0
  318. package/lib/plugins/ToolbarPlugin/fontSize.d.ts +9 -0
  319. package/lib/plugins/ToolbarPlugin/fontSize.js +80 -0
  320. package/lib/plugins/ToolbarPlugin/index.d.ts +9 -0
  321. package/lib/plugins/ToolbarPlugin/index.js +500 -0
  322. package/lib/plugins/ToolbarPlugin/utils.d.ts +26 -0
  323. package/lib/plugins/ToolbarPlugin/utils.js +243 -0
  324. package/lib/plugins/TreeViewPlugin/index.d.ts +2 -0
  325. package/lib/plugins/TreeViewPlugin/index.js +7 -0
  326. package/lib/plugins/TwitterPlugin/index.d.ts +4 -0
  327. package/lib/plugins/TwitterPlugin/index.js +20 -0
  328. package/lib/plugins/TypingPerfPlugin/index.d.ts +2 -0
  329. package/lib/plugins/TypingPerfPlugin/index.js +93 -0
  330. package/lib/plugins/YouTubePlugin/index.d.ts +4 -0
  331. package/lib/plugins/YouTubePlugin/index.js +20 -0
  332. package/lib/server/validation.d.ts +1 -0
  333. package/lib/server/validation.js +111 -0
  334. package/lib/setupEnv.d.ts +2 -0
  335. package/lib/setupEnv.js +25 -0
  336. package/lib/themes/CommentEditorTheme.d.ts +4 -0
  337. package/lib/themes/CommentEditorTheme.js +7 -0
  338. package/lib/themes/PlaygroundEditorTheme.d.ts +4 -0
  339. package/lib/themes/PlaygroundEditorTheme.js +120 -0
  340. package/lib/themes/StickyEditorTheme.d.ts +4 -0
  341. package/lib/themes/StickyEditorTheme.js +7 -0
  342. package/lib/tyes.dt.d.ts +12 -0
  343. package/lib/tyes.dt.js +0 -0
  344. package/lib/ui/Button.d.ts +12 -0
  345. package/lib/ui/Button.js +6 -0
  346. package/lib/ui/ColorPicker.d.ts +14 -0
  347. package/lib/ui/ColorPicker.js +219 -0
  348. package/lib/ui/ContentEditable.d.ts +9 -0
  349. package/lib/ui/ContentEditable.js +6 -0
  350. package/lib/ui/Dialog.d.ts +10 -0
  351. package/lib/ui/Dialog.js +8 -0
  352. package/lib/ui/DropDown.d.ts +18 -0
  353. package/lib/ui/DropDown.js +133 -0
  354. package/lib/ui/DropdownColorPicker.d.ts +13 -0
  355. package/lib/ui/DropdownColorPicker.js +6 -0
  356. package/lib/ui/EquationEditor.d.ts +8 -0
  357. package/lib/ui/EquationEditor.js +11 -0
  358. package/lib/ui/ExcalidrawModal.d.ts +42 -0
  359. package/lib/ui/ExcalidrawModal.js +103 -0
  360. package/lib/ui/FileInput.d.ts +10 -0
  361. package/lib/ui/FileInput.js +5 -0
  362. package/lib/ui/FlashMessage.d.ts +7 -0
  363. package/lib/ui/FlashMessage.js +6 -0
  364. package/lib/ui/ImageResizer.d.ts +17 -0
  365. package/lib/ui/ImageResizer.js +171 -0
  366. package/lib/ui/KatexEquationAlterer.d.ts +8 -0
  367. package/lib/ui/KatexEquationAlterer.js +23 -0
  368. package/lib/ui/KatexRenderer.d.ts +6 -0
  369. package/lib/ui/KatexRenderer.js +24 -0
  370. package/lib/ui/Modal.d.ts +9 -0
  371. package/lib/ui/Modal.js +48 -0
  372. package/lib/ui/Select.d.ts +8 -0
  373. package/lib/ui/Select.js +5 -0
  374. package/lib/ui/Switch.d.ts +8 -0
  375. package/lib/ui/Switch.js +6 -0
  376. package/lib/ui/TextInput.d.ts +13 -0
  377. package/lib/ui/TextInput.js +7 -0
  378. package/lib/utils/docSerialization.d.ts +3 -0
  379. package/lib/utils/docSerialization.js +56 -0
  380. package/lib/utils/emoji-list.d.ts +20 -0
  381. package/lib/utils/emoji-list.js +16605 -0
  382. package/lib/utils/getDOMRangeRect.d.ts +8 -0
  383. package/lib/utils/getDOMRangeRect.js +22 -0
  384. package/lib/utils/getSelectedNode.d.ts +2 -0
  385. package/lib/utils/getSelectedNode.js +24 -0
  386. package/lib/utils/getThemeSelector.d.ts +2 -0
  387. package/lib/utils/getThemeSelector.js +10 -0
  388. package/lib/utils/isMobileWidth.d.ts +7 -0
  389. package/lib/utils/isMobileWidth.js +7 -0
  390. package/lib/utils/joinClasses.d.ts +1 -0
  391. package/lib/utils/joinClasses.js +3 -0
  392. package/lib/utils/setFloatingElemPosition.d.ts +1 -0
  393. package/lib/utils/setFloatingElemPosition.js +55 -0
  394. package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +1 -0
  395. package/lib/utils/setFloatingElemPositionForLinkEditor.js +32 -0
  396. package/lib/utils/swipe.d.ts +4 -0
  397. package/lib/utils/swipe.js +90 -0
  398. package/lib/utils/url.d.ts +2 -0
  399. package/lib/utils/url.js +27 -0
  400. package/package.json +82 -51
  401. package/lib/DiffMerge.d.ts +0 -39
  402. package/lib/DiffMerge.js +0 -437
  403. package/lib/LoroCollaborativePlugin.d.ts +0 -62
  404. package/lib/LoroCollaborativePlugin.js +0 -2826
  405. package/lib/stableNodeState.d.ts +0 -8
  406. package/lib/stableNodeState.js +0 -15
@@ -0,0 +1,168 @@
1
+ import { $getRoot } from 'lexical';
2
+ import { getNodeMapper } from '../nodes/NodesMapper';
3
+ /**
4
+ * Handle RootNode creation (typically only happens once during initialization)
5
+ */
6
+ export function createRootNodeInLoro(nodeKey, lexicalNodeJSON, // JSON object from exportJSON()
7
+ options) {
8
+ const { tree, peerId } = options;
9
+ const mapper = getNodeMapper();
10
+ // Use mapper to get or create the tree node (don't pass lexicalNode to avoid context issues)
11
+ // Root node has no parent (undefined) and is always at index 0
12
+ const rootTreeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, // don't pass lexicalNode to avoid context issues
13
+ undefined, // no parent for root
14
+ 0 // always at index 0
15
+ );
16
+ // Store complete lexical node data as clean JSON if provided
17
+ if (lexicalNodeJSON) {
18
+ try {
19
+ // Store complete lexical JSON without all key-related fields
20
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
21
+ const { key, __key, lexicalKey, ...cleanedData } = lexicalNodeJSON;
22
+ rootTreeNode.data.set('lexical', cleanedData);
23
+ }
24
+ else {
25
+ rootTreeNode.data.set('lexical', lexicalNodeJSON);
26
+ }
27
+ }
28
+ catch (error) {
29
+ console.warn('Failed to store lexical node JSON for RootNode:', error);
30
+ }
31
+ }
32
+ // Store only essential metadata
33
+ rootTreeNode.data.set('elementType', 'root');
34
+ rootTreeNode.data.set('createdAt', Date.now());
35
+ // The exported Lexical node data is already propagated by the mapper
36
+ // Return the TreeID from the node's ID
37
+ return rootTreeNode.id;
38
+ }
39
+ /**
40
+ * Handle RootNode updates (rarely needed since root doesn't change much)
41
+ */
42
+ export function updateRootNodeInLoro(nodeKey, lexicalNodeJSON, // JSON object from exportJSON()
43
+ options) {
44
+ const mapper = getNodeMapper();
45
+ // Get the existing tree node using the mapper (don't pass lexicalNode to avoid context issues)
46
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
47
+ // Store complete lexical node data as clean JSON if provided
48
+ if (lexicalNodeJSON) {
49
+ try {
50
+ // Store complete lexical JSON without all key-related fields
51
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
52
+ const { key, __key, lexicalKey, ...cleanedData } = lexicalNodeJSON;
53
+ treeNode.data.set('lexical', cleanedData);
54
+ }
55
+ else {
56
+ treeNode.data.set('lexical', lexicalNodeJSON);
57
+ }
58
+ }
59
+ catch (error) {
60
+ console.warn('Failed to store lexical node JSON for RootNode update:', error);
61
+ }
62
+ }
63
+ // Update only essential metadata
64
+ treeNode.data.set('elementType', 'root');
65
+ treeNode.data.set('lastUpdated', Date.now());
66
+ }
67
+ /**
68
+ * Handle RootNode deletion (should rarely happen, but included for completeness)
69
+ */
70
+ export function deleteRootNodeInLoro(nodeKey, options) {
71
+ const mapper = getNodeMapper();
72
+ // Note: Deleting root node should be done with extreme caution
73
+ // as it represents the entire editor content
74
+ mapper.deleteMapping(nodeKey);
75
+ }
76
+ /**
77
+ * Create RootNode in Lexical from Loro tree data
78
+ */
79
+ export function createRootNodeFromLoro(treeId, options) {
80
+ // In Lexical, there's always exactly one root node
81
+ // This function would typically be called during initialization
82
+ const root = $getRoot();
83
+ // Root node already exists, just return it
84
+ return root;
85
+ }
86
+ /**
87
+ * Update RootNode in Lexical from Loro tree data
88
+ */
89
+ export function updateRootNodeFromLoro(treeId, options) {
90
+ // Root node updates are typically propagated at the document level
91
+ // Most changes to root would be indirect (children changes)
92
+ console.log('Root node update from Loro:', treeId);
93
+ }
94
+ /**
95
+ * Delete RootNode in Lexical (should not happen in normal operation)
96
+ */
97
+ export function deleteRootNodeFromLoro(treeId, options) {
98
+ // Root node deletion should not happen in normal circumstances
99
+ // This would essentially clear the entire editor
100
+ console.warn('Attempting to delete root node - this should not happen:', treeId);
101
+ }
102
+ /**
103
+ * Utility to check if a tree node represents a RootNode
104
+ */
105
+ export function isRootNodeInTree(treeId, tree) {
106
+ if (!tree.has(treeId)) {
107
+ return false;
108
+ }
109
+ const treeNode = tree.getNodeByID(treeId);
110
+ return treeNode?.data.get('nodeType') === 'root';
111
+ }
112
+ /**
113
+ * Main propagate method for RootNode - propagates all mutation types
114
+ */
115
+ export function propagateRootNode(update, mutation, nodeKey, options) {
116
+ const { tree, peerId } = options;
117
+ switch (mutation) {
118
+ case 'created': {
119
+ // Get the current editor state to find the root node
120
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
121
+ if (currentNode) {
122
+ // Export node data as JSON object within editor context where node methods are available
123
+ let lexicalNodeJSON = undefined;
124
+ update.editorState.read(() => {
125
+ if (currentNode.getType() === 'root') {
126
+ try {
127
+ lexicalNodeJSON = currentNode.exportJSON();
128
+ }
129
+ catch (error) {
130
+ console.warn('Failed to export root node JSON:', error);
131
+ }
132
+ }
133
+ });
134
+ if (lexicalNodeJSON) {
135
+ createRootNodeInLoro(nodeKey, lexicalNodeJSON, options);
136
+ }
137
+ }
138
+ break;
139
+ }
140
+ case 'updated': {
141
+ // Root nodes typically don't change much, but we can update metadata
142
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
143
+ if (currentNode) {
144
+ // Export node data as JSON object within editor context where node methods are available
145
+ let lexicalNodeJSON = undefined;
146
+ update.editorState.read(() => {
147
+ if (currentNode.getType() === 'root') {
148
+ try {
149
+ lexicalNodeJSON = currentNode.exportJSON();
150
+ }
151
+ catch (error) {
152
+ console.warn('Failed to export root node JSON for update:', error);
153
+ }
154
+ }
155
+ });
156
+ if (lexicalNodeJSON) {
157
+ updateRootNodeInLoro(nodeKey, lexicalNodeJSON, options);
158
+ }
159
+ }
160
+ break;
161
+ }
162
+ case 'destroyed': {
163
+ // Delete the root node from Loro tree
164
+ deleteRootNodeInLoro(nodeKey, options);
165
+ break;
166
+ }
167
+ }
168
+ }
@@ -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,434 @@
1
+ import { $createTextNode, $isTextNode } from 'lexical';
2
+ import { getNodeMapper } from '../nodes/NodesMapper';
3
+ import { $diffTextContentAndApplyDelta } from '../utils/Utils';
4
+ /**
5
+ * Create TextNode in Loro tree
6
+ */
7
+ export function createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, // JSON object from exportJSON()
8
+ options) {
9
+ const mapper = getNodeMapper();
10
+ // Debug logging for text node creation issues
11
+ if (!parentId) {
12
+ console.warn(`❌ Creating TextNode ${nodeKey} without parent in Loro tree - THIS WILL FAIL`);
13
+ return null; // Return early to avoid creating orphaned nodes
14
+ }
15
+ // Use mapper to get or create the tree node
16
+ // Note: We can't pass lexicalNode directly due to context issues, but parentId should be sufficient
17
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined, // don't pass lexicalNode to avoid context issues
18
+ parentId, index);
19
+ // Store complete lexical node data as clean JSON if provided
20
+ if (lexicalNodeJSON) {
21
+ try {
22
+ // Store complete lexical JSON without the key
23
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
24
+ const { key, __key, lexicalKey, ...cleanedData } = lexicalNodeJSON;
25
+ treeNode.data.set('lexical', cleanedData);
26
+ }
27
+ else {
28
+ treeNode.data.set('lexical', lexicalNodeJSON);
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.warn('Failed to store lexical node JSON for TextNode:', error);
33
+ }
34
+ }
35
+ // Store only essential metadata (elementType for debug panel)
36
+ treeNode.data.set('elementType', 'text');
37
+ treeNode.data.set('createdAt', Date.now());
38
+ // Return the TreeID from the node's ID
39
+ return treeNode.id;
40
+ }
41
+ /**
42
+ * Update TextNode in Loro tree
43
+ */
44
+ export function updateTextNodeInLoro(nodeKey, newTextContent, format, mode, lexicalNodeJSON, // JSON object from exportJSON()
45
+ options) {
46
+ const mapper = getNodeMapper();
47
+ // Get the existing tree node using the mapper
48
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey, undefined);
49
+ if (!treeNode) {
50
+ console.warn(`📝 TextNode ${nodeKey} not found in Loro, skipping update`);
51
+ return;
52
+ }
53
+ // Note: Container validation is done in each try-catch block below since
54
+ // the container can be deleted between operations
55
+ // Store complete lexical node data as clean JSON if provided
56
+ if (lexicalNodeJSON) {
57
+ try {
58
+ // Store complete lexical JSON without the key
59
+ if ('key' in lexicalNodeJSON || '__key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
60
+ const { key, __key, lexicalKey, ...cleanedData } = lexicalNodeJSON;
61
+ treeNode.data.set('lexical', cleanedData);
62
+ }
63
+ else {
64
+ treeNode.data.set('lexical', lexicalNodeJSON);
65
+ }
66
+ }
67
+ catch (error) {
68
+ // This is expected during text operations when nodes get deleted/recreated
69
+ console.warn(`📝 TextNode ${nodeKey} container was deleted during update, skipping (normal during text operations):`, error.message);
70
+ return;
71
+ }
72
+ }
73
+ // Update only essential metadata
74
+ try {
75
+ treeNode.data.set('elementType', 'text');
76
+ treeNode.data.set('updatedAt', Date.now());
77
+ }
78
+ catch (error) {
79
+ console.warn(`📝 TextNode ${nodeKey} container deleted during metadata update (normal during text operations):`, error.message);
80
+ return;
81
+ }
82
+ // The exported Lexical node data is already propagated by the mapper
83
+ // No additional JSON export needed since mapper propagates exportJSON automatically
84
+ }
85
+ /**
86
+ * Delete TextNode from Loro tree
87
+ */
88
+ export function deleteTextNodeInLoro(nodeKey, options) {
89
+ const mapper = getNodeMapper();
90
+ mapper.deleteMapping(nodeKey);
91
+ }
92
+ /**
93
+ * Create TextNode in Lexical from Loro tree data
94
+ */
95
+ export function createTextNodeFromLoro(treeId, parentNode, index, options) {
96
+ const { tree } = options;
97
+ if (!tree.has(treeId)) {
98
+ return null;
99
+ }
100
+ const treeNode = tree.getNodeByID(treeId);
101
+ if (!treeNode) {
102
+ return null;
103
+ }
104
+ // Get LexicalNodeData (JSON object format only)
105
+ const lexicalData = treeNode.data.get('lexical');
106
+ let textNode;
107
+ if (lexicalData && typeof lexicalData === 'object') {
108
+ try {
109
+ // lexicalData is a direct JSON object, use it to create a TextNode
110
+ const lexicalDataObj = lexicalData;
111
+ const textContent = lexicalDataObj.text || lexicalDataObj.__text || '';
112
+ const format = lexicalDataObj.format || lexicalDataObj.__format || 0;
113
+ const mode = lexicalDataObj.mode || lexicalDataObj.__mode || 0;
114
+ textNode = $createTextNode(textContent);
115
+ textNode.setFormat(format);
116
+ textNode.setMode(mode);
117
+ }
118
+ catch (error) {
119
+ console.warn('Failed to create TextNode from JSON data for TreeID:', treeId, error);
120
+ return null;
121
+ }
122
+ }
123
+ else {
124
+ // No lexical JSON data found - cannot create TextNode
125
+ console.warn('No lexical JSON data found for TextNode TreeID:', treeId);
126
+ return null;
127
+ }
128
+ // Apply mode if present (only for old format)
129
+ if (!lexicalData || typeof lexicalData !== 'string') {
130
+ // const mode = treeNode.data.get('mode');
131
+ // if (mode && typeof textNode.setMode === 'function') {
132
+ // textNode.setMode(mode);
133
+ // }
134
+ }
135
+ // Insert into the parent at the specified index
136
+ if (index !== undefined && index >= 0) {
137
+ parentNode.splice(index, 0, [textNode]);
138
+ }
139
+ else {
140
+ parentNode.append(textNode);
141
+ }
142
+ return textNode;
143
+ }
144
+ /**
145
+ * Update TextNode in Lexical from Loro tree data
146
+ */
147
+ export function updateTextNodeFromLoro(treeId, textNode, newParentNode, newIndex, options) {
148
+ const { tree } = options;
149
+ if (!tree.has(treeId)) {
150
+ return;
151
+ }
152
+ const treeNode = tree.getNodeByID(treeId);
153
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
154
+ return;
155
+ }
156
+ // Update text content if it has changed
157
+ const textContent = treeNode.data.get('textContent');
158
+ if (textContent !== undefined && typeof textContent === 'string' &&
159
+ textNode.getTextContent() !== textContent) {
160
+ const currentText = textNode.getTextContent();
161
+ $diffTextContentAndApplyDelta(textNode, textNode.getKey(), currentText, textContent);
162
+ }
163
+ // Update format if it has changed
164
+ const format = treeNode.data.get('format');
165
+ if (format !== undefined && typeof format === 'number') {
166
+ textNode.setFormat(format);
167
+ }
168
+ // Update mode if it has changed (skip for now due to type complexity)
169
+ // const mode = treeNode.data.get('mode');
170
+ // if (mode !== undefined && typeof lexicalNode.setMode === 'function') {
171
+ // lexicalNode.setMode(mode);
172
+ // }
173
+ // If parent or position changed, move the node
174
+ if (newParentNode && newIndex !== undefined) {
175
+ // Remove from current location
176
+ textNode.remove();
177
+ // Insert at new location
178
+ newParentNode.splice(newIndex, 0, [textNode]);
179
+ }
180
+ }
181
+ /**
182
+ * Delete TextNode from Lexical
183
+ */
184
+ export function deleteTextNodeFromLoro(treeId, lexicalNode, options) {
185
+ if ($isTextNode(lexicalNode)) {
186
+ lexicalNode.remove();
187
+ }
188
+ }
189
+ /**
190
+ * Utility to check if a tree node represents a TextNode
191
+ */
192
+ export function isTextNodeInTree(treeId, tree) {
193
+ if (!tree.has(treeId)) {
194
+ return false;
195
+ }
196
+ const treeNode = tree.getNodeByID(treeId);
197
+ return treeNode?.data.get('nodeType') === 'text';
198
+ }
199
+ /**
200
+ * Get TextNode data from Loro tree
201
+ */
202
+ export function getTextNodeDataFromTree(treeId, tree) {
203
+ if (!tree.has(treeId)) {
204
+ return null;
205
+ }
206
+ const treeNode = tree.getNodeByID(treeId);
207
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
208
+ return null;
209
+ }
210
+ return {
211
+ nodeType: 'text',
212
+ textContent: treeNode.data.get('textContent'),
213
+ format: treeNode.data.get('format'),
214
+ mode: treeNode.data.get('mode'),
215
+ createdAt: treeNode.data.get('createdAt'),
216
+ lastUpdated: treeNode.data.get('lastUpdated'),
217
+ };
218
+ }
219
+ /**
220
+ * Apply text formatting operations (bold, italic, etc.)
221
+ */
222
+ export function applyTextFormatInLoro(nodeKey, formatType, apply, options) {
223
+ const mapper = getNodeMapper();
224
+ // Get the existing Loro node from the mapper
225
+ const treeNode = mapper.getLoroNodeByLexicalKey(nodeKey);
226
+ if (!treeNode) {
227
+ return;
228
+ }
229
+ if (!treeNode || treeNode.data.get('nodeType') !== 'text') {
230
+ return;
231
+ }
232
+ // Check if the TreeNode's container is still valid
233
+ try {
234
+ // Try a simple read operation to verify the container is accessible
235
+ treeNode.data.get('format');
236
+ }
237
+ catch (error) {
238
+ console.warn(`📝 TextNode ${nodeKey} container deleted during format check (normal during text operations):`, error.message);
239
+ return;
240
+ }
241
+ let currentFormat = treeNode.data.get('format') || 0;
242
+ const formatNumber = formatType;
243
+ if (apply) {
244
+ // Add the format flag
245
+ currentFormat = currentFormat | formatNumber;
246
+ }
247
+ else {
248
+ // Remove the format flag
249
+ currentFormat = currentFormat & ~formatNumber;
250
+ }
251
+ try {
252
+ treeNode.data.set('format', currentFormat);
253
+ treeNode.data.set('lastUpdated', Date.now());
254
+ }
255
+ catch (error) {
256
+ console.warn(`📝 TextNode ${nodeKey} container deleted during format update (normal during text operations):`, error.message);
257
+ return;
258
+ }
259
+ }
260
+ /**
261
+ * Main propagate method for TextNode - propagates all mutation types
262
+ */
263
+ export function propagateTextNode(update, mutation, nodeKey, options) {
264
+ const { tree, peerId } = options;
265
+ switch (mutation) {
266
+ case 'created': {
267
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
268
+ // Check if this node already exists in Loro
269
+ const mapper = getNodeMapper();
270
+ const existingTreeID = mapper.getTreeIDByLexicalKey(nodeKey);
271
+ if (existingTreeID && currentNode && $isTextNode(currentNode)) {
272
+ // Check if the existing text node has the correct parent relationship
273
+ const { currentParentId, expectedParentId } = update.editorState.read(() => {
274
+ const parent = currentNode.getParent();
275
+ const expectedParentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
276
+ // Get the current parent from Loro tree
277
+ let currentParentId;
278
+ try {
279
+ const treeNode = tree.getNodeByID(existingTreeID);
280
+ if (treeNode) {
281
+ const parentNode = treeNode.parent();
282
+ currentParentId = parentNode ? parentNode.id.toString() : undefined;
283
+ }
284
+ }
285
+ catch (error) {
286
+ console.warn(`📝 Failed to get parent for existing TreeID ${existingTreeID}:`, error);
287
+ }
288
+ return { currentParentId, expectedParentId };
289
+ });
290
+ if (currentParentId === expectedParentId) {
291
+ return; // Skip creation since the parent relationship is correct
292
+ }
293
+ else {
294
+ // Get the actual TreeNode and its ID before deleting
295
+ let actualTreeID = existingTreeID;
296
+ try {
297
+ const treeNode = tree.getNodeByID(existingTreeID);
298
+ if (treeNode) {
299
+ actualTreeID = treeNode.id;
300
+ }
301
+ }
302
+ catch (error) {
303
+ console.warn(`📝 Could not get TreeNode for ${existingTreeID} during creation:`, error);
304
+ }
305
+ // Clear the old mapping first to avoid conflicts
306
+ mapper.deleteMapping(nodeKey);
307
+ // Then delete the TreeNode from Loro tree
308
+ try {
309
+ if (tree.has(actualTreeID)) {
310
+ tree.delete(actualTreeID);
311
+ }
312
+ }
313
+ catch (error) {
314
+ console.warn(`📝 Failed to delete TreeNode ${actualTreeID} during creation:`, error);
315
+ }
316
+ }
317
+ }
318
+ if (currentNode && $isTextNode(currentNode)) {
319
+ // Get parent, positioning, content, and serialized data using editor state context
320
+ const { parent, parentId, index, textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
321
+ const parent = currentNode.getParent();
322
+ // Get parentId from the mapper instead of constructing it manually
323
+ const mapper = getNodeMapper();
324
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
325
+ const index = currentNode.getIndexWithinParent();
326
+ const textContent = currentNode.getTextContent();
327
+ const format = currentNode.getFormat();
328
+ const mode = currentNode.getMode();
329
+ // Export node data as JSON object within editor context where node methods are available
330
+ let lexicalNodeJSON = undefined;
331
+ try {
332
+ lexicalNodeJSON = currentNode.exportJSON();
333
+ }
334
+ catch (error) {
335
+ console.warn('Failed to export node JSON in propagateTextNode created:', error);
336
+ }
337
+ return { parent, parentId, index, textContent, format, mode, lexicalNodeJSON };
338
+ });
339
+ createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, options);
340
+ }
341
+ break;
342
+ }
343
+ case 'updated': {
344
+ const currentNode = update.editorState._nodeMap.get(nodeKey);
345
+ if (currentNode && $isTextNode(currentNode)) {
346
+ // First, check if this TextNode's parent has changed (like during double Enter)
347
+ const mapper = getNodeMapper();
348
+ const existingTreeID = mapper.getTreeIDByLexicalKey(nodeKey);
349
+ if (existingTreeID) {
350
+ const { currentParentId, expectedParentId, parent } = update.editorState.read(() => {
351
+ const parent = currentNode.getParent();
352
+ const expectedParentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
353
+ // Get the current parent from Loro tree
354
+ let currentParentId;
355
+ try {
356
+ const treeNode = tree.getNodeByID(existingTreeID);
357
+ if (treeNode) {
358
+ const parentNode = treeNode.parent();
359
+ currentParentId = parentNode ? parentNode.id.toString() : undefined;
360
+ }
361
+ }
362
+ catch (error) {
363
+ console.warn(`📝 Failed to get parent for existing TreeID ${existingTreeID} during update:`, error);
364
+ }
365
+ return { currentParentId, expectedParentId, parent };
366
+ });
367
+ if (currentParentId !== expectedParentId) {
368
+ // Get the actual TreeNode and its ID before deleting
369
+ let actualTreeID = existingTreeID;
370
+ try {
371
+ const treeNode = tree.getNodeByID(existingTreeID);
372
+ if (treeNode) {
373
+ actualTreeID = treeNode.id;
374
+ }
375
+ }
376
+ catch (error) {
377
+ console.warn(`📝 Could not get TreeNode for ${existingTreeID}:`, error);
378
+ }
379
+ // Clear the old mapping first to avoid conflicts
380
+ mapper.deleteMapping(nodeKey);
381
+ // Then delete the TreeNode from Loro tree
382
+ try {
383
+ if (tree.has(actualTreeID)) {
384
+ tree.delete(actualTreeID);
385
+ }
386
+ }
387
+ catch (error) {
388
+ console.warn(`📝 Failed to delete TreeNode ${actualTreeID} during update:`, error);
389
+ }
390
+ // Now recreate the TextNode with the new parent (treat as "created")
391
+ const { parentId, index, textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
392
+ const parentId = parent ? mapper.getTreeIDByLexicalKey(parent.getKey()) : undefined;
393
+ const index = currentNode.getIndexWithinParent();
394
+ const textContent = currentNode.getTextContent();
395
+ const format = currentNode.getFormat();
396
+ const mode = currentNode.getMode();
397
+ let lexicalNodeJSON = undefined;
398
+ try {
399
+ lexicalNodeJSON = currentNode.exportJSON();
400
+ }
401
+ catch (error) {
402
+ console.warn('Failed to export node JSON during TextNode recreation:', error);
403
+ }
404
+ return { parentId, index, textContent, format, mode, lexicalNodeJSON };
405
+ });
406
+ createTextNodeInLoro(nodeKey, textContent, format, mode, parentId, index, lexicalNodeJSON, options);
407
+ return; // Exit early since we recreated the node
408
+ }
409
+ }
410
+ // Normal update case - parent hasn't changed
411
+ const { textContent, format, mode, lexicalNodeJSON } = update.editorState.read(() => {
412
+ const textContent = currentNode.getTextContent();
413
+ const format = currentNode.getFormat();
414
+ const mode = currentNode.getMode();
415
+ // Export node data as JSON object within editor context where node methods are available
416
+ let lexicalNodeJSON = undefined;
417
+ try {
418
+ lexicalNodeJSON = currentNode.exportJSON();
419
+ }
420
+ catch (error) {
421
+ console.warn('Failed to export node JSON in propagateTextNode updated:', error);
422
+ }
423
+ return { textContent, format, mode, lexicalNodeJSON };
424
+ });
425
+ updateTextNodeInLoro(nodeKey, textContent, format, mode, lexicalNodeJSON, options);
426
+ }
427
+ break;
428
+ }
429
+ case 'destroyed': {
430
+ deleteTextNodeInLoro(nodeKey, options);
431
+ break;
432
+ }
433
+ }
434
+ }