@@ -12,7 +12,7 @@ import { formDataChildren, FormDataPropertyView } from "../formComp/formDataCons
12
12
import { AnimationStyle , JsonEditorStyle } from "comps/controls/styleControlConstants" ;
13
13
import { styleControl } from "comps/controls/styleControl" ;
14
14
import { migrateOldData , withDefault } from "comps/generators/simpleGenerators" ;
15
- import { useRef , useEffect , useContext } from "react" ;
15
+ import { useRef , useEffect , useContext , useCallback , useMemo } from "react" ;
16
16
import {
17
17
EditorState ,
18
18
EditorView ,
@@ -67,7 +67,7 @@ const childrenMap = {
67
67
value : jsonValueExposingStateControl ( 'value' , defaultData ) ,
68
68
onEvent : ChangeEventHandlerControl ,
69
69
autoHeight : withDefault ( AutoHeightControl , 'auto' ) ,
70
- showVerticalScrollbar :BoolControl ,
70
+ showVerticalScrollbar : BoolControl ,
71
71
label : withDefault ( LabelControl , { position : 'column' } ) ,
72
72
style : styleControl ( JsonEditorStyle , 'style' ) ,
73
73
animationStyle : styleControl ( AnimationStyle , 'animationStyle' ) ,
@@ -77,72 +77,110 @@ const childrenMap = {
77
77
let JsonEditorTmpComp = ( function ( ) {
78
78
return new UICompBuilder ( childrenMap , ( props ) => {
79
79
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
+
84
99
const { extensions } = useExtensions ( {
85
100
codeType : "PureJSON" ,
86
101
language : "json" ,
87
102
showLineNum : true ,
88
103
enableClickCompName : false ,
89
- onFocus : ( focused ) => {
104
+ onFocus : useCallback ( ( focused : boolean ) => {
90
105
if ( focused ) {
91
106
wrapperRef . current ?. click ( ) ;
92
107
}
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 ,
102
110
} ) ;
103
111
112
+ // Initialize editor state
104
113
useEffect ( ( ) => {
105
- if ( ! initialized . current && wrapperRef . current ) {
106
- state . current = EditorState . create ( {
114
+ if ( ! initializedRef . current && wrapperRef . current ) {
115
+ stateRef . current = EditorState . create ( {
107
116
doc : JSON . stringify ( props . value . value , null , 2 ) ,
108
117
extensions,
109
118
} ) ;
110
119
}
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 ] ) ;
112
128
129
+ // Create editor view
113
130
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 ;
117
137
}
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
+
130
173
return props . label ( {
131
174
style : props . style ,
132
175
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 ,
143
177
} ) ;
144
178
} )
145
179
. 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
+
146
184
return (
147
185
< >
148
186
< Section name = { sectionNames . basic } >
@@ -151,35 +189,40 @@ let JsonEditorTmpComp = (function () {
151
189
152
190
< FormDataPropertyView { ...children } />
153
191
154
- { ( useContext ( EditorContext ) . editorModeStatus === "logic" || useContext ( EditorContext ) . editorModeStatus === "both" ) && (
192
+ { isLogicMode && (
155
193
< Section name = { sectionNames . interaction } >
156
194
{ children . onEvent . getPropertyView ( ) }
157
195
{ hiddenPropertyView ( children ) }
158
196
{ showDataLoadingIndicatorsPropertyView ( children ) }
159
197
</ Section >
160
198
) }
199
+
161
200
< Section name = { trans ( 'prop.height' ) } >
162
201
{ children . autoHeight . propertyView ( { label : trans ( 'prop.height' ) } ) }
163
202
</ 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 >
173
208
) }
174
209
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
+ ) }
175
219
</ >
176
220
) ;
177
221
} )
178
222
. build ( ) ;
179
223
} ) ( ) ;
180
224
181
225
JsonEditorTmpComp = migrateOldData ( JsonEditorTmpComp , fixOldData ) ;
182
-
183
226
JsonEditorTmpComp = migrateOldData ( JsonEditorTmpComp , fixOldDataSecond ) ;
184
227
185
228
JsonEditorTmpComp = class extends JsonEditorTmpComp {
0 commit comments