File size: 2,054 Bytes
60f878e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 = (
      <Text

        {...props}

        afterInit={(editor) => {

          currentEditor = editor as ReactEditor;

          props.afterInit && props.afterInit(editor);

        }}

      ></Text>
    );
    root.render(text);
    let newProps = { ...props };
    const ref: RenderComponentRef<TextProps> = {
      destroy: () => {
        setTimeout(() => {
          root.unmount();
        }, 0);
      },
      update: (updatedProps: Partial<TextProps>) => {
        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(<Text {...newProps}></Text>);

        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;
};