@@ -14,7 +14,7 @@ import { Layers } from "constants/Layers";
1414import { HintPlaceHolder , Modal , Section , sectionNames } from "lowcoder-design" ;
1515import { trans } from "i18n" ;
1616import { changeChildAction } from "lowcoder-core" ;
17- import { CSSProperties , useCallback } from "react" ;
17+ import { CSSProperties , useCallback , useMemo , useRef } from "react" ;
1818import { ResizeHandle } from "react-resizable" ;
1919import styled , { css } from "styled-components" ;
2020import { useUserViewMode } from "util/hooks" ;
@@ -116,19 +116,36 @@ let TmpModalComp = (function () {
116116 ( props , dispatch ) => {
117117 const userViewMode = useUserViewMode ( ) ;
118118 const appID = useApplicationId ( ) ;
119- const bodyStyle : CSSProperties = { padding : 0 } ;
120- const width = transToPxSize ( props . width || DEFAULT_WIDTH ) ;
121- let height = undefined ;
122- let resizeHandles : ResizeHandle [ ] = [ "w" , "e" ] ;
123- if ( ! props . autoHeight ) {
124- height = transToPxSize ( props . height || DEFAULT_HEIGHT ) ;
125- resizeHandles . push ( "s" ) ;
126- bodyStyle . overflow = "hidden auto" ;
127- }
128- if ( userViewMode ) {
129- resizeHandles = [ ] ;
130- }
131- const { items, ...otherContainerProps } = props . container ;
119+ const containerRef = useRef < HTMLElement | null > ( null ) ;
120+
121+ // Memoize body style
122+ const bodyStyle = useMemo < CSSProperties > ( ( ) => ( {
123+ padding : 0 ,
124+ overflow : props . autoHeight ? undefined : "hidden auto"
125+ } ) , [ props . autoHeight ] ) ;
126+
127+ // Memoize width and height
128+ const width = useMemo ( ( ) =>
129+ transToPxSize ( props . width || DEFAULT_WIDTH ) ,
130+ [ props . width ]
131+ ) ;
132+
133+ const height = useMemo ( ( ) =>
134+ ! props . autoHeight ? transToPxSize ( props . height || DEFAULT_HEIGHT ) : undefined ,
135+ [ props . autoHeight , props . height ]
136+ ) ;
137+
138+ // Memoize resize handles
139+ const resizeHandles = useMemo < ResizeHandle [ ] > ( ( ) => {
140+ if ( userViewMode ) return [ ] ;
141+ const handles : ResizeHandle [ ] = [ "w" , "e" ] ;
142+ if ( ! props . autoHeight ) {
143+ handles . push ( "s" ) ;
144+ }
145+ return handles ;
146+ } , [ userViewMode , props . autoHeight ] ) ;
147+
148+ // Memoize resize handler
132149 const onResizeStop = useCallback (
133150 (
134151 e : React . SyntheticEvent ,
@@ -144,13 +161,48 @@ let TmpModalComp = (function () {
144161 } ,
145162 [ dispatch ]
146163 ) ;
147- let paddingValues = [ 10 , 10 ] ;
148- if ( props . style . padding != undefined ) {
164+
165+ // Memoize padding values
166+ const paddingValues = useMemo ( ( ) => {
167+ if ( ! props . style . padding ) return [ 10 , 10 ] ;
149168 const extractedValues = extractMarginValues ( props . style ) ;
150- if ( extractedValues !== null ) {
151- paddingValues = extractedValues ;
152- }
153- }
169+ return extractedValues || [ 10 , 10 ] ;
170+ } , [ props . style . padding ] ) ;
171+
172+ // Memoize container getter
173+ const getContainer = useCallback ( ( ) => {
174+ if ( ! containerRef . current ) {
175+ containerRef . current = document . querySelector ( `#${ CanvasContainerID } ` ) || document . body ;
176+ }
177+ return containerRef . current ;
178+ } , [ ] ) ;
179+
180+ // Memoize event handlers
181+ const handleCancel = useCallback ( ( e : React . MouseEvent ) => {
182+ if ( props . toggleClose ) {
183+ props . visible . onChange ( false ) ;
184+ }
185+ } , [ props . toggleClose , props . visible ] ) ;
186+
187+ const handleAfterClose = useCallback ( ( ) => {
188+ if ( props . toggleClose ) {
189+ props . onEvent ( "close" ) ;
190+ }
191+ } , [ props . toggleClose , props . onEvent ] ) ;
192+
193+ const handleAfterOpenChange = useCallback ( ( open : boolean ) => {
194+ if ( open ) {
195+ props . onEvent ( "open" ) ;
196+ }
197+ } , [ props . onEvent ] ) ;
198+
199+ // Memoize modal render function
200+ const modalRender = useCallback ( ( node : React . ReactNode ) => (
201+ < ModalStyled $style = { props . style } $modalScrollbar = { props . modalScrollbar } >
202+ { node }
203+ </ ModalStyled >
204+ ) , [ props . style , props . modalScrollbar ] ) ;
205+
154206 return (
155207 < BackgroundColorContext . Provider value = { props . style . background } >
156208 < ModalWrapper >
@@ -162,30 +214,24 @@ let TmpModalComp = (function () {
162214 open = { props . visible . value }
163215 maskClosable = { props . maskClosable }
164216 focusTriggerAfterClose = { false }
165- getContainer = { ( ) => document . querySelector ( `# ${ CanvasContainerID } ` ) || document . body }
217+ getContainer = { getContainer }
166218 footer = { null }
167219 styles = { { body : bodyStyle } }
168220 title = { props . title }
169221 $titleAlign = { props . titleAlign }
170222 width = { width }
171- onCancel = { ( e ) => {
172- props . toggleClose && props . visible . onChange ( false ) ;
173- } }
174- afterClose = { ( ) => {
175- props . toggleClose && props . onEvent ( "close" ) ;
176- } }
177- afterOpenChange = { ( open : boolean ) => {
178- if ( open ) props . onEvent ( "open" ) ;
179- } }
223+ onCancel = { handleCancel }
224+ afterClose = { handleAfterClose }
225+ afterOpenChange = { handleAfterOpenChange }
180226 zIndex = { Layers . modal }
181- modalRender = { ( node ) => < ModalStyled $style = { props . style } $modalScrollbar = { props . modalScrollbar } > { node } </ ModalStyled > }
227+ modalRender = { modalRender }
182228 mask = { props . showMask }
183229 className = { clsx ( `app-${ appID } ` , props . className ) }
184230 data-testid = { props . dataTestId as string }
185231 >
186232 < InnerGrid
187- { ...otherContainerProps }
188- items = { gridItemCompToGridItems ( items ) }
233+ { ...props . container }
234+ items = { gridItemCompToGridItems ( props . container . items ) }
189235 horizontalGridCells = { props . horizontalGridCells }
190236 autoHeight = { props . autoHeight }
191237 minHeight = { paddingValues ? DEFAULT_HEIGHT - paddingValues [ 0 ] * 2 + "px" : "" }
0 commit comments