@ctzhian/tiptap 2.9.0 → 2.9.2
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/EditorToolbar/index.js +33 -16
- package/dist/component/CustomBubbleMenu/index.js +10 -29
- package/dist/component/FloatingPopover/index.js +2 -1
- package/dist/component/Toolbar/EditorHeading.js +1 -1
- package/dist/component/Toolbar/EditorMore/index.js +1 -4
- package/dist/component/Toolbar/Item.js +1 -1
- package/dist/extension/component/Link/Insert.js +2 -2
- package/dist/extension/component/Tooltip/EditPopover.d.ts +11 -0
- package/dist/extension/component/Tooltip/EditPopover.js +171 -0
- package/dist/extension/component/Tooltip/index.js +55 -6
- package/dist/extension/mark/Tooltip.js +13 -13
- package/package.json +1 -1
- package/dist/component/CustomBubbleMenu/TooltipInputPopover.d.ts +0 -11
- package/dist/component/CustomBubbleMenu/TooltipInputPopover.js +0 -80
|
@@ -13,7 +13,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
13
13
|
import { Box, Divider, Stack } from '@mui/material';
|
|
14
14
|
import { useEditorState } from '@tiptap/react';
|
|
15
15
|
import React from 'react';
|
|
16
|
-
import { AiGenerate2Icon, ArrowGoBackLineIcon, ArrowGoForwardLineIcon, BoldIcon, CodeBoxLineIcon, CollapseHorizontalLine, EraserLineIcon, ExpandHorizontalLineIcon, ItalicIcon, LinkIcon, MarkPenLineIcon, StrikethroughIcon, SubscriptIcon, SuperscriptIcon, UnderlineIcon } from "../component/Icons";
|
|
16
|
+
import { AiGenerate2Icon, ArrowGoBackLineIcon, ArrowGoForwardLineIcon, BoldIcon, CodeBoxLineIcon, CollapseHorizontalLine, EraserLineIcon, ExpandHorizontalLineIcon, ItalicIcon, LinkIcon, MarkPenLineIcon, StrikethroughIcon, SubscriptIcon, SuperscriptIcon, TooltipLineIcon, UnderlineIcon } from "../component/Icons";
|
|
17
17
|
import { EditorAlignSelect, EditorFontBgColor, EditorFontColor, EditorFontSize, EditorHeading, EditorInsert, EditorListSelect, EditorMore, EditorVerticalAlignSelect, ToolbarItem } from "../component/Toolbar";
|
|
18
18
|
import { getLinkAttributesWithSelectedText, hasMarksInSelection } from "../util";
|
|
19
19
|
var EditorToolbar = function EditorToolbar(_ref) {
|
|
@@ -55,7 +55,8 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
55
55
|
isLink: ctx.editor.isActive('link'),
|
|
56
56
|
isHighlight: ctx.editor.isActive('highlight'),
|
|
57
57
|
isAiWriting: !!((_ctx$editor$storage = ctx.editor.storage) !== null && _ctx$editor$storage !== void 0 && (_ctx$editor$storage = _ctx$editor$storage.aiWriting) !== null && _ctx$editor$storage !== void 0 && _ctx$editor$storage.enabled),
|
|
58
|
-
isCodeBlock: ctx.editor.isActive('codeBlock')
|
|
58
|
+
isCodeBlock: ctx.editor.isActive('codeBlock'),
|
|
59
|
+
isTooltip: ctx.editor.isActive('tooltip')
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
}),
|
|
@@ -71,7 +72,8 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
71
72
|
isLink = _useEditorState.isLink,
|
|
72
73
|
isAiWriting = _useEditorState.isAiWriting,
|
|
73
74
|
isHighlight = _useEditorState.isHighlight,
|
|
74
|
-
isCodeBlock = _useEditorState.isCodeBlock
|
|
75
|
+
isCodeBlock = _useEditorState.isCodeBlock,
|
|
76
|
+
isTooltip = _useEditorState.isTooltip;
|
|
75
77
|
return /*#__PURE__*/React.createElement(Box, {
|
|
76
78
|
className: "editor-toolbar"
|
|
77
79
|
}, /*#__PURE__*/React.createElement(Stack, {
|
|
@@ -82,7 +84,7 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
82
84
|
sx: {
|
|
83
85
|
minHeight: '44px',
|
|
84
86
|
overflowX: isSimpleMode ? 'auto' : 'visible',
|
|
85
|
-
columnGap:
|
|
87
|
+
columnGap: '1px',
|
|
86
88
|
'.MuiSelect-root': {
|
|
87
89
|
minWidth: '36px',
|
|
88
90
|
bgcolor: 'background.paper',
|
|
@@ -127,7 +129,7 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
127
129
|
orientation: "vertical",
|
|
128
130
|
flexItem: true,
|
|
129
131
|
sx: {
|
|
130
|
-
mx: 0.
|
|
132
|
+
mx: 0.25,
|
|
131
133
|
height: 20,
|
|
132
134
|
alignSelf: 'center'
|
|
133
135
|
}
|
|
@@ -170,19 +172,23 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
170
172
|
orientation: "vertical",
|
|
171
173
|
flexItem: true,
|
|
172
174
|
sx: {
|
|
173
|
-
mx: 0.
|
|
175
|
+
mx: 0.25,
|
|
174
176
|
height: 20,
|
|
175
177
|
alignSelf: 'center'
|
|
176
178
|
}
|
|
177
179
|
}), /*#__PURE__*/React.createElement(EditorHeading, {
|
|
178
180
|
editor: editor
|
|
179
|
-
}), !isSimpleMode && /*#__PURE__*/React.createElement(EditorFontSize, {
|
|
181
|
+
}), !isSimpleMode && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EditorFontSize, {
|
|
180
182
|
editor: editor
|
|
181
|
-
}), /*#__PURE__*/React.createElement(
|
|
183
|
+
}), /*#__PURE__*/React.createElement(EditorFontColor, {
|
|
184
|
+
editor: editor
|
|
185
|
+
}), /*#__PURE__*/React.createElement(EditorFontBgColor, {
|
|
186
|
+
editor: editor
|
|
187
|
+
})), /*#__PURE__*/React.createElement(Divider, {
|
|
182
188
|
orientation: "vertical",
|
|
183
189
|
flexItem: true,
|
|
184
190
|
sx: {
|
|
185
|
-
mx: 0.
|
|
191
|
+
mx: 0.25,
|
|
186
192
|
height: 20,
|
|
187
193
|
alignSelf: 'center'
|
|
188
194
|
}
|
|
@@ -234,7 +240,7 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
234
240
|
return editor.chain().focus().toggleUnderline().run();
|
|
235
241
|
},
|
|
236
242
|
className: isUnderline ? 'tool-active' : ''
|
|
237
|
-
})
|
|
243
|
+
}), /*#__PURE__*/React.createElement(ToolbarItem, {
|
|
238
244
|
tip: '高亮',
|
|
239
245
|
shortcutKey: ['ctrl', 'shift', 'H'],
|
|
240
246
|
icon: /*#__PURE__*/React.createElement(MarkPenLineIcon, {
|
|
@@ -246,6 +252,21 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
246
252
|
return editor.chain().focus().toggleHighlight().run();
|
|
247
253
|
},
|
|
248
254
|
className: isHighlight ? 'tool-active' : ''
|
|
255
|
+
}), /*#__PURE__*/React.createElement(ToolbarItem, {
|
|
256
|
+
tip: '文本提示',
|
|
257
|
+
icon: /*#__PURE__*/React.createElement(TooltipLineIcon, {
|
|
258
|
+
sx: {
|
|
259
|
+
fontSize: '1rem'
|
|
260
|
+
}
|
|
261
|
+
}),
|
|
262
|
+
onClick: function onClick() {
|
|
263
|
+
if (isTooltip) {
|
|
264
|
+
editor.chain().focus().unsetTooltip().run();
|
|
265
|
+
} else {
|
|
266
|
+
editor.chain().focus().toggleTooltip().run();
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
className: isTooltip ? 'tool-active' : ''
|
|
249
270
|
}), /*#__PURE__*/React.createElement(ToolbarItem, {
|
|
250
271
|
tip: '上标',
|
|
251
272
|
shortcutKey: ['ctrl', '.'],
|
|
@@ -270,15 +291,11 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
270
291
|
return editor.chain().focus().toggleSubscript().run();
|
|
271
292
|
},
|
|
272
293
|
className: isSubscript ? 'tool-active' : ''
|
|
273
|
-
}), /*#__PURE__*/React.createElement(EditorFontColor, {
|
|
274
|
-
editor: editor
|
|
275
|
-
}), /*#__PURE__*/React.createElement(EditorFontBgColor, {
|
|
276
|
-
editor: editor
|
|
277
294
|
}), /*#__PURE__*/React.createElement(Divider, {
|
|
278
295
|
orientation: "vertical",
|
|
279
296
|
flexItem: true,
|
|
280
297
|
sx: {
|
|
281
|
-
mx: 0.
|
|
298
|
+
mx: 0.25,
|
|
282
299
|
height: 20,
|
|
283
300
|
alignSelf: 'center'
|
|
284
301
|
}
|
|
@@ -319,7 +336,7 @@ var EditorToolbar = function EditorToolbar(_ref) {
|
|
|
319
336
|
orientation: "vertical",
|
|
320
337
|
flexItem: true,
|
|
321
338
|
sx: {
|
|
322
|
-
mx: 0.
|
|
339
|
+
mx: 0.25,
|
|
323
340
|
height: 20,
|
|
324
341
|
alignSelf: 'center'
|
|
325
342
|
}
|
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
-
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."); }
|
|
3
|
-
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); }
|
|
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
|
-
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
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
1
|
import { BoldIcon, CodeLineIcon, EraserLineIcon, ItalicIcon, MarkPenLineIcon, StrikethroughIcon, TooltipLineIcon, UnderlineIcon } from "../Icons";
|
|
8
2
|
import { hasMarksInSelection } from "../../util";
|
|
9
3
|
import { Divider, Paper, Stack } from '@mui/material';
|
|
10
4
|
import { useEditorState } from '@tiptap/react';
|
|
11
5
|
import { BubbleMenu } from '@tiptap/react/menus';
|
|
12
|
-
import React
|
|
6
|
+
import React from 'react';
|
|
13
7
|
import { ToolbarItem } from "../Toolbar";
|
|
14
|
-
import TooltipInputPopover from "./TooltipInputPopover";
|
|
15
8
|
var CustomBubbleMenu = function CustomBubbleMenu(_ref) {
|
|
16
9
|
var editor = _ref.editor,
|
|
17
10
|
more = _ref.more;
|
|
18
|
-
var _useState = useState(null),
|
|
19
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
20
|
-
tooltipAnchorEl = _useState2[0],
|
|
21
|
-
setTooltipAnchorEl = _useState2[1];
|
|
22
11
|
var _useEditorState = useEditorState({
|
|
23
12
|
editor: editor,
|
|
24
13
|
selector: function selector(ctx) {
|
|
25
|
-
var _ctx$editor$getAttrib;
|
|
26
14
|
return {
|
|
27
15
|
isBold: ctx.editor.isActive('bold'),
|
|
28
16
|
isItalic: ctx.editor.isActive('italic'),
|
|
@@ -31,7 +19,6 @@ var CustomBubbleMenu = function CustomBubbleMenu(_ref) {
|
|
|
31
19
|
isCode: ctx.editor.isActive('code'),
|
|
32
20
|
isHighlight: ctx.editor.isActive('highlight'),
|
|
33
21
|
isTooltip: ctx.editor.isActive('tooltip'),
|
|
34
|
-
currentTooltip: ((_ctx$editor$getAttrib = ctx.editor.getAttributes('tooltip')) === null || _ctx$editor$getAttrib === void 0 ? void 0 : _ctx$editor$getAttrib.tooltip) || '',
|
|
35
22
|
hasAnyMarks: hasMarksInSelection(ctx.editor.state)
|
|
36
23
|
};
|
|
37
24
|
}
|
|
@@ -43,12 +30,11 @@ var CustomBubbleMenu = function CustomBubbleMenu(_ref) {
|
|
|
43
30
|
isCode = _useEditorState.isCode,
|
|
44
31
|
isHighlight = _useEditorState.isHighlight,
|
|
45
32
|
isTooltip = _useEditorState.isTooltip,
|
|
46
|
-
currentTooltip = _useEditorState.currentTooltip,
|
|
47
33
|
hasAnyMarks = _useEditorState.hasAnyMarks;
|
|
48
34
|
if (editor && !editor.isEditable) {
|
|
49
35
|
return null;
|
|
50
36
|
}
|
|
51
|
-
return /*#__PURE__*/React.createElement(
|
|
37
|
+
return /*#__PURE__*/React.createElement(BubbleMenu, {
|
|
52
38
|
editor: editor,
|
|
53
39
|
pluginKey: 'bubble-menu',
|
|
54
40
|
updateDelay: 750,
|
|
@@ -139,11 +125,14 @@ var CustomBubbleMenu = function CustomBubbleMenu(_ref) {
|
|
|
139
125
|
fontSize: '1rem'
|
|
140
126
|
}
|
|
141
127
|
}),
|
|
142
|
-
onClick: function onClick(
|
|
143
|
-
|
|
128
|
+
onClick: function onClick() {
|
|
129
|
+
if (isTooltip) {
|
|
130
|
+
editor.chain().focus().unsetTooltip().run();
|
|
131
|
+
} else {
|
|
132
|
+
editor.chain().focus().toggleTooltip().run();
|
|
133
|
+
}
|
|
144
134
|
},
|
|
145
|
-
className: isTooltip ? "tool-active" : ""
|
|
146
|
-
tip: "\u6DFB\u52A0\u63D0\u793A\u6587\u672C"
|
|
135
|
+
className: isTooltip ? "tool-active" : ""
|
|
147
136
|
}), /*#__PURE__*/React.createElement(Divider, {
|
|
148
137
|
orientation: "vertical",
|
|
149
138
|
flexItem: true,
|
|
@@ -170,14 +159,6 @@ var CustomBubbleMenu = function CustomBubbleMenu(_ref) {
|
|
|
170
159
|
icon: item.icon || /*#__PURE__*/React.createElement(React.Fragment, null),
|
|
171
160
|
onClick: item.onClick
|
|
172
161
|
});
|
|
173
|
-
}))))
|
|
174
|
-
open: Boolean(tooltipAnchorEl),
|
|
175
|
-
anchorEl: tooltipAnchorEl,
|
|
176
|
-
onClose: function onClose() {
|
|
177
|
-
return setTooltipAnchorEl(null);
|
|
178
|
-
},
|
|
179
|
-
editor: editor,
|
|
180
|
-
currentTooltip: currentTooltip
|
|
181
|
-
}));
|
|
162
|
+
}))));
|
|
182
163
|
};
|
|
183
164
|
export default CustomBubbleMenu;
|
|
@@ -111,7 +111,8 @@ export var FloatingPopover = function FloatingPopover(_ref) {
|
|
|
111
111
|
top: position.y,
|
|
112
112
|
zIndex: 1300,
|
|
113
113
|
boxShadow: 'var(--mui-shadows-1)',
|
|
114
|
-
borderRadius: 'var(--mui-shape-borderRadius)'
|
|
114
|
+
borderRadius: 'var(--mui-shape-borderRadius)',
|
|
115
|
+
opacity: position.x === 0 && position.y === 0 ? 0 : 1
|
|
115
116
|
}, style),
|
|
116
117
|
elevation: 8
|
|
117
118
|
}, children)), document.body);
|
|
@@ -125,7 +125,7 @@ var EditorHeading = function EditorHeading(_ref) {
|
|
|
125
125
|
})[0].label), /*#__PURE__*/React.createElement(ArrowDownSLineIcon, {
|
|
126
126
|
sx: {
|
|
127
127
|
position: 'absolute',
|
|
128
|
-
right: -
|
|
128
|
+
right: -2,
|
|
129
129
|
top: '50%',
|
|
130
130
|
transform: 'translateY(-50%)',
|
|
131
131
|
flexSelf: 'center',
|
|
@@ -60,10 +60,7 @@ var EditorMore = function EditorMore(_ref) {
|
|
|
60
60
|
icon: /*#__PURE__*/React.createElement(Stack, {
|
|
61
61
|
direction: 'row',
|
|
62
62
|
alignItems: 'center',
|
|
63
|
-
justifyContent: "center"
|
|
64
|
-
sx: {
|
|
65
|
-
mr: 0.5
|
|
66
|
-
}
|
|
63
|
+
justifyContent: "center"
|
|
67
64
|
}, /*#__PURE__*/React.createElement(MoreLineIcon, {
|
|
68
65
|
sx: {
|
|
69
66
|
fontSize: '1rem'
|
|
@@ -162,7 +162,7 @@ var InsertLink = function InsertLink(_ref) {
|
|
|
162
162
|
}, /*#__PURE__*/React.createElement(Stack, {
|
|
163
163
|
direction: 'row',
|
|
164
164
|
gap: 2,
|
|
165
|
-
alignItems: '
|
|
165
|
+
alignItems: 'center',
|
|
166
166
|
sx: {
|
|
167
167
|
'.MuiFormControlLabel-label': {
|
|
168
168
|
fontSize: '0.875rem'
|
|
@@ -203,7 +203,7 @@ var InsertLink = function InsertLink(_ref) {
|
|
|
203
203
|
}, /*#__PURE__*/React.createElement(Stack, {
|
|
204
204
|
direction: 'row',
|
|
205
205
|
gap: 2,
|
|
206
|
-
alignItems: '
|
|
206
|
+
alignItems: 'center',
|
|
207
207
|
sx: {
|
|
208
208
|
'.MuiFormControlLabel-label': {
|
|
209
209
|
fontSize: '0.875rem'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
interface EditPopoverProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
editor: Editor;
|
|
6
|
+
text: string;
|
|
7
|
+
anchorEl: HTMLElement | null;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
declare const EditPopover: ({ open, editor, text, anchorEl, onClose, }: EditPopoverProps) => React.JSX.Element | null;
|
|
11
|
+
export default EditPopover;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
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."); }
|
|
3
|
+
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); }
|
|
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
|
+
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
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
import { FloatingPopover } from "../../../component";
|
|
8
|
+
import { Button, Stack, TextField } from "@mui/material";
|
|
9
|
+
import { TextSelection } from "@tiptap/pm/state";
|
|
10
|
+
import React, { useEffect, useState } from "react";
|
|
11
|
+
var EditPopover = function EditPopover(_ref) {
|
|
12
|
+
var open = _ref.open,
|
|
13
|
+
editor = _ref.editor,
|
|
14
|
+
text = _ref.text,
|
|
15
|
+
anchorEl = _ref.anchorEl,
|
|
16
|
+
onClose = _ref.onClose;
|
|
17
|
+
var isEditable = editor.isEditable;
|
|
18
|
+
var _useState = useState(text || ''),
|
|
19
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
20
|
+
tooltipText = _useState2[0],
|
|
21
|
+
setTooltipText = _useState2[1];
|
|
22
|
+
var onConfirm = function onConfirm(tooltipText) {
|
|
23
|
+
if (!anchorEl) {
|
|
24
|
+
onClose();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 通过 DOM 元素找到文档位置
|
|
29
|
+
var view = editor.view;
|
|
30
|
+
var domPos = view.posAtDOM(anchorEl, 0);
|
|
31
|
+
if (domPos === null || domPos === undefined) {
|
|
32
|
+
onClose();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 找到包含该 mark 的完整范围
|
|
37
|
+
var state = editor.state;
|
|
38
|
+
var doc = state.doc;
|
|
39
|
+
var tooltipMarkType = editor.schema.marks.tooltip;
|
|
40
|
+
if (!tooltipMarkType) {
|
|
41
|
+
onClose();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 遍历文档找到所有包含该 mark 的文本节点,并确定连续范围
|
|
46
|
+
var markFrom = null;
|
|
47
|
+
var markTo = null;
|
|
48
|
+
doc.nodesBetween(0, doc.content.size, function (node, pos) {
|
|
49
|
+
if (node.isText && node.marks.some(function (m) {
|
|
50
|
+
return m.type === tooltipMarkType && m.attrs.tooltip === text;
|
|
51
|
+
})) {
|
|
52
|
+
// 检查是否在 domPos 附近(包含 domPos 的节点)
|
|
53
|
+
if (pos <= domPos && domPos < pos + node.nodeSize) {
|
|
54
|
+
if (markFrom === null) {
|
|
55
|
+
markFrom = pos;
|
|
56
|
+
}
|
|
57
|
+
markTo = pos + node.nodeSize;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// 如果找到了包含 domPos 的节点,扩展范围以包含所有连续的相同 mark
|
|
63
|
+
if (markFrom !== null && markTo !== null) {
|
|
64
|
+
// 向前扩展
|
|
65
|
+
while (markFrom > 0) {
|
|
66
|
+
var $pos = doc.resolve(markFrom - 1);
|
|
67
|
+
var node = $pos.nodeAfter;
|
|
68
|
+
if (node && node.isText && node.marks.some(function (m) {
|
|
69
|
+
return m.type === tooltipMarkType && m.attrs.tooltip === text;
|
|
70
|
+
})) {
|
|
71
|
+
markFrom = markFrom - 1;
|
|
72
|
+
} else {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// 向后扩展
|
|
77
|
+
while (markTo < doc.content.size) {
|
|
78
|
+
var _$pos = doc.resolve(markTo);
|
|
79
|
+
var _node = _$pos.nodeAfter;
|
|
80
|
+
if (_node && _node.isText && _node.marks.some(function (m) {
|
|
81
|
+
return m.type === tooltipMarkType && m.attrs.tooltip === text;
|
|
82
|
+
})) {
|
|
83
|
+
markTo = markTo + _node.nodeSize;
|
|
84
|
+
} else {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (markFrom !== null && markTo !== null && markFrom < markTo) {
|
|
90
|
+
// 选中该范围并应用 tooltip
|
|
91
|
+
var tr = state.tr;
|
|
92
|
+
var selection = TextSelection.create(tr.doc, markFrom, markTo);
|
|
93
|
+
tr.setSelection(selection);
|
|
94
|
+
if (tooltipText) {
|
|
95
|
+
tr.addMark(markFrom, markTo, tooltipMarkType.create({
|
|
96
|
+
tooltip: tooltipText
|
|
97
|
+
}));
|
|
98
|
+
} else {
|
|
99
|
+
tr.removeMark(markFrom, markTo, tooltipMarkType);
|
|
100
|
+
}
|
|
101
|
+
view.dispatch(tr);
|
|
102
|
+
editor.commands.focus();
|
|
103
|
+
} else {
|
|
104
|
+
// 如果找不到范围,使用原来的方法
|
|
105
|
+
if (tooltipText) {
|
|
106
|
+
editor.chain().focus().setTooltip(tooltipText).run();
|
|
107
|
+
} else {
|
|
108
|
+
editor.chain().focus().unsetTooltip().run();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
onClose();
|
|
112
|
+
};
|
|
113
|
+
var handleKeyDown = function handleKeyDown(event) {
|
|
114
|
+
if (event.key === 'Enter') {
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
onConfirm(tooltipText.trim());
|
|
117
|
+
} else if (event.key === 'Escape') {
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
setTooltipText(text || '');
|
|
120
|
+
onClose();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
useEffect(function () {
|
|
124
|
+
if (isEditable) setTooltipText(text || '');
|
|
125
|
+
}, [text]);
|
|
126
|
+
if (!isEditable) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return /*#__PURE__*/React.createElement(FloatingPopover, {
|
|
130
|
+
open: open,
|
|
131
|
+
anchorEl: anchorEl,
|
|
132
|
+
onClose: onClose,
|
|
133
|
+
placement: "bottom"
|
|
134
|
+
}, /*#__PURE__*/React.createElement(Stack, {
|
|
135
|
+
gap: 2,
|
|
136
|
+
sx: {
|
|
137
|
+
p: 2,
|
|
138
|
+
width: 350
|
|
139
|
+
}
|
|
140
|
+
}, /*#__PURE__*/React.createElement(TextField, {
|
|
141
|
+
fullWidth: true,
|
|
142
|
+
size: "small",
|
|
143
|
+
value: tooltipText,
|
|
144
|
+
onChange: function onChange(e) {
|
|
145
|
+
return setTooltipText(e.target.value);
|
|
146
|
+
},
|
|
147
|
+
placeholder: "\u8F93\u5165\u9F20\u6807\u60AC\u505C\u65F6\u663E\u793A\u7684\u63D0\u793A\u6587\u672C",
|
|
148
|
+
required: true,
|
|
149
|
+
autoFocus: true,
|
|
150
|
+
onKeyDown: handleKeyDown,
|
|
151
|
+
error: tooltipText.length > 0 && !tooltipText.trim(),
|
|
152
|
+
helperText: tooltipText.length > 0 && !tooltipText.trim() ? "请输入有效的提示文本" : ""
|
|
153
|
+
}), /*#__PURE__*/React.createElement(Stack, {
|
|
154
|
+
direction: 'row',
|
|
155
|
+
gap: 1
|
|
156
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
157
|
+
size: "small",
|
|
158
|
+
variant: "outlined",
|
|
159
|
+
fullWidth: true,
|
|
160
|
+
onClick: onClose
|
|
161
|
+
}, "\u53D6\u6D88"), /*#__PURE__*/React.createElement(Button, {
|
|
162
|
+
size: "small",
|
|
163
|
+
variant: "contained",
|
|
164
|
+
fullWidth: true,
|
|
165
|
+
onClick: function onClick() {
|
|
166
|
+
return onConfirm(tooltipText.trim());
|
|
167
|
+
},
|
|
168
|
+
disabled: !tooltipText.trim() && !text
|
|
169
|
+
}, tooltipText.trim() ? '应用' : '移除'))));
|
|
170
|
+
};
|
|
171
|
+
export default EditPopover;
|
|
@@ -1,19 +1,68 @@
|
|
|
1
|
-
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
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."); }
|
|
3
|
+
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); }
|
|
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
|
+
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
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
+
import { EditLineIcon } from "../../../component/Icons";
|
|
8
|
+
import { Box, Stack, Tooltip } from "@mui/material";
|
|
2
9
|
import { MarkViewContent } from "@tiptap/react";
|
|
3
|
-
import React from "react";
|
|
10
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
11
|
+
import EditPopover from "./EditPopover";
|
|
4
12
|
var TooltipView = function TooltipView(_ref) {
|
|
5
|
-
var mark = _ref.mark
|
|
13
|
+
var mark = _ref.mark,
|
|
14
|
+
editor = _ref.editor;
|
|
6
15
|
var tooltip = mark.attrs.tooltip;
|
|
7
|
-
|
|
16
|
+
var isEditable = editor.isEditable;
|
|
17
|
+
var _useState = useState(false),
|
|
18
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
19
|
+
open = _useState2[0],
|
|
20
|
+
setOpen = _useState2[1];
|
|
21
|
+
var anchorRef = useRef(null);
|
|
22
|
+
var handleEditClick = function handleEditClick(e) {
|
|
23
|
+
e.stopPropagation();
|
|
24
|
+
setOpen(true);
|
|
25
|
+
};
|
|
26
|
+
var handleClose = function handleClose() {
|
|
27
|
+
return setOpen(false);
|
|
28
|
+
};
|
|
29
|
+
useEffect(function () {
|
|
30
|
+
var isSelectionEmpty = editor.state.selection.empty;
|
|
31
|
+
if (isEditable && tooltip === '' && !isSelectionEmpty && anchorRef.current) {
|
|
32
|
+
setOpen(true);
|
|
33
|
+
}
|
|
34
|
+
}, [tooltip, isEditable, anchorRef.current]);
|
|
35
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Tooltip, {
|
|
36
|
+
key: tooltip || 'empty-tooltip',
|
|
8
37
|
arrow: true,
|
|
9
38
|
placement: "top",
|
|
10
|
-
title: /*#__PURE__*/React.createElement(
|
|
39
|
+
title: /*#__PURE__*/React.createElement(Stack, {
|
|
40
|
+
direction: "row",
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
gap: 0.5,
|
|
43
|
+
maxWidth: 300
|
|
44
|
+
}, /*#__PURE__*/React.createElement(Box, {
|
|
45
|
+
component: "span"
|
|
46
|
+
}, tooltip), isEditable && /*#__PURE__*/React.createElement(EditLineIcon, {
|
|
47
|
+
sx: {
|
|
48
|
+
fontSize: '0.75rem',
|
|
49
|
+
cursor: 'pointer'
|
|
50
|
+
},
|
|
51
|
+
onClick: handleEditClick
|
|
52
|
+
}))
|
|
11
53
|
}, /*#__PURE__*/React.createElement(Box, {
|
|
54
|
+
ref: anchorRef,
|
|
12
55
|
component: "span",
|
|
13
56
|
sx: {
|
|
14
57
|
borderBottom: '1px dotted',
|
|
15
58
|
borderColor: 'text.secondary'
|
|
16
59
|
}
|
|
17
|
-
}, /*#__PURE__*/React.createElement(MarkViewContent, null)))
|
|
60
|
+
}, /*#__PURE__*/React.createElement(MarkViewContent, null))), isEditable && /*#__PURE__*/React.createElement(EditPopover, {
|
|
61
|
+
open: open,
|
|
62
|
+
editor: editor,
|
|
63
|
+
text: tooltip || '',
|
|
64
|
+
anchorEl: anchorRef.current,
|
|
65
|
+
onClose: handleClose
|
|
66
|
+
}));
|
|
18
67
|
};
|
|
19
68
|
export default TooltipView;
|
|
@@ -18,12 +18,8 @@ export var Tooltip = Mark.create({
|
|
|
18
18
|
return element.getAttribute('data-tooltip');
|
|
19
19
|
},
|
|
20
20
|
renderHTML: function renderHTML(attributes) {
|
|
21
|
-
if (!attributes.tooltip) {
|
|
22
|
-
return {};
|
|
23
|
-
}
|
|
24
21
|
return {
|
|
25
|
-
'data-tooltip': attributes.tooltip
|
|
26
|
-
'class': 'tooltip-mark'
|
|
22
|
+
'data-tooltip': attributes.tooltip || ''
|
|
27
23
|
};
|
|
28
24
|
}
|
|
29
25
|
}
|
|
@@ -49,11 +45,11 @@ export var Tooltip = Mark.create({
|
|
|
49
45
|
});
|
|
50
46
|
};
|
|
51
47
|
},
|
|
52
|
-
toggleTooltip: function toggleTooltip(
|
|
48
|
+
toggleTooltip: function toggleTooltip() {
|
|
53
49
|
return function (_ref3) {
|
|
54
50
|
var commands = _ref3.commands;
|
|
55
51
|
return commands.toggleMark(_this.name, {
|
|
56
|
-
tooltip:
|
|
52
|
+
tooltip: ''
|
|
57
53
|
});
|
|
58
54
|
};
|
|
59
55
|
},
|
|
@@ -82,7 +78,6 @@ export var Tooltip = Mark.create({
|
|
|
82
78
|
var _tooltip = mark.attrs.tooltip;
|
|
83
79
|
if (_tooltip) {
|
|
84
80
|
decorations.push(Decoration.inline(pos, pos + node.nodeSize, {
|
|
85
|
-
class: 'tooltip-mark',
|
|
86
81
|
'data-tooltip': _tooltip
|
|
87
82
|
}));
|
|
88
83
|
}
|
|
@@ -98,15 +93,20 @@ export var Tooltip = Mark.create({
|
|
|
98
93
|
name: 'tooltip',
|
|
99
94
|
level: 'inline',
|
|
100
95
|
start: function start(src) {
|
|
101
|
-
return src.indexOf('
|
|
96
|
+
return src.indexOf('<span');
|
|
102
97
|
},
|
|
103
98
|
tokenize: function tokenize(src, _tokens, helpers) {
|
|
104
|
-
var match =
|
|
99
|
+
var match = /^<span\s+([^>]*?)>([\s\S]+?)<\/span>/.exec(src);
|
|
105
100
|
if (!match) {
|
|
106
101
|
return;
|
|
107
102
|
}
|
|
108
|
-
var
|
|
109
|
-
var
|
|
103
|
+
var attrs = match[1] || '';
|
|
104
|
+
var text = match[2] || '';
|
|
105
|
+
var tooltipMatch = /data-tooltip=["']([^"']+)["']/.exec(attrs);
|
|
106
|
+
if (!tooltipMatch) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
var tooltip = tooltipMatch[1];
|
|
110
110
|
return {
|
|
111
111
|
type: 'tooltip',
|
|
112
112
|
raw: match[0],
|
|
@@ -135,7 +135,7 @@ export var Tooltip = Mark.create({
|
|
|
135
135
|
if (!tooltip) {
|
|
136
136
|
return content;
|
|
137
137
|
}
|
|
138
|
-
return "
|
|
138
|
+
return "<span data-tooltip=\"".concat(tooltip, "\">").concat(content, "</span>");
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
export default Tooltip;
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Editor } from "@tiptap/react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
interface TooltipInputPopoverProps {
|
|
4
|
-
open: boolean;
|
|
5
|
-
anchorEl: HTMLElement | null;
|
|
6
|
-
onClose: () => void;
|
|
7
|
-
editor: Editor;
|
|
8
|
-
currentTooltip?: string;
|
|
9
|
-
}
|
|
10
|
-
declare const TooltipInputPopover: React.FC<TooltipInputPopoverProps>;
|
|
11
|
-
export default TooltipInputPopover;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
-
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."); }
|
|
3
|
-
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); }
|
|
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
|
-
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
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
7
|
-
import { FloatingPopover } from "../FloatingPopover";
|
|
8
|
-
import { Box, Button, Stack, TextField } from "@mui/material";
|
|
9
|
-
import React, { useState } from "react";
|
|
10
|
-
var TooltipInputPopover = function TooltipInputPopover(_ref) {
|
|
11
|
-
var open = _ref.open,
|
|
12
|
-
anchorEl = _ref.anchorEl,
|
|
13
|
-
onClose = _ref.onClose,
|
|
14
|
-
editor = _ref.editor,
|
|
15
|
-
_ref$currentTooltip = _ref.currentTooltip,
|
|
16
|
-
currentTooltip = _ref$currentTooltip === void 0 ? '' : _ref$currentTooltip;
|
|
17
|
-
var _useState = useState(currentTooltip),
|
|
18
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
19
|
-
tooltipText = _useState2[0],
|
|
20
|
-
setTooltipText = _useState2[1];
|
|
21
|
-
var handleConfirm = function handleConfirm() {
|
|
22
|
-
if (tooltipText.trim()) {
|
|
23
|
-
editor.chain().focus().setTooltip(tooltipText.trim()).run();
|
|
24
|
-
} else {
|
|
25
|
-
editor.chain().focus().unsetTooltip().run();
|
|
26
|
-
}
|
|
27
|
-
onClose();
|
|
28
|
-
};
|
|
29
|
-
var handleCancel = function handleCancel() {
|
|
30
|
-
setTooltipText(currentTooltip);
|
|
31
|
-
onClose();
|
|
32
|
-
};
|
|
33
|
-
var handleKeyDown = function handleKeyDown(event) {
|
|
34
|
-
if (event.key === 'Enter') {
|
|
35
|
-
event.preventDefault();
|
|
36
|
-
handleConfirm();
|
|
37
|
-
} else if (event.key === 'Escape') {
|
|
38
|
-
event.preventDefault();
|
|
39
|
-
handleCancel();
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
return /*#__PURE__*/React.createElement(FloatingPopover, {
|
|
43
|
-
open: open,
|
|
44
|
-
anchorEl: anchorEl,
|
|
45
|
-
onClose: handleCancel,
|
|
46
|
-
placement: "bottom"
|
|
47
|
-
}, /*#__PURE__*/React.createElement(Stack, {
|
|
48
|
-
gap: 2,
|
|
49
|
-
sx: {
|
|
50
|
-
p: 2,
|
|
51
|
-
width: 350
|
|
52
|
-
}
|
|
53
|
-
}, /*#__PURE__*/React.createElement(TextField, {
|
|
54
|
-
fullWidth: true,
|
|
55
|
-
size: "small",
|
|
56
|
-
value: tooltipText,
|
|
57
|
-
onChange: function onChange(e) {
|
|
58
|
-
return setTooltipText(e.target.value);
|
|
59
|
-
},
|
|
60
|
-
placeholder: "\u8F93\u5165\u9F20\u6807\u60AC\u505C\u65F6\u663E\u793A\u7684\u63D0\u793A\u6587\u672C",
|
|
61
|
-
required: true,
|
|
62
|
-
error: tooltipText.length > 0 && !tooltipText.trim(),
|
|
63
|
-
helperText: tooltipText.length > 0 && !tooltipText.trim() ? "请输入有效的提示文本" : ""
|
|
64
|
-
}), /*#__PURE__*/React.createElement(Box, {
|
|
65
|
-
sx: {
|
|
66
|
-
display: 'flex',
|
|
67
|
-
gap: 1,
|
|
68
|
-
justifyContent: 'flex-end'
|
|
69
|
-
}
|
|
70
|
-
}, /*#__PURE__*/React.createElement(Button, {
|
|
71
|
-
size: "small",
|
|
72
|
-
onClick: handleCancel
|
|
73
|
-
}, "\u53D6\u6D88"), /*#__PURE__*/React.createElement(Button, {
|
|
74
|
-
size: "small",
|
|
75
|
-
variant: "contained",
|
|
76
|
-
onClick: handleConfirm,
|
|
77
|
-
disabled: !tooltipText.trim() && !currentTooltip
|
|
78
|
-
}, tooltipText.trim() ? '应用' : '移除'))));
|
|
79
|
-
};
|
|
80
|
-
export default TooltipInputPopover;
|