@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.
- package/README.md +24 -137
- package/lib/App.d.ts +2 -0
- package/lib/App.js +141 -0
- package/lib/Editor.d.ts +2 -0
- package/lib/Editor.js +111 -0
- package/lib/Settings.d.ts +2 -0
- package/lib/Settings.js +57 -0
- package/lib/appSettings.d.ts +36 -0
- package/lib/appSettings.js +44 -0
- package/lib/collab/loro/Bindings.d.ts +41 -0
- package/lib/collab/loro/Bindings.js +95 -0
- package/lib/collab/loro/Debug.d.ts +33 -0
- package/lib/collab/loro/Debug.js +448 -0
- package/lib/collab/loro/LexicalCollaborationContext.d.ts +19 -0
- package/lib/collab/loro/LexicalCollaborationContext.js +48 -0
- package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +24 -0
- package/lib/collab/loro/LexicalCollaborationPlugin.js +83 -0
- package/lib/collab/loro/State.d.ts +53 -0
- package/lib/collab/loro/State.js +90 -0
- package/lib/collab/loro/components/LoroCollaborationUI.d.ts +13 -0
- package/lib/collab/loro/components/LoroCollaborationUI.js +9 -0
- package/lib/collab/loro/components/LoroCollaborators.d.ts +8 -0
- package/lib/collab/loro/components/LoroCollaborators.js +97 -0
- package/lib/collab/loro/components/index.d.ts +2 -0
- package/lib/collab/loro/components/index.js +2 -0
- package/lib/collab/loro/index.d.ts +6 -0
- package/lib/collab/loro/index.js +6 -0
- package/lib/collab/loro/integrators/BaseIntegrator.d.ts +14 -0
- package/lib/collab/loro/integrators/BaseIntegrator.js +1 -0
- package/lib/collab/loro/integrators/CounterIntegrator.d.ts +23 -0
- package/lib/collab/loro/integrators/CounterIntegrator.js +40 -0
- package/lib/collab/loro/integrators/ListIntegrator.d.ts +23 -0
- package/lib/collab/loro/integrators/ListIntegrator.js +49 -0
- package/lib/collab/loro/integrators/MapIntegrator.d.ts +24 -0
- package/lib/collab/loro/integrators/MapIntegrator.js +177 -0
- package/lib/collab/loro/integrators/TextIntegrator.d.ts +25 -0
- package/lib/collab/loro/integrators/TextIntegrator.js +51 -0
- package/lib/collab/loro/integrators/TreeIntegrator.d.ts +25 -0
- package/lib/collab/loro/integrators/TreeIntegrator.js +201 -0
- package/lib/collab/loro/nodes/NodeFactory.d.ts +8 -0
- package/lib/collab/loro/nodes/NodeFactory.js +105 -0
- package/lib/collab/loro/nodes/NodesMapper.d.ts +111 -0
- package/lib/collab/loro/nodes/NodesMapper.js +258 -0
- package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +60 -0
- package/lib/collab/loro/propagators/DecoratorNodePropagator.js +302 -0
- package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +62 -0
- package/lib/collab/loro/propagators/ElementNodePropagator.js +335 -0
- package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +57 -0
- package/lib/collab/loro/propagators/LineBreakNodePropagator.js +196 -0
- package/lib/collab/loro/propagators/RootNodePropagator.d.ts +55 -0
- package/lib/collab/loro/propagators/RootNodePropagator.js +168 -0
- package/lib/collab/loro/propagators/TextNodePropagator.d.ts +60 -0
- package/lib/collab/loro/propagators/TextNodePropagator.js +434 -0
- package/lib/collab/loro/propagators/index.d.ts +49 -0
- package/lib/collab/loro/propagators/index.js +32 -0
- package/lib/collab/loro/provider/websocket.d.ts +116 -0
- package/lib/collab/loro/provider/websocket.js +907 -0
- package/lib/collab/loro/servers/index.d.ts +0 -0
- package/lib/collab/loro/servers/index.js +0 -0
- package/lib/collab/loro/servers/ws/callback.d.ts +5 -0
- package/lib/collab/loro/servers/ws/callback.js +85 -0
- package/lib/collab/loro/servers/ws/server.d.ts +2 -0
- package/lib/collab/loro/servers/ws/server.js +25 -0
- package/lib/collab/loro/servers/ws/utils.d.ts +40 -0
- package/lib/collab/loro/servers/ws/utils.js +513 -0
- package/lib/collab/loro/sync/SyncCursors.d.ts +32 -0
- package/lib/collab/loro/sync/SyncCursors.js +435 -0
- package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +4 -0
- package/lib/collab/loro/sync/SyncLexicalToLoro.js +80 -0
- package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +5 -0
- package/lib/collab/loro/sync/SyncLoroToLexical.js +96 -0
- package/lib/collab/loro/types/LexicalNodeData.d.ts +32 -0
- package/lib/collab/loro/types/LexicalNodeData.js +71 -0
- package/lib/collab/loro/useCollaboration.d.ts +12 -0
- package/lib/collab/loro/useCollaboration.js +248 -0
- package/lib/collab/loro/utils/InitialContent.d.ts +64 -0
- package/lib/collab/loro/utils/InitialContent.js +109 -0
- package/lib/collab/loro/utils/LexicalToLoro.d.ts +18 -0
- package/lib/collab/loro/utils/LexicalToLoro.js +96 -0
- package/lib/collab/loro/utils/Utils.d.ts +44 -0
- package/lib/collab/loro/utils/Utils.js +153 -0
- package/lib/collab/loro/wsProvider.d.ts +8 -0
- package/lib/collab/loro/wsProvider.js +31 -0
- package/lib/collab/utils/invariant.d.ts +1 -0
- package/lib/collab/utils/invariant.js +11 -0
- package/lib/collab/utils/simpleDiffWithCursor.d.ts +5 -0
- package/lib/collab/utils/simpleDiffWithCursor.js +31 -0
- package/lib/collab/yjs/Bindings.d.ts +23 -0
- package/lib/collab/yjs/Bindings.js +26 -0
- package/lib/collab/yjs/Debug.d.ts +23 -0
- package/lib/collab/yjs/Debug.js +213 -0
- package/lib/collab/yjs/LexicalCollaborationContext.d.ts +10 -0
- package/lib/collab/yjs/LexicalCollaborationContext.js +37 -0
- package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +21 -0
- package/lib/collab/yjs/LexicalCollaborationPlugin.js +63 -0
- package/lib/collab/yjs/State.d.ts +51 -0
- package/lib/collab/yjs/State.js +35 -0
- package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +5 -0
- package/lib/collab/yjs/nodes/AnyCollabNode.js +1 -0
- package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +22 -0
- package/lib/collab/yjs/nodes/CollabDecoratorNode.js +64 -0
- package/lib/collab/yjs/nodes/CollabElementNode.d.ts +40 -0
- package/lib/collab/yjs/nodes/CollabElementNode.js +462 -0
- package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +19 -0
- package/lib/collab/yjs/nodes/CollabLineBreakNode.js +44 -0
- package/lib/collab/yjs/nodes/CollabTextNode.d.ts +25 -0
- package/lib/collab/yjs/nodes/CollabTextNode.js +103 -0
- package/lib/collab/yjs/provider/websocket.d.ts +88 -0
- package/lib/collab/yjs/provider/websocket.js +415 -0
- package/lib/collab/yjs/servers/index.d.ts +0 -0
- package/lib/collab/yjs/servers/index.js +0 -0
- package/lib/collab/yjs/servers/ws/callback.d.ts +5 -0
- package/lib/collab/yjs/servers/ws/callback.js +72 -0
- package/lib/collab/yjs/servers/ws/server.d.ts +2 -0
- package/lib/collab/yjs/servers/ws/server.js +25 -0
- package/lib/collab/yjs/servers/ws/utils.d.ts +49 -0
- package/lib/collab/yjs/servers/ws/utils.js +284 -0
- package/lib/collab/yjs/sync/SyncCursors.d.ts +39 -0
- package/lib/collab/yjs/sync/SyncCursors.js +351 -0
- package/lib/collab/yjs/sync/SyncEditorStates.d.ts +10 -0
- package/lib/collab/yjs/sync/SyncEditorStates.js +200 -0
- package/lib/collab/yjs/useCollaboration.d.ts +12 -0
- package/lib/collab/yjs/useCollaboration.js +255 -0
- package/lib/collab/yjs/utils/Utils.d.ts +25 -0
- package/lib/collab/yjs/utils/Utils.js +402 -0
- package/lib/collab/yjs/wsProvider.d.ts +3 -0
- package/lib/collab/yjs/wsProvider.js +21 -0
- package/lib/commenting/index.d.ts +41 -0
- package/lib/commenting/index.js +324 -0
- package/lib/context/FlashMessageContext.d.ts +7 -0
- package/lib/context/FlashMessageContext.js +24 -0
- package/lib/context/SettingsContext.d.ts +12 -0
- package/lib/context/SettingsContext.js +38 -0
- package/lib/context/SharedHistoryContext.d.ts +11 -0
- package/lib/context/SharedHistoryContext.js +11 -0
- package/lib/context/ToolbarContext.d.ts +65 -0
- package/lib/context/ToolbarContext.js +84 -0
- package/lib/demo.d.ts +12 -0
- package/lib/demo.js +41 -0
- package/lib/hooks/useFlashMessage.d.ts +2 -0
- package/lib/hooks/useFlashMessage.js +4 -0
- package/lib/hooks/useModal.d.ts +5 -0
- package/lib/hooks/useModal.js +26 -0
- package/lib/hooks/useReport.d.ts +1 -0
- package/lib/hooks/useReport.js +46 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -5
- package/lib/nodes/AutocompleteNode.d.ts +27 -0
- package/lib/nodes/AutocompleteNode.js +56 -0
- package/lib/nodes/CounterComponent.d.ts +6 -0
- package/lib/nodes/CounterComponent.js +137 -0
- package/lib/nodes/CounterNode.d.ts +23 -0
- package/lib/nodes/CounterNode.js +47 -0
- package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +8 -0
- package/lib/nodes/DateTimeNode/DateTimeComponent.js +119 -0
- package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +27 -0
- package/lib/nodes/DateTimeNode/DateTimeNode.js +82 -0
- package/lib/nodes/EmojiNode.d.ts +18 -0
- package/lib/nodes/EmojiNode.js +50 -0
- package/lib/nodes/EquationComponent.d.ts +9 -0
- package/lib/nodes/EquationComponent.js +75 -0
- package/lib/nodes/EquationNode.d.ts +26 -0
- package/lib/nodes/EquationNode.js +109 -0
- package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +8 -0
- package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +110 -0
- package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +50 -0
- package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +55 -0
- package/lib/nodes/ExcalidrawNode/index.d.ts +32 -0
- package/lib/nodes/ExcalidrawNode/index.js +117 -0
- package/lib/nodes/FigmaNode.d.ts +20 -0
- package/lib/nodes/FigmaNode.js +52 -0
- package/lib/nodes/ImageComponent.d.ts +16 -0
- package/lib/nodes/ImageComponent.js +272 -0
- package/lib/nodes/ImageNode.d.ts +50 -0
- package/lib/nodes/ImageNode.js +151 -0
- package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +26 -0
- package/lib/nodes/InlineImageNode/InlineImageComponent.js +161 -0
- package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +59 -0
- package/lib/nodes/InlineImageNode/InlineImageNode.js +162 -0
- package/lib/nodes/KeywordNode.d.ts +14 -0
- package/lib/nodes/KeywordNode.js +33 -0
- package/lib/nodes/LayoutContainerNode.d.ts +24 -0
- package/lib/nodes/LayoutContainerNode.js +91 -0
- package/lib/nodes/LayoutItemNode.d.ts +16 -0
- package/lib/nodes/LayoutItemNode.js +65 -0
- package/lib/nodes/MentionNode.d.ts +20 -0
- package/lib/nodes/MentionNode.js +81 -0
- package/lib/nodes/PageBreakNode/index.d.ts +17 -0
- package/lib/nodes/PageBreakNode/index.js +83 -0
- package/lib/nodes/PlaygroundNodes.d.ts +3 -0
- package/lib/nodes/PlaygroundNodes.js +71 -0
- package/lib/nodes/PollComponent.d.ts +9 -0
- package/lib/nodes/PollComponent.js +85 -0
- package/lib/nodes/PollNode.d.ts +43 -0
- package/lib/nodes/PollNode.js +153 -0
- package/lib/nodes/SpecialTextNode.d.ts +24 -0
- package/lib/nodes/SpecialTextNode.js +50 -0
- package/lib/nodes/StickyComponent.d.ts +10 -0
- package/lib/nodes/StickyComponent.js +162 -0
- package/lib/nodes/StickyNode.d.ts +31 -0
- package/lib/nodes/StickyNode.js +76 -0
- package/lib/nodes/TweetNode.d.ts +21 -0
- package/lib/nodes/TweetNode.js +119 -0
- package/lib/nodes/YouTubeNode.d.ts +22 -0
- package/lib/nodes/YouTubeNode.js +84 -0
- package/lib/plugins/ActionsPlugin/index.d.ts +5 -0
- package/lib/plugins/ActionsPlugin/index.js +168 -0
- package/lib/plugins/AutoEmbedPlugin/index.d.ts +19 -0
- package/lib/plugins/AutoEmbedPlugin/index.js +158 -0
- package/lib/plugins/AutoLinkPlugin/index.d.ts +2 -0
- package/lib/plugins/AutoLinkPlugin/index.js +15 -0
- package/lib/plugins/AutocompletePlugin/index.d.ts +10 -0
- package/lib/plugins/AutocompletePlugin/index.js +2473 -0
- package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +7 -0
- package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +42 -0
- package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +17 -0
- package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +111 -0
- package/lib/plugins/CodeActionMenuPlugin/index.d.ts +5 -0
- package/lib/plugins/CodeActionMenuPlugin/index.js +104 -0
- package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +1 -0
- package/lib/plugins/CodeActionMenuPlugin/utils.js +18 -0
- package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +2 -0
- package/lib/plugins/CodeHighlightPrismPlugin/index.js +10 -0
- package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +2 -0
- package/lib/plugins/CodeHighlightShikiPlugin/index.js +10 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +25 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +131 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +16 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +79 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +16 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +81 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +2 -0
- package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +8 -0
- package/lib/plugins/CollapsiblePlugin/index.d.ts +3 -0
- package/lib/plugins/CollapsiblePlugin/index.js +128 -0
- package/lib/plugins/CommentPlugin/index.d.ts +9 -0
- package/lib/plugins/CommentPlugin/index.js +460 -0
- package/lib/plugins/ComponentPickerPlugin/index.d.ts +2 -0
- package/lib/plugins/ComponentPickerPlugin/index.js +276 -0
- package/lib/plugins/ContextMenuPlugin/index.d.ts +2 -0
- package/lib/plugins/ContextMenuPlugin/index.js +112 -0
- package/lib/plugins/CounterPlugin/index.d.ts +3 -0
- package/lib/plugins/CounterPlugin/index.js +20 -0
- package/lib/plugins/DatalayerPlugin/index.d.ts +2 -0
- package/lib/plugins/DatalayerPlugin/index.js +218 -0
- package/lib/plugins/DateTimePlugin/index.d.ts +8 -0
- package/lib/plugins/DateTimePlugin/index.js +24 -0
- package/lib/plugins/DocsPlugin/index.d.ts +2 -0
- package/lib/plugins/DocsPlugin/index.js +4 -0
- package/lib/plugins/DragDropPastePlugin/index.d.ts +1 -0
- package/lib/plugins/DragDropPastePlugin/index.js +33 -0
- package/lib/plugins/DraggableBlockPlugin/index.d.ts +12 -0
- package/lib/plugins/DraggableBlockPlugin/index.js +36 -0
- package/lib/plugins/EmojiPickerPlugin/index.d.ts +1 -0
- package/lib/plugins/EmojiPickerPlugin/index.js +80 -0
- package/lib/plugins/EmojisPlugin/index.d.ts +2 -0
- package/lib/plugins/EmojisPlugin/index.js +52 -0
- package/lib/plugins/EquationsPlugin/index.d.ts +14 -0
- package/lib/plugins/EquationsPlugin/index.js +34 -0
- package/lib/plugins/ExcalidrawPlugin/index.d.ts +5 -0
- package/lib/plugins/ExcalidrawPlugin/index.js +44 -0
- package/lib/plugins/FigmaPlugin/index.d.ts +4 -0
- package/lib/plugins/FigmaPlugin/index.js +20 -0
- package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +15 -0
- package/lib/plugins/FloatingLinkEditorPlugin/index.js +280 -0
- package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +7 -0
- package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +219 -0
- package/lib/plugins/ImagesPlugin/index.d.ts +24 -0
- package/lib/plugins/ImagesPlugin/index.js +195 -0
- package/lib/plugins/InlineImagePlugin/index.d.ts +17 -0
- package/lib/plugins/InlineImagePlugin/index.js +180 -0
- package/lib/plugins/KeywordsPlugin/index.d.ts +2 -0
- package/lib/plugins/KeywordsPlugin/index.js +31 -0
- package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +6 -0
- package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +21 -0
- package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +7 -0
- package/lib/plugins/LayoutPlugin/LayoutPlugin.js +131 -0
- package/lib/plugins/LinkPlugin/index.d.ts +6 -0
- package/lib/plugins/LinkPlugin/index.js +11 -0
- package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +2 -0
- package/lib/plugins/MarkdownShortcutPlugin/index.js +6 -0
- package/lib/plugins/MarkdownTransformers/index.d.ts +8 -0
- package/lib/plugins/MarkdownTransformers/index.js +234 -0
- package/lib/plugins/MaxLengthPlugin/index.d.ts +3 -0
- package/lib/plugins/MaxLengthPlugin/index.js +37 -0
- package/lib/plugins/MentionsPlugin/index.d.ts +2 -0
- package/lib/plugins/MentionsPlugin/index.js +564 -0
- package/lib/plugins/PageBreakPlugin/index.d.ts +4 -0
- package/lib/plugins/PageBreakPlugin/index.js +27 -0
- package/lib/plugins/PasteLogPlugin/index.d.ts +2 -0
- package/lib/plugins/PasteLogPlugin/index.js +27 -0
- package/lib/plugins/PollPlugin/index.d.ts +8 -0
- package/lib/plugins/PollPlugin/index.js +38 -0
- package/lib/plugins/ShortcutsPlugin/index.d.ts +6 -0
- package/lib/plugins/ShortcutsPlugin/index.js +112 -0
- package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +59 -0
- package/lib/plugins/ShortcutsPlugin/shortcuts.js +169 -0
- package/lib/plugins/SpecialTextPlugin/index.d.ts +2 -0
- package/lib/plugins/SpecialTextPlugin/index.js +46 -0
- package/lib/plugins/SpeechToTextPlugin/index.d.ts +5 -0
- package/lib/plugins/SpeechToTextPlugin/index.js +82 -0
- package/lib/plugins/StickyPlugin/index.d.ts +2 -0
- package/lib/plugins/StickyPlugin/index.js +12 -0
- package/lib/plugins/TabFocusPlugin/index.d.ts +1 -0
- package/lib/plugins/TabFocusPlugin/index.js +34 -0
- package/lib/plugins/TableActionMenuPlugin/index.d.ts +5 -0
- package/lib/plugins/TableActionMenuPlugin/index.js +492 -0
- package/lib/plugins/TableCellResizer/index.d.ts +3 -0
- package/lib/plugins/TableCellResizer/index.js +297 -0
- package/lib/plugins/TableHoverActionsPlugin/index.d.ts +4 -0
- package/lib/plugins/TableHoverActionsPlugin/index.js +188 -0
- package/lib/plugins/TableOfContentsPlugin/index.d.ts +2 -0
- package/lib/plugins/TableOfContentsPlugin/index.js +116 -0
- package/lib/plugins/TablePlugin.d.ts +31 -0
- package/lib/plugins/TablePlugin.js +63 -0
- package/lib/plugins/TestRecorderPlugin/index.d.ts +3 -0
- package/lib/plugins/TestRecorderPlugin/index.js +346 -0
- package/lib/plugins/ToolbarPlugin/fontSize.d.ts +9 -0
- package/lib/plugins/ToolbarPlugin/fontSize.js +80 -0
- package/lib/plugins/ToolbarPlugin/index.d.ts +9 -0
- package/lib/plugins/ToolbarPlugin/index.js +500 -0
- package/lib/plugins/ToolbarPlugin/utils.d.ts +26 -0
- package/lib/plugins/ToolbarPlugin/utils.js +243 -0
- package/lib/plugins/TreeViewPlugin/index.d.ts +2 -0
- package/lib/plugins/TreeViewPlugin/index.js +7 -0
- package/lib/plugins/TwitterPlugin/index.d.ts +4 -0
- package/lib/plugins/TwitterPlugin/index.js +20 -0
- package/lib/plugins/TypingPerfPlugin/index.d.ts +2 -0
- package/lib/plugins/TypingPerfPlugin/index.js +93 -0
- package/lib/plugins/YouTubePlugin/index.d.ts +4 -0
- package/lib/plugins/YouTubePlugin/index.js +20 -0
- package/lib/server/validation.d.ts +1 -0
- package/lib/server/validation.js +111 -0
- package/lib/setupEnv.d.ts +2 -0
- package/lib/setupEnv.js +25 -0
- package/lib/themes/CommentEditorTheme.d.ts +4 -0
- package/lib/themes/CommentEditorTheme.js +7 -0
- package/lib/themes/PlaygroundEditorTheme.d.ts +4 -0
- package/lib/themes/PlaygroundEditorTheme.js +120 -0
- package/lib/themes/StickyEditorTheme.d.ts +4 -0
- package/lib/themes/StickyEditorTheme.js +7 -0
- package/lib/tyes.dt.d.ts +12 -0
- package/lib/tyes.dt.js +0 -0
- package/lib/ui/Button.d.ts +12 -0
- package/lib/ui/Button.js +6 -0
- package/lib/ui/ColorPicker.d.ts +14 -0
- package/lib/ui/ColorPicker.js +219 -0
- package/lib/ui/ContentEditable.d.ts +9 -0
- package/lib/ui/ContentEditable.js +6 -0
- package/lib/ui/Dialog.d.ts +10 -0
- package/lib/ui/Dialog.js +8 -0
- package/lib/ui/DropDown.d.ts +18 -0
- package/lib/ui/DropDown.js +133 -0
- package/lib/ui/DropdownColorPicker.d.ts +13 -0
- package/lib/ui/DropdownColorPicker.js +6 -0
- package/lib/ui/EquationEditor.d.ts +8 -0
- package/lib/ui/EquationEditor.js +11 -0
- package/lib/ui/ExcalidrawModal.d.ts +42 -0
- package/lib/ui/ExcalidrawModal.js +103 -0
- package/lib/ui/FileInput.d.ts +10 -0
- package/lib/ui/FileInput.js +5 -0
- package/lib/ui/FlashMessage.d.ts +7 -0
- package/lib/ui/FlashMessage.js +6 -0
- package/lib/ui/ImageResizer.d.ts +17 -0
- package/lib/ui/ImageResizer.js +171 -0
- package/lib/ui/KatexEquationAlterer.d.ts +8 -0
- package/lib/ui/KatexEquationAlterer.js +23 -0
- package/lib/ui/KatexRenderer.d.ts +6 -0
- package/lib/ui/KatexRenderer.js +24 -0
- package/lib/ui/Modal.d.ts +9 -0
- package/lib/ui/Modal.js +48 -0
- package/lib/ui/Select.d.ts +8 -0
- package/lib/ui/Select.js +5 -0
- package/lib/ui/Switch.d.ts +8 -0
- package/lib/ui/Switch.js +6 -0
- package/lib/ui/TextInput.d.ts +13 -0
- package/lib/ui/TextInput.js +7 -0
- package/lib/utils/docSerialization.d.ts +3 -0
- package/lib/utils/docSerialization.js +56 -0
- package/lib/utils/emoji-list.d.ts +20 -0
- package/lib/utils/emoji-list.js +16605 -0
- package/lib/utils/getDOMRangeRect.d.ts +8 -0
- package/lib/utils/getDOMRangeRect.js +22 -0
- package/lib/utils/getSelectedNode.d.ts +2 -0
- package/lib/utils/getSelectedNode.js +24 -0
- package/lib/utils/getThemeSelector.d.ts +2 -0
- package/lib/utils/getThemeSelector.js +10 -0
- package/lib/utils/isMobileWidth.d.ts +7 -0
- package/lib/utils/isMobileWidth.js +7 -0
- package/lib/utils/joinClasses.d.ts +1 -0
- package/lib/utils/joinClasses.js +3 -0
- package/lib/utils/setFloatingElemPosition.d.ts +1 -0
- package/lib/utils/setFloatingElemPosition.js +55 -0
- package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +1 -0
- package/lib/utils/setFloatingElemPositionForLinkEditor.js +32 -0
- package/lib/utils/swipe.d.ts +4 -0
- package/lib/utils/swipe.js +90 -0
- package/lib/utils/url.d.ts +2 -0
- package/lib/utils/url.js +27 -0
- package/package.json +82 -51
- package/lib/DiffMerge.d.ts +0 -39
- package/lib/DiffMerge.js +0 -437
- package/lib/LoroCollaborativePlugin.d.ts +0 -62
- package/lib/LoroCollaborativePlugin.js +0 -2826
- package/lib/stableNodeState.d.ts +0 -8
- package/lib/stableNodeState.js +0 -15
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { $getNodeByKey } from 'lexical';
|
|
2
|
+
import { $diffTextContentAndApplyDelta } from '../utils/Utils';
|
|
3
|
+
/**
|
|
4
|
+
* Handles map data changes (node properties, metadata updates)
|
|
5
|
+
*/
|
|
6
|
+
export class MapIntegrator {
|
|
7
|
+
integrate(diff, binding, provider) {
|
|
8
|
+
// Handle updated properties
|
|
9
|
+
if (diff.updated) {
|
|
10
|
+
Object.entries(diff.updated).forEach(([key, value]) => {
|
|
11
|
+
this.integratePropertyUpdate(key, value, binding, provider);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
// Handle deleted properties
|
|
15
|
+
if (diff.deleted) {
|
|
16
|
+
diff.deleted.forEach((key) => {
|
|
17
|
+
this.integratePropertyDelete(key, binding, provider);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Enhanced integrate method with TreeID context
|
|
22
|
+
integrateWithContext(diff, treeId, binding, provider) {
|
|
23
|
+
this.integrateWithContextInternal(diff, treeId, binding, provider);
|
|
24
|
+
}
|
|
25
|
+
// Internal method for use when already inside editor.update()
|
|
26
|
+
integrateInternal(diff, binding, provider) {
|
|
27
|
+
// Handle updated properties
|
|
28
|
+
if (diff.updated) {
|
|
29
|
+
Object.entries(diff.updated).forEach(([key, value]) => {
|
|
30
|
+
this.integratePropertyUpdate(key, value, binding, provider);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// Handle deleted properties
|
|
34
|
+
if (diff.deleted) {
|
|
35
|
+
diff.deleted.forEach((key) => {
|
|
36
|
+
this.integratePropertyDelete(key, binding, provider);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Internal method for use when already inside editor.update() with context
|
|
41
|
+
integrateWithContextInternal(diff, treeId, binding, provider) {
|
|
42
|
+
// Handle updated properties with TreeID context
|
|
43
|
+
if (diff.updated) {
|
|
44
|
+
Object.entries(diff.updated).forEach(([key, value]) => {
|
|
45
|
+
this.integratePropertyUpdateWithContextInternal(key, value, treeId, binding, provider);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Handle deleted properties
|
|
49
|
+
if (diff.deleted) {
|
|
50
|
+
diff.deleted.forEach((key) => {
|
|
51
|
+
this.integratePropertyDelete(key, binding, provider);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
integratePropertyUpdateWithContext(key, value, treeId, binding, provider) {
|
|
56
|
+
// Handle specific property updates with TreeID context
|
|
57
|
+
switch (key) {
|
|
58
|
+
case 'lexical':
|
|
59
|
+
this.integrateLexicalDataUpdateWithContext(value, treeId, binding);
|
|
60
|
+
break;
|
|
61
|
+
case 'textContent':
|
|
62
|
+
// Text content updates should be integrated via lexical data updates
|
|
63
|
+
break;
|
|
64
|
+
case 'elementType':
|
|
65
|
+
// Element type changes are rare, mostly for debugging
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
//
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Internal version for use when already inside editor.update()
|
|
72
|
+
integratePropertyUpdateWithContextInternal(key, value, treeId, binding, provider) {
|
|
73
|
+
// Handle specific property updates with TreeID context
|
|
74
|
+
switch (key) {
|
|
75
|
+
case 'lexical':
|
|
76
|
+
// Extract TreeID and call internal method directly (already inside editor.update())
|
|
77
|
+
let actualTreeID = treeId;
|
|
78
|
+
if (typeof treeId === 'string' && treeId.startsWith('cid:')) {
|
|
79
|
+
const parts = treeId.split(':');
|
|
80
|
+
if (parts.length >= 3) {
|
|
81
|
+
actualTreeID = parts[1];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(actualTreeID);
|
|
85
|
+
if (lexicalKey) {
|
|
86
|
+
this.integrateLexicalDataUpdateInternal(value, lexicalKey, actualTreeID);
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
case 'textContent':
|
|
90
|
+
// Text content updates should be integrated via lexical data updates
|
|
91
|
+
break;
|
|
92
|
+
case 'elementType':
|
|
93
|
+
// Element type changes are rare, mostly for debugging
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
// Generic property update with context
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
integratePropertyUpdate(key, value, binding, provider) {
|
|
101
|
+
// Handle specific property updates
|
|
102
|
+
switch (key) {
|
|
103
|
+
case 'lexical':
|
|
104
|
+
// Use targeted update only - the broad heuristic causes scrambling
|
|
105
|
+
break;
|
|
106
|
+
case 'textContent':
|
|
107
|
+
// Text content updates should be integrated via lexical data updates
|
|
108
|
+
break;
|
|
109
|
+
case 'elementType':
|
|
110
|
+
// Element type changes are rare, mostly for debugging
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
// Generic property update
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
integratePropertyDelete(key, binding, provider) {
|
|
118
|
+
// Handle specific property deletions
|
|
119
|
+
switch (key) {
|
|
120
|
+
case 'lexical':
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
// Generic property deleted
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
integrateLexicalDataUpdateWithContext(lexicalData, treeId, binding) {
|
|
128
|
+
// Extract the actual TreeID from container ID format
|
|
129
|
+
// Container ID format: "cid:6@7648424808278730813:Map"
|
|
130
|
+
// TreeID format: "6@7648424808278730813"
|
|
131
|
+
let actualTreeID = treeId;
|
|
132
|
+
if (typeof treeId === 'string' && treeId.startsWith('cid:')) {
|
|
133
|
+
const parts = treeId.split(':');
|
|
134
|
+
if (parts.length >= 3) {
|
|
135
|
+
actualTreeID = parts[1]; // Extract "6@7648424808278730813" from "cid:6@7648424808278730813:Map"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Use the TreeID to find the specific Lexical node
|
|
139
|
+
const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(actualTreeID);
|
|
140
|
+
if (!lexicalKey) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (lexicalData && typeof lexicalData === 'object') {
|
|
144
|
+
binding.editor.update(() => {
|
|
145
|
+
this.integrateLexicalDataUpdateInternal(lexicalData, lexicalKey, actualTreeID);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Internal method for use when already inside editor.update()
|
|
150
|
+
integrateLexicalDataUpdateInternal(lexicalData, lexicalKey, treeId) {
|
|
151
|
+
const targetType = lexicalData.type || lexicalData.__type;
|
|
152
|
+
const targetNode = $getNodeByKey(lexicalKey);
|
|
153
|
+
if (!targetNode) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const textContent = lexicalData.__text || lexicalData.text || lexicalData.textContent;
|
|
157
|
+
if (targetType === 'text' && textContent !== undefined) {
|
|
158
|
+
// Cast to TextNode to access text-specific methods
|
|
159
|
+
if (targetNode.getType() === 'text') {
|
|
160
|
+
const textNode = targetNode;
|
|
161
|
+
// Only update if the content is actually different to avoid unnecessary updates
|
|
162
|
+
const currentText = textNode.getTextContent();
|
|
163
|
+
if (currentText !== textContent) {
|
|
164
|
+
// Apply the text update using delta to preserve cursor position and minimize disruption
|
|
165
|
+
$diffTextContentAndApplyDelta(textNode, lexicalKey, currentText, textContent);
|
|
166
|
+
}
|
|
167
|
+
// Apply other text properties if present
|
|
168
|
+
if (lexicalData.format !== undefined) {
|
|
169
|
+
textNode.setFormat(lexicalData.format);
|
|
170
|
+
}
|
|
171
|
+
if (lexicalData.style !== undefined) {
|
|
172
|
+
textNode.setStyle(lexicalData.style);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseIntegrator } from './BaseIntegrator';
|
|
2
|
+
import { Binding } from '../Bindings';
|
|
3
|
+
import { Provider } from '../State';
|
|
4
|
+
interface TextDiff {
|
|
5
|
+
type: 'text';
|
|
6
|
+
diff?: Array<{
|
|
7
|
+
type: 'insert' | 'delete' | 'retain';
|
|
8
|
+
index?: number;
|
|
9
|
+
length?: number;
|
|
10
|
+
value?: string;
|
|
11
|
+
attributes?: any;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Handles text changes (character insertions, deletions, formatting)
|
|
16
|
+
*/
|
|
17
|
+
export declare class TextIntegrator implements BaseIntegrator<TextDiff> {
|
|
18
|
+
integrate(diff: TextDiff, binding: Binding, provider: Provider): void;
|
|
19
|
+
integrateInternal(diff: TextDiff, binding: Binding, provider: Provider): void;
|
|
20
|
+
private integrateTextInsert;
|
|
21
|
+
private integrateTextDelete;
|
|
22
|
+
private integrateTextRetain;
|
|
23
|
+
private applyTextFormatting;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles text changes (character insertions, deletions, formatting)
|
|
3
|
+
*/
|
|
4
|
+
export class TextIntegrator {
|
|
5
|
+
integrate(diff, binding, provider) {
|
|
6
|
+
this.integrateInternal(diff, binding, provider);
|
|
7
|
+
}
|
|
8
|
+
// Internal method for use when already inside editor.update()
|
|
9
|
+
integrateInternal(diff, binding, provider) {
|
|
10
|
+
if (diff.diff) {
|
|
11
|
+
diff.diff.forEach((change) => {
|
|
12
|
+
switch (change.type) {
|
|
13
|
+
case 'insert':
|
|
14
|
+
this.integrateTextInsert(change, binding, provider);
|
|
15
|
+
break;
|
|
16
|
+
case 'delete':
|
|
17
|
+
this.integrateTextDelete(change, binding, provider);
|
|
18
|
+
break;
|
|
19
|
+
case 'retain':
|
|
20
|
+
this.integrateTextRetain(change, binding, provider);
|
|
21
|
+
break;
|
|
22
|
+
default:
|
|
23
|
+
console.warn(`📝 Unknown text change type: ${change.type}`);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
integrateTextInsert(change, binding, provider) {
|
|
29
|
+
// To integrate text insertion, we need to know which TextNode this applies to
|
|
30
|
+
// This information should come from the event context or be tracked separately
|
|
31
|
+
// For now, this is a placeholder - in a complete implementation,
|
|
32
|
+
// we would need to identify the target TextNode and update it
|
|
33
|
+
}
|
|
34
|
+
integrateTextDelete(change, binding, provider) {
|
|
35
|
+
// Similar to insert, we need target node context for text deletion
|
|
36
|
+
}
|
|
37
|
+
integrateTextRetain(change, binding, provider) {
|
|
38
|
+
if (change.attributes) {
|
|
39
|
+
// Handle text formatting changes
|
|
40
|
+
this.applyTextFormatting({ ...change, attributes: change.attributes }, binding, provider);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
applyTextFormatting(change, binding, provider) {
|
|
44
|
+
// Text formatting in Lexical is typically integrated through TextNode format property
|
|
45
|
+
// This would need to be coordinated with the specific TextNode being modified
|
|
46
|
+
// Example formatting attributes might include:
|
|
47
|
+
// - bold, italic, underline
|
|
48
|
+
// - font size, color
|
|
49
|
+
// - etc.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TreeID } from 'loro-crdt';
|
|
2
|
+
import { BaseIntegrator } from './BaseIntegrator';
|
|
3
|
+
import { Binding } from '../Bindings';
|
|
4
|
+
import { Provider } from '../State';
|
|
5
|
+
interface TreeDiff {
|
|
6
|
+
type: 'tree';
|
|
7
|
+
diff: Array<{
|
|
8
|
+
action: 'create' | 'move' | 'delete';
|
|
9
|
+
target: TreeID;
|
|
10
|
+
parent?: TreeID;
|
|
11
|
+
index?: number;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Simplified tree diff integrater that trusts Loro's CRDT conflict resolution
|
|
16
|
+
* and applies operations directly without complex filtering or context classification
|
|
17
|
+
*/
|
|
18
|
+
export declare class TreeIntegrator implements BaseIntegrator<TreeDiff> {
|
|
19
|
+
integrate(diff: TreeDiff, binding: Binding, provider: Provider): void;
|
|
20
|
+
integrateInternal(diff: TreeDiff, binding: Binding, provider: Provider): void;
|
|
21
|
+
private integrateCreate;
|
|
22
|
+
private integrateMove;
|
|
23
|
+
private integrateDelete;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { $getRoot, $getNodeByKey, $isElementNode } from 'lexical';
|
|
2
|
+
import { parseTreeID } from '../utils/Utils';
|
|
3
|
+
import { createLexicalNodeFromLoro } from '../nodes/NodeFactory';
|
|
4
|
+
/**
|
|
5
|
+
* Simplified tree diff integrater that trusts Loro's CRDT conflict resolution
|
|
6
|
+
* and applies operations directly without complex filtering or context classification
|
|
7
|
+
*/
|
|
8
|
+
export class TreeIntegrator {
|
|
9
|
+
integrate(diff, binding, provider) {
|
|
10
|
+
// Batch all changes in a single editor update
|
|
11
|
+
binding.editor.update(() => {
|
|
12
|
+
this.integrateInternal(diff, binding, provider);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
// Internal method that can be called when already inside editor.update()
|
|
16
|
+
integrateInternal(diff, binding, provider) {
|
|
17
|
+
// Sort operations: deletes first, then creates (element nodes before text), then moves
|
|
18
|
+
const operations = [...diff.diff];
|
|
19
|
+
operations.sort((a, b) => {
|
|
20
|
+
// Delete operations first
|
|
21
|
+
if (a.action === 'delete' && b.action !== 'delete')
|
|
22
|
+
return -1;
|
|
23
|
+
if (b.action === 'delete' && a.action !== 'delete')
|
|
24
|
+
return 1;
|
|
25
|
+
// Move operations last
|
|
26
|
+
if (a.action === 'move' && b.action !== 'move')
|
|
27
|
+
return 1;
|
|
28
|
+
if (b.action === 'move' && a.action !== 'move')
|
|
29
|
+
return -1;
|
|
30
|
+
// For create operations, prioritize element nodes over text nodes
|
|
31
|
+
if (a.action === 'create' && b.action === 'create') {
|
|
32
|
+
const aNode = binding.tree.getNodeByID(a.target);
|
|
33
|
+
const bNode = binding.tree.getNodeByID(b.target);
|
|
34
|
+
const aIsText = aNode?.data.get('elementType') === 'text';
|
|
35
|
+
const bIsText = bNode?.data.get('elementType') === 'text';
|
|
36
|
+
if (aIsText && !bIsText)
|
|
37
|
+
return 1; // b (element) comes before a (text)
|
|
38
|
+
if (!aIsText && bIsText)
|
|
39
|
+
return -1; // a (element) comes before b (text)
|
|
40
|
+
}
|
|
41
|
+
return 0; // Keep original order for same priority
|
|
42
|
+
});
|
|
43
|
+
operations.forEach(operation => {
|
|
44
|
+
switch (operation.action) {
|
|
45
|
+
case 'create':
|
|
46
|
+
this.integrateCreate(operation, binding, provider);
|
|
47
|
+
break;
|
|
48
|
+
case 'move':
|
|
49
|
+
this.integrateMove(operation, binding, provider);
|
|
50
|
+
break;
|
|
51
|
+
case 'delete':
|
|
52
|
+
this.integrateDelete(operation, binding, provider);
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
console.warn(`🌳 Unknown tree operation: ${operation.action}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
integrateCreate(operation, binding, provider) {
|
|
60
|
+
try {
|
|
61
|
+
let { nodeKey } = parseTreeID(operation.target);
|
|
62
|
+
// Skip root node creation - root is integrated during initial setup
|
|
63
|
+
// But ensure the root mapping exists
|
|
64
|
+
// Only treat as root if it's actually a root-type node in Loro
|
|
65
|
+
if (nodeKey === "0") {
|
|
66
|
+
const treeNode = binding.tree.getNodeByID(operation.target);
|
|
67
|
+
const elementType = treeNode?.data.get('elementType');
|
|
68
|
+
if (elementType === 'root' || !elementType) {
|
|
69
|
+
const root = $getRoot();
|
|
70
|
+
binding.nodeMapper.setMapping(root.getKey(), operation.target);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// If nodeKey is "0" but it's not actually a root element, continue with normal processing
|
|
74
|
+
}
|
|
75
|
+
// Check if node already exists and if it's the same TreeID
|
|
76
|
+
const existingNode = $getNodeByKey(nodeKey);
|
|
77
|
+
if (existingNode) {
|
|
78
|
+
const existingTreeID = binding.nodeMapper.getTreeIDByLexicalKey(nodeKey);
|
|
79
|
+
if (existingTreeID === operation.target) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Don't reuse existing keys for different TreeIDs - let Lexical generate a fresh one
|
|
84
|
+
nodeKey = undefined; // Let createLexicalNodeFromLoro generate a fresh key
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Create Lexical node from Loro data
|
|
88
|
+
const lexicalNode = createLexicalNodeFromLoro(operation.target, binding.tree, binding);
|
|
89
|
+
if (!lexicalNode) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Find parent node
|
|
93
|
+
let parentNode;
|
|
94
|
+
if (operation.parent) {
|
|
95
|
+
const parentKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.parent);
|
|
96
|
+
const parentLexicalNode = parentKey ? $getNodeByKey(parentKey) : null;
|
|
97
|
+
if (parentLexicalNode && $isElementNode(parentLexicalNode)) {
|
|
98
|
+
parentNode = parentLexicalNode;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// For text nodes, we MUST have a proper parent element
|
|
102
|
+
if (lexicalNode.getType() === 'text') {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
parentNode = $getRoot();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
parentNode = $getRoot();
|
|
110
|
+
}
|
|
111
|
+
// Normal insertion
|
|
112
|
+
if (operation.index !== undefined) {
|
|
113
|
+
parentNode.splice(operation.index, 0, [lexicalNode]);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
parentNode.append(lexicalNode);
|
|
117
|
+
}
|
|
118
|
+
// Set up mapping
|
|
119
|
+
binding.nodeMapper.setMapping(lexicalNode.getKey(), operation.target);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.warn(`🌳 Error creating node for ${operation.target}:`, error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
integrateMove(operation, binding, provider) {
|
|
126
|
+
try {
|
|
127
|
+
const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.target);
|
|
128
|
+
if (!lexicalKey) {
|
|
129
|
+
console.warn(`🌳 No Lexical key found for move target ${operation.target}`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const nodeToMove = $getNodeByKey(lexicalKey);
|
|
133
|
+
if (!nodeToMove) {
|
|
134
|
+
console.warn(`🌳 Node to move not found: ${lexicalKey}`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Find new parent
|
|
138
|
+
let newParent;
|
|
139
|
+
if (operation.parent) {
|
|
140
|
+
const parentKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.parent);
|
|
141
|
+
const parentNode = parentKey ? $getNodeByKey(parentKey) : null;
|
|
142
|
+
if (parentNode && $isElementNode(parentNode)) {
|
|
143
|
+
newParent = parentNode;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// For text nodes, we can't move them to root - skip this move operation
|
|
147
|
+
// The node is already in the correct position from our create fix
|
|
148
|
+
if (nodeToMove.getType() === 'text') {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
newParent = $getRoot();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// For text nodes without a parent, skip the move
|
|
156
|
+
if (nodeToMove.getType() === 'text') {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
newParent = $getRoot();
|
|
160
|
+
}
|
|
161
|
+
// Remove from current position and insert at new position
|
|
162
|
+
nodeToMove.remove();
|
|
163
|
+
if (operation.index !== undefined) {
|
|
164
|
+
newParent.splice(operation.index, 0, [nodeToMove]);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
newParent.append(nodeToMove);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.warn(`🌳 Error moving node ${operation.target}:`, error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
integrateDelete(operation, binding, provider) {
|
|
175
|
+
try {
|
|
176
|
+
const lexicalKey = binding.nodeMapper.getLexicalKeyByLoroId(operation.target);
|
|
177
|
+
if (!lexicalKey) {
|
|
178
|
+
console.warn(`🌳 No Lexical key found for delete target ${operation.target}`);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const nodeToDelete = $getNodeByKey(lexicalKey);
|
|
182
|
+
if (!nodeToDelete) {
|
|
183
|
+
console.warn(`🌳 Node to delete not found: ${lexicalKey}`);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// Remove from Lexical tree
|
|
187
|
+
nodeToDelete.remove();
|
|
188
|
+
// Clean up mapping
|
|
189
|
+
binding.nodeMapper.deleteMapping(lexicalKey);
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
// Handle the case where Loro is trying to delete an already deleted node
|
|
193
|
+
if (error.message && error.message.includes('is deleted or does not exist')) {
|
|
194
|
+
console.log(`🌳 Node ${operation.target} already deleted (normal during restructuring):`, error.message);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.warn(`🌳 Error deleting node ${operation.target}:`, error);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TreeID, LoroTree } from 'loro-crdt';
|
|
2
|
+
import { LexicalNode, NodeKey } from 'lexical';
|
|
3
|
+
import { Binding } from '../Bindings';
|
|
4
|
+
/**
|
|
5
|
+
* Factory function to create Lexical nodes from Loro TreeID
|
|
6
|
+
* Uses the editor's registered node classes, similar to YJS implementation
|
|
7
|
+
*/
|
|
8
|
+
export declare function createLexicalNodeFromLoro(treeId: TreeID, loroTree: LoroTree, binding: Binding, parentKey?: NodeKey, nodeDataFromDiff?: any): LexicalNode | null;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory function to create Lexical nodes from Loro TreeID
|
|
3
|
+
* Uses the editor's registered node classes, similar to YJS implementation
|
|
4
|
+
*/
|
|
5
|
+
export function createLexicalNodeFromLoro(treeId, loroTree, binding, parentKey, nodeDataFromDiff) {
|
|
6
|
+
// Get node data from Loro tree
|
|
7
|
+
if (!loroTree.has(treeId)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const treeNode = loroTree.getNodeByID(treeId);
|
|
11
|
+
// First try nodeData passed from TreeDiff integrater (has immediate lexical data)
|
|
12
|
+
let lexicalData = nodeDataFromDiff?.lexical;
|
|
13
|
+
// Fallback to tree node data
|
|
14
|
+
if (!lexicalData) {
|
|
15
|
+
lexicalData = treeNode?.data.get('lexical');
|
|
16
|
+
}
|
|
17
|
+
let nodeType;
|
|
18
|
+
let deserializedData = null;
|
|
19
|
+
if (lexicalData && typeof lexicalData === 'object') {
|
|
20
|
+
// JSON object format - the only supported format
|
|
21
|
+
nodeType = lexicalData.type || lexicalData.__type;
|
|
22
|
+
deserializedData = { lexicalNode: lexicalData };
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Fallback to element type from nodeDataFromDiff or old nodeType
|
|
26
|
+
const fallbackType = nodeDataFromDiff?.elementType || treeNode?.data.get('nodeType');
|
|
27
|
+
if (!fallbackType || typeof fallbackType !== 'string') {
|
|
28
|
+
console.warn('No lexical data or nodeType found for TreeID:', treeId);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
nodeType = fallbackType;
|
|
32
|
+
}
|
|
33
|
+
// Get the registered node class from the editor (following YJS pattern)
|
|
34
|
+
const registeredNodes = binding.editor._nodes;
|
|
35
|
+
const nodeInfo = registeredNodes.get(nodeType);
|
|
36
|
+
if (!nodeInfo) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
// Create new instance of the registered node class
|
|
40
|
+
let lexicalNode;
|
|
41
|
+
// Special handling for HeadingNode which requires tag parameter in constructor
|
|
42
|
+
if (nodeType === 'heading') {
|
|
43
|
+
const tag = (deserializedData?.lexicalNode?.tag ||
|
|
44
|
+
(lexicalData && typeof lexicalData === 'object' && lexicalData.tag) ||
|
|
45
|
+
'h1');
|
|
46
|
+
try {
|
|
47
|
+
// HeadingNode constructor signature: new HeadingNode(tag, key)
|
|
48
|
+
// We pass tag as first argument, let Lexical generate the key
|
|
49
|
+
lexicalNode = new nodeInfo.klass(tag);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.warn(`🏭 NodeFactory: Failed to create HeadingNode:`, error);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
try {
|
|
58
|
+
lexicalNode = new nodeInfo.klass();
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.warn(`🏭 NodeFactory: Failed to create ${nodeType} instance:`, error);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Note: DO NOT set __parent manually - let Lexical integrate parent-child relationships
|
|
66
|
+
// through proper $ methods like append(), insertBefore(), etc.
|
|
67
|
+
// Apply properties from the deserialized data if available
|
|
68
|
+
if (deserializedData?.lexicalNode) {
|
|
69
|
+
const nodeData = deserializedData.lexicalNode;
|
|
70
|
+
// Apply all properties except system ones and tag (for HeadingNode)
|
|
71
|
+
Object.keys(nodeData).forEach(key => {
|
|
72
|
+
if (key !== '__parent' && key !== '__key') {
|
|
73
|
+
try {
|
|
74
|
+
if (key === 'tag' && nodeType === 'heading') {
|
|
75
|
+
// Tag is already set in HeadingNode constructor, skip
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
lexicalNode[key] = nodeData[key];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.warn(`Failed to set property ${key} on node:`, error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if (lexicalData && typeof lexicalData === 'object') {
|
|
88
|
+
// For direct object format (like heading data), apply properties directly
|
|
89
|
+
const applicableKeys = Object.keys(lexicalData).filter(key => key !== '__parent' && key !== '__key' && key !== 'type' && key !== 'children');
|
|
90
|
+
applicableKeys.forEach(key => {
|
|
91
|
+
try {
|
|
92
|
+
if (key === 'tag' && nodeType === 'heading') {
|
|
93
|
+
// Tag is already set in HeadingNode constructor, skip
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
lexicalNode[key] = lexicalData[key];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.warn(`Failed to set property ${key} on node:`, error);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return lexicalNode;
|
|
105
|
+
}
|