@@ -27,6 +27,7 @@ const _styles = {
2727 alignItems : 'stretch'
2828 } ,
2929
30+ // See resize detector comments in renderResizeDetectorIfNeeded() method below.
3031 resizeDetectorContainerStyles : {
3132 position : 'absolute' ,
3233 left : '0' ,
@@ -77,40 +78,22 @@ export class View extends ViewBase<Types.ViewProps, {}> {
7778 } ;
7879
7980 private resizeDetectorAnimationFrame : number ;
80- private resizeDetectorNodes : { grow ?: HTMLElement , shrink ?: HTMLElement } = { } ;
81-
82- private resizeDetectorReset ( ) {
83- const scrollMax = 100500 ;
84-
85- let node = this . resizeDetectorNodes . grow ;
86-
87- if ( node ) {
88- node . scrollLeft = scrollMax ;
89- node . scrollTop = scrollMax ;
90- }
91-
92- node = this . resizeDetectorNodes . shrink ;
93-
94- if ( node ) {
95- node . scrollLeft = scrollMax ;
96- node . scrollTop = scrollMax ;
97- }
98- }
99-
100- private resizeDetectorOnScroll ( ) {
101- if ( this . resizeDetectorAnimationFrame ) {
102- return ;
103- }
104-
105- this . resizeDetectorAnimationFrame = window . requestAnimationFrame ( ( ) => {
106- this . resizeDetectorReset ( ) ;
107- this . resizeDetectorAnimationFrame = undefined ;
108- ViewBase . _checkViews ( ) ;
109- } ) ;
110-
111- }
81+ private resizeDetectorNodes : { grow ?: HTMLElement , shrink ?: HTMLElement } = { } ;
11282
11383 private renderResizeDetectorIfNeeded ( containerStyles : any ) : React . ReactNode {
84+ // If needed, additional invisible DOM elements will be added inside the
85+ // view to track the size changes that are performed behind our back by
86+ // the browser's layout engine faster (ViewBase checks for the layout
87+ // updates once a second and sometimes it's not fast enough).
88+
89+ // Unfortunately <div> doesn't have `resize` event, so we're trying to
90+ // detect the fact that the view has been resized with `scroll` events.
91+ // To do that, we create two scrollable <div>s and we put them into a
92+ // state in which `scroll` event is triggered by the browser when the
93+ // container gets resized (one element triggers `scroll` when the
94+ // container gets bigger, another triggers `scroll` when the container
95+ // gets smaller).
96+
11497 if ( ! this . props . importantForLayout ) {
11598 return null ;
11699 }
@@ -138,27 +121,62 @@ export class View extends ViewBase<Types.ViewProps, {}> {
138121 return [
139122 (
140123 < div
141- key = 'grow'
124+ key = { 'grow' }
142125 style = { _styles . resizeDetectorContainerStyles }
143126 ref = { ( ref ) => initResizer ( 'grow' , ref ) }
144127 onScroll = { ( ) => this . resizeDetectorOnScroll ( ) } >
145128
146- < div style = { _styles . resizeGrowDetectorStyles } > </ div >
129+ < div style = { _styles . resizeGrowDetectorStyles } > </ div >
147130 </ div >
148131 ) ,
149132 (
150133 < div
151- key = 'shrink'
134+ key = { 'shrink' }
152135 style = { _styles . resizeDetectorContainerStyles }
153136 ref = { ( ref ) => initResizer ( 'shrink' , ref ) }
154137 onScroll = { ( ) => this . resizeDetectorOnScroll ( ) } >
155138
156- < div style = { _styles . resizeShrinkDetectorStyles } > </ div >
139+ < div style = { _styles . resizeShrinkDetectorStyles } > </ div >
157140 </ div >
158141 )
159142 ] ;
160143 }
161144
145+ private resizeDetectorReset ( ) {
146+ // Scroll the detectors to the bottom-right corner so
147+ // that `scroll` events will be triggered when the container
148+ // is resized.
149+ const scrollMax = 100500 ;
150+
151+ let node = this . resizeDetectorNodes . grow ;
152+
153+ if ( node ) {
154+ node . scrollLeft = scrollMax ;
155+ node . scrollTop = scrollMax ;
156+ }
157+
158+ node = this . resizeDetectorNodes . shrink ;
159+
160+ if ( node ) {
161+ node . scrollLeft = scrollMax ;
162+ node . scrollTop = scrollMax ;
163+ }
164+ }
165+
166+ private resizeDetectorOnScroll ( ) {
167+ if ( this . resizeDetectorAnimationFrame ) {
168+ // Do not execute action more often than once per animation frame.
169+ return ;
170+ }
171+
172+ this . resizeDetectorAnimationFrame = window . requestAnimationFrame ( ( ) => {
173+ this . resizeDetectorReset ( ) ;
174+ this . resizeDetectorAnimationFrame = undefined ;
175+ ViewBase . _checkViews ( ) ;
176+ } ) ;
177+
178+ }
179+
162180 getChildContext ( ) {
163181 // Let descendant Types components know that their nearest Types ancestor is not an Types.Text.
164182 // Because they're in an Types.View, they should use their normal styling rather than their
@@ -209,19 +227,19 @@ export class View extends ViewBase<Types.ViewProps, {}> {
209227 if ( childAnimationsEnabled ) {
210228 reactElement = (
211229 < AnimateListEdits
212- { ...props }
213- animateChildEnter = { this . props . animateChildEnter }
214- animateChildMove = { this . props . animateChildMove }
215- animateChildLeave = { this . props . animateChildLeave }
230+ { ...props }
231+ animateChildEnter = { this . props . animateChildEnter }
232+ animateChildMove = { this . props . animateChildMove }
233+ animateChildLeave = { this . props . animateChildLeave }
216234 >
217- { this . props . children }
235+ { this . props . children }
218236 </ AnimateListEdits >
219237 ) ;
220238 } else {
221239 reactElement = (
222- < div { ...props } >
223- { this . renderResizeDetectorIfNeeded ( combinedStyles ) }
224- { this . props . children }
240+ < div { ...props } >
241+ { this . renderResizeDetectorIfNeeded ( combinedStyles ) }
242+ { this . props . children }
225243 </ div >
226244 ) ;
227245 }
0 commit comments