1- /* eslint-disable @typescript-eslint/explicit-function-return-type */
2- import { useState } from 'react' ;
3- import CustomEditor from '@ckeditor/ckeditor5-build-custom' ;
4- import { CKEditor } from '@ckeditor/ckeditor5-react' ;
5- import { FormHelperText , InputLabel } from '@mui/material' ;
1+ import { lazy , Suspense , useState } from 'react' ;
2+ import { FormHelperText , InputLabel , Skeleton } from '@mui/material' ;
63import { cyan } from '@mui/material/colors' ;
74
8- import attachmentsAPI from 'api/Attachments' ;
5+ const CKEditorField = lazy (
6+ ( ) => import ( /* webpackChunkName: "CKEditorField" */ './CKEditorField' ) ,
7+ ) ;
98
10- import './CKEditor.css' ;
11-
12- interface Props {
9+ const CKEditorRichText = ( {
10+ label,
11+ value,
12+ onChange,
13+ disabled,
14+ error,
15+ field,
16+ required,
17+ name,
18+ inputId,
19+ disableMargins,
20+ placeholder,
21+ autofocus,
22+ } : {
1323 name : string ;
1424 onChange : ( text : string ) => void ;
1525 value : string ;
@@ -22,160 +32,71 @@ interface Props {
2232 label ?: string ;
2333 placeholder ?: string ;
2434 required ?: boolean | undefined ;
25- }
26-
27- const uploadAdapter = ( loader ) => {
28- return {
29- upload : ( ) =>
30- new Promise ( ( resolve , reject ) => {
31- loader . file . then ( ( file : File ) => {
32- attachmentsAPI
33- . create ( file )
34- . then ( ( response ) => response . data )
35- . then ( ( data ) => {
36- if ( data . success ) {
37- resolve ( { default : `/attachments/${ data . id } ` } ) ;
38- }
39- } )
40- . catch ( ( err ) => {
41- reject ( err ) ;
42- } ) ;
43- } ) ;
44- } ) ,
45- abort : ( ) => { } ,
46- } ;
47- } ;
48-
49- const CKEditorRichText = ( props : Props ) => {
50- const {
51- label,
52- value,
53- onChange,
54- disabled,
55- error,
56- field,
57- required,
58- name,
59- inputId,
60- disableMargins,
61- placeholder,
62- autofocus,
63- } = props ;
64-
35+ } ) : JSX . Element => {
6536 const [ isFocused , setIsFocused ] = useState ( false ) ;
6637 const textFieldLabelColor = isFocused ? cyan [ 500 ] : undefined ;
6738
6839 return (
6940 < div
41+ className = "w-full inline-block bg-transparent relative"
7042 style = { {
7143 fontSize : 16 ,
72- width : '100%' ,
73- display : 'inline-block' ,
74- position : 'relative' ,
75- backgroundColor : 'transparent' ,
7644 fontFamily : 'Roboto, sans-serif' ,
7745 paddingTop : ! disableMargins && label ? '1em' : 0 ,
7846 paddingBottom : ! disableMargins ? '1em' : 0 ,
7947 } }
8048 >
8149 { label && (
8250 < InputLabel
51+ className = "pointer-events-none"
8352 disabled = { disabled }
8453 error = { ! ! error }
8554 htmlFor = { field }
8655 required = { required }
8756 shrink
8857 style = { {
89- pointerEvents : 'none' ,
9058 color : disabled ? 'rgba(0, 0, 0, 0.3)' : textFieldLabelColor ,
9159 } }
9260 >
9361 { label }
9462 </ InputLabel >
9563 ) }
64+
9665 < textarea
66+ aria-hidden
67+ className = "hidden"
9768 disabled = { disabled }
9869 id = { inputId }
9970 name = { name }
100- onChange = { ( event ) => {
101- onChange ( event . target . value ) ;
102- } }
71+ onChange = { ( e ) => onChange ( e . target . value ) }
10372 required = { required }
104- style = { { display : 'none' } }
10573 value = { value || '' }
10674 />
75+
10776 < div className = "react-ck" >
108- < CKEditor
109- config = { {
110- // To format <pre> properly (summernote compatability).
111- // CKEditor will change it to <pre><code> but on edit it will render properly
112- heading : {
113- options : [
114- { model : 'formatted' , view : 'pre' , title : 'Formatted' } ,
115- ] ,
116- } ,
117- // To add the default https protocol and
118- // an option to open the link in a new tab.
119- link : {
120- defaultProtocol : 'https://' ,
121- decorators : {
122- openInNewTab : {
123- mode : 'manual' ,
124- label : 'Open in a new tab' ,
125- attributes : {
126- target : '_blank' ,
127- rel : 'noopener noreferrer' ,
128- } ,
129- } ,
130- } ,
131- } ,
132- placeholder,
133- mediaEmbed : {
134- removeProviders : [
135- 'spotify' ,
136- 'instagram' ,
137- 'twitter' ,
138- 'googleMaps' ,
139- 'flickr' ,
140- 'facebook' ,
141- ] ,
142- } ,
143- } }
144- data = { value }
145- disabled = { disabled }
146- editor = { CustomEditor }
147- onBlur = { ( _event , _editor ) => {
148- setIsFocused ( false ) ;
149- } }
150- onChange = { ( _event , editor ) => {
151- onChange ( editor . getData ( ) ) ;
152- } }
153- onFocus = { ( _event , _editor ) => {
154- setIsFocused ( true ) ;
155- } }
156- onReady = { ( editor ) => {
157- // Enable the following to set a max height for ckeditor
158- editor . editing . view . change ( ( writer ) => {
159- writer . setStyle (
160- 'max-height' ,
161- '350px' ,
162- editor . editing . view . document . getRoot ( ) ,
163- ) ;
164- } ) ;
165- editor . plugins . get ( 'FileRepository' ) . createUploadAdapter = (
166- loader ,
167- ) => {
168- return uploadAdapter ( loader ) ;
169- } ;
170- if ( autofocus ) editor . focus ( ) ;
171- } }
172- />
77+ < Suspense
78+ fallback = {
79+ < Skeleton
80+ className = "min-h-[94.2px] max-h-[35rem] w-full"
81+ variant = "rounded"
82+ />
83+ }
84+ >
85+ < CKEditorField
86+ autoFocus = { autofocus }
87+ disabled = { disabled }
88+ onBlur = { ( ) => setIsFocused ( false ) }
89+ onChange = { onChange }
90+ onFocus = { ( ) => setIsFocused ( true ) }
91+ placeholder = { placeholder }
92+ value = { value }
93+ />
94+ </ Suspense >
17395 </ div >
96+
17497 { error && < FormHelperText error = { ! ! error } > { error } </ FormHelperText > }
17598 </ div >
17699 ) ;
177100} ;
178101
179- CKEditorRichText . displayName = 'CKEditor' ;
180-
181102export default CKEditorRichText ;
0 commit comments