onchain-lexical-instance 0.0.8 → 0.0.9
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/dist/OnchainLexicalInstance.js +119 -52
- package/dist/OnchainLexicalInstance.mjs +118 -54
- package/package.json +4 -4
- package/src/const.ts +15 -0
- package/src/image/ImageComponent.tsx +18 -14
- package/src/image/index.tsx +1 -0
- package/src/instancePlugin.ts +2 -2
- package/src/internalLink/index.tsx +15 -2
- package/src/internalLink/internalLinkComponent.tsx +36 -36
- package/src/paragraph/title.ts +12 -5
- package/src/placeholder/index.ts +1 -0
- package/src/utils.ts +51 -6
|
@@ -8,26 +8,19 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
var lexical = require('lexical');
|
|
12
|
-
var utils$1 = require('@lexical/utils');
|
|
13
|
-
var traversal = require('onchain-utility/traversal');
|
|
14
11
|
var code = require('@lexical/code');
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var onchainUtility = require('onchain-utility');
|
|
12
|
+
var utils$1 = require('@lexical/utils');
|
|
13
|
+
var lexical = require('lexical');
|
|
14
|
+
var LexicalHorizontalRuleNode = require('@lexical/react/LexicalHorizontalRuleNode');
|
|
19
15
|
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
20
|
-
var instanceConfig = require('onchain-lexical-context/instanceConfig');
|
|
21
|
-
var Skeleton = require('onchain-lexical-ui/Skeleton');
|
|
22
16
|
var React = require('react');
|
|
23
17
|
var jsxRuntime = require('react/jsx-runtime');
|
|
24
|
-
var
|
|
25
|
-
var
|
|
26
|
-
var Icon = require('onchain-lexical-ui/Icon');
|
|
27
|
-
var LexicalHorizontalRuleNode = require('@lexical/react/LexicalHorizontalRuleNode');
|
|
18
|
+
var onchainLexicalMarkdown = require('onchain-lexical-markdown');
|
|
19
|
+
var list = require('@lexical/list');
|
|
28
20
|
var selection = require('@lexical/selection');
|
|
29
21
|
var table = require('@lexical/table');
|
|
30
22
|
var useLexicalNodeSelection = require('@lexical/react/useLexicalNodeSelection');
|
|
23
|
+
var richText = require('@lexical/rich-text');
|
|
31
24
|
var useLexicalEditable = require('@lexical/react/useLexicalEditable');
|
|
32
25
|
var EquationEditor = require('onchain-lexical-ui/EquationEditor');
|
|
33
26
|
var KatexRenderer = require('onchain-lexical-ui/KatexRenderer');
|
|
@@ -41,9 +34,16 @@ var LexicalNestedComposer = require('@lexical/react/LexicalNestedComposer');
|
|
|
41
34
|
var LexicalRichTextPlugin = require('@lexical/react/LexicalRichTextPlugin');
|
|
42
35
|
var onchainLexicalContext = require('onchain-lexical-context');
|
|
43
36
|
var collaboration = require('onchain-lexical-context/collaboration');
|
|
37
|
+
var instanceConfig = require('onchain-lexical-context/instanceConfig');
|
|
44
38
|
var sharedHistory = require('onchain-lexical-context/sharedHistory');
|
|
45
39
|
var ContentEditable = require('onchain-lexical-ui/ContentEditable');
|
|
46
40
|
var ImageResizer = require('onchain-lexical-ui/ImageResizer');
|
|
41
|
+
var onchainUtility = require('onchain-utility');
|
|
42
|
+
var traversal = require('onchain-utility/traversal');
|
|
43
|
+
var Skeleton = require('onchain-lexical-ui/Skeleton');
|
|
44
|
+
var settings = require('onchain-lexical-context/settings');
|
|
45
|
+
var DropDown = require('onchain-lexical-ui/DropDown');
|
|
46
|
+
var Icon = require('onchain-lexical-ui/Icon');
|
|
47
47
|
var hashtag = require('@lexical/hashtag');
|
|
48
48
|
var Button = require('onchain-lexical-ui/Button');
|
|
49
49
|
var Dialog = require('onchain-lexical-ui/Dialog');
|
|
@@ -142,12 +142,28 @@ const fixedAddress = new Map();
|
|
|
142
142
|
|
|
143
143
|
/** 用来存储内联链接,更新文本函数,用来实现链接目标标题变化时,引用处可以实时更新 */
|
|
144
144
|
const internalLinkNameUpdateMap = new Map();
|
|
145
|
+
|
|
146
|
+
/** 打开创建实例节点 */
|
|
145
147
|
const OPEN_CREATE_WINDOW = lexical.createCommand('OPEN_CREATE_WINDOW');
|
|
148
|
+
|
|
149
|
+
/** 添加新的实例节点 */
|
|
146
150
|
const ADD_NEW_INSTANCE_NODE = lexical.createCommand('ADD_NEW_INSTANCE_NODE');
|
|
151
|
+
|
|
152
|
+
/** 删除实例节点 */
|
|
147
153
|
const DELETE_INSTANCE_NODE = 'DELETE_INSTANCE_NODE';
|
|
154
|
+
|
|
155
|
+
/** 插入参数 */
|
|
148
156
|
const INSERT_PARAMETERS = lexical.createCommand('INSERT_PARAMETERS');
|
|
157
|
+
|
|
158
|
+
/** 富文本 DecoratorNode 节点组件更新事件*/
|
|
149
159
|
const COMPONENT_UPDATE = lexical.createCommand('COMPONENT_UPDATE');
|
|
150
160
|
|
|
161
|
+
/** 标题更新事件 */
|
|
162
|
+
const INSTANCE_TITLE_UPDATE = lexical.createCommand('INSTANCE_TITLE_UPDATE');
|
|
163
|
+
|
|
164
|
+
/** 获取禁止编辑dom节点选择器 */
|
|
165
|
+
const DisableSelector = `[contenteditable='false']:not([ignorecontenteditable])`;
|
|
166
|
+
|
|
151
167
|
/**
|
|
152
168
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
153
169
|
*
|
|
@@ -417,6 +433,7 @@ class PlaceholderDecoratorNode extends lexical.DecoratorNode {
|
|
|
417
433
|
pointer-events: none;
|
|
418
434
|
user-select: none;
|
|
419
435
|
`;
|
|
436
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
420
437
|
return span;
|
|
421
438
|
}
|
|
422
439
|
updateDOM() {
|
|
@@ -565,7 +582,16 @@ class InstanceTitleNode extends InstanceHeadingNode {
|
|
|
565
582
|
if (instanceNode && instanceNode.__instance.value) {
|
|
566
583
|
const text = this.getTextContent().trim();
|
|
567
584
|
setInstanceAttrValue(instanceNode.__instance.value, 'insDesc', text);
|
|
568
|
-
|
|
585
|
+
const editor = lexical.$getEditor();
|
|
586
|
+
Promise.resolve().then(() => {
|
|
587
|
+
editor.read(() => {
|
|
588
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
589
|
+
isInput: true,
|
|
590
|
+
number: instanceNode.__instance.value.number,
|
|
591
|
+
title: text
|
|
592
|
+
});
|
|
593
|
+
});
|
|
594
|
+
});
|
|
569
595
|
}
|
|
570
596
|
return super.updateDOM(prevNode, dom, config);
|
|
571
597
|
}
|
|
@@ -837,7 +863,14 @@ function updateRelatedInternalLink(nodes) {
|
|
|
837
863
|
const insNodes = nodes.filter(node => $isInstanceNode(node));
|
|
838
864
|
if (insNodes.length) {
|
|
839
865
|
insNodes.forEach(node => {
|
|
840
|
-
|
|
866
|
+
const editor = lexical.$getEditor();
|
|
867
|
+
Promise.resolve().then(() => {
|
|
868
|
+
editor.read(() => {
|
|
869
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
870
|
+
number: node.__instance.value.number
|
|
871
|
+
});
|
|
872
|
+
});
|
|
873
|
+
});
|
|
841
874
|
});
|
|
842
875
|
}
|
|
843
876
|
}
|
|
@@ -853,7 +886,7 @@ function nodeMoveUp(nodes) {
|
|
|
853
886
|
previous?.insertBefore(current);
|
|
854
887
|
}
|
|
855
888
|
}
|
|
856
|
-
updateRelatedInternalLink(nodes);
|
|
889
|
+
updateRelatedInternalLink($isInstanceNode(previous) ? [...nodes, previous] : nodes);
|
|
857
890
|
}
|
|
858
891
|
}
|
|
859
892
|
function nodeMoveDown(nodes) {
|
|
@@ -868,7 +901,7 @@ function nodeMoveDown(nodes) {
|
|
|
868
901
|
next?.insertAfter(current);
|
|
869
902
|
}
|
|
870
903
|
}
|
|
871
|
-
updateRelatedInternalLink(nodes);
|
|
904
|
+
updateRelatedInternalLink($isInstanceNode(next) ? [...nodes, next] : nodes);
|
|
872
905
|
}
|
|
873
906
|
}
|
|
874
907
|
async function $nodeUpgrade(nodes) {
|
|
@@ -1011,6 +1044,27 @@ function setHSEntryMap(hs, instanceNode) {
|
|
|
1011
1044
|
return state;
|
|
1012
1045
|
});
|
|
1013
1046
|
}
|
|
1047
|
+
function useContentEditable() {
|
|
1048
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
1049
|
+
const [contentEditable, setContentEditable] = React.useState(true);
|
|
1050
|
+
const $updateContentEditable = React.useCallback(() => {
|
|
1051
|
+
const selection = lexical.$getSelection();
|
|
1052
|
+
if (selection) {
|
|
1053
|
+
setContentEditable(!selection.getNodes().some(node => {
|
|
1054
|
+
return editor.getElementByKey(node.getKey())?.closest(DisableSelector);
|
|
1055
|
+
}));
|
|
1056
|
+
}
|
|
1057
|
+
}, [editor]);
|
|
1058
|
+
React.useEffect(() => {
|
|
1059
|
+
return editor.registerCommand(lexical.SELECTION_CHANGE_COMMAND, _payload => {
|
|
1060
|
+
$updateContentEditable();
|
|
1061
|
+
return false;
|
|
1062
|
+
}, lexical.COMMAND_PRIORITY_CRITICAL);
|
|
1063
|
+
}, [editor, $updateContentEditable]);
|
|
1064
|
+
return {
|
|
1065
|
+
contentEditable
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1014
1068
|
|
|
1015
1069
|
/**
|
|
1016
1070
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -22342,6 +22396,7 @@ class ImageNode extends lexical.DecoratorNode {
|
|
|
22342
22396
|
if (className !== undefined) {
|
|
22343
22397
|
span.className = className;
|
|
22344
22398
|
}
|
|
22399
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
22345
22400
|
return span;
|
|
22346
22401
|
}
|
|
22347
22402
|
updateDOM() {
|
|
@@ -23674,7 +23729,7 @@ const InstancePlugin = props => {
|
|
|
23674
23729
|
const selection = lexical.$getSelection();
|
|
23675
23730
|
if (selection) {
|
|
23676
23731
|
return selection.getNodes().some(node => {
|
|
23677
|
-
return editor.getElementByKey(node.getKey())?.closest(
|
|
23732
|
+
return editor.getElementByKey(node.getKey())?.closest(DisableSelector);
|
|
23678
23733
|
});
|
|
23679
23734
|
}
|
|
23680
23735
|
return false;
|
|
@@ -23765,43 +23820,38 @@ styleInject(css_248z$3);
|
|
|
23765
23820
|
/* eslint-disable @lexical/rules-of-lexical */
|
|
23766
23821
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
23767
23822
|
|
|
23768
|
-
function InternalLinkComponent({
|
|
23769
|
-
|
|
23770
|
-
|
|
23771
|
-
|
|
23772
|
-
|
|
23773
|
-
nodeKey
|
|
23774
|
-
}) {
|
|
23823
|
+
function InternalLinkComponent(props) {
|
|
23824
|
+
const {
|
|
23825
|
+
editor,
|
|
23826
|
+
number
|
|
23827
|
+
} = props;
|
|
23775
23828
|
const [name, setName] = React.useState();
|
|
23776
23829
|
const [serial, setSerial] = React.useState();
|
|
23777
|
-
const update = React.useCallback(function () {
|
|
23778
|
-
editor.read(() => {
|
|
23779
|
-
const node = $getInstanceNodeByNumber(number);
|
|
23780
|
-
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
23781
|
-
setSerial(node.getSerialNumber());
|
|
23782
|
-
});
|
|
23783
|
-
}, []);
|
|
23784
23830
|
React.useEffect(() => {
|
|
23785
|
-
|
|
23831
|
+
Promise.resolve().then(() => {
|
|
23832
|
+
// 需要等待节点载入富文本后才能获取到实例节点
|
|
23833
|
+
editor.read(() => {
|
|
23834
|
+
const node = $getInstanceNodeByNumber(number);
|
|
23835
|
+
if (node) {
|
|
23836
|
+
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
23837
|
+
setSerial(node.getSerialNumber());
|
|
23838
|
+
}
|
|
23839
|
+
});
|
|
23840
|
+
});
|
|
23786
23841
|
}, []);
|
|
23787
23842
|
React.useEffect(() => {
|
|
23788
|
-
|
|
23789
|
-
|
|
23790
|
-
|
|
23791
|
-
|
|
23792
|
-
|
|
23793
|
-
|
|
23794
|
-
|
|
23795
|
-
|
|
23796
|
-
|
|
23797
|
-
|
|
23798
|
-
|
|
23799
|
-
|
|
23800
|
-
internalLinkNameUpdateMap.set(number, map);
|
|
23801
|
-
}
|
|
23802
|
-
return () => {
|
|
23803
|
-
map.delete(number);
|
|
23804
|
-
};
|
|
23843
|
+
return utils$1.mergeRegister(editor.registerCommand(INSTANCE_TITLE_UPDATE, priority => {
|
|
23844
|
+
if (priority.number === number) {
|
|
23845
|
+
editor.read(() => {
|
|
23846
|
+
const node = $getInstanceNodeByNumber(priority.number);
|
|
23847
|
+
if (priority.title !== undefined && priority.title !== null) {
|
|
23848
|
+
setName(priority.title);
|
|
23849
|
+
}
|
|
23850
|
+
setSerial(node.getSerialNumber());
|
|
23851
|
+
});
|
|
23852
|
+
}
|
|
23853
|
+
return false;
|
|
23854
|
+
}, lexical.COMMAND_PRIORITY_EDITOR));
|
|
23805
23855
|
}, []);
|
|
23806
23856
|
if (name) {
|
|
23807
23857
|
return /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
@@ -23836,12 +23886,23 @@ class InternalLinkNode extends lexical.TextDecoratorNode {
|
|
|
23836
23886
|
return new InternalLinkNode(node.__number, node.__key);
|
|
23837
23887
|
}
|
|
23838
23888
|
static importJSON(serializedNode) {
|
|
23839
|
-
return $createInternalLinkNode(serializedNode.
|
|
23889
|
+
return $createInternalLinkNode(serializedNode.number).updateFromJSON(serializedNode);
|
|
23840
23890
|
}
|
|
23841
23891
|
constructor(number, key) {
|
|
23842
23892
|
super(key);
|
|
23843
23893
|
this.__number = number;
|
|
23844
23894
|
}
|
|
23895
|
+
exportJSON() {
|
|
23896
|
+
return {
|
|
23897
|
+
...super.exportJSON(),
|
|
23898
|
+
number: this.__number
|
|
23899
|
+
};
|
|
23900
|
+
}
|
|
23901
|
+
createDOM(config, editor) {
|
|
23902
|
+
const span = super.createDOM(config, editor);
|
|
23903
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
23904
|
+
return span;
|
|
23905
|
+
}
|
|
23845
23906
|
updateDOM(prevNode, dom, config) {
|
|
23846
23907
|
return super.updateDOM(prevNode, dom, config);
|
|
23847
23908
|
}
|
|
@@ -24620,6 +24681,9 @@ function ImageComponent({
|
|
|
24620
24681
|
const onResizeStart = () => {
|
|
24621
24682
|
setIsResizing(true);
|
|
24622
24683
|
};
|
|
24684
|
+
const {
|
|
24685
|
+
contentEditable
|
|
24686
|
+
} = useContentEditable();
|
|
24623
24687
|
const {
|
|
24624
24688
|
historyState
|
|
24625
24689
|
} = sharedHistory.useSharedHistoryContext();
|
|
@@ -24660,7 +24724,7 @@ function ImageComponent({
|
|
|
24660
24724
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
24661
24725
|
})]
|
|
24662
24726
|
})
|
|
24663
|
-
}), resizable && lexical.$isNodeSelection(selection) && isFocused && /*#__PURE__*/jsxRuntime.jsx(ImageResizer, {
|
|
24727
|
+
}), resizable && lexical.$isNodeSelection(selection) && isFocused && contentEditable && /*#__PURE__*/jsxRuntime.jsx(ImageResizer, {
|
|
24664
24728
|
showCaption: showCaption,
|
|
24665
24729
|
setShowCaption: setShowCaption,
|
|
24666
24730
|
editor: editor,
|
|
@@ -25073,10 +25137,12 @@ exports.CollapsibleContainerNode = CollapsibleContainerNode;
|
|
|
25073
25137
|
exports.CollapsibleContentNode = CollapsibleContentNode;
|
|
25074
25138
|
exports.CollapsibleTitleNode = CollapsibleTitleNode;
|
|
25075
25139
|
exports.DELETE_INSTANCE_NODE = DELETE_INSTANCE_NODE;
|
|
25140
|
+
exports.DisableSelector = DisableSelector;
|
|
25076
25141
|
exports.Fragment = Fragment;
|
|
25077
25142
|
exports.INSERT_COLLAPSIBLE_COMMAND = INSERT_COLLAPSIBLE_COMMAND;
|
|
25078
25143
|
exports.INSERT_INS_HORIZONTAL_RULE_COMMAND = INSERT_INS_HORIZONTAL_RULE_COMMAND;
|
|
25079
25144
|
exports.INSERT_PARAMETERS = INSERT_PARAMETERS;
|
|
25145
|
+
exports.INSTANCE_TITLE_UPDATE = INSTANCE_TITLE_UPDATE;
|
|
25080
25146
|
exports.ImageNode = ImageNode;
|
|
25081
25147
|
exports.InlineImageNode = InlineImageNode;
|
|
25082
25148
|
exports.InstanceCodeHighlightNode = InstanceCodeHighlightNode;
|
|
@@ -25127,3 +25193,4 @@ exports.setInstanceAttrValue = setInstanceAttrValue;
|
|
|
25127
25193
|
exports.setTemporaryContentText = setTemporaryContentText;
|
|
25128
25194
|
exports.updateChildrenListItemValue = updateChildrenListItemValue;
|
|
25129
25195
|
exports.updateRelatedInternalLink = updateRelatedInternalLink;
|
|
25196
|
+
exports.useContentEditable = useContentEditable;
|
|
@@ -6,27 +6,20 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { createCommand, ElementNode, $applyNodeReplacement, isHTMLElement, setNodeIndentFromDOM, DecoratorNode, $isTextNode, $createTextNode, TextNode as TextNode$1, $getSelection, $isRootOrShadowRoot, $isRootNode, $getEditor, $getNodeByKey, scrollIntoViewIfNeeded, $isElementNode, ParagraphNode, COMMAND_PRIORITY_EDITOR, $getSiblingCaret, $isTabNode, $createTabNode, $createLineBreakNode, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, INSERT_TAB_COMMAND, $insertNodes, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, KEY_ARROW_UP_COMMAND, $isRangeSelection, KEY_ARROW_DOWN_COMMAND, MOVE_TO_START, MOVE_TO_END, $isLineBreakNode, $rewindSiblingCaret, $createParagraphNode, createEditor, RootNode, LineBreakNode, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_NORMAL, $getPreviousSelection, DELETE_CHARACTER_COMMAND, COMMAND_PRIORITY_CRITICAL, TextDecoratorNode, COMMAND_PRIORITY_HIGH, CLICK_COMMAND, SELECTION_CHANGE_COMMAND, KEY_ESCAPE_COMMAND, $isNodeSelection, $createNodeSelection, $setSelection, DRAGSTART_COMMAND, KEY_ENTER_COMMAND } from 'lexical';
|
|
10
|
-
import { $findMatchingParent, addClassNamesToElement, mergeRegister, removeClassNamesFromElement, $getAdjacentCaret, isHTMLElement as isHTMLElement$1, IS_CHROME, $insertNodeToNearestRoot, $getNearestNodeOfType, $descendantsMatching } from '@lexical/utils';
|
|
11
|
-
import { dfs as dfs$1 } from 'onchain-utility/traversal';
|
|
12
9
|
import { $isCodeNode, CodeNode } from '@lexical/code';
|
|
13
|
-
import { $
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { hasOwnProperty, dfs, translateI18n } from 'onchain-utility';
|
|
10
|
+
import { $findMatchingParent, addClassNamesToElement, mergeRegister, removeClassNamesFromElement, $getAdjacentCaret, isHTMLElement as isHTMLElement$1, IS_CHROME, $insertNodeToNearestRoot, $getNearestNodeOfType, $descendantsMatching } from '@lexical/utils';
|
|
11
|
+
import { createCommand, ElementNode, $applyNodeReplacement, isHTMLElement, setNodeIndentFromDOM, DecoratorNode, $getEditor, $isTextNode, $createTextNode, TextNode as TextNode$1, $getSelection, $isRootOrShadowRoot, $isRootNode, $getNodeByKey, scrollIntoViewIfNeeded, $isElementNode, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, ParagraphNode, COMMAND_PRIORITY_EDITOR, $getSiblingCaret, $isTabNode, $createTabNode, $createLineBreakNode, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, INSERT_TAB_COMMAND, $insertNodes, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, KEY_ARROW_UP_COMMAND, $isRangeSelection, KEY_ARROW_DOWN_COMMAND, MOVE_TO_START, MOVE_TO_END, $isLineBreakNode, $rewindSiblingCaret, $createParagraphNode, createEditor, RootNode, LineBreakNode, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_NORMAL, $getPreviousSelection, DELETE_CHARACTER_COMMAND, TextDecoratorNode, COMMAND_PRIORITY_HIGH, CLICK_COMMAND, KEY_ESCAPE_COMMAND, $isNodeSelection, $createNodeSelection, $setSelection, DRAGSTART_COMMAND, KEY_ENTER_COMMAND } from 'lexical';
|
|
12
|
+
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
17
13
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
18
|
-
import { useInstanceConfig } from 'onchain-lexical-context/instanceConfig';
|
|
19
|
-
import Skeleton from 'onchain-lexical-ui/Skeleton';
|
|
20
14
|
import * as React from 'react';
|
|
21
|
-
import React__default, { useState, useEffect, useMemo,
|
|
15
|
+
import React__default, { useState, useCallback, useEffect, useMemo, useRef, Suspense } from 'react';
|
|
22
16
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
23
|
-
import {
|
|
24
|
-
import
|
|
25
|
-
import { Icon, StaticIcon } from 'onchain-lexical-ui/Icon';
|
|
26
|
-
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
17
|
+
import { $textToRichNodes } from 'onchain-lexical-markdown';
|
|
18
|
+
import { $isListNode, $isListItemNode, $createListItemNode, ListItemNode, ListNode } from '@lexical/list';
|
|
27
19
|
import { $setBlocksType } from '@lexical/selection';
|
|
28
20
|
import { TableNode, INSERT_TABLE_COMMAND, $findTableNode, PIXEL_VALUE_REG_EXP, $isTableRowNode, $createTableRowNode, $createTableCellNode, TableCellHeaderStates } from '@lexical/table';
|
|
29
21
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
22
|
+
import { HeadingNode, $isHeadingNode, $isQuoteNode, QuoteNode } from '@lexical/rich-text';
|
|
30
23
|
import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
|
|
31
24
|
import EquationEditor from 'onchain-lexical-ui/EquationEditor';
|
|
32
25
|
import KatexRenderer from 'onchain-lexical-ui/KatexRenderer';
|
|
@@ -40,9 +33,16 @@ import { LexicalNestedComposer } from '@lexical/react/LexicalNestedComposer';
|
|
|
40
33
|
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
|
|
41
34
|
import { upload, deleteUpload } from 'onchain-lexical-context';
|
|
42
35
|
import { createWebsocketProvider } from 'onchain-lexical-context/collaboration';
|
|
36
|
+
import { useInstanceConfig } from 'onchain-lexical-context/instanceConfig';
|
|
43
37
|
import { useSharedHistoryContext } from 'onchain-lexical-context/sharedHistory';
|
|
44
38
|
import ContentEditable from 'onchain-lexical-ui/ContentEditable';
|
|
45
39
|
import ImageResizer from 'onchain-lexical-ui/ImageResizer';
|
|
40
|
+
import { hasOwnProperty, dfs, translateI18n } from 'onchain-utility';
|
|
41
|
+
import { dfs as dfs$1 } from 'onchain-utility/traversal';
|
|
42
|
+
import Skeleton from 'onchain-lexical-ui/Skeleton';
|
|
43
|
+
import { useSettings } from 'onchain-lexical-context/settings';
|
|
44
|
+
import DropDown, { DropDownItem } from 'onchain-lexical-ui/DropDown';
|
|
45
|
+
import { Icon, StaticIcon } from 'onchain-lexical-ui/Icon';
|
|
46
46
|
import { HashtagNode } from '@lexical/hashtag';
|
|
47
47
|
import Button from 'onchain-lexical-ui/Button';
|
|
48
48
|
import { DialogActions } from 'onchain-lexical-ui/Dialog';
|
|
@@ -128,12 +128,28 @@ const fixedAddress = new Map();
|
|
|
128
128
|
|
|
129
129
|
/** 用来存储内联链接,更新文本函数,用来实现链接目标标题变化时,引用处可以实时更新 */
|
|
130
130
|
const internalLinkNameUpdateMap = new Map();
|
|
131
|
+
|
|
132
|
+
/** 打开创建实例节点 */
|
|
131
133
|
const OPEN_CREATE_WINDOW = createCommand('OPEN_CREATE_WINDOW');
|
|
134
|
+
|
|
135
|
+
/** 添加新的实例节点 */
|
|
132
136
|
const ADD_NEW_INSTANCE_NODE = createCommand('ADD_NEW_INSTANCE_NODE');
|
|
137
|
+
|
|
138
|
+
/** 删除实例节点 */
|
|
133
139
|
const DELETE_INSTANCE_NODE = 'DELETE_INSTANCE_NODE';
|
|
140
|
+
|
|
141
|
+
/** 插入参数 */
|
|
134
142
|
const INSERT_PARAMETERS = createCommand('INSERT_PARAMETERS');
|
|
143
|
+
|
|
144
|
+
/** 富文本 DecoratorNode 节点组件更新事件*/
|
|
135
145
|
const COMPONENT_UPDATE = createCommand('COMPONENT_UPDATE');
|
|
136
146
|
|
|
147
|
+
/** 标题更新事件 */
|
|
148
|
+
const INSTANCE_TITLE_UPDATE = createCommand('INSTANCE_TITLE_UPDATE');
|
|
149
|
+
|
|
150
|
+
/** 获取禁止编辑dom节点选择器 */
|
|
151
|
+
const DisableSelector = `[contenteditable='false']:not([ignorecontenteditable])`;
|
|
152
|
+
|
|
137
153
|
/**
|
|
138
154
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
139
155
|
*
|
|
@@ -403,6 +419,7 @@ class PlaceholderDecoratorNode extends DecoratorNode {
|
|
|
403
419
|
pointer-events: none;
|
|
404
420
|
user-select: none;
|
|
405
421
|
`;
|
|
422
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
406
423
|
return span;
|
|
407
424
|
}
|
|
408
425
|
updateDOM() {
|
|
@@ -551,7 +568,16 @@ class InstanceTitleNode extends InstanceHeadingNode {
|
|
|
551
568
|
if (instanceNode && instanceNode.__instance.value) {
|
|
552
569
|
const text = this.getTextContent().trim();
|
|
553
570
|
setInstanceAttrValue(instanceNode.__instance.value, 'insDesc', text);
|
|
554
|
-
|
|
571
|
+
const editor = $getEditor();
|
|
572
|
+
Promise.resolve().then(() => {
|
|
573
|
+
editor.read(() => {
|
|
574
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
575
|
+
isInput: true,
|
|
576
|
+
number: instanceNode.__instance.value.number,
|
|
577
|
+
title: text
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
});
|
|
555
581
|
}
|
|
556
582
|
return super.updateDOM(prevNode, dom, config);
|
|
557
583
|
}
|
|
@@ -823,7 +849,14 @@ function updateRelatedInternalLink(nodes) {
|
|
|
823
849
|
const insNodes = nodes.filter(node => $isInstanceNode(node));
|
|
824
850
|
if (insNodes.length) {
|
|
825
851
|
insNodes.forEach(node => {
|
|
826
|
-
|
|
852
|
+
const editor = $getEditor();
|
|
853
|
+
Promise.resolve().then(() => {
|
|
854
|
+
editor.read(() => {
|
|
855
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
856
|
+
number: node.__instance.value.number
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
});
|
|
827
860
|
});
|
|
828
861
|
}
|
|
829
862
|
}
|
|
@@ -839,7 +872,7 @@ function nodeMoveUp(nodes) {
|
|
|
839
872
|
previous?.insertBefore(current);
|
|
840
873
|
}
|
|
841
874
|
}
|
|
842
|
-
updateRelatedInternalLink(nodes);
|
|
875
|
+
updateRelatedInternalLink($isInstanceNode(previous) ? [...nodes, previous] : nodes);
|
|
843
876
|
}
|
|
844
877
|
}
|
|
845
878
|
function nodeMoveDown(nodes) {
|
|
@@ -854,7 +887,7 @@ function nodeMoveDown(nodes) {
|
|
|
854
887
|
next?.insertAfter(current);
|
|
855
888
|
}
|
|
856
889
|
}
|
|
857
|
-
updateRelatedInternalLink(nodes);
|
|
890
|
+
updateRelatedInternalLink($isInstanceNode(next) ? [...nodes, next] : nodes);
|
|
858
891
|
}
|
|
859
892
|
}
|
|
860
893
|
async function $nodeUpgrade(nodes) {
|
|
@@ -997,6 +1030,27 @@ function setHSEntryMap(hs, instanceNode) {
|
|
|
997
1030
|
return state;
|
|
998
1031
|
});
|
|
999
1032
|
}
|
|
1033
|
+
function useContentEditable() {
|
|
1034
|
+
const [editor] = useLexicalComposerContext();
|
|
1035
|
+
const [contentEditable, setContentEditable] = useState(true);
|
|
1036
|
+
const $updateContentEditable = useCallback(() => {
|
|
1037
|
+
const selection = $getSelection();
|
|
1038
|
+
if (selection) {
|
|
1039
|
+
setContentEditable(!selection.getNodes().some(node => {
|
|
1040
|
+
return editor.getElementByKey(node.getKey())?.closest(DisableSelector);
|
|
1041
|
+
}));
|
|
1042
|
+
}
|
|
1043
|
+
}, [editor]);
|
|
1044
|
+
useEffect(() => {
|
|
1045
|
+
return editor.registerCommand(SELECTION_CHANGE_COMMAND, _payload => {
|
|
1046
|
+
$updateContentEditable();
|
|
1047
|
+
return false;
|
|
1048
|
+
}, COMMAND_PRIORITY_CRITICAL);
|
|
1049
|
+
}, [editor, $updateContentEditable]);
|
|
1050
|
+
return {
|
|
1051
|
+
contentEditable
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1000
1054
|
|
|
1001
1055
|
/**
|
|
1002
1056
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -22328,6 +22382,7 @@ class ImageNode extends DecoratorNode {
|
|
|
22328
22382
|
if (className !== undefined) {
|
|
22329
22383
|
span.className = className;
|
|
22330
22384
|
}
|
|
22385
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
22331
22386
|
return span;
|
|
22332
22387
|
}
|
|
22333
22388
|
updateDOM() {
|
|
@@ -23660,7 +23715,7 @@ const InstancePlugin = props => {
|
|
|
23660
23715
|
const selection = $getSelection();
|
|
23661
23716
|
if (selection) {
|
|
23662
23717
|
return selection.getNodes().some(node => {
|
|
23663
|
-
return editor.getElementByKey(node.getKey())?.closest(
|
|
23718
|
+
return editor.getElementByKey(node.getKey())?.closest(DisableSelector);
|
|
23664
23719
|
});
|
|
23665
23720
|
}
|
|
23666
23721
|
return false;
|
|
@@ -23751,43 +23806,38 @@ styleInject(css_248z$3);
|
|
|
23751
23806
|
/* eslint-disable @lexical/rules-of-lexical */
|
|
23752
23807
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
23753
23808
|
|
|
23754
|
-
function InternalLinkComponent({
|
|
23755
|
-
|
|
23756
|
-
|
|
23757
|
-
|
|
23758
|
-
|
|
23759
|
-
nodeKey
|
|
23760
|
-
}) {
|
|
23809
|
+
function InternalLinkComponent(props) {
|
|
23810
|
+
const {
|
|
23811
|
+
editor,
|
|
23812
|
+
number
|
|
23813
|
+
} = props;
|
|
23761
23814
|
const [name, setName] = useState();
|
|
23762
23815
|
const [serial, setSerial] = useState();
|
|
23763
|
-
const update = useCallback(function () {
|
|
23764
|
-
editor.read(() => {
|
|
23765
|
-
const node = $getInstanceNodeByNumber(number);
|
|
23766
|
-
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
23767
|
-
setSerial(node.getSerialNumber());
|
|
23768
|
-
});
|
|
23769
|
-
}, []);
|
|
23770
23816
|
useEffect(() => {
|
|
23771
|
-
|
|
23817
|
+
Promise.resolve().then(() => {
|
|
23818
|
+
// 需要等待节点载入富文本后才能获取到实例节点
|
|
23819
|
+
editor.read(() => {
|
|
23820
|
+
const node = $getInstanceNodeByNumber(number);
|
|
23821
|
+
if (node) {
|
|
23822
|
+
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
23823
|
+
setSerial(node.getSerialNumber());
|
|
23824
|
+
}
|
|
23825
|
+
});
|
|
23826
|
+
});
|
|
23772
23827
|
}, []);
|
|
23773
23828
|
useEffect(() => {
|
|
23774
|
-
|
|
23775
|
-
|
|
23776
|
-
|
|
23777
|
-
|
|
23778
|
-
|
|
23779
|
-
|
|
23780
|
-
|
|
23781
|
-
|
|
23782
|
-
|
|
23783
|
-
|
|
23784
|
-
|
|
23785
|
-
|
|
23786
|
-
internalLinkNameUpdateMap.set(number, map);
|
|
23787
|
-
}
|
|
23788
|
-
return () => {
|
|
23789
|
-
map.delete(number);
|
|
23790
|
-
};
|
|
23829
|
+
return mergeRegister(editor.registerCommand(INSTANCE_TITLE_UPDATE, priority => {
|
|
23830
|
+
if (priority.number === number) {
|
|
23831
|
+
editor.read(() => {
|
|
23832
|
+
const node = $getInstanceNodeByNumber(priority.number);
|
|
23833
|
+
if (priority.title !== undefined && priority.title !== null) {
|
|
23834
|
+
setName(priority.title);
|
|
23835
|
+
}
|
|
23836
|
+
setSerial(node.getSerialNumber());
|
|
23837
|
+
});
|
|
23838
|
+
}
|
|
23839
|
+
return false;
|
|
23840
|
+
}, COMMAND_PRIORITY_EDITOR));
|
|
23791
23841
|
}, []);
|
|
23792
23842
|
if (name) {
|
|
23793
23843
|
return /*#__PURE__*/jsxs("span", {
|
|
@@ -23822,12 +23872,23 @@ class InternalLinkNode extends TextDecoratorNode {
|
|
|
23822
23872
|
return new InternalLinkNode(node.__number, node.__key);
|
|
23823
23873
|
}
|
|
23824
23874
|
static importJSON(serializedNode) {
|
|
23825
|
-
return $createInternalLinkNode(serializedNode.
|
|
23875
|
+
return $createInternalLinkNode(serializedNode.number).updateFromJSON(serializedNode);
|
|
23826
23876
|
}
|
|
23827
23877
|
constructor(number, key) {
|
|
23828
23878
|
super(key);
|
|
23829
23879
|
this.__number = number;
|
|
23830
23880
|
}
|
|
23881
|
+
exportJSON() {
|
|
23882
|
+
return {
|
|
23883
|
+
...super.exportJSON(),
|
|
23884
|
+
number: this.__number
|
|
23885
|
+
};
|
|
23886
|
+
}
|
|
23887
|
+
createDOM(config, editor) {
|
|
23888
|
+
const span = super.createDOM(config, editor);
|
|
23889
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
23890
|
+
return span;
|
|
23891
|
+
}
|
|
23831
23892
|
updateDOM(prevNode, dom, config) {
|
|
23832
23893
|
return super.updateDOM(prevNode, dom, config);
|
|
23833
23894
|
}
|
|
@@ -24606,6 +24667,9 @@ function ImageComponent({
|
|
|
24606
24667
|
const onResizeStart = () => {
|
|
24607
24668
|
setIsResizing(true);
|
|
24608
24669
|
};
|
|
24670
|
+
const {
|
|
24671
|
+
contentEditable
|
|
24672
|
+
} = useContentEditable();
|
|
24609
24673
|
const {
|
|
24610
24674
|
historyState
|
|
24611
24675
|
} = useSharedHistoryContext();
|
|
@@ -24646,7 +24710,7 @@ function ImageComponent({
|
|
|
24646
24710
|
ErrorBoundary: LexicalErrorBoundary
|
|
24647
24711
|
})]
|
|
24648
24712
|
})
|
|
24649
|
-
}), resizable && $isNodeSelection(selection) && isFocused && /*#__PURE__*/jsx(ImageResizer, {
|
|
24713
|
+
}), resizable && $isNodeSelection(selection) && isFocused && contentEditable && /*#__PURE__*/jsx(ImageResizer, {
|
|
24650
24714
|
showCaption: showCaption,
|
|
24651
24715
|
setShowCaption: setShowCaption,
|
|
24652
24716
|
editor: editor,
|
|
@@ -24974,4 +25038,4 @@ var InlineImageComponent$1 = {
|
|
|
24974
25038
|
default: InlineImageComponent
|
|
24975
25039
|
};
|
|
24976
25040
|
|
|
24977
|
-
export { $createBarDecoratorNode, $createCollapsibleContainerNode, $createCollapsibleContentNode, $createCollapsibleTitleNode, $createFragmentNode, $createImageNode, $createInlineImageNode, $createInstanceCodeHighlightNode, $createInstanceCodeNode, $createInstanceEquationNode, $createInstanceHeadingNode, $createInstanceHorizontalRuleNode, $createInstanceListItemNode, $createInstanceListNode, $createInstanceNode, $createInstanceParagraphNode, $createInstanceQuoteNode, $createInstanceTableNode, $createInstanceTitleNode, $createInternalLinkNode, $createKeywordNode, $createNumberDecoratorNode, $createPageBreakNode, $createPlaceholderDecoratorNode, $createTitleOnlyInstanceNode, $findNearestListItemNode, $getAllListItems, $getAnchorRootNode, $getInstanceNodeByChild, $getInstanceNodeByNumber, $getInstanceNodeKeyByNumber, $getListDepth, $getTitleNodeByChild, $getTopListNode, $handleIndent, $handleListInsertParagraph, $handleOutdent, $insertInstanceList, $isBarDecoratorNode, $isCollapsibleContainerNode, $isCollapsibleContentNode, $isCollapsibleTitleNode, $isEmptyInstanceParagraphNode, $isEmptyParagraphNode, $isImageNode, $isInInstanceTitleNode, $isInlineImageNode, $isInstanceCodeHighlightNode, $isInstanceCodeNode, $isInstanceEquationNode, $isInstanceHeadingNode, $isInstanceHorizontalRuleNode, $isInstanceListItemNode, $isInstanceListNode, $isInstanceNode, $isInstanceParagraphFormalNode, $isInstanceParagraphNode, $isInstanceQuoteNode, $isInstanceTableNode, $isInstanceTitleNode, $isInternalLinkNode, $isKeywordNode, $isLastItemInList, $isNumberDecoratorNode, $isPageBreakNode, $isPlaceholderDecoratorNode, $isRemoved, $isSelectedTitleNode, $isTextTypeNode, $nodeDowngrade, $nodeUpgrade, $removeHighestEmptyListParent, $removeList, $scrollTo, $updateRichHistoryStateMap, $updateRichInstanceContent, $updateRichInstanceTitle, $wrapInListItem, ADD_NEW_INSTANCE_NODE, BarDecoratorNode, COMPONENT_UPDATE, CollapsibleContainerNode, CollapsibleContentNode, CollapsibleTitleNode, DELETE_INSTANCE_NODE, Fragment, INSERT_COLLAPSIBLE_COMMAND, INSERT_INS_HORIZONTAL_RULE_COMMAND, INSERT_PARAMETERS, ImageNode, InlineImageNode, InstanceCodeHighlightNode, InstanceCodeNode, InstanceEquationNode, InstanceHeadingNode, InstanceHorizontalRuleNode, InstanceListItemNode, InstanceListNode, InstanceNode, InstanceParagraphNode, InstanceParagraphType, InstancePlugin, InstanceQuoteNode, InstanceTableNode, InstanceTitleNode, InternalLinkNode, KeywordNode, NumberDecoratorNode, OPEN_CREATE_WINDOW, PageBreakNode, PlaceholderDecoratorNode, clearCache, fixedAddress, getCachedClassNameArray, getCodeLanguages, getDefaultCodeLanguage, getInstanceAttrValue, getInstanceBaseInfo, getLanguageFriendlyName, getLatestValue, getTemporaryContentText, ignoreHistory, instanceNodeMap, internalLinkNameUpdateMap, isCompleteInstance, isNestedListNode, mergeLists, mergeNextSiblingListIfSameType, nodeMoveDown, nodeMoveUp, normalizeCodeLang, numberNodeKey, paragraphSymbol, registerCodeHighlighting, setDisable, setInstanceAttrValue, setTemporaryContentText, updateChildrenListItemValue, updateRelatedInternalLink };
|
|
25041
|
+
export { $createBarDecoratorNode, $createCollapsibleContainerNode, $createCollapsibleContentNode, $createCollapsibleTitleNode, $createFragmentNode, $createImageNode, $createInlineImageNode, $createInstanceCodeHighlightNode, $createInstanceCodeNode, $createInstanceEquationNode, $createInstanceHeadingNode, $createInstanceHorizontalRuleNode, $createInstanceListItemNode, $createInstanceListNode, $createInstanceNode, $createInstanceParagraphNode, $createInstanceQuoteNode, $createInstanceTableNode, $createInstanceTitleNode, $createInternalLinkNode, $createKeywordNode, $createNumberDecoratorNode, $createPageBreakNode, $createPlaceholderDecoratorNode, $createTitleOnlyInstanceNode, $findNearestListItemNode, $getAllListItems, $getAnchorRootNode, $getInstanceNodeByChild, $getInstanceNodeByNumber, $getInstanceNodeKeyByNumber, $getListDepth, $getTitleNodeByChild, $getTopListNode, $handleIndent, $handleListInsertParagraph, $handleOutdent, $insertInstanceList, $isBarDecoratorNode, $isCollapsibleContainerNode, $isCollapsibleContentNode, $isCollapsibleTitleNode, $isEmptyInstanceParagraphNode, $isEmptyParagraphNode, $isImageNode, $isInInstanceTitleNode, $isInlineImageNode, $isInstanceCodeHighlightNode, $isInstanceCodeNode, $isInstanceEquationNode, $isInstanceHeadingNode, $isInstanceHorizontalRuleNode, $isInstanceListItemNode, $isInstanceListNode, $isInstanceNode, $isInstanceParagraphFormalNode, $isInstanceParagraphNode, $isInstanceQuoteNode, $isInstanceTableNode, $isInstanceTitleNode, $isInternalLinkNode, $isKeywordNode, $isLastItemInList, $isNumberDecoratorNode, $isPageBreakNode, $isPlaceholderDecoratorNode, $isRemoved, $isSelectedTitleNode, $isTextTypeNode, $nodeDowngrade, $nodeUpgrade, $removeHighestEmptyListParent, $removeList, $scrollTo, $updateRichHistoryStateMap, $updateRichInstanceContent, $updateRichInstanceTitle, $wrapInListItem, ADD_NEW_INSTANCE_NODE, BarDecoratorNode, COMPONENT_UPDATE, CollapsibleContainerNode, CollapsibleContentNode, CollapsibleTitleNode, DELETE_INSTANCE_NODE, DisableSelector, Fragment, INSERT_COLLAPSIBLE_COMMAND, INSERT_INS_HORIZONTAL_RULE_COMMAND, INSERT_PARAMETERS, INSTANCE_TITLE_UPDATE, ImageNode, InlineImageNode, InstanceCodeHighlightNode, InstanceCodeNode, InstanceEquationNode, InstanceHeadingNode, InstanceHorizontalRuleNode, InstanceListItemNode, InstanceListNode, InstanceNode, InstanceParagraphNode, InstanceParagraphType, InstancePlugin, InstanceQuoteNode, InstanceTableNode, InstanceTitleNode, InternalLinkNode, KeywordNode, NumberDecoratorNode, OPEN_CREATE_WINDOW, PageBreakNode, PlaceholderDecoratorNode, clearCache, fixedAddress, getCachedClassNameArray, getCodeLanguages, getDefaultCodeLanguage, getInstanceAttrValue, getInstanceBaseInfo, getLanguageFriendlyName, getLatestValue, getTemporaryContentText, ignoreHistory, instanceNodeMap, internalLinkNameUpdateMap, isCompleteInstance, isNestedListNode, mergeLists, mergeNextSiblingListIfSameType, nodeMoveDown, nodeMoveUp, normalizeCodeLang, numberNodeKey, paragraphSymbol, registerCodeHighlighting, setDisable, setInstanceAttrValue, setTemporaryContentText, updateChildrenListItemValue, updateRelatedInternalLink, useContentEditable };
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"instance"
|
|
8
8
|
],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.0.
|
|
10
|
+
"version": "0.0.9",
|
|
11
11
|
"types": "index.d.ts",
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"@lexical/table": "^0.30.0",
|
|
24
24
|
"@lexical/utils": "^0.30.0",
|
|
25
25
|
"lexical": "0.30.0",
|
|
26
|
-
"onchain-lexical-context": "^0.0.
|
|
27
|
-
"onchain-lexical-markdown": "^0.0.
|
|
28
|
-
"onchain-lexical-ui": "^0.0.
|
|
26
|
+
"onchain-lexical-context": "^0.0.8",
|
|
27
|
+
"onchain-lexical-markdown": "^0.0.8",
|
|
28
|
+
"onchain-lexical-ui": "^0.0.8",
|
|
29
29
|
"onchain-utility": "^0.0.8"
|
|
30
30
|
},
|
|
31
31
|
"sideEffects": false,
|
package/src/const.ts
CHANGED
|
@@ -70,24 +70,39 @@ export const internalLinkNameUpdateMap = new Map<
|
|
|
70
70
|
Map<string, () => void>
|
|
71
71
|
>();
|
|
72
72
|
|
|
73
|
+
/** 打开创建实例节点 */
|
|
73
74
|
export const OPEN_CREATE_WINDOW: LexicalCommand<{
|
|
74
75
|
isAddChildLevel: boolean;
|
|
75
76
|
number: string;
|
|
76
77
|
insNodeKey?: string;
|
|
77
78
|
}> = createCommand('OPEN_CREATE_WINDOW');
|
|
78
79
|
|
|
80
|
+
/** 添加新的实例节点 */
|
|
79
81
|
export const ADD_NEW_INSTANCE_NODE: LexicalCommand<{
|
|
80
82
|
instances: Instance[];
|
|
81
83
|
isAddChildLevel: boolean;
|
|
82
84
|
insNodeKey?: string;
|
|
83
85
|
}> = createCommand('ADD_NEW_INSTANCE_NODE');
|
|
84
86
|
|
|
87
|
+
/** 删除实例节点 */
|
|
85
88
|
export const DELETE_INSTANCE_NODE = 'DELETE_INSTANCE_NODE';
|
|
86
89
|
|
|
90
|
+
/** 插入参数 */
|
|
87
91
|
export const INSERT_PARAMETERS: LexicalCommand<undefined> =
|
|
88
92
|
createCommand('INSERT_PARAMETERS');
|
|
89
93
|
|
|
94
|
+
/** 富文本 DecoratorNode 节点组件更新事件*/
|
|
90
95
|
export const COMPONENT_UPDATE: LexicalCommand<{
|
|
91
96
|
insNodeKey?: string;
|
|
92
97
|
name: 'bar';
|
|
93
98
|
}> = createCommand('COMPONENT_UPDATE');
|
|
99
|
+
|
|
100
|
+
/** 标题更新事件 */
|
|
101
|
+
export const INSTANCE_TITLE_UPDATE: LexicalCommand<{
|
|
102
|
+
number: string;
|
|
103
|
+
isInput?: boolean;
|
|
104
|
+
title?: string;
|
|
105
|
+
}> = createCommand('INSTANCE_TITLE_UPDATE');
|
|
106
|
+
|
|
107
|
+
/** 获取禁止编辑dom节点选择器 */
|
|
108
|
+
export const DisableSelector = `[contenteditable='false']:not([ignorecontenteditable])`;
|
|
@@ -49,6 +49,7 @@ import ImageResizer from 'onchain-lexical-ui/ImageResizer';
|
|
|
49
49
|
import * as React from 'react';
|
|
50
50
|
import {Suspense, useCallback, useEffect, useRef, useState} from 'react';
|
|
51
51
|
|
|
52
|
+
import {useContentEditable} from '../utils';
|
|
52
53
|
import {$isImageNode} from '.';
|
|
53
54
|
import Styles from './ImageNode.module.less';
|
|
54
55
|
|
|
@@ -461,7 +462,7 @@ export default function ImageComponent({
|
|
|
461
462
|
const onResizeStart = () => {
|
|
462
463
|
setIsResizing(true);
|
|
463
464
|
};
|
|
464
|
-
|
|
465
|
+
const {contentEditable} = useContentEditable();
|
|
465
466
|
const {historyState} = useSharedHistoryContext();
|
|
466
467
|
|
|
467
468
|
const draggable = isSelected && $isNodeSelection(selection) && !isResizing;
|
|
@@ -518,19 +519,22 @@ export default function ImageComponent({
|
|
|
518
519
|
</LexicalNestedComposer>
|
|
519
520
|
</div>
|
|
520
521
|
)}
|
|
521
|
-
{resizable &&
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
522
|
+
{resizable &&
|
|
523
|
+
$isNodeSelection(selection) &&
|
|
524
|
+
isFocused &&
|
|
525
|
+
contentEditable && (
|
|
526
|
+
<ImageResizer
|
|
527
|
+
showCaption={showCaption}
|
|
528
|
+
setShowCaption={setShowCaption}
|
|
529
|
+
editor={editor}
|
|
530
|
+
buttonRef={buttonRef}
|
|
531
|
+
imageRef={imageRef}
|
|
532
|
+
maxWidth={maxWidth}
|
|
533
|
+
onResizeStart={onResizeStart}
|
|
534
|
+
onResizeEnd={onResizeEnd}
|
|
535
|
+
captionsEnabled={!isLoadError && captionsEnabled}
|
|
536
|
+
/>
|
|
537
|
+
)}
|
|
534
538
|
</>
|
|
535
539
|
</Suspense>
|
|
536
540
|
);
|
package/src/image/index.tsx
CHANGED
package/src/instancePlugin.ts
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
$createTitleOnlyInstanceNode,
|
|
24
24
|
$isInstanceNode,
|
|
25
25
|
} from './base';
|
|
26
|
-
import {ADD_NEW_INSTANCE_NODE, PluginProps} from './const';
|
|
26
|
+
import {ADD_NEW_INSTANCE_NODE, DisableSelector, PluginProps} from './const';
|
|
27
27
|
import {$createFragmentNode} from './fragment';
|
|
28
28
|
import {HorizontalRulePlugin} from './horizontal/horizontalPlugin';
|
|
29
29
|
import {$registerInstanceListItemInsertParagraph} from './list/item';
|
|
@@ -57,7 +57,7 @@ export const InstancePlugin: React.FC<PluginProps> = (props) => {
|
|
|
57
57
|
return selection.getNodes().some((node) => {
|
|
58
58
|
return editor
|
|
59
59
|
.getElementByKey(node.getKey())
|
|
60
|
-
?.closest(
|
|
60
|
+
?.closest(DisableSelector);
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
return false;
|
|
@@ -20,7 +20,7 @@ import InternalLinkComponent from './internalLinkComponent';
|
|
|
20
20
|
|
|
21
21
|
export type SerializedInternalNode = Spread<
|
|
22
22
|
{
|
|
23
|
-
|
|
23
|
+
number: string;
|
|
24
24
|
},
|
|
25
25
|
SerializedTextDecoratorNode
|
|
26
26
|
>;
|
|
@@ -35,7 +35,7 @@ export class InternalLinkNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
static importJSON(serializedNode: SerializedInternalNode): InternalLinkNode {
|
|
38
|
-
return $createInternalLinkNode(serializedNode.
|
|
38
|
+
return $createInternalLinkNode(serializedNode.number).updateFromJSON(
|
|
39
39
|
serializedNode,
|
|
40
40
|
);
|
|
41
41
|
}
|
|
@@ -45,6 +45,19 @@ export class InternalLinkNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
45
45
|
this.__number = number;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
exportJSON(): SerializedInternalNode {
|
|
49
|
+
return {
|
|
50
|
+
...super.exportJSON(),
|
|
51
|
+
number: this.__number,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
createDOM(config: EditorConfig, editor?: LexicalEditor): HTMLElement {
|
|
56
|
+
const span = super.createDOM(config, editor);
|
|
57
|
+
span.setAttribute('ignorecontenteditable', '');
|
|
58
|
+
return span;
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean {
|
|
49
62
|
return super.updateDOM(prevNode, dom, config);
|
|
50
63
|
}
|
|
@@ -10,59 +10,59 @@
|
|
|
10
10
|
|
|
11
11
|
import type {InternalLinkNode} from '.';
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import {mergeRegister} from '@lexical/utils';
|
|
14
|
+
import {COMMAND_PRIORITY_EDITOR, EditorConfig, LexicalEditor} from 'lexical';
|
|
15
|
+
import {useEffect, useState} from 'react';
|
|
15
16
|
|
|
16
|
-
import {
|
|
17
|
+
import {INSTANCE_TITLE_UPDATE} from '../const';
|
|
17
18
|
import {$getInstanceNodeByNumber, $scrollTo, getLatestValue} from '../utils';
|
|
18
19
|
import Styles from './styles.module.less';
|
|
19
20
|
|
|
20
|
-
export default function InternalLinkComponent({
|
|
21
|
-
self,
|
|
22
|
-
editor,
|
|
23
|
-
config,
|
|
24
|
-
number,
|
|
25
|
-
nodeKey,
|
|
26
|
-
}: {
|
|
21
|
+
export default function InternalLinkComponent(props: {
|
|
27
22
|
self: InternalLinkNode;
|
|
23
|
+
/** 链接目标的编号 */
|
|
28
24
|
number: string;
|
|
25
|
+
/** 引用链接组件所在文档内自身节点 */
|
|
29
26
|
nodeKey: string;
|
|
30
27
|
editor: LexicalEditor;
|
|
31
28
|
config: EditorConfig;
|
|
32
29
|
}) {
|
|
30
|
+
const {editor, number} = props;
|
|
33
31
|
const [name, setName] = useState<string>();
|
|
34
32
|
const [serial, setSerial] = useState<string>();
|
|
35
33
|
|
|
36
|
-
const update = useCallback(function () {
|
|
37
|
-
editor.read(() => {
|
|
38
|
-
const node = $getInstanceNodeByNumber(number)!;
|
|
39
|
-
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
40
|
-
setSerial(node.getSerialNumber());
|
|
41
|
-
});
|
|
42
|
-
}, []);
|
|
43
|
-
|
|
44
34
|
useEffect(() => {
|
|
45
|
-
|
|
35
|
+
Promise.resolve().then(() => {
|
|
36
|
+
// 需要等待节点载入富文本后才能获取到实例节点
|
|
37
|
+
editor.read(() => {
|
|
38
|
+
const node = $getInstanceNodeByNumber(number)!;
|
|
39
|
+
if (node) {
|
|
40
|
+
setName(getLatestValue(node.__instance.value, 'insDesc'));
|
|
41
|
+
setSerial(node.getSerialNumber());
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
46
45
|
}, []);
|
|
47
46
|
|
|
48
47
|
useEffect(() => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
return mergeRegister(
|
|
49
|
+
editor.registerCommand(
|
|
50
|
+
INSTANCE_TITLE_UPDATE,
|
|
51
|
+
(priority) => {
|
|
52
|
+
if (priority.number === number) {
|
|
53
|
+
editor.read(() => {
|
|
54
|
+
const node = $getInstanceNodeByNumber(priority.number)!;
|
|
55
|
+
if (priority.title !== undefined && priority.title !== null) {
|
|
56
|
+
setName(priority.title);
|
|
57
|
+
}
|
|
58
|
+
setSerial(node.getSerialNumber());
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
},
|
|
63
|
+
COMMAND_PRIORITY_EDITOR,
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
66
|
}, []);
|
|
67
67
|
|
|
68
68
|
if (name) {
|
package/src/paragraph/title.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
$applyNodeReplacement,
|
|
15
15
|
$createTextNode,
|
|
16
|
+
$getEditor,
|
|
16
17
|
$getSelection,
|
|
17
18
|
$isTextNode,
|
|
18
19
|
BaseSelection,
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
} from 'lexical';
|
|
30
31
|
|
|
31
32
|
import {$isInstanceNode} from '../base';
|
|
32
|
-
import {
|
|
33
|
+
import {INSTANCE_TITLE_UPDATE, Placeholder} from '../const';
|
|
33
34
|
import {InstanceHeadingNode, isGoogleDocsTitle} from '../heading';
|
|
34
35
|
import {
|
|
35
36
|
$createPlaceholderDecoratorNode,
|
|
@@ -143,10 +144,16 @@ export class InstanceTitleNode extends InstanceHeadingNode {
|
|
|
143
144
|
if (instanceNode && instanceNode.__instance.value) {
|
|
144
145
|
const text = this.getTextContent().trim();
|
|
145
146
|
setInstanceAttrValue(instanceNode.__instance.value, 'insDesc', text);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
const editor = $getEditor();
|
|
148
|
+
Promise.resolve().then(() => {
|
|
149
|
+
editor.read(() => {
|
|
150
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
151
|
+
isInput: true,
|
|
152
|
+
number: instanceNode.__instance.value.number!,
|
|
153
|
+
title: text,
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
150
157
|
}
|
|
151
158
|
return super.updateDOM(prevNode, dom, config);
|
|
152
159
|
}
|
package/src/placeholder/index.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type {HistoryState, HistoryStateEntry} from '@lexical/history';
|
|
|
11
11
|
|
|
12
12
|
import {$isCodeNode} from '@lexical/code';
|
|
13
13
|
import {$isListNode} from '@lexical/list';
|
|
14
|
+
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
14
15
|
import {$isQuoteNode} from '@lexical/rich-text';
|
|
15
16
|
import {$findMatchingParent} from '@lexical/utils';
|
|
16
17
|
import {
|
|
@@ -19,21 +20,26 @@ import {
|
|
|
19
20
|
$getSelection,
|
|
20
21
|
$isElementNode,
|
|
21
22
|
$isRootNode,
|
|
23
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
22
24
|
type EditorThemeClasses,
|
|
23
25
|
ElementNode,
|
|
24
26
|
LexicalEditor,
|
|
25
27
|
type LexicalNode,
|
|
26
28
|
scrollIntoViewIfNeeded,
|
|
29
|
+
SELECTION_CHANGE_COMMAND,
|
|
27
30
|
TextNode,
|
|
28
31
|
} from 'lexical';
|
|
29
32
|
import {$isRootOrShadowRoot} from 'lexical';
|
|
30
33
|
import {$textToRichNodes} from 'onchain-lexical-markdown';
|
|
31
34
|
import {dfs, hasOwnProperty} from 'onchain-utility';
|
|
35
|
+
import {useCallback, useEffect, useState} from 'react';
|
|
32
36
|
import normalizeClassNames from 'shared/normalizeClassNames';
|
|
33
37
|
|
|
34
38
|
import {$createBarDecoratorNode, $isBarDecoratorNode} from './bar';
|
|
35
39
|
import {$isInstanceNode, InstanceNode} from './base';
|
|
36
40
|
import {
|
|
41
|
+
DisableSelector,
|
|
42
|
+
INSTANCE_TITLE_UPDATE,
|
|
37
43
|
internalLinkNameUpdateMap,
|
|
38
44
|
numberNodeKey,
|
|
39
45
|
paragraphSymbol,
|
|
@@ -253,10 +259,14 @@ export function updateRelatedInternalLink<T extends ElementNode>(nodes: T[]) {
|
|
|
253
259
|
const insNodes = nodes.filter((node) => $isInstanceNode(node));
|
|
254
260
|
if (insNodes.length) {
|
|
255
261
|
insNodes.forEach((node) => {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
const editor = $getEditor();
|
|
263
|
+
Promise.resolve().then(() => {
|
|
264
|
+
editor.read(() => {
|
|
265
|
+
editor.dispatchCommand(INSTANCE_TITLE_UPDATE, {
|
|
266
|
+
number: node.__instance.value.number!,
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
260
270
|
});
|
|
261
271
|
}
|
|
262
272
|
}
|
|
@@ -273,7 +283,9 @@ export function nodeMoveUp<T extends ElementNode>(nodes?: T[] | null) {
|
|
|
273
283
|
previous?.insertBefore(current);
|
|
274
284
|
}
|
|
275
285
|
}
|
|
276
|
-
updateRelatedInternalLink(
|
|
286
|
+
updateRelatedInternalLink(
|
|
287
|
+
$isInstanceNode(previous) ? [...nodes, previous] : nodes,
|
|
288
|
+
);
|
|
277
289
|
}
|
|
278
290
|
}
|
|
279
291
|
|
|
@@ -289,7 +301,7 @@ export function nodeMoveDown<T extends ElementNode>(nodes?: T[] | null) {
|
|
|
289
301
|
next?.insertAfter(current);
|
|
290
302
|
}
|
|
291
303
|
}
|
|
292
|
-
updateRelatedInternalLink(nodes);
|
|
304
|
+
updateRelatedInternalLink($isInstanceNode(next) ? [...nodes, next] : nodes);
|
|
293
305
|
}
|
|
294
306
|
}
|
|
295
307
|
|
|
@@ -463,3 +475,36 @@ function setHSEntryMap(hs: HistoryStateEntry[], instanceNode: InstanceNode) {
|
|
|
463
475
|
return state;
|
|
464
476
|
});
|
|
465
477
|
}
|
|
478
|
+
|
|
479
|
+
export function useContentEditable() {
|
|
480
|
+
const [editor] = useLexicalComposerContext();
|
|
481
|
+
const [contentEditable, setContentEditable] = useState(true);
|
|
482
|
+
|
|
483
|
+
const $updateContentEditable = useCallback(() => {
|
|
484
|
+
const selection = $getSelection();
|
|
485
|
+
if (selection) {
|
|
486
|
+
setContentEditable(
|
|
487
|
+
!selection.getNodes().some((node) => {
|
|
488
|
+
return editor
|
|
489
|
+
.getElementByKey(node.getKey())
|
|
490
|
+
?.closest(DisableSelector);
|
|
491
|
+
}),
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
}, [editor]);
|
|
495
|
+
|
|
496
|
+
useEffect(() => {
|
|
497
|
+
return editor.registerCommand(
|
|
498
|
+
SELECTION_CHANGE_COMMAND,
|
|
499
|
+
(_payload) => {
|
|
500
|
+
$updateContentEditable();
|
|
501
|
+
return false;
|
|
502
|
+
},
|
|
503
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
504
|
+
);
|
|
505
|
+
}, [editor, $updateContentEditable]);
|
|
506
|
+
|
|
507
|
+
return {
|
|
508
|
+
contentEditable,
|
|
509
|
+
};
|
|
510
|
+
}
|