@tiptap/react 2.5.8 → 3.0.0-next.0
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/index.cjs +34 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +35 -21
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +34 -20
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/Extension.d.ts +1 -1
- package/dist/packages/core/src/Mark.d.ts +1 -1
- package/dist/packages/core/src/Node.d.ts +1 -1
- package/dist/packages/core/src/style.d.ts +1 -1
- package/dist/packages/extension-bubble-menu/src/bubble-menu-plugin.d.ts +35 -12
- package/dist/packages/extension-floating-menu/src/floating-menu-plugin.d.ts +29 -14
- package/dist/packages/react/src/BubbleMenu.d.ts +2 -0
- package/dist/packages/react/src/FloatingMenu.d.ts +1 -0
- package/package.json +7 -7
- package/src/BubbleMenu.tsx +29 -12
- package/src/FloatingMenu.tsx +25 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { type ArrowOptions, type AutoPlacementOptions, type FlipOptions, type HideOptions, type InlineOptions, type OffsetOptions, type Placement, type ShiftOptions, type SizeOptions, type Strategy } from '@floating-ui/dom';
|
|
1
2
|
import { Editor } from '@tiptap/core';
|
|
2
3
|
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
4
|
import { EditorView } from '@tiptap/pm/view';
|
|
4
|
-
import { Instance, Props } from 'tippy.js';
|
|
5
5
|
export interface BubbleMenuPluginProps {
|
|
6
6
|
/**
|
|
7
7
|
* The plugin key.
|
|
@@ -19,11 +19,6 @@ export interface BubbleMenuPluginProps {
|
|
|
19
19
|
* @default null
|
|
20
20
|
*/
|
|
21
21
|
element: HTMLElement;
|
|
22
|
-
/**
|
|
23
|
-
* The options for the tippy.js instance.
|
|
24
|
-
* @see https://atomiks.github.io/tippyjs/v6/all-props/
|
|
25
|
-
*/
|
|
26
|
-
tippyOptions?: Partial<Props>;
|
|
27
22
|
/**
|
|
28
23
|
* The delay in milliseconds before the menu should be updated.
|
|
29
24
|
* This can be useful to prevent performance issues.
|
|
@@ -31,11 +26,18 @@ export interface BubbleMenuPluginProps {
|
|
|
31
26
|
* @default 250
|
|
32
27
|
*/
|
|
33
28
|
updateDelay?: number;
|
|
29
|
+
/**
|
|
30
|
+
* The delay in milliseconds before the menu position should be updated on window resize.
|
|
31
|
+
* This can be useful to prevent performance issues.
|
|
32
|
+
* @type {number}
|
|
33
|
+
* @default 60
|
|
34
|
+
*/
|
|
35
|
+
resizeDelay?: number;
|
|
34
36
|
/**
|
|
35
37
|
* A function that determines whether the menu should be shown or not.
|
|
36
38
|
* If this function returns `false`, the menu will be hidden, otherwise it will be shown.
|
|
37
39
|
*/
|
|
38
|
-
shouldShow
|
|
40
|
+
shouldShow: ((props: {
|
|
39
41
|
editor: Editor;
|
|
40
42
|
view: EditorView;
|
|
41
43
|
state: EditorState;
|
|
@@ -43,6 +45,21 @@ export interface BubbleMenuPluginProps {
|
|
|
43
45
|
from: number;
|
|
44
46
|
to: number;
|
|
45
47
|
}) => boolean) | null;
|
|
48
|
+
/**
|
|
49
|
+
* FloatingUI options.
|
|
50
|
+
*/
|
|
51
|
+
options?: {
|
|
52
|
+
strategy?: Strategy;
|
|
53
|
+
placement?: Placement;
|
|
54
|
+
offset?: OffsetOptions | boolean;
|
|
55
|
+
flip?: FlipOptions | boolean;
|
|
56
|
+
shift?: ShiftOptions | boolean;
|
|
57
|
+
arrow?: ArrowOptions | false;
|
|
58
|
+
size?: SizeOptions | boolean;
|
|
59
|
+
autoPlacement?: AutoPlacementOptions | boolean;
|
|
60
|
+
hide?: HideOptions | boolean;
|
|
61
|
+
inline?: InlineOptions | boolean;
|
|
62
|
+
};
|
|
46
63
|
}
|
|
47
64
|
export type BubbleMenuViewProps = BubbleMenuPluginProps & {
|
|
48
65
|
view: EditorView;
|
|
@@ -52,22 +69,28 @@ export declare class BubbleMenuView {
|
|
|
52
69
|
element: HTMLElement;
|
|
53
70
|
view: EditorView;
|
|
54
71
|
preventHide: boolean;
|
|
55
|
-
tippy: Instance | undefined;
|
|
56
|
-
tippyOptions?: Partial<Props>;
|
|
57
72
|
updateDelay: number;
|
|
73
|
+
resizeDelay: number;
|
|
58
74
|
private updateDebounceTimer;
|
|
75
|
+
private resizeDebounceTimer;
|
|
76
|
+
private floatingUIOptions;
|
|
59
77
|
shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null>;
|
|
60
|
-
|
|
78
|
+
get middlewares(): {
|
|
79
|
+
name: string;
|
|
80
|
+
options?: any;
|
|
81
|
+
fn: (state: import("@floating-ui/dom").MiddlewareState) => import("@floating-ui/core").MiddlewareReturn | Promise<import("@floating-ui/core").MiddlewareReturn>;
|
|
82
|
+
}[];
|
|
83
|
+
constructor({ editor, element, view, updateDelay, resizeDelay, shouldShow, options, }: BubbleMenuViewProps);
|
|
61
84
|
mousedownHandler: () => void;
|
|
62
85
|
dragstartHandler: () => void;
|
|
63
86
|
focusHandler: () => void;
|
|
64
87
|
blurHandler: ({ event }: {
|
|
65
88
|
event: FocusEvent;
|
|
66
89
|
}) => void;
|
|
67
|
-
|
|
68
|
-
createTooltip(): void;
|
|
90
|
+
updatePosition(): void;
|
|
69
91
|
update(view: EditorView, oldState?: EditorState): void;
|
|
70
92
|
handleDebouncedUpdate: (view: EditorView, oldState?: EditorState) => void;
|
|
93
|
+
getShouldShow(oldState?: EditorState): boolean;
|
|
71
94
|
updateHandler: (view: EditorView, selectionChanged: boolean, docChanged: boolean, oldState?: EditorState) => void;
|
|
72
95
|
show(): void;
|
|
73
96
|
hide(): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { type ArrowOptions, type AutoPlacementOptions, type FlipOptions, type HideOptions, type InlineOptions, type OffsetOptions, type Placement, type ShiftOptions, type SizeOptions, type Strategy } from '@floating-ui/dom';
|
|
1
2
|
import { Editor } from '@tiptap/core';
|
|
2
3
|
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
4
|
import { EditorView } from '@tiptap/pm/view';
|
|
4
|
-
import { Instance, Props } from 'tippy.js';
|
|
5
5
|
export interface FloatingMenuPluginProps {
|
|
6
6
|
/**
|
|
7
7
|
* The plugin key for the floating menu.
|
|
@@ -18,23 +18,33 @@ export interface FloatingMenuPluginProps {
|
|
|
18
18
|
* @default null
|
|
19
19
|
*/
|
|
20
20
|
element: HTMLElement;
|
|
21
|
-
/**
|
|
22
|
-
* The options for the tippy instance.
|
|
23
|
-
* @default {}
|
|
24
|
-
* @see https://atomiks.github.io/tippyjs/v6/all-props/
|
|
25
|
-
*/
|
|
26
|
-
tippyOptions?: Partial<Props>;
|
|
27
21
|
/**
|
|
28
22
|
* A function that determines whether the menu should be shown or not.
|
|
29
23
|
* If this function returns `false`, the menu will be hidden, otherwise it will be shown.
|
|
30
|
-
* @default null
|
|
31
24
|
*/
|
|
32
|
-
shouldShow
|
|
25
|
+
shouldShow: ((props: {
|
|
33
26
|
editor: Editor;
|
|
34
27
|
view: EditorView;
|
|
35
28
|
state: EditorState;
|
|
36
29
|
oldState?: EditorState;
|
|
30
|
+
from: number;
|
|
31
|
+
to: number;
|
|
37
32
|
}) => boolean) | null;
|
|
33
|
+
/**
|
|
34
|
+
* FloatingUI options.
|
|
35
|
+
*/
|
|
36
|
+
options?: {
|
|
37
|
+
strategy?: Strategy;
|
|
38
|
+
placement?: Placement;
|
|
39
|
+
offset?: OffsetOptions | boolean;
|
|
40
|
+
flip?: FlipOptions | boolean;
|
|
41
|
+
shift?: ShiftOptions | boolean;
|
|
42
|
+
arrow?: ArrowOptions | false;
|
|
43
|
+
size?: SizeOptions | boolean;
|
|
44
|
+
autoPlacement?: AutoPlacementOptions | boolean;
|
|
45
|
+
hide?: HideOptions | boolean;
|
|
46
|
+
inline?: InlineOptions | boolean;
|
|
47
|
+
};
|
|
38
48
|
}
|
|
39
49
|
export type FloatingMenuViewProps = FloatingMenuPluginProps & {
|
|
40
50
|
/**
|
|
@@ -47,17 +57,22 @@ export declare class FloatingMenuView {
|
|
|
47
57
|
element: HTMLElement;
|
|
48
58
|
view: EditorView;
|
|
49
59
|
preventHide: boolean;
|
|
50
|
-
tippy: Instance | undefined;
|
|
51
|
-
tippyOptions?: Partial<Props>;
|
|
52
60
|
shouldShow: Exclude<FloatingMenuPluginProps['shouldShow'], null>;
|
|
53
|
-
|
|
61
|
+
private floatingUIOptions;
|
|
62
|
+
get middlewares(): {
|
|
63
|
+
name: string;
|
|
64
|
+
options?: any;
|
|
65
|
+
fn: (state: import("@floating-ui/dom").MiddlewareState) => import("@floating-ui/core").MiddlewareReturn | Promise<import("@floating-ui/core").MiddlewareReturn>;
|
|
66
|
+
}[];
|
|
67
|
+
constructor({ editor, element, view, options, shouldShow, }: FloatingMenuViewProps);
|
|
68
|
+
getShouldShow(oldState?: EditorState): boolean;
|
|
69
|
+
updateHandler: (view: EditorView, selectionChanged: boolean, docChanged: boolean, oldState?: EditorState) => void;
|
|
54
70
|
mousedownHandler: () => void;
|
|
55
71
|
focusHandler: () => void;
|
|
56
72
|
blurHandler: ({ event }: {
|
|
57
73
|
event: FocusEvent;
|
|
58
74
|
}) => void;
|
|
59
|
-
|
|
60
|
-
createTooltip(): void;
|
|
75
|
+
updatePosition(): void;
|
|
61
76
|
update(view: EditorView, oldState?: EditorState): void;
|
|
62
77
|
show(): void;
|
|
63
78
|
hide(): void;
|
|
@@ -6,6 +6,8 @@ export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>,
|
|
|
6
6
|
className?: string;
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
updateDelay?: number;
|
|
9
|
+
resizeDelay?: number;
|
|
10
|
+
options?: BubbleMenuPluginProps['options'];
|
|
9
11
|
};
|
|
10
12
|
export declare const BubbleMenu: (props: BubbleMenuProps) => React.JSX.Element;
|
|
11
13
|
export {};
|
|
@@ -5,6 +5,7 @@ export type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKe
|
|
|
5
5
|
editor: FloatingMenuPluginProps['editor'] | null;
|
|
6
6
|
className?: string;
|
|
7
7
|
children: React.ReactNode;
|
|
8
|
+
options?: FloatingMenuPluginProps['options'];
|
|
8
9
|
};
|
|
9
10
|
export declare const FloatingMenu: (props: FloatingMenuProps) => React.JSX.Element;
|
|
10
11
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/react",
|
|
3
3
|
"description": "React components for tiptap",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "3.0.0-next.0",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@tiptap/extension-bubble-menu": "^
|
|
33
|
-
"@tiptap/extension-floating-menu": "^
|
|
32
|
+
"@tiptap/extension-bubble-menu": "^3.0.0-next.0",
|
|
33
|
+
"@tiptap/extension-floating-menu": "^3.0.0-next.0",
|
|
34
34
|
"@types/use-sync-external-store": "^0.0.6",
|
|
35
35
|
"use-sync-external-store": "^1.2.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@tiptap/core": "^
|
|
39
|
-
"@tiptap/pm": "^
|
|
38
|
+
"@tiptap/core": "^3.0.0-next.0",
|
|
39
|
+
"@tiptap/pm": "^3.0.0-next.0",
|
|
40
40
|
"@types/react": "^18.2.14",
|
|
41
41
|
"@types/react-dom": "^18.2.6",
|
|
42
42
|
"react": "^18.0.0",
|
|
43
43
|
"react-dom": "^18.0.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@tiptap/core": "^
|
|
47
|
-
"@tiptap/pm": "^
|
|
46
|
+
"@tiptap/core": "^3.0.0-next.0",
|
|
47
|
+
"@tiptap/pm": "^3.0.0-next.0",
|
|
48
48
|
"react": "^17.0.0 || ^18.0.0",
|
|
49
49
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
50
50
|
},
|
package/src/BubbleMenu.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BubbleMenuPlugin, BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu'
|
|
2
|
-
import React, { useEffect,
|
|
2
|
+
import React, { useEffect, useRef } from 'react'
|
|
3
|
+
import { createPortal } from 'react-dom'
|
|
3
4
|
|
|
4
5
|
import { useCurrentEditor } from './Context.js'
|
|
5
6
|
|
|
@@ -10,23 +11,24 @@ export type BubbleMenuProps = Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>,
|
|
|
10
11
|
className?: string;
|
|
11
12
|
children: React.ReactNode;
|
|
12
13
|
updateDelay?: number;
|
|
14
|
+
resizeDelay?: number;
|
|
15
|
+
options?: BubbleMenuPluginProps['options'];
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
export const BubbleMenu = (props: BubbleMenuProps) => {
|
|
16
|
-
const
|
|
19
|
+
const menuEl = useRef(document.createElement('div'))
|
|
17
20
|
const { editor: currentEditor } = useCurrentEditor()
|
|
18
21
|
|
|
19
22
|
useEffect(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
+
menuEl.current.style.visibility = 'hidden'
|
|
24
|
+
menuEl.current.style.position = 'absolute'
|
|
23
25
|
|
|
24
26
|
if (props.editor?.isDestroyed || currentEditor?.isDestroyed) {
|
|
25
27
|
return
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const {
|
|
29
|
-
pluginKey = 'bubbleMenu', editor,
|
|
31
|
+
pluginKey = 'bubbleMenu', editor, updateDelay, resizeDelay, shouldShow = null,
|
|
30
32
|
} = props
|
|
31
33
|
|
|
32
34
|
const menuEditor = editor || currentEditor
|
|
@@ -38,20 +40,35 @@ export const BubbleMenu = (props: BubbleMenuProps) => {
|
|
|
38
40
|
|
|
39
41
|
const plugin = BubbleMenuPlugin({
|
|
40
42
|
updateDelay,
|
|
43
|
+
resizeDelay,
|
|
41
44
|
editor: menuEditor,
|
|
42
|
-
element,
|
|
45
|
+
element: menuEl.current,
|
|
43
46
|
pluginKey,
|
|
44
47
|
shouldShow,
|
|
45
|
-
|
|
48
|
+
options: props.options,
|
|
46
49
|
})
|
|
47
50
|
|
|
48
51
|
menuEditor.registerPlugin(plugin)
|
|
49
|
-
return () => menuEditor.unregisterPlugin(pluginKey)
|
|
50
|
-
}, [props.editor, currentEditor, element])
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
return () => {
|
|
54
|
+
menuEditor.unregisterPlugin(pluginKey)
|
|
55
|
+
window.requestAnimationFrame(() => {
|
|
56
|
+
if (menuEl.current.parentNode) {
|
|
57
|
+
menuEl.current.parentNode.removeChild(menuEl.current)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}, [props.editor, currentEditor])
|
|
62
|
+
|
|
63
|
+
const portal = createPortal(
|
|
64
|
+
(
|
|
65
|
+
<div className={props.className}>
|
|
54
66
|
{props.children}
|
|
55
67
|
</div>
|
|
68
|
+
), menuEl.current,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<>{portal}</>
|
|
56
73
|
)
|
|
57
74
|
}
|
package/src/FloatingMenu.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { FloatingMenuPlugin, FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'
|
|
2
2
|
import React, {
|
|
3
|
-
useEffect,
|
|
3
|
+
useEffect, useRef,
|
|
4
4
|
} from 'react'
|
|
5
|
+
import { createPortal } from 'react-dom'
|
|
5
6
|
|
|
6
7
|
import { useCurrentEditor } from './Context.js'
|
|
7
8
|
|
|
@@ -11,16 +12,16 @@ export type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKe
|
|
|
11
12
|
editor: FloatingMenuPluginProps['editor'] | null;
|
|
12
13
|
className?: string,
|
|
13
14
|
children: React.ReactNode
|
|
15
|
+
options?: FloatingMenuPluginProps['options']
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export const FloatingMenu = (props: FloatingMenuProps) => {
|
|
17
|
-
const
|
|
19
|
+
const menuEl = useRef(document.createElement('div'))
|
|
18
20
|
const { editor: currentEditor } = useCurrentEditor()
|
|
19
21
|
|
|
20
22
|
useEffect(() => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
23
|
+
menuEl.current.style.visibility = 'hidden'
|
|
24
|
+
menuEl.current.style.position = 'absolute'
|
|
24
25
|
|
|
25
26
|
if (props.editor?.isDestroyed || currentEditor?.isDestroyed) {
|
|
26
27
|
return
|
|
@@ -29,7 +30,7 @@ export const FloatingMenu = (props: FloatingMenuProps) => {
|
|
|
29
30
|
const {
|
|
30
31
|
pluginKey = 'floatingMenu',
|
|
31
32
|
editor,
|
|
32
|
-
|
|
33
|
+
options,
|
|
33
34
|
shouldShow = null,
|
|
34
35
|
} = props
|
|
35
36
|
|
|
@@ -43,22 +44,34 @@ export const FloatingMenu = (props: FloatingMenuProps) => {
|
|
|
43
44
|
const plugin = FloatingMenuPlugin({
|
|
44
45
|
pluginKey,
|
|
45
46
|
editor: menuEditor,
|
|
46
|
-
element,
|
|
47
|
-
|
|
47
|
+
element: menuEl.current,
|
|
48
|
+
options,
|
|
48
49
|
shouldShow,
|
|
49
50
|
})
|
|
50
51
|
|
|
51
52
|
menuEditor.registerPlugin(plugin)
|
|
52
|
-
return () =>
|
|
53
|
+
return () => {
|
|
54
|
+
menuEditor.unregisterPlugin(pluginKey)
|
|
55
|
+
window.requestAnimationFrame(() => {
|
|
56
|
+
if (menuEl.current.parentNode) {
|
|
57
|
+
menuEl.current.parentNode.removeChild(menuEl.current)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
}
|
|
53
61
|
}, [
|
|
54
62
|
props.editor,
|
|
55
63
|
currentEditor,
|
|
56
|
-
element,
|
|
57
64
|
])
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
const portal = createPortal(
|
|
67
|
+
(
|
|
68
|
+
<div className={props.className}>
|
|
61
69
|
{props.children}
|
|
62
70
|
</div>
|
|
71
|
+
), menuEl.current,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>{portal}</>
|
|
63
76
|
)
|
|
64
77
|
}
|