Skip to content

Commit 743e8aa

Browse files
authored
fix: forward refs to the final component (#1485)
1 parent c8dc85e commit 743e8aa

File tree

1 file changed

+72
-64
lines changed

1 file changed

+72
-64
lines changed

packages/react/src/editor/BlockNoteView.tsx

+72-64
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ function BlockNoteViewComponent<
163163
className,
164164
editorColorScheme,
165165
contentEditableProps,
166-
ref,
167166
...rest,
168167
};
169168

@@ -176,7 +175,7 @@ function BlockNoteViewComponent<
176175
}}>
177176
<ElementRenderer ref={setElementRenderer} />
178177
{renderEditor ? (
179-
<BlockNoteViewEditor>{children}</BlockNoteViewEditor>
178+
<BlockNoteViewEditor ref={ref}>{children}</BlockNoteViewEditor>
180179
) : (
181180
children
182181
)}
@@ -199,73 +198,82 @@ export const BlockNoteViewRaw = React.forwardRef(BlockNoteViewComponent) as <
199198
/**
200199
* Renders the editor itself and the default UI elements
201200
*/
202-
export const BlockNoteViewEditor = (props: { children: ReactNode }) => {
203-
const ctx = useBlockNoteViewContext()!;
204-
const editor = useBlockNoteEditor();
201+
export const BlockNoteViewEditor = React.forwardRef(
202+
(props: { children: ReactNode }, ref: React.Ref<HTMLDivElement>) => {
203+
const ctx = useBlockNoteViewContext()!;
204+
const editor = useBlockNoteEditor();
205205

206-
const portalManager = useMemo(() => {
207-
return getContentComponent();
208-
}, []);
206+
const portalManager = useMemo(() => {
207+
return getContentComponent();
208+
}, []);
209209

210-
const mount = useCallback(
211-
(element: HTMLElement | null) => {
212-
editor.mount(element, portalManager);
213-
},
214-
[editor, portalManager]
215-
);
210+
const mount = useCallback(
211+
(element: HTMLElement | null) => {
212+
editor.mount(element, portalManager);
213+
},
214+
[editor, portalManager]
215+
);
216216

217-
return (
218-
<>
219-
<Portals contentComponent={portalManager} />
220-
<EditorElement {...ctx.editorProps} {...props} mount={mount}>
221-
{/* Renders the UI elements such as formatting toolbar, etc, unless they have been explicitly disabled in defaultUIProps */}
222-
<BlockNoteDefaultUI {...ctx.defaultUIProps} />
223-
{/* Manually passed in children, such as customized UI elements / controllers */}
224-
{props.children}
225-
</EditorElement>
226-
</>
227-
);
228-
};
217+
return (
218+
<>
219+
<Portals contentComponent={portalManager} />
220+
<EditorElement {...ctx.editorProps} {...props} mount={mount} ref={ref}>
221+
{/* Renders the UI elements such as formatting toolbar, etc, unless they have been explicitly disabled in defaultUIProps */}
222+
<BlockNoteDefaultUI {...ctx.defaultUIProps} />
223+
{/* Manually passed in children, such as customized UI elements / controllers */}
224+
{props.children}
225+
</EditorElement>
226+
</>
227+
);
228+
}
229+
);
229230

230231
/**
231232
* Renders the container div + contentEditable div.
232233
*/
233-
const EditorElement = (
234-
props: {
235-
className?: string;
236-
editorColorScheme?: string;
237-
autoFocus?: boolean;
238-
mount: (element: HTMLElement | null) => void;
239-
contentEditableProps?: Record<string, any>;
240-
children: ReactNode;
241-
ref?: React.Ref<HTMLDivElement>;
242-
} & HTMLAttributes<HTMLDivElement>
243-
) => {
244-
const {
245-
className,
246-
editorColorScheme,
247-
autoFocus,
248-
mount,
249-
children,
250-
contentEditableProps,
251-
...rest
252-
} = props;
253-
return (
254-
// The container wraps the contentEditable div and UI Elements such as sidebar, formatting toolbar, etc.
255-
<div
256-
className={mergeCSSClasses("bn-container", editorColorScheme, className)}
257-
data-color-scheme={editorColorScheme}
258-
{...rest}>
259-
{/* The actual contentEditable that Prosemirror mounts to */}
234+
const EditorElement = React.forwardRef(
235+
(
236+
props: {
237+
className?: string;
238+
editorColorScheme?: string;
239+
autoFocus?: boolean;
240+
mount: (element: HTMLElement | null) => void;
241+
contentEditableProps?: Record<string, any>;
242+
children: ReactNode;
243+
} & HTMLAttributes<HTMLDivElement>,
244+
ref: React.Ref<HTMLDivElement>
245+
) => {
246+
const {
247+
className,
248+
editorColorScheme,
249+
autoFocus,
250+
mount,
251+
children,
252+
contentEditableProps,
253+
...rest
254+
} = props;
255+
return (
256+
// The container wraps the contentEditable div and UI Elements such as sidebar, formatting toolbar, etc.
260257
<div
261-
aria-autocomplete="list"
262-
aria-haspopup="listbox"
263-
data-bn-autofocus={autoFocus}
264-
ref={mount}
265-
{...contentEditableProps}
266-
/>
267-
{/* The UI elements such as sidebar, formatting toolbar, etc. */}
268-
{children}
269-
</div>
270-
);
271-
};
258+
className={mergeCSSClasses(
259+
"bn-container",
260+
editorColorScheme,
261+
className
262+
)}
263+
data-color-scheme={editorColorScheme}
264+
{...rest}
265+
ref={ref}>
266+
{/* The actual contentEditable that Prosemirror mounts to */}
267+
<div
268+
aria-autocomplete="list"
269+
aria-haspopup="listbox"
270+
data-bn-autofocus={autoFocus}
271+
ref={mount}
272+
{...contentEditableProps}
273+
/>
274+
{/* The UI elements such as sidebar, formatting toolbar, etc. */}
275+
{children}
276+
</div>
277+
);
278+
}
279+
);

0 commit comments

Comments
 (0)