1
+ /**
2
+ * React wrapper for xterm.js
3
+ * Taken from https://github.com/robert-harbison/xterm-for-react
4
+ */
5
+
6
+
7
+ import * as React from 'react'
8
+ import PropTypes from 'prop-types'
9
+
10
+ import 'xterm/css/xterm.css'
11
+
12
+ // We are using these as types.
13
+ // eslint-disable-next-line no-unused-vars
14
+ import { Terminal , ITerminalOptions , ITerminalAddon } from 'xterm'
15
+
16
+ export default class Xterm extends React . Component {
17
+ /**
18
+ * The ref for the containing element.
19
+ */
20
+ terminalRef
21
+
22
+ /**
23
+ * XTerm.js Terminal object.
24
+ */
25
+ terminal // This is assigned in the setupTerminal() which is called from the constructor
26
+
27
+ static propTypes = {
28
+ className : PropTypes . string ,
29
+ options : PropTypes . object ,
30
+ addons : PropTypes . array ,
31
+ onBinary : PropTypes . func ,
32
+ onCursorMove : PropTypes . func ,
33
+ onData : PropTypes . func ,
34
+ onKey : PropTypes . func ,
35
+ onLineFeed : PropTypes . func ,
36
+ onScroll : PropTypes . func ,
37
+ onSelectionChange : PropTypes . func ,
38
+ onRender : PropTypes . func ,
39
+ onResize : PropTypes . func ,
40
+ onTitleChange : PropTypes . func ,
41
+ customKeyEventHandler : PropTypes . func ,
42
+ }
43
+
44
+ constructor ( props ) {
45
+ super ( props )
46
+
47
+ this . terminalRef = React . createRef ( )
48
+
49
+ // Bind Methods
50
+ this . onData = this . onData . bind ( this )
51
+ this . onCursorMove = this . onCursorMove . bind ( this )
52
+ this . onKey = this . onKey . bind ( this )
53
+ this . onBinary = this . onBinary . bind ( this )
54
+ this . onLineFeed = this . onLineFeed . bind ( this )
55
+ this . onScroll = this . onScroll . bind ( this )
56
+ this . onSelectionChange = this . onSelectionChange . bind ( this )
57
+ this . onRender = this . onRender . bind ( this )
58
+ this . onResize = this . onResize . bind ( this )
59
+ this . onTitleChange = this . onTitleChange . bind ( this )
60
+
61
+ this . setupTerminal ( )
62
+ }
63
+
64
+ setupTerminal ( ) {
65
+ // Setup the XTerm terminal.
66
+ this . terminal = new Terminal ( this . props . options )
67
+
68
+ // Load addons if the prop exists.
69
+ if ( this . props . addons ) {
70
+ this . props . addons . forEach ( ( addon ) => {
71
+ this . terminal . loadAddon ( addon )
72
+ } )
73
+ }
74
+
75
+ // Create Listeners
76
+ this . terminal . onBinary ( this . onBinary )
77
+ this . terminal . onCursorMove ( this . onCursorMove )
78
+ this . terminal . onData ( this . onData )
79
+ this . terminal . onKey ( this . onKey )
80
+ this . terminal . onLineFeed ( this . onLineFeed )
81
+ this . terminal . onScroll ( this . onScroll )
82
+ this . terminal . onSelectionChange ( this . onSelectionChange )
83
+ this . terminal . onRender ( this . onRender )
84
+ this . terminal . onResize ( this . onResize )
85
+ this . terminal . onTitleChange ( this . onTitleChange )
86
+
87
+ // Add Custom Key Event Handler
88
+ if ( this . props . customKeyEventHandler ) {
89
+ this . terminal . attachCustomKeyEventHandler ( this . props . customKeyEventHandler )
90
+ }
91
+ }
92
+
93
+ componentDidMount ( ) {
94
+ if ( this . terminalRef . current ) {
95
+ // Creates the terminal within the container element.
96
+ this . terminal . open ( this . terminalRef . current )
97
+ }
98
+ }
99
+
100
+ componentWillUnmount ( ) {
101
+ // When the component unmounts dispose of the terminal and all of its listeners.
102
+ this . terminal . dispose ( )
103
+ }
104
+
105
+ onBinary ( data ) {
106
+ if ( this . props . onBinary ) this . props . onBinary ( data )
107
+ }
108
+
109
+ onCursorMove ( ) {
110
+ if ( this . props . onCursorMove ) this . props . onCursorMove ( )
111
+ }
112
+
113
+ onData ( data ) {
114
+ if ( this . props . onData ) this . props . onData ( data )
115
+ }
116
+
117
+ onKey ( event ) {
118
+ if ( this . props . onKey ) this . props . onKey ( event )
119
+ }
120
+
121
+ onLineFeed ( ) {
122
+ if ( this . props . onLineFeed ) this . props . onLineFeed ( )
123
+ }
124
+
125
+ onScroll ( newPosition ) {
126
+ if ( this . props . onScroll ) this . props . onScroll ( newPosition )
127
+ }
128
+
129
+ onSelectionChange ( ) {
130
+ if ( this . props . onSelectionChange ) this . props . onSelectionChange ( )
131
+ }
132
+
133
+ onRender ( event ) {
134
+ if ( this . props . onRender ) this . props . onRender ( event )
135
+ }
136
+
137
+ onResize ( event ) {
138
+ if ( this . props . onResize ) this . props . onResize ( event )
139
+ }
140
+
141
+ onTitleChange ( newTitle ) {
142
+ if ( this . props . onTitleChange ) this . props . onTitleChange ( newTitle )
143
+ }
144
+
145
+ render ( ) {
146
+ return < div className = { this . props . className } ref = { this . terminalRef } />
147
+ }
148
+ }
0 commit comments