@ctzhian/tiptap 1.12.20 → 1.12.23
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/Editor/demo.js +1 -1
- package/dist/EditorMarkdown/Toolbar.d.ts +2 -5
- package/dist/EditorMarkdown/Toolbar.js +62 -251
- package/dist/EditorMarkdown/UploadProgress.d.ts +7 -0
- package/dist/EditorMarkdown/UploadProgress.js +85 -0
- package/dist/EditorMarkdown/demo.js +4 -3
- package/dist/EditorMarkdown/index.d.ts +2 -0
- package/dist/EditorMarkdown/index.js +291 -9
- package/dist/EditorMarkdown/util.d.ts +17 -0
- package/dist/EditorMarkdown/util.js +84 -0
- package/dist/component/CustomBubbleMenu/index.js +8 -27
- package/dist/component/CustomDragHandle/index.js +44 -72
- package/dist/component/Icons/emotion-line-icon.d.ts +6 -0
- package/dist/component/Icons/emotion-line-icon.js +13 -0
- package/dist/component/Icons/index.d.ts +1 -0
- package/dist/component/Icons/index.js +1 -0
- package/dist/component/Menu/NestedList.d.ts +1 -1
- package/dist/component/Menu/index.js +4 -1
- package/dist/component/Toolbar/EditorInsert/index.js +90 -80
- package/dist/contants/slash-commands.js +65 -53
- package/dist/extension/component/Attachment/AttachmentContent.js +5 -9
- package/dist/extension/component/EmojiList/index.d.ts +3 -0
- package/dist/extension/component/EmojiList/index.js +380 -32
- package/dist/extension/suggestion/emoji.js +165 -16
- package/dist/index.css +1 -0
- package/dist/type/index.d.ts +2 -1
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +10 -0
- package/package.json +1 -1
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
|
|
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
|
+
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; }
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
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); }
|
|
7
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
8
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
+
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
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
11
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
12
|
+
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; }
|
|
13
|
+
import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
|
|
2
14
|
import { ReactRenderer } from '@tiptap/react';
|
|
3
15
|
import { EmojiList } from "../component/EmojiList";
|
|
4
16
|
export var emojiSuggestion = {
|
|
@@ -6,40 +18,157 @@ export var emojiSuggestion = {
|
|
|
6
18
|
items: function items(_ref) {
|
|
7
19
|
var editor = _ref.editor,
|
|
8
20
|
query = _ref.query;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
var normalizedQuery = query.toLowerCase().trim();
|
|
22
|
+
if (!normalizedQuery) {
|
|
23
|
+
// 如果没有查询,返回所有 emoji(限制数量以避免性能问题)
|
|
24
|
+
return editor.storage.emoji.emojis.slice(0, 200);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 优化搜索:优先匹配开头,其次匹配包含
|
|
28
|
+
return editor.storage.emoji.emojis.map(function (item) {
|
|
29
|
+
var _item$shortcodes = item.shortcodes,
|
|
30
|
+
shortcodes = _item$shortcodes === void 0 ? [] : _item$shortcodes,
|
|
31
|
+
_item$tags = item.tags,
|
|
32
|
+
tags = _item$tags === void 0 ? [] : _item$tags;
|
|
33
|
+
var score = 0;
|
|
34
|
+
|
|
35
|
+
// 检查 shortcodes 和 tags
|
|
36
|
+
var allMatches = [].concat(_toConsumableArray(shortcodes.map(function (s) {
|
|
37
|
+
return s.toLowerCase();
|
|
38
|
+
})), _toConsumableArray(tags.map(function (t) {
|
|
39
|
+
return t.toLowerCase();
|
|
40
|
+
})));
|
|
41
|
+
|
|
42
|
+
// 计算匹配分数
|
|
43
|
+
var exactStart = allMatches.some(function (m) {
|
|
44
|
+
return m === normalizedQuery;
|
|
16
45
|
});
|
|
17
|
-
|
|
46
|
+
var startsWith = allMatches.some(function (m) {
|
|
47
|
+
return m.startsWith(normalizedQuery);
|
|
48
|
+
});
|
|
49
|
+
var includes = allMatches.some(function (m) {
|
|
50
|
+
return m.includes(normalizedQuery);
|
|
51
|
+
});
|
|
52
|
+
if (exactStart) score = 3;else if (startsWith) score = 2;else if (includes) score = 1;else score = 0;
|
|
53
|
+
return {
|
|
54
|
+
item: item,
|
|
55
|
+
score: score
|
|
56
|
+
};
|
|
57
|
+
}).filter(function (_ref2) {
|
|
58
|
+
var score = _ref2.score;
|
|
59
|
+
return score > 0;
|
|
60
|
+
}).sort(function (a, b) {
|
|
61
|
+
return b.score - a.score;
|
|
62
|
+
}) // 按分数排序
|
|
63
|
+
.map(function (_ref3) {
|
|
64
|
+
var item = _ref3.item;
|
|
65
|
+
return item;
|
|
66
|
+
}).slice(0, 100); // 限制结果数量
|
|
18
67
|
},
|
|
19
68
|
render: function render() {
|
|
20
69
|
var component = null;
|
|
70
|
+
var cleanupAutoUpdate = null;
|
|
71
|
+
var isMouseOver = false;
|
|
72
|
+
var shouldClose = false;
|
|
73
|
+
var currentProps = null;
|
|
74
|
+
var updatePosition = function updatePosition(editor, element, clientRect) {
|
|
75
|
+
if (!clientRect) return;
|
|
76
|
+
var virtualElement = {
|
|
77
|
+
getBoundingClientRect: function getBoundingClientRect() {
|
|
78
|
+
return clientRect;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
computePosition(virtualElement, element, {
|
|
82
|
+
placement: 'bottom-start',
|
|
83
|
+
strategy: 'absolute',
|
|
84
|
+
middleware: [offset(4), flip(), shift({
|
|
85
|
+
padding: 8
|
|
86
|
+
})]
|
|
87
|
+
}).then(function (_ref4) {
|
|
88
|
+
var x = _ref4.x,
|
|
89
|
+
y = _ref4.y;
|
|
90
|
+
element.style.position = 'absolute';
|
|
91
|
+
element.style.left = "".concat(x, "px");
|
|
92
|
+
element.style.top = "".concat(y, "px");
|
|
93
|
+
});
|
|
94
|
+
};
|
|
21
95
|
return {
|
|
22
96
|
onStart: function onStart(props) {
|
|
97
|
+
var _props$clientRect;
|
|
98
|
+
currentProps = props;
|
|
99
|
+
shouldClose = false;
|
|
23
100
|
component = new ReactRenderer(EmojiList, {
|
|
24
|
-
props: props,
|
|
101
|
+
props: _objectSpread(_objectSpread({}, props), {}, {
|
|
102
|
+
query: props.query || '',
|
|
103
|
+
editor: props.editor,
|
|
104
|
+
command: function command(commandProps) {
|
|
105
|
+
// 标记应该关闭,然后调用原始 command
|
|
106
|
+
shouldClose = true;
|
|
107
|
+
props.command(commandProps);
|
|
108
|
+
}
|
|
109
|
+
}),
|
|
25
110
|
editor: props.editor
|
|
26
111
|
});
|
|
27
|
-
|
|
112
|
+
var clientRect = (_props$clientRect = props.clientRect) === null || _props$clientRect === void 0 ? void 0 : _props$clientRect.call(props);
|
|
113
|
+
if (!clientRect) return;
|
|
28
114
|
var element = component.element;
|
|
29
|
-
element.style.position = 'absolute';
|
|
30
115
|
document.body.appendChild(element);
|
|
31
|
-
|
|
116
|
+
|
|
117
|
+
// 添加鼠标事件监听
|
|
118
|
+
var handleMouseEnter = function handleMouseEnter() {
|
|
119
|
+
isMouseOver = true;
|
|
120
|
+
};
|
|
121
|
+
var handleMouseLeave = function handleMouseLeave() {
|
|
122
|
+
isMouseOver = false;
|
|
123
|
+
};
|
|
124
|
+
element.addEventListener('mouseenter', handleMouseEnter);
|
|
125
|
+
element.addEventListener('mouseleave', handleMouseLeave);
|
|
126
|
+
|
|
127
|
+
// 初始定位
|
|
128
|
+
updatePosition(props.editor, element, clientRect);
|
|
129
|
+
|
|
130
|
+
// 设置自动更新位置
|
|
131
|
+
var virtualElement = {
|
|
132
|
+
getBoundingClientRect: function getBoundingClientRect() {
|
|
133
|
+
var _currentProps, _currentProps$clientR;
|
|
134
|
+
var rect = (_currentProps = currentProps) === null || _currentProps === void 0 || (_currentProps$clientR = _currentProps.clientRect) === null || _currentProps$clientR === void 0 ? void 0 : _currentProps$clientR.call(_currentProps);
|
|
135
|
+
return rect || new DOMRect();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
cleanupAutoUpdate = autoUpdate(virtualElement, element, function () {
|
|
139
|
+
var _currentProps2, _currentProps2$client;
|
|
140
|
+
var rect = (_currentProps2 = currentProps) === null || _currentProps2 === void 0 || (_currentProps2$client = _currentProps2.clientRect) === null || _currentProps2$client === void 0 ? void 0 : _currentProps2$client.call(_currentProps2);
|
|
141
|
+
if (rect) {
|
|
142
|
+
updatePosition(props.editor, element, rect);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
32
145
|
},
|
|
33
146
|
onUpdate: function onUpdate(props) {
|
|
147
|
+
var _props$clientRect2;
|
|
148
|
+
currentProps = props;
|
|
34
149
|
if (!component) return;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
150
|
+
shouldClose = false;
|
|
151
|
+
component.updateProps(_objectSpread(_objectSpread({}, props), {}, {
|
|
152
|
+
query: props.query || '',
|
|
153
|
+
editor: props.editor,
|
|
154
|
+
command: function command(commandProps) {
|
|
155
|
+
// 标记应该关闭,然后调用原始 command
|
|
156
|
+
shouldClose = true;
|
|
157
|
+
props.command(commandProps);
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
var clientRect = (_props$clientRect2 = props.clientRect) === null || _props$clientRect2 === void 0 ? void 0 : _props$clientRect2.call(props);
|
|
161
|
+
if (!clientRect) return;
|
|
162
|
+
updatePosition(props.editor, component.element, clientRect);
|
|
38
163
|
},
|
|
39
164
|
onKeyDown: function onKeyDown(props) {
|
|
40
165
|
var _component$ref;
|
|
41
166
|
if (!component) return false;
|
|
42
167
|
if (props.event.key === 'Escape') {
|
|
168
|
+
if (cleanupAutoUpdate) {
|
|
169
|
+
cleanupAutoUpdate();
|
|
170
|
+
cleanupAutoUpdate = null;
|
|
171
|
+
}
|
|
43
172
|
component.element.remove();
|
|
44
173
|
component.destroy();
|
|
45
174
|
return true;
|
|
@@ -48,6 +177,26 @@ export var emojiSuggestion = {
|
|
|
48
177
|
},
|
|
49
178
|
onExit: function onExit() {
|
|
50
179
|
if (!component) return;
|
|
180
|
+
|
|
181
|
+
// 如果用户已经选择了 emoji,应该关闭
|
|
182
|
+
if (shouldClose) {
|
|
183
|
+
if (cleanupAutoUpdate) {
|
|
184
|
+
cleanupAutoUpdate();
|
|
185
|
+
cleanupAutoUpdate = null;
|
|
186
|
+
}
|
|
187
|
+
component.destroy();
|
|
188
|
+
component.element.remove();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 如果鼠标在弹框内,不关闭
|
|
193
|
+
if (isMouseOver) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (cleanupAutoUpdate) {
|
|
197
|
+
cleanupAutoUpdate();
|
|
198
|
+
cleanupAutoUpdate = null;
|
|
199
|
+
}
|
|
51
200
|
component.destroy();
|
|
52
201
|
component.element.remove();
|
|
53
202
|
}
|
package/dist/index.css
CHANGED
package/dist/type/index.d.ts
CHANGED
|
@@ -21,7 +21,8 @@ export interface MenuItem {
|
|
|
21
21
|
}
|
|
22
22
|
export interface MenuProps {
|
|
23
23
|
id?: string;
|
|
24
|
-
width?:
|
|
24
|
+
width?: React.CSSProperties['width'];
|
|
25
|
+
maxHeight?: React.CSSProperties['maxHeight'];
|
|
25
26
|
arrowIcon?: React.ReactNode;
|
|
26
27
|
list: MenuItem[];
|
|
27
28
|
header?: React.ReactNode;
|
package/dist/util/index.d.ts
CHANGED
|
@@ -5,10 +5,12 @@ export * from './linewiseConvert';
|
|
|
5
5
|
export * from './migrateMathStrings';
|
|
6
6
|
export * from './resourceExtractor';
|
|
7
7
|
export * from './shortcutKey';
|
|
8
|
+
import { Node } from '@tiptap/pm/model';
|
|
8
9
|
import { EditorState } from '@tiptap/pm/state';
|
|
9
10
|
import { Editor } from '@tiptap/react';
|
|
10
11
|
export declare const formatFileSize: (bytes: number) => string;
|
|
11
12
|
export declare const insertNodeAfterPosition: (editor: Editor, pos: number, nodeContent: any) => void;
|
|
13
|
+
export declare const hasMarksInBlock: (node: Node | null | undefined) => boolean;
|
|
12
14
|
export declare const hasMarksInSelection: (state: EditorState) => boolean;
|
|
13
15
|
export declare function addOpacityToColor(color: string, opacity: number): string;
|
|
14
16
|
export declare const getLinkTitle: (href: string) => string;
|
package/dist/util/index.js
CHANGED
|
@@ -15,6 +15,16 @@ export var formatFileSize = function formatFileSize(bytes) {
|
|
|
15
15
|
export var insertNodeAfterPosition = function insertNodeAfterPosition(editor, pos, nodeContent) {
|
|
16
16
|
editor.chain().focus().insertContentAt(pos, nodeContent).run();
|
|
17
17
|
};
|
|
18
|
+
export var hasMarksInBlock = function hasMarksInBlock(node) {
|
|
19
|
+
var _content;
|
|
20
|
+
if (!node) return false;
|
|
21
|
+
if (node.marks && node.marks.length > 0) return true;
|
|
22
|
+
var children = (_content = node.content) === null || _content === void 0 ? void 0 : _content.content;
|
|
23
|
+
if (!children || children.length === 0) return false;
|
|
24
|
+
return children.some(function (child) {
|
|
25
|
+
return hasMarksInBlock(child);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
18
28
|
export var hasMarksInSelection = function hasMarksInSelection(state) {
|
|
19
29
|
if (state.selection.empty) {
|
|
20
30
|
return false;
|