import {
type PlaitTextBoard,
type RenderComponentRef,
type TextProps,
} from '@plait/common';
import type { PlaitBoard } from '@plait/core';
import { createRoot } from 'react-dom/client';
import { Text } from '@plait-board/react-text';
import { ReactEditor } from 'slate-react';
import type { ReactBoard } from './board';
export const withReact = (board: PlaitBoard & PlaitTextBoard) => {
const newBoard = board as PlaitBoard & PlaitTextBoard & ReactBoard;
newBoard.renderText = (
container: Element | DocumentFragment,
props: TextProps
) => {
const root = createRoot(container);
let currentEditor: ReactEditor;
const text = (
{
currentEditor = editor as ReactEditor;
props.afterInit && props.afterInit(editor);
}}
>
);
root.render(text);
let newProps = { ...props };
const ref: RenderComponentRef = {
destroy: () => {
setTimeout(() => {
root.unmount();
}, 0);
},
update: (updatedProps: Partial) => {
const hasUpdated =
updatedProps &&
newProps &&
!Object.keys(updatedProps).every(
(key) =>
updatedProps[key as keyof TextProps] ===
newProps[key as keyof TextProps]
);
if (!hasUpdated) {
return;
}
const readonly = ReactEditor.isReadOnly(currentEditor);
newProps = { ...newProps, ...updatedProps };
root.render();
if (readonly === true && newProps.readonly === false) {
setTimeout(() => {
ReactEditor.focus(currentEditor);
}, 0);
} else if (readonly === false && newProps.readonly === true) {
ReactEditor.blur(currentEditor);
ReactEditor.deselect(currentEditor);
}
},
};
return ref;
};
return newBoard;
};