@@ -12,7 +12,7 @@ import { formDataChildren, FormDataPropertyView } from "../formComp/formDataCons
1212import  {  AnimationStyle ,  JsonEditorStyle  }  from  "comps/controls/styleControlConstants" ; 
1313import  {  styleControl  }  from  "comps/controls/styleControl" ; 
1414import  {  migrateOldData ,  withDefault  }  from  "comps/generators/simpleGenerators" ; 
15- import  {  useRef ,  useEffect ,  useContext  }  from  "react" ; 
15+ import  {  useRef ,  useEffect ,  useContext ,   useCallback ,   useMemo  }  from  "react" ; 
1616import  { 
1717  EditorState , 
1818  EditorView , 
@@ -67,7 +67,7 @@ const childrenMap = {
6767  value : jsonValueExposingStateControl ( 'value' ,  defaultData ) , 
6868  onEvent : ChangeEventHandlerControl , 
6969  autoHeight : withDefault ( AutoHeightControl , 'auto' ) , 
70-   showVerticalScrollbar :BoolControl , 
70+   showVerticalScrollbar :  BoolControl , 
7171  label : withDefault ( LabelControl ,  { position : 'column' } ) , 
7272  style : styleControl ( JsonEditorStyle ,  'style' ) , 
7373  animationStyle : styleControl ( AnimationStyle ,  'animationStyle' ) , 
@@ -77,72 +77,110 @@ const childrenMap = {
7777let  JsonEditorTmpComp  =  ( function  ( )  { 
7878  return  new  UICompBuilder ( childrenMap ,  ( props )  =>  { 
7979    const  wrapperRef  =  useRef < HTMLDivElement > ( null ) ; 
80-     const  view  =  useRef < EditorViewType  |  null > ( null ) ; 
81-     const  initialized  =  useRef ( false ) ; 
82-     const  state  =  useRef < EditorState  |  null > ( null ) ; 
83-     const  editContent  =  useRef < string > ( ) ; 
80+     const  viewRef  =  useRef < EditorViewType  |  null > ( null ) ; 
81+     const  initializedRef  =  useRef ( false ) ; 
82+     const  stateRef  =  useRef < EditorState  |  null > ( null ) ; 
83+     const  editContentRef  =  useRef < string > ( ) ; 
84+     const  mountedRef  =  useRef ( true ) ; 
85+ 
86+     const  handleChange  =  useCallback ( ( state : EditorState )  =>  { 
87+       if  ( ! mountedRef . current )  return ; 
88+       
89+       editContentRef . current  =  state . doc . toString ( ) ; 
90+       try  { 
91+         const  value  =  JSON . parse ( state . doc . toString ( ) ) ; 
92+         props . value . onChange ( value ) ; 
93+         props . onEvent ( "change" ) ; 
94+       }  catch  ( error )  { 
95+         // Invalid JSON - ignore 
96+       } 
97+     } ,  [ props . value ,  props . onEvent ] ) ; 
98+ 
8499    const  {  extensions }  =  useExtensions ( { 
85100      codeType : "PureJSON" , 
86101      language : "json" , 
87102      showLineNum : true , 
88103      enableClickCompName : false , 
89-       onFocus : ( focused )  =>  { 
104+       onFocus : useCallback ( ( focused :  boolean )  =>  { 
90105        if  ( focused )  { 
91106          wrapperRef . current ?. click ( ) ; 
92107        } 
93-       } , 
94-       onChange : ( state )  =>  { 
95-         editContent . current  =  state . doc . toString ( ) ; 
96-         try  { 
97-           const  value  =  JSON . parse ( state . doc . toString ( ) ) ; 
98-           props . value . onChange ( value ) ; 
99-           props . onEvent ( "change" ) ; 
100-         }  catch  ( error )  { } 
101-       } , 
108+       } ,  [ ] ) , 
109+       onChange : handleChange , 
102110    } ) ; 
103111
112+     // Initialize editor state 
104113    useEffect ( ( )  =>  { 
105-       if  ( ! initialized . current  &&  wrapperRef . current )  { 
106-         state . current  =  EditorState . create ( { 
114+       if  ( ! initializedRef . current  &&  wrapperRef . current )  { 
115+         stateRef . current  =  EditorState . create ( { 
107116          doc : JSON . stringify ( props . value . value ,  null ,  2 ) , 
108117          extensions, 
109118        } ) ; 
110119      } 
111-     } ,  [ wrapperRef . current ] ) ; 
120+       if  ( wrapperRef . current  &&  viewRef . current  &&  ! editContentRef . current )  { 
121+         const  newState  =  EditorState . create ( { 
122+           doc : JSON . stringify ( props . value . value ,  null ,  2 ) , 
123+           extensions, 
124+         } ) ; 
125+         viewRef . current ?. setState ( newState ) ; 
126+       } 
127+     } ,  [ wrapperRef . current ,  extensions ,  props . value . value ] ) ; 
112128
129+     // Create editor view 
113130    useEffect ( ( )  =>  { 
114-       if  ( state . current && wrapperRef . current )  { 
115-         view . current  =  new  EditorView ( {  state : state . current ,  parent : wrapperRef . current  } ) ; 
116-         initialized . current  =  true ; 
131+       if  ( stateRef . current  &&  wrapperRef . current )  { 
132+         viewRef . current  =  new  EditorView ( {  
133+           state : stateRef . current ,  
134+           parent : wrapperRef . current  
135+         } ) ; 
136+         initializedRef . current  =  true ; 
117137      } 
118-     } ,  [ props . showVerticalScrollbar ] ) 
119- 
120-     if  ( wrapperRef . current  &&  view . current  &&  ! editContent . current )  { 
121-       const  state  =  EditorState . create ( { 
122-         doc : JSON . stringify ( props . value . value ,  null ,  2 ) , 
123-         extensions, 
124-       } ) ; 
125-       view . current ?. setState ( state ) ; 
126-     } 
127-     if  ( editContent . current )  { 
128-       editContent . current  =  undefined ; 
129-     } 
138+ 
139+       return  ( )  =>  { 
140+         viewRef . current ?. destroy ( ) ; 
141+         viewRef . current  =  null ; 
142+         stateRef . current  =  null ; 
143+         initializedRef . current  =  false ; 
144+       } ; 
145+     } ,  [ props . showVerticalScrollbar ] ) ; 
146+ 
147+     // Cleanup on unmount 
148+     useEffect ( ( )  =>  { 
149+       return  ( )  =>  { 
150+         mountedRef . current  =  false ; 
151+         viewRef . current ?. destroy ( ) ; 
152+         viewRef . current  =  null ; 
153+         stateRef . current  =  null ; 
154+         initializedRef . current  =  false ; 
155+       } ; 
156+     } ,  [ ] ) ; 
157+ 
158+     const  handleFocus  =  useCallback ( ( )  =>  { 
159+       editContentRef . current  =  'focus' ; 
160+     } ,  [ ] ) ; 
161+ 
162+     const  editorContent  =  useMemo ( ( )  =>  ( 
163+       < ScrollBar  hideScrollbar = { ! props . showVerticalScrollbar } > 
164+         < Wrapper 
165+           ref = { wrapperRef } 
166+           onFocus = { handleFocus } 
167+           $height = { props . autoHeight } 
168+           $showVerticalScrollbar = { props . showVerticalScrollbar } 
169+         /> 
170+       </ ScrollBar > 
171+     ) ,  [ props . showVerticalScrollbar ,  props . autoHeight ,  handleFocus ] ) ; 
172+ 
130173    return  props . label ( { 
131174      style : props . style , 
132175      animationStyle : props . animationStyle , 
133-       children : ( 
134-         < ScrollBar  hideScrollbar = { ! props . showVerticalScrollbar } > 
135-           < Wrapper 
136-             ref = { wrapperRef } 
137-             onFocus = { ( )  =>  ( editContent . current  =  'focus' ) } 
138-             $height = { props . autoHeight } 
139-             $showVerticalScrollbar = { props . showVerticalScrollbar } 
140-           /> 
141-         </ ScrollBar > 
142-       ) , 
176+       children : editorContent , 
143177    } ) ; 
144178  } ) 
145179    . setPropertyViewFn ( ( children )  =>  { 
180+       const  editorContext  =  useContext ( EditorContext ) ; 
181+       const  isLogicMode  =  editorContext . editorModeStatus  ===  "logic"  ||  editorContext . editorModeStatus  ===  "both" ; 
182+       const  isLayoutMode  =  editorContext . editorModeStatus  ===  "layout"  ||  editorContext . editorModeStatus  ===  "both" ; 
183+ 
146184      return  ( 
147185        < > 
148186          < Section  name = { sectionNames . basic } > 
@@ -151,35 +189,40 @@ let JsonEditorTmpComp = (function () {
151189
152190          < FormDataPropertyView  { ...children }  /> 
153191
154-           { ( useContext ( EditorContext ) . editorModeStatus   ===   "logic"   ||   useContext ( EditorContext ) . editorModeStatus   ===   "both" )  &&  ( 
192+           { isLogicMode  &&  ( 
155193            < Section  name = { sectionNames . interaction } > 
156194              { children . onEvent . getPropertyView ( ) } 
157195              { hiddenPropertyView ( children ) } 
158196              { showDataLoadingIndicatorsPropertyView ( children ) } 
159197            </ Section > 
160198          ) } 
199+ 
161200          < Section  name = { trans ( 'prop.height' ) } > 
162201            { children . autoHeight . propertyView ( {  label : trans ( 'prop.height' )  } ) } 
163202          </ Section > 
164-             { ! children . autoHeight . getView ( ) && < Section  name = { sectionNames . layout } > 
165-             { children . showVerticalScrollbar . propertyView ( { label : trans ( 'prop.showVerticalScrollbar' ) } ) } 
166-           </ Section > } 
167-           { ( useContext ( EditorContext ) . editorModeStatus  ===  "layout"  ||  useContext ( EditorContext ) . editorModeStatus  ===  "both" )  &&  (  children . label . getPropertyView ( )  ) } 
168-           { ( useContext ( EditorContext ) . editorModeStatus  ===  "layout"  ||  useContext ( EditorContext ) . editorModeStatus  ===  "both" )  &&  ( 
169-             < > 
170-             < Section  name = { sectionNames . style } > { children . style . getPropertyView ( ) } </ Section > 
171-               < Section  name = { sectionNames . animationStyle }  hasTooltip = { true } > { children . animationStyle . getPropertyView ( ) } </ Section > 
172-               </ > 
203+ 
204+           { ! children . autoHeight . getView ( )  &&  ( 
205+             < Section  name = { sectionNames . layout } > 
206+               { children . showVerticalScrollbar . propertyView ( { label : trans ( 'prop.showVerticalScrollbar' ) } ) } 
207+             </ Section > 
173208          ) } 
174209
210+           { isLayoutMode  &&  ( 
211+             < > 
212+               { children . label . getPropertyView ( ) } 
213+               < Section  name = { sectionNames . style } > { children . style . getPropertyView ( ) } </ Section > 
214+               < Section  name = { sectionNames . animationStyle }  hasTooltip = { true } > 
215+                 { children . animationStyle . getPropertyView ( ) } 
216+               </ Section > 
217+             </ > 
218+           ) } 
175219        </ > 
176220      ) ; 
177221    } ) 
178222    . build ( ) ; 
179223} ) ( ) ; 
180224
181225JsonEditorTmpComp  =  migrateOldData ( JsonEditorTmpComp ,  fixOldData ) ; 
182- 
183226JsonEditorTmpComp  =  migrateOldData ( JsonEditorTmpComp ,  fixOldDataSecond ) ; 
184227
185228JsonEditorTmpComp  =  class  extends  JsonEditorTmpComp  { 
0 commit comments