77 * @flow
88 */
99
10- import React , {
11- Suspense ,
12- Fragment ,
13- useRef ,
14- useState ,
15- useLayoutEffect ,
16- useCallback ,
17- } from 'react' ;
10+ import React , { Suspense , Fragment , useRef , useEffect , useReducer } from 'react' ;
1811import Tree from './Tree' ;
1912import SelectedElement from './SelectedElement' ;
2013import { InspectedElementContextController } from './InspectedElementContext' ;
@@ -79,44 +72,113 @@ const RESIZE_DIRECTIONS: {|
7972 VERTICAL : 'VERTICAL' ,
8073} ;
8174
82- const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${ RESIZE_DIRECTIONS . HORIZONTAL } ` ;
83- const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${ RESIZE_DIRECTIONS . VERTICAL } ` ;
84-
85- function ComponentResizer ( { children} ) : { | children: Function | } {
86- const [ isResizing , setIsResizing ] = useState < boolean > ( false ) ;
75+ function createResizeReducer ( wrapperRef ) {
76+ const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${ RESIZE_DIRECTIONS . HORIZONTAL } ` ;
77+ const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${ RESIZE_DIRECTIONS . VERTICAL } ` ;
8778 const [
8879 horizontalPercentage ,
8980 setHorizontalPercentage ,
90- ] = useLocalStorage < number > (
81+ ] = useLocalStorage < string > (
9182 LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY ,
92- 65 ,
83+ '65%' ,
9384 ) ;
94- const [ verticalPercentage , setVerticalPercentage ] = useLocalStorage < number > (
85+ const [ verticalPercentage , setVerticalPercentage ] = useLocalStorage < string > (
9586 LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY ,
96- 50 ,
87+ '50%' ,
9788 ) ;
98- const updateLocalStorageTimeoutId = useRef < number > ( null ) ;
99- const componentsWrapperRef = useRef < HTMLDivElement > ( null ) ;
100- const resizeElementRef = useRef < HTMLElement > ( null ) ;
101- const [ resizeElementStyles , setResizeElementStyles ] = useState < Object > ( { } ) ;
102- const getResizeDirection : Function = useCallback ( ( ) => {
103- if ( componentsWrapperRef . current === null ) {
104- return RESIZE_DIRECTIONS . HORIZONTAL ;
89+ const resizeTimeout = useRef ( null ) ;
90+
91+ const getResizeDirection : Function = ref => ( ) => {
92+ if ( ref . current != null ) {
93+ const VERTICAL_MODE_MAX_WIDTH : number = 600 ;
94+ const { width} = ref . current . getBoundingClientRect ( ) ;
95+
96+ return width > VERTICAL_MODE_MAX_WIDTH
97+ ? RESIZE_DIRECTIONS . HORIZONTAL
98+ : RESIZE_DIRECTIONS . VERTICAL ;
99+ }
100+
101+ return RESIZE_DIRECTIONS . HORIZONTAL ;
102+ } ;
103+
104+ // We need to watch/set for changes to this ref in order to get the correct resize direction.
105+ useEffect ( ( ) => {
106+ if ( wrapperRef . current != null ) {
107+ dispatch ( { type : 'setWrapperRef' , payload : wrapperRef } ) ;
108+ }
109+ } , [ wrapperRef ] ) ;
110+
111+ const initialState = {
112+ wrapperRef : wrapperRef ,
113+ isResizing : false ,
114+ horizontalPercentage,
115+ verticalPercentage,
116+ getResizeDirection : getResizeDirection ( wrapperRef ) ,
117+ } ;
118+
119+ const ACTION_TYPES = {
120+ SET_IS_RESIZING : 'setIsResizing' ,
121+ SET_WRAPPER_REF : 'setWrapperRef' ,
122+ SET_HORIZONTAL_PERCENTAGE : 'setHorizontalPercentage' ,
123+ SET_VERTICAL_PERCENTAGE : 'setVerticalPercentage' ,
124+ } ;
125+
126+ // eslint-disable-next-line no-shadow
127+ const [ state , dispatch ] = useReducer ( ( state , action ) => {
128+ switch ( action . type ) {
129+ case ACTION_TYPES . SET_IS_RESIZING :
130+ return {
131+ ...state ,
132+ isResizing : action . payload ,
133+ } ;
134+ case ACTION_TYPES . SET_WRAPPER_REF :
135+ return {
136+ ...state ,
137+ wrapperRef : action . payload ,
138+ getResizeDirection : getResizeDirection ( action . payload ) ,
139+ } ;
140+ case ACTION_TYPES . SET_HORIZONTAL_PERCENTAGE :
141+ case ACTION_TYPES . SET_VERTICAL_PERCENTAGE :
142+ const percentageState = {
143+ [ action . type === ACTION_TYPES . SET_HORIZONTAL_PERCENTAGE
144+ ? 'horizontalPercentage'
145+ : 'verticalPercentage' ] : action . payload ,
146+ } ;
147+
148+ clearTimeout ( resizeTimeout . current ) ;
149+ resizeTimeout . current = setTimeout ( ( ) => {
150+ if ( action . type === ACTION_TYPES . SET_HORIZONTAL_PERCENTAGE ) {
151+ setHorizontalPercentage ( action . payload ) ;
152+ } else {
153+ setVerticalPercentage ( action . payload ) ;
154+ }
155+ } , 400 ) ;
156+
157+ return {
158+ ...state ,
159+ ...percentageState ,
160+ } ;
161+ default :
162+ return state ;
105163 }
106- const VERTICAL_MODE_MAX_WIDTH : number = 600 ;
107- const { width} = componentsWrapperRef . current . getBoundingClientRect ( ) ;
164+ } , initialState ) ;
108165
109- return width > VERTICAL_MODE_MAX_WIDTH
110- ? RESIZE_DIRECTIONS . HORIZONTAL
111- : RESIZE_DIRECTIONS . VERTICAL ;
112- } , [ componentsWrapperRef ] ) ;
166+ return [ state , dispatch , ACTION_TYPES ] ;
167+ }
113168
114- const onResizeStart = ( ) => setIsResizing ( true ) ;
115- const onResizeEnd = ( ) => setIsResizing ( false ) ;
169+ function ComponentResizer ( { children} ) : { | children : Function | } {
170+ const componentsWrapperRef = useRef < HTMLDivElement > ( null ) ;
171+ const resizeElementRef = useRef < HTMLElement > ( null ) ;
172+ const [ state , dispatch , ACTION_TYPES ] = createResizeReducer ( componentsWrapperRef ) ;
173+
174+ const onResizeStart = ( ) =>
175+ dispatch ( { type : ACTION_TYPES . SET_IS_RESIZING , payload : true } ) ;
176+ const onResizeEnd = ( ) =>
177+ dispatch ( { type : ACTION_TYPES . SET_IS_RESIZING , payload : false } ) ;
116178 const onResize = e => {
117179 if (
118- ! isResizing ||
119- componentsWrapperRef . current === null ||
180+ ! state . isResizing ||
181+ state . wrapperRef . current === null ||
120182 resizeElementRef . current === null
121183 ) {
122184 return ;
@@ -129,13 +191,14 @@ function ComponentResizer({children}): {|children: Function|} {
129191 width,
130192 left,
131193 top,
132- } = componentsWrapperRef . current . getBoundingClientRect ( ) ;
133- const resizeDirection = getResizeDirection ( ) ;
194+ } = state . wrapperRef . current . getBoundingClientRect ( ) ;
195+ const resizeDirection = state . getResizeDirection ( ) ;
196+
134197 const currentMousePosition : number =
135198 resizeDirection === RESIZE_DIRECTIONS . HORIZONTAL
136199 ? e . clientX - left
137200 : e . clientY - top ;
138- const BOUNDARY_PADDING : number = 40 ;
201+ const BOUNDARY_PADDING : number = 42 ;
139202 const boundary : { |
140203 min : number ,
141204 max : number ,
@@ -153,42 +216,31 @@ function ComponentResizer({children}): {|children: Function|} {
153216 if ( isMousePositionInBounds ) {
154217 const resizedElementDimension : number =
155218 resizeDirection === RESIZE_DIRECTIONS . HORIZONTAL ? width : height ;
156- const updatedFlexBasisValue : number =
157- ( currentMousePosition / resizedElementDimension ) * 100 ;
158-
159- resizeElementRef . current . style . flexBasis = `${ updatedFlexBasisValue } %` ;
160-
161- clearTimeout ( updateLocalStorageTimeoutId . current ) ;
219+ const updatedFlexBasisValue : string = `${ ( currentMousePosition /
220+ resizedElementDimension ) *
221+ 100 } %`;
222+ const SET_PERCENTAGE_ACTION =
223+ resizeDirection === RESIZE_DIRECTIONS . HORIZONTAL
224+ ? ACTION_TYPES . SET_HORIZONTAL_PERCENTAGE
225+ : ACTION_TYPES . SET_VERTICAL_PERCENTAGE ;
162226
163- updateLocalStorageTimeoutId . current = setTimeout ( ( ) => {
164- if ( resizeDirection === RESIZE_DIRECTIONS . HORIZONTAL ) {
165- setHorizontalPercentage ( updatedFlexBasisValue ) ;
166- } else {
167- setVerticalPercentage ( updatedFlexBasisValue ) ;
168- }
169- } , 500 ) ;
227+ resizeElementRef . current . style . flexBasis = updatedFlexBasisValue ;
228+ dispatch ( { type : SET_PERCENTAGE_ACTION , payload : updatedFlexBasisValue } ) ;
170229 }
171230 } ;
172231
173- useLayoutEffect ( ( ) => {
174- if ( componentsWrapperRef . current !== null ) {
175- if ( getResizeDirection ( ) === RESIZE_DIRECTIONS . HORIZONTAL ) {
176- setResizeElementStyles ( {
177- flexBasis : `${ horizontalPercentage } %` ,
178- } ) ;
179- } else {
180- setResizeElementStyles ( {
181- flexBasis : `${ verticalPercentage } %` ,
182- } ) ;
183- }
184- }
185- } , [ componentsWrapperRef , horizontalPercentage , verticalPercentage ] ) ;
232+ const resizeElementStyles = {
233+ flexBasis :
234+ state . getResizeDirection ( ) === RESIZE_DIRECTIONS . HORIZONTAL
235+ ? state . horizontalPercentage
236+ : state . verticalPercentage ,
237+ } ;
186238
187239 return (
188240 < div
189241 ref = { componentsWrapperRef}
190242 className = { styles . ComponentsWrapper}
191- { ...( isResizing && {
243+ { ...( state . isResizing && {
192244 onMouseMove : onResize ,
193245 onMouseLeave : onResizeEnd ,
194246 onMouseUp : onResizeEnd ,
0 commit comments