@tiptap/react 3.0.0-beta.5 → 3.0.0-beta.7

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.
@@ -1,5 +1,13 @@
1
1
  import type { Editor } from '@tiptap/core'
2
- import React from 'react'
2
+ import type {
3
+ ComponentClass,
4
+ ForwardRefExoticComponent,
5
+ FunctionComponent,
6
+ PropsWithoutRef,
7
+ ReactNode,
8
+ RefAttributes,
9
+ } from 'react'
10
+ import { version as reactVersion } from 'react'
3
11
  import { flushSync } from 'react-dom'
4
12
 
5
13
  import type { EditorWithContentComponent } from './Editor.js'
@@ -22,6 +30,26 @@ function isForwardRefComponent(Component: any) {
22
30
  return !!(typeof Component === 'object' && Component.$$typeof?.toString() === 'Symbol(react.forward_ref)')
23
31
  }
24
32
 
33
+ /**
34
+ * Check if we're running React 19+ by detecting if function components support ref props
35
+ * @returns {boolean}
36
+ */
37
+ function isReact19Plus(): boolean {
38
+ // React 19 is detected by checking React version if available
39
+ // In practice, we'll use a more conservative approach and assume React 18 behavior
40
+ // unless we can definitively detect React 19
41
+ try {
42
+ // @ts-ignore
43
+ if (reactVersion) {
44
+ const majorVersion = parseInt(reactVersion.split('.')[0], 10)
45
+ return majorVersion >= 19
46
+ }
47
+ } catch {
48
+ // Fallback to React 18 behavior if we can't determine version
49
+ }
50
+ return false
51
+ }
52
+
25
53
  export interface ReactRendererOptions {
26
54
  /**
27
55
  * The editor instance.
@@ -53,9 +81,9 @@ export interface ReactRendererOptions {
53
81
  }
54
82
 
55
83
  type ComponentType<R, P> =
56
- | React.ComponentClass<P>
57
- | React.FunctionComponent<P>
58
- | React.ForwardRefExoticComponent<React.PropsWithoutRef<P> & React.RefAttributes<R>>
84
+ | ComponentClass<P>
85
+ | FunctionComponent<P>
86
+ | ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<R>>
59
87
 
60
88
  /**
61
89
  * The ReactRenderer class. It's responsible for rendering React components inside the editor.
@@ -79,7 +107,7 @@ export class ReactRenderer<R = unknown, P extends Record<string, any> = object>
79
107
 
80
108
  props: P
81
109
 
82
- reactElement: React.ReactNode
110
+ reactElement: ReactNode
83
111
 
84
112
  ref: R | null = null
85
113
 
@@ -120,14 +148,32 @@ export class ReactRenderer<R = unknown, P extends Record<string, any> = object>
120
148
  const props = this.props
121
149
  const editor = this.editor as EditorWithContentComponent
122
150
 
123
- if (isClassComponent(Component) || isForwardRefComponent(Component)) {
124
- // @ts-ignore This is a hack to make the ref work
125
- props.ref = (ref: R) => {
126
- this.ref = ref
151
+ // Handle ref forwarding with React 18/19 compatibility
152
+ const isReact19 = isReact19Plus()
153
+ const isClassComp = isClassComponent(Component)
154
+ const isForwardRefComp = isForwardRefComponent(Component)
155
+
156
+ const elementProps = { ...props }
157
+
158
+ if (!elementProps.ref) {
159
+ if (isReact19) {
160
+ // React 19: ref is a standard prop for all components
161
+ // @ts-ignore - Setting ref prop for React 19 compatibility
162
+ elementProps.ref = (ref: R) => {
163
+ this.ref = ref
164
+ }
165
+ } else if (isClassComp || isForwardRefComp) {
166
+ // React 18 and prior: only set ref for class components and forwardRef components
167
+ // @ts-ignore - Setting ref prop for React 18 class/forwardRef components
168
+ elementProps.ref = (ref: R) => {
169
+ this.ref = ref
170
+ }
127
171
  }
172
+ // For function components in React 18, we can't use ref - the component won't receive it
173
+ // This is a limitation we have to accept for React 18 function components without forwardRef
128
174
  }
129
175
 
130
- this.reactElement = <Component {...props} />
176
+ this.reactElement = <Component {...elementProps} />
131
177
 
132
178
  editor?.contentComponent?.setRenderer(this.id, this)
133
179
  }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export * from './NodeViewWrapper.js'
5
5
  export * from './ReactMarkViewRenderer.js'
6
6
  export * from './ReactNodeViewRenderer.js'
7
7
  export * from './ReactRenderer.js'
8
+ export * from './types.js'
8
9
  export * from './useEditor.js'
9
10
  export * from './useEditorState.js'
10
11
  export * from './useReactNodeView.js'
package/src/types.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { NodeViewProps as CoreNodeViewProps } from '@tiptap/core'
2
+ import type React from 'react'
3
+
4
+ export type ReactNodeViewProps<T = HTMLElement> = CoreNodeViewProps & {
5
+ ref: React.RefObject<T | null>
6
+ }