@tiptap/react 3.20.2 → 3.20.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/dist/menus/index.cjs +312 -42
- package/dist/menus/index.cjs.map +1 -1
- package/dist/menus/index.js +304 -34
- package/dist/menus/index.js.map +1 -1
- package/package.json +7 -7
- package/src/menus/BubbleMenu.spec.ts +174 -0
- package/src/menus/BubbleMenu.tsx +12 -4
- package/src/menus/FloatingMenu.spec.ts +164 -0
- package/src/menus/FloatingMenu.tsx +12 -15
- package/src/menus/getAutoPluginKey.ts +5 -0
- package/src/menus/useMenuElementProps.ts +354 -0
package/dist/menus/index.js
CHANGED
|
@@ -1,12 +1,288 @@
|
|
|
1
1
|
// src/menus/BubbleMenu.tsx
|
|
2
2
|
import { BubbleMenuPlugin } from "@tiptap/extension-bubble-menu";
|
|
3
3
|
import { useCurrentEditor } from "@tiptap/react";
|
|
4
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
4
|
+
import React, { useEffect as useEffect2, useRef as useRef2, useState } from "react";
|
|
5
5
|
import { createPortal } from "react-dom";
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
// src/menus/getAutoPluginKey.ts
|
|
8
|
+
import { PluginKey } from "@tiptap/pm/state";
|
|
9
|
+
function getAutoPluginKey(pluginKey, defaultName) {
|
|
10
|
+
return pluginKey != null ? pluginKey : new PluginKey(defaultName);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/menus/useMenuElementProps.ts
|
|
14
|
+
import { useEffect, useLayoutEffect, useRef } from "react";
|
|
15
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
16
|
+
var PLUGIN_MANAGED_STYLE_PROPERTIES = /* @__PURE__ */ new Set(["left", "opacity", "position", "top", "visibility", "width"]);
|
|
17
|
+
var UNITLESS_STYLE_PROPERTIES = /* @__PURE__ */ new Set([
|
|
18
|
+
"animationIterationCount",
|
|
19
|
+
"aspectRatio",
|
|
20
|
+
"borderImageOutset",
|
|
21
|
+
"borderImageSlice",
|
|
22
|
+
"borderImageWidth",
|
|
23
|
+
"columnCount",
|
|
24
|
+
"columns",
|
|
25
|
+
"fillOpacity",
|
|
26
|
+
"flex",
|
|
27
|
+
"flexGrow",
|
|
28
|
+
"flexShrink",
|
|
29
|
+
"fontWeight",
|
|
30
|
+
"gridArea",
|
|
31
|
+
"gridColumn",
|
|
32
|
+
"gridColumnEnd",
|
|
33
|
+
"gridColumnStart",
|
|
34
|
+
"gridRow",
|
|
35
|
+
"gridRowEnd",
|
|
36
|
+
"gridRowStart",
|
|
37
|
+
"lineClamp",
|
|
38
|
+
"lineHeight",
|
|
39
|
+
"opacity",
|
|
40
|
+
"order",
|
|
41
|
+
"orphans",
|
|
42
|
+
"scale",
|
|
43
|
+
"stopOpacity",
|
|
44
|
+
"strokeDasharray",
|
|
45
|
+
"strokeDashoffset",
|
|
46
|
+
"strokeMiterlimit",
|
|
47
|
+
"strokeOpacity",
|
|
48
|
+
"strokeWidth",
|
|
49
|
+
"tabSize",
|
|
50
|
+
"widows",
|
|
51
|
+
"zIndex",
|
|
52
|
+
"zoom"
|
|
53
|
+
]);
|
|
54
|
+
var ATTRIBUTE_EXCLUSIONS = /* @__PURE__ */ new Set(["children", "className", "style"]);
|
|
55
|
+
var DIRECT_PROPERTY_KEYS = /* @__PURE__ */ new Set(["tabIndex"]);
|
|
56
|
+
var FORWARDED_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
|
|
57
|
+
"accessKey",
|
|
58
|
+
"autoCapitalize",
|
|
59
|
+
"contentEditable",
|
|
60
|
+
"contextMenu",
|
|
61
|
+
"dir",
|
|
62
|
+
"draggable",
|
|
63
|
+
"enterKeyHint",
|
|
64
|
+
"hidden",
|
|
65
|
+
"id",
|
|
66
|
+
"lang",
|
|
67
|
+
"nonce",
|
|
68
|
+
"role",
|
|
69
|
+
"slot",
|
|
70
|
+
"spellCheck",
|
|
71
|
+
"tabIndex",
|
|
72
|
+
"title",
|
|
73
|
+
"translate"
|
|
74
|
+
]);
|
|
75
|
+
var SPECIAL_EVENT_NAMES = {
|
|
76
|
+
Blur: "focusout",
|
|
77
|
+
DoubleClick: "dblclick",
|
|
78
|
+
Focus: "focusin",
|
|
79
|
+
MouseEnter: "mouseenter",
|
|
80
|
+
MouseLeave: "mouseleave"
|
|
81
|
+
};
|
|
82
|
+
function isEventProp(key, value) {
|
|
83
|
+
return /^on[A-Z]/.test(key) && typeof value === "function";
|
|
84
|
+
}
|
|
85
|
+
function toAttributeName(key) {
|
|
86
|
+
if (key.startsWith("aria-") || key.startsWith("data-")) {
|
|
87
|
+
return key;
|
|
88
|
+
}
|
|
89
|
+
return key;
|
|
90
|
+
}
|
|
91
|
+
function isForwardedAttributeKey(key) {
|
|
92
|
+
return key.startsWith("aria-") || key.startsWith("data-") || FORWARDED_ATTRIBUTE_KEYS.has(key);
|
|
93
|
+
}
|
|
94
|
+
function toStylePropertyName(key) {
|
|
95
|
+
if (key.startsWith("--")) {
|
|
96
|
+
return key;
|
|
97
|
+
}
|
|
98
|
+
return key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
|
|
99
|
+
}
|
|
100
|
+
function toEventConfig(key) {
|
|
101
|
+
var _a;
|
|
102
|
+
const useCapture = key.endsWith("Capture");
|
|
103
|
+
const baseKey = useCapture ? key.slice(0, -7) : key;
|
|
104
|
+
const reactEventName = baseKey.slice(2);
|
|
105
|
+
const eventName = (_a = SPECIAL_EVENT_NAMES[reactEventName]) != null ? _a : reactEventName.toLowerCase();
|
|
106
|
+
return {
|
|
107
|
+
eventName,
|
|
108
|
+
options: useCapture ? { capture: true } : void 0
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function createSyntheticEvent(element, nativeEvent) {
|
|
112
|
+
let defaultPrevented = nativeEvent.defaultPrevented;
|
|
113
|
+
let propagationStopped = false;
|
|
114
|
+
const syntheticEvent = Object.create(nativeEvent);
|
|
115
|
+
Object.defineProperties(syntheticEvent, {
|
|
116
|
+
nativeEvent: { value: nativeEvent },
|
|
117
|
+
currentTarget: { value: element },
|
|
118
|
+
target: { value: nativeEvent.target },
|
|
119
|
+
persist: { value: () => void 0 },
|
|
120
|
+
isDefaultPrevented: { value: () => defaultPrevented },
|
|
121
|
+
isPropagationStopped: { value: () => propagationStopped },
|
|
122
|
+
preventDefault: {
|
|
123
|
+
value: () => {
|
|
124
|
+
defaultPrevented = true;
|
|
125
|
+
nativeEvent.preventDefault();
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
stopPropagation: {
|
|
129
|
+
value: () => {
|
|
130
|
+
propagationStopped = true;
|
|
131
|
+
nativeEvent.stopPropagation();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
return syntheticEvent;
|
|
136
|
+
}
|
|
137
|
+
function isDirectPropertyKey(key) {
|
|
138
|
+
return DIRECT_PROPERTY_KEYS.has(key);
|
|
139
|
+
}
|
|
140
|
+
function setDirectProperty(element, key, value) {
|
|
141
|
+
if (key === "tabIndex") {
|
|
142
|
+
element.tabIndex = Number(value);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
;
|
|
146
|
+
element[key] = value;
|
|
147
|
+
}
|
|
148
|
+
function clearDirectProperty(element, key) {
|
|
149
|
+
if (key === "tabIndex") {
|
|
150
|
+
element.removeAttribute("tabindex");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const propertyValue = element[key];
|
|
154
|
+
if (typeof propertyValue === "boolean") {
|
|
155
|
+
;
|
|
156
|
+
element[key] = false;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (typeof propertyValue === "number") {
|
|
160
|
+
;
|
|
161
|
+
element[key] = 0;
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
;
|
|
165
|
+
element[key] = "";
|
|
166
|
+
}
|
|
167
|
+
function toStyleValue(styleName, value) {
|
|
168
|
+
if (typeof value !== "number" || value === 0 || styleName.startsWith("--") || UNITLESS_STYLE_PROPERTIES.has(styleName)) {
|
|
169
|
+
return String(value);
|
|
170
|
+
}
|
|
171
|
+
return `${value}px`;
|
|
172
|
+
}
|
|
173
|
+
function removeStyleProperty(element, styleName) {
|
|
174
|
+
if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
element.style.removeProperty(toStylePropertyName(styleName));
|
|
178
|
+
}
|
|
179
|
+
function applyStyleProperty(element, styleName, value) {
|
|
180
|
+
if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value));
|
|
184
|
+
}
|
|
185
|
+
function syncAttributes(element, prevProps, nextProps) {
|
|
186
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(prevProps), ...Object.keys(nextProps)]);
|
|
187
|
+
allKeys.forEach((key) => {
|
|
188
|
+
if (ATTRIBUTE_EXCLUSIONS.has(key) || !isForwardedAttributeKey(key) || isEventProp(key, prevProps[key]) || isEventProp(key, nextProps[key])) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const prevValue = prevProps[key];
|
|
192
|
+
const nextValue = nextProps[key];
|
|
193
|
+
if (prevValue === nextValue) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const attributeName = toAttributeName(key);
|
|
197
|
+
if (nextValue == null || nextValue === false) {
|
|
198
|
+
if (isDirectPropertyKey(key)) {
|
|
199
|
+
clearDirectProperty(element, key);
|
|
200
|
+
}
|
|
201
|
+
element.removeAttribute(attributeName);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (nextValue === true) {
|
|
205
|
+
if (isDirectPropertyKey(key)) {
|
|
206
|
+
setDirectProperty(element, key, true);
|
|
207
|
+
}
|
|
208
|
+
element.setAttribute(attributeName, "");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (isDirectPropertyKey(key)) {
|
|
212
|
+
setDirectProperty(element, key, nextValue);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
element.setAttribute(attributeName, String(nextValue));
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function syncClassName(element, prevClassName, nextClassName) {
|
|
219
|
+
if (prevClassName === nextClassName) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (nextClassName) {
|
|
223
|
+
element.className = nextClassName;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
element.removeAttribute("class");
|
|
227
|
+
}
|
|
228
|
+
function syncStyles(element, prevStyle, nextStyle) {
|
|
229
|
+
const previousStyle = prevStyle != null ? prevStyle : {};
|
|
230
|
+
const currentStyle = nextStyle != null ? nextStyle : {};
|
|
231
|
+
const allStyleNames = /* @__PURE__ */ new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)]);
|
|
232
|
+
allStyleNames.forEach((styleName) => {
|
|
233
|
+
const prevValue = previousStyle[styleName];
|
|
234
|
+
const nextValue = currentStyle[styleName];
|
|
235
|
+
if (prevValue === nextValue) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (nextValue == null) {
|
|
239
|
+
removeStyleProperty(element, styleName);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
applyStyleProperty(element, styleName, nextValue);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
function syncEventListeners(element, prevListeners, nextProps) {
|
|
246
|
+
prevListeners.forEach(({ eventName, listener, options }) => {
|
|
247
|
+
element.removeEventListener(eventName, listener, options);
|
|
248
|
+
});
|
|
249
|
+
const nextListeners = [];
|
|
250
|
+
Object.entries(nextProps).forEach(([key, value]) => {
|
|
251
|
+
if (!isEventProp(key, value)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const { eventName, options } = toEventConfig(key);
|
|
255
|
+
const listener = (event) => {
|
|
256
|
+
value(createSyntheticEvent(element, event));
|
|
257
|
+
};
|
|
258
|
+
element.addEventListener(eventName, listener, options);
|
|
259
|
+
nextListeners.push({ eventName, listener, options });
|
|
260
|
+
});
|
|
261
|
+
return nextListeners;
|
|
262
|
+
}
|
|
263
|
+
function useMenuElementProps(element, props) {
|
|
264
|
+
const previousPropsRef = useRef({});
|
|
265
|
+
const listenersRef = useRef([]);
|
|
266
|
+
useIsomorphicLayoutEffect(() => {
|
|
267
|
+
const previousProps = previousPropsRef.current;
|
|
268
|
+
syncClassName(element, previousProps.className, props.className);
|
|
269
|
+
syncStyles(element, previousProps.style, props.style);
|
|
270
|
+
syncAttributes(element, previousProps, props);
|
|
271
|
+
listenersRef.current = syncEventListeners(element, listenersRef.current, props);
|
|
272
|
+
previousPropsRef.current = props;
|
|
273
|
+
return () => {
|
|
274
|
+
listenersRef.current.forEach(({ eventName, listener, options }) => {
|
|
275
|
+
element.removeEventListener(eventName, listener, options);
|
|
276
|
+
});
|
|
277
|
+
listenersRef.current = [];
|
|
278
|
+
};
|
|
279
|
+
}, [element, props]);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/menus/BubbleMenu.tsx
|
|
7
283
|
var BubbleMenu = React.forwardRef(
|
|
8
284
|
({
|
|
9
|
-
pluginKey
|
|
285
|
+
pluginKey,
|
|
10
286
|
editor,
|
|
11
287
|
updateDelay,
|
|
12
288
|
resizeDelay,
|
|
@@ -17,7 +293,9 @@ var BubbleMenu = React.forwardRef(
|
|
|
17
293
|
children,
|
|
18
294
|
...restProps
|
|
19
295
|
}, ref) => {
|
|
20
|
-
const menuEl =
|
|
296
|
+
const menuEl = useRef2(document.createElement("div"));
|
|
297
|
+
const resolvedPluginKey = useRef2(getAutoPluginKey(pluginKey, "bubbleMenu")).current;
|
|
298
|
+
useMenuElementProps(menuEl.current, restProps);
|
|
21
299
|
if (typeof ref === "function") {
|
|
22
300
|
ref(menuEl.current);
|
|
23
301
|
} else if (ref) {
|
|
@@ -29,16 +307,16 @@ var BubbleMenu = React.forwardRef(
|
|
|
29
307
|
updateDelay,
|
|
30
308
|
resizeDelay,
|
|
31
309
|
appendTo,
|
|
32
|
-
pluginKey,
|
|
310
|
+
pluginKey: resolvedPluginKey,
|
|
33
311
|
shouldShow,
|
|
34
312
|
getReferencedVirtualElement,
|
|
35
313
|
options
|
|
36
314
|
};
|
|
37
|
-
const bubbleMenuPluginPropsRef =
|
|
315
|
+
const bubbleMenuPluginPropsRef = useRef2(bubbleMenuPluginProps);
|
|
38
316
|
bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps;
|
|
39
317
|
const [pluginInitialized, setPluginInitialized] = useState(false);
|
|
40
|
-
const skipFirstUpdateRef =
|
|
41
|
-
|
|
318
|
+
const skipFirstUpdateRef = useRef2(true);
|
|
319
|
+
useEffect2(() => {
|
|
42
320
|
if (pluginEditor == null ? void 0 : pluginEditor.isDestroyed) {
|
|
43
321
|
return;
|
|
44
322
|
}
|
|
@@ -68,7 +346,7 @@ var BubbleMenu = React.forwardRef(
|
|
|
68
346
|
});
|
|
69
347
|
};
|
|
70
348
|
}, [pluginEditor]);
|
|
71
|
-
|
|
349
|
+
useEffect2(() => {
|
|
72
350
|
if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {
|
|
73
351
|
return;
|
|
74
352
|
}
|
|
@@ -77,7 +355,7 @@ var BubbleMenu = React.forwardRef(
|
|
|
77
355
|
return;
|
|
78
356
|
}
|
|
79
357
|
pluginEditor.view.dispatch(
|
|
80
|
-
pluginEditor.state.tr.setMeta(
|
|
358
|
+
pluginEditor.state.tr.setMeta(resolvedPluginKey, {
|
|
81
359
|
type: "updateOptions",
|
|
82
360
|
options: bubbleMenuPluginPropsRef.current
|
|
83
361
|
})
|
|
@@ -90,31 +368,23 @@ var BubbleMenu = React.forwardRef(
|
|
|
90
368
|
shouldShow,
|
|
91
369
|
options,
|
|
92
370
|
appendTo,
|
|
93
|
-
getReferencedVirtualElement
|
|
371
|
+
getReferencedVirtualElement,
|
|
372
|
+
resolvedPluginKey
|
|
94
373
|
]);
|
|
95
|
-
return createPortal(
|
|
374
|
+
return createPortal(children, menuEl.current);
|
|
96
375
|
}
|
|
97
376
|
);
|
|
98
377
|
|
|
99
378
|
// src/menus/FloatingMenu.tsx
|
|
100
379
|
import { FloatingMenuPlugin } from "@tiptap/extension-floating-menu";
|
|
101
380
|
import { useCurrentEditor as useCurrentEditor2 } from "@tiptap/react";
|
|
102
|
-
import React2, { useEffect as
|
|
381
|
+
import React2, { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
103
382
|
import { createPortal as createPortal2 } from "react-dom";
|
|
104
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
105
383
|
var FloatingMenu = React2.forwardRef(
|
|
106
|
-
({
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
resizeDelay,
|
|
111
|
-
appendTo,
|
|
112
|
-
shouldShow = null,
|
|
113
|
-
options,
|
|
114
|
-
children,
|
|
115
|
-
...restProps
|
|
116
|
-
}, ref) => {
|
|
117
|
-
const menuEl = useRef2(document.createElement("div"));
|
|
384
|
+
({ pluginKey, editor, updateDelay, resizeDelay, appendTo, shouldShow = null, options, children, ...restProps }, ref) => {
|
|
385
|
+
const menuEl = useRef3(document.createElement("div"));
|
|
386
|
+
const resolvedPluginKey = useRef3(getAutoPluginKey(pluginKey, "floatingMenu")).current;
|
|
387
|
+
useMenuElementProps(menuEl.current, restProps);
|
|
118
388
|
if (typeof ref === "function") {
|
|
119
389
|
ref(menuEl.current);
|
|
120
390
|
} else if (ref) {
|
|
@@ -126,15 +396,15 @@ var FloatingMenu = React2.forwardRef(
|
|
|
126
396
|
updateDelay,
|
|
127
397
|
resizeDelay,
|
|
128
398
|
appendTo,
|
|
129
|
-
pluginKey,
|
|
399
|
+
pluginKey: resolvedPluginKey,
|
|
130
400
|
shouldShow,
|
|
131
401
|
options
|
|
132
402
|
};
|
|
133
|
-
const floatingMenuPluginPropsRef =
|
|
403
|
+
const floatingMenuPluginPropsRef = useRef3(floatingMenuPluginProps);
|
|
134
404
|
floatingMenuPluginPropsRef.current = floatingMenuPluginProps;
|
|
135
405
|
const [pluginInitialized, setPluginInitialized] = useState2(false);
|
|
136
|
-
const skipFirstUpdateRef =
|
|
137
|
-
|
|
406
|
+
const skipFirstUpdateRef = useRef3(true);
|
|
407
|
+
useEffect3(() => {
|
|
138
408
|
if (pluginEditor == null ? void 0 : pluginEditor.isDestroyed) {
|
|
139
409
|
return;
|
|
140
410
|
}
|
|
@@ -166,7 +436,7 @@ var FloatingMenu = React2.forwardRef(
|
|
|
166
436
|
});
|
|
167
437
|
};
|
|
168
438
|
}, [pluginEditor]);
|
|
169
|
-
|
|
439
|
+
useEffect3(() => {
|
|
170
440
|
if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {
|
|
171
441
|
return;
|
|
172
442
|
}
|
|
@@ -175,13 +445,13 @@ var FloatingMenu = React2.forwardRef(
|
|
|
175
445
|
return;
|
|
176
446
|
}
|
|
177
447
|
pluginEditor.view.dispatch(
|
|
178
|
-
pluginEditor.state.tr.setMeta(
|
|
448
|
+
pluginEditor.state.tr.setMeta(resolvedPluginKey, {
|
|
179
449
|
type: "updateOptions",
|
|
180
450
|
options: floatingMenuPluginPropsRef.current
|
|
181
451
|
})
|
|
182
452
|
);
|
|
183
|
-
}, [pluginInitialized, pluginEditor, updateDelay, resizeDelay, shouldShow, options, appendTo]);
|
|
184
|
-
return createPortal2(
|
|
453
|
+
}, [pluginInitialized, pluginEditor, updateDelay, resizeDelay, shouldShow, options, appendTo, resolvedPluginKey]);
|
|
454
|
+
return createPortal2(children, menuEl.current);
|
|
185
455
|
}
|
|
186
456
|
);
|
|
187
457
|
export {
|
package/dist/menus/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey = 'bubbleMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the bubble menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const bubbleMenuPluginProps: Omit<BubbleMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n }\n /**\n * The props for the bubble menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps)\n bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.style.position = 'absolute'\n\n const plugin = BubbleMenuPlugin({\n ...bubbleMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: bubbleMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(pluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n ])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element' | 'editor'> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n {\n pluginKey = 'floatingMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the floating menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'FloatingMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\n return\n }\n\n const floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(pluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [pluginInitialized, pluginEditor, updateDelay, resizeDelay, shouldShow, options, appendTo])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n"],"mappings":"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","names":["useCurrentEditor","React","useEffect","useRef","useState","createPortal","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/getAutoPluginKey.ts","../../src/menus/useMenuElementProps.ts","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey,\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(getAutoPluginKey(pluginKey, 'bubbleMenu')).current\n\n useMenuElementProps(menuEl.current, restProps)\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the bubble menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const bubbleMenuPluginProps: Omit<BubbleMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n }\n /**\n * The props for the bubble menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps)\n bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.style.position = 'absolute'\n\n const plugin = BubbleMenuPlugin({\n ...bubbleMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: bubbleMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n","import { PluginKey } from '@tiptap/pm/state'\n\nexport function getAutoPluginKey(pluginKey: PluginKey | string | undefined, defaultName: string) {\n return pluginKey ?? new PluginKey(defaultName)\n}\n","import type { CSSProperties, HTMLAttributes } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ntype MenuElementProps = HTMLAttributes<HTMLDivElement>\ntype MenuSyntheticEvent = Event & {\n nativeEvent: Event\n currentTarget: HTMLDivElement\n target: EventTarget | null\n persist: () => void\n isDefaultPrevented: () => boolean\n isPropagationStopped: () => boolean\n}\ntype MenuEventListener = (event: MenuSyntheticEvent) => void\ntype MenuNativeListener = (event: Event) => void\ntype MenuEventListenerOptions = {\n capture?: boolean\n}\n\ntype EventListenerEntry = {\n eventName: string\n listener: MenuNativeListener\n options?: MenuEventListenerOptions\n}\n\nconst PLUGIN_MANAGED_STYLE_PROPERTIES = new Set(['left', 'opacity', 'position', 'top', 'visibility', 'width'])\nconst UNITLESS_STYLE_PROPERTIES = new Set([\n 'animationIterationCount',\n 'aspectRatio',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'fillOpacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'scale',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n])\nconst ATTRIBUTE_EXCLUSIONS = new Set(['children', 'className', 'style'])\nconst DIRECT_PROPERTY_KEYS = new Set(['tabIndex'])\nconst FORWARDED_ATTRIBUTE_KEYS = new Set([\n 'accessKey',\n 'autoCapitalize',\n 'contentEditable',\n 'contextMenu',\n 'dir',\n 'draggable',\n 'enterKeyHint',\n 'hidden',\n 'id',\n 'lang',\n 'nonce',\n 'role',\n 'slot',\n 'spellCheck',\n 'tabIndex',\n 'title',\n 'translate',\n])\nconst SPECIAL_EVENT_NAMES: Record<string, string> = {\n Blur: 'focusout',\n DoubleClick: 'dblclick',\n Focus: 'focusin',\n MouseEnter: 'mouseenter',\n MouseLeave: 'mouseleave',\n}\n\nfunction isEventProp(key: string, value: unknown): value is MenuEventListener {\n return /^on[A-Z]/.test(key) && typeof value === 'function'\n}\n\nfunction toAttributeName(key: string) {\n if (key.startsWith('aria-') || key.startsWith('data-')) {\n return key\n }\n\n return key\n}\n\nfunction isForwardedAttributeKey(key: string) {\n return key.startsWith('aria-') || key.startsWith('data-') || FORWARDED_ATTRIBUTE_KEYS.has(key)\n}\n\nfunction toStylePropertyName(key: string) {\n if (key.startsWith('--')) {\n return key\n }\n\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\n}\n\nfunction toEventConfig(key: string) {\n const useCapture = key.endsWith('Capture')\n const baseKey = useCapture ? key.slice(0, -7) : key\n const reactEventName = baseKey.slice(2)\n const eventName = SPECIAL_EVENT_NAMES[reactEventName] ?? reactEventName.toLowerCase()\n\n return {\n eventName,\n options: useCapture ? { capture: true } : undefined,\n }\n}\n\nfunction createSyntheticEvent(element: HTMLDivElement, nativeEvent: Event): MenuSyntheticEvent {\n let defaultPrevented = nativeEvent.defaultPrevented\n let propagationStopped = false\n const syntheticEvent = Object.create(nativeEvent)\n\n Object.defineProperties(syntheticEvent, {\n nativeEvent: { value: nativeEvent },\n currentTarget: { value: element },\n target: { value: nativeEvent.target },\n persist: { value: () => undefined },\n isDefaultPrevented: { value: () => defaultPrevented },\n isPropagationStopped: { value: () => propagationStopped },\n preventDefault: {\n value: () => {\n defaultPrevented = true\n nativeEvent.preventDefault()\n },\n },\n stopPropagation: {\n value: () => {\n propagationStopped = true\n nativeEvent.stopPropagation()\n },\n },\n })\n\n return syntheticEvent as MenuSyntheticEvent\n}\n\nfunction isDirectPropertyKey(key: string) {\n return DIRECT_PROPERTY_KEYS.has(key)\n}\n\nfunction setDirectProperty(element: HTMLDivElement, key: string, value: unknown) {\n if (key === 'tabIndex') {\n element.tabIndex = Number(value)\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = value\n}\n\nfunction clearDirectProperty(element: HTMLDivElement, key: string) {\n if (key === 'tabIndex') {\n element.removeAttribute('tabindex')\n return\n }\n\n const propertyValue = (element as unknown as Record<string, unknown>)[key]\n\n if (typeof propertyValue === 'boolean') {\n ;(element as unknown as Record<string, unknown>)[key] = false\n return\n }\n\n if (typeof propertyValue === 'number') {\n ;(element as unknown as Record<string, unknown>)[key] = 0\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = ''\n}\n\nfunction toStyleValue(styleName: string, value: string | number) {\n if (\n typeof value !== 'number' ||\n value === 0 ||\n styleName.startsWith('--') ||\n UNITLESS_STYLE_PROPERTIES.has(styleName)\n ) {\n return String(value)\n }\n\n return `${value}px`\n}\n\nfunction removeStyleProperty(element: HTMLDivElement, styleName: string) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.removeProperty(toStylePropertyName(styleName))\n}\n\nfunction applyStyleProperty(element: HTMLDivElement, styleName: string, value: string | number) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value))\n}\n\nfunction syncAttributes(element: HTMLDivElement, prevProps: MenuElementProps, nextProps: MenuElementProps) {\n const allKeys = new Set([...Object.keys(prevProps), ...Object.keys(nextProps)])\n\n allKeys.forEach(key => {\n if (\n ATTRIBUTE_EXCLUSIONS.has(key) ||\n !isForwardedAttributeKey(key) ||\n isEventProp(key, prevProps[key as keyof MenuElementProps]) ||\n isEventProp(key, nextProps[key as keyof MenuElementProps])\n ) {\n return\n }\n\n const prevValue = prevProps[key as keyof MenuElementProps]\n const nextValue = nextProps[key as keyof MenuElementProps]\n\n if (prevValue === nextValue) {\n return\n }\n\n const attributeName = toAttributeName(key)\n\n if (nextValue == null || nextValue === false) {\n if (isDirectPropertyKey(key)) {\n clearDirectProperty(element, key)\n }\n\n element.removeAttribute(attributeName)\n return\n }\n\n if (nextValue === true) {\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, true)\n }\n\n element.setAttribute(attributeName, '')\n return\n }\n\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, nextValue)\n return\n }\n\n element.setAttribute(attributeName, String(nextValue))\n })\n}\n\nfunction syncClassName(element: HTMLDivElement, prevClassName?: string, nextClassName?: string) {\n if (prevClassName === nextClassName) {\n return\n }\n\n if (nextClassName) {\n element.className = nextClassName\n return\n }\n\n element.removeAttribute('class')\n}\n\nfunction syncStyles(\n element: HTMLDivElement,\n prevStyle: CSSProperties | undefined,\n nextStyle: CSSProperties | undefined,\n) {\n const previousStyle = prevStyle ?? {}\n const currentStyle = nextStyle ?? {}\n const allStyleNames = new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)])\n\n allStyleNames.forEach(styleName => {\n const prevValue = previousStyle[styleName as keyof CSSProperties]\n const nextValue = currentStyle[styleName as keyof CSSProperties]\n\n if (prevValue === nextValue) {\n return\n }\n\n if (nextValue == null) {\n removeStyleProperty(element, styleName)\n return\n }\n\n applyStyleProperty(element, styleName, nextValue as string | number)\n })\n}\n\nfunction syncEventListeners(element: HTMLDivElement, prevListeners: EventListenerEntry[], nextProps: MenuElementProps) {\n prevListeners.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n\n const nextListeners: EventListenerEntry[] = []\n\n Object.entries(nextProps).forEach(([key, value]) => {\n if (!isEventProp(key, value)) {\n return\n }\n\n const { eventName, options } = toEventConfig(key)\n const listener: MenuNativeListener = event => {\n value(createSyntheticEvent(element, event))\n }\n\n element.addEventListener(eventName, listener, options)\n nextListeners.push({ eventName, listener, options })\n })\n\n return nextListeners\n}\n\nexport function useMenuElementProps(element: HTMLDivElement, props: MenuElementProps) {\n const previousPropsRef = useRef<MenuElementProps>({})\n const listenersRef = useRef<EventListenerEntry[]>([])\n\n useIsomorphicLayoutEffect(() => {\n const previousProps = previousPropsRef.current\n\n syncClassName(element, previousProps.className, props.className)\n syncStyles(element, previousProps.style, props.style)\n syncAttributes(element, previousProps, props)\n listenersRef.current = syncEventListeners(element, listenersRef.current, props)\n previousPropsRef.current = props\n\n return () => {\n listenersRef.current.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n listenersRef.current = []\n }\n }, [element, props])\n}\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element' | 'editor'> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n { pluginKey, editor, updateDelay, resizeDelay, appendTo, shouldShow = null, options, children, ...restProps },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(getAutoPluginKey(pluginKey, 'floatingMenu')).current\n\n useMenuElementProps(menuEl.current, restProps)\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the floating menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'FloatingMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\n return\n }\n\n const floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [pluginInitialized, pluginEditor, updateDelay, resizeDelay, shouldShow, options, appendTo, resolvedPluginKey])\n\n return createPortal(children, menuEl.current)\n },\n)\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","useCurrentEditor","React","useEffect","useRef","useState","createPortal","React","useRef","useCurrentEditor","useState","useEffect","createPortal"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/react",
|
|
3
3
|
"description": "React components for tiptap",
|
|
4
|
-
"version": "3.20.
|
|
4
|
+
"version": "3.20.4",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -48,20 +48,20 @@
|
|
|
48
48
|
"@types/react-dom": "^19.0.0",
|
|
49
49
|
"react": "^19.0.0",
|
|
50
50
|
"react-dom": "^19.0.0",
|
|
51
|
-
"@tiptap/core": "^3.20.
|
|
52
|
-
"@tiptap/pm": "^3.20.
|
|
51
|
+
"@tiptap/core": "^3.20.4",
|
|
52
|
+
"@tiptap/pm": "^3.20.4"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@tiptap/extension-bubble-menu": "^3.20.
|
|
56
|
-
"@tiptap/extension-floating-menu": "^3.20.
|
|
55
|
+
"@tiptap/extension-bubble-menu": "^3.20.4",
|
|
56
|
+
"@tiptap/extension-floating-menu": "^3.20.4"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
60
60
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
61
61
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
62
62
|
"@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
63
|
-
"@tiptap/core": "^3.20.
|
|
64
|
-
"@tiptap/pm": "^3.20.
|
|
63
|
+
"@tiptap/core": "^3.20.4",
|
|
64
|
+
"@tiptap/pm": "^3.20.4"
|
|
65
65
|
},
|
|
66
66
|
"repository": {
|
|
67
67
|
"type": "git",
|