@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.
@@ -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
- class EditorStateManager<TEditor extends Editor | null = Editor | null> {
34
- private transactionNumber = 0
35
-
36
- private lastTransactionNumber = 0
37
-
38
- private lastSnapshot: EditorStateSnapshot<TEditor>
39
-
40
- private editor: TEditor
41
-
42
- private subscribers = new Set<() => void>()
43
-
44
- constructor(initialEditor: TEditor) {
45
- this.editor = initialEditor
46
- this.lastSnapshot = { editor: initialEditor, transactionNumber: 0 }
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
- const currentEditor = this.editor
101
-
102
- currentEditor.on('transaction', fn)
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
- currentEditor.off('transaction', fn)
64
+ subscribers.delete(callback)
105
65
  }
106
- }
107
-
108
- return undefined
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(() => new EditorStateManager(options.editor))
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, editorInstance])
120
+ }, [options.editor])
136
121
 
137
122
  useDebugValue(selectedState)
138
123