# ProseMirror React View

This library is a full React implementation of the official [prosemirror-view](https://github.com/ProseMirror/prosemirror-view) package. Aims to implement a simple React Component that uses ProseMirror Data Model to render the document and bind the right events to synchronize the user selection and created ProseMirror transaction based on user inputs.

## TODO

* Support of decorations
* Improve selection synchronization to support block nodes and decorations.
* Add Cypress tests, tried but I was getting a bug of high CPU.

## Components

### Renderer

#### Usage

```typescript
import { Node as ProseMirrorNode } from 'prosemirror-model';
import { Renderer, SchemaDOMSerializer, DecorationSet } from 'prosemirror-react-view';

interface Props {
  node: ProseMirrorNode,
  decorations: DecorationSet,
}

const MyRenderer: React.FC<Props> = ({ doc, decorations }) => {
  return (
    <SchemaDOMSerializer schema={mySchema} plugins={myPlugins}>
    	<Renderer doc={doc} decorations={decorations} />
    </SchemaDOMSerializer>
  )
}
```

### Editor

#### Usage

```typescript
import { Editor } from 'prosemirror-react-view';

interface Props {
  onChange(node: ProseMirrorNode): void
}

const MyEditor: React.FC<Props> = ({ onChange }) => {
  return (
    <Editor 
      schema={mySchema} 
      initialDoc={doc} 
      plugins={myPlugins} 
      onChange={onChange}
    />
   )
}
```

## Advance Usage

```typescript
import {
  Renderer,
  Editor,
  Editable
  DomSerializer,
  DOMSerializerContext,
  useEditorState,
  useEditorView,
} from 'prosemirror-react-view';

class CustomSerializer implements DomSerializer {
  // implement
}

const MyToolbar: React.FC = () => {
  const toolbarState = useEditorState(editorState => editorState.toolbarState);
  const editorView = useEditorView();
  
  return <Toolbar toolbar={toolbarState} editorView={editorView} />;
}

const CustomRenderer: React.FC = () => {
  // Create my custom serializer instance
  const customSerializer = useMemo(() => new CustomSerializer(), []);
  
  // Extract my doc and my decorations from the ProseMirror Editor State
  const doc = useEditorState(editorState => editorState.doc);
  const decorations = useEditorState(editorState => editorState.decorations);

  return (
    <DOMSerializerContext value={customSerializer}>
      <Renderer doc={doc} decorations={decorations} />			
    </DOMSerializerContext>
  );
}

const MyAdvanceEditor: React.FC = () => {
  return (
    <Editor schema={mySchema} plugins={myPlugins}>
    	<MyToolbar />
    	<Editable>
          <CustomRenderer/>
    	</Editable>
    </Editor>
  );
}
```

## Thanks

This project is highly inspired by these two projects:

* [ProseMirror View](https://github.com/ProseMirror/prosemirror-view): The official library to render ProseMirror Editor, it covers a lot of border cases and makes easy to understand the best approach to calculate selection, also contains a lot of the core functionaly that this library needs to implement.
* [Slate](https://github.com/ianstormtaylor/slate): A great project with great ideas. It helped me to understand the best approach to trigger/capture events in React. Most of the logic around synchronize selection and `beforeInput` strategy were based on this implementations.
