import React , { Component } from 'react' ; import PropTypes from 'prop-types' ; import styled from 'styled-components' ; import CodeMirror , { EditorChange } from 'codemirror' ; import { Base16Theme } from 'base16' ; import { defaultStyle , themedStyle } from './styles' ; import { Theme } from '../themes/default' ; import 'codemirror/mode/javascript/javascript' ; import 'codemirror/addon/fold/foldgutter' ; import 'codemirror/addon/fold/foldcode' ; import 'codemirror/addon/fold/brace-fold' ; import '../../fonts/index.css' ; import 'codemirror/lib/codemirror.css' ; import 'codemirror/addon/fold/foldgutter.css' ; const EditorContainer = styled . div ( '' as unknown as TemplateStringsArray , ( { theme } ) => theme . scheme === 'default' && theme . light ? defaultStyle : themedStyle ( theme ) ) ; export interface EditorProps { value : string ; mode : string ; lineNumbers : boolean ; lineWrapping : boolean ; readOnly : boolean ; theme ? : Base16Theme ; foldGutter : boolean ; autofocus : boolean ; onChange ? : ( value : string , change : EditorChange ) => void ; } /**
 * Based on [CodeMirror](http://codemirror.net/).
 */ export default class Editor extends Component < EditorProps > { cm ? : CodeMirror . Editor | null ; node ? : HTMLDivElement | null ; componentDidMount ( ) { this . cm = CodeMirror ( this . node ! , { value : this . props . value , mode : this . props . mode , lineNumbers : this . props . lineNumbers , lineWrapping : this . props . lineWrapping , readOnly : this . props . readOnly , autofocus : this . props . autofocus , foldGutter : this . props . foldGutter , gutters : [ 'CodeMirror-linenumbers' , 'CodeMirror-foldgutter' ] , } ) ; if ( this . props . onChange ) { this . cm . on ( 'change' , ( doc , change ) => { this . props . onChange ! ( doc . getValue ( ) , change ) ; } ) ; } } UNSAFE_componentWillReceiveProps ( nextProps ) { if ( nextProps . value !== this . cm ! . getValue ( ) ) { this . cm ! . setValue ( nextProps . value ) ; } if ( nextProps . readOnly !== this . props . readOnly ) { this . cm ! . setOption ( 'readOnly' , nextProps . readOnly ) ; } if ( nextProps . lineNumbers !== this . props . lineNumbers ) { this . cm ! . setOption ( 'lineNumbers' , nextProps . lineNumbers ) ; } if ( nextProps . lineWrapping !== this . props . lineWrapping ) { this . cm ! . setOption ( 'lineWrapping' , nextProps . lineWrapping ) ; } if ( nextProps . foldGutter !== this . props . foldGutter ) { this . cm ! . setOption ( 'foldGutter' , nextProps . foldGutter ) ; } } shouldComponentUpdate ( ) { return false ; } componentWillUnmount ( ) { const node = this . node ! ; node . removeChild ( node . children [ 0 ] ) ; this . cm = null ; } getRef : React . RefCallback < HTMLDivElement > = ( node ) => { this . node = node ; } ; render ( ) { return < EditorContainer ref = { this . getRef } theme = { this . props . theme } / > ; } static propTypes = { value : PropTypes . string , mode : PropTypes . string , lineNumbers : PropTypes . bool , lineWrapping : PropTypes . bool , readOnly : PropTypes . bool , theme : PropTypes . object , foldGutter : PropTypes . bool , autofocus : PropTypes . bool , onChange : PropTypes . func , } ; static defaultProps = { value : '' , mode : 'javascript' , lineNumbers : true , lineWrapping : false , readOnly : false , foldGutter : true , autofocus : false , } ; }