66 getMaxLengthToIgnoreLineDiff ,
77 changeMaxLengthToIgnoreLineDiff ,
88} from "@git-diff-view/react" ;
9- import { useMantineColorScheme , Code , Button , Switch , NumberInput , Tooltip } from "@mantine/core" ;
9+ import { useMantineColorScheme , Code , Button , Switch , NumberInput , Tooltip , Divider , Collapse } from "@mantine/core" ;
1010import { useCallbackRef } from "@mantine/hooks" ;
1111import { debounce } from "lodash" ;
1212import { useState , useCallback , useEffect , useMemo } from "react" ;
@@ -48,6 +48,14 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
4848
4949 const [ ignoreWhiteSpace , setIgnoreWhiteSpace ] = useState ( false ) ;
5050
51+ const [ rangeDiffInstance , setRangeDiffInstance ] = useState < DiffFile > ( ) ;
52+
53+ const [ rangeMode , setRangeMode ] = useState ( false ) ;
54+
55+ const [ start , setStart ] = useState ( 0 ) ;
56+
57+ const [ end , setEnd ] = useState ( 0 ) ;
58+
5159 const [ fastDiffTemplate , setFastDiffTemplate ] = useState ( getEnableFastDiffTemplate ( ) ) ;
5260
5361 const [ file1 , setFile1 ] = useState ( initialState . file1 ) ;
@@ -71,6 +79,10 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
7179
7280 const setDiffInstanceCb = useCallback (
7381 debounce ( ( lang1 , lang2 , file1 , file2 , ignoreWhiteSpace ) => {
82+ setRangeMode ( false ) ;
83+ setStart ( 0 ) ;
84+ setEnd ( 0 ) ;
85+ setRangeDiffInstance ( undefined ) ;
7486 if ( ! file1 && ! file2 ) {
7587 setDiffInstance ( undefined ) ;
7688 return ;
@@ -103,6 +115,12 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
103115 reloadDiffInstance ( ) ;
104116 } , [ fastDiffTemplate ] ) ;
105117
118+ useEffect ( ( ) => {
119+ if ( diffInstance && start && end ) {
120+ setRangeDiffInstance ( diffInstance . generateInstanceFromLineNumberRange ( start , end ) ) ;
121+ }
122+ } , [ diffInstance , start , end ] ) ;
123+
106124 const handleShare = useCallback ( async ( ) => {
107125 try {
108126 const success = await copyToClipboard ( window . location . href ) ;
@@ -121,11 +139,32 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
121139
122140 return (
123141 < div className = "m-auto mb-[1em] mt-[1em] w-[90%]" >
142+ < div className = "flex items-center gap-x-6" >
143+ < Button onClick = { onClick } > Go to `Git diff` mode</ Button >
144+ < Tooltip
145+ label = {
146+ shareStatus === "copied"
147+ ? "Copied!"
148+ : shareStatus === "error"
149+ ? "Failed to copy"
150+ : "Copy share URL to clipboard"
151+ }
152+ >
153+ < Button
154+ variant = { shareStatus === "copied" ? "filled" : "outline" }
155+ color = { shareStatus === "error" ? "red" : shareStatus === "copied" ? "green" : undefined }
156+ onClick = { handleShare }
157+ >
158+ { shareStatus === "copied" ? "Copied!" : shareStatus === "error" ? "Error" : "Share" }
159+ </ Button >
160+ </ Tooltip >
161+ </ div >
162+ < Divider className = "my-2" />
124163 < h2 className = "flex flex-wrap gap-x-8 gap-y-4 text-[24px]" >
125164 < span >
126- < Code className = "text-[24px]" > File diff</ Code > mode
165+ < Code className = "text-[24px] font-medium " > File diff</ Code > mode
127166 </ span >
128- < div className = "inline-flex gap-x-2 text-[14px]" >
167+ { /* <div className="inline-flex gap-x-2 text-[14px]">
129168 <Button onClick={onClick}>Go to `Git diff` mode</Button>
130169 <Tooltip
131170 label={
@@ -144,7 +183,7 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
144183 {shareStatus === "copied" ? "Copied!" : shareStatus === "error" ? "Error" : "Share"}
145184 </Button>
146185 </Tooltip>
147- </ div >
186+ </div> */ }
148187 < div className = "inline-flex items-center gap-x-4" >
149188 < Switch
150189 checked = { ignoreWhiteSpace }
@@ -156,6 +195,11 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
156195 onChange = { ( e ) => setFastDiffTemplate ( e . target . checked ) }
157196 label = "Fast Diff Template (better line diff)"
158197 />
198+ < Switch
199+ checked = { rangeMode }
200+ onChange = { ( e ) => setRangeMode ( e . target . checked ) }
201+ label = "RangeMode (show part of diff)"
202+ />
159203 < Tooltip label = "Ignore line diff when line length over this value" >
160204 < NumberInput
161205 value = { getMaxLengthToIgnoreLineDiff ( ) }
@@ -169,6 +213,28 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
169213 </ Tooltip >
170214 </ div >
171215 </ h2 >
216+ < Collapse in = { rangeMode } >
217+ < div className = "flex items-center gap-x-6 py-2" >
218+ < NumberInput
219+ value = { start }
220+ min = { 0 }
221+ label = "Range Start"
222+ max = { diffInstance ?. splitLineLength }
223+ onChange = { ( n ) => {
224+ setStart ( Number ( n ) ) ;
225+ } }
226+ />
227+ < NumberInput
228+ value = { end }
229+ min = { 0 }
230+ label = "Range End"
231+ max = { diffInstance ?. splitLineLength }
232+ onChange = { ( n ) => {
233+ setEnd ( Number ( n ) ) ;
234+ } }
235+ />
236+ </ div >
237+ </ Collapse >
172238 < div className = "mt-[10px] flex gap-x-[10px]" >
173239 < div className = "flex w-[50%] flex-col gap-y-[10px]" >
174240 < span className = "border-color border-b p-[3px]" > Lang: </ span >
@@ -195,10 +261,10 @@ export const PlayGroundFileDiff = ({ onClick }: { onClick: () => void }) => {
195261 </ div >
196262 </ div >
197263
198- { diffInstance ? (
264+ { ( rangeMode ? rangeDiffInstance : diffInstance ) ? (
199265 < DiffView < string >
200266 className = "border-color mt-[10px] overflow-hidden rounded-[4px] border"
201- diffFile = { diffInstance }
267+ diffFile = { ( rangeMode ? rangeDiffInstance : diffInstance ) ! }
202268 diffViewFontSize = { 13 }
203269 diffViewTheme = { colorScheme === "dark" ? "dark" : "light" }
204270 diffViewHighlight = { true }
0 commit comments