@tiptap/react 2.5.9 → 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 +171 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +172 -274
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +171 -273
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +4 -10
- 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
- package/src/useEditor.ts +87 -241
- package/src/useEditorState.ts +60 -75
package/src/useEditorState.ts
CHANGED
|
@@ -30,83 +30,68 @@ export type UseEditorStateOptions<
|
|
|
30
30
|
* To synchronize the editor instance with the component state,
|
|
31
31
|
* we need to create a separate instance that is not affected by the component re-renders.
|
|
32
32
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.getSnapshot = this.getSnapshot.bind(this)
|
|
49
|
-
this.getServerSnapshot = this.getServerSnapshot.bind(this)
|
|
50
|
-
this.watch = this.watch.bind(this)
|
|
51
|
-
this.subscribe = this.subscribe.bind(this)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get the current editor instance.
|
|
56
|
-
*/
|
|
57
|
-
getSnapshot(): EditorStateSnapshot<TEditor> {
|
|
58
|
-
if (this.transactionNumber === this.lastTransactionNumber) {
|
|
59
|
-
return this.lastSnapshot
|
|
60
|
-
}
|
|
61
|
-
this.lastTransactionNumber = this.transactionNumber
|
|
62
|
-
this.lastSnapshot = { editor: this.editor, transactionNumber: this.transactionNumber }
|
|
63
|
-
return this.lastSnapshot
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Always disable the editor on the server-side.
|
|
68
|
-
*/
|
|
69
|
-
getServerSnapshot(): EditorStateSnapshot<null> {
|
|
70
|
-
return { editor: null, transactionNumber: 0 }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Subscribe to the editor instance's changes.
|
|
75
|
-
*/
|
|
76
|
-
subscribe(callback: () => void): () => void {
|
|
77
|
-
this.subscribers.add(callback)
|
|
78
|
-
return () => {
|
|
79
|
-
this.subscribers.delete(callback)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Watch the editor instance for changes.
|
|
85
|
-
*/
|
|
86
|
-
watch(nextEditor: Editor | null): undefined | (() => void) {
|
|
87
|
-
this.editor = nextEditor as TEditor
|
|
88
|
-
|
|
89
|
-
if (this.editor) {
|
|
90
|
-
/**
|
|
91
|
-
* This will force a re-render when the editor state changes.
|
|
92
|
-
* This is to support things like `editor.can().toggleBold()` in components that `useEditor`.
|
|
93
|
-
* This could be more efficient, but it's a good trade-off for now.
|
|
94
|
-
*/
|
|
95
|
-
const fn = () => {
|
|
96
|
-
this.transactionNumber += 1
|
|
97
|
-
this.subscribers.forEach(callback => callback())
|
|
33
|
+
function makeEditorStateInstance<TEditor extends Editor | null = Editor | null>(initialEditor: TEditor) {
|
|
34
|
+
let transactionNumber = 0
|
|
35
|
+
let lastTransactionNumber = 0
|
|
36
|
+
let lastSnapshot: EditorStateSnapshot<TEditor> = { editor: initialEditor, transactionNumber: 0 }
|
|
37
|
+
let editor = initialEditor
|
|
38
|
+
const subscribers = new Set<() => void>()
|
|
39
|
+
|
|
40
|
+
const editorInstance = {
|
|
41
|
+
/**
|
|
42
|
+
* Get the current editor instance.
|
|
43
|
+
*/
|
|
44
|
+
getSnapshot(): EditorStateSnapshot<TEditor> {
|
|
45
|
+
if (transactionNumber === lastTransactionNumber) {
|
|
46
|
+
return lastSnapshot
|
|
98
47
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
48
|
+
lastTransactionNumber = transactionNumber
|
|
49
|
+
lastSnapshot = { editor, transactionNumber }
|
|
50
|
+
return lastSnapshot
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Always disable the editor on the server-side.
|
|
54
|
+
*/
|
|
55
|
+
getServerSnapshot(): EditorStateSnapshot<null> {
|
|
56
|
+
return { editor: null, transactionNumber: 0 }
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Subscribe to the editor instance's changes.
|
|
60
|
+
*/
|
|
61
|
+
subscribe(callback: () => void) {
|
|
62
|
+
subscribers.add(callback)
|
|
103
63
|
return () => {
|
|
104
|
-
|
|
64
|
+
subscribers.delete(callback)
|
|
105
65
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Watch the editor instance for changes.
|
|
69
|
+
*/
|
|
70
|
+
watch(nextEditor: Editor | null) {
|
|
71
|
+
editor = nextEditor as TEditor
|
|
72
|
+
|
|
73
|
+
if (editor) {
|
|
74
|
+
/**
|
|
75
|
+
* This will force a re-render when the editor state changes.
|
|
76
|
+
* This is to support things like `editor.can().toggleBold()` in components that `useEditor`.
|
|
77
|
+
* This could be more efficient, but it's a good trade-off for now.
|
|
78
|
+
*/
|
|
79
|
+
const fn = () => {
|
|
80
|
+
transactionNumber += 1
|
|
81
|
+
subscribers.forEach(callback => callback())
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const currentEditor = editor
|
|
85
|
+
|
|
86
|
+
currentEditor.on('transaction', fn)
|
|
87
|
+
return () => {
|
|
88
|
+
currentEditor.off('transaction', fn)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
109
92
|
}
|
|
93
|
+
|
|
94
|
+
return editorInstance
|
|
110
95
|
}
|
|
111
96
|
|
|
112
97
|
export function useEditorState<TSelectorResult>(
|
|
@@ -119,7 +104,7 @@ export function useEditorState<TSelectorResult>(
|
|
|
119
104
|
export function useEditorState<TSelectorResult>(
|
|
120
105
|
options: UseEditorStateOptions<TSelectorResult, Editor> | UseEditorStateOptions<TSelectorResult, Editor | null>,
|
|
121
106
|
): TSelectorResult | null {
|
|
122
|
-
const [editorInstance] = useState(() =>
|
|
107
|
+
const [editorInstance] = useState(() => makeEditorStateInstance(options.editor))
|
|
123
108
|
|
|
124
109
|
// Using the `useSyncExternalStore` hook to sync the editor instance with the component state
|
|
125
110
|
const selectedState = useSyncExternalStoreWithSelector(
|
|
@@ -132,7 +117,7 @@ export function useEditorState<TSelectorResult>(
|
|
|
132
117
|
|
|
133
118
|
useEffect(() => {
|
|
134
119
|
return editorInstance.watch(options.editor)
|
|
135
|
-
}, [options.editor
|
|
120
|
+
}, [options.editor])
|
|
136
121
|
|
|
137
122
|
useDebugValue(selectedState)
|
|
138
123
|
|