@datalayer/lexical-loro 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +2 -2
  2. package/lib/App.d.ts +2 -0
  3. package/lib/App.js +141 -0
  4. package/lib/Editor.d.ts +2 -0
  5. package/lib/Editor.js +116 -0
  6. package/lib/Settings.d.ts +2 -0
  7. package/lib/Settings.js +57 -0
  8. package/lib/appSettings.d.ts +36 -0
  9. package/lib/appSettings.js +48 -0
  10. package/lib/collab/loro/Bindings.d.ts +41 -0
  11. package/lib/collab/loro/Bindings.js +99 -0
  12. package/lib/collab/loro/Debug.d.ts +33 -0
  13. package/lib/collab/loro/Debug.js +452 -0
  14. package/lib/collab/loro/LexicalCollaborationContext.d.ts +19 -0
  15. package/lib/collab/loro/LexicalCollaborationContext.js +52 -0
  16. package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +29 -0
  17. package/lib/collab/loro/LexicalCollaborationPlugin.js +111 -0
  18. package/lib/collab/loro/State.d.ts +53 -0
  19. package/lib/collab/loro/State.js +94 -0
  20. package/lib/collab/loro/components/LoroCollaborationUI.d.ts +13 -0
  21. package/lib/collab/loro/components/LoroCollaborationUI.js +9 -0
  22. package/lib/collab/loro/components/LoroCollaborators.d.ts +8 -0
  23. package/lib/collab/loro/components/LoroCollaborators.js +90 -0
  24. package/lib/collab/loro/components/index.d.ts +2 -0
  25. package/lib/collab/loro/components/index.js +6 -0
  26. package/lib/collab/loro/index.d.ts +6 -0
  27. package/lib/collab/loro/index.js +10 -0
  28. package/lib/collab/loro/integrators/BaseIntegrator.d.ts +14 -0
  29. package/lib/collab/loro/integrators/BaseIntegrator.js +5 -0
  30. package/lib/collab/loro/integrators/CounterIntegrator.d.ts +23 -0
  31. package/lib/collab/loro/integrators/CounterIntegrator.js +44 -0
  32. package/lib/collab/loro/integrators/ListIntegrator.d.ts +23 -0
  33. package/lib/collab/loro/integrators/ListIntegrator.js +53 -0
  34. package/lib/collab/loro/integrators/MapIntegrator.d.ts +24 -0
  35. package/lib/collab/loro/integrators/MapIntegrator.js +235 -0
  36. package/lib/collab/loro/integrators/TextIntegrator.d.ts +25 -0
  37. package/lib/collab/loro/integrators/TextIntegrator.js +55 -0
  38. package/lib/collab/loro/integrators/TreeIntegrator.d.ts +41 -0
  39. package/lib/collab/loro/integrators/TreeIntegrator.js +293 -0
  40. package/lib/collab/loro/nodes/NodeFactory.d.ts +15 -0
  41. package/lib/collab/loro/nodes/NodeFactory.js +80 -0
  42. package/lib/collab/loro/nodes/NodesMapper.d.ts +120 -0
  43. package/lib/collab/loro/nodes/NodesMapper.js +289 -0
  44. package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +60 -0
  45. package/lib/collab/loro/propagators/DecoratorNodePropagator.js +306 -0
  46. package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +62 -0
  47. package/lib/collab/loro/propagators/ElementNodePropagator.js +393 -0
  48. package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +57 -0
  49. package/lib/collab/loro/propagators/LineBreakNodePropagator.js +200 -0
  50. package/lib/collab/loro/propagators/RootNodePropagator.d.ts +55 -0
  51. package/lib/collab/loro/propagators/RootNodePropagator.js +174 -0
  52. package/lib/collab/loro/propagators/TextNodePropagator.d.ts +60 -0
  53. package/lib/collab/loro/propagators/TextNodePropagator.js +450 -0
  54. package/lib/collab/loro/propagators/index.d.ts +49 -0
  55. package/lib/collab/loro/propagators/index.js +30 -0
  56. package/lib/collab/loro/provider/websocket.d.ts +117 -0
  57. package/lib/collab/loro/provider/websocket.js +946 -0
  58. package/lib/collab/loro/servers/index.d.ts +0 -0
  59. package/lib/collab/loro/servers/index.js +4 -0
  60. package/lib/collab/loro/servers/ws/callback.d.ts +5 -0
  61. package/lib/collab/loro/servers/ws/callback.js +89 -0
  62. package/lib/collab/loro/servers/ws/server.d.ts +2 -0
  63. package/lib/collab/loro/servers/ws/server.js +29 -0
  64. package/lib/collab/loro/servers/ws/utils.d.ts +40 -0
  65. package/lib/collab/loro/servers/ws/utils.js +517 -0
  66. package/lib/collab/loro/sync/SyncCursors.d.ts +32 -0
  67. package/lib/collab/loro/sync/SyncCursors.js +501 -0
  68. package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +4 -0
  69. package/lib/collab/loro/sync/SyncLexicalToLoro.js +152 -0
  70. package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +5 -0
  71. package/lib/collab/loro/sync/SyncLoroToLexical.js +106 -0
  72. package/lib/collab/loro/types/LexicalNodeData.d.ts +32 -0
  73. package/lib/collab/loro/types/LexicalNodeData.js +75 -0
  74. package/lib/collab/loro/useCollaboration.d.ts +12 -0
  75. package/lib/collab/loro/useCollaboration.js +405 -0
  76. package/lib/collab/loro/utils/InitialContent.d.ts +64 -0
  77. package/lib/collab/loro/utils/InitialContent.js +113 -0
  78. package/lib/collab/loro/utils/Invariant.d.ts +15 -0
  79. package/lib/collab/loro/utils/Invariant.js +24 -0
  80. package/lib/collab/loro/utils/LexicalToLoro.d.ts +18 -0
  81. package/lib/collab/loro/utils/LexicalToLoro.js +100 -0
  82. package/lib/collab/loro/utils/Utils.d.ts +44 -0
  83. package/lib/collab/loro/utils/Utils.js +157 -0
  84. package/lib/collab/loro/wsProvider.d.ts +8 -0
  85. package/lib/collab/loro/wsProvider.js +52 -0
  86. package/lib/collab/utils/invariant.d.ts +1 -0
  87. package/lib/collab/utils/invariant.js +15 -0
  88. package/lib/collab/utils/simpleDiffWithCursor.d.ts +5 -0
  89. package/lib/collab/utils/simpleDiffWithCursor.js +35 -0
  90. package/lib/collab/yjs/Bindings.d.ts +23 -0
  91. package/lib/collab/yjs/Bindings.js +26 -0
  92. package/lib/collab/yjs/Debug.d.ts +23 -0
  93. package/lib/collab/yjs/Debug.js +213 -0
  94. package/lib/collab/yjs/LexicalCollaborationContext.d.ts +10 -0
  95. package/lib/collab/yjs/LexicalCollaborationContext.js +37 -0
  96. package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +21 -0
  97. package/lib/collab/yjs/LexicalCollaborationPlugin.js +63 -0
  98. package/lib/collab/yjs/State.d.ts +51 -0
  99. package/lib/collab/yjs/State.js +35 -0
  100. package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +5 -0
  101. package/lib/collab/yjs/nodes/AnyCollabNode.js +1 -0
  102. package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +22 -0
  103. package/lib/collab/yjs/nodes/CollabDecoratorNode.js +64 -0
  104. package/lib/collab/yjs/nodes/CollabElementNode.d.ts +40 -0
  105. package/lib/collab/yjs/nodes/CollabElementNode.js +462 -0
  106. package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +19 -0
  107. package/lib/collab/yjs/nodes/CollabLineBreakNode.js +44 -0
  108. package/lib/collab/yjs/nodes/CollabTextNode.d.ts +25 -0
  109. package/lib/collab/yjs/nodes/CollabTextNode.js +103 -0
  110. package/lib/collab/yjs/provider/websocket.d.ts +88 -0
  111. package/lib/collab/yjs/provider/websocket.js +415 -0
  112. package/lib/collab/yjs/servers/index.d.ts +0 -0
  113. package/lib/collab/yjs/servers/index.js +0 -0
  114. package/lib/collab/yjs/servers/ws/callback.d.ts +5 -0
  115. package/lib/collab/yjs/servers/ws/callback.js +72 -0
  116. package/lib/collab/yjs/servers/ws/server.d.ts +2 -0
  117. package/lib/collab/yjs/servers/ws/server.js +25 -0
  118. package/lib/collab/yjs/servers/ws/utils.d.ts +49 -0
  119. package/lib/collab/yjs/servers/ws/utils.js +284 -0
  120. package/lib/collab/yjs/sync/SyncCursors.d.ts +39 -0
  121. package/lib/collab/yjs/sync/SyncCursors.js +351 -0
  122. package/lib/collab/yjs/sync/SyncEditorStates.d.ts +10 -0
  123. package/lib/collab/yjs/sync/SyncEditorStates.js +200 -0
  124. package/lib/collab/yjs/useCollaboration.d.ts +12 -0
  125. package/lib/collab/yjs/useCollaboration.js +255 -0
  126. package/lib/collab/yjs/utils/Utils.d.ts +25 -0
  127. package/lib/collab/yjs/utils/Utils.js +402 -0
  128. package/lib/collab/yjs/wsProvider.d.ts +3 -0
  129. package/lib/collab/yjs/wsProvider.js +21 -0
  130. package/lib/commenting/index.d.ts +41 -0
  131. package/lib/commenting/index.js +328 -0
  132. package/lib/context/FlashMessageContext.d.ts +7 -0
  133. package/lib/context/FlashMessageContext.js +24 -0
  134. package/lib/context/SettingsContext.d.ts +12 -0
  135. package/lib/context/SettingsContext.js +38 -0
  136. package/lib/context/SharedHistoryContext.d.ts +11 -0
  137. package/lib/context/SharedHistoryContext.js +11 -0
  138. package/lib/context/ToolbarContext.d.ts +65 -0
  139. package/lib/context/ToolbarContext.js +84 -0
  140. package/lib/demo.d.ts +12 -0
  141. package/lib/demo.js +45 -0
  142. package/lib/hooks/useFlashMessage.d.ts +2 -0
  143. package/lib/hooks/useFlashMessage.js +8 -0
  144. package/lib/hooks/useModal.d.ts +5 -0
  145. package/lib/hooks/useModal.js +26 -0
  146. package/lib/hooks/useReport.d.ts +1 -0
  147. package/lib/hooks/useReport.js +50 -0
  148. package/lib/index.d.ts +1 -0
  149. package/lib/index.js +5 -0
  150. package/lib/nodes/AutocompleteNode.d.ts +27 -0
  151. package/lib/nodes/AutocompleteNode.js +60 -0
  152. package/lib/nodes/CounterComponent.d.ts +6 -0
  153. package/lib/nodes/CounterComponent.js +137 -0
  154. package/lib/nodes/CounterNode.d.ts +23 -0
  155. package/lib/nodes/CounterNode.js +47 -0
  156. package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +8 -0
  157. package/lib/nodes/DateTimeNode/DateTimeComponent.js +119 -0
  158. package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +27 -0
  159. package/lib/nodes/DateTimeNode/DateTimeNode.js +82 -0
  160. package/lib/nodes/EmojiNode.d.ts +18 -0
  161. package/lib/nodes/EmojiNode.js +54 -0
  162. package/lib/nodes/EquationComponent.d.ts +9 -0
  163. package/lib/nodes/EquationComponent.js +75 -0
  164. package/lib/nodes/EquationNode.d.ts +26 -0
  165. package/lib/nodes/EquationNode.js +109 -0
  166. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +8 -0
  167. package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +110 -0
  168. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +50 -0
  169. package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +55 -0
  170. package/lib/nodes/ExcalidrawNode/index.d.ts +32 -0
  171. package/lib/nodes/ExcalidrawNode/index.js +117 -0
  172. package/lib/nodes/FigmaNode.d.ts +20 -0
  173. package/lib/nodes/FigmaNode.js +52 -0
  174. package/lib/nodes/ImageComponent.d.ts +16 -0
  175. package/lib/nodes/ImageComponent.js +272 -0
  176. package/lib/nodes/ImageNode.d.ts +50 -0
  177. package/lib/nodes/ImageNode.js +151 -0
  178. package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +26 -0
  179. package/lib/nodes/InlineImageNode/InlineImageComponent.js +161 -0
  180. package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +59 -0
  181. package/lib/nodes/InlineImageNode/InlineImageNode.js +162 -0
  182. package/lib/nodes/KeywordNode.d.ts +14 -0
  183. package/lib/nodes/KeywordNode.js +37 -0
  184. package/lib/nodes/LayoutContainerNode.d.ts +24 -0
  185. package/lib/nodes/LayoutContainerNode.js +95 -0
  186. package/lib/nodes/LayoutItemNode.d.ts +16 -0
  187. package/lib/nodes/LayoutItemNode.js +69 -0
  188. package/lib/nodes/MentionNode.d.ts +20 -0
  189. package/lib/nodes/MentionNode.js +85 -0
  190. package/lib/nodes/PageBreakNode/index.d.ts +17 -0
  191. package/lib/nodes/PageBreakNode/index.js +83 -0
  192. package/lib/nodes/PlaygroundNodes.d.ts +3 -0
  193. package/lib/nodes/PlaygroundNodes.js +75 -0
  194. package/lib/nodes/PollComponent.d.ts +9 -0
  195. package/lib/nodes/PollComponent.js +85 -0
  196. package/lib/nodes/PollNode.d.ts +43 -0
  197. package/lib/nodes/PollNode.js +153 -0
  198. package/lib/nodes/SpecialTextNode.d.ts +24 -0
  199. package/lib/nodes/SpecialTextNode.js +54 -0
  200. package/lib/nodes/StickyComponent.d.ts +10 -0
  201. package/lib/nodes/StickyComponent.js +162 -0
  202. package/lib/nodes/StickyNode.d.ts +31 -0
  203. package/lib/nodes/StickyNode.js +76 -0
  204. package/lib/nodes/TweetNode.d.ts +21 -0
  205. package/lib/nodes/TweetNode.js +119 -0
  206. package/lib/nodes/YouTubeNode.d.ts +22 -0
  207. package/lib/nodes/YouTubeNode.js +84 -0
  208. package/lib/plugins/ActionsPlugin/index.d.ts +5 -0
  209. package/lib/plugins/ActionsPlugin/index.js +168 -0
  210. package/lib/plugins/AutoEmbedPlugin/index.d.ts +19 -0
  211. package/lib/plugins/AutoEmbedPlugin/index.js +158 -0
  212. package/lib/plugins/AutoLinkPlugin/index.d.ts +2 -0
  213. package/lib/plugins/AutoLinkPlugin/index.js +15 -0
  214. package/lib/plugins/AutocompletePlugin/index.d.ts +10 -0
  215. package/lib/plugins/AutocompletePlugin/index.js +2477 -0
  216. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +7 -0
  217. package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +46 -0
  218. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +17 -0
  219. package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +115 -0
  220. package/lib/plugins/CodeActionMenuPlugin/index.d.ts +5 -0
  221. package/lib/plugins/CodeActionMenuPlugin/index.js +104 -0
  222. package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +1 -0
  223. package/lib/plugins/CodeActionMenuPlugin/utils.js +22 -0
  224. package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +2 -0
  225. package/lib/plugins/CodeHighlightPrismPlugin/index.js +14 -0
  226. package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +2 -0
  227. package/lib/plugins/CodeHighlightShikiPlugin/index.js +14 -0
  228. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +25 -0
  229. package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +135 -0
  230. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +16 -0
  231. package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +83 -0
  232. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +16 -0
  233. package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +85 -0
  234. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +2 -0
  235. package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +12 -0
  236. package/lib/plugins/CollapsiblePlugin/index.d.ts +3 -0
  237. package/lib/plugins/CollapsiblePlugin/index.js +132 -0
  238. package/lib/plugins/CommentPlugin/index.d.ts +9 -0
  239. package/lib/plugins/CommentPlugin/index.js +460 -0
  240. package/lib/plugins/ComponentPickerPlugin/index.d.ts +2 -0
  241. package/lib/plugins/ComponentPickerPlugin/index.js +276 -0
  242. package/lib/plugins/ContextMenuPlugin/index.d.ts +2 -0
  243. package/lib/plugins/ContextMenuPlugin/index.js +112 -0
  244. package/lib/plugins/CounterPlugin/index.d.ts +3 -0
  245. package/lib/plugins/CounterPlugin/index.js +24 -0
  246. package/lib/plugins/DateTimePlugin/index.d.ts +8 -0
  247. package/lib/plugins/DateTimePlugin/index.js +28 -0
  248. package/lib/plugins/DebugPlugin/index.d.ts +3 -0
  249. package/lib/plugins/DebugPlugin/index.js +275 -0
  250. package/lib/plugins/DocsPlugin/index.d.ts +2 -0
  251. package/lib/plugins/DocsPlugin/index.js +4 -0
  252. package/lib/plugins/DragDropPastePlugin/index.d.ts +1 -0
  253. package/lib/plugins/DragDropPastePlugin/index.js +37 -0
  254. package/lib/plugins/DraggableBlockPlugin/index.d.ts +12 -0
  255. package/lib/plugins/DraggableBlockPlugin/index.js +36 -0
  256. package/lib/plugins/EmojiPickerPlugin/index.d.ts +1 -0
  257. package/lib/plugins/EmojiPickerPlugin/index.js +84 -0
  258. package/lib/plugins/EmojisPlugin/index.d.ts +2 -0
  259. package/lib/plugins/EmojisPlugin/index.js +56 -0
  260. package/lib/plugins/EquationsPlugin/index.d.ts +14 -0
  261. package/lib/plugins/EquationsPlugin/index.js +34 -0
  262. package/lib/plugins/ExcalidrawPlugin/index.d.ts +5 -0
  263. package/lib/plugins/ExcalidrawPlugin/index.js +44 -0
  264. package/lib/plugins/FigmaPlugin/index.d.ts +4 -0
  265. package/lib/plugins/FigmaPlugin/index.js +24 -0
  266. package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +15 -0
  267. package/lib/plugins/FloatingLinkEditorPlugin/index.js +280 -0
  268. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +7 -0
  269. package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +219 -0
  270. package/lib/plugins/ImagesPlugin/index.d.ts +24 -0
  271. package/lib/plugins/ImagesPlugin/index.js +195 -0
  272. package/lib/plugins/InlineImagePlugin/index.d.ts +17 -0
  273. package/lib/plugins/InlineImagePlugin/index.js +180 -0
  274. package/lib/plugins/KeywordsPlugin/index.d.ts +2 -0
  275. package/lib/plugins/KeywordsPlugin/index.js +35 -0
  276. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +6 -0
  277. package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +21 -0
  278. package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +7 -0
  279. package/lib/plugins/LayoutPlugin/LayoutPlugin.js +135 -0
  280. package/lib/plugins/LinkPlugin/index.d.ts +6 -0
  281. package/lib/plugins/LinkPlugin/index.js +11 -0
  282. package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +2 -0
  283. package/lib/plugins/MarkdownShortcutPlugin/index.js +6 -0
  284. package/lib/plugins/MarkdownTransformers/index.d.ts +8 -0
  285. package/lib/plugins/MarkdownTransformers/index.js +238 -0
  286. package/lib/plugins/MaxLengthPlugin/index.d.ts +3 -0
  287. package/lib/plugins/MaxLengthPlugin/index.js +41 -0
  288. package/lib/plugins/MentionsPlugin/index.d.ts +2 -0
  289. package/lib/plugins/MentionsPlugin/index.js +564 -0
  290. package/lib/plugins/PageBreakPlugin/index.d.ts +4 -0
  291. package/lib/plugins/PageBreakPlugin/index.js +31 -0
  292. package/lib/plugins/PasteLogPlugin/index.d.ts +2 -0
  293. package/lib/plugins/PasteLogPlugin/index.js +27 -0
  294. package/lib/plugins/PollPlugin/index.d.ts +8 -0
  295. package/lib/plugins/PollPlugin/index.js +38 -0
  296. package/lib/plugins/ShortcutsPlugin/index.d.ts +6 -0
  297. package/lib/plugins/ShortcutsPlugin/index.js +116 -0
  298. package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +59 -0
  299. package/lib/plugins/ShortcutsPlugin/shortcuts.js +173 -0
  300. package/lib/plugins/SpecialTextPlugin/index.d.ts +2 -0
  301. package/lib/plugins/SpecialTextPlugin/index.js +50 -0
  302. package/lib/plugins/SpeechToTextPlugin/index.d.ts +5 -0
  303. package/lib/plugins/SpeechToTextPlugin/index.js +86 -0
  304. package/lib/plugins/StickyPlugin/index.d.ts +2 -0
  305. package/lib/plugins/StickyPlugin/index.js +16 -0
  306. package/lib/plugins/TabFocusPlugin/index.d.ts +1 -0
  307. package/lib/plugins/TabFocusPlugin/index.js +38 -0
  308. package/lib/plugins/TableActionMenuPlugin/index.d.ts +5 -0
  309. package/lib/plugins/TableActionMenuPlugin/index.js +492 -0
  310. package/lib/plugins/TableCellResizer/index.d.ts +3 -0
  311. package/lib/plugins/TableCellResizer/index.js +297 -0
  312. package/lib/plugins/TableHoverActionsPlugin/index.d.ts +4 -0
  313. package/lib/plugins/TableHoverActionsPlugin/index.js +188 -0
  314. package/lib/plugins/TableOfContentsPlugin/index.d.ts +2 -0
  315. package/lib/plugins/TableOfContentsPlugin/index.js +116 -0
  316. package/lib/plugins/TablePlugin.d.ts +31 -0
  317. package/lib/plugins/TablePlugin.js +63 -0
  318. package/lib/plugins/TestRecorderPlugin/index.d.ts +3 -0
  319. package/lib/plugins/TestRecorderPlugin/index.js +346 -0
  320. package/lib/plugins/ToolbarPlugin/fontSize.d.ts +9 -0
  321. package/lib/plugins/ToolbarPlugin/fontSize.js +84 -0
  322. package/lib/plugins/ToolbarPlugin/index.d.ts +9 -0
  323. package/lib/plugins/ToolbarPlugin/index.js +500 -0
  324. package/lib/plugins/ToolbarPlugin/utils.d.ts +26 -0
  325. package/lib/plugins/ToolbarPlugin/utils.js +247 -0
  326. package/lib/plugins/TreeViewPlugin/index.d.ts +2 -0
  327. package/lib/plugins/TreeViewPlugin/index.js +7 -0
  328. package/lib/plugins/TwitterPlugin/index.d.ts +4 -0
  329. package/lib/plugins/TwitterPlugin/index.js +24 -0
  330. package/lib/plugins/TypingPerfPlugin/index.d.ts +2 -0
  331. package/lib/plugins/TypingPerfPlugin/index.js +97 -0
  332. package/lib/plugins/YouTubePlugin/index.d.ts +4 -0
  333. package/lib/plugins/YouTubePlugin/index.js +24 -0
  334. package/lib/server/validation.d.ts +1 -0
  335. package/lib/server/validation.js +115 -0
  336. package/lib/setupEnv.d.ts +2 -0
  337. package/lib/setupEnv.js +29 -0
  338. package/lib/themes/CommentEditorTheme.d.ts +4 -0
  339. package/lib/themes/CommentEditorTheme.js +11 -0
  340. package/lib/themes/PlaygroundEditorTheme.d.ts +4 -0
  341. package/lib/themes/PlaygroundEditorTheme.js +124 -0
  342. package/lib/themes/StickyEditorTheme.d.ts +4 -0
  343. package/lib/themes/StickyEditorTheme.js +11 -0
  344. package/lib/tyes.dt.d.ts +12 -0
  345. package/lib/tyes.dt.js +4 -0
  346. package/lib/ui/Button.d.ts +12 -0
  347. package/lib/ui/Button.js +6 -0
  348. package/lib/ui/ColorPicker.d.ts +14 -0
  349. package/lib/ui/ColorPicker.js +219 -0
  350. package/lib/ui/ContentEditable.d.ts +9 -0
  351. package/lib/ui/ContentEditable.js +6 -0
  352. package/lib/ui/Dialog.d.ts +10 -0
  353. package/lib/ui/Dialog.js +8 -0
  354. package/lib/ui/DropDown.d.ts +18 -0
  355. package/lib/ui/DropDown.js +133 -0
  356. package/lib/ui/DropdownColorPicker.d.ts +13 -0
  357. package/lib/ui/DropdownColorPicker.js +6 -0
  358. package/lib/ui/EquationEditor.d.ts +8 -0
  359. package/lib/ui/EquationEditor.js +11 -0
  360. package/lib/ui/ExcalidrawModal.d.ts +42 -0
  361. package/lib/ui/ExcalidrawModal.js +103 -0
  362. package/lib/ui/FileInput.d.ts +10 -0
  363. package/lib/ui/FileInput.js +5 -0
  364. package/lib/ui/FlashMessage.d.ts +7 -0
  365. package/lib/ui/FlashMessage.js +6 -0
  366. package/lib/ui/ImageResizer.d.ts +17 -0
  367. package/lib/ui/ImageResizer.js +171 -0
  368. package/lib/ui/KatexEquationAlterer.d.ts +8 -0
  369. package/lib/ui/KatexEquationAlterer.js +23 -0
  370. package/lib/ui/KatexRenderer.d.ts +6 -0
  371. package/lib/ui/KatexRenderer.js +24 -0
  372. package/lib/ui/Modal.d.ts +9 -0
  373. package/lib/ui/Modal.js +48 -0
  374. package/lib/ui/Select.d.ts +8 -0
  375. package/lib/ui/Select.js +5 -0
  376. package/lib/ui/Switch.d.ts +8 -0
  377. package/lib/ui/Switch.js +6 -0
  378. package/lib/ui/TextInput.d.ts +13 -0
  379. package/lib/ui/TextInput.js +7 -0
  380. package/lib/utils/docSerialization.d.ts +3 -0
  381. package/lib/utils/docSerialization.js +60 -0
  382. package/lib/utils/emoji-list.d.ts +20 -0
  383. package/lib/utils/emoji-list.js +16609 -0
  384. package/lib/utils/getDOMRangeRect.d.ts +8 -0
  385. package/lib/utils/getDOMRangeRect.js +26 -0
  386. package/lib/utils/getSelectedNode.d.ts +2 -0
  387. package/lib/utils/getSelectedNode.js +28 -0
  388. package/lib/utils/getThemeSelector.d.ts +2 -0
  389. package/lib/utils/getThemeSelector.js +14 -0
  390. package/lib/utils/isMobileWidth.d.ts +7 -0
  391. package/lib/utils/isMobileWidth.js +11 -0
  392. package/lib/utils/joinClasses.d.ts +1 -0
  393. package/lib/utils/joinClasses.js +7 -0
  394. package/lib/utils/setFloatingElemPosition.d.ts +1 -0
  395. package/lib/utils/setFloatingElemPosition.js +59 -0
  396. package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +1 -0
  397. package/lib/utils/setFloatingElemPositionForLinkEditor.js +36 -0
  398. package/lib/utils/swipe.d.ts +4 -0
  399. package/lib/utils/swipe.js +94 -0
  400. package/lib/utils/url.d.ts +2 -0
  401. package/lib/utils/url.js +31 -0
  402. package/package.json +4 -4
