Path: blob/master/src/packages/frontend/editors/slate/slate-react/components/slate.tsx
1698 views
import React from "react";1import { useMemo, useState, useCallback, useEffect } from "react";2import { Descendant } from "slate";34import { ReactEditor } from "../plugin/react-editor";5import { FocusedContext } from "../hooks/use-focused";6import { EditorContext } from "../hooks/use-slate-static";7import { SlateContext } from "../hooks/use-slate";8import { EDITOR_TO_ON_CHANGE } from "../utils/weak-maps";910/**11* A wrapper around the provider to handle `onChange` events, because the editor12* is a mutable singleton so it won't ever register as "changed" otherwise.13*/1415export const Slate = (props: {16editor: ReactEditor;17value: Descendant[];18children: React.ReactNode;19onChange: (value: Descendant[]) => void;20}) => {21const { editor, children, onChange, value, ...rest } = props;22const [ticks, setTick] = useState(0);2324const context: [ReactEditor] = useMemo(() => {25editor.children = value;26editor.ticks = ticks;27Object.assign(editor, rest);28return [editor];29}, [ticks, value, ...Object.values(rest)]);3031// We use a singleton object for the focused context..32// It turns out not doing this with these contexts makes slate33// **insanely slow** on large documents. Doing this, and it34// is VERY fast. It probably took over a month of my life to35// understand this, so please don't mess it up again!36const focused: { isFocused: boolean } = useMemo(() => {37return { isFocused: ReactEditor.isFocused(editor) };38}, []);39focused.isFocused = ReactEditor.isFocused(editor);4041const onContextChange = useCallback(() => {42onChange(editor.children);43setTick(ticks + 1);44}, [ticks, onChange]);4546EDITOR_TO_ON_CHANGE.set(editor, onContextChange);4748useEffect(() => {49return () => {50EDITOR_TO_ON_CHANGE.set(editor, () => {});51};52}, []);5354return (55<SlateContext.Provider value={context}>56<EditorContext.Provider value={editor}>57<FocusedContext.Provider value={focused}>58{children}59</FocusedContext.Provider>60</EditorContext.Provider>61</SlateContext.Provider>62);63};646566