@lobehub/editor 1.4.7 → 1.5.1
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/editor-kernel/kernel.d.ts +4 -1
- package/es/editor-kernel/kernel.js +56 -1
- package/es/index.d.ts +2 -0
- package/es/index.js +2 -0
- package/es/locale/index.d.ts +7 -0
- package/es/locale/index.js +7 -0
- package/es/plugins/code/command/index.d.ts +3 -0
- package/es/plugins/code/command/index.js +48 -0
- package/es/plugins/code/index.d.ts +3 -0
- package/es/plugins/code/index.js +3 -0
- package/es/plugins/code/node/code.d.ts +19 -0
- package/es/plugins/{common/node/LexicalLineBreakNode.js → code/node/code.js} +93 -95
- package/es/plugins/code/plugin/index.d.ts +5 -0
- package/es/plugins/{common/node/ParagraphNode.js → code/plugin/index.js} +40 -33
- package/es/plugins/code/plugin/registry.d.ts +3 -0
- package/es/plugins/code/plugin/registry.js +48 -0
- package/es/plugins/code/react/CodeReactPlugin.d.ts +4 -0
- package/es/plugins/code/react/CodeReactPlugin.js +31 -0
- package/es/plugins/code/react/index.d.ts +1 -0
- package/es/plugins/code/react/index.js +1 -0
- package/es/plugins/code/react/style.d.ts +3 -0
- package/es/plugins/code/react/style.js +10 -0
- package/es/plugins/code/react/type.d.ts +3 -0
- package/es/plugins/code/react/type.js +1 -0
- package/es/plugins/common/data-source/json-data-source.js +42 -5
- package/es/plugins/common/data-source/text-data-source.js +2 -2
- package/es/plugins/common/index.d.ts +1 -0
- package/es/plugins/common/index.js +1 -0
- package/es/plugins/common/node/ElementDOMSlot.d.ts +3 -5
- package/es/plugins/common/node/ElementDOMSlot.js +29 -56
- package/es/plugins/common/node/cursor.d.ts +12 -0
- package/es/plugins/common/node/cursor.js +303 -0
- package/es/plugins/common/plugin/index.js +11 -9
- package/es/plugins/common/plugin/register.d.ts +3 -1
- package/es/plugins/common/plugin/register.js +46 -13
- package/es/plugins/link/command/index.d.ts +5 -1
- package/es/plugins/link/command/index.js +21 -3
- package/es/plugins/link/react/ReactLinkPlugin.js +6 -9
- package/es/plugins/link/react/components/LinkEdit.d.ts +2 -1
- package/es/plugins/link/react/components/LinkEdit.js +195 -51
- package/es/plugins/link/react/components/LinkToolbar.d.ts +10 -0
- package/es/plugins/link/react/components/LinkToolbar.js +73 -0
- package/es/plugins/link/react/style.d.ts +3 -2
- package/es/plugins/link/react/style.js +8 -5
- package/es/plugins/list/command/index.d.ts +1 -0
- package/es/plugins/list/command/index.js +1 -0
- package/es/plugins/list/plugin/checkList.d.ts +3 -0
- package/es/plugins/list/plugin/checkList.js +167 -0
- package/es/plugins/list/plugin/index.js +9 -2
- package/es/plugins/list/react/style.js +4 -2
- package/es/plugins/markdown/data-source/markdown-data-source.js +5 -1
- package/es/plugins/markdown/service/shortcut.d.ts +3 -3
- package/es/plugins/math/command/index.d.ts +13 -0
- package/es/plugins/math/command/index.js +47 -0
- package/es/plugins/math/index.d.ts +3 -0
- package/es/plugins/math/index.js +3 -0
- package/es/plugins/math/node/index.d.ts +45 -0
- package/es/plugins/math/node/index.js +259 -0
- package/es/plugins/math/plugin/index.d.ts +11 -0
- package/es/plugins/math/plugin/index.js +103 -0
- package/es/plugins/math/react/component/MathEditor.d.ts +10 -0
- package/es/plugins/math/react/component/MathEditor.js +253 -0
- package/es/plugins/math/react/component/MathEditorContainer.d.ts +14 -0
- package/es/plugins/math/react/component/MathEditorContainer.js +60 -0
- package/es/plugins/math/react/component/MathEditorContent.d.ts +26 -0
- package/es/plugins/math/react/component/MathEditorContent.js +163 -0
- package/es/plugins/math/react/component/MathInline.d.ts +10 -0
- package/es/plugins/math/react/component/MathInline.js +105 -0
- package/es/plugins/math/react/component/Placeholder.d.ts +3 -0
- package/es/plugins/math/react/component/Placeholder.js +19 -0
- package/es/plugins/math/react/index.d.ts +3 -0
- package/es/plugins/math/react/index.js +43 -0
- package/es/plugins/math/react/style.d.ts +6 -0
- package/es/plugins/math/react/style.js +16 -0
- package/es/plugins/math/react/type.d.ts +13 -0
- package/es/plugins/math/react/type.js +1 -0
- package/es/plugins/slash/react/ReactSlashPlugin.js +12 -10
- package/es/react/FloatMenu/FloatMenu.d.ts +4 -0
- package/es/react/FloatMenu/FloatMenu.js +49 -0
- package/es/react/FloatMenu/index.d.ts +2 -0
- package/es/react/FloatMenu/index.js +2 -0
- package/es/react/FloatMenu/type.d.ts +19 -0
- package/es/react/FloatMenu/type.js +1 -0
- package/es/react/SlashMenu/SlashMenu.js +32 -48
- package/es/react/SlashMenu/type.d.ts +5 -13
- package/es/react/hooks/useEditorState/index.d.ts +4 -0
- package/es/react/hooks/useEditorState/index.js +40 -4
- package/es/react/index.d.ts +1 -0
- package/es/react/index.js +1 -0
- package/es/types/global.d.ts +4 -0
- package/es/types/kernel.d.ts +26 -1
- package/package.json +2 -1
- package/es/plugins/common/node/LexicalLineBreakNode.d.ts +0 -31
- package/es/plugins/common/node/ParagraphNode.d.ts +0 -7
- package/es/plugins/link/react/components/Toolbar.d.ts +0 -7
- package/es/plugins/link/react/components/Toolbar.js +0 -63
- /package/es/react/{SlashMenu → FloatMenu}/style.d.ts +0 -0
- /package/es/react/{SlashMenu → FloatMenu}/style.js +0 -0
|
@@ -6,29 +6,39 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
|
|
|
6
6
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
7
|
import { computePosition, flip, offset, shift } from '@floating-ui/dom';
|
|
8
8
|
import { mergeRegister } from '@lexical/utils';
|
|
9
|
-
import { Icon, Input } from '@lobehub/ui';
|
|
9
|
+
import { Block, Button, Hotkey, Icon, Input, Text } from '@lobehub/ui';
|
|
10
10
|
import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_NORMAL, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, createCommand } from 'lexical';
|
|
11
|
-
import { LinkIcon } from 'lucide-react';
|
|
11
|
+
import { BaselineIcon, LinkIcon } from 'lucide-react';
|
|
12
12
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
13
|
+
import { Flexbox } from 'react-layout-kit';
|
|
13
14
|
import { useLexicalComposerContext, useLexicalEditor } from "../../../../editor-kernel/react";
|
|
15
|
+
import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
|
|
16
|
+
import { UPDATE_LINK_TEXT_COMMAND } from "../../command";
|
|
14
17
|
import { useStyles } from "../style";
|
|
15
18
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
19
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
20
|
export var EDIT_LINK_COMMAND = createCommand();
|
|
17
|
-
|
|
21
|
+
var LinkEdit = function LinkEdit() {
|
|
18
22
|
var divRef = useRef(null);
|
|
19
23
|
var linkNodeRef = useRef(null);
|
|
20
24
|
var linkInputRef = useRef(null);
|
|
25
|
+
var linkTextInputRef = useRef(null);
|
|
21
26
|
var _useState = useState(''),
|
|
22
27
|
_useState2 = _slicedToArray(_useState, 2),
|
|
23
28
|
linkUrl = _useState2[0],
|
|
24
29
|
setLinkUrl = _useState2[1];
|
|
25
|
-
var _useState3 = useState(
|
|
30
|
+
var _useState3 = useState(''),
|
|
26
31
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
linkText = _useState4[0],
|
|
33
|
+
setLinkText = _useState4[1];
|
|
34
|
+
var _useState5 = useState(null),
|
|
35
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
36
|
+
linkDom = _useState6[0],
|
|
37
|
+
setLinkDom = _useState6[1];
|
|
29
38
|
var _useLexicalComposerCo = useLexicalComposerContext(),
|
|
30
39
|
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
|
|
31
40
|
editor = _useLexicalComposerCo2[0];
|
|
41
|
+
var t = useTranslation();
|
|
32
42
|
var _useStyles = useStyles(),
|
|
33
43
|
styles = _useStyles.styles,
|
|
34
44
|
theme = _useStyles.theme;
|
|
@@ -48,39 +58,132 @@ export var LinkEdit = function LinkEdit() {
|
|
|
48
58
|
}
|
|
49
59
|
});
|
|
50
60
|
}, [linkDom]);
|
|
51
|
-
|
|
61
|
+
|
|
62
|
+
// 提取提交逻辑到独立函数
|
|
63
|
+
var handleSubmit = useCallback(function () {
|
|
52
64
|
var lexicalEditor = editor.getLexicalEditor();
|
|
53
|
-
if (!linkNodeRef.current || !linkInputRef.current || !lexicalEditor) {
|
|
65
|
+
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !lexicalEditor) {
|
|
54
66
|
return;
|
|
55
67
|
}
|
|
56
68
|
var linkNode = linkNodeRef.current;
|
|
57
69
|
var input = linkInputRef.current;
|
|
58
70
|
var inputDOM = input.input;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
71
|
+
var textInput = linkTextInputRef.current;
|
|
72
|
+
var textInputDOM = textInput.input;
|
|
73
|
+
|
|
74
|
+
// 更新链接URL
|
|
75
|
+
var currentURL = lexicalEditor.read(function () {
|
|
76
|
+
return linkNode.getURL();
|
|
77
|
+
});
|
|
78
|
+
if (currentURL !== inputDOM.value) {
|
|
79
|
+
lexicalEditor.update(function () {
|
|
80
|
+
linkNode.setURL(inputDOM.value);
|
|
63
81
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 更新链接文本
|
|
85
|
+
var currentText = lexicalEditor.read(function () {
|
|
86
|
+
return linkNode.getTextContent();
|
|
87
|
+
});
|
|
88
|
+
if (currentText !== textInputDOM.value) {
|
|
89
|
+
lexicalEditor.dispatchCommand(UPDATE_LINK_TEXT_COMMAND, {
|
|
90
|
+
key: linkNode.getKey(),
|
|
91
|
+
text: textInputDOM.value
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 关闭编辑器并聚焦到编辑器
|
|
96
|
+
lexicalEditor.focus();
|
|
97
|
+
|
|
98
|
+
// 隐藏编辑面板
|
|
99
|
+
if (divRef.current) {
|
|
100
|
+
divRef.current.style.left = '-9999px';
|
|
101
|
+
divRef.current.style.top = '-9999px';
|
|
102
|
+
}
|
|
103
|
+
linkNodeRef.current = null;
|
|
104
|
+
setLinkUrl('');
|
|
105
|
+
setLinkText('');
|
|
106
|
+
setLinkDom(null);
|
|
107
|
+
}, [editor, linkNodeRef, linkInputRef, linkTextInputRef]);
|
|
108
|
+
|
|
109
|
+
// 取消编辑,不保存更改
|
|
110
|
+
var handleCancel = useCallback(function () {
|
|
111
|
+
var lexicalEditor = editor.getLexicalEditor();
|
|
112
|
+
if (!lexicalEditor) return;
|
|
113
|
+
|
|
114
|
+
// 将焦点返回到编辑器
|
|
115
|
+
lexicalEditor.focus();
|
|
116
|
+
|
|
117
|
+
// 隐藏编辑面板
|
|
118
|
+
if (divRef.current) {
|
|
119
|
+
divRef.current.style.left = '-9999px';
|
|
120
|
+
divRef.current.style.top = '-9999px';
|
|
121
|
+
}
|
|
122
|
+
linkNodeRef.current = null;
|
|
123
|
+
setLinkUrl('');
|
|
124
|
+
setLinkText('');
|
|
125
|
+
setLinkDom(null);
|
|
126
|
+
}, [editor]);
|
|
127
|
+
var handleKeyDown = useCallback(function (event) {
|
|
128
|
+
var lexicalEditor = editor.getLexicalEditor();
|
|
129
|
+
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !lexicalEditor) {
|
|
76
130
|
return;
|
|
77
131
|
}
|
|
78
|
-
|
|
132
|
+
var linkNode = linkNodeRef.current;
|
|
133
|
+
var input = linkInputRef.current;
|
|
134
|
+
var inputDOM = input.input;
|
|
135
|
+
var textInput = linkTextInputRef.current;
|
|
136
|
+
var textInputDOM = textInput.input;
|
|
137
|
+
switch (event.key) {
|
|
138
|
+
case 'Enter':
|
|
139
|
+
{
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
if (event.currentTarget === textInputDOM) {
|
|
142
|
+
var currentText = lexicalEditor.read(function () {
|
|
143
|
+
return linkNode.getTextContent();
|
|
144
|
+
});
|
|
145
|
+
if (currentText !== textInputDOM.value) {
|
|
146
|
+
lexicalEditor.dispatchCommand(UPDATE_LINK_TEXT_COMMAND, {
|
|
147
|
+
key: linkNode.getKey(),
|
|
148
|
+
text: textInputDOM.value
|
|
149
|
+
});
|
|
150
|
+
// 更新文本后跳转到链接输入框
|
|
151
|
+
inputDOM.focus();
|
|
152
|
+
} else {
|
|
153
|
+
// 如果文本没有变化,直接跳转到链接输入框
|
|
154
|
+
inputDOM.focus();
|
|
155
|
+
}
|
|
156
|
+
} else if (event.currentTarget === inputDOM) {
|
|
157
|
+
// 在链接输入框按回车时提交所有更改
|
|
158
|
+
handleSubmit();
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
case 'Tab':
|
|
163
|
+
{
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
if (event.currentTarget === textInputDOM) {
|
|
166
|
+
inputDOM.focus();
|
|
167
|
+
} else {
|
|
168
|
+
lexicalEditor.focus();
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
case 'Escape':
|
|
173
|
+
{
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
handleCancel();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// No default
|
|
179
|
+
}
|
|
180
|
+
}, [linkNodeRef, linkInputRef, handleSubmit, handleCancel]);
|
|
79
181
|
useLexicalEditor(function (editor) {
|
|
80
182
|
return mergeRegister(editor.registerCommand(EDIT_LINK_COMMAND, function (payload) {
|
|
81
183
|
if (!payload.linkNode || !payload.linkNodeDOM) {
|
|
82
184
|
setLinkDom(null);
|
|
83
185
|
setLinkUrl('');
|
|
186
|
+
setLinkText('');
|
|
84
187
|
if (divRef.current) {
|
|
85
188
|
divRef.current.style.left = '-9999px';
|
|
86
189
|
divRef.current.style.top = '-9999px';
|
|
@@ -89,6 +192,7 @@ export var LinkEdit = function LinkEdit() {
|
|
|
89
192
|
}
|
|
90
193
|
linkNodeRef.current = payload.linkNode;
|
|
91
194
|
setLinkUrl(payload.linkNode.getURL());
|
|
195
|
+
setLinkText(payload.linkNode.getTextContent());
|
|
92
196
|
setLinkDom(payload.linkNodeDOM);
|
|
93
197
|
return true;
|
|
94
198
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_ESCAPE_COMMAND, function () {
|
|
@@ -98,41 +202,81 @@ export var LinkEdit = function LinkEdit() {
|
|
|
98
202
|
}
|
|
99
203
|
linkNodeRef.current = null;
|
|
100
204
|
setLinkUrl('');
|
|
205
|
+
setLinkText('');
|
|
101
206
|
setLinkDom(null);
|
|
102
207
|
return true;
|
|
103
208
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_TAB_COMMAND, function (payload) {
|
|
104
|
-
if (linkNodeRef.current &&
|
|
209
|
+
if (linkNodeRef.current && linkTextInputRef.current) {
|
|
105
210
|
payload.stopImmediatePropagation();
|
|
106
211
|
payload.preventDefault();
|
|
107
|
-
|
|
212
|
+
linkTextInputRef.current.focus();
|
|
108
213
|
return true;
|
|
109
214
|
}
|
|
110
215
|
return false;
|
|
111
216
|
}, COMMAND_PRIORITY_NORMAL));
|
|
112
217
|
}, []);
|
|
113
|
-
return /*#__PURE__*/
|
|
114
|
-
className: styles.
|
|
218
|
+
return /*#__PURE__*/_jsxs(Block, {
|
|
219
|
+
className: styles.linkEdit,
|
|
115
220
|
ref: divRef,
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
221
|
+
shadow: true,
|
|
222
|
+
variant: 'outlined',
|
|
223
|
+
children: [/*#__PURE__*/_jsxs(Flexbox, {
|
|
224
|
+
gap: 8,
|
|
225
|
+
padding: 12,
|
|
226
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
227
|
+
weight: 500,
|
|
228
|
+
children: t('link.editTextTitle')
|
|
229
|
+
}), /*#__PURE__*/_jsx(Input, {
|
|
230
|
+
onChange: function onChange(e) {
|
|
231
|
+
// Handle link text change
|
|
232
|
+
setLinkText(e.target.value);
|
|
233
|
+
},
|
|
234
|
+
onKeyDown: handleKeyDown,
|
|
235
|
+
prefix: /*#__PURE__*/_jsx(Icon, {
|
|
236
|
+
color: theme.colorTextDescription,
|
|
237
|
+
icon: BaselineIcon
|
|
238
|
+
}),
|
|
239
|
+
ref: linkTextInputRef,
|
|
240
|
+
value: linkText
|
|
241
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
242
|
+
weight: 500,
|
|
243
|
+
children: t('link.editLinkTitle')
|
|
244
|
+
}), /*#__PURE__*/_jsx(Input, {
|
|
245
|
+
onChange: function onChange(e) {
|
|
246
|
+
// Handle link URL change
|
|
247
|
+
setLinkUrl(e.target.value);
|
|
248
|
+
},
|
|
249
|
+
onKeyDown: handleKeyDown,
|
|
250
|
+
placeholder: "https://enter-link-url",
|
|
251
|
+
prefix: /*#__PURE__*/_jsx(Icon, {
|
|
252
|
+
color: theme.colorTextDescription,
|
|
253
|
+
icon: LinkIcon
|
|
254
|
+
}),
|
|
255
|
+
ref: linkInputRef,
|
|
256
|
+
value: linkUrl,
|
|
257
|
+
variant: 'outlined'
|
|
258
|
+
})]
|
|
259
|
+
}), /*#__PURE__*/_jsx(Flexbox, {
|
|
260
|
+
className: styles.linkEditFooter,
|
|
261
|
+
horizontal: true,
|
|
262
|
+
justify: 'flex-end',
|
|
263
|
+
padding: 4,
|
|
264
|
+
width: '100%',
|
|
265
|
+
children: /*#__PURE__*/_jsxs(Button, {
|
|
266
|
+
onClick: function onClick(e) {
|
|
267
|
+
e.preventDefault();
|
|
268
|
+
handleSubmit();
|
|
269
|
+
},
|
|
270
|
+
size: 'small',
|
|
271
|
+
type: 'text',
|
|
272
|
+
variant: 'filled',
|
|
273
|
+
children: [t('confirm'), /*#__PURE__*/_jsx(Hotkey, {
|
|
274
|
+
compact: true,
|
|
275
|
+
keys: "enter",
|
|
276
|
+
variant: 'borderless'
|
|
277
|
+
})]
|
|
278
|
+
})
|
|
279
|
+
})]
|
|
137
280
|
});
|
|
138
|
-
};
|
|
281
|
+
};
|
|
282
|
+
export default LinkEdit;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { type ActionIconGroupProps } from '@lobehub/ui';
|
|
3
|
+
import { LexicalEditor } from 'lexical';
|
|
4
|
+
import { LinkNode } from '../../node/LinkNode';
|
|
5
|
+
interface LinkToolbarProps extends Omit<ActionIconGroupProps, 'items'> {
|
|
6
|
+
editor: LexicalEditor;
|
|
7
|
+
linkNode: LinkNode | null;
|
|
8
|
+
}
|
|
9
|
+
declare const LinkToolbar: import("react").NamedExoticComponent<LinkToolbarProps>;
|
|
10
|
+
export default LinkToolbar;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
var _excluded = ["linkNode", "editor"];
|
|
3
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
9
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
10
|
+
import { ActionIconGroup } from '@lobehub/ui';
|
|
11
|
+
import { EditIcon, ExternalLinkIcon, UnlinkIcon } from 'lucide-react';
|
|
12
|
+
import { memo } from 'react';
|
|
13
|
+
import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
|
|
14
|
+
import { TOGGLE_LINK_COMMAND } from "../../node/LinkNode";
|
|
15
|
+
import { useStyles } from "../style";
|
|
16
|
+
import { EDIT_LINK_COMMAND } from "./LinkEdit";
|
|
17
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
+
var LinkToolbar = /*#__PURE__*/memo(function (_ref) {
|
|
19
|
+
var linkNode = _ref.linkNode,
|
|
20
|
+
editor = _ref.editor,
|
|
21
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
22
|
+
var _useStyles = useStyles(),
|
|
23
|
+
styles = _useStyles.styles;
|
|
24
|
+
var t = useTranslation();
|
|
25
|
+
var handleEdit = function handleEdit() {
|
|
26
|
+
// Edit link
|
|
27
|
+
if (linkNode) {
|
|
28
|
+
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
29
|
+
linkNode: linkNode,
|
|
30
|
+
linkNodeDOM: editor.getElementByKey(linkNode.getKey())
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var handleRemove = function handleRemove() {
|
|
35
|
+
// Remove link
|
|
36
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
37
|
+
};
|
|
38
|
+
var handleOpenLink = function handleOpenLink() {
|
|
39
|
+
// Open link in new window
|
|
40
|
+
if (linkNode) {
|
|
41
|
+
var url = editor.read(function () {
|
|
42
|
+
return linkNode.getURL();
|
|
43
|
+
});
|
|
44
|
+
window.open(url, '_blank');
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return /*#__PURE__*/_jsx(ActionIconGroup, _objectSpread({
|
|
48
|
+
className: styles.linkToolbar,
|
|
49
|
+
items: [{
|
|
50
|
+
icon: EditIcon,
|
|
51
|
+
key: 'edit',
|
|
52
|
+
label: t('link.edit'),
|
|
53
|
+
onClick: handleEdit
|
|
54
|
+
}, {
|
|
55
|
+
icon: ExternalLinkIcon,
|
|
56
|
+
key: 'openLink',
|
|
57
|
+
label: t('link.open'),
|
|
58
|
+
onClick: handleOpenLink
|
|
59
|
+
}, {
|
|
60
|
+
icon: UnlinkIcon,
|
|
61
|
+
key: 'unlink',
|
|
62
|
+
label: t('link.unlink'),
|
|
63
|
+
onClick: handleRemove
|
|
64
|
+
}],
|
|
65
|
+
shadow: true,
|
|
66
|
+
size: {
|
|
67
|
+
blockSize: 32,
|
|
68
|
+
size: 16
|
|
69
|
+
},
|
|
70
|
+
variant: 'outlined'
|
|
71
|
+
}, rest));
|
|
72
|
+
});
|
|
73
|
+
export default LinkToolbar;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const useStyles: (props?: unknown) => import("antd-style").ReturnStyles<{
|
|
2
|
-
editor_linkEdit: import("antd-style").SerializedStyles;
|
|
3
|
-
editor_linkPlugin: import("antd-style").SerializedStyles;
|
|
4
2
|
link: import("antd-style").SerializedStyles;
|
|
3
|
+
linkEdit: string;
|
|
4
|
+
linkEditFooter: import("antd-style").SerializedStyles;
|
|
5
|
+
linkToolbar: string;
|
|
5
6
|
}>;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
var _templateObject, _templateObject2;
|
|
1
|
+
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5;
|
|
2
2
|
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
4
|
export var useStyles = createStyles(function (_ref) {
|
|
5
|
-
var
|
|
5
|
+
var cx = _ref.cx,
|
|
6
|
+
css = _ref.css,
|
|
7
|
+
token = _ref.token;
|
|
6
8
|
var position = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: absolute;\n z-index: 999;\n inset-block-start: -9999px;\n inset-inline-start: -9999px;\n "])));
|
|
7
9
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
link: css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n cursor: pointer;\n\n margin-block: 1em;\n margin-inline: 0;\n padding: 2px;\n border: none;\n "]))),
|
|
11
|
+
linkEdit: cx(position, css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n min-width: 320px;\n max-width: 100%;\n background: ", ";\n "])), token.colorBgElevated)),
|
|
12
|
+
linkEditFooter: css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n border-block-start: 1px solid ", ";\n background: ", ";\n "])), token.colorBorderSecondary, token.colorFillQuaternary),
|
|
13
|
+
linkToolbar: cx(position, css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n background: ", ";\n "])), token.colorBgElevated))
|
|
11
14
|
};
|
|
12
15
|
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import { $insertList, $isListItemNode, $isListNode } from '@lexical/list';
|
|
9
|
+
import { $findMatchingParent, calculateZoomLevel, isHTMLElement, mergeRegister } from '@lexical/utils';
|
|
10
|
+
import { $getNearestNodeFromDOMNode, $getSelection, $isElementNode, $isRangeSelection, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_UP_COMMAND, createCommand, getNearestEditorFromDOMNode } from 'lexical';
|
|
11
|
+
export var INSERT_CHECK_LIST_COMMAND = createCommand('INSERT_CHECK_LIST_COMMAND');
|
|
12
|
+
function handleCheckItemEvent(event, callback) {
|
|
13
|
+
var target = event.target;
|
|
14
|
+
if (!isHTMLElement(target)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Ignore clicks on LI that have nested lists
|
|
19
|
+
var firstChild = target.firstChild;
|
|
20
|
+
if (isHTMLElement(firstChild) && (firstChild.tagName === 'UL' || firstChild.tagName === 'OL')) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
var parentNode = target.parentNode;
|
|
24
|
+
|
|
25
|
+
// @ts-ignore internal field
|
|
26
|
+
if (!parentNode || parentNode.__lexicalListType !== 'check') {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
var rect = target.getBoundingClientRect();
|
|
30
|
+
var zoom = calculateZoomLevel(target);
|
|
31
|
+
var clientX = event.clientX / zoom;
|
|
32
|
+
|
|
33
|
+
// Use getComputedStyle if available, otherwise fallback to 0px width
|
|
34
|
+
var beforeStyles = window.getComputedStyle ? window.getComputedStyle(target, '::before') : {
|
|
35
|
+
width: '0px'
|
|
36
|
+
};
|
|
37
|
+
var beforeWidthInPixels = parseFloat(beforeStyles.width);
|
|
38
|
+
var beforeMargin = parseFloat(beforeStyles.marginLeft);
|
|
39
|
+
|
|
40
|
+
// Make click area slightly larger for touch devices to improve accessibility
|
|
41
|
+
var isTouchEvent = event.pointerType === 'touch';
|
|
42
|
+
var clickAreaPadding = isTouchEvent ? 32 : 0; // Add 32px padding for touch events
|
|
43
|
+
|
|
44
|
+
if (target.dir === 'rtl' ? clientX < rect.right + clickAreaPadding && clientX > rect.right - beforeWidthInPixels - clickAreaPadding : clientX > rect.left + beforeMargin - clickAreaPadding && clientX < rect.left + beforeMargin + beforeWidthInPixels + clickAreaPadding) {
|
|
45
|
+
callback();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function handleClick(event) {
|
|
49
|
+
handleCheckItemEvent(event, function () {
|
|
50
|
+
if (isHTMLElement(event.target)) {
|
|
51
|
+
var domNode = event.target;
|
|
52
|
+
var editor = getNearestEditorFromDOMNode(domNode);
|
|
53
|
+
if (editor && editor.isEditable()) {
|
|
54
|
+
editor.update(function () {
|
|
55
|
+
var node = $getNearestNodeFromDOMNode(domNode);
|
|
56
|
+
if ($isListItemNode(node)) {
|
|
57
|
+
domNode.focus();
|
|
58
|
+
node.toggleChecked();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function handlePointerDown(event) {
|
|
66
|
+
handleCheckItemEvent(event, function () {
|
|
67
|
+
// Prevents caret moving when clicking on check mark
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function getActiveCheckListItem() {
|
|
72
|
+
var activeElement = document.activeElement;
|
|
73
|
+
return isHTMLElement(activeElement) && activeElement.tagName === 'LI' && activeElement.parentNode &&
|
|
74
|
+
// @ts-ignore internal field
|
|
75
|
+
activeElement.parentNode.__lexicalListType === 'check' ? activeElement : null;
|
|
76
|
+
}
|
|
77
|
+
function findCheckListItemSibling(node, backward) {
|
|
78
|
+
var sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
|
|
79
|
+
var parent = node;
|
|
80
|
+
|
|
81
|
+
// Going up in a tree to get non-null sibling
|
|
82
|
+
while (!sibling && $isListItemNode(parent)) {
|
|
83
|
+
// Get li -> parent ul/ol -> parent li
|
|
84
|
+
parent = parent.getParentOrThrow().getParent();
|
|
85
|
+
if (parent) {
|
|
86
|
+
sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Going down in a tree to get first non-nested list item
|
|
91
|
+
while ($isListItemNode(sibling)) {
|
|
92
|
+
var firstChild = backward ? sibling.getLastChild() : sibling.getFirstChild();
|
|
93
|
+
if (!$isListNode(firstChild)) {
|
|
94
|
+
return sibling;
|
|
95
|
+
}
|
|
96
|
+
sibling = backward ? firstChild.getLastChild() : firstChild.getFirstChild();
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
function handleArrowUpOrDown(event, editor, backward) {
|
|
101
|
+
var activeItem = getActiveCheckListItem();
|
|
102
|
+
if (activeItem) {
|
|
103
|
+
editor.update(function () {
|
|
104
|
+
var listItem = $getNearestNodeFromDOMNode(activeItem);
|
|
105
|
+
if (!$isListItemNode(listItem)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
var nextListItem = findCheckListItemSibling(listItem, backward);
|
|
109
|
+
if (nextListItem) {
|
|
110
|
+
nextListItem.selectStart();
|
|
111
|
+
var dom = editor.getElementByKey(nextListItem.__key);
|
|
112
|
+
if (dom) {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
setTimeout(function () {
|
|
115
|
+
dom.focus();
|
|
116
|
+
}, 0);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
export function registerCheckList(editor) {
|
|
124
|
+
return mergeRegister(editor.registerCommand(INSERT_CHECK_LIST_COMMAND, function () {
|
|
125
|
+
$insertList('check');
|
|
126
|
+
return true;
|
|
127
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_DOWN_COMMAND, function (event) {
|
|
128
|
+
return handleArrowUpOrDown(event, editor, false);
|
|
129
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_UP_COMMAND, function (event) {
|
|
130
|
+
return handleArrowUpOrDown(event, editor, true);
|
|
131
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, function (event) {
|
|
132
|
+
return editor.getEditorState().read(function () {
|
|
133
|
+
var selection = $getSelection();
|
|
134
|
+
if ($isRangeSelection(selection) && selection.isCollapsed()) {
|
|
135
|
+
var anchor = selection.anchor;
|
|
136
|
+
var isElement = anchor.type === 'element';
|
|
137
|
+
if (isElement || anchor.offset === 0) {
|
|
138
|
+
var anchorNode = anchor.getNode();
|
|
139
|
+
var elementNode = $findMatchingParent(anchorNode, function (node) {
|
|
140
|
+
return $isElementNode(node) && !node.isInline();
|
|
141
|
+
});
|
|
142
|
+
if ($isListItemNode(elementNode)) {
|
|
143
|
+
var parent = elementNode.getParent();
|
|
144
|
+
if ($isListNode(parent) && parent.getListType() === 'check' && (isElement || elementNode.getFirstDescendant() === anchorNode)) {
|
|
145
|
+
var domNode = editor.getElementByKey(elementNode.__key);
|
|
146
|
+
if (domNode && document.activeElement !== domNode) {
|
|
147
|
+
domNode.focus();
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
});
|
|
157
|
+
}, COMMAND_PRIORITY_LOW), editor.registerRootListener(function (rootElement, prevElement) {
|
|
158
|
+
if (rootElement !== null) {
|
|
159
|
+
rootElement.addEventListener('click', handleClick);
|
|
160
|
+
rootElement.addEventListener('pointerdown', handlePointerDown);
|
|
161
|
+
}
|
|
162
|
+
if (prevElement !== null) {
|
|
163
|
+
prevElement.removeEventListener('click', handleClick);
|
|
164
|
+
prevElement.removeEventListener('pointerdown', handlePointerDown);
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
@@ -20,6 +20,7 @@ import { $createParagraphNode, $getSelection, $isRangeSelection, $isRootNode, $i
|
|
|
20
20
|
import { KernelPlugin } from "../../../editor-kernel/plugin";
|
|
21
21
|
import { IMarkdownShortCutService } from "../../markdown";
|
|
22
22
|
import { $indentOverTab, listReplace } from "../utils";
|
|
23
|
+
import { registerCheckList } from "./checkList";
|
|
23
24
|
var ORDERED_LIST_REGEX = /^(\s*)(\d+)\.\s/;
|
|
24
25
|
var UNORDERED_LIST_REGEX = /^(\s*)[*+-]\s/;
|
|
25
26
|
var CHECK_LIST_REGEX = /^(\s*)(?:-\s)?\s?(\[(\s|x)?])\s/i;
|
|
@@ -41,7 +42,10 @@ export var ListPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
41
42
|
kernel.registerThemes({
|
|
42
43
|
// Define themes for list nodes here
|
|
43
44
|
list: {
|
|
45
|
+
checklist: 'editor_listItemCheck',
|
|
44
46
|
listitem: 'editor_listItem',
|
|
47
|
+
listitemChecked: 'editor_listItemChecked',
|
|
48
|
+
listitemUnchecked: 'editor_listItemUnchecked',
|
|
45
49
|
nested: {
|
|
46
50
|
listitem: 'editor_listItemNested'
|
|
47
51
|
},
|
|
@@ -102,7 +106,7 @@ export var ListPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
102
106
|
}
|
|
103
107
|
case 'check':
|
|
104
108
|
{
|
|
105
|
-
ctx.wrap("".concat(prefix, "[").concat(node.getChecked() ? 'x' : ' ', "] "), '\n');
|
|
109
|
+
ctx.wrap("".concat(prefix, "- [").concat(node.getChecked() ? 'x' : ' ', "] "), '\n');
|
|
106
110
|
break;
|
|
107
111
|
}
|
|
108
112
|
default:
|
|
@@ -118,6 +122,7 @@ export var ListPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
118
122
|
key: "onInit",
|
|
119
123
|
value: function onInit(editor) {
|
|
120
124
|
this.register(registerList(editor));
|
|
125
|
+
this.register(registerCheckList(editor));
|
|
121
126
|
this.register(registerListStrictIndentTransform(editor));
|
|
122
127
|
this.registerClears(editor.registerCommand(KEY_TAB_COMMAND, function (event) {
|
|
123
128
|
var selection = $getSelection();
|
|
@@ -139,7 +144,9 @@ export var ListPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
|
|
|
139
144
|
}
|
|
140
145
|
var anchorNode = anchor.getNode();
|
|
141
146
|
var listItemNode;
|
|
142
|
-
if ($
|
|
147
|
+
if ($isListItemNode(anchorNode)) {
|
|
148
|
+
listItemNode = anchorNode;
|
|
149
|
+
} else if ($isTextNode(anchorNode)) {
|
|
143
150
|
// Do not handle non-leading text nodes
|
|
144
151
|
if (anchorNode.getPreviousSibling()) {
|
|
145
152
|
return false;
|