@@ -0,0 +1,64 @@
1
+ import { LoroDoc } from 'loro-crdt';
2
+ /**
3
+ * Initial Lexical JSON structure that matches what the Python server uses
4
+ */
5
+ export declare const INITIAL_LEXICAL_JSON: {
6
+ root: {
7
+ children: ({
8
+ children: {
9
+ detail: number;
10
+ format: number;
11
+ mode: string;
12
+ style: string;
13
+ text: string;
14
+ type: string;
15
+ version: number;
16
+ }[];
17
+ direction: any;
18
+ format: string;
19
+ indent: number;
20
+ type: string;
21
+ version: number;
22
+ tag: string;
23
+ textFormat?: undefined;
24
+ textStyle?: undefined;
25
+ } | {
26
+ children: {
27
+ detail: number;
28
+ format: number;
29
+ mode: string;
30
+ style: string;
31
+ text: string;
32
+ type: string;
33
+ version: number;
34
+ }[];
35
+ direction: any;
36
+ format: string;
37
+ indent: number;
38
+ type: string;
39
+ version: number;
40
+ textFormat: number;
41
+ textStyle: string;
42
+ tag?: undefined;
43
+ })[];
44
+ direction: any;
45
+ format: string;
46
+ indent: number;
47
+ type: string;
48
+ version: number;
49
+ };
50
+ };
51
+ /**
52
+ * Initialize a new Loro document with the initial Lexical content
53
+ * This ensures consistent starting state across all clients
54
+ */
55
+ export declare function initializeLoroDocWithLexicalContent(doc: LoroDoc): void;
56
+ /**
57
+ * Check if a Loro document is empty (has no tree content)
58
+ */
59
+ export declare function isLoroDocumentEmpty(doc: LoroDoc): boolean;
60
+ /**
61
+ * Check if a Loro document should be initialized (more robust check)
62
+ * This helps prevent race conditions where multiple clients try to initialize
63
+ */
64
+ export declare function shouldInitializeLoroDoc(doc: LoroDoc): boolean;
@@ -0,0 +1,113 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { lexicalToLoroTree } from './LexicalToLoro';
6
+ /**
7
+ * Initial Lexical JSON structure that matches what the Python server uses
8
+ */
9
+ export const INITIAL_LEXICAL_JSON = {
10
+ "root": {
11
+ "children": [
12
+ {
13
+ "children": [
14
+ {
15
+ "detail": 0,
16
+ "format": 0,
17
+ "mode": "normal",
18
+ "style": "",
19
+ "text": "Lexical with Loro",
20
+ "type": "text",
21
+ "version": 1
22
+ }
23
+ ],
24
+ "direction": null,
25
+ "format": "",
26
+ "indent": 0,
27
+ "type": "heading",
28
+ "version": 1,
29
+ "tag": "h1"
30
+ },
31
+ {
32
+ "children": [
33
+ {
34
+ "detail": 0,
35
+ "format": 0,
36
+ "mode": "normal",
37
+ "style": "",
38
+ "text": "Type something...",
39
+ "type": "text",
40
+ "version": 1
41
+ }
42
+ ],
43
+ "direction": null,
44
+ "format": "",
45
+ "indent": 0,
46
+ "type": "paragraph",
47
+ "version": 1,
48
+ "textFormat": 0,
49
+ "textStyle": ""
50
+ }
51
+ ],
52
+ "direction": null,
53
+ "format": "",
54
+ "indent": 0,
55
+ "type": "root",
56
+ "version": 1
57
+ }
58
+ };
59
+ /**
60
+ * Initialize a new Loro document with the initial Lexical content
61
+ * This ensures consistent starting state across all clients
62
+ */
63
+ export function initializeLoroDocWithLexicalContent(doc) {
64
+ const tree = doc.getTree('tree');
65
+ tree.enableFractionalIndex(0.001);
66
+ // Convert the initial Lexical JSON to Loro tree structure
67
+ lexicalToLoroTree(INITIAL_LEXICAL_JSON, tree);
68
+ }
69
+ /**
70
+ * Check if a Loro document is empty (has no tree content)
71
+ */
72
+ export function isLoroDocumentEmpty(doc) {
73
+ const tree = doc.getTree('tree');
74
+ try {
75
+ // Get all root nodes
76
+ const roots = tree.roots();
77
+ // Also check if the document has any nodes at all
78
+ const allNodes = tree.nodes();
79
+ return roots.length === 0 && allNodes.length === 0;
80
+ }
81
+ catch (error) {
82
+ // If there's an error accessing roots, consider it empty
83
+ return true;
84
+ }
85
+ }
86
+ /**
87
+ * Check if a Loro document should be initialized (more robust check)
88
+ * This helps prevent race conditions where multiple clients try to initialize
89
+ */
90
+ export function shouldInitializeLoroDoc(doc) {
91
+ const tree = doc.getTree('tree');
92
+ try {
93
+ const allNodes = tree.nodes();
94
+ const roots = tree.roots();
95
+ // Only initialize if there are truly no nodes
96
+ const isEmpty = allNodes.length === 0;
97
+ // Additional check: look for any existing root nodes with our content
98
+ if (!isEmpty) {
99
+ // Check if any root has the expected initial structure
100
+ for (const root of roots) {
101
+ const data = Object.fromEntries(root.data.entries());
102
+ if (data.elementType === 'root') {
103
+ return false;
104
+ }
105
+ }
106
+ }
107
+ return isEmpty;
108
+ }
109
+ catch (error) {
110
+ console.warn('Error checking if doc should be initialized:', error);
111
+ return false; // Don't initialize if there's an error
112
+ }
113
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Assert a collaboration invariant.
3
+ *
4
+ * The Loro <-> Lexical sync engine relies on a set of structural invariants
5
+ * (a node's parent is already mapped, an insertion index is within range, a
6
+ * text node always has a parent, ...). When one of these does not hold the
7
+ * engine is in a state it cannot resolve correctly.
8
+ *
9
+ * Historically such cases were "handled" by logging a warning and skipping the
10
+ * operation (or clamping an index). That silently corrupts the shared document
11
+ * and hides the underlying bug. Instead we throw: the failure surfaces
12
+ * immediately, the surrounding `editor.update()` rolls back cleanly, and the
13
+ * root cause can be found and fixed rather than masked.
14
+ */
15
+ export declare function invariant(condition: unknown, message: string, context?: Record<string, unknown>): asserts condition;
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ /**
6
+ * Assert a collaboration invariant.
7
+ *
8
+ * The Loro <-> Lexical sync engine relies on a set of structural invariants
9
+ * (a node's parent is already mapped, an insertion index is within range, a
10
+ * text node always has a parent, ...). When one of these does not hold the
11
+ * engine is in a state it cannot resolve correctly.
12
+ *
13
+ * Historically such cases were "handled" by logging a warning and skipping the
14
+ * operation (or clamping an index). That silently corrupts the shared document
15
+ * and hides the underlying bug. Instead we throw: the failure surfaces
16
+ * immediately, the surrounding `editor.update()` rolls back cleanly, and the
17
+ * root cause can be found and fixed rather than masked.
18
+ */
19
+ export function invariant(condition, message, context) {
20
+ if (!condition) {
21
+ const details = context ? ` ${JSON.stringify(context)}` : '';
22
+ throw new Error(`[loro-collab] Invariant failed: ${message}${details}`);
23
+ }
24
+ }
@@ -0,0 +1,18 @@
1
+ import { LoroTree, TreeID } from 'loro-crdt';
2
+ /**
3
+ * Utility to convert Lexical JSON structure to Loro tree
4
+ */
5
+ interface LexicalNodeJSON {
6
+ type: string;
7
+ children?: LexicalNodeJSON[];
8
+ [key: string]: any;
9
+ }
10
+ interface LexicalJSON {
11
+ root: LexicalNodeJSON;
12
+ }
13
+ /**
14
+ * Convert a Lexical JSON structure to a Loro tree
15
+ * This is used to initialize a Loro tree from existing Lexical content
16
+ */
17
+ export declare function lexicalToLoroTree(lexicalJson: string | LexicalJSON, tree: LoroTree): TreeID;
18
+ export {};
@@ -0,0 +1,100 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ /**
6
+ * Convert a Lexical JSON structure to a Loro tree
7
+ * This is used to initialize a Loro tree from existing Lexical content
8
+ */
9
+ export function lexicalToLoroTree(lexicalJson, tree) {
10
+ let parsedJson;
11
+ if (typeof lexicalJson === 'string') {
12
+ try {
13
+ parsedJson = JSON.parse(lexicalJson);
14
+ }
15
+ catch (error) {
16
+ throw new Error(`Failed to parse Lexical JSON: ${error}`);
17
+ }
18
+ }
19
+ else {
20
+ parsedJson = lexicalJson;
21
+ }
22
+ // Start with the root node - create it without a parent
23
+ const rootTreeNode = tree.createNode();
24
+ const rootTreeID = rootTreeNode.id;
25
+ processLexicalNode(parsedJson.root, tree, rootTreeNode);
26
+ return rootTreeID;
27
+ }
28
+ /**
29
+ * Recursively process a Lexical node and add it to the Loro tree
30
+ */
31
+ function processLexicalNode(lexicalNode, tree, treeNode) {
32
+ // Store the lexical data in the tree node
33
+ const nodeData = treeNode.data;
34
+ if (nodeData) {
35
+ // Store element type for quick access
36
+ nodeData.set('elementType', lexicalNode.type);
37
+ // Store lexical node data directly as JSON object
38
+ const lexicalNodeData = createLexicalNodeFromJSON(lexicalNode);
39
+ const lexicalNodeJSON = lexicalNodeData.lexicalNode.exportJSON();
40
+ // Remove all key-related fields to avoid duplication (TreeID serves as the key)
41
+ if ('__key' in lexicalNodeJSON || 'key' in lexicalNodeJSON || 'lexicalKey' in lexicalNodeJSON) {
42
+ const { __key, key, lexicalKey, ...cleanedData } = lexicalNodeJSON;
43
+ nodeData.set('lexical', cleanedData);
44
+ }
45
+ else {
46
+ nodeData.set('lexical', lexicalNodeJSON);
47
+ }
48
+ }
49
+ // Process children if they exist
50
+ if (lexicalNode.children && Array.isArray(lexicalNode.children)) {
51
+ lexicalNode.children.forEach((child, childIndex) => {
52
+ // Create child node under current node
53
+ const childTreeNode = tree.createNode(treeNode.id, childIndex);
54
+ processLexicalNode(child, tree, childTreeNode);
55
+ });
56
+ }
57
+ }
58
+ /**
59
+ * Create a minimal Lexical node representation from JSON data
60
+ * This doesn't create actual Lexical nodes, just the data structure needed for serialization
61
+ */
62
+ function createLexicalNodeFromJSON(nodeJson) {
63
+ // Create a minimal node-like object with the essential properties
64
+ const nodeData = {
65
+ __key: generateNodeKey(), // Generate a temporary key
66
+ __type: nodeJson.type,
67
+ __parent: null, // Will be set during tree construction
68
+ __text: nodeJson.text || undefined,
69
+ __format: nodeJson.format || 0,
70
+ __style: nodeJson.style || '',
71
+ __mode: nodeJson.mode || undefined,
72
+ __detail: nodeJson.detail || undefined,
73
+ __indent: nodeJson.indent || 0,
74
+ __direction: nodeJson.direction || null,
75
+ __tag: nodeJson.tag || undefined,
76
+ __textFormat: nodeJson.textFormat || undefined,
77
+ __textStyle: nodeJson.textStyle || undefined,
78
+ __version: nodeJson.version || 1
79
+ };
80
+ // Remove undefined properties
81
+ Object.keys(nodeData).forEach(key => {
82
+ if (nodeData[key] === undefined) {
83
+ delete nodeData[key];
84
+ }
85
+ });
86
+ // Return in the format expected by LexicalNodeDataHelper
87
+ return {
88
+ lexicalNode: {
89
+ getType: () => nodeJson.type,
90
+ exportJSON: () => nodeData,
91
+ getKey: () => nodeData.__key
92
+ }
93
+ };
94
+ }
95
+ /**
96
+ * Generate a simple node key for temporary use
97
+ */
98
+ function generateNodeKey() {
99
+ return Math.random().toString(36).substr(2, 9);
100
+ }
@@ -0,0 +1,44 @@
1
+ import { LoroDoc, TreeID } from 'loro-crdt';
2
+ import { EditorState, LexicalNode, NodeKey, RangeSelection, TextNode } from 'lexical';
3
+ export declare const DEFAULT_TREE_NAME = "lexical-tree";
4
+ /**
5
+ * Generates a consistent client ID from a Loro document.
6
+ * Uses the numeric peer ID directly to ensure consistency across all components.
7
+ *
8
+ * @param doc - The Loro document
9
+ * @returns A number representing the client ID
10
+ */
11
+ export declare function generateClientID(doc: LoroDoc): number;
12
+ /**
13
+ * Generates a client ID for cases where no document is available.
14
+ * Creates a random ID within the safe integer range.
15
+ *
16
+ * @returns A randomly generated client ID
17
+ */
18
+ export declare function generateRandomClientID(): number;
19
+ /**
20
+ * Ensure doc has a LoroTree instance
21
+ */
22
+ export declare function getLoroTree(doc: LoroDoc, treeName?: string): import("loro-crdt").LoroTree<Record<string, unknown>>;
23
+ /**
24
+ * Helper function to parse TreeID back to nodeKey and peerId
25
+ */
26
+ export declare function parseTreeID(treeId: TreeID): {
27
+ nodeKey: NodeKey;
28
+ peerId: number;
29
+ };
30
+ /**
31
+ * Helper function to get Lexical node information for Loro sync
32
+ */
33
+ export declare function getLexicalNodeInfo(node: LexicalNode): {
34
+ parentKey?: string;
35
+ index?: number;
36
+ };
37
+ /**
38
+ * Check if a class extends another class (proper inheritance checking)
39
+ */
40
+ export declare function isClassExtending(Klass: any, BaseClass: any): boolean;
41
+ export declare function toKeyNodeNumber(nodeKey: NodeKey): number;
42
+ export declare function $diffTextContentAndApplyDelta(textNode: TextNode, key: NodeKey, prevText: string, nextText: string): void;
43
+ export declare function doesSelectionNeedRecovering(selection: RangeSelection): boolean;
44
+ export declare function $moveSelectionToPreviousNode(anchorNodeKey: string, currentEditorState: EditorState): void;
@@ -0,0 +1,157 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { $getNodeByKey, $getRoot, $getSelection, $isRangeSelection, $isTextNode } from 'lexical';
6
+ import simpleDiffWithCursor from '../../utils/simpleDiffWithCursor';
7
+ export const DEFAULT_TREE_NAME = 'lexical-tree';
8
+ /**
9
+ * Generates a consistent client ID from a Loro document.
10
+ * Uses the numeric peer ID directly to ensure consistency across all components.
11
+ *
12
+ * @param doc - The Loro document
13
+ * @returns A number representing the client ID
14
+ */
15
+ export function generateClientID(doc) {
16
+ return Number(doc.peerId);
17
+ }
18
+ /**
19
+ * Generates a client ID for cases where no document is available.
20
+ * Creates a random ID within the safe integer range.
21
+ *
22
+ * @returns A randomly generated client ID
23
+ */
24
+ export function generateRandomClientID() {
25
+ return Math.floor(Math.random() * 2147483647);
26
+ }
27
+ /**
28
+ * Ensure doc has a LoroTree instance
29
+ */
30
+ export function getLoroTree(doc, treeName = DEFAULT_TREE_NAME) {
31
+ const tree = doc.getTree(treeName);
32
+ // Enable fractional index for ordered siblings (useful for maintaining order)
33
+ // tree.enableFractionalIndex(0.001);
34
+ return tree;
35
+ }
36
+ /**
37
+ * Helper function to parse TreeID back to nodeKey and peerId
38
+ */
39
+ export function parseTreeID(treeId) {
40
+ const [nodeKey, peerId] = treeId.split('@');
41
+ return {
42
+ nodeKey: nodeKey,
43
+ peerId: Number(peerId)
44
+ };
45
+ }
46
+ /**
47
+ * Helper function to get Lexical node information for Loro sync
48
+ */
49
+ export function getLexicalNodeInfo(node) {
50
+ // TODO: Implement logic to get parent and index from Lexical node
51
+ // This is a placeholder that should be replaced with actual Lexical API calls
52
+ return {
53
+ parentKey: node.getParent()?.getKey(),
54
+ index: node.getIndexWithinParent()
55
+ };
56
+ }
57
+ /**
58
+ * Check if a class extends another class (proper inheritance checking)
59
+ */
60
+ export function isClassExtending(Klass, BaseClass) {
61
+ // Direct class equality
62
+ if (Klass === BaseClass) {
63
+ return true;
64
+ }
65
+ // Check by name (for cases where classes might be different instances)
66
+ if (Klass.name === BaseClass.name) {
67
+ return true;
68
+ }
69
+ // Check prototype chain for inheritance
70
+ if (Klass.prototype && Object.prototype.isPrototypeOf.call(BaseClass, Klass)) {
71
+ return true;
72
+ }
73
+ return false;
74
+ }
75
+ export function toKeyNodeNumber(nodeKey) {
76
+ // Special case for root node
77
+ if (nodeKey === "root") {
78
+ return 0;
79
+ }
80
+ // Attempt to convert NodeKey (string) to a number
81
+ const keyAsNumber = Number(nodeKey);
82
+ if (!isNaN(keyAsNumber)) {
83
+ return keyAsNumber;
84
+ }
85
+ // If conversion fails, throw an error
86
+ throw new Error(`NodeKey "${nodeKey}" cannot be converted to a number. Expected numeric string or "root".`);
87
+ }
88
+ export function $diffTextContentAndApplyDelta(textNode, key, prevText, nextText) {
89
+ const selection = $getSelection();
90
+ let cursorOffset = nextText.length;
91
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
92
+ const anchor = selection.anchor;
93
+ if (anchor.key === key) {
94
+ // Ensure cursor offset doesn't exceed the new text length
95
+ // This prevents errors when text is split or content changes significantly
96
+ cursorOffset = Math.min(anchor.offset, nextText.length);
97
+ }
98
+ }
99
+ const diff = simpleDiffWithCursor(prevText, nextText, cursorOffset);
100
+ const beforeSplice = textNode.getTextContent();
101
+ textNode.spliceText(diff.index, diff.remove, diff.insert);
102
+ const afterSplice = textNode.getTextContent();
103
+ }
104
+ export function doesSelectionNeedRecovering(selection) {
105
+ const anchor = selection.anchor;
106
+ const focus = selection.focus;
107
+ let recoveryNeeded = false;
108
+ try {
109
+ const anchorNode = anchor.getNode();
110
+ const focusNode = focus.getNode();
111
+ if (
112
+ // We might have removed a node that no longer exists
113
+ !anchorNode.isAttached() ||
114
+ !focusNode.isAttached() ||
115
+ // If we've split a node, then the offset might not be right
116
+ ($isTextNode(anchorNode) &&
117
+ anchor.offset > anchorNode.getTextContentSize()) ||
118
+ ($isTextNode(focusNode) && focus.offset > focusNode.getTextContentSize())) {
119
+ recoveryNeeded = true;
120
+ }
121
+ }
122
+ catch (e) {
123
+ // Sometimes checking nor a node via getNode might trigger
124
+ // an error, so we need recovery then too.
125
+ recoveryNeeded = true;
126
+ }
127
+ return recoveryNeeded;
128
+ }
129
+ export function $moveSelectionToPreviousNode(anchorNodeKey, currentEditorState) {
130
+ const anchorNode = currentEditorState._nodeMap.get(anchorNodeKey);
131
+ if (!anchorNode) {
132
+ $getRoot().selectStart();
133
+ return;
134
+ }
135
+ // Get previous node
136
+ const prevNodeKey = anchorNode.__prev;
137
+ let prevNode = null;
138
+ if (prevNodeKey) {
139
+ prevNode = $getNodeByKey(prevNodeKey);
140
+ }
141
+ // If previous node not found, get parent node
142
+ if (prevNode === null && anchorNode.__parent !== null) {
143
+ prevNode = $getNodeByKey(anchorNode.__parent);
144
+ }
145
+ if (prevNode === null) {
146
+ $getRoot().selectStart();
147
+ return;
148
+ }
149
+ if (prevNode !== null && prevNode.isAttached()) {
150
+ prevNode.selectEnd();
151
+ return;
152
+ }
153
+ else {
154
+ // If the found node is also deleted, select the next one
155
+ $moveSelectionToPreviousNode(prevNode.__key, currentEditorState);
156
+ }
157
+ }
@@ -0,0 +1,8 @@
1
+ import { LoroDoc } from 'loro-crdt';
2
+ import { Provider } from './State';
3
+ /**
4
+ * Create a WebSocket provider for Loro collaboration with periodic ephemeral state synchronization.
5
+ * The resyncInterval enables client-side periodic querying to complement server-side cleanup,
6
+ * preventing stale user states from accumulating after browser refreshes.
7
+ */
8
+ export declare function createWebsocketProvider(id: string, docMap: Map<string, LoroDoc>, websocketUrl?: string): Provider;
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ import { LoroDoc } from 'loro-crdt';
6
+ import { WebsocketProvider } from './provider/websocket';
7
+ const url = new URL(window.location.href);
8
+ const params = new URLSearchParams(url.search);
9
+ const RESYNC_INTERVAL = parseInt(params.get('resyncInterval') || '30000', 10); // Default 30s, configurable via URL
10
+ /**
11
+ * Create a WebSocket provider for Loro collaboration with periodic ephemeral state synchronization.
12
+ * The resyncInterval enables client-side periodic querying to complement server-side cleanup,
13
+ * preventing stale user states from accumulating after browser refreshes.
14
+ */
15
+ export function createWebsocketProvider(id, docMap, websocketUrl) {
16
+ let doc = docMap.get(id);
17
+ if (doc === undefined) {
18
+ doc = new LoroDoc();
19
+ docMap.set(id, doc);
20
+ }
21
+ const providerInstanceId = Math.random().toString(36).substr(2, 9);
22
+ console.log(` Creating WebsocketProvider instance (ID: ${providerInstanceId}) for docId: ${id}`);
23
+ // Use provided websocketUrl or fallback to URL parameters/defaults
24
+ const rawWebsocketUrl = websocketUrl || (() => {
25
+ const url = new URL(window.location.href);
26
+ const params = new URLSearchParams(url.search);
27
+ return params.get('collabEndpoint') || 'ws://localhost:3002';
28
+ })();
29
+ // The WebsocketProvider builds the connection URL as
30
+ // `serverUrl + '/' + docId + '?' + params`. If the caller embedded a query
31
+ // string (for example `?token=<jwt>`) directly in the URL, the docId would be
32
+ // appended *after* the query string, corrupting the URL. Split any query
33
+ // string off the base URL and forward it through the provider `params` so the
34
+ // final URL is `serverUrl/docId?token=<jwt>` as the server expects.
35
+ let finalWebsocketUrl = rawWebsocketUrl;
36
+ const params = {};
37
+ const queryIndex = finalWebsocketUrl.indexOf('?');
38
+ if (queryIndex !== -1) {
39
+ const query = finalWebsocketUrl.slice(queryIndex + 1);
40
+ finalWebsocketUrl = finalWebsocketUrl.slice(0, queryIndex);
41
+ new URLSearchParams(query).forEach((value, key) => {
42
+ params[key] = value;
43
+ });
44
+ }
45
+ const websocketProvider = new WebsocketProvider(finalWebsocketUrl, id, doc, {
46
+ connect: false,
47
+ params,
48
+ resyncInterval: RESYNC_INTERVAL, // Poll ephemeral state periodically to prevent stale user accumulation
49
+ });
50
+ console.log(` WebsocketProvider created for: ${finalWebsocketUrl}/${id} with resyncInterval: ${RESYNC_INTERVAL}ms`);
51
+ return websocketProvider;
52
+ }
@@ -0,0 +1 @@
1
+ export default function invariant(cond?: boolean, message?: string, ...args: string[]): asserts cond;
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ // invariant(condition, message) will refine types based on "condition", and
6
+ // if "condition" is false will throw an error. This function is special-cased
7
+ // in flow itself, so we can't name it anything else.
8
+ export default function invariant(cond, message, ...args) {
9
+ if (cond) {
10
+ return;
11
+ }
12
+ throw new Error('Internal Lexical error: invariant() is meant to be replaced at compile ' +
13
+ 'time. There is no runtime version. Error: ' +
14
+ message);
15
+ }
@@ -0,0 +1,5 @@
1
+ export default function simpleDiffWithCursor(a: string, b: string, cursor: number): {
2
+ index: number;
3
+ insert: string;
4
+ remove: number;
5
+ };
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the MIT License.
4
+ */
5
+ export default function simpleDiffWithCursor(a, b, cursor) {
6
+ const aLength = a.length;
7
+ const bLength = b.length;
8
+ let left = 0; // number of same characters counting from left
9
+ let right = 0; // number of same characters counting from right
10
+ // Iterate left to the right until we find a changed character
11
+ // First iteration considers the current cursor position
12
+ while (left < aLength &&
13
+ left < bLength &&
14
+ a[left] === b[left] &&
15
+ left < cursor) {
16
+ left++;
17
+ }
18
+ // Iterate right to the left until we find a changed character
19
+ while (right + left < aLength &&
20
+ right + left < bLength &&
21
+ a[aLength - right - 1] === b[bLength - right - 1]) {
22
+ right++;
23
+ }
24
+ // Try to iterate left further to the right without caring about the current cursor position
25
+ while (right + left < aLength &&
26
+ right + left < bLength &&
27
+ a[left] === b[left]) {
28
+ left++;
29
+ }
30
+ return {
31
+ index: left,
32
+ insert: b.slice(left, bLength - right),
33
+ remove: aLength - left - right,
34
+ };
35
+ }