7
7
* @flow
8
8
*/
9
9
10
- import type { ElementRef } from 'react' ;
11
-
12
10
import * as React from 'react' ;
13
11
import { useEffect , useLayoutEffect , useReducer , useRef } from 'react' ;
14
12
import {
@@ -21,86 +19,6 @@ const LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer';
21
19
const VERTICAL_MODE_MAX_WIDTH = 600 ;
22
20
const MINIMUM_SIZE = 50 ;
23
21
24
- type Props = { |
25
- children : ( {
26
- resizeElementRef : ElementRef < HTMLElement > ,
27
- onResizeStart : ( ) => void ,
28
- } ) => React$Node ,
29
- | } ;
30
-
31
- export default function ComponentsResizer ( { children} : Props ) {
32
- const wrapperElementRef = useRef < HTMLDivElement > ( null ) ;
33
- const resizeElementRef = useRef < HTMLElement > ( null ) ;
34
- const [ state , dispatch ] = createResizeReducer (
35
- wrapperElementRef ,
36
- resizeElementRef ,
37
- ) ;
38
-
39
- const { isResizing} = state ;
40
-
41
- const onResizeStart = ( ) =>
42
- dispatch ( { type : 'ACTION_SET_IS_RESIZING' , payload : true } ) ;
43
- const onResizeEnd = ( ) =>
44
- dispatch ( { type : 'ACTION_SET_IS_RESIZING' , payload : false } ) ;
45
-
46
- const onResize = event => {
47
- const resizeElement = resizeElementRef . current ;
48
- const wrapperElement = wrapperElementRef . current ;
49
-
50
- if ( ! isResizing || wrapperElement === null || resizeElement === null ) {
51
- return ;
52
- }
53
-
54
- event . preventDefault ( ) ;
55
-
56
- const orientation = getOrientation ( wrapperElementRef ) ;
57
-
58
- const { height, width, left, top} = wrapperElement . getBoundingClientRect ( ) ;
59
-
60
- const currentMousePosition =
61
- orientation === 'horizontal' ? event . clientX - left : event . clientY - top ;
62
-
63
- const boundaryMin = MINIMUM_SIZE ;
64
- const boundaryMax =
65
- orientation === 'horizontal'
66
- ? width - MINIMUM_SIZE
67
- : height - MINIMUM_SIZE ;
68
-
69
- const isMousePositionInBounds =
70
- currentMousePosition > boundaryMin && currentMousePosition < boundaryMax ;
71
-
72
- if ( isMousePositionInBounds ) {
73
- const resizedElementDimension =
74
- orientation === 'horizontal' ? width : height ;
75
- const actionType =
76
- orientation === 'horizontal'
77
- ? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
78
- : 'ACTION_SET_VERTICAL_PERCENTAGE' ;
79
- const percentage = ( currentMousePosition / resizedElementDimension ) * 100 ;
80
-
81
- setResizeCSSVariable ( resizeElementRef , orientation , percentage ) ;
82
-
83
- dispatch ( {
84
- type : actionType ,
85
- payload : currentMousePosition / resizedElementDimension ,
86
- } ) ;
87
- }
88
- } ;
89
-
90
- return (
91
- < div
92
- ref = { wrapperElementRef }
93
- className = { styles . ComponentsWrapper }
94
- { ...( isResizing && {
95
- onMouseMove : onResize ,
96
- onMouseLeave : onResizeEnd ,
97
- onMouseUp : onResizeEnd ,
98
- } ) } >
99
- { children ( { resizeElementRef, onResizeStart} ) }
100
- </ div >
101
- ) ;
102
- }
103
-
104
22
type Orientation = 'horizontal' | 'vertical' ;
105
23
106
24
type ResizeActionType =
@@ -162,67 +80,34 @@ function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {
162
80
}
163
81
}
164
82
165
- function getOrientation (
166
- wrapperElementRef : ElementRef < HTMLElement > ,
167
- ) : null | Orientation {
168
- const wrapperElement = wrapperElementRef . current ;
169
- if ( wrapperElement != null ) {
170
- const { width} = wrapperElement . getBoundingClientRect ( ) ;
171
- return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical' ;
172
- }
173
- return null ;
174
- }
175
-
176
- function setResizeCSSVariable (
177
- resizeElementRef : ElementRef < HTMLElement > ,
178
- orientation : null | Orientation ,
179
- percentage : number ,
180
- ) : void {
181
- const resizeElement = resizeElementRef . current ;
83
+ type Props = { |
84
+ children : ( {
85
+ resizeElementRef : React$Ref < HTMLElement > ,
86
+ onResizeStart : ( ) => void ,
87
+ } ) => React$Node ,
88
+ | } ;
182
89
183
- if ( resizeElement !== null && orientation !== null ) {
184
- resizeElement . style . setProperty (
185
- `--${ orientation } -resize-percentage` ,
186
- `${ percentage } %` ,
187
- ) ;
188
- }
189
- }
90
+ export default function ComponentsResizer ( { children} : Props ) {
91
+ const wrapperElementRef = useRef < HTMLElement > ( null ) ;
92
+ const resizeElementRef = useRef < HTMLElement > ( null ) ;
190
93
191
- function createResizeReducer ( wrapperElementRef , resizeElementRef ) {
192
94
const [ state , dispatch ] = useReducer < ResizeState , ResizeAction > (
193
95
resizeReducer ,
194
96
null ,
195
97
initResizeState ,
196
98
) ;
99
+
197
100
const { horizontalPercentage, verticalPercentage} = state ;
198
101
199
- // Initial set up for the resize percentage CSS variables.
200
102
useLayoutEffect ( ( ) => {
201
- const orientationAndPercentage = {
202
- horizontal : horizontalPercentage ,
203
- vertical : verticalPercentage ,
204
- } ;
205
-
206
- Object . keys ( orientationAndPercentage ) . forEach ( orientation => {
207
- setResizeCSSVariable (
208
- resizeElementRef ,
209
- orientation ,
210
- orientationAndPercentage [ orientation ] * 100 ,
211
- ) ;
212
- } ) ;
213
- } , [ ] ) ;
103
+ const resizeElement = resizeElementRef . current ;
214
104
215
- useLayoutEffect ( ( ) => {
216
105
setResizeCSSVariable (
217
- resizeElementRef ,
106
+ resizeElement ,
218
107
'horizontal' ,
219
108
horizontalPercentage * 100 ,
220
109
) ;
221
- setResizeCSSVariable (
222
- resizeElementRef ,
223
- 'vertical' ,
224
- verticalPercentage * 100 ,
225
- ) ;
110
+ setResizeCSSVariable ( resizeElement , 'vertical' , verticalPercentage * 100 ) ;
226
111
} , [ ] ) ;
227
112
228
113
useEffect ( ( ) => {
@@ -239,5 +124,90 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) {
239
124
return ( ) => clearTimeout ( timeoutID ) ;
240
125
} , [ horizontalPercentage , verticalPercentage ] ) ;
241
126
242
- return [ state , dispatch ] ;
127
+ const { isResizing} = state ;
128
+
129
+ const onResizeStart = ( ) =>
130
+ dispatch ( { type : 'ACTION_SET_IS_RESIZING' , payload : true } ) ;
131
+ const onResizeEnd = ( ) =>
132
+ dispatch ( { type : 'ACTION_SET_IS_RESIZING' , payload : false } ) ;
133
+
134
+ const onResize = event => {
135
+ const resizeElement = resizeElementRef . current ;
136
+ const wrapperElement = wrapperElementRef . current ;
137
+
138
+ if ( ! isResizing || wrapperElement === null || resizeElement === null ) {
139
+ return ;
140
+ }
141
+
142
+ event . preventDefault ( ) ;
143
+
144
+ const orientation = getOrientation ( wrapperElement ) ;
145
+
146
+ const { height, width, left, top} = wrapperElement . getBoundingClientRect ( ) ;
147
+
148
+ const currentMousePosition =
149
+ orientation === 'horizontal' ? event . clientX - left : event . clientY - top ;
150
+
151
+ const boundaryMin = MINIMUM_SIZE ;
152
+ const boundaryMax =
153
+ orientation === 'horizontal'
154
+ ? width - MINIMUM_SIZE
155
+ : height - MINIMUM_SIZE ;
156
+
157
+ const isMousePositionInBounds =
158
+ currentMousePosition > boundaryMin && currentMousePosition < boundaryMax ;
159
+
160
+ if ( isMousePositionInBounds ) {
161
+ const resizedElementDimension =
162
+ orientation === 'horizontal' ? width : height ;
163
+ const actionType =
164
+ orientation === 'horizontal'
165
+ ? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
166
+ : 'ACTION_SET_VERTICAL_PERCENTAGE' ;
167
+ const percentage = ( currentMousePosition / resizedElementDimension ) * 100 ;
168
+
169
+ setResizeCSSVariable ( resizeElement , orientation , percentage ) ;
170
+
171
+ dispatch ( {
172
+ type : actionType ,
173
+ payload : currentMousePosition / resizedElementDimension ,
174
+ } ) ;
175
+ }
176
+ } ;
177
+
178
+ return (
179
+ < div
180
+ ref = { wrapperElementRef }
181
+ className = { styles . ComponentsWrapper }
182
+ { ...( isResizing && {
183
+ onMouseMove : onResize ,
184
+ onMouseLeave : onResizeEnd ,
185
+ onMouseUp : onResizeEnd ,
186
+ } ) } >
187
+ { children ( { resizeElementRef, onResizeStart} ) }
188
+ </ div >
189
+ ) ;
190
+ }
191
+
192
+ function getOrientation (
193
+ wrapperElement : null | HTMLElement ,
194
+ ) : null | Orientation {
195
+ if ( wrapperElement != null ) {
196
+ const { width} = wrapperElement . getBoundingClientRect ( ) ;
197
+ return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical' ;
198
+ }
199
+ return null ;
200
+ }
201
+
202
+ function setResizeCSSVariable (
203
+ resizeElement : null | HTMLElement ,
204
+ orientation : null | Orientation ,
205
+ percentage : number ,
206
+ ) : void {
207
+ if ( resizeElement !== null && orientation !== null ) {
208
+ resizeElement . style . setProperty (
209
+ `--${ orientation } -resize-percentage` ,
210
+ `${ percentage } %` ,
211
+ ) ;
212
+ }
243
213
}
0 commit comments