| 8 | const EDITABLE_TO_STORE = new WeakMap<Editable, UseBoundStore<StoreApi<EditableStore>>>() |
| 9 | |
| 10 | export const EditableProvider = (props: { |
| 11 | editor: Editable |
| 12 | value?: Descendant[] |
| 13 | children: React.ReactNode |
| 14 | onChange?: (value: Descendant[]) => void |
| 15 | }) => { |
| 16 | const { |
| 17 | editor, |
| 18 | children, |
| 19 | value = [{ type: 'paragraph', children: [{ text: '' }] }], |
| 20 | onChange, |
| 21 | ...rest |
| 22 | } = props |
| 23 | |
| 24 | const store = React.useMemo(() => { |
| 25 | const store = EDITABLE_TO_STORE.get(editor) |
| 26 | if (store) { |
| 27 | return store |
| 28 | } |
| 29 | if (!Node.isNodeList(value)) { |
| 30 | throw new Error( |
| 31 | `[Editable] value is invalid! Expected a list of elements` + |
| 32 | `but got: ${Scrubber.stringify(value)}`, |
| 33 | ) |
| 34 | } |
| 35 | if (!Editor.isEditor(editor)) { |
| 36 | throw new Error(`[Editable] editor is invalid! you passed:` + `${Scrubber.stringify(editor)}`) |
| 37 | } |
| 38 | editor.children = value |
| 39 | Object.assign(editor, rest) |
| 40 | const newStore = create<EditableStore>(() => ({ |
| 41 | editor: [editor], |
| 42 | })) |
| 43 | EDITABLE_TO_STORE.set(editor, newStore) |
| 44 | editor.normalizeNode([editor, []]) |
| 45 | return newStore |
| 46 | }, [editor, value, rest]) |
| 47 | |
| 48 | useIsomorphicLayoutEffect(() => { |
| 49 | const handleChange = () => { |
| 50 | if (onChange) { |
| 51 | onChange(editor.children) |
| 52 | } |
| 53 | store.setState({ |
| 54 | editor: [editor], |
| 55 | }) |
| 56 | } |
| 57 | editor.on('change', handleChange) |
| 58 | return () => { |
| 59 | editor.off('change', handleChange) |
| 60 | } |
| 61 | }, [editor, onChange]) |
| 62 | |
| 63 | return ( |
| 64 | <EditableStoreContext.Provider |
| 65 | value={{ |
| 66 | store, |
| 67 | editor, |