diff --git a/merge/src/Internal.tsx b/merge/src/Internal.tsx index 1bc6b1bc2..3c5744208 100644 --- a/merge/src/Internal.tsx +++ b/merge/src/Internal.tsx @@ -1,10 +1,10 @@ import React, { useEffect, useImperativeHandle, useRef } from 'react'; -import { EditorStateConfig, StateEffect } from '@codemirror/state'; +import { EditorStateConfig } from '@codemirror/state'; import { getDefaultExtensions } from '@uiw/react-codemirror'; import { MergeView, MergeConfig, DirectMergeConfig } from '@codemirror/merge'; import { useStore } from './store'; import { CodeMirrorMergeProps } from './'; - +import { EditorView, ViewUpdate } from '@codemirror/view'; export interface InternalRef { container?: HTMLDivElement | null; view?: MergeView; @@ -48,14 +48,31 @@ export const Internal = React.forwardRef((pro [editor, view, modified, original, opts], ); + const originalUpdateListener = EditorView.updateListener.of((vu: ViewUpdate) => { + if (vu.docChanged && typeof originalExtension?.onChange === 'function') { + const doc = vu.state.doc; + const val = doc.toString(); + originalExtension?.onChange(val, vu); + } + }); + + const modifiedUpdateListener = EditorView.updateListener.of((vu: ViewUpdate) => { + if (vu.docChanged && typeof modifiedExtension?.onChange === 'function') { + const doc = vu.state.doc; + const val = doc.toString(); + modifiedExtension?.onChange(val, vu); + } + }); + useEffect(() => { - if (!view.current && editor.current) { + if (!view.current && editor.current && originalExtension && modifiedExtension) { view.current = new MergeView({ a: { ...original, extensions: [ ...(originalExtension?.extension || []), ...getDefaultExtensions({ ...originalExtension?.option, theme }), + originalUpdateListener, ], }, b: { @@ -63,13 +80,14 @@ export const Internal = React.forwardRef((pro extensions: [ ...(modifiedExtension?.extension || []), ...getDefaultExtensions({ ...modifiedExtension?.option, theme }), + modifiedUpdateListener, ], }, parent: editor.current, ...opts, }); } - }, [view, editor]); + }, [view, editor, originalExtension, modifiedExtension]); useEffect(() => { if (original && original.doc && view.current) { diff --git a/merge/src/Modified.tsx b/merge/src/Modified.tsx index f02913119..a16d42596 100644 --- a/merge/src/Modified.tsx +++ b/merge/src/Modified.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { getDefaultExtensions, DefaultExtensionsOptions } from '@uiw/react-codemirror'; import { EditorStateConfig, Extension } from '@codemirror/state'; -import { EditorView, ViewUpdate } from '@codemirror/view'; +import { ViewUpdate } from '@codemirror/view'; import { useStore } from './store'; export interface ModifiedProps extends Omit, Omit { @@ -15,30 +15,20 @@ export const Modified = (props: ModifiedProps): JSX.Element | null => { const { extensions = [], value, selection, onChange, ...otherOption } = props; const { theme, dispatch } = useStore(); const defaultExtensions = getDefaultExtensions({ ...otherOption, theme }); - const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => { - if (vu.docChanged && typeof onChange === 'function') { - const doc = vu.state.doc; - const val = doc.toString(); - onChange(val, vu); - } - }); - - useEffect( - () => - dispatch!({ - modified: { - doc: value, - selection: selection, - extensions: [updateListener, ...defaultExtensions, ...extensions], - }, - modifiedExtension: { - onChange, - option: otherOption, - extension: [updateListener, extensions], - }, - }), - [props], - ); + useEffect(() => { + dispatch!({ + modified: { + doc: value, + selection: selection, + extensions: [...defaultExtensions, ...extensions], + }, + modifiedExtension: { + onChange, + option: otherOption, + extension: [extensions], + }, + }); + }, [props]); return null; }; diff --git a/merge/src/Original.tsx b/merge/src/Original.tsx index 575ce32ed..455ec9893 100644 --- a/merge/src/Original.tsx +++ b/merge/src/Original.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { getDefaultExtensions, DefaultExtensionsOptions } from '@uiw/react-codemirror'; import { EditorStateConfig, Extension } from '@codemirror/state'; -import { EditorView, ViewUpdate } from '@codemirror/view'; +import { ViewUpdate } from '@codemirror/view'; import { useStore } from './store'; export interface OriginalProps extends Omit, Omit { @@ -15,13 +15,6 @@ export const Original = (props: OriginalProps): JSX.Element | null => { const { extensions = [], value, selection, onChange, ...otherOption } = props; const { theme, dispatch } = useStore(); const defaultExtensions = getDefaultExtensions({ ...otherOption, theme }); - const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => { - if (vu.docChanged && typeof onChange === 'function') { - const doc = vu.state.doc; - const val = doc.toString(); - onChange(val, vu); - } - }); useEffect( () => @@ -29,12 +22,12 @@ export const Original = (props: OriginalProps): JSX.Element | null => { original: { doc: value, selection: selection, - extensions: [updateListener, ...defaultExtensions, ...extensions], + extensions: [...defaultExtensions, ...extensions], }, originalExtension: { onChange, option: otherOption, - extension: [extensions, updateListener], + extension: [extensions], }, }), [props], diff --git a/www/src/pages/merge/examples/Example.md b/www/src/pages/merge/examples/Example.md index 908abbf12..9934cc205 100644 --- a/www/src/pages/merge/examples/Example.md +++ b/www/src/pages/merge/examples/Example.md @@ -13,22 +13,24 @@ four five`; export default function App() { - const [value, setValue] = useState(''); - const [valueModified, setValueModified] = useState(''); + const [value, setValue] = useState(doc); + const [valueModified, setValueModified] = useState(doc); return (
- + { - setValue(value); + onChange={(val) => { + console.log('~~:1', val); + setValue(val); }} - value={doc} + value={value} /> { - setValueModified(value); + onChange={(val) => { + console.log('~~:2', val); + setValueModified(val); }} - value={doc.replace(/t/g, 'T') + 'Six'} + value={valueModified} />