@lobehub/editor 4.10.3 → 4.11.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/es/{ReactSlashPlugin-CBLFF1e6.js → ReactSlashPlugin-DkEXwDgH.js} +105 -6
- package/es/headless.d.ts +24 -0
- package/es/headless.js +75 -6
- package/es/{index-BXj6uAM3.d.ts → index-DJq7pYS0.d.ts} +25 -1
- package/es/index.d.ts +83 -2
- package/es/index.js +1215 -88
- package/es/react.d.ts +1 -1
- package/es/react.js +3 -3
- package/es/renderer.js +2 -2
- package/es/{style-D-dIPHv5.js → style-DejqW6OX.js} +1 -1
- package/es/{style-CLtp6okE.js → style-DjwW7ClE.js} +75 -6
- package/package.json +1 -1
package/es/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as DOM_TEXT_TYPE, A as $createCodeMirrorNode, At as createDebugLogger, B as Editor, C as $createCodeNode$1, Ct as CONTROL_OR_META, Dt as KeyEnum, E as CodeNode$1, Et as HotkeyScopeEnum, F as $isCursorNode, Ft as init_debug, G as kernel_exports, Gt as INodeHelper, H as DataSource, I as CardLikeElementNode, It as prodSafeLogger, J as $getNearestNodeFromDOMNode, K as $closest, Kt as init_helper, M as CodeMirrorNode, Mt as debugLoggers, N as $createCursorNode, Nt as debug_exports, Ot as init_hotkey, P as $isCardLikeElementNode, Pt as devConsole, Q as DOM_ELEMENT_TYPE, R as cursorNodeSerialized, S as formatUrl, St as init_registerHotkey, Tt as HotkeyEnum, U as Kernel, V as resetRandomKey, W as init_kernel, X as DOM_DOCUMENT_FRAGMENT_TYPE, Y as $getNodeFromDOMNode, Yt as __toCommonJS, Z as DOM_DOCUMENT_TYPE, _ as AutoLinkNode, _t as unregisterEditorKernel, a as $createMathBlockNode, at as generateEditorId, b as LinkNode, bt as HOVER_COMMAND, c as MathBlockNode, ct as getNodeKeyFromDOMNode, dt as isDOMNode, et as EDITOR_THEME_KEY, f as LinkHighlightNode, ft as isDocumentFragment, g as $toggleLink, gt as registerEditorKernel, h as $isLinkNode, ht as reconcileDecorator, it as genServiceId, j as $isCodeMirrorNode, jt as debugLogger, kt as browserDebug, l as MathInlineNode, lt as getParentElement, m as $createLinkNode, mt as noop, nt as compareNodeOrder, o as $createMathInlineNode, ot as getKernelFromEditor, pt as moment, q as $closestNodeType, rt as createEmptyEditorState, s as $isMathNode, st as getKernelFromEditorConfig, tt as assert, u as $createLinkHighlightNode, ut as init_utils, v as HOVER_LINK_COMMAND, vt as KernelPlugin, wt as init_sys, x as TOGGLE_LINK_COMMAND, xt as getHotkeyById, y as HOVER_OUT_LINK_COMMAND, yt as init_plugin } from "./style-
|
|
2
|
-
import { A as
|
|
3
|
-
import { S as DiffNode, _ as PlaceholderNode, a as styles$
|
|
1
|
+
import { $ as DOM_TEXT_TYPE, A as $createCodeMirrorNode, At as createDebugLogger, B as Editor, C as $createCodeNode$1, Ct as CONTROL_OR_META, Dt as KeyEnum, E as CodeNode$1, Et as HotkeyScopeEnum, F as $isCursorNode, Ft as init_debug, G as kernel_exports, Gt as INodeHelper, H as DataSource, I as CardLikeElementNode, It as prodSafeLogger, J as $getNearestNodeFromDOMNode, K as $closest, Kt as init_helper, M as CodeMirrorNode, Mt as debugLoggers, N as $createCursorNode, Nt as debug_exports, Ot as init_hotkey, P as $isCardLikeElementNode, Pt as devConsole, Q as DOM_ELEMENT_TYPE, R as cursorNodeSerialized, S as formatUrl, St as init_registerHotkey, Tt as HotkeyEnum, U as Kernel, V as resetRandomKey, W as init_kernel, X as DOM_DOCUMENT_FRAGMENT_TYPE, Y as $getNodeFromDOMNode, Yt as __toCommonJS, Z as DOM_DOCUMENT_TYPE, _ as AutoLinkNode, _t as unregisterEditorKernel, a as $createMathBlockNode, at as generateEditorId, b as LinkNode, bt as HOVER_COMMAND, c as MathBlockNode, ct as getNodeKeyFromDOMNode, dt as isDOMNode, et as EDITOR_THEME_KEY, f as LinkHighlightNode, ft as isDocumentFragment, g as $toggleLink, gt as registerEditorKernel, h as $isLinkNode, ht as reconcileDecorator, it as genServiceId, j as $isCodeMirrorNode, jt as debugLogger, kt as browserDebug, l as MathInlineNode, lt as getParentElement, m as $createLinkNode, mt as noop, nt as compareNodeOrder, o as $createMathInlineNode, ot as getKernelFromEditor, pt as moment, q as $closestNodeType, rt as createEmptyEditorState, s as $isMathNode, st as getKernelFromEditorConfig, tt as assert, u as $createLinkHighlightNode, ut as init_utils, v as HOVER_LINK_COMMAND, vt as KernelPlugin, wt as init_sys, x as TOGGLE_LINK_COMMAND, xt as getHotkeyById, y as HOVER_OUT_LINK_COMMAND, yt as init_plugin } from "./style-DjwW7ClE.js";
|
|
2
|
+
import { $ as LexicalErrorBoundary, A as MarkdownPlugin, B as ILitexmlService, C as INSERT_CODEINLINE_COMMAND, D as CommonPlugin, E as ReactEditorContent, F as MARKDOWN_READER_LEVEL_NORMAL, G as $parseSerializedNodeImpl, H as INodePlugin, I as MARKDOWN_WRITER_LEVEL_MAX, J as INSERT_HEADING_COMMAND, K as charToId, L as GET_MARKDOWN_SELECTION_COMMAND, M as detectLanguage, N as IMarkdownShortCutService, O as ReactMarkdownPlugin, P as MARKDOWN_READER_LEVEL_HIGH, Q as useLexicalComposerContext, R as INSERT_MARKDOWN_COMMAND, T as ReactPlainText, U as INodeService, V as LitexmlService, W as $cloneNode, X as useLexicalEditor, Y as INSERT_QUOTE_COMMAND, Z as ReactEditor, _ as INSERT_CHECK_LIST_COMMAND, a as ReactMentionPlugin, b as getSelectedNode, c as INSERT_LINK_HIGHLIGHT_COMMAND, d as bundledLanguagesInfo, f as CodeblockPlugin, g as getCodeLanguageByInput, h as IBlockMenuService, i as SlashPlugin, j as detectCodeLanguage, k as useTranslation, l as registerLinkHighlightCommand, m as BlockMenuService, n as ReactSlashOption, o as MentionPlugin, p as UPDATE_CODEBLOCK_LANG, q as idToChar, r as SlashMenu, s as INSERT_MENTION_COMMAND, t as ReactSlashPlugin, u as useLexicalNodeSelection, v as registerCheckList, w as registerCodeInlineCommand, x as sanitizeUrl, y as extractUrlFromText, z as isPunctuationChar } from "./ReactSlashPlugin-DkEXwDgH.js";
|
|
3
|
+
import { S as DiffNode, _ as PlaceholderNode, a as styles$17, b as HorizontalRuleNode, c as ImageNode, d as BlockImageNode, f as styles$16, g as PlaceholderBlockNode, h as FileNode, i as imageBroken, l as $createBlockImageNode, m as $isFileNode, n as styles$19, o as $createImageNode, p as $createFileNode, r as styles$18, s as $isImageNode, t as styles$20, u as $isBlockImageNode, v as $createHorizontalRuleNode, x as $createDiffNode, y as $isHorizontalRuleNode } from "./style-DejqW6OX.js";
|
|
4
4
|
import { $computeTableMapSkipCellCheck, $createTableNodeWithDimensions, $createTableSelection, $deleteTableColumnAtSelection, $deleteTableRowAtSelection, $findTableNode, $getElementForTableNode, $getNodeTriplet, $getTableAndElementByKey, $getTableCellNodeFromLexicalNode, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $insertTableColumnAtSelection, $insertTableRowAtSelection, $isTableCellNode, $isTableNode, $isTableRowNode, $isTableSelection, $mergeCells, $unmergeCell, TableCellHeaderStates, TableCellNode, TableNode, TableNode as TableNode$1, TableRowNode, getDOMCellFromTarget, getTableElement, getTableObserverFromTableElement, registerTableCellUnmergeTransform, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive } from "@lexical/table";
|
|
5
5
|
import { debounce } from "es-toolkit/compat";
|
|
6
6
|
import EventEmitter from "eventemitter3";
|
|
7
|
-
import { $createNodeSelection, $createParagraphNode, $createRangeSelection, $createTextNode, $getNearestNodeFromDOMNode as $getNearestNodeFromDOMNode$1, $getNodeByKey, $getPreviousSelection, $getRoot, $getSelection, $insertNodes, $isBlockElementNode, $isDecoratorNode, $isElementNode, $isNodeSelection, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isTextNode, $nodesOfType, $normalizeSelection__EXPERIMENTAL, $setSelection, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, DROP_COMMAND, HISTORY_MERGE_TAG, INDENT_CONTENT_COMMAND, INSERT_TAB_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, SELECTION_CHANGE_COMMAND, SKIP_SCROLL_INTO_VIEW_TAG, TabNode, TextNode, createCommand, getDOMSelection, getDOMSelectionFromTarget, isHTMLElement, isModifierMatch } from "lexical";
|
|
7
|
+
import { $createNodeSelection, $createParagraphNode, $createRangeSelection, $createTextNode, $getNearestNodeFromDOMNode as $getNearestNodeFromDOMNode$1, $getNodeByKey, $getPreviousSelection, $getRoot, $getSelection, $insertNodes, $isBlockElementNode, $isDecoratorNode, $isElementNode, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isTextNode, $nodesOfType, $normalizeSelection__EXPERIMENTAL, $setSelection, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, DROP_COMMAND, HISTORY_MERGE_TAG, INDENT_CONTENT_COMMAND, INSERT_TAB_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, SELECTION_CHANGE_COMMAND, SKIP_SCROLL_INTO_VIEW_TAG, TabNode, TextNode, createCommand, getDOMSelection, getDOMSelectionFromTarget, isHTMLElement, isModifierMatch } from "lexical";
|
|
8
8
|
import { DRAG_DROP_PASTE } from "@lexical/rich-text";
|
|
9
9
|
import { $filter, $findMatchingParent, $getNearestBlockElementAncestorOrThrow, $getNearestNodeOfType, $insertNodeToNearestRoot, $wrapNodeInElement, addClassNamesToElement, calculateZoomLevel, mergeRegister, removeClassNamesFromElement } from "@lexical/utils";
|
|
10
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -15,9 +15,9 @@ import katex, { renderToString } from "katex";
|
|
|
15
15
|
import { $isCodeHighlightNode, $isCodeNode, CodeHighlightNode, CodeNode } from "@lexical/code-core";
|
|
16
16
|
import { ActionIcon, ActionIconGroup, Block, Button, Center, Dropdown, Flexbox, Hotkey, Icon, Input, InputNumber, LOBE_THEME_APP_ID, MaterialFileTypeIcon, Popover, Select, Text, TextArea } from "@lobehub/ui";
|
|
17
17
|
import { createStaticStyles, cssVar, cx, useThemeMode } from "antd-style";
|
|
18
|
-
import { BaselineIcon, Check, ChevronDown, ChevronRight, CopyIcon, EditIcon, ExternalLinkIcon, Grid2X2XIcon, LinkIcon, LoaderCircleIcon, MoreHorizontalIcon, PanelBottomCloseIcon, PanelLeftCloseIcon, PanelRightCloseIcon, PanelTopCloseIcon, PlusIcon, TableColumnsSplitIcon, TableRowsSplitIcon, UnlinkIcon, UploadIcon, X } from "lucide-react";
|
|
18
|
+
import { BaselineIcon, Check, ChevronDown, ChevronRight, CopyIcon, EditIcon, ExternalLinkIcon, Grid2X2XIcon, GripVerticalIcon, LinkIcon, LoaderCircleIcon, MoreHorizontalIcon, PanelBottomCloseIcon, PanelLeftCloseIcon, PanelRightCloseIcon, PanelTopCloseIcon, PlusIcon, TableColumnsSplitIcon, TableRowsSplitIcon, UnlinkIcon, UploadIcon, X } from "lucide-react";
|
|
19
19
|
import { createPortal } from "react-dom";
|
|
20
|
-
import { Switch, message } from "antd";
|
|
20
|
+
import { Button as Button$1, Dropdown as Dropdown$1, Switch, message, theme } from "antd";
|
|
21
21
|
import { computePosition, flip, offset, shift } from "@floating-ui/dom";
|
|
22
22
|
//#region src/editor-kernel/react/PortalContainer.tsx
|
|
23
23
|
const LexicalPortalContainer = forwardRef(({ editor, node, children }, ref) => {
|
|
@@ -46,7 +46,7 @@ init_helper();
|
|
|
46
46
|
init_hotkey();
|
|
47
47
|
init_plugin();
|
|
48
48
|
init_debug();
|
|
49
|
-
const logger$
|
|
49
|
+
const logger$9 = createDebugLogger("plugin", "litexml");
|
|
50
50
|
function toArrayXml(litexml) {
|
|
51
51
|
return Array.isArray(litexml) ? litexml : [litexml];
|
|
52
52
|
}
|
|
@@ -58,7 +58,7 @@ function tryParseChild(child, editor) {
|
|
|
58
58
|
oldNode
|
|
59
59
|
};
|
|
60
60
|
} catch (error) {
|
|
61
|
-
logger$
|
|
61
|
+
logger$9.error("❌ Error parsing child node:", error);
|
|
62
62
|
return {
|
|
63
63
|
newNode: null,
|
|
64
64
|
oldNode: null
|
|
@@ -171,12 +171,12 @@ function registerLiteXMLCommand(editor, dataSource) {
|
|
|
171
171
|
delay: true
|
|
172
172
|
}, dataSource);
|
|
173
173
|
break;
|
|
174
|
-
default: logger$
|
|
174
|
+
default: logger$9.warn(`⚠️ Unknown action type: ${action}`);
|
|
175
175
|
}
|
|
176
176
|
});
|
|
177
177
|
return false;
|
|
178
178
|
} catch (error) {
|
|
179
|
-
logger$
|
|
179
|
+
logger$9.error("❌ Error processing LITEXML_MODIFY_COMMAND:", error);
|
|
180
180
|
return false;
|
|
181
181
|
}
|
|
182
182
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(LITEXML_APPLY_COMMAND, (payload) => {
|
|
@@ -201,9 +201,9 @@ function handleModify(editor, dataSource, arrayXml, delay) {
|
|
|
201
201
|
try {
|
|
202
202
|
const { oldNode, newNode } = tryParseChild(child, editor);
|
|
203
203
|
if (oldNode && newNode) handleReplaceForApplyDelay(oldNode, newNode, modifyBlockNodes, diffNodeMap, editor);
|
|
204
|
-
else logger$
|
|
204
|
+
else logger$9.warn(`⚠️ Node with key ${child.id} not found for diffing.`);
|
|
205
205
|
} catch (error) {
|
|
206
|
-
logger$
|
|
206
|
+
logger$9.error("❌ Error replacing node:", error);
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
});
|
|
@@ -227,7 +227,7 @@ function handleModify(editor, dataSource, arrayXml, delay) {
|
|
|
227
227
|
} else prevNode = prevNode.insertAfter(newNode);
|
|
228
228
|
else $insertNodes([newNode]);
|
|
229
229
|
} catch (error) {
|
|
230
|
-
logger$
|
|
230
|
+
logger$9.error("❌ Error replacing node:", error);
|
|
231
231
|
}
|
|
232
232
|
});
|
|
233
233
|
});
|
|
@@ -364,7 +364,7 @@ function handleInsert(editor, payload, dataSource) {
|
|
|
364
364
|
});
|
|
365
365
|
}
|
|
366
366
|
} catch (error) {
|
|
367
|
-
logger$
|
|
367
|
+
logger$9.error("❌ Error inserting node:", error);
|
|
368
368
|
}
|
|
369
369
|
});
|
|
370
370
|
}
|
|
@@ -474,7 +474,7 @@ ReactNodePlugin.displayName = "ReactNodePlugin";
|
|
|
474
474
|
//#endregion
|
|
475
475
|
//#region src/plugins/litexml/data-source/litexml-data-source.ts
|
|
476
476
|
init_debug();
|
|
477
|
-
const logger$
|
|
477
|
+
const logger$8 = createDebugLogger("plugin", "litexml");
|
|
478
478
|
var IXmlWriterContext = class {
|
|
479
479
|
createXmlNode(tagName, attributes, textContent) {
|
|
480
480
|
return {
|
|
@@ -502,7 +502,7 @@ var LitexmlDataSource = class extends DataSource {
|
|
|
502
502
|
const xml = this.parseXMLString(litexml);
|
|
503
503
|
const inode = this.xmlToLexical(xml);
|
|
504
504
|
this.getService?.(INodeService)?.processNodeTree(inode);
|
|
505
|
-
logger$
|
|
505
|
+
logger$8.debug("Parsed XML to Lexical State:", inode);
|
|
506
506
|
return inode;
|
|
507
507
|
}
|
|
508
508
|
/**
|
|
@@ -523,7 +523,7 @@ var LitexmlDataSource = class extends DataSource {
|
|
|
523
523
|
});
|
|
524
524
|
editor.setEditorState(newState);
|
|
525
525
|
} catch (error) {
|
|
526
|
-
logger$
|
|
526
|
+
logger$8.error("Failed to parse XML:", error);
|
|
527
527
|
throw error;
|
|
528
528
|
}
|
|
529
529
|
}
|
|
@@ -558,7 +558,7 @@ var LitexmlDataSource = class extends DataSource {
|
|
|
558
558
|
return this.lexicalToXML(rootNode);
|
|
559
559
|
});
|
|
560
560
|
} catch (error) {
|
|
561
|
-
logger$
|
|
561
|
+
logger$8.error("Failed to export to XML:", error);
|
|
562
562
|
throw error;
|
|
563
563
|
}
|
|
564
564
|
}
|
|
@@ -873,7 +873,7 @@ const LitexmlPlugin = class extends KernelPlugin {
|
|
|
873
873
|
};
|
|
874
874
|
//#endregion
|
|
875
875
|
//#region src/plugins/litexml/react/DiffNodeToolbar/style.ts
|
|
876
|
-
const styles$
|
|
876
|
+
const styles$15 = createStaticStyles(({ css, cssVar }) => ({
|
|
877
877
|
accept: css`
|
|
878
878
|
color: ${cssVar.colorSuccess};
|
|
879
879
|
`,
|
|
@@ -902,7 +902,7 @@ const ReactDiffNodeToolbar = ({ editor, node }) => {
|
|
|
902
902
|
editor,
|
|
903
903
|
node,
|
|
904
904
|
children: /* @__PURE__ */ jsxs(Block, {
|
|
905
|
-
className: isDarkMode ? styles$
|
|
905
|
+
className: isDarkMode ? styles$15.toolbarDark : styles$15.toolbarLight,
|
|
906
906
|
gap: 2,
|
|
907
907
|
horizontal: true,
|
|
908
908
|
padding: 2,
|
|
@@ -910,7 +910,7 @@ const ReactDiffNodeToolbar = ({ editor, node }) => {
|
|
|
910
910
|
variant: "outlined",
|
|
911
911
|
children: [/* @__PURE__ */ jsx(ActionIcon, {
|
|
912
912
|
"aria-label": "Reject change",
|
|
913
|
-
className: styles$
|
|
913
|
+
className: styles$15.reject,
|
|
914
914
|
danger: true,
|
|
915
915
|
icon: X,
|
|
916
916
|
onClick: () => {
|
|
@@ -926,7 +926,7 @@ const ReactDiffNodeToolbar = ({ editor, node }) => {
|
|
|
926
926
|
title: t("modifier.reject")
|
|
927
927
|
}), /* @__PURE__ */ jsx(ActionIcon, {
|
|
928
928
|
"aria-label": "Accept change",
|
|
929
|
-
className: styles$
|
|
929
|
+
className: styles$15.accept,
|
|
930
930
|
icon: Check,
|
|
931
931
|
onClick: () => {
|
|
932
932
|
editor.dispatchCommand(LITEXML_DIFFNODE_COMMAND, {
|
|
@@ -946,7 +946,7 @@ const ReactDiffNodeToolbar = ({ editor, node }) => {
|
|
|
946
946
|
ReactDiffNodeToolbar.displayName = "ReactDiffNodeToolbar";
|
|
947
947
|
//#endregion
|
|
948
948
|
//#region src/plugins/litexml/react/style.ts
|
|
949
|
-
const styles$
|
|
949
|
+
const styles$14 = createStaticStyles(({ css, cssVar }) => css`
|
|
950
950
|
position: relative;
|
|
951
951
|
|
|
952
952
|
.toolbar {
|
|
@@ -1077,7 +1077,7 @@ const ReactLiteXmlPlugin = () => {
|
|
|
1077
1077
|
editor,
|
|
1078
1078
|
node
|
|
1079
1079
|
}),
|
|
1080
|
-
theme: styles$
|
|
1080
|
+
theme: styles$14
|
|
1081
1081
|
});
|
|
1082
1082
|
}, [editor]);
|
|
1083
1083
|
return null;
|
|
@@ -2274,8 +2274,6 @@ function createHeadlessEditor(options) {
|
|
|
2274
2274
|
init_plugin();
|
|
2275
2275
|
init_debug();
|
|
2276
2276
|
const AUTO_COMPLETE_GUARD_LIMIT = 5e4;
|
|
2277
|
-
const CLEAR_PLACEHOLDER_BURST_LIMIT = 20;
|
|
2278
|
-
const CLEAR_PLACEHOLDER_BURST_WINDOW_MS = 1e3;
|
|
2279
2277
|
const AutoCompletePlugin = class extends KernelPlugin {
|
|
2280
2278
|
static {
|
|
2281
2279
|
this.pluginName = "AutoCompletePlugin";
|
|
@@ -2288,11 +2286,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2288
2286
|
this.lastCursorPosition = null;
|
|
2289
2287
|
this.cursorStableTimer = null;
|
|
2290
2288
|
this.abortController = null;
|
|
2291
|
-
this.placeholderNodes = [];
|
|
2292
2289
|
this.currentSuggestion = null;
|
|
2290
|
+
this.placeholderAnchorPosition = null;
|
|
2291
|
+
this.placeholderSelectionSnapshot = null;
|
|
2293
2292
|
this.markdownService = null;
|
|
2294
2293
|
this.skipNextTextContentListener = false;
|
|
2295
|
-
this.clearPlaceholderCallTimestamps = [];
|
|
2296
2294
|
this.delay = config?.delay ?? 1e3;
|
|
2297
2295
|
kernel.registerNodes([PlaceholderNode, PlaceholderBlockNode]);
|
|
2298
2296
|
if (config?.theme) kernel.registerThemes(config?.theme);
|
|
@@ -2307,13 +2305,13 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2307
2305
|
editorState.read(() => {
|
|
2308
2306
|
if (editor.isComposing()) {
|
|
2309
2307
|
this.clearTimer();
|
|
2310
|
-
this.clearPlaceholderNodes(editor);
|
|
2308
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2311
2309
|
return;
|
|
2312
2310
|
}
|
|
2313
2311
|
const selection = $getSelection();
|
|
2314
2312
|
if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
2315
2313
|
this.clearTimer();
|
|
2316
|
-
this.clearPlaceholderNodes(editor);
|
|
2314
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2317
2315
|
return;
|
|
2318
2316
|
}
|
|
2319
2317
|
const currentPosition = {
|
|
@@ -2323,7 +2321,7 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2323
2321
|
};
|
|
2324
2322
|
if (this.hasPositionChanged(currentPosition)) {
|
|
2325
2323
|
this.clearTimer();
|
|
2326
|
-
this.clearPlaceholderNodes(editor);
|
|
2324
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2327
2325
|
this.abortController = new AbortController();
|
|
2328
2326
|
this.cursorStableTimer = window.setTimeout(() => {
|
|
2329
2327
|
this.handleCursorStable(editor, currentPosition);
|
|
@@ -2339,11 +2337,24 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2339
2337
|
}
|
|
2340
2338
|
return false;
|
|
2341
2339
|
}, COMMAND_PRIORITY_HIGH));
|
|
2340
|
+
this.register(editor.registerCommand(KEY_ARROW_LEFT_COMMAND, () => {
|
|
2341
|
+
if (this.currentSuggestion) {
|
|
2342
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2343
|
+
return false;
|
|
2344
|
+
}
|
|
2345
|
+
return false;
|
|
2346
|
+
}, COMMAND_PRIORITY_CRITICAL));
|
|
2347
|
+
this.register(editor.registerCommand(KEY_ARROW_RIGHT_COMMAND, () => {
|
|
2348
|
+
if (this.currentSuggestion) {
|
|
2349
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2350
|
+
return false;
|
|
2351
|
+
}
|
|
2352
|
+
return false;
|
|
2353
|
+
}, COMMAND_PRIORITY_CRITICAL));
|
|
2342
2354
|
this.register(editor.registerCommand(KEY_ESCAPE_COMMAND, (event) => {
|
|
2343
2355
|
if (this.currentSuggestion) {
|
|
2344
2356
|
event?.preventDefault();
|
|
2345
2357
|
this.clearPlaceholderNodes(editor);
|
|
2346
|
-
this.currentSuggestion = null;
|
|
2347
2358
|
return true;
|
|
2348
2359
|
}
|
|
2349
2360
|
return false;
|
|
@@ -2353,7 +2364,7 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2353
2364
|
this.skipNextTextContentListener = false;
|
|
2354
2365
|
return;
|
|
2355
2366
|
}
|
|
2356
|
-
if (this.currentSuggestion) this.clearPlaceholderNodes(editor);
|
|
2367
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2357
2368
|
}));
|
|
2358
2369
|
}
|
|
2359
2370
|
hasPositionChanged(currentPosition) {
|
|
@@ -2371,7 +2382,7 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2371
2382
|
editor.getEditorState().read(() => {
|
|
2372
2383
|
if (editor.isComposing()) {
|
|
2373
2384
|
this.clearTimer();
|
|
2374
|
-
this.clearPlaceholderNodes(editor);
|
|
2385
|
+
if (this.currentSuggestion) this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2375
2386
|
return;
|
|
2376
2387
|
}
|
|
2377
2388
|
if (!this.abortController || this.abortController.signal.aborted) return;
|
|
@@ -2386,9 +2397,8 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2386
2397
|
if (this.lastCursorPosition && this.isSamePosition(position, this.lastCursorPosition)) return;
|
|
2387
2398
|
this.lastCursorPosition = currentPosition;
|
|
2388
2399
|
const anchorNode = selection.anchor.getNode();
|
|
2389
|
-
let selectionType = "unknown";
|
|
2390
2400
|
const textRet = this.getTextBeforeCursor(selection);
|
|
2391
|
-
selectionType = anchorNode.getType();
|
|
2401
|
+
const selectionType = anchorNode.getType();
|
|
2392
2402
|
if (this.config?.onAutoComplete) this.config.onAutoComplete({
|
|
2393
2403
|
abortSignal: this.abortController.signal,
|
|
2394
2404
|
afterText: textRet.textAfter,
|
|
@@ -2401,11 +2411,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2401
2411
|
currentSelection = $getSelection();
|
|
2402
2412
|
});
|
|
2403
2413
|
if (editor.isComposing()) {
|
|
2404
|
-
this.clearPlaceholderNodes(editor);
|
|
2414
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2405
2415
|
return;
|
|
2406
2416
|
}
|
|
2407
2417
|
if (!currentSelection || !$isRangeSelection(currentSelection) || !currentSelection.isCollapsed()) {
|
|
2408
|
-
this.clearPlaceholderNodes(editor);
|
|
2418
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2409
2419
|
return;
|
|
2410
2420
|
}
|
|
2411
2421
|
const newPosition = {
|
|
@@ -2414,11 +2424,12 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2414
2424
|
type: currentSelection.anchor.type
|
|
2415
2425
|
};
|
|
2416
2426
|
if (!this.isSamePosition(currentPosition, newPosition)) {
|
|
2417
|
-
this.clearPlaceholderNodes(editor);
|
|
2427
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2418
2428
|
return;
|
|
2419
2429
|
}
|
|
2420
2430
|
if (result) {
|
|
2421
2431
|
this.currentSuggestion = result;
|
|
2432
|
+
this.placeholderAnchorPosition = currentPosition;
|
|
2422
2433
|
this.showPlaceholderNodes(editor, result);
|
|
2423
2434
|
this.logger.debug("🔍 Auto-complete triggered:", {
|
|
2424
2435
|
afterText: textRet.textAfter,
|
|
@@ -2427,15 +2438,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2427
2438
|
result,
|
|
2428
2439
|
selectionType
|
|
2429
2440
|
});
|
|
2430
|
-
} else this.clearPlaceholderNodes(editor);
|
|
2441
|
+
} else this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2431
2442
|
});
|
|
2432
2443
|
});
|
|
2433
2444
|
}
|
|
2434
2445
|
getTextBeforeCursor(selection) {
|
|
2435
|
-
const ret = {
|
|
2436
|
-
textAfter: "",
|
|
2437
|
-
textBefore: ""
|
|
2438
|
-
};
|
|
2439
2446
|
const anchorNode = selection.anchor.getNode();
|
|
2440
2447
|
const anchorOffset = selection.anchor.offset;
|
|
2441
2448
|
let paragraphNode = anchorNode;
|
|
@@ -2447,7 +2454,10 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2447
2454
|
if (!parent) break;
|
|
2448
2455
|
paragraphNode = parent;
|
|
2449
2456
|
}
|
|
2450
|
-
if (!paragraphNode) return
|
|
2457
|
+
if (!paragraphNode) return {
|
|
2458
|
+
textAfter: "",
|
|
2459
|
+
textBefore: ""
|
|
2460
|
+
};
|
|
2451
2461
|
this.logger.debug("🔍 Paragraph Node Type:", paragraphNode, anchorNode);
|
|
2452
2462
|
let founded = false;
|
|
2453
2463
|
let recursionDepth = 0;
|
|
@@ -2503,6 +2513,8 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2503
2513
|
this.logger.warn("⚠️ No valid markdown service for placeholder");
|
|
2504
2514
|
return;
|
|
2505
2515
|
}
|
|
2516
|
+
for (const node of $nodesOfType(PlaceholderNode)) node.remove();
|
|
2517
|
+
for (const node of $nodesOfType(PlaceholderBlockNode)) node.remove();
|
|
2506
2518
|
const nodes = this.markdownService.parseMarkdownToLexical(suggestion);
|
|
2507
2519
|
if (nodes.children[0]) {
|
|
2508
2520
|
const firstChild = nodes.children[0];
|
|
@@ -2519,28 +2531,31 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2519
2531
|
};
|
|
2520
2532
|
}
|
|
2521
2533
|
const saveSel = selection.clone();
|
|
2534
|
+
this.placeholderSelectionSnapshot = saveSel;
|
|
2522
2535
|
this.markdownService.insertIRootNode(editor, nodes, selection);
|
|
2523
2536
|
$setSelection(saveSel);
|
|
2524
2537
|
});
|
|
2525
2538
|
}
|
|
2526
|
-
clearPlaceholderNodes(editor) {
|
|
2527
|
-
const
|
|
2528
|
-
|
|
2529
|
-
if (this.clearPlaceholderCallTimestamps.length >= CLEAR_PLACEHOLDER_BURST_LIMIT) return;
|
|
2530
|
-
this.clearPlaceholderCallTimestamps.push(now);
|
|
2531
|
-
this.skipNextTextContentListener = true;
|
|
2539
|
+
clearPlaceholderNodes(editor, options) {
|
|
2540
|
+
const shouldRestoreSelection = options?.restoreSelection ?? true;
|
|
2541
|
+
const restoreSelection = this.placeholderSelectionSnapshot;
|
|
2532
2542
|
this.currentSuggestion = null;
|
|
2533
|
-
this.
|
|
2543
|
+
this.placeholderAnchorPosition = null;
|
|
2544
|
+
this.placeholderSelectionSnapshot = null;
|
|
2545
|
+
this.clearTimer();
|
|
2546
|
+
let hasPlaceholderNodes = false;
|
|
2547
|
+
editor.getEditorState().read(() => {
|
|
2548
|
+
hasPlaceholderNodes = $nodesOfType(PlaceholderNode).length > 0 || $nodesOfType(PlaceholderBlockNode).length > 0;
|
|
2549
|
+
});
|
|
2550
|
+
if (!hasPlaceholderNodes && !(shouldRestoreSelection && restoreSelection)) {
|
|
2551
|
+
this.skipNextTextContentListener = false;
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
this.skipNextTextContentListener = true;
|
|
2534
2555
|
editor.update(() => {
|
|
2535
|
-
const
|
|
2536
|
-
const
|
|
2537
|
-
|
|
2538
|
-
editor.getEditorState()._nodeMap.forEach((node) => {
|
|
2539
|
-
iterCount++;
|
|
2540
|
-
if (iterCount > AUTO_COMPLETE_GUARD_LIMIT) throw new Error(`clearPlaceholderNodes: forEach loop > ${AUTO_COMPLETE_GUARD_LIMIT} iterations`);
|
|
2541
|
-
if (node.isAttached() && ["PlaceholderBlock", "PlaceholderInline"].includes(node.getType())) node.remove();
|
|
2542
|
-
});
|
|
2543
|
-
if (clonedSelection) $setSelection(clonedSelection);
|
|
2556
|
+
for (const node of $nodesOfType(PlaceholderNode)) node.remove();
|
|
2557
|
+
for (const node of $nodesOfType(PlaceholderBlockNode)) node.remove();
|
|
2558
|
+
if (shouldRestoreSelection && restoreSelection) $setSelection(restoreSelection);
|
|
2544
2559
|
});
|
|
2545
2560
|
}
|
|
2546
2561
|
applySuggestion(editor) {
|
|
@@ -2549,13 +2564,11 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2549
2564
|
editor.update(() => {
|
|
2550
2565
|
const selection = $getSelection();
|
|
2551
2566
|
if (!$isRangeSelection(selection) || !selection.isCollapsed() || !this.markdownService) return;
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
});
|
|
2567
|
+
for (const node of $nodesOfType(PlaceholderNode)) node.remove();
|
|
2568
|
+
for (const node of $nodesOfType(PlaceholderBlockNode)) node.remove();
|
|
2555
2569
|
const nodes = this.markdownService.parseMarkdownToLexical(markdown);
|
|
2556
2570
|
this.markdownService.insertIRootNode(editor, nodes, selection);
|
|
2557
|
-
this.clearPlaceholderNodes(editor);
|
|
2558
|
-
this.currentSuggestion = null;
|
|
2571
|
+
this.clearPlaceholderNodes(editor, { restoreSelection: false });
|
|
2559
2572
|
});
|
|
2560
2573
|
}
|
|
2561
2574
|
isSamePosition(pos1, pos2) {
|
|
@@ -2563,13 +2576,12 @@ const AutoCompletePlugin = class extends KernelPlugin {
|
|
|
2563
2576
|
}
|
|
2564
2577
|
destroy() {
|
|
2565
2578
|
this.clearTimer();
|
|
2566
|
-
this.placeholderNodes = [];
|
|
2567
2579
|
super.destroy();
|
|
2568
2580
|
}
|
|
2569
2581
|
};
|
|
2570
2582
|
//#endregion
|
|
2571
2583
|
//#region src/plugins/auto-complete/react/style.ts
|
|
2572
|
-
const styles$
|
|
2584
|
+
const styles$13 = createStaticStyles(({ css }) => ({
|
|
2573
2585
|
placeholderBlock: css`
|
|
2574
2586
|
opacity: 0.4;
|
|
2575
2587
|
`,
|
|
@@ -2586,8 +2598,8 @@ const ReactAutoCompletePlugin = ({ onAutoComplete, delay }) => {
|
|
|
2586
2598
|
delay,
|
|
2587
2599
|
onAutoComplete,
|
|
2588
2600
|
theme: {
|
|
2589
|
-
placeholderBlock: cx(styles$
|
|
2590
|
-
placeholderInline: cx(styles$
|
|
2601
|
+
placeholderBlock: cx(styles$13.placeholderBlock),
|
|
2602
|
+
placeholderInline: cx(styles$13.placeholderInline)
|
|
2591
2603
|
}
|
|
2592
2604
|
});
|
|
2593
2605
|
}, []);
|
|
@@ -2595,6 +2607,1119 @@ const ReactAutoCompletePlugin = ({ onAutoComplete, delay }) => {
|
|
|
2595
2607
|
};
|
|
2596
2608
|
ReactAutoCompletePlugin.displayName = "ReactAutoCompletePlugin";
|
|
2597
2609
|
//#endregion
|
|
2610
|
+
//#region src/plugins/block/command/index.ts
|
|
2611
|
+
init_debug();
|
|
2612
|
+
const MOVE_BLOCK_COMMAND = createCommand("MOVE_BLOCK_COMMAND");
|
|
2613
|
+
const logger$7 = createDebugLogger("plugin", "block-command");
|
|
2614
|
+
const getListParent = (node) => {
|
|
2615
|
+
if (!node) return null;
|
|
2616
|
+
const parent = node.getParent();
|
|
2617
|
+
return $isListNode(parent) ? parent : null;
|
|
2618
|
+
};
|
|
2619
|
+
const getTopListContextFromItem = (item) => {
|
|
2620
|
+
let currentItem = item;
|
|
2621
|
+
let currentList = getListParent(item);
|
|
2622
|
+
while (currentList && $isListItemNode(currentList.getParent())) {
|
|
2623
|
+
currentItem = currentList.getParent();
|
|
2624
|
+
currentList = getListParent(currentItem);
|
|
2625
|
+
}
|
|
2626
|
+
return {
|
|
2627
|
+
item: currentItem,
|
|
2628
|
+
list: currentList
|
|
2629
|
+
};
|
|
2630
|
+
};
|
|
2631
|
+
const cloneListTail = (listNode, tailStart, fallbackStartValue) => {
|
|
2632
|
+
if (!tailStart) return null;
|
|
2633
|
+
const newListNode = $createListNode(listNode.getListType(), fallbackStartValue);
|
|
2634
|
+
let current = tailStart;
|
|
2635
|
+
while (current) {
|
|
2636
|
+
const nextSibling = current.getNextSibling();
|
|
2637
|
+
current.remove();
|
|
2638
|
+
newListNode.append(current);
|
|
2639
|
+
current = nextSibling;
|
|
2640
|
+
}
|
|
2641
|
+
return newListNode;
|
|
2642
|
+
};
|
|
2643
|
+
const alignListItemDepth = (item, target) => {
|
|
2644
|
+
const targetWithIndent = target;
|
|
2645
|
+
const itemWithIndent = item;
|
|
2646
|
+
if (typeof targetWithIndent.getIndent === "function" && typeof itemWithIndent.setIndent === "function") itemWithIndent.setIndent(targetWithIndent.getIndent());
|
|
2647
|
+
};
|
|
2648
|
+
const cleanupEmptyListForItem = (listItem) => {
|
|
2649
|
+
const parentList = getListParent(listItem);
|
|
2650
|
+
if (parentList && parentList.getChildrenSize() === 0) parentList.remove();
|
|
2651
|
+
};
|
|
2652
|
+
const moveBlockNode = (payload) => {
|
|
2653
|
+
logger$7.debug("start", payload);
|
|
2654
|
+
const sourceNode = $getNodeByKey(payload.sourceBlockId);
|
|
2655
|
+
const targetNode = $getNodeByKey(payload.targetBlockId);
|
|
2656
|
+
if (!sourceNode || !targetNode) {
|
|
2657
|
+
logger$7.debug("abort: node-not-found", {
|
|
2658
|
+
sourceFound: Boolean(sourceNode),
|
|
2659
|
+
targetFound: Boolean(targetNode)
|
|
2660
|
+
});
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2663
|
+
if (sourceNode === targetNode) {
|
|
2664
|
+
logger$7.debug("abort: source-equals-target");
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2667
|
+
if (!$isListItemNode(targetNode)) {
|
|
2668
|
+
const sourceIsListItem = $isListItemNode(sourceNode);
|
|
2669
|
+
let movingNode = sourceNode;
|
|
2670
|
+
logger$7.debug("branch: normal-block-target", {
|
|
2671
|
+
placement: payload.placement,
|
|
2672
|
+
targetType: targetNode.getType()
|
|
2673
|
+
});
|
|
2674
|
+
if (sourceIsListItem) {
|
|
2675
|
+
const sourceListItem = sourceNode;
|
|
2676
|
+
const paragraphNode = $createParagraphNode();
|
|
2677
|
+
paragraphNode.append(...sourceListItem.getChildren());
|
|
2678
|
+
sourceListItem.remove();
|
|
2679
|
+
cleanupEmptyListForItem(sourceListItem);
|
|
2680
|
+
movingNode = paragraphNode;
|
|
2681
|
+
logger$7.debug("convert: listItem-to-paragraph", { sourceType: sourceNode.getType() });
|
|
2682
|
+
}
|
|
2683
|
+
if (payload.placement === "before") targetNode.insertBefore(movingNode);
|
|
2684
|
+
else targetNode.insertAfter(movingNode);
|
|
2685
|
+
logger$7.debug("done: normal-block-target");
|
|
2686
|
+
return;
|
|
2687
|
+
}
|
|
2688
|
+
const targetListItem = targetNode;
|
|
2689
|
+
const sourceIsListItem = $isListItemNode(sourceNode);
|
|
2690
|
+
const sourceIsParagraph = $isParagraphNode(sourceNode);
|
|
2691
|
+
if (sourceIsListItem || sourceIsParagraph) {
|
|
2692
|
+
logger$7.debug("branch: list-insert-with-item-or-paragraph", {
|
|
2693
|
+
sourceIsListItem,
|
|
2694
|
+
sourceIsParagraph,
|
|
2695
|
+
targetType: targetListItem.getType()
|
|
2696
|
+
});
|
|
2697
|
+
let movingListItem;
|
|
2698
|
+
if (sourceIsListItem) movingListItem = sourceNode;
|
|
2699
|
+
else {
|
|
2700
|
+
const sourceParagraph = sourceNode;
|
|
2701
|
+
const targetListType = getListParent(targetListItem)?.getListType();
|
|
2702
|
+
const targetChecked = targetListItem.getChecked?.();
|
|
2703
|
+
const newListItem = $createListItemNode(targetListType === "check" ? targetChecked : void 0);
|
|
2704
|
+
newListItem.append(...sourceParagraph.getChildren());
|
|
2705
|
+
sourceParagraph.remove();
|
|
2706
|
+
movingListItem = newListItem;
|
|
2707
|
+
}
|
|
2708
|
+
alignListItemDepth(movingListItem, targetListItem);
|
|
2709
|
+
if (payload.placement === "before") targetListItem.insertBefore(movingListItem);
|
|
2710
|
+
else targetListItem.insertAfter(movingListItem);
|
|
2711
|
+
logger$7.debug("done: list-insert-with-item-or-paragraph");
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2714
|
+
const topContext = getTopListContextFromItem(targetListItem);
|
|
2715
|
+
const topListNode = topContext.list;
|
|
2716
|
+
const topListItem = topContext.item;
|
|
2717
|
+
if (!topListNode) {
|
|
2718
|
+
logger$7.debug("branch: list-target-without-top-list", { placement: payload.placement });
|
|
2719
|
+
if (payload.placement === "before") targetListItem.insertBefore(sourceNode);
|
|
2720
|
+
else targetListItem.insertAfter(sourceNode);
|
|
2721
|
+
logger$7.debug("done: list-target-without-top-list");
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
const tailStart = payload.placement === "before" ? topListItem : topListItem.getNextSibling();
|
|
2725
|
+
if (tailStart === topListItem && topListItem.getPreviousSibling() === null) {
|
|
2726
|
+
logger$7.debug("branch: split-list-head-insert-before-list");
|
|
2727
|
+
topListNode.insertBefore(sourceNode);
|
|
2728
|
+
logger$7.debug("done: split-list-head-insert-before-list");
|
|
2729
|
+
return;
|
|
2730
|
+
}
|
|
2731
|
+
if (!tailStart) {
|
|
2732
|
+
logger$7.debug("branch: split-list-tail-insert-after-list");
|
|
2733
|
+
topListNode.insertAfter(sourceNode);
|
|
2734
|
+
logger$7.debug("done: split-list-tail-insert-after-list");
|
|
2735
|
+
return;
|
|
2736
|
+
}
|
|
2737
|
+
const listStartValue = $isListItemNode(tailStart) && typeof tailStart.getValue === "function" ? tailStart.getValue() : 1;
|
|
2738
|
+
const newTailList = cloneListTail(topListNode, tailStart, listStartValue);
|
|
2739
|
+
logger$7.debug("branch: split-list-middle", {
|
|
2740
|
+
hasNewTailList: Boolean(newTailList),
|
|
2741
|
+
listStartValue,
|
|
2742
|
+
tailStartType: tailStart.getType()
|
|
2743
|
+
});
|
|
2744
|
+
topListNode.insertAfter(sourceNode);
|
|
2745
|
+
if (newTailList) sourceNode.insertAfter(newTailList);
|
|
2746
|
+
if (topListNode.getChildrenSize() === 0) topListNode.remove();
|
|
2747
|
+
if (!$isRootNode(sourceNode.getParent())) {
|
|
2748
|
+
const parent = sourceNode.getParent();
|
|
2749
|
+
if (parent && !$isRootNode(parent) && $isListItemNode(parent)) {
|
|
2750
|
+
const parentList = getListParent(parent);
|
|
2751
|
+
if (parentList && parentList.getChildrenSize() === 0) parentList.remove();
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
logger$7.debug("done: split-list-middle");
|
|
2755
|
+
};
|
|
2756
|
+
function registerBlockMoveCommand(editor) {
|
|
2757
|
+
const unregister = editor.registerCommand(MOVE_BLOCK_COMMAND, (payload) => {
|
|
2758
|
+
logger$7.debug("received-command", payload);
|
|
2759
|
+
moveBlockNode(payload);
|
|
2760
|
+
return true;
|
|
2761
|
+
}, COMMAND_PRIORITY_EDITOR);
|
|
2762
|
+
return () => {
|
|
2763
|
+
unregister();
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
//#endregion
|
|
2767
|
+
//#region src/plugins/block/plugin/index.ts
|
|
2768
|
+
init_plugin();
|
|
2769
|
+
const PATCHED_NODE_TYPES = /* @__PURE__ */ new Set();
|
|
2770
|
+
const resolveNodeClass = (node) => {
|
|
2771
|
+
if (typeof node === "function") return node;
|
|
2772
|
+
if (typeof node === "object" && node && typeof node.replace === "function") return node.replace;
|
|
2773
|
+
return null;
|
|
2774
|
+
};
|
|
2775
|
+
const patchBlockNodeCreateDOM = (nodeClass, attributeName) => {
|
|
2776
|
+
const type = nodeClass.getType?.();
|
|
2777
|
+
if (!type || PATCHED_NODE_TYPES.has(type)) return;
|
|
2778
|
+
const originCreateDOM = nodeClass.prototype.createDOM;
|
|
2779
|
+
if (typeof originCreateDOM !== "function") return;
|
|
2780
|
+
nodeClass.prototype.createDOM = function patchedCreateDOM(config, editor) {
|
|
2781
|
+
const dom = originCreateDOM.call(this, config, editor);
|
|
2782
|
+
const latestNode = typeof this.getLatest === "function" ? this.getLatest() : this;
|
|
2783
|
+
const isRootOrListChainToRoot = (() => {
|
|
2784
|
+
let current = typeof latestNode.getParent === "function" ? latestNode.getParent() : null;
|
|
2785
|
+
if (!current || typeof current.getType !== "function") return false;
|
|
2786
|
+
if (current.getType() === "root") return true;
|
|
2787
|
+
while (current && typeof current.getType === "function") {
|
|
2788
|
+
const parentType = current.getType();
|
|
2789
|
+
if (parentType === "root") return true;
|
|
2790
|
+
if (parentType !== "list" && parentType !== "listitem") return false;
|
|
2791
|
+
current = typeof current.getParent === "function" ? current.getParent() : null;
|
|
2792
|
+
}
|
|
2793
|
+
return false;
|
|
2794
|
+
})();
|
|
2795
|
+
const nodeKey = typeof latestNode.getKey === "function" ? latestNode.getKey() : this.getKey();
|
|
2796
|
+
const nodeType = typeof latestNode.getType === "function" ? latestNode.getType() : "";
|
|
2797
|
+
if (dom && typeof latestNode.isInline === "function" && !latestNode.isInline() && nodeType !== "list" && isRootOrListChainToRoot) {
|
|
2798
|
+
dom.dataset.blockId = nodeKey;
|
|
2799
|
+
if (attributeName !== "data-block-id") dom.setAttribute(attributeName, nodeKey);
|
|
2800
|
+
}
|
|
2801
|
+
return dom;
|
|
2802
|
+
};
|
|
2803
|
+
PATCHED_NODE_TYPES.add(type);
|
|
2804
|
+
};
|
|
2805
|
+
const BlockPlugin = class extends KernelPlugin {
|
|
2806
|
+
static {
|
|
2807
|
+
this.pluginName = "BlockPlugin";
|
|
2808
|
+
}
|
|
2809
|
+
constructor(kernel, config) {
|
|
2810
|
+
super();
|
|
2811
|
+
this.kernel = kernel;
|
|
2812
|
+
this.config = config;
|
|
2813
|
+
const attributeName = config?.attributeName || "data-block-id";
|
|
2814
|
+
const rootClassName = config?.className?.trim();
|
|
2815
|
+
kernel.registerServiceHotReload(IBlockMenuService, new BlockMenuService());
|
|
2816
|
+
if (rootClassName) this.registerRootClassName(kernel, rootClassName);
|
|
2817
|
+
patchBlockNodeCreateDOM(ParagraphNode, attributeName);
|
|
2818
|
+
this.registerNodeTransform(kernel, (node) => {
|
|
2819
|
+
const nodeClass = resolveNodeClass(node);
|
|
2820
|
+
if (!nodeClass) return node;
|
|
2821
|
+
patchBlockNodeCreateDOM(nodeClass, attributeName);
|
|
2822
|
+
return node;
|
|
2823
|
+
});
|
|
2824
|
+
}
|
|
2825
|
+
onInit(editor) {
|
|
2826
|
+
const blockMenuService = this.kernel.requireService(IBlockMenuService);
|
|
2827
|
+
if (blockMenuService) {
|
|
2828
|
+
const unregisterDeleteMenu = blockMenuService.registerMenu({
|
|
2829
|
+
key: "__block_default_delete",
|
|
2830
|
+
label: (context) => context.editor.t("block.delete"),
|
|
2831
|
+
onClick: (context) => {
|
|
2832
|
+
const lexicalEditor = context.editor.getLexicalEditor();
|
|
2833
|
+
if (!lexicalEditor) return;
|
|
2834
|
+
lexicalEditor.update(() => {
|
|
2835
|
+
const target = $getNodeByKey(context.blockId);
|
|
2836
|
+
if (!target) return;
|
|
2837
|
+
target.remove();
|
|
2838
|
+
});
|
|
2839
|
+
},
|
|
2840
|
+
order: 999
|
|
2841
|
+
});
|
|
2842
|
+
this.register(unregisterDeleteMenu);
|
|
2843
|
+
}
|
|
2844
|
+
this.register(registerBlockMoveCommand(editor));
|
|
2845
|
+
}
|
|
2846
|
+
};
|
|
2847
|
+
//#endregion
|
|
2848
|
+
//#region src/plugins/block/react/core/runtime-context.ts
|
|
2849
|
+
const createRuntimeContext = () => ({
|
|
2850
|
+
dragAutoScrollRaf: null,
|
|
2851
|
+
dragBlocks: [],
|
|
2852
|
+
dragCleanup: null,
|
|
2853
|
+
dragMoved: false,
|
|
2854
|
+
dragPointerY: null,
|
|
2855
|
+
dragRaf: null,
|
|
2856
|
+
dragStartPoint: null,
|
|
2857
|
+
dragStarted: false,
|
|
2858
|
+
dragTarget: null,
|
|
2859
|
+
draggingSource: null,
|
|
2860
|
+
hideTimer: null,
|
|
2861
|
+
hoveredBlock: null,
|
|
2862
|
+
ignoreNextHandleClick: false,
|
|
2863
|
+
operationMenuAnchorBlockId: null
|
|
2864
|
+
});
|
|
2865
|
+
//#endregion
|
|
2866
|
+
//#region src/plugins/block/react/drag/drag-utils.ts
|
|
2867
|
+
const collectDragBlocks = (root) => {
|
|
2868
|
+
if (!root) return [];
|
|
2869
|
+
return Array.from(root.querySelectorAll("[data-block-id]")).reduce((acc, block) => {
|
|
2870
|
+
const blockId = block.dataset.blockId;
|
|
2871
|
+
if (!blockId) return acc;
|
|
2872
|
+
const rect = block.getBoundingClientRect();
|
|
2873
|
+
if (rect.height <= 0) return acc;
|
|
2874
|
+
acc.push({
|
|
2875
|
+
block,
|
|
2876
|
+
blockId,
|
|
2877
|
+
rect: {
|
|
2878
|
+
bottom: rect.bottom,
|
|
2879
|
+
height: rect.height,
|
|
2880
|
+
left: rect.left,
|
|
2881
|
+
top: rect.top,
|
|
2882
|
+
width: rect.width
|
|
2883
|
+
}
|
|
2884
|
+
});
|
|
2885
|
+
return acc;
|
|
2886
|
+
}, []).sort((a, b) => a.rect.top - b.rect.top);
|
|
2887
|
+
};
|
|
2888
|
+
const resolveScrollContainers = (root) => {
|
|
2889
|
+
if (!root) return [];
|
|
2890
|
+
let element = root;
|
|
2891
|
+
const containers = [];
|
|
2892
|
+
while (element) {
|
|
2893
|
+
const overflowY = window.getComputedStyle(element).overflowY;
|
|
2894
|
+
if ((overflowY === "auto" || overflowY === "scroll") && element.scrollHeight > element.clientHeight) containers.push(element);
|
|
2895
|
+
element = element.parentElement;
|
|
2896
|
+
}
|
|
2897
|
+
const pageScroller = document.scrollingElement;
|
|
2898
|
+
if (pageScroller && !containers.includes(pageScroller)) containers.push(pageScroller);
|
|
2899
|
+
return containers;
|
|
2900
|
+
};
|
|
2901
|
+
const getAutoScrollDelta = (pointerY, container) => {
|
|
2902
|
+
const isPageScroller = container === document.scrollingElement;
|
|
2903
|
+
const top = isPageScroller ? 0 : container.getBoundingClientRect().top;
|
|
2904
|
+
const bottom = isPageScroller ? window.innerHeight : container.getBoundingClientRect().bottom;
|
|
2905
|
+
if (pointerY < top + 80) {
|
|
2906
|
+
const ratio = (top + 80 - pointerY) / 80;
|
|
2907
|
+
return -Math.max(1, Math.round(ratio * 18));
|
|
2908
|
+
}
|
|
2909
|
+
if (pointerY > bottom - 80) {
|
|
2910
|
+
const ratio = (pointerY - (bottom - 80)) / 80;
|
|
2911
|
+
return Math.max(1, Math.round(ratio * 18));
|
|
2912
|
+
}
|
|
2913
|
+
return 0;
|
|
2914
|
+
};
|
|
2915
|
+
const resolveNearestInsertionSlot = (sourceBlockId, blocks, y) => {
|
|
2916
|
+
if (blocks.length === 0) return null;
|
|
2917
|
+
const slots = [];
|
|
2918
|
+
const first = blocks[0];
|
|
2919
|
+
slots.push({
|
|
2920
|
+
left: first.rect.left,
|
|
2921
|
+
placement: "before",
|
|
2922
|
+
sourceBlockId,
|
|
2923
|
+
targetBlockId: first.blockId,
|
|
2924
|
+
width: first.rect.width,
|
|
2925
|
+
y: first.rect.top
|
|
2926
|
+
});
|
|
2927
|
+
for (let i = 0; i < blocks.length - 1; i++) {
|
|
2928
|
+
const next = blocks[i + 1];
|
|
2929
|
+
slots.push({
|
|
2930
|
+
left: next.rect.left,
|
|
2931
|
+
placement: "before",
|
|
2932
|
+
sourceBlockId,
|
|
2933
|
+
targetBlockId: next.blockId,
|
|
2934
|
+
width: next.rect.width,
|
|
2935
|
+
y: next.rect.top
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2938
|
+
const last = blocks[blocks.length - 1];
|
|
2939
|
+
slots.push({
|
|
2940
|
+
left: last.rect.left,
|
|
2941
|
+
placement: "after",
|
|
2942
|
+
sourceBlockId,
|
|
2943
|
+
targetBlockId: last.blockId,
|
|
2944
|
+
width: last.rect.width,
|
|
2945
|
+
y: last.rect.bottom
|
|
2946
|
+
});
|
|
2947
|
+
let bestSlot = slots[0];
|
|
2948
|
+
let bestDistance = Math.abs(y - bestSlot.y);
|
|
2949
|
+
for (let i = 1; i < slots.length; i++) {
|
|
2950
|
+
const slot = slots[i];
|
|
2951
|
+
const distance = Math.abs(y - slot.y);
|
|
2952
|
+
if (distance < bestDistance) {
|
|
2953
|
+
bestSlot = slot;
|
|
2954
|
+
bestDistance = distance;
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
return bestSlot;
|
|
2958
|
+
};
|
|
2959
|
+
//#endregion
|
|
2960
|
+
//#region src/plugins/block/react/drag/drag-session.ts
|
|
2961
|
+
init_debug();
|
|
2962
|
+
const logger$6 = createDebugLogger("plugin", "block-react");
|
|
2963
|
+
const DRAG_GHOST_OFFSET_X = 14;
|
|
2964
|
+
const DRAG_GHOST_OFFSET_Y = 14;
|
|
2965
|
+
const DRAG_SOURCE_OPACITY = "0.45";
|
|
2966
|
+
const LIST_ITEM_GHOST_PADDING_INLINE_START = 24;
|
|
2967
|
+
const createDragGhostContent = (sourceBlock, clone) => {
|
|
2968
|
+
if (sourceBlock.tagName !== "LI") return clone;
|
|
2969
|
+
const list = sourceBlock.parentElement;
|
|
2970
|
+
if (!list || list.tagName !== "UL" && list.tagName !== "OL") return clone;
|
|
2971
|
+
const listClone = list.cloneNode(false);
|
|
2972
|
+
listClone.style.margin = "0";
|
|
2973
|
+
listClone.style.paddingInlineStart = `${LIST_ITEM_GHOST_PADDING_INLINE_START}px`;
|
|
2974
|
+
listClone.style.pointerEvents = "none";
|
|
2975
|
+
listClone.style.width = `calc(100% - ${LIST_ITEM_GHOST_PADDING_INLINE_START}px)`;
|
|
2976
|
+
listClone.append(clone);
|
|
2977
|
+
return listClone;
|
|
2978
|
+
};
|
|
2979
|
+
const createDragGhost = (sourceBlock, x, y, container) => {
|
|
2980
|
+
const rect = sourceBlock.getBoundingClientRect();
|
|
2981
|
+
const ghost = document.createElement("div");
|
|
2982
|
+
const clone = sourceBlock.cloneNode(true);
|
|
2983
|
+
ghost.dataset.blockDragGhost = "true";
|
|
2984
|
+
ghost.setAttribute("aria-hidden", "true");
|
|
2985
|
+
ghost.style.position = "fixed";
|
|
2986
|
+
ghost.style.top = "0";
|
|
2987
|
+
ghost.style.left = "0";
|
|
2988
|
+
ghost.style.pointerEvents = "none";
|
|
2989
|
+
ghost.style.zIndex = "10001";
|
|
2990
|
+
ghost.style.opacity = "0.5";
|
|
2991
|
+
ghost.style.width = `${rect.width}px`;
|
|
2992
|
+
ghost.style.height = `${rect.height}px`;
|
|
2993
|
+
ghost.style.overflow = "hidden";
|
|
2994
|
+
ghost.style.borderRadius = "8px";
|
|
2995
|
+
ghost.style.boxShadow = "0 10px 30px rgba(0, 0, 0, 0.12), 0 0 0 1px var(--lobe-color-border-secondary, rgba(0, 0, 0, 0.06)) inset";
|
|
2996
|
+
ghost.style.transform = `translate3d(${x + DRAG_GHOST_OFFSET_X}px, ${y + DRAG_GHOST_OFFSET_Y}px, 0)`;
|
|
2997
|
+
clone.style.margin = "0";
|
|
2998
|
+
clone.style.pointerEvents = "none";
|
|
2999
|
+
clone.style.width = "100%";
|
|
3000
|
+
clone.style.height = "100%";
|
|
3001
|
+
clone.setAttribute("contenteditable", "false");
|
|
3002
|
+
clone.querySelectorAll("[contenteditable]").forEach((element) => {
|
|
3003
|
+
element.setAttribute("contenteditable", "false");
|
|
3004
|
+
});
|
|
3005
|
+
ghost.append(createDragGhostContent(sourceBlock, clone));
|
|
3006
|
+
(container || document.body).append(ghost);
|
|
3007
|
+
return ghost;
|
|
3008
|
+
};
|
|
3009
|
+
const updateDragGhostPosition = (ghost, x, y) => {
|
|
3010
|
+
ghost.style.transform = `translate3d(${x + DRAG_GHOST_OFFSET_X}px, ${y + DRAG_GHOST_OFFSET_Y}px, 0)`;
|
|
3011
|
+
};
|
|
3012
|
+
const removeDragGhost = (ghost) => {
|
|
3013
|
+
if (!ghost) return;
|
|
3014
|
+
ghost.remove();
|
|
3015
|
+
};
|
|
3016
|
+
const applyDragSourceOpacity = (sourceBlock) => {
|
|
3017
|
+
const previousOpacity = sourceBlock.style.opacity;
|
|
3018
|
+
sourceBlock.style.opacity = DRAG_SOURCE_OPACITY;
|
|
3019
|
+
return () => {
|
|
3020
|
+
sourceBlock.style.opacity = previousOpacity;
|
|
3021
|
+
};
|
|
3022
|
+
};
|
|
3023
|
+
const startBlockDragSession = ({ clientX, clientY, clearDragPreview, contextRef, dragGhostContainer, editor, menuContext, onDraggingChange, onDragTargetResolve, setDragIndicator, setOperationMenuContext, setOperationMenuOpen, toggleOperationMenu }) => {
|
|
3024
|
+
setOperationMenuOpen(false);
|
|
3025
|
+
let dragGhost = null;
|
|
3026
|
+
let restoreSourceOpacity = null;
|
|
3027
|
+
contextRef.current.dragStartPoint = {
|
|
3028
|
+
x: clientX,
|
|
3029
|
+
y: clientY
|
|
3030
|
+
};
|
|
3031
|
+
contextRef.current.dragStarted = false;
|
|
3032
|
+
contextRef.current.dragMoved = false;
|
|
3033
|
+
contextRef.current.dragCleanup?.();
|
|
3034
|
+
contextRef.current.dragCleanup = null;
|
|
3035
|
+
if (contextRef.current.hideTimer !== null) {
|
|
3036
|
+
window.clearTimeout(contextRef.current.hideTimer);
|
|
3037
|
+
contextRef.current.hideTimer = null;
|
|
3038
|
+
}
|
|
3039
|
+
contextRef.current.draggingSource = {
|
|
3040
|
+
blockElement: menuContext.blockElement,
|
|
3041
|
+
blockId: menuContext.blockId
|
|
3042
|
+
};
|
|
3043
|
+
contextRef.current.dragPointerY = clientY;
|
|
3044
|
+
contextRef.current.dragBlocks = collectDragBlocks(editor.getRootElement());
|
|
3045
|
+
const refreshDragBlocksSnapshot = () => {
|
|
3046
|
+
if (!contextRef.current.draggingSource) return;
|
|
3047
|
+
contextRef.current.dragBlocks = collectDragBlocks(editor.getRootElement());
|
|
3048
|
+
};
|
|
3049
|
+
const updateDragPreview = (y) => {
|
|
3050
|
+
const source = contextRef.current.draggingSource;
|
|
3051
|
+
const blocks = contextRef.current.dragBlocks;
|
|
3052
|
+
if (!source || blocks.length === 0) {
|
|
3053
|
+
clearDragPreview();
|
|
3054
|
+
return;
|
|
3055
|
+
}
|
|
3056
|
+
const bestSlot = resolveNearestInsertionSlot(source.blockId, blocks, y);
|
|
3057
|
+
if (!bestSlot) {
|
|
3058
|
+
clearDragPreview();
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
contextRef.current.dragTarget = {
|
|
3062
|
+
placement: bestSlot.placement,
|
|
3063
|
+
sourceBlockId: bestSlot.sourceBlockId,
|
|
3064
|
+
targetBlockId: bestSlot.targetBlockId
|
|
3065
|
+
};
|
|
3066
|
+
setDragIndicator({
|
|
3067
|
+
left: bestSlot.left,
|
|
3068
|
+
top: bestSlot.y,
|
|
3069
|
+
width: bestSlot.width
|
|
3070
|
+
});
|
|
3071
|
+
};
|
|
3072
|
+
const scrollContainers = resolveScrollContainers(editor.getRootElement());
|
|
3073
|
+
const onPointerMove = (pointerEvent) => {
|
|
3074
|
+
contextRef.current.dragPointerY = pointerEvent.clientY;
|
|
3075
|
+
if (!contextRef.current.dragStarted && contextRef.current.dragStartPoint) {
|
|
3076
|
+
if (Math.hypot(pointerEvent.clientX - contextRef.current.dragStartPoint.x, pointerEvent.clientY - contextRef.current.dragStartPoint.y) >= 10) {
|
|
3077
|
+
contextRef.current.dragStarted = true;
|
|
3078
|
+
contextRef.current.dragMoved = true;
|
|
3079
|
+
contextRef.current.ignoreNextHandleClick = true;
|
|
3080
|
+
onDraggingChange?.(true);
|
|
3081
|
+
setOperationMenuOpen(false);
|
|
3082
|
+
setOperationMenuContext(null);
|
|
3083
|
+
if (!dragGhost && contextRef.current.draggingSource) {
|
|
3084
|
+
dragGhost = createDragGhost(contextRef.current.draggingSource.blockElement, pointerEvent.clientX, pointerEvent.clientY, dragGhostContainer || editor.getRootElement()?.parentElement);
|
|
3085
|
+
if (!restoreSourceOpacity) restoreSourceOpacity = applyDragSourceOpacity(contextRef.current.draggingSource.blockElement);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
if (!contextRef.current.dragStarted) return;
|
|
3090
|
+
if (dragGhost) updateDragGhostPosition(dragGhost, pointerEvent.clientX, pointerEvent.clientY);
|
|
3091
|
+
if (contextRef.current.dragRaf !== null) return;
|
|
3092
|
+
contextRef.current.dragRaf = window.requestAnimationFrame(() => {
|
|
3093
|
+
contextRef.current.dragRaf = null;
|
|
3094
|
+
if (contextRef.current.dragPointerY === null) {
|
|
3095
|
+
clearDragPreview();
|
|
3096
|
+
return;
|
|
3097
|
+
}
|
|
3098
|
+
updateDragPreview(contextRef.current.dragPointerY);
|
|
3099
|
+
});
|
|
3100
|
+
};
|
|
3101
|
+
const onViewportChange = () => {
|
|
3102
|
+
refreshDragBlocksSnapshot();
|
|
3103
|
+
if (contextRef.current.dragPointerY !== null) updateDragPreview(contextRef.current.dragPointerY);
|
|
3104
|
+
};
|
|
3105
|
+
const onPointerUp = () => {
|
|
3106
|
+
if (!contextRef.current.dragStarted && !contextRef.current.dragMoved) {
|
|
3107
|
+
toggleOperationMenu(menuContext);
|
|
3108
|
+
contextRef.current.ignoreNextHandleClick = true;
|
|
3109
|
+
contextRef.current.draggingSource = null;
|
|
3110
|
+
contextRef.current.dragPointerY = null;
|
|
3111
|
+
contextRef.current.dragBlocks = [];
|
|
3112
|
+
contextRef.current.dragStartPoint = null;
|
|
3113
|
+
removeDragGhost(dragGhost);
|
|
3114
|
+
dragGhost = null;
|
|
3115
|
+
restoreSourceOpacity?.();
|
|
3116
|
+
restoreSourceOpacity = null;
|
|
3117
|
+
onDraggingChange?.(false);
|
|
3118
|
+
window.removeEventListener("pointermove", onPointerMove, true);
|
|
3119
|
+
window.removeEventListener("pointerup", onPointerUp, true);
|
|
3120
|
+
window.removeEventListener("resize", onViewportChange);
|
|
3121
|
+
document.removeEventListener("scroll", onViewportChange, true);
|
|
3122
|
+
contextRef.current.dragCleanup = null;
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3125
|
+
const finalTarget = contextRef.current.dragTarget;
|
|
3126
|
+
if (finalTarget) {
|
|
3127
|
+
logger$6.debug("drag-end", {
|
|
3128
|
+
位置: finalTarget.placement === "before" ? "上方" : "下方",
|
|
3129
|
+
位置节点id: finalTarget.targetBlockId,
|
|
3130
|
+
插入节点id: finalTarget.sourceBlockId
|
|
3131
|
+
});
|
|
3132
|
+
const handled = editor.dispatchCommand(MOVE_BLOCK_COMMAND, finalTarget);
|
|
3133
|
+
logger$6.debug("move-block-command-handled", handled);
|
|
3134
|
+
}
|
|
3135
|
+
onDragTargetResolve?.(contextRef.current.dragTarget);
|
|
3136
|
+
if (contextRef.current.dragRaf !== null) {
|
|
3137
|
+
window.cancelAnimationFrame(contextRef.current.dragRaf);
|
|
3138
|
+
contextRef.current.dragRaf = null;
|
|
3139
|
+
}
|
|
3140
|
+
if (contextRef.current.dragAutoScrollRaf !== null) {
|
|
3141
|
+
window.cancelAnimationFrame(contextRef.current.dragAutoScrollRaf);
|
|
3142
|
+
contextRef.current.dragAutoScrollRaf = null;
|
|
3143
|
+
}
|
|
3144
|
+
contextRef.current.draggingSource = null;
|
|
3145
|
+
contextRef.current.dragPointerY = null;
|
|
3146
|
+
contextRef.current.dragBlocks = [];
|
|
3147
|
+
contextRef.current.dragStartPoint = null;
|
|
3148
|
+
removeDragGhost(dragGhost);
|
|
3149
|
+
dragGhost = null;
|
|
3150
|
+
restoreSourceOpacity?.();
|
|
3151
|
+
restoreSourceOpacity = null;
|
|
3152
|
+
onDraggingChange?.(false);
|
|
3153
|
+
clearDragPreview();
|
|
3154
|
+
window.removeEventListener("pointermove", onPointerMove, true);
|
|
3155
|
+
window.removeEventListener("pointerup", onPointerUp, true);
|
|
3156
|
+
window.removeEventListener("resize", onViewportChange);
|
|
3157
|
+
document.removeEventListener("scroll", onViewportChange, true);
|
|
3158
|
+
contextRef.current.dragCleanup = null;
|
|
3159
|
+
};
|
|
3160
|
+
window.addEventListener("pointermove", onPointerMove, true);
|
|
3161
|
+
window.addEventListener("pointerup", onPointerUp, true);
|
|
3162
|
+
window.addEventListener("resize", onViewportChange);
|
|
3163
|
+
document.addEventListener("scroll", onViewportChange, true);
|
|
3164
|
+
const runAutoScroll = () => {
|
|
3165
|
+
contextRef.current.dragAutoScrollRaf = window.requestAnimationFrame(runAutoScroll);
|
|
3166
|
+
if (!contextRef.current.draggingSource || contextRef.current.dragPointerY === null || !contextRef.current.dragStarted) return;
|
|
3167
|
+
let didScroll = false;
|
|
3168
|
+
for (const scrollContainer of scrollContainers) {
|
|
3169
|
+
const delta = getAutoScrollDelta(contextRef.current.dragPointerY, scrollContainer);
|
|
3170
|
+
if (delta === 0) continue;
|
|
3171
|
+
const maxScrollTop = scrollContainer.scrollHeight - scrollContainer.clientHeight;
|
|
3172
|
+
const nextScrollTop = Math.max(0, Math.min(maxScrollTop, scrollContainer.scrollTop + delta));
|
|
3173
|
+
if (nextScrollTop === scrollContainer.scrollTop) continue;
|
|
3174
|
+
scrollContainer.scrollTop = nextScrollTop;
|
|
3175
|
+
didScroll = true;
|
|
3176
|
+
}
|
|
3177
|
+
if (didScroll) {
|
|
3178
|
+
refreshDragBlocksSnapshot();
|
|
3179
|
+
if (contextRef.current.dragPointerY !== null) updateDragPreview(contextRef.current.dragPointerY);
|
|
3180
|
+
return;
|
|
3181
|
+
}
|
|
3182
|
+
const blocks = contextRef.current.dragBlocks;
|
|
3183
|
+
if (blocks.length === 0) return;
|
|
3184
|
+
const pointerY = contextRef.current.dragPointerY;
|
|
3185
|
+
const nearBottom = pointerY > window.innerHeight - 80;
|
|
3186
|
+
const nearTop = pointerY < 80;
|
|
3187
|
+
const lastBlock = blocks[blocks.length - 1];
|
|
3188
|
+
if (nearBottom) lastBlock.block.scrollIntoView({ block: "end" });
|
|
3189
|
+
else if (nearTop) blocks[0].block.scrollIntoView({ block: "start" });
|
|
3190
|
+
refreshDragBlocksSnapshot();
|
|
3191
|
+
if (contextRef.current.dragPointerY !== null) updateDragPreview(contextRef.current.dragPointerY);
|
|
3192
|
+
};
|
|
3193
|
+
contextRef.current.dragAutoScrollRaf = window.requestAnimationFrame(runAutoScroll);
|
|
3194
|
+
contextRef.current.dragCleanup = () => {
|
|
3195
|
+
if (contextRef.current.dragRaf !== null) {
|
|
3196
|
+
window.cancelAnimationFrame(contextRef.current.dragRaf);
|
|
3197
|
+
contextRef.current.dragRaf = null;
|
|
3198
|
+
}
|
|
3199
|
+
if (contextRef.current.dragAutoScrollRaf !== null) {
|
|
3200
|
+
window.cancelAnimationFrame(contextRef.current.dragAutoScrollRaf);
|
|
3201
|
+
contextRef.current.dragAutoScrollRaf = null;
|
|
3202
|
+
}
|
|
3203
|
+
contextRef.current.draggingSource = null;
|
|
3204
|
+
contextRef.current.dragPointerY = null;
|
|
3205
|
+
contextRef.current.dragBlocks = [];
|
|
3206
|
+
contextRef.current.dragStartPoint = null;
|
|
3207
|
+
removeDragGhost(dragGhost);
|
|
3208
|
+
dragGhost = null;
|
|
3209
|
+
restoreSourceOpacity?.();
|
|
3210
|
+
restoreSourceOpacity = null;
|
|
3211
|
+
onDraggingChange?.(false);
|
|
3212
|
+
clearDragPreview();
|
|
3213
|
+
window.removeEventListener("pointermove", onPointerMove, true);
|
|
3214
|
+
window.removeEventListener("pointerup", onPointerUp, true);
|
|
3215
|
+
window.removeEventListener("resize", onViewportChange);
|
|
3216
|
+
document.removeEventListener("scroll", onViewportChange, true);
|
|
3217
|
+
};
|
|
3218
|
+
};
|
|
3219
|
+
//#endregion
|
|
3220
|
+
//#region src/plugins/block/react/style.ts
|
|
3221
|
+
const styles$12 = createStaticStyles(({ css, cssVar }) => ({
|
|
3222
|
+
dragHandle: css`
|
|
3223
|
+
cursor: grab !important;
|
|
3224
|
+
|
|
3225
|
+
&:active {
|
|
3226
|
+
cursor: grabbing !important;
|
|
3227
|
+
}
|
|
3228
|
+
`,
|
|
3229
|
+
dragIndicator: css`
|
|
3230
|
+
pointer-events: none;
|
|
3231
|
+
|
|
3232
|
+
position: fixed;
|
|
3233
|
+
z-index: 10000;
|
|
3234
|
+
|
|
3235
|
+
height: 2px;
|
|
3236
|
+
border-radius: 999px;
|
|
3237
|
+
|
|
3238
|
+
background: var(--lobe-color-primary, ${cssVar.colorPrimary});
|
|
3239
|
+
`,
|
|
3240
|
+
dragLayer: css`
|
|
3241
|
+
pointer-events: none;
|
|
3242
|
+
|
|
3243
|
+
position: fixed;
|
|
3244
|
+
z-index: 10001;
|
|
3245
|
+
inset: 0;
|
|
3246
|
+
|
|
3247
|
+
overflow: visible;
|
|
3248
|
+
`,
|
|
3249
|
+
menu: css`
|
|
3250
|
+
pointer-events: auto;
|
|
3251
|
+
position: fixed;
|
|
3252
|
+
z-index: 100;
|
|
3253
|
+
transition:
|
|
3254
|
+
inset-inline-start 200ms ease,
|
|
3255
|
+
inset-block-start 200ms ease;
|
|
3256
|
+
`,
|
|
3257
|
+
menuInner: css`
|
|
3258
|
+
display: flex;
|
|
3259
|
+
gap: 4px;
|
|
3260
|
+
align-items: center;
|
|
3261
|
+
|
|
3262
|
+
min-width: 28px;
|
|
3263
|
+
min-height: 28px;
|
|
3264
|
+
padding: 2px;
|
|
3265
|
+
border-radius: 8px;
|
|
3266
|
+
|
|
3267
|
+
background: transparent;
|
|
3268
|
+
box-shadow: none;
|
|
3269
|
+
|
|
3270
|
+
transition:
|
|
3271
|
+
background 120ms ease,
|
|
3272
|
+
box-shadow 120ms ease;
|
|
3273
|
+
|
|
3274
|
+
&:hover {
|
|
3275
|
+
background: var(--lobe-color-fill-secondary, ${cssVar.colorFillSecondary});
|
|
3276
|
+
box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary} inset;
|
|
3277
|
+
}
|
|
3278
|
+
`,
|
|
3279
|
+
root: css`
|
|
3280
|
+
padding-inline: 54px 54px;
|
|
3281
|
+
`
|
|
3282
|
+
}));
|
|
3283
|
+
//#endregion
|
|
3284
|
+
//#region src/plugins/block/react/ReactBlockPlugin.tsx
|
|
3285
|
+
init_debug();
|
|
3286
|
+
const logger$5 = createDebugLogger("plugin", "block-react");
|
|
3287
|
+
const OPERATION_MENU_OVERLAY_CLASS = "lobe-block-operation-dropdown";
|
|
3288
|
+
const ReactBlockPlugin = (props) => {
|
|
3289
|
+
const { token } = theme.useToken();
|
|
3290
|
+
const [editor] = useLexicalComposerContext();
|
|
3291
|
+
const { rootClassName, className, attributeName, locale, onHoverBlockChange, onDragTargetChange, onDragTargetResolve } = props;
|
|
3292
|
+
const mergedRootClassName = cx(styles$12.root, rootClassName?.trim() || className?.trim());
|
|
3293
|
+
const menuRef = useRef(null);
|
|
3294
|
+
const dragLayerRef = useRef(null);
|
|
3295
|
+
const contextRef = useRef(createRuntimeContext());
|
|
3296
|
+
const [hoveredBlock, setHoveredBlock] = useState(null);
|
|
3297
|
+
const [menuVersion, setMenuVersion] = useState(0);
|
|
3298
|
+
const [menuPosition, setMenuPosition] = useState({});
|
|
3299
|
+
const [operationMenuOpen, setOperationMenuOpen] = useState(false);
|
|
3300
|
+
const [operationMenuContext, setOperationMenuContext] = useState(null);
|
|
3301
|
+
const [dragIndicator, setDragIndicator] = useState(null);
|
|
3302
|
+
const [dragLayerContainer, setDragLayerContainer] = useState(null);
|
|
3303
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
3304
|
+
const [blockMenuService, setBlockMenuService] = useState(null);
|
|
3305
|
+
useLayoutEffect(() => {
|
|
3306
|
+
if (locale) editor.registerLocale(locale);
|
|
3307
|
+
editor.registerPlugin(BlockPlugin, {
|
|
3308
|
+
attributeName,
|
|
3309
|
+
className: mergedRootClassName
|
|
3310
|
+
});
|
|
3311
|
+
}, [
|
|
3312
|
+
attributeName,
|
|
3313
|
+
editor,
|
|
3314
|
+
locale,
|
|
3315
|
+
mergedRootClassName
|
|
3316
|
+
]);
|
|
3317
|
+
useLexicalEditor(() => {
|
|
3318
|
+
const service = editor.requireService(IBlockMenuService);
|
|
3319
|
+
if (!service) {
|
|
3320
|
+
logger$5.warn("BlockMenuService not found");
|
|
3321
|
+
return;
|
|
3322
|
+
}
|
|
3323
|
+
setBlockMenuService(service);
|
|
3324
|
+
return () => {
|
|
3325
|
+
setBlockMenuService((current) => current === service ? null : current);
|
|
3326
|
+
};
|
|
3327
|
+
}, []);
|
|
3328
|
+
useEffect(() => {
|
|
3329
|
+
contextRef.current.hoveredBlock = hoveredBlock;
|
|
3330
|
+
}, [hoveredBlock]);
|
|
3331
|
+
useEffect(() => {
|
|
3332
|
+
if (!blockMenuService) return;
|
|
3333
|
+
return blockMenuService.subscribe(() => {
|
|
3334
|
+
setMenuVersion((v) => v + 1);
|
|
3335
|
+
});
|
|
3336
|
+
}, [blockMenuService]);
|
|
3337
|
+
useEffect(() => {
|
|
3338
|
+
return () => {
|
|
3339
|
+
contextRef.current.dragCleanup?.();
|
|
3340
|
+
contextRef.current.dragCleanup = null;
|
|
3341
|
+
setIsDragging(false);
|
|
3342
|
+
};
|
|
3343
|
+
}, []);
|
|
3344
|
+
useEffect(() => {
|
|
3345
|
+
let raf = null;
|
|
3346
|
+
const syncDragLayerContainer = () => {
|
|
3347
|
+
const container = editor.getRootElement()?.parentElement ?? null;
|
|
3348
|
+
setDragLayerContainer((current) => current === container ? current : container);
|
|
3349
|
+
if (!container) raf = window.requestAnimationFrame(syncDragLayerContainer);
|
|
3350
|
+
};
|
|
3351
|
+
syncDragLayerContainer();
|
|
3352
|
+
return () => {
|
|
3353
|
+
if (raf !== null) window.cancelAnimationFrame(raf);
|
|
3354
|
+
};
|
|
3355
|
+
}, [editor]);
|
|
3356
|
+
useEffect(() => {
|
|
3357
|
+
let hoverRaf = null;
|
|
3358
|
+
let blockRectsCache = collectDragBlocks(editor.getRootElement());
|
|
3359
|
+
let blockRectsDirty = true;
|
|
3360
|
+
let latestPointer = null;
|
|
3361
|
+
const markBlockRectsDirty = () => {
|
|
3362
|
+
blockRectsDirty = true;
|
|
3363
|
+
};
|
|
3364
|
+
const getBlockRects = (root) => {
|
|
3365
|
+
if (blockRectsDirty) {
|
|
3366
|
+
blockRectsCache = collectDragBlocks(root);
|
|
3367
|
+
blockRectsDirty = false;
|
|
3368
|
+
}
|
|
3369
|
+
return blockRectsCache;
|
|
3370
|
+
};
|
|
3371
|
+
const resolveBlockByY = (rects, y) => {
|
|
3372
|
+
if (rects.length === 0) return null;
|
|
3373
|
+
let left = 0;
|
|
3374
|
+
let right = rects.length - 1;
|
|
3375
|
+
while (left <= right) {
|
|
3376
|
+
const mid = left + right >> 1;
|
|
3377
|
+
const entry = rects[mid];
|
|
3378
|
+
if (y < entry.rect.top) {
|
|
3379
|
+
right = mid - 1;
|
|
3380
|
+
continue;
|
|
3381
|
+
}
|
|
3382
|
+
if (y > entry.rect.bottom) {
|
|
3383
|
+
left = mid + 1;
|
|
3384
|
+
continue;
|
|
3385
|
+
}
|
|
3386
|
+
return entry;
|
|
3387
|
+
}
|
|
3388
|
+
const nextIndex = Math.min(Math.max(left, 0), rects.length - 1);
|
|
3389
|
+
const prevIndex = Math.min(Math.max(right, 0), rects.length - 1);
|
|
3390
|
+
const next = rects[nextIndex];
|
|
3391
|
+
const prev = rects[prevIndex];
|
|
3392
|
+
if (!next) return prev || null;
|
|
3393
|
+
if (!prev) return next || null;
|
|
3394
|
+
return Math.min(Math.abs(y - next.rect.top), Math.abs(y - next.rect.bottom)) < Math.min(Math.abs(y - prev.rect.top), Math.abs(y - prev.rect.bottom)) ? next : prev;
|
|
3395
|
+
};
|
|
3396
|
+
const isInRootLeftPaddingArea = (root, clientX, clientY) => {
|
|
3397
|
+
const rootRect = root.getBoundingClientRect();
|
|
3398
|
+
if (!(clientX >= rootRect.left && clientX <= rootRect.right && clientY >= rootRect.top && clientY <= rootRect.bottom)) return false;
|
|
3399
|
+
const paddingLeft = Number.parseFloat(window.getComputedStyle(root).paddingLeft || "0");
|
|
3400
|
+
if (paddingLeft <= 0) return false;
|
|
3401
|
+
return clientX <= rootRect.left + paddingLeft;
|
|
3402
|
+
};
|
|
3403
|
+
const getHoveredBlock = (target, clientX, clientY) => {
|
|
3404
|
+
const root = editor.getRootElement();
|
|
3405
|
+
if (!root || !(target instanceof Node)) return null;
|
|
3406
|
+
const targetElement = target instanceof Element ? target : target.parentElement;
|
|
3407
|
+
if (!targetElement) return null;
|
|
3408
|
+
if (menuRef.current?.contains(targetElement)) return contextRef.current.hoveredBlock;
|
|
3409
|
+
if (targetElement.closest(`.${OPERATION_MENU_OVERLAY_CLASS}`)) return contextRef.current.hoveredBlock;
|
|
3410
|
+
const blockElement = targetElement.closest("[data-block-id]");
|
|
3411
|
+
if (blockElement instanceof HTMLElement && root.contains(blockElement)) {
|
|
3412
|
+
const blockId = blockElement.dataset.blockId;
|
|
3413
|
+
if (!blockId) return null;
|
|
3414
|
+
return {
|
|
3415
|
+
blockElement,
|
|
3416
|
+
blockId
|
|
3417
|
+
};
|
|
3418
|
+
}
|
|
3419
|
+
if (!root.contains(targetElement)) return null;
|
|
3420
|
+
if (!isInRootLeftPaddingArea(root, clientX, clientY)) return null;
|
|
3421
|
+
const rects = getBlockRects(root);
|
|
3422
|
+
if (rects.length === 0) return null;
|
|
3423
|
+
const entry = resolveBlockByY(rects, clientY);
|
|
3424
|
+
if (!entry) return null;
|
|
3425
|
+
return {
|
|
3426
|
+
blockElement: entry.block,
|
|
3427
|
+
blockId: entry.blockId
|
|
3428
|
+
};
|
|
3429
|
+
};
|
|
3430
|
+
const processHover = () => {
|
|
3431
|
+
if (!latestPointer) return;
|
|
3432
|
+
if (contextRef.current.draggingSource) return;
|
|
3433
|
+
const { clientX, clientY, target } = latestPointer;
|
|
3434
|
+
const next = getHoveredBlock(target, clientX, clientY);
|
|
3435
|
+
if (next) {
|
|
3436
|
+
if (contextRef.current.hideTimer !== null) {
|
|
3437
|
+
window.clearTimeout(contextRef.current.hideTimer);
|
|
3438
|
+
contextRef.current.hideTimer = null;
|
|
3439
|
+
}
|
|
3440
|
+
setHoveredBlock((current) => {
|
|
3441
|
+
if (!current) return next;
|
|
3442
|
+
if (next.blockId === current.blockId && next.blockElement === current.blockElement) return current;
|
|
3443
|
+
return next;
|
|
3444
|
+
});
|
|
3445
|
+
return;
|
|
3446
|
+
}
|
|
3447
|
+
if (contextRef.current.hideTimer !== null) return;
|
|
3448
|
+
contextRef.current.hideTimer = window.setTimeout(() => {
|
|
3449
|
+
contextRef.current.hideTimer = null;
|
|
3450
|
+
setHoveredBlock((current) => current ? null : current);
|
|
3451
|
+
}, 120);
|
|
3452
|
+
};
|
|
3453
|
+
const scheduleHoverProcess = () => {
|
|
3454
|
+
if (hoverRaf !== null) return;
|
|
3455
|
+
hoverRaf = window.requestAnimationFrame(() => {
|
|
3456
|
+
hoverRaf = null;
|
|
3457
|
+
processHover();
|
|
3458
|
+
});
|
|
3459
|
+
};
|
|
3460
|
+
const handleMouseMove = (event) => {
|
|
3461
|
+
const root = editor.getRootElement();
|
|
3462
|
+
const target = event.target;
|
|
3463
|
+
if (!root || !(target instanceof Node)) {
|
|
3464
|
+
if (!contextRef.current.hoveredBlock) return;
|
|
3465
|
+
} else {
|
|
3466
|
+
const targetElement = target instanceof Element ? target : target.parentElement;
|
|
3467
|
+
if (!targetElement) {
|
|
3468
|
+
if (!contextRef.current.hoveredBlock) return;
|
|
3469
|
+
} else {
|
|
3470
|
+
const overMenu = menuRef.current?.contains(targetElement) || Boolean(targetElement.closest(`.${OPERATION_MENU_OVERLAY_CLASS}`));
|
|
3471
|
+
const overBlock = targetElement.closest("[data-block-id]") instanceof HTMLElement && root.contains(targetElement);
|
|
3472
|
+
const inPaddingArea = root.contains(targetElement) ? isInRootLeftPaddingArea(root, event.clientX, event.clientY) : false;
|
|
3473
|
+
if (!overMenu && !overBlock && !inPaddingArea && !contextRef.current.hoveredBlock) return;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
latestPointer = {
|
|
3477
|
+
clientX: event.clientX,
|
|
3478
|
+
clientY: event.clientY,
|
|
3479
|
+
target
|
|
3480
|
+
};
|
|
3481
|
+
scheduleHoverProcess();
|
|
3482
|
+
};
|
|
3483
|
+
const handleViewportChange = () => {
|
|
3484
|
+
markBlockRectsDirty();
|
|
3485
|
+
scheduleHoverProcess();
|
|
3486
|
+
};
|
|
3487
|
+
const rootResizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
|
|
3488
|
+
markBlockRectsDirty();
|
|
3489
|
+
}) : null;
|
|
3490
|
+
const root = editor.getRootElement();
|
|
3491
|
+
const unregisterUpdate = editor.getLexicalEditor()?.registerUpdateListener(() => {
|
|
3492
|
+
markBlockRectsDirty();
|
|
3493
|
+
scheduleHoverProcess();
|
|
3494
|
+
}) || (() => {});
|
|
3495
|
+
if (root) rootResizeObserver?.observe(root);
|
|
3496
|
+
document.addEventListener("mousemove", handleMouseMove, true);
|
|
3497
|
+
window.addEventListener("resize", handleViewportChange);
|
|
3498
|
+
document.addEventListener("scroll", handleViewportChange, true);
|
|
3499
|
+
return () => {
|
|
3500
|
+
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
3501
|
+
window.removeEventListener("resize", handleViewportChange);
|
|
3502
|
+
document.removeEventListener("scroll", handleViewportChange, true);
|
|
3503
|
+
rootResizeObserver?.disconnect();
|
|
3504
|
+
unregisterUpdate();
|
|
3505
|
+
if (hoverRaf !== null) {
|
|
3506
|
+
window.cancelAnimationFrame(hoverRaf);
|
|
3507
|
+
hoverRaf = null;
|
|
3508
|
+
}
|
|
3509
|
+
if (contextRef.current.hideTimer !== null) {
|
|
3510
|
+
window.clearTimeout(contextRef.current.hideTimer);
|
|
3511
|
+
contextRef.current.hideTimer = null;
|
|
3512
|
+
}
|
|
3513
|
+
};
|
|
3514
|
+
}, [editor, isDragging]);
|
|
3515
|
+
useEffect(() => {
|
|
3516
|
+
if (!hoveredBlock) {
|
|
3517
|
+
if (operationMenuOpen) return;
|
|
3518
|
+
setMenuPosition({});
|
|
3519
|
+
return;
|
|
3520
|
+
}
|
|
3521
|
+
const updateMenuPosition = () => {
|
|
3522
|
+
const rect = hoveredBlock.blockElement.getBoundingClientRect();
|
|
3523
|
+
const menuWidth = menuRef.current?.offsetWidth || 32;
|
|
3524
|
+
const gap = 8;
|
|
3525
|
+
const listItemOffset = hoveredBlock.blockElement.tagName === "LI" ? 16 : 0;
|
|
3526
|
+
setMenuPosition({
|
|
3527
|
+
left: Math.max(gap, rect.left - menuWidth - gap - listItemOffset),
|
|
3528
|
+
top: rect.top
|
|
3529
|
+
});
|
|
3530
|
+
};
|
|
3531
|
+
updateMenuPosition();
|
|
3532
|
+
window.addEventListener("resize", updateMenuPosition);
|
|
3533
|
+
document.addEventListener("scroll", updateMenuPosition, true);
|
|
3534
|
+
return () => {
|
|
3535
|
+
window.removeEventListener("resize", updateMenuPosition);
|
|
3536
|
+
document.removeEventListener("scroll", updateMenuPosition, true);
|
|
3537
|
+
};
|
|
3538
|
+
}, [hoveredBlock]);
|
|
3539
|
+
const menuContext = useMemo(() => {
|
|
3540
|
+
if (!hoveredBlock) return null;
|
|
3541
|
+
return {
|
|
3542
|
+
blockElement: hoveredBlock.blockElement,
|
|
3543
|
+
blockId: hoveredBlock.blockId,
|
|
3544
|
+
editor
|
|
3545
|
+
};
|
|
3546
|
+
}, [editor, hoveredBlock]);
|
|
3547
|
+
const operationMenus = useMemo(() => {
|
|
3548
|
+
if (!operationMenuContext || !blockMenuService) return [];
|
|
3549
|
+
return blockMenuService.getMenus(operationMenuContext);
|
|
3550
|
+
}, [
|
|
3551
|
+
blockMenuService,
|
|
3552
|
+
operationMenuContext,
|
|
3553
|
+
menuVersion
|
|
3554
|
+
]);
|
|
3555
|
+
const actionButtons = useMemo(() => {
|
|
3556
|
+
if (!menuContext || !blockMenuService) return [];
|
|
3557
|
+
return blockMenuService.getActionButtons(menuContext);
|
|
3558
|
+
}, [
|
|
3559
|
+
blockMenuService,
|
|
3560
|
+
menuContext,
|
|
3561
|
+
menuVersion
|
|
3562
|
+
]);
|
|
3563
|
+
useEffect(() => {
|
|
3564
|
+
onHoverBlockChange?.(menuContext);
|
|
3565
|
+
}, [menuContext, onHoverBlockChange]);
|
|
3566
|
+
useEffect(() => {
|
|
3567
|
+
if (!operationMenuOpen || !menuContext || !contextRef.current.operationMenuAnchorBlockId) return;
|
|
3568
|
+
if (contextRef.current.operationMenuAnchorBlockId !== menuContext.blockId) {
|
|
3569
|
+
setOperationMenuOpen(false);
|
|
3570
|
+
setOperationMenuContext(null);
|
|
3571
|
+
}
|
|
3572
|
+
}, [menuContext, operationMenuOpen]);
|
|
3573
|
+
useEffect(() => {
|
|
3574
|
+
if (!operationMenuOpen) {
|
|
3575
|
+
contextRef.current.operationMenuAnchorBlockId = null;
|
|
3576
|
+
setOperationMenuContext(null);
|
|
3577
|
+
}
|
|
3578
|
+
}, [operationMenuOpen]);
|
|
3579
|
+
useEffect(() => {
|
|
3580
|
+
if (!operationMenuOpen) return;
|
|
3581
|
+
const handlePointerDown = (event) => {
|
|
3582
|
+
const target = event.target;
|
|
3583
|
+
if (!(target instanceof Element)) return;
|
|
3584
|
+
if (menuRef.current?.contains(target)) return;
|
|
3585
|
+
if (target.closest(`.${OPERATION_MENU_OVERLAY_CLASS}`)) return;
|
|
3586
|
+
contextRef.current.operationMenuAnchorBlockId = null;
|
|
3587
|
+
setOperationMenuOpen(false);
|
|
3588
|
+
setOperationMenuContext(null);
|
|
3589
|
+
};
|
|
3590
|
+
document.addEventListener("pointerdown", handlePointerDown, true);
|
|
3591
|
+
return () => {
|
|
3592
|
+
document.removeEventListener("pointerdown", handlePointerDown, true);
|
|
3593
|
+
};
|
|
3594
|
+
}, [operationMenuOpen]);
|
|
3595
|
+
useEffect(() => {
|
|
3596
|
+
onDragTargetChange?.(contextRef.current.dragTarget);
|
|
3597
|
+
}, [dragIndicator, onDragTargetChange]);
|
|
3598
|
+
const preventEditorSelectionLost = (event) => {
|
|
3599
|
+
if (event.target?.closest("[data-block-drag-handle=\"true\"]")) return;
|
|
3600
|
+
event.preventDefault();
|
|
3601
|
+
};
|
|
3602
|
+
const clearDragPreview = () => {
|
|
3603
|
+
contextRef.current.dragTarget = null;
|
|
3604
|
+
setDragIndicator(null);
|
|
3605
|
+
};
|
|
3606
|
+
const toggleOperationMenu = (context) => {
|
|
3607
|
+
if (!context) {
|
|
3608
|
+
setOperationMenuOpen(false);
|
|
3609
|
+
setOperationMenuContext(null);
|
|
3610
|
+
return;
|
|
3611
|
+
}
|
|
3612
|
+
setOperationMenuOpen((open) => {
|
|
3613
|
+
const shouldOpen = !(open && contextRef.current.operationMenuAnchorBlockId === context.blockId);
|
|
3614
|
+
contextRef.current.operationMenuAnchorBlockId = shouldOpen ? context.blockId : null;
|
|
3615
|
+
setOperationMenuContext(shouldOpen ? context : null);
|
|
3616
|
+
return shouldOpen;
|
|
3617
|
+
});
|
|
3618
|
+
};
|
|
3619
|
+
const handleDragHandlePointerDown = (event) => {
|
|
3620
|
+
if (!menuContext) return;
|
|
3621
|
+
event.stopPropagation();
|
|
3622
|
+
startBlockDragSession({
|
|
3623
|
+
clearDragPreview,
|
|
3624
|
+
clientX: event.clientX,
|
|
3625
|
+
clientY: event.clientY,
|
|
3626
|
+
contextRef,
|
|
3627
|
+
dragGhostContainer: dragLayerRef.current,
|
|
3628
|
+
editor,
|
|
3629
|
+
menuContext,
|
|
3630
|
+
onDragTargetResolve,
|
|
3631
|
+
onDraggingChange: setIsDragging,
|
|
3632
|
+
setDragIndicator,
|
|
3633
|
+
setOperationMenuContext,
|
|
3634
|
+
setOperationMenuOpen,
|
|
3635
|
+
toggleOperationMenu
|
|
3636
|
+
});
|
|
3637
|
+
};
|
|
3638
|
+
const handleDragHandleClick = () => {
|
|
3639
|
+
if (contextRef.current.ignoreNextHandleClick) {
|
|
3640
|
+
contextRef.current.ignoreNextHandleClick = false;
|
|
3641
|
+
return;
|
|
3642
|
+
}
|
|
3643
|
+
toggleOperationMenu(menuContext);
|
|
3644
|
+
};
|
|
3645
|
+
const dropdownItems = useMemo(() => operationMenus.map((item) => ({
|
|
3646
|
+
key: item.key,
|
|
3647
|
+
label: typeof item.label === "function" ? item.label(operationMenuContext) : item.label,
|
|
3648
|
+
onClick: () => {
|
|
3649
|
+
item.onClick(operationMenuContext);
|
|
3650
|
+
setOperationMenuOpen(false);
|
|
3651
|
+
setOperationMenuContext(null);
|
|
3652
|
+
}
|
|
3653
|
+
})), [operationMenus, operationMenuContext]);
|
|
3654
|
+
const shouldRenderPortal = menuContext || dragIndicator;
|
|
3655
|
+
const menuNode = menuContext && !isDragging ? /* @__PURE__ */ jsx("div", {
|
|
3656
|
+
className: styles$12.menu,
|
|
3657
|
+
ref: menuRef,
|
|
3658
|
+
style: menuPosition,
|
|
3659
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3660
|
+
className: styles$12.menuInner,
|
|
3661
|
+
onMouseDown: preventEditorSelectionLost,
|
|
3662
|
+
children: [actionButtons.map((item) => {
|
|
3663
|
+
const title = typeof item.title === "function" ? item.title(menuContext) : item.title;
|
|
3664
|
+
return /* @__PURE__ */ jsx(Button$1, {
|
|
3665
|
+
"aria-label": title,
|
|
3666
|
+
icon: item.icon === "plus" ? /* @__PURE__ */ jsx(Icon, {
|
|
3667
|
+
icon: PlusIcon,
|
|
3668
|
+
size: 14
|
|
3669
|
+
}) : void 0,
|
|
3670
|
+
onClick: () => item.onClick(menuContext),
|
|
3671
|
+
size: "small",
|
|
3672
|
+
title,
|
|
3673
|
+
type: "text"
|
|
3674
|
+
}, item.key);
|
|
3675
|
+
}), /* @__PURE__ */ jsx(Dropdown$1, {
|
|
3676
|
+
align: { points: ["tr", "tl"] },
|
|
3677
|
+
classNames: { root: OPERATION_MENU_OVERLAY_CLASS },
|
|
3678
|
+
menu: { items: dropdownItems },
|
|
3679
|
+
onOpenChange: (open) => {
|
|
3680
|
+
if (!open) {
|
|
3681
|
+
setOperationMenuOpen(false);
|
|
3682
|
+
setOperationMenuContext(null);
|
|
3683
|
+
contextRef.current.operationMenuAnchorBlockId = null;
|
|
3684
|
+
}
|
|
3685
|
+
},
|
|
3686
|
+
open: operationMenuOpen && operationMenuContext?.blockId === menuContext.blockId,
|
|
3687
|
+
trigger: [],
|
|
3688
|
+
children: /* @__PURE__ */ jsx(Button$1, {
|
|
3689
|
+
"aria-label": "Block actions and drag",
|
|
3690
|
+
className: styles$12.dragHandle,
|
|
3691
|
+
"data-block-drag-handle": "true",
|
|
3692
|
+
icon: /* @__PURE__ */ jsx(Icon, {
|
|
3693
|
+
icon: GripVerticalIcon,
|
|
3694
|
+
size: 14
|
|
3695
|
+
}),
|
|
3696
|
+
onClick: handleDragHandleClick,
|
|
3697
|
+
onPointerDown: handleDragHandlePointerDown,
|
|
3698
|
+
size: "small",
|
|
3699
|
+
title: "Block actions and drag",
|
|
3700
|
+
type: "text"
|
|
3701
|
+
})
|
|
3702
|
+
})]
|
|
3703
|
+
})
|
|
3704
|
+
}) : null;
|
|
3705
|
+
const dragLayerNode = /* @__PURE__ */ jsx("div", {
|
|
3706
|
+
"aria-hidden": "true",
|
|
3707
|
+
className: styles$12.dragLayer,
|
|
3708
|
+
"data-block-drag-layer": "true",
|
|
3709
|
+
ref: dragLayerRef
|
|
3710
|
+
});
|
|
3711
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [dragLayerContainer ? createPortal(dragLayerNode, dragLayerContainer) : dragLayerNode, shouldRenderPortal && createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [menuNode, dragIndicator && /* @__PURE__ */ jsx("div", {
|
|
3712
|
+
className: styles$12.dragIndicator,
|
|
3713
|
+
style: {
|
|
3714
|
+
backgroundColor: token.colorPrimary,
|
|
3715
|
+
left: dragIndicator.left,
|
|
3716
|
+
top: dragIndicator.top,
|
|
3717
|
+
width: dragIndicator.width
|
|
3718
|
+
}
|
|
3719
|
+
})] }), document.body)] });
|
|
3720
|
+
};
|
|
3721
|
+
ReactBlockPlugin.displayName = "ReactBlockPlugin";
|
|
3722
|
+
//#endregion
|
|
2598
3723
|
//#region src/plugins/code/react/style.ts
|
|
2599
3724
|
const styles$11 = createStaticStyles(({ css, cssVar }) => ({ codeInline: css`
|
|
2600
3725
|
display: inline;
|
|
@@ -4273,7 +5398,7 @@ const ReactFilePlugin = ({ className, locale, handleUpload, markdownWriter, them
|
|
|
4273
5398
|
throw new Error("No upload handler provided");
|
|
4274
5399
|
},
|
|
4275
5400
|
markdownWriter,
|
|
4276
|
-
theme: theme || styles$
|
|
5401
|
+
theme: theme || styles$16
|
|
4277
5402
|
});
|
|
4278
5403
|
}, [editor]);
|
|
4279
5404
|
return null;
|
|
@@ -5038,6 +6163,10 @@ const ResizeHandle = ({ imageRef, isBlock, onResize, onResizeEnd, onResizeStart,
|
|
|
5038
6163
|
ResizeHandle.displayName = "ResizeHandle";
|
|
5039
6164
|
//#endregion
|
|
5040
6165
|
//#region src/plugins/image/react/components/Image.tsx
|
|
6166
|
+
function getResizedImageWidth(startWidth, deltaX, maxWidth) {
|
|
6167
|
+
const adjustedDeltaX = deltaX * 2;
|
|
6168
|
+
return Math.max(50, Math.min(startWidth + adjustedDeltaX, maxWidth));
|
|
6169
|
+
}
|
|
5041
6170
|
const Image$1 = memo(({ node, className, showScaleInfo = false, handleUpload, onPickFile }) => {
|
|
5042
6171
|
const [isSelected, setSelected] = useLexicalNodeSelection(node.getKey());
|
|
5043
6172
|
const [isHovered, setIsHovered] = useState(false);
|
|
@@ -5073,8 +6202,7 @@ const Image$1 = memo(({ node, className, showScaleInfo = false, handleUpload, on
|
|
|
5073
6202
|
if (!imageRef.current) return;
|
|
5074
6203
|
const aspectRatio = originalSizeRef.current.width / originalSizeRef.current.height;
|
|
5075
6204
|
const maxWidth = imageRef.current.parentElement?.clientWidth || window.innerWidth;
|
|
5076
|
-
const
|
|
5077
|
-
const newWidth = Math.max(50, Math.min(startWidthRef.current + adjustedDeltaX, maxWidth));
|
|
6205
|
+
const newWidth = getResizedImageWidth(startWidthRef.current, deltaX, maxWidth);
|
|
5078
6206
|
setSize({
|
|
5079
6207
|
height: newWidth / aspectRatio,
|
|
5080
6208
|
width: newWidth
|
|
@@ -5148,8 +6276,7 @@ const Image$1 = memo(({ node, className, showScaleInfo = false, handleUpload, on
|
|
|
5148
6276
|
if (!originalSizeRef.current.width || !originalSizeRef.current.height) return;
|
|
5149
6277
|
if (!imageRef.current) return;
|
|
5150
6278
|
const maxWidth = imageRef.current.parentElement?.clientWidth || window.innerWidth;
|
|
5151
|
-
const
|
|
5152
|
-
const finalWidth = Math.max(50, Math.min(startWidthRef.current + adjustedDeltaX, maxWidth));
|
|
6279
|
+
const finalWidth = getResizedImageWidth(startWidthRef.current, deltaX, maxWidth);
|
|
5153
6280
|
const editor = editorRef.current;
|
|
5154
6281
|
if (!editor) return;
|
|
5155
6282
|
editor.update(() => {
|
|
@@ -5235,7 +6362,7 @@ const ReactImagePlugin = ({ theme, className, defaultBlockImage, handleUpload, n
|
|
|
5235
6362
|
onPickFile
|
|
5236
6363
|
});
|
|
5237
6364
|
},
|
|
5238
|
-
theme: theme || styles$
|
|
6365
|
+
theme: theme || styles$17
|
|
5239
6366
|
});
|
|
5240
6367
|
}, []);
|
|
5241
6368
|
return null;
|
|
@@ -5844,9 +6971,9 @@ const ReactListPlugin = ({ enableHotkey = true }) => {
|
|
|
5844
6971
|
editor.registerPlugin(MarkdownPlugin);
|
|
5845
6972
|
editor.registerPlugin(ListPlugin, {
|
|
5846
6973
|
enableHotkey,
|
|
5847
|
-
theme: styles$
|
|
6974
|
+
theme: styles$18
|
|
5848
6975
|
});
|
|
5849
|
-
}, [enableHotkey, styles$
|
|
6976
|
+
}, [enableHotkey, styles$18]);
|
|
5850
6977
|
return null;
|
|
5851
6978
|
};
|
|
5852
6979
|
ReactListPlugin.displayName = "ReactListPlugin";
|
|
@@ -6091,7 +7218,7 @@ const MathEditorContainer = memo(({ children, isBlockMode, mathDOM, onFocus, pre
|
|
|
6091
7218
|
return /* @__PURE__ */ jsx(Popover, {
|
|
6092
7219
|
arrow: false,
|
|
6093
7220
|
content: /* @__PURE__ */ jsx(Flexbox, {
|
|
6094
|
-
className: styles$
|
|
7221
|
+
className: styles$19.mathEditor,
|
|
6095
7222
|
"data-math-editor-container": true,
|
|
6096
7223
|
style: blockWidth ? { width: blockWidth } : void 0,
|
|
6097
7224
|
children
|
|
@@ -6103,7 +7230,7 @@ const MathEditorContainer = memo(({ children, isBlockMode, mathDOM, onFocus, pre
|
|
|
6103
7230
|
padding: 0
|
|
6104
7231
|
} },
|
|
6105
7232
|
children: /* @__PURE__ */ jsx("span", {
|
|
6106
|
-
className: styles$
|
|
7233
|
+
className: styles$19.mathEditorAnchor,
|
|
6107
7234
|
onClick: handleAnchorClick,
|
|
6108
7235
|
ref: anchorRef
|
|
6109
7236
|
})
|
|
@@ -6187,7 +7314,7 @@ const MathEditorContent = memo(({ focusRef, mathNode, onArrowLeft, onArrowRight,
|
|
|
6187
7314
|
maxRows: 6,
|
|
6188
7315
|
minRows: 1
|
|
6189
7316
|
},
|
|
6190
|
-
className: styles$
|
|
7317
|
+
className: styles$19.mathEditorTextArea,
|
|
6191
7318
|
onChange: (e) => {
|
|
6192
7319
|
onValueChange(e.target.value);
|
|
6193
7320
|
},
|
|
@@ -6199,7 +7326,7 @@ const MathEditorContent = memo(({ focusRef, mathNode, onArrowLeft, onArrowRight,
|
|
|
6199
7326
|
variant: "borderless"
|
|
6200
7327
|
}),
|
|
6201
7328
|
latexError && /* @__PURE__ */ jsx(Flexbox, {
|
|
6202
|
-
className: styles$
|
|
7329
|
+
className: styles$19.mathEditorFooter,
|
|
6203
7330
|
horizontal: true,
|
|
6204
7331
|
paddingBlock: 4,
|
|
6205
7332
|
paddingInline: 12,
|
|
@@ -6211,7 +7338,7 @@ const MathEditorContent = memo(({ focusRef, mathNode, onArrowLeft, onArrowRight,
|
|
|
6211
7338
|
})
|
|
6212
7339
|
}),
|
|
6213
7340
|
/* @__PURE__ */ jsx(Flexbox, {
|
|
6214
|
-
className: styles$
|
|
7341
|
+
className: styles$19.mathEditorFooter,
|
|
6215
7342
|
horizontal: true,
|
|
6216
7343
|
justify: "flex-end",
|
|
6217
7344
|
padding: 4,
|
|
@@ -6425,7 +7552,7 @@ const Placeholder = ({ mathBlock }) => {
|
|
|
6425
7552
|
const t = useTranslation();
|
|
6426
7553
|
const node = /* @__PURE__ */ jsx(Text, {
|
|
6427
7554
|
as: "span",
|
|
6428
|
-
className: cx("katex", styles$
|
|
7555
|
+
className: cx("katex", styles$19.mathPlaceholder),
|
|
6429
7556
|
fontSize: mathBlock ? "1.2em" : "1em",
|
|
6430
7557
|
type: "secondary",
|
|
6431
7558
|
children: t("math.placeholder")
|
|
@@ -6526,13 +7653,13 @@ const ReactMathPlugin = ({ className, renderComp, theme }) => {
|
|
|
6526
7653
|
node
|
|
6527
7654
|
});
|
|
6528
7655
|
},
|
|
6529
|
-
theme: theme || styles$
|
|
7656
|
+
theme: theme || styles$19
|
|
6530
7657
|
});
|
|
6531
7658
|
}, [
|
|
6532
7659
|
editor,
|
|
6533
7660
|
className,
|
|
6534
7661
|
theme,
|
|
6535
|
-
styles$
|
|
7662
|
+
styles$19
|
|
6536
7663
|
]);
|
|
6537
7664
|
return /* @__PURE__ */ jsx(MathEdit, { renderComp });
|
|
6538
7665
|
};
|
|
@@ -7405,7 +8532,7 @@ const ReactTablePlugin = ({ className, locale }) => {
|
|
|
7405
8532
|
}, []);
|
|
7406
8533
|
useLayoutEffect(() => {
|
|
7407
8534
|
if (locale) editor.registerLocale(locale);
|
|
7408
|
-
editor.registerPlugin(TablePlugin, { theme: cx(styles$
|
|
8535
|
+
editor.registerPlugin(TablePlugin, { theme: cx(styles$20, className) });
|
|
7409
8536
|
}, []);
|
|
7410
8537
|
useLexicalEditor((editor) => {
|
|
7411
8538
|
setLexicalEditor(editor);
|
|
@@ -7882,4 +9009,4 @@ function disableHotReload() {
|
|
|
7882
9009
|
}
|
|
7883
9010
|
}
|
|
7884
9011
|
//#endregion
|
|
7885
|
-
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, AutoCompletePlugin, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodemirrorPlugin, CommonPlugin, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, FilePlugin, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HeadlessEditor, HotkeyEnum, HotkeyScopeEnum, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodeService, IUploadService, ImagePlugin, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkPlugin, ListPlugin, LitexmlDataSource, LitexmlPlugin, LitexmlService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MarkdownPlugin, MathPlugin, MentionPlugin, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactCodePlugin, ReactCodeblockPlugin, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactFilePlugin, ReactHRPlugin, ReactImagePlugin, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactListPlugin, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactNodePlugin, ReactPlainText, ReactSlashOption, ReactSlashPlugin, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SlashMenu, SlashPlugin, TablePlugin, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, VirtualBlockPlugin, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|
|
9012
|
+
export { $closest, $closestNodeType, $createCursorNode, $getNearestNodeFromDOMNode, $getNodeFromDOMNode, $isCardLikeElementNode, $isCursorNode, AutoCompletePlugin, BlockMenuService, BlockPlugin, CardLikeElementNode, CodePlugin, CodeblockPlugin, CodemirrorPlugin, CommonPlugin, DEFAULT_HEADLESS_EDITOR_PLUGINS, DOM_DOCUMENT_FRAGMENT_TYPE, DOM_DOCUMENT_TYPE, DOM_ELEMENT_TYPE, DOM_TEXT_TYPE, DataSource, DiffAction, EDITOR_THEME_KEY, FilePlugin, GET_MARKDOWN_SELECTION_COMMAND, HIDE_TOOLBAR_COMMAND, HOVER_COMMAND, HRPlugin, HeadlessEditor, HotkeyEnum, HotkeyScopeEnum, IBlockMenuService, ILinkService, ILitexmlService, IMarkdownShortCutService, INSERT_CHECK_LIST_COMMAND, INSERT_CODEINLINE_COMMAND, INSERT_CODEMIRROR_COMMAND, INSERT_FILE_COMMAND, INSERT_HEADING_COMMAND, INSERT_HORIZONTAL_RULE_COMMAND, INSERT_IMAGE_COMMAND, INSERT_LINK_COMMAND, INSERT_LINK_HIGHLIGHT_COMMAND, INSERT_MARKDOWN_COMMAND, INSERT_MATH_COMMAND, INSERT_MENTION_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_QUOTE_COMMAND, INSERT_TABLE_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INodePlugin, INodeService, IUploadService, ImagePlugin, Kernel, KeyEnum, LITEXML_APPLY_COMMAND, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND, LITEXML_INSERT_COMMAND, LITEXML_MODIFY_COMMAND, LITEXML_REMOVE_COMMAND, LexicalErrorBoundary, LexicalPortalContainer, LinkHighlightPlugin, LinkPlugin, ListPlugin, LitexmlDataSource, LitexmlPlugin, LitexmlService, MARKDOWN_READER_LEVEL_HIGH, MARKDOWN_READER_LEVEL_NORMAL, MARKDOWN_WRITER_LEVEL_MAX, MOVE_BLOCK_COMMAND, MarkdownPlugin, MathPlugin, MentionPlugin, REMOVE_LIST_COMMAND, ReactAutoCompletePlugin, ReactBlockPlugin, ReactCodePlugin, ReactCodeblockPlugin, ReactCodemirrorPlugin, ReactEditor, ReactEditorContent, ReactFilePlugin, ReactHRPlugin, ReactImagePlugin, ReactLinkHighlightPlugin, ReactLinkPlugin, ReactListPlugin, ReactLiteXmlPlugin, ReactMarkdownPlugin, ReactMathPlugin, ReactMentionPlugin, ReactNodePlugin, ReactPlainText, ReactSlashOption, ReactSlashPlugin, ReactTablePlugin, ReactToolbarPlugin, ReactVirtualBlockPlugin, SELECT_AFTER_CODEMIRROR_COMMAND, SELECT_BEFORE_CODEMIRROR_COMMAND, SELECT_TABLE_COMMAND, SHOW_TOOLBAR_COMMAND, SlashMenu, SlashPlugin, TablePlugin, UPDATE_CODEBLOCK_LANG, UPDATE_LIST_START_COMMAND, UPLOAD_PRIORITY_HIGH, UPLOAD_PRIORITY_LOW, UPLOAD_PRIORITY_MEDIUM, UploadPlugin, VirtualBlockPlugin, assert, browserDebug, bundledLanguagesInfo, compareNodeOrder, createDebugLogger, createEmptyEditorState, createHeadlessEditor, cursorNodeSerialized, debugLogger, debugLoggers, detectCodeLanguage, detectLanguage, devConsole, disableHotReload, enableHotReload, genServiceId, generateEditorId, getHotkeyById, getKernelFromEditor, getKernelFromEditorConfig, getNodeKeyFromDOMNode, getParentElement, isDOMNode, isDocumentFragment, isPunctuationChar, isPureUrl, isValidUrl, moment, noop, prodSafeLogger, reconcileDecorator, registerBlockMoveCommand, registerEditorKernel, registerLinkHighlightCommand, registerToolbarCommand, resetRandomKey, scrollIntoView, unregisterEditorKernel, useHasDiffNode, useLexicalComposerContext, useLexicalEditor };
|