Skip to content

Commit

Permalink
fix(merge): fix onChange issue. (#566)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Sep 21, 2023
1 parent 92c4abe commit b84b763
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 3 deletions.
105 changes: 105 additions & 0 deletions example/nextjs/src/app/merg/_editor/Com.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
'use client';

import { Fragment, useRef, useState } from 'react';
import CodeMirrorMerge, { CodeMirrorMergeProps } from 'react-codemirror-merge';
import { langs } from '@uiw/codemirror-extensions-langs';
import { originalCode, modifiedCode } from './code';

const Original = CodeMirrorMerge.Original;
const Modified = CodeMirrorMerge.Modified;

export const MergeExample = () => {
const [orientation, setOrientation] = useState<CodeMirrorMergeProps['orientation']>('a-b');
const [revertControls, setRevertControls] = useState<CodeMirrorMergeProps['revertControls']>();
const [highlightChanges, setHighlightChanges] = useState<CodeMirrorMergeProps['highlightChanges']>(true);
const [gutter, setGutter] = useState<CodeMirrorMergeProps['gutter']>(true);
const [collapseUnchanged, setCollapseUnchanged] = useState<CodeMirrorMergeProps['collapseUnchanged']>();
const handleOrientation = (evn: React.ChangeEvent<HTMLSelectElement>) => {
setOrientation(evn.target.value as CodeMirrorMergeProps['orientation']);
};
const [originalValue, setOriginalValue] = useState(originalCode);
const [modifiedValue, setModifiedValue] = useState(modifiedCode);
const random = useRef<number>();
const click = () => {
random.current = Math.floor(Math.random() * 101);
const code = '// hello world' + random.current + '\n' + originalCode;
setOriginalValue(code);
};
return (
<Fragment>
<button onClick={click}>Change Original Value {random.current}</button>
<CodeMirrorMerge
orientation={orientation}
revertControls={revertControls}
collapseUnchanged={collapseUnchanged}
highlightChanges={highlightChanges}
// destroyRerender={false}
gutter={gutter}
style={{ height: 300, overflow: 'auto' }}
theme="dark"
>
<Original
value={originalValue}
extensions={[langs.javascript()]}
onChange={(val) => {
setOriginalValue(val);
// console.log('::::::::::', val)
}}
/>
<Modified
value={modifiedValue}
extensions={[
langs.javascript(),
// EditorView.editable.of(false),
// EditorState.readOnly.of(true)
]}
onChange={(val) => {
setModifiedValue(val);
}}
/>
</CodeMirrorMerge>
<label>
Orientation
<select onChange={handleOrientation} defaultValue={orientation}>
<option value="">please orientation choose</option>
<option value="a-b">a-b</option>
<option value="b-a">b-a</option>
</select>
</label>
<br />
<label>
Revert buttons
<select
defaultValue={revertControls}
onChange={(evn) => setRevertControls(evn.target.value as CodeMirrorMergeProps['revertControls'])}
>
<option value="">please revertControls choose</option>
<option value="a-to-b">a-to-b</option>
<option value="b-to-a">b-to-a</option>
</select>
</label>
<br />
<label>
Highlight changes
<input
type="checkbox"
checked={!!highlightChanges}
onChange={(evn) => setHighlightChanges(evn.target.checked)}
/>
</label>
<br />
<label>
Gutter markers
<input type="checkbox" checked={!!gutter} onChange={(evn) => setGutter(evn.target.checked)} />
</label>
<label>
Collapse unchanged code
<input
type="checkbox"
checked={!!collapseUnchanged}
onChange={(evn) => setCollapseUnchanged(evn.target.checked ? {} : undefined)}
/>
</label>
</Fragment>
);
};
74 changes: 74 additions & 0 deletions example/nextjs/src/app/merg/_editor/code.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
export const originalCode = `// The player has a position, a size, and a current speed.
class Player {
size = new Vec(0.8, 1.5);
constructor(pos, speed) {
this.pos = pos;
this.speed = speed;
}
static create(pos) {
return new Player(pos.plus(new Vec(0, -0.5)), new Vec(0, 0));
}
}
// Lava block. When you touch it, you die.
class Lava {
size = new Vec(1, 1)
constructor(pos, speed, reset) {
this.pos = pos;
this.speed = speed;
this.reset = reset;
}
static horizontal(pos) {
return new Lava(pos, new Vec(2, 0));
}
static vertical(pos) {
return new Lava(pos, new Vec(0, 2));
}
static drip(pos) {
return new Lava(pos, new Vec(0, 3), pos);
}
}
`;

export const modifiedCode = `class Player {
get type() { return "player" }
constructor(pos, speed) {
this.pos = pos;
this.speed = speed;
}
static create(pos) {
return new Player(pos.plus(new Vec(0, -0.5)), new Vec(0, 0));
}
}
class Lava {
constructor(pos, speed, reset) {
this.pos = pos;
this.speed = speed;
this.reset = reset;
}
get type() { return "lava"; }
static create(pos, ch) {
if (ch == "=") {
return new Lava(pos, new Vec(2, 0));
} else if (ch == "|") {
return new Lava(pos, new Vec(0, 2));
} else if (ch == "v") {
return new Lava(pos, new Vec(0, 3), pos);
}
}
}
Player.prototype.size = new Vec(0.8, 1.5);
Lava.prototype.size = new Vec(1, 1);
`;
40 changes: 40 additions & 0 deletions example/nextjs/src/app/merg/_editor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client';

import React, { useState } from 'react';
import CodeMirrorMerge from 'react-codemirror-merge';
import { abyss } from '@uiw/codemirror-theme-abyss';

const Original = CodeMirrorMerge.Original;
const Modified = CodeMirrorMerge.Modified;
let doc = `one
two
three
four
five`;

export default function Editor() {
const [value, setValue] = useState(doc);
const [valueModified, setValueModified] = useState(doc.replace(/t/g, 'T') + 'Six');
return (
<div>
<CodeMirrorMerge theme={abyss}>
<Original
value={value}
onChange={(value) => {
setValue(value);
}}
/>
<Modified
value={valueModified}
onChange={(value) => {
setValueModified(value);
}}
/>
</CodeMirrorMerge>
<div style={{ display: 'flex', marginTop: 10 }}>
<pre style={{ flex: 1 }}>{value} </pre>
<pre style={{ flex: 1 }}>{valueModified} </pre>
</div>
</div>
);
}
10 changes: 10 additions & 0 deletions example/nextjs/src/app/merg/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// import Editor from './_editor';
import { MergeExample } from './_editor/Com';

export default function Merg() {
return (
<div>
<MergeExample />
</div>
);
}
26 changes: 23 additions & 3 deletions merge/src/Internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
highlightChanges,
gutter,
collapseUnchanged,
destroyRerender,
destroyRerender = true,
renderRevertControl,
...elmProps
} = props;
Expand Down Expand Up @@ -96,8 +96,10 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
});
}
}
if (destroyRerender) {
view.current?.destroy();
if (destroyRerender && view.current) {
const originalFrom = view.current.a.state.selection.ranges[0].from;
const modifiedFrom = view.current.b.state.selection.ranges[0].from;
view.current.destroy();
view.current = new MergeView({
a: {
...original,
Expand All @@ -116,6 +118,24 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
parent: editor.current!,
...opts,
});
if (originalFrom) {
view.current.a.focus();
view.current.a.dispatch({
selection: {
anchor: originalFrom,
head: originalFrom,
},
});
}
if (modifiedFrom) {
view.current.b.focus();
view.current.b.dispatch({
selection: {
anchor: modifiedFrom,
head: modifiedFrom,
},
});
}
}
}, [view, theme, editor.current, original, modified, originalExtension, modifiedExtension, destroyRerender]);

Expand Down

0 comments on commit b84b763

Please sign in to comment.