1- import { FC , ReactNode , useState } from 'react'
1+ import React , { FC , useState , Suspense } from 'react'
22import { useTranslation } from 'react-i18next'
33import Box from '@mui/material/Box'
44import Typography from '@mui/material/Typography'
5- import { styled } from '@mui/material/styles'
6- import { ScrollableDataDisplay } from '../../components/ScrollableDataDisplay'
75import { CopyToClipboard , FloatingCopyToClipboard } from '../../components/CopyToClipboard'
86import { useScreenSize } from '../../hooks/useScreensize'
97import { base64ToHex } from '../../utils/helpers'
8+ import { MonacoLanguages } from './MonacoLanguages'
9+
10+ const TextAreaFallback = ( { value } : { value ?: string } ) => (
11+ < textarea readOnly value = { value } style = { { width : '100%' , height : '100%' , colorScheme : 'dark' } } />
12+ )
13+
14+ const MonacoEditor = React . lazy ( async ( ) => {
15+ try {
16+ const monaco = await import ( 'monaco-editor' )
17+ const monacoReact = await import ( '@monaco-editor/react' )
18+ // Load from npm, not cdn.jsdelivr.net
19+ // https://www.npmjs.com/package/@monaco -editor/react#use-monaco-editor-as-an-npm-package
20+ window . MonacoEnvironment = {
21+ getWorker ( id , label ) {
22+ return new Worker (
23+ new URL ( '../../../../node_modules/monaco-editor/esm/vs/editor/editor.worker.js' , import . meta. url ) ,
24+ { type : 'module' } ,
25+ )
26+ } ,
27+ }
28+ monacoReact . loader . config ( { monaco } )
29+
30+ return monacoReact
31+ } catch ( e ) {
32+ console . error ( 'monaco-editor wrapper failed to load. Using <textarea> instead' )
33+ return {
34+ default : ( props => (
35+ < TextAreaFallback value = { props . value || props . defaultValue } />
36+ ) ) as typeof import ( '@monaco-editor/react' ) . default ,
37+ }
38+ }
39+ } )
1040
1141type CodeDisplayProps = {
12- code : ReactNode
13- copyToClipboardValue : string
42+ code : string
43+ language : MonacoLanguages
1444 label ?: string
1545 extraTopPadding ?: boolean
1646 floatingCopyButton ?: boolean
1747}
1848
1949const CodeDisplay : FC < CodeDisplayProps > = ( {
2050 code,
21- copyToClipboardValue ,
22- label,
23- extraTopPadding,
51+ language ,
52+ label = undefined ,
53+ extraTopPadding = false ,
2454 floatingCopyButton = false ,
2555} ) => {
2656 const { t } = useTranslation ( )
@@ -52,15 +82,31 @@ const CodeDisplay: FC<CodeDisplayProps> = ({
5282 </ Typography >
5383 ) }
5484 { floatingCopyButton ? (
55- < FloatingCopyToClipboard isVisible = { isHovering } value = { copyToClipboardValue } />
85+ < FloatingCopyToClipboard isVisible = { isHovering } value = { code } />
5686 ) : (
5787 < CopyToClipboard
58- value = { copyToClipboardValue }
88+ value = { code }
5989 label = { isMobile ? t ( 'common.copy' ) : t ( 'contract.copyButton' , { subject : label } ) }
6090 />
6191 ) }
6292 </ Box >
63- < ScrollableDataDisplay data = { code } />
93+ < Box sx = { { height : '350px' , overflow : 'auto' , resize : 'vertical' } } >
94+ { /* While loading wrapper show <textarea> instead */ }
95+ < Suspense fallback = { < TextAreaFallback value = { code } /> } >
96+ < MonacoEditor
97+ // While loading and if monaco-editor internals fail to load: show <textarea> instead
98+ loading = { < TextAreaFallback value = { code } /> }
99+ language = { language }
100+ value = { code }
101+ theme = "vs-dark"
102+ options = { {
103+ readOnly : true ,
104+ fontSize : 14 ,
105+ wordWrap : 'on' ,
106+ } }
107+ />
108+ </ Suspense >
109+ </ Box >
64110 </ Box >
65111 )
66112}
@@ -72,16 +118,10 @@ type RawDataDisplayProps = {
72118
73119export const RawDataDisplay : FC < RawDataDisplayProps > = ( { data, label } ) => {
74120 const code = data === undefined ? undefined : base64ToHex ( data )
75- if ( ! code ) {
76- return null
77- }
78- return < CodeDisplay code = { code } copyToClipboardValue = { code } label = { label } extraTopPadding />
79- }
121+ if ( ! code ) return null
80122
81- const StyledPre = styled ( 'pre' ) ( {
82- margin : 0 ,
83- whiteSpace : 'break-spaces' ,
84- } )
123+ return < CodeDisplay code = { code } label = { label } extraTopPadding language = "plaintext" />
124+ }
85125
86126type FileDisplayProps = {
87127 code : string | undefined
@@ -91,14 +131,7 @@ type FileDisplayProps = {
91131export const FileDisplay : FC < FileDisplayProps > = ( { code, filename } ) => {
92132 if ( ! code ) return null
93133
94- return (
95- < CodeDisplay
96- code = { < StyledPre > { code } </ StyledPre > }
97- copyToClipboardValue = { code }
98- label = { filename }
99- extraTopPadding
100- />
101- )
134+ return < CodeDisplay code = { code } label = { filename } extraTopPadding language = "sol" />
102135}
103136
104137type JsonCodeDisplayProps = {
@@ -111,11 +144,6 @@ export const JsonCodeDisplay: FC<JsonCodeDisplayProps> = ({ data, label, floatin
111144 const formattedJson = JSON . stringify ( data , null , 2 )
112145
113146 return (
114- < CodeDisplay
115- code = { < StyledPre > { formattedJson } </ StyledPre > }
116- copyToClipboardValue = { formattedJson }
117- label = { label }
118- floatingCopyButton = { floatingCopyButton }
119- />
147+ < CodeDisplay code = { formattedJson } label = { label } floatingCopyButton = { floatingCopyButton } language = "json" />
120148 )
121149}
0 commit comments