1- import { MergeView , unifiedMergeView } from "@codemirror/merge" ;
1+ import {
2+ acceptChunk ,
3+ MergeView ,
4+ rejectChunk ,
5+ unifiedMergeView ,
6+ } from "@codemirror/merge" ;
27import { EditorState , type Extension } from "@codemirror/state" ;
38import { EditorView } from "@codemirror/view" ;
49import { handleExternalAppAction } from "@utils/handleExternalAppAction" ;
@@ -19,8 +24,44 @@ interface DiffOptions extends UseCodeMirrorOptions {
1924 original : string ;
2025 modified : string ;
2126 mode : "split" | "unified" ;
27+ onContentChange ?: ( content : string ) => void ;
2228}
2329
30+ const createMergeControls = ( onReject ?: ( ) => void ) => {
31+ return ( type : "accept" | "reject" , action : ( e : MouseEvent ) => void ) => {
32+ if ( type === "accept" ) {
33+ return document . createElement ( "span" ) ;
34+ }
35+
36+ const button = document . createElement ( "button" ) ;
37+ button . textContent = "Reject" ;
38+ button . name = "reject" ;
39+ button . style . background = "var(--red-9)" ;
40+ button . style . color = "white" ;
41+ button . style . border = "none" ;
42+ button . style . padding = "2px 6px" ;
43+ button . style . borderRadius = "3px" ;
44+ button . style . cursor = "pointer" ;
45+ button . style . fontSize = "11px" ;
46+
47+ button . onmousedown = ( e ) => {
48+ action ( e ) ;
49+ onReject ?.( ) ;
50+ } ;
51+
52+ return button ;
53+ } ;
54+ } ;
55+
56+ const getBaseDiffConfig = (
57+ onReject ?: ( ) => void ,
58+ ) : Partial < Parameters < typeof unifiedMergeView > [ 0 ] > => ( {
59+ collapseUnchanged : { margin : 3 , minSize : 4 } ,
60+ highlightChanges : false ,
61+ gutter : true ,
62+ mergeControls : createMergeControls ( onReject ) ,
63+ } ) ;
64+
2465export function useCodeMirror ( options : SingleDocOptions | DiffOptions ) {
2566 const containerRef = useRef < HTMLDivElement > ( null ) ;
2667 const instanceRef = useRef < EditorInstance | null > ( null ) ;
@@ -40,21 +81,63 @@ export function useCodeMirror(options: SingleDocOptions | DiffOptions) {
4081 parent : containerRef . current ,
4182 } ) ;
4283 } else if ( options . mode === "split" ) {
84+ const diffConfig = getBaseDiffConfig (
85+ options . onContentChange
86+ ? ( ) => {
87+ if ( instanceRef . current instanceof MergeView ) {
88+ const content = instanceRef . current . b . state . doc . toString ( ) ;
89+ options . onContentChange ?.( content ) ;
90+ }
91+ }
92+ : undefined ,
93+ ) ;
94+
95+ const updateListener = options . onContentChange
96+ ? EditorView . updateListener . of ( ( update ) => {
97+ if (
98+ update . docChanged &&
99+ update . transactions . some ( ( tr ) => tr . isUserEvent ( "revert" ) )
100+ ) {
101+ const content = update . state . doc . toString ( ) ;
102+ options . onContentChange ?.( content ) ;
103+ }
104+ } )
105+ : [ ] ;
106+
43107 instanceRef . current = new MergeView ( {
44108 a : { doc : options . original , extensions : options . extensions } ,
45- b : { doc : options . modified , extensions : options . extensions } ,
109+ b : {
110+ doc : options . modified ,
111+ extensions : [
112+ ...options . extensions ,
113+ ...( Array . isArray ( updateListener )
114+ ? updateListener
115+ : [ updateListener ] ) ,
116+ ] ,
117+ } ,
118+ ...diffConfig ,
46119 parent : containerRef . current ,
120+ revertControls : "a-to-b" ,
47121 } ) ;
48122 } else {
123+ const diffConfig = getBaseDiffConfig (
124+ options . onContentChange
125+ ? ( ) => {
126+ if ( instanceRef . current instanceof EditorView ) {
127+ const content = instanceRef . current . state . doc . toString ( ) ;
128+ options . onContentChange ?.( content ) ;
129+ }
130+ }
131+ : undefined ,
132+ ) ;
133+
49134 instanceRef . current = new EditorView ( {
50135 doc : options . modified ,
51136 extensions : [
52137 ...options . extensions ,
53138 unifiedMergeView ( {
54139 original : options . original ,
55- highlightChanges : true ,
56- gutter : true ,
57- mergeControls : false ,
140+ ...diffConfig ,
58141 } ) ,
59142 ] ,
60143 parent : containerRef . current ,
@@ -95,3 +178,5 @@ export function useCodeMirror(options: SingleDocOptions | DiffOptions) {
95178
96179 return containerRef ;
97180}
181+
182+ export { acceptChunk , rejectChunk } ;
0 commit comments