@@ -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