11import * as React from 'react' ;
2- import * as PropTypes from 'prop-types ' ;
2+ import { ReactElement } from 'react ' ;
33import cn from 'classnames' ;
44
55import { computeLineInformation , DiffInformation , DiffMethod , DiffType , LineInformation , } from './compute-lines' ;
66import computeStyles , { ReactDiffViewerStyles , ReactDiffViewerStylesOverride , } from './styles' ;
7- import { ReactElement } from "react" ;
8- import { computeHiddenBlocks } from "./compute-hidden-blocks" ;
7+ import { Block , computeHiddenBlocks } from "./compute-hidden-blocks" ;
98import IntrinsicElements = React . JSX . IntrinsicElements ;
9+ import { Expand } from "./expand" ;
10+ import { Fold } from "./fold" ;
1011
1112const m = require ( 'memoize-one' ) ;
1213
@@ -69,6 +70,10 @@ export interface ReactDiffViewerProps {
6970 styles ?: ReactDiffViewerStylesOverride ;
7071 // Use dark theme.
7172 useDarkTheme ?: boolean ;
73+ /**
74+ * Used to describe the thing being diffed
75+ */
76+ summary ?: string | ReactElement ;
7277 // Title for left column
7378 leftTitle ?: string | ReactElement ;
7479 // Title for left column
@@ -519,7 +524,7 @@ class DiffViewer extends React.Component<
519524 /**
520525 * Generates the entire diff view.
521526 */
522- private renderDiff = ( ) : { leftLines : ReactElement [ ] , rightLines : ReactElement [ ] } => {
527+ private renderDiff = ( ) : { leftLines : ReactElement [ ] , rightLines : ReactElement [ ] , lineInformation : LineInformation [ ] , blocks : Block [ ] } => {
523528 const {
524529 oldValue,
525530 newValue,
@@ -577,7 +582,7 @@ class DiffViewer extends React.Component<
577582 rightLines . push ( ...right )
578583 } ,
579584 ) ;
580- return { leftLines, rightLines} ;
585+ return { leftLines, rightLines, lineInformation , blocks } ;
581586 } ;
582587
583588 public render = ( ) : ReactElement => {
@@ -600,36 +605,67 @@ class DiffViewer extends React.Component<
600605
601606 this . styles = this . computeStyles ( this . props . styles , useDarkTheme , nonce ) ;
602607 const nodes = this . renderDiff ( ) ;
603- const colSpanOnSplitView = hideLineNumbers ? 2 : 3 ;
604- const colSpanOnInlineView = hideLineNumbers ? 2 : 4 ;
605- let columnExtension = this . props . renderGutter ? 1 : 0 ;
606-
607- console . log ( nodes . rightLines )
608+ let deletions = 0 , additions = 0
609+ nodes . lineInformation . forEach ( ( l ) => {
610+ if ( l . left . type === DiffType . ADDED ) {
611+ additions ++
612+ }
613+ if ( l . right . type === DiffType . ADDED ) {
614+ additions ++
615+ }
616+ if ( l . left . type === DiffType . REMOVED ) {
617+ deletions ++
618+ }
619+ if ( l . right . type === DiffType . REMOVED ) {
620+ deletions ++
621+ }
622+ } )
623+ const totalChanges = deletions + additions
624+
625+ const percentageAddition = Math . round ( ( additions / totalChanges ) * 100 )
626+ const blocks : ReactElement [ ] = [ ]
627+ for ( let i = 0 ; i < 5 ; i ++ ) {
628+ if ( percentageAddition > i * 20 ) {
629+ blocks . push ( < span key = { i } className = { cn ( this . styles . block , this . styles . blockAddition ) } /> )
630+ } else {
631+ blocks . push ( < span key = { i } className = { cn ( this . styles . block , this . styles . blockDeletion ) } /> )
632+ }
633+ }
634+ const allExpanded = this . state . expandedBlocks . length === nodes . blocks . length
608635
609636 return (
610- < div
611- className = { cn ( this . styles . diffContainer , {
612- [ this . styles . splitView ] : splitView ,
613- } ) }
614- >
615- < div className = { this . styles . column } role = { 'table' } title = { `Diff information for ${ leftTitle } ` } >
616- < div
617- className = { cn ( this . styles . titleBlock , this . styles . column ) }
618- role = { 'columnheader' }
619- >
620- < pre className = { this . styles . contentText } > { leftTitle } </ pre >
621- </ div >
622- { nodes . leftLines }
637+ < div >
638+ < div className = { this . styles . summary } role = { 'banner' } >
639+ < a style = { { cursor : 'pointer' } } onClick = { ( ) => {
640+ this . setState ( {
641+ expandedBlocks : allExpanded ? [ ] : nodes . blocks . map ( b => b . index )
642+ } )
643+ } } > { allExpanded ? < Fold /> : < Expand /> } </ a > { totalChanges } < div style = { { display : 'flex' , gap : '1px' } } > { blocks } </ div > { this . props . summary ? < span > { this . props . summary } </ span > : null }
623644 </ div >
624- { nodes . rightLines . length > 0 ? < div className = { this . styles . column } role = { 'table' } title = { `Diff information for ${ rightTitle } ` } >
625- < div
626- className = { cn ( this . styles . titleBlock , this . styles . column ) }
627- role = { 'columnheader' }
628- >
629- < pre className = { this . styles . contentText } > { rightTitle } </ pre >
645+ < div
646+ className = { cn ( this . styles . diffContainer , {
647+ [ this . styles . splitView ] : splitView ,
648+ } ) }
649+ >
650+ < div className = { this . styles . column } role = { 'table' } title = { `Diff information for ${ leftTitle } ` } >
651+ { leftTitle ? < div
652+ className = { cn ( this . styles . titleBlock , this . styles . column ) }
653+ role = { 'columnheader' }
654+ >
655+ < pre className = { this . styles . contentText } > { leftTitle } </ pre >
656+ </ div > : null }
657+ { nodes . leftLines }
630658 </ div >
631- { nodes . rightLines }
632- </ div > : null }
659+ { nodes . rightLines . length > 0 ? < div className = { this . styles . column } role = { 'table' } title = { `Diff information for ${ rightTitle } ` } >
660+ { rightTitle ? < div
661+ className = { cn ( this . styles . titleBlock , this . styles . column ) }
662+ role = { 'columnheader' }
663+ >
664+ < pre className = { this . styles . contentText } > { rightTitle } </ pre >
665+ </ div > : null }
666+ { nodes . rightLines }
667+ </ div > : null }
668+ </ div >
633669 </ div >
634670 ) ;
635671 } ;
0 commit comments