1
+ import React , { useCallback , useState } from "react" ;
2
+ import Ansi from "ansi-to-react" ;
3
+
4
+ import { BlockOutputPropsType } from "./types" ;
5
+
6
+ function BlockOutput ( props :BlockOutputPropsType ) {
7
+ const metadata = props . cell [ 'metadata' ] ;
8
+ const outputs = props . cell [ 'outputs' ]
9
+
10
+ const [ state , setState ] = useState ( {
11
+ highlighted : false ,
12
+ prevDisplay : 1 ,
13
+ display : 1 ,
14
+ contentHeight : 0 ,
15
+ } )
16
+ const contentRef = useCallback ( ( node ) => {
17
+ if ( node ) {
18
+ setState ( state => ( { ...state , contentHeight : node . offsetHeight } ) ) ;
19
+ }
20
+ } , [ ] )
21
+
22
+ if ( props . display !== state . prevDisplay ) {
23
+ let newDisplay = props . display ;
24
+ if ( newDisplay === - 1 ) {
25
+ if ( metadata [ 'collapsed' ] || ( metadata [ 'jupyter' ] !== undefined && metadata [ 'jupyter' ] [ 'outputs_hidden' ] ) ) {
26
+ newDisplay = 0 ;
27
+ }
28
+ else if ( metadata [ 'scrolled' ] ) {
29
+ newDisplay = 2 ;
30
+ }
31
+ }
32
+
33
+ setState ( { ...state , prevDisplay : props . display , display : newDisplay } ) ;
34
+ }
35
+
36
+ return (
37
+ < div
38
+ className = "block-output"
39
+ >
40
+ < div
41
+ className = { props . highlighted ? "block-light-selected" : "block-light" }
42
+ onClick = { ( ) => {
43
+ setState ( { ...state , display : ( state . display + 1 ) % 3 } )
44
+ } }
45
+ />
46
+ { state . display === 0 ? < div className = "block-hidden" /> :
47
+ < div
48
+ className = "block-output-content"
49
+ style = { state . display !== 2 ? undefined : {
50
+ maxHeight : state . contentHeight ,
51
+ height : 200 ,
52
+ boxShadow : "inset 0 0 6px 2px rgb(0 0 0 / 30%)" ,
53
+ resize : "vertical" ,
54
+ } }
55
+ >
56
+ < div ref = { contentRef } >
57
+ { ! outputs ? null : outputs . map ( ( output , index ) => {
58
+ let executionCount ;
59
+ let htmlContent ;
60
+ if ( 'output_type' in output ) {
61
+ let output_type = output [ 'output_type' ] ;
62
+ switch ( output_type ) {
63
+ // Stdout and stderr
64
+ case 'stream' :
65
+ htmlContent = (
66
+ < pre className = { `cell-content ${ output [ 'name' ] === 'stdout' ? 'output-std' : 'output-err' } ` } >
67
+ { ! output [ 'text' ] ? '' : output [ 'text' ] . join ( '' ) }
68
+ </ pre >
69
+ )
70
+
71
+ break ;
72
+ // Output with execution_count
73
+ // @ts -expect-error
74
+ case 'execute_result' :
75
+ executionCount = output [ 'execution_count' ]
76
+
77
+ // Output without execution_count
78
+ case 'display_data' :
79
+ const output_data = output [ 'data' ] ;
80
+ if ( output_data ) {
81
+ if ( 'image/png' in output_data ) {
82
+ let output_metadata = output [ 'metadata' ] ;
83
+ let size = output_metadata && output_metadata [ 'image/png' ] ;
84
+ htmlContent = (
85
+ < div
86
+ className = "cell-content output-display"
87
+ style = { {
88
+ justifyContent : props . mediaAlign ,
89
+ } }
90
+ >
91
+ < img
92
+ src = { `data:image/png;base64,${ output_data [ 'image/png' ] } ` }
93
+ width = { size ? size [ 'width' ] : 'auto' }
94
+ height = { size ? size [ 'height' ] : 'auto' }
95
+ alt = ""
96
+ />
97
+ </ div >
98
+ )
99
+ }
100
+ else if ( 'text/html' in output_data ) {
101
+ htmlContent = (
102
+ < div
103
+ className = "cell-content output-display"
104
+ style = { {
105
+ justifyContent : props . mediaAlign ,
106
+ } }
107
+ dangerouslySetInnerHTML = { { __html : output_data [ 'text/html' ] . join ( '' ) } }
108
+ />
109
+ )
110
+ }
111
+ else if ( 'text/plain' in output_data ) {
112
+ htmlContent = (
113
+ < pre className = "cell-content output-std" > { output_data [ 'text/plain' ] . join ( '' ) } </ pre >
114
+ )
115
+ }
116
+ }
117
+
118
+ break ;
119
+ // Exceptions
120
+ case 'error' :
121
+ htmlContent = (
122
+ < pre className = "cell-content output-err" >
123
+ < Ansi >
124
+ { ! output . traceback ? undefined : output . traceback . join ( '\n' ) }
125
+ </ Ansi >
126
+ </ pre >
127
+ )
128
+
129
+ break ;
130
+ default :
131
+ console . log ( 'Unexpected output_type: ' , output_type ) ;
132
+ }
133
+ }
134
+
135
+ return (
136
+ < div
137
+ key = { index }
138
+ className = "cell-row"
139
+ >
140
+ < pre className = "cell-header output" > { executionCount ? `[${ executionCount } ]: ` : null } </ pre >
141
+ { htmlContent }
142
+ </ div >
143
+ ) ;
144
+ } ) }
145
+ </ div >
146
+ </ div >
147
+ }
148
+ </ div >
149
+ )
150
+ }
151
+
152
+ export default BlockOutput ;
0 commit comments