@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.
@@ -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: 0.5,
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.5,
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.5,
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(Divider, {
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.5,
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
- })), !isSimpleMode && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ToolbarItem, {
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.5,
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.5,
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, { useState } from '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(React.Fragment, null, /*#__PURE__*/React.createElement(BubbleMenu, {
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(event) {
143
- return setTooltipAnchorEl(event.currentTarget);
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
- })))), /*#__PURE__*/React.createElement(TooltipInputPopover, {
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: -6,
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'
@@ -61,7 +61,7 @@ var ToolbarItem = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
61
61
  }, rest), /*#__PURE__*/React.createElement(Stack, {
62
62
  direction: 'row',
63
63
  alignItems: 'center',
64
- gap: 1,
64
+ gap: 0.5,
65
65
  sx: {
66
66
  lineHeight: 1,
67
67
  flexShrink: 0
@@ -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: 'flex-start',
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: 'flex-start',
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
- import { Box, Tooltip } from "@mui/material";
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
- return /*#__PURE__*/React.createElement(Tooltip, {
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(Box, null, tooltip)
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(tooltip) {
48
+ toggleTooltip: function toggleTooltip() {
53
49
  return function (_ref3) {
54
50
  var commands = _ref3.commands;
55
51
  return commands.toggleMark(_this.name, {
56
- tooltip: 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 = /^\{([^}]+)\}\(([^)]+)\)/.exec(src);
99
+ var match = /^<span\s+([^>]*?)>([\s\S]+?)<\/span>/.exec(src);
105
100
  if (!match) {
106
101
  return;
107
102
  }
108
- var text = match[1];
109
- var tooltip = match[2];
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 "{".concat(content, "}(").concat(tooltip, ")");
138
+ return "<span data-tooltip=\"".concat(tooltip, "\">").concat(content, "</span>");
139
139
  }
140
140
  });
141
141
  export default Tooltip;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctzhian/tiptap",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "基于 Tiptap 二次开发的编辑器组件",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -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;