@lobehub/editor 1.8.2 → 1.8.4
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/react/PortalAnchor.d.ts +5 -0
- package/es/editor-kernel/react/PortalAnchor.js +13 -0
- package/es/editor-kernel/react/useAnchor.d.ts +1 -0
- package/es/editor-kernel/react/useAnchor.js +23 -0
- package/es/plugins/link/react/ReactLinkPlugin.js +9 -104
- package/es/plugins/link/react/components/LinkEdit.d.ts +6 -2
- package/es/plugins/link/react/components/LinkEdit.js +49 -94
- package/es/plugins/link/react/components/LinkToolbar.d.ts +1 -4
- package/es/plugins/link/react/components/LinkToolbar.js +87 -21
- package/es/plugins/link/react/style.js +1 -1
- package/es/plugins/math/react/{component → components}/MathEditor.js +11 -8
- package/es/plugins/math/react/{component → components}/MathEditorContainer.d.ts +2 -1
- package/es/plugins/math/react/{component → components}/MathEditorContainer.js +27 -31
- package/es/plugins/math/react/{component → components}/MathEditorContent.d.ts +2 -1
- package/es/plugins/math/react/{component → components}/MathEditorContent.js +3 -2
- package/es/plugins/math/react/index.js +2 -2
- package/es/plugins/math/react/style.js +1 -1
- package/es/plugins/slash/react/components/DefaultSlashMenu.d.ts +5 -0
- package/es/plugins/slash/react/components/DefaultSlashMenu.js +48 -0
- package/es/plugins/slash/react/components/SlashMenu.d.ts +2 -2
- package/es/plugins/slash/react/components/SlashMenu.js +16 -36
- package/es/plugins/table/react/TableActionMenu/ActionMenu.d.ts +19 -0
- package/es/plugins/table/react/TableActionMenu/ActionMenu.js +285 -0
- package/es/plugins/table/react/TableActionMenu/index.d.ts +2 -3
- package/es/plugins/table/react/TableActionMenu/index.js +27 -329
- package/es/plugins/table/react/TableActionMenu/style.js +1 -1
- package/es/plugins/table/react/TableHoverActions/index.d.ts +3 -4
- package/es/plugins/table/react/TableHoverActions/index.js +7 -20
- package/es/plugins/table/react/index.js +8 -5
- package/es/utils/updatePosition.d.ts +9 -0
- package/es/utils/updatePosition.js +27 -0
- package/package.json +1 -1
- /package/es/plugins/math/react/{component → components}/MathEditor.d.ts +0 -0
- /package/es/plugins/math/react/{component → components}/MathInline.d.ts +0 -0
- /package/es/plugins/math/react/{component → components}/MathInline.js +0 -0
- /package/es/plugins/math/react/{component → components}/Placeholder.d.ts +0 -0
- /package/es/plugins/math/react/{component → components}/Placeholder.js +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { useAnchor } from "./useAnchor";
|
|
6
|
+
var PortalAnchor = /*#__PURE__*/memo(function (_ref) {
|
|
7
|
+
var children = _ref.children;
|
|
8
|
+
var targetElement = useAnchor();
|
|
9
|
+
if (!targetElement) return null;
|
|
10
|
+
return /*#__PURE__*/createPortal(children, targetElement);
|
|
11
|
+
});
|
|
12
|
+
PortalAnchor.displayName = 'PortalAnchor';
|
|
13
|
+
export default PortalAnchor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useAnchor: () => HTMLElement | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
4
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
5
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
6
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
7
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
8
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
9
|
+
import { useMemo } from 'react';
|
|
10
|
+
import { useLexicalComposerContext } from "./react-context";
|
|
11
|
+
export var useAnchor = function useAnchor() {
|
|
12
|
+
var _useLexicalComposerCo = useLexicalComposerContext(),
|
|
13
|
+
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
|
|
14
|
+
editor = _useLexicalComposerCo2[0];
|
|
15
|
+
// Don't render portal on server side
|
|
16
|
+
|
|
17
|
+
return useMemo(function () {
|
|
18
|
+
if (typeof document === 'undefined' || !editor) return;
|
|
19
|
+
var root = editor.getRootElement();
|
|
20
|
+
var anchor = root ? root.parentElement : null;
|
|
21
|
+
return anchor || document.body;
|
|
22
|
+
}, [editor]);
|
|
23
|
+
};
|
|
@@ -6,25 +6,17 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
6
6
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
7
7
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
8
8
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_NORMAL } from 'lexical';
|
|
12
|
-
import { useLayoutEffect, useRef, useState } from 'react';
|
|
13
|
-
import { createPortal } from 'react-dom';
|
|
14
|
-
import { useLexicalEditor } from "../../../editor-kernel/react";
|
|
9
|
+
import { useLayoutEffect } from 'react';
|
|
10
|
+
import PortalAnchor from "../../../editor-kernel/react/PortalAnchor";
|
|
15
11
|
import { useLexicalComposerContext } from "../../../editor-kernel/react/react-context";
|
|
16
12
|
import { MarkdownPlugin } from "../../markdown";
|
|
17
|
-
import { $isLinkNode, HOVER_LINK_COMMAND, HOVER_OUT_LINK_COMMAND } from "../node/LinkNode";
|
|
18
13
|
import { LinkPlugin } from "../plugin";
|
|
19
|
-
import
|
|
20
|
-
import LinkEdit, { EDIT_LINK_COMMAND } from "./components/LinkEdit";
|
|
14
|
+
import LinkEdit from "./components/LinkEdit";
|
|
21
15
|
import LinkToolbar from "./components/LinkToolbar";
|
|
22
16
|
import { useStyles } from "./style";
|
|
23
17
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
|
-
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
25
18
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
26
19
|
export var ReactLinkPlugin = function ReactLinkPlugin(_ref) {
|
|
27
|
-
var _editor$getLexicalEdi, _lexicalEditor$getRoo;
|
|
28
20
|
var theme = _ref.theme,
|
|
29
21
|
_ref$enableHotkey = _ref.enableHotkey,
|
|
30
22
|
enableHotkey = _ref$enableHotkey === void 0 ? true : _ref$enableHotkey,
|
|
@@ -33,16 +25,6 @@ export var ReactLinkPlugin = function ReactLinkPlugin(_ref) {
|
|
|
33
25
|
var _useLexicalComposerCo = useLexicalComposerContext(),
|
|
34
26
|
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
|
|
35
27
|
editor = _useLexicalComposerCo2[0];
|
|
36
|
-
var _useState = useState(null),
|
|
37
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
38
|
-
linkNode = _useState2[0],
|
|
39
|
-
setLinkNode = _useState2[1];
|
|
40
|
-
var state = useRef({
|
|
41
|
-
isLink: false
|
|
42
|
-
});
|
|
43
|
-
var divRef = useRef(null);
|
|
44
|
-
var LinkRef = useRef(null);
|
|
45
|
-
var clearTimerRef = useRef(-1);
|
|
46
28
|
var _useStyles = useStyles(),
|
|
47
29
|
styles = _useStyles.styles;
|
|
48
30
|
useLayoutEffect(function () {
|
|
@@ -54,90 +36,13 @@ export var ReactLinkPlugin = function ReactLinkPlugin(_ref) {
|
|
|
54
36
|
validateUrl: validateUrl
|
|
55
37
|
});
|
|
56
38
|
}, [attributes, enableHotkey, styles, theme, validateUrl]);
|
|
57
|
-
|
|
58
|
-
return mergeRegister(editor.registerUpdateListener(function () {
|
|
59
|
-
var selection = editor.read(function () {
|
|
60
|
-
return $getSelection();
|
|
61
|
-
});
|
|
62
|
-
if (!selection) return;
|
|
63
|
-
if ($isRangeSelection(selection)) {
|
|
64
|
-
// Update links for UI components
|
|
65
|
-
editor.read(function () {
|
|
66
|
-
var node = getSelectedNode(selection);
|
|
67
|
-
var parent = node.getParent();
|
|
68
|
-
var isLink = $isLinkNode(parent) || $isLinkNode(node);
|
|
69
|
-
state.current.isLink = isLink;
|
|
70
|
-
if (isLink) {
|
|
71
|
-
var _linkNode = $isLinkNode(parent) ? parent : node;
|
|
72
|
-
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
73
|
-
linkNode: _linkNode,
|
|
74
|
-
linkNodeDOM: editor.getElementByKey(_linkNode.getKey())
|
|
75
|
-
});
|
|
76
|
-
} else {
|
|
77
|
-
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
78
|
-
linkNode: null,
|
|
79
|
-
linkNodeDOM: null
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
} else {
|
|
84
|
-
state.current.isLink = false;
|
|
85
|
-
}
|
|
86
|
-
}), editor.registerCommand(HOVER_LINK_COMMAND, function (payload) {
|
|
87
|
-
if (!payload.event.target || divRef.current === null) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
// Cancel any pending hide timers when hovering a link again
|
|
91
|
-
clearTimeout(clearTimerRef.current);
|
|
92
|
-
setLinkNode(payload.linkNode);
|
|
93
|
-
computePosition(payload.event.target, divRef.current, {
|
|
94
|
-
middleware: [offset(5), flip(), shift()],
|
|
95
|
-
placement: 'top-start'
|
|
96
|
-
}).then(function (_ref2) {
|
|
97
|
-
var x = _ref2.x,
|
|
98
|
-
y = _ref2.y;
|
|
99
|
-
if (!payload.event.target || divRef.current === null) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
LinkRef.current = payload.event.target;
|
|
103
|
-
divRef.current.style.left = "".concat(x, "px");
|
|
104
|
-
divRef.current.style.top = "".concat(y, "px");
|
|
105
|
-
});
|
|
106
|
-
return false;
|
|
107
|
-
}, COMMAND_PRIORITY_NORMAL), editor.registerCommand(HOVER_OUT_LINK_COMMAND, function () {
|
|
108
|
-
clearTimeout(clearTimerRef.current);
|
|
109
|
-
clearTimerRef.current = setTimeout(function () {
|
|
110
|
-
if (divRef.current) {
|
|
111
|
-
divRef.current.style.left = '-9999px';
|
|
112
|
-
divRef.current.style.top = '-9999px';
|
|
113
|
-
}
|
|
114
|
-
}, 300);
|
|
115
|
-
return true;
|
|
116
|
-
}, COMMAND_PRIORITY_NORMAL));
|
|
117
|
-
}, []);
|
|
118
|
-
|
|
119
|
-
// Determine anchor element (editor inner wrapper)
|
|
120
|
-
var lexicalEditor = (_editor$getLexicalEdi = editor.getLexicalEditor) === null || _editor$getLexicalEdi === void 0 ? void 0 : _editor$getLexicalEdi.call(editor);
|
|
121
|
-
var root = lexicalEditor === null || lexicalEditor === void 0 || (_lexicalEditor$getRoo = lexicalEditor.getRootElement) === null || _lexicalEditor$getRoo === void 0 ? void 0 : _lexicalEditor$getRoo.call(lexicalEditor);
|
|
122
|
-
var anchor = root ? root.parentElement : null;
|
|
123
|
-
var targetElement = anchor || (typeof document !== 'undefined' ? document.body : null);
|
|
124
|
-
return targetElement ? /*#__PURE__*/createPortal( /*#__PURE__*/_jsxs(_Fragment, {
|
|
39
|
+
return /*#__PURE__*/_jsxs(PortalAnchor, {
|
|
125
40
|
children: [/*#__PURE__*/_jsx(LinkToolbar, {
|
|
126
|
-
editor: editor.getLexicalEditor()
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
onMouseLeave: function onMouseLeave() {
|
|
132
|
-
clearTimeout(clearTimerRef.current);
|
|
133
|
-
if (divRef.current) {
|
|
134
|
-
divRef.current.style.left = '-9999px';
|
|
135
|
-
divRef.current.style.top = '-9999px';
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
ref: divRef
|
|
139
|
-
}), /*#__PURE__*/_jsx(LinkEdit, {})]
|
|
140
|
-
}), targetElement) : null;
|
|
41
|
+
editor: editor.getLexicalEditor()
|
|
42
|
+
}), /*#__PURE__*/_jsx(LinkEdit, {
|
|
43
|
+
editor: editor.getLexicalEditor()
|
|
44
|
+
})]
|
|
45
|
+
});
|
|
141
46
|
};
|
|
142
47
|
ReactLinkPlugin.displayName = 'ReactLinkPlugin';
|
|
143
48
|
export default ReactLinkPlugin;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { LexicalEditor } from 'lexical';
|
|
2
3
|
import { LinkNode } from '../../node/LinkNode';
|
|
3
4
|
export declare const EDIT_LINK_COMMAND: import("lexical").LexicalCommand<{
|
|
4
5
|
linkNode: LinkNode | null;
|
|
5
6
|
linkNodeDOM: HTMLElement | null;
|
|
6
7
|
}>;
|
|
7
|
-
|
|
8
|
+
interface LinkEditProps {
|
|
9
|
+
editor: LexicalEditor;
|
|
10
|
+
}
|
|
11
|
+
declare const LinkEdit: import("react").NamedExoticComponent<LinkEditProps>;
|
|
8
12
|
export default LinkEdit;
|
|
@@ -4,21 +4,22 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
4
4
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
-
import { computePosition, flip, offset, shift } from '@floating-ui/dom';
|
|
8
7
|
import { mergeRegister } from '@lexical/utils';
|
|
9
8
|
import { Block, Button, Hotkey, Icon, Input, Text } from '@lobehub/ui';
|
|
10
9
|
import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_NORMAL, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, createCommand } from 'lexical';
|
|
11
10
|
import { BaselineIcon, LinkIcon } from 'lucide-react';
|
|
12
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
11
|
+
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
13
12
|
import { Flexbox } from 'react-layout-kit';
|
|
14
|
-
import {
|
|
13
|
+
import { useLexicalEditor } from "../../../../editor-kernel/react";
|
|
15
14
|
import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
|
|
15
|
+
import { cleanPosition, updatePosition } from "../../../../utils/updatePosition";
|
|
16
16
|
import { UPDATE_LINK_TEXT_COMMAND } from "../../command";
|
|
17
17
|
import { useStyles } from "../style";
|
|
18
18
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
19
19
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
20
|
export var EDIT_LINK_COMMAND = createCommand();
|
|
21
|
-
var LinkEdit = function
|
|
21
|
+
var LinkEdit = /*#__PURE__*/memo(function (_ref) {
|
|
22
|
+
var editor = _ref.editor;
|
|
22
23
|
var divRef = useRef(null);
|
|
23
24
|
var linkNodeRef = useRef(null);
|
|
24
25
|
var linkInputRef = useRef(null);
|
|
@@ -35,9 +36,6 @@ var LinkEdit = function LinkEdit() {
|
|
|
35
36
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
36
37
|
linkDom = _useState6[0],
|
|
37
38
|
setLinkDom = _useState6[1];
|
|
38
|
-
var _useLexicalComposerCo = useLexicalComposerContext(),
|
|
39
|
-
_useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
|
|
40
|
-
editor = _useLexicalComposerCo2[0];
|
|
41
39
|
var t = useTranslation();
|
|
42
40
|
var _useStyles = useStyles(),
|
|
43
41
|
styles = _useStyles.styles,
|
|
@@ -45,66 +43,18 @@ var LinkEdit = function LinkEdit() {
|
|
|
45
43
|
|
|
46
44
|
// 取消编辑,不保存更改
|
|
47
45
|
var handleCancel = useCallback(function () {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// 将焦点返回到编辑器
|
|
52
|
-
lexicalEditor.focus();
|
|
53
|
-
|
|
54
|
-
// 隐藏编辑面板
|
|
55
|
-
if (divRef.current) {
|
|
56
|
-
divRef.current.style.left = '-9999px';
|
|
57
|
-
divRef.current.style.top = '-9999px';
|
|
58
|
-
}
|
|
46
|
+
if (!editor) return;
|
|
47
|
+
editor.focus();
|
|
48
|
+
cleanPosition(divRef.current);
|
|
59
49
|
linkNodeRef.current = null;
|
|
60
50
|
setLinkUrl('');
|
|
61
51
|
setLinkText('');
|
|
62
52
|
setLinkDom(null);
|
|
63
53
|
}, [editor]);
|
|
64
|
-
useEffect(function () {
|
|
65
|
-
if (!linkDom || !divRef.current) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
computePosition(linkDom, divRef.current, {
|
|
69
|
-
middleware: [offset(8), flip(), shift()],
|
|
70
|
-
placement: 'bottom-start'
|
|
71
|
-
}).then(function (_ref) {
|
|
72
|
-
var x = _ref.x,
|
|
73
|
-
y = _ref.y;
|
|
74
|
-
if (divRef.current) {
|
|
75
|
-
divRef.current.style.left = "".concat(x, "px");
|
|
76
|
-
divRef.current.style.top = "".concat(y, "px");
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}, [linkDom]);
|
|
80
|
-
|
|
81
|
-
// 点击编辑器外部时关闭面板
|
|
82
|
-
useEffect(function () {
|
|
83
|
-
var handlePointerDown = function handlePointerDown(event) {
|
|
84
|
-
if (!divRef.current) return;
|
|
85
|
-
var target = event.target;
|
|
86
|
-
if (!target) return;
|
|
87
|
-
// 点击面板内部忽略
|
|
88
|
-
if (divRef.current.contains(target)) return;
|
|
89
|
-
// 面板打开时(存在 linkDom)才触发关闭
|
|
90
|
-
if (linkDom) {
|
|
91
|
-
handleCancel();
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
document.addEventListener('mousedown', handlePointerDown);
|
|
95
|
-
document.addEventListener('touchstart', handlePointerDown);
|
|
96
|
-
return function () {
|
|
97
|
-
document.removeEventListener('mousedown', handlePointerDown);
|
|
98
|
-
document.removeEventListener('touchstart', handlePointerDown);
|
|
99
|
-
};
|
|
100
|
-
}, [handleCancel, linkDom]);
|
|
101
54
|
|
|
102
55
|
// 提取提交逻辑到独立函数
|
|
103
56
|
var handleSubmit = useCallback(function () {
|
|
104
|
-
|
|
105
|
-
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !lexicalEditor) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
57
|
+
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !editor) return;
|
|
108
58
|
var linkNode = linkNodeRef.current;
|
|
109
59
|
var input = linkInputRef.current;
|
|
110
60
|
var inputDOM = input.input;
|
|
@@ -112,42 +62,34 @@ var LinkEdit = function LinkEdit() {
|
|
|
112
62
|
var textInputDOM = textInput.input;
|
|
113
63
|
|
|
114
64
|
// 更新链接URL
|
|
115
|
-
var currentURL =
|
|
65
|
+
var currentURL = editor.read(function () {
|
|
116
66
|
return linkNode.getURL();
|
|
117
67
|
});
|
|
118
68
|
if (currentURL !== inputDOM.value) {
|
|
119
|
-
|
|
69
|
+
editor.update(function () {
|
|
120
70
|
linkNode.setURL(inputDOM.value);
|
|
121
71
|
});
|
|
122
72
|
}
|
|
123
73
|
|
|
124
74
|
// 更新链接文本
|
|
125
|
-
var currentText =
|
|
75
|
+
var currentText = editor.read(function () {
|
|
126
76
|
return linkNode.getTextContent();
|
|
127
77
|
});
|
|
128
78
|
if (currentText !== textInputDOM.value) {
|
|
129
|
-
|
|
79
|
+
editor.dispatchCommand(UPDATE_LINK_TEXT_COMMAND, {
|
|
130
80
|
key: linkNode.getKey(),
|
|
131
81
|
text: textInputDOM.value
|
|
132
82
|
});
|
|
133
83
|
}
|
|
134
84
|
|
|
135
85
|
// 关闭编辑器并聚焦到编辑器
|
|
136
|
-
|
|
86
|
+
editor.focus();
|
|
137
87
|
|
|
138
88
|
// 隐藏编辑面板
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
divRef.current.style.top = '-9999px';
|
|
142
|
-
}
|
|
143
|
-
linkNodeRef.current = null;
|
|
144
|
-
setLinkUrl('');
|
|
145
|
-
setLinkText('');
|
|
146
|
-
setLinkDom(null);
|
|
147
|
-
}, [editor, linkNodeRef, linkInputRef, linkTextInputRef]);
|
|
89
|
+
handleCancel();
|
|
90
|
+
}, [editor, linkNodeRef, linkInputRef, linkTextInputRef, handleCancel]);
|
|
148
91
|
var handleKeyDown = useCallback(function (event) {
|
|
149
|
-
|
|
150
|
-
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !lexicalEditor) {
|
|
92
|
+
if (!linkNodeRef.current || !linkInputRef.current || !linkTextInputRef.current || !editor) {
|
|
151
93
|
return;
|
|
152
94
|
}
|
|
153
95
|
var linkNode = linkNodeRef.current;
|
|
@@ -160,11 +102,11 @@ var LinkEdit = function LinkEdit() {
|
|
|
160
102
|
{
|
|
161
103
|
event.preventDefault();
|
|
162
104
|
if (event.currentTarget === textInputDOM) {
|
|
163
|
-
var currentText =
|
|
105
|
+
var currentText = editor.read(function () {
|
|
164
106
|
return linkNode.getTextContent();
|
|
165
107
|
});
|
|
166
108
|
if (currentText !== textInputDOM.value) {
|
|
167
|
-
|
|
109
|
+
editor.dispatchCommand(UPDATE_LINK_TEXT_COMMAND, {
|
|
168
110
|
key: linkNode.getKey(),
|
|
169
111
|
text: textInputDOM.value
|
|
170
112
|
});
|
|
@@ -186,7 +128,7 @@ var LinkEdit = function LinkEdit() {
|
|
|
186
128
|
if (event.currentTarget === textInputDOM) {
|
|
187
129
|
inputDOM.focus();
|
|
188
130
|
} else {
|
|
189
|
-
|
|
131
|
+
editor.focus();
|
|
190
132
|
}
|
|
191
133
|
return;
|
|
192
134
|
}
|
|
@@ -199,16 +141,35 @@ var LinkEdit = function LinkEdit() {
|
|
|
199
141
|
// No default
|
|
200
142
|
}
|
|
201
143
|
}, [linkNodeRef, linkInputRef, handleSubmit, handleCancel]);
|
|
144
|
+
useEffect(function () {
|
|
145
|
+
updatePosition({
|
|
146
|
+
floating: divRef.current,
|
|
147
|
+
reference: linkDom
|
|
148
|
+
});
|
|
149
|
+
}, [linkDom]);
|
|
150
|
+
|
|
151
|
+
// 点击编辑器外部时关闭面板
|
|
152
|
+
useEffect(function () {
|
|
153
|
+
var handlePointerDown = function handlePointerDown(event) {
|
|
154
|
+
if (!divRef.current) return;
|
|
155
|
+
var target = event.target;
|
|
156
|
+
if (!target) return;
|
|
157
|
+
// 点击面板内部忽略
|
|
158
|
+
if (divRef.current.contains(target)) return;
|
|
159
|
+
// 面板打开时(存在 linkDom)才触发关闭
|
|
160
|
+
if (linkDom) handleCancel();
|
|
161
|
+
};
|
|
162
|
+
document.addEventListener('mousedown', handlePointerDown);
|
|
163
|
+
document.addEventListener('touchstart', handlePointerDown);
|
|
164
|
+
return function () {
|
|
165
|
+
document.removeEventListener('mousedown', handlePointerDown);
|
|
166
|
+
document.removeEventListener('touchstart', handlePointerDown);
|
|
167
|
+
};
|
|
168
|
+
}, [linkDom]);
|
|
202
169
|
useLexicalEditor(function (editor) {
|
|
203
170
|
return mergeRegister(editor.registerCommand(EDIT_LINK_COMMAND, function (payload) {
|
|
204
171
|
if (!payload.linkNode || !payload.linkNodeDOM) {
|
|
205
|
-
|
|
206
|
-
setLinkUrl('');
|
|
207
|
-
setLinkText('');
|
|
208
|
-
if (divRef.current) {
|
|
209
|
-
divRef.current.style.left = '-9999px';
|
|
210
|
-
divRef.current.style.top = '-9999px';
|
|
211
|
-
}
|
|
172
|
+
handleCancel();
|
|
212
173
|
return false;
|
|
213
174
|
}
|
|
214
175
|
linkNodeRef.current = payload.linkNode;
|
|
@@ -217,14 +178,7 @@ var LinkEdit = function LinkEdit() {
|
|
|
217
178
|
setLinkDom(payload.linkNodeDOM);
|
|
218
179
|
return true;
|
|
219
180
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_ESCAPE_COMMAND, function () {
|
|
220
|
-
|
|
221
|
-
divRef.current.style.left = '-9999px';
|
|
222
|
-
divRef.current.style.top = '-9999px';
|
|
223
|
-
}
|
|
224
|
-
linkNodeRef.current = null;
|
|
225
|
-
setLinkUrl('');
|
|
226
|
-
setLinkText('');
|
|
227
|
-
setLinkDom(null);
|
|
181
|
+
handleCancel();
|
|
228
182
|
return true;
|
|
229
183
|
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(KEY_TAB_COMMAND, function (payload) {
|
|
230
184
|
if (linkNodeRef.current && linkTextInputRef.current) {
|
|
@@ -298,5 +252,6 @@ var LinkEdit = function LinkEdit() {
|
|
|
298
252
|
})
|
|
299
253
|
})]
|
|
300
254
|
});
|
|
301
|
-
};
|
|
255
|
+
});
|
|
256
|
+
LinkEdit.displayName = 'LinkEdit';
|
|
302
257
|
export default LinkEdit;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { type ActionIconGroupProps } from '@lobehub/ui';
|
|
3
2
|
import { LexicalEditor } from 'lexical';
|
|
4
|
-
|
|
5
|
-
interface LinkToolbarProps extends Omit<ActionIconGroupProps, 'items'> {
|
|
3
|
+
interface LinkToolbarProps {
|
|
6
4
|
editor: LexicalEditor;
|
|
7
|
-
linkNode: LinkNode | null;
|
|
8
5
|
}
|
|
9
6
|
declare const LinkToolbar: import("react").NamedExoticComponent<LinkToolbarProps>;
|
|
10
7
|
export default LinkToolbar;
|
|
@@ -1,32 +1,38 @@
|
|
|
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", "onMouseLeave"];
|
|
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
1
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
2
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
3
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
4
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
5
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
11
|
-
function
|
|
12
|
-
function
|
|
6
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
7
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
8
|
+
import { mergeRegister } from '@lexical/utils';
|
|
13
9
|
import { ActionIconGroup } from '@lobehub/ui';
|
|
14
|
-
import { $createRangeSelection, $getNodeByKey, $getSelection, $isRangeSelection, $isTextNode, $setSelection } from 'lexical';
|
|
10
|
+
import { $createRangeSelection, $getNodeByKey, $getSelection, $isRangeSelection, $isTextNode, $setSelection, COMMAND_PRIORITY_NORMAL } from 'lexical';
|
|
15
11
|
import { EditIcon, ExternalLinkIcon, UnlinkIcon } from 'lucide-react';
|
|
16
|
-
import { memo, useCallback } from 'react';
|
|
12
|
+
import { memo, useCallback, useRef, useState } from 'react';
|
|
13
|
+
import { useLexicalEditor } from "../../../../editor-kernel/react";
|
|
17
14
|
import { useTranslation } from "../../../../editor-kernel/react/useTranslation";
|
|
18
|
-
import {
|
|
15
|
+
import { getSelectedNode } from "../../utils";
|
|
16
|
+
import { cleanPosition, updatePosition } from "../../../../utils/updatePosition";
|
|
17
|
+
import { $isLinkNode, HOVER_LINK_COMMAND, HOVER_OUT_LINK_COMMAND, TOGGLE_LINK_COMMAND } from "../../node/LinkNode";
|
|
19
18
|
import { useStyles } from "../style";
|
|
20
19
|
import { EDIT_LINK_COMMAND } from "./LinkEdit";
|
|
21
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
21
|
var LinkToolbar = /*#__PURE__*/memo(function (_ref) {
|
|
23
|
-
var
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
rest = _objectWithoutProperties(_ref, _excluded);
|
|
22
|
+
var editor = _ref.editor;
|
|
23
|
+
var divRef = useRef(null);
|
|
24
|
+
var LinkRef = useRef(null);
|
|
27
25
|
var _useStyles = useStyles(),
|
|
28
26
|
styles = _useStyles.styles;
|
|
27
|
+
var _useState = useState(null),
|
|
28
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
29
|
+
linkNode = _useState2[0],
|
|
30
|
+
setLinkNode = _useState2[1];
|
|
31
|
+
var state = useRef({
|
|
32
|
+
isLink: false
|
|
33
|
+
});
|
|
29
34
|
var t = useTranslation();
|
|
35
|
+
var clearTimerRef = useRef(-1);
|
|
30
36
|
var handleEdit = useCallback(function () {
|
|
31
37
|
if (!linkNode) return;
|
|
32
38
|
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
@@ -34,6 +40,10 @@ var LinkToolbar = /*#__PURE__*/memo(function (_ref) {
|
|
|
34
40
|
linkNodeDOM: editor.getElementByKey(linkNode.getKey())
|
|
35
41
|
});
|
|
36
42
|
}, [editor, linkNode]);
|
|
43
|
+
var handleCancel = useCallback(function () {
|
|
44
|
+
clearTimeout(clearTimerRef.current);
|
|
45
|
+
cleanPosition(divRef.current);
|
|
46
|
+
}, []);
|
|
37
47
|
var handleRemove = useCallback(function () {
|
|
38
48
|
if (!linkNode) return;
|
|
39
49
|
editor.update(function () {
|
|
@@ -79,7 +89,56 @@ var LinkToolbar = /*#__PURE__*/memo(function (_ref) {
|
|
|
79
89
|
});
|
|
80
90
|
window.open(url, '_blank');
|
|
81
91
|
}, [editor, linkNode]);
|
|
82
|
-
|
|
92
|
+
useLexicalEditor(function (editor) {
|
|
93
|
+
return mergeRegister(editor.registerUpdateListener(function () {
|
|
94
|
+
var selection = editor.read(function () {
|
|
95
|
+
return $getSelection();
|
|
96
|
+
});
|
|
97
|
+
if (!selection) return;
|
|
98
|
+
if ($isRangeSelection(selection)) {
|
|
99
|
+
// Update links for UI components
|
|
100
|
+
editor.read(function () {
|
|
101
|
+
var node = getSelectedNode(selection);
|
|
102
|
+
var parent = node.getParent();
|
|
103
|
+
var isLink = $isLinkNode(parent) || $isLinkNode(node);
|
|
104
|
+
state.current.isLink = isLink;
|
|
105
|
+
if (isLink) {
|
|
106
|
+
var _linkNode = $isLinkNode(parent) ? parent : node;
|
|
107
|
+
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
108
|
+
linkNode: _linkNode,
|
|
109
|
+
linkNodeDOM: editor.getElementByKey(_linkNode.getKey())
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
editor.dispatchCommand(EDIT_LINK_COMMAND, {
|
|
113
|
+
linkNode: null,
|
|
114
|
+
linkNodeDOM: null
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
state.current.isLink = false;
|
|
120
|
+
}
|
|
121
|
+
}), editor.registerCommand(HOVER_LINK_COMMAND, function (payload) {
|
|
122
|
+
if (!payload.event.target || divRef.current === null) return false;
|
|
123
|
+
// Cancel any pending hide timers when hovering a link again
|
|
124
|
+
clearTimeout(clearTimerRef.current);
|
|
125
|
+
setLinkNode(payload.linkNode);
|
|
126
|
+
updatePosition({
|
|
127
|
+
callback: function callback() {
|
|
128
|
+
LinkRef.current = payload.event.target;
|
|
129
|
+
},
|
|
130
|
+
floating: divRef.current,
|
|
131
|
+
offset: 4,
|
|
132
|
+
placement: 'top-start',
|
|
133
|
+
reference: payload.event.target
|
|
134
|
+
});
|
|
135
|
+
return false;
|
|
136
|
+
}, COMMAND_PRIORITY_NORMAL), editor.registerCommand(HOVER_OUT_LINK_COMMAND, function () {
|
|
137
|
+
clearTimerRef.current = setTimeout(handleCancel, 300);
|
|
138
|
+
return true;
|
|
139
|
+
}, COMMAND_PRIORITY_NORMAL));
|
|
140
|
+
}, []);
|
|
141
|
+
return /*#__PURE__*/_jsx(ActionIconGroup, {
|
|
83
142
|
className: styles.linkToolbar,
|
|
84
143
|
items: [{
|
|
85
144
|
icon: EditIcon,
|
|
@@ -95,18 +154,25 @@ var LinkToolbar = /*#__PURE__*/memo(function (_ref) {
|
|
|
95
154
|
icon: UnlinkIcon,
|
|
96
155
|
key: 'unlink',
|
|
97
156
|
label: t('link.unlink'),
|
|
98
|
-
onClick: function onClick(
|
|
157
|
+
onClick: function onClick() {
|
|
99
158
|
handleRemove();
|
|
100
|
-
|
|
159
|
+
handleCancel();
|
|
101
160
|
}
|
|
102
161
|
}],
|
|
103
|
-
|
|
162
|
+
onMouseEnter: function onMouseEnter() {
|
|
163
|
+
clearTimeout(clearTimerRef.current);
|
|
164
|
+
},
|
|
165
|
+
onMouseLeave: function onMouseLeave() {
|
|
166
|
+
handleCancel();
|
|
167
|
+
},
|
|
168
|
+
ref: divRef,
|
|
104
169
|
shadow: true,
|
|
105
170
|
size: {
|
|
106
171
|
blockSize: 32,
|
|
107
172
|
size: 16
|
|
108
173
|
},
|
|
109
174
|
variant: 'outlined'
|
|
110
|
-
}
|
|
175
|
+
});
|
|
111
176
|
});
|
|
177
|
+
LinkToolbar.displayName = 'LinkToolbar';
|
|
112
178
|
export default LinkToolbar;
|
|
@@ -5,7 +5,7 @@ export var useStyles = createStyles(function (_ref) {
|
|
|
5
5
|
var cx = _ref.cx,
|
|
6
6
|
css = _ref.css,
|
|
7
7
|
token = _ref.token;
|
|
8
|
-
var position = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: absolute;\n z-index: 999;\n
|
|
8
|
+
var position = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: absolute;\n z-index: 999;\n "])));
|
|
9
9
|
return {
|
|
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
11
|
linkEdit: cx(position, css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n min-width: 320px;\n max-width: 100%;\n background: ", ";\n "])), token.colorBgElevated)),
|