@@ -6,6 +6,7 @@ import cloneElement from './cloneElement';
6
6
import type { Element as ReactElement , Node as ReactNode } from 'react' ;
7
7
8
8
type Axis = 'both' | 'x' | 'y' | 'none' ;
9
+ type ResizeHandle = 's' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne' ;
9
10
type State = {
10
11
resizing : boolean ,
11
12
width : number , height : number ,
@@ -35,7 +36,8 @@ export type Props = {
35
36
onResizeStop ?: ?( e : SyntheticEvent < > , data : ResizeCallbackData ) => any ,
36
37
onResizeStart ?: ?( e : SyntheticEvent < > , data : ResizeCallbackData ) => any ,
37
38
onResize ?: ?( e : SyntheticEvent < > , data : ResizeCallbackData ) => any ,
38
- draggableOpts ?: ?Object
39
+ draggableOpts ?: ?Object ,
40
+ resizeHandles ?: ?ResizeHandle [ ]
39
41
} ;
40
42
41
43
export default class Resizable extends React . Component < Props , State > {
@@ -61,6 +63,18 @@ export default class Resizable extends React.Component<Props, State> {
61
63
// If you change this, be sure to update your css
62
64
handleSize : PropTypes . array ,
63
65
66
+ // Defines which resize handles should be rendered (default: 'se')
67
+ // Allows for any combination of:
68
+ // 's' - South handle (bottom-center)
69
+ // 'w' - West handle (left-center)
70
+ // 'e' - East handle (right-center)
71
+ // 'n' - North handle (top-center)
72
+ // 'sw' - Southwest handle (bottom-left)
73
+ // 'nw' - Northwest handle (top-left)
74
+ // 'se' - Southeast handle (bottom-right)
75
+ // 'ne' - Northeast handle (top-center)
76
+ resizeHandles : PropTypes . arrayOf ( PropTypes . oneOf ( [ 's' , 'w' , 'e' , 'n' , 'sw' , 'nw' , 'se' , 'ne' ] ) ) ,
77
+
64
78
// If true, will only allow width/height to move in lockstep
65
79
lockAspectRatio : PropTypes . bool ,
66
80
@@ -89,7 +103,8 @@ export default class Resizable extends React.Component<Props, State> {
89
103
lockAspectRatio : false ,
90
104
axis : 'both' ,
91
105
minConstraints : [ 20 , 20 ] ,
92
- maxConstraints : [ Infinity , Infinity ]
106
+ maxConstraints : [ Infinity , Infinity ] ,
107
+ resizeHandles : [ 'se' ]
93
108
} ;
94
109
95
110
state : State = {
@@ -161,12 +176,19 @@ export default class Resizable extends React.Component<Props, State> {
161
176
* @param {String } handlerName Handler name to wrap.
162
177
* @return {Function } Handler function.
163
178
*/
164
- resizeHandler ( handlerName : string ) : Function {
179
+ resizeHandler ( handlerName : string , axis : ResizeHandle ) : Function {
165
180
return ( e : SyntheticEvent < > | MouseEvent , { node , deltaX , deltaY } : DragCallbackData ) => {
166
181
167
182
// Axis restrictions
168
- const canDragX = this . props . axis === 'both' || this . props . axis === 'x' ;
169
- const canDragY = this . props . axis === 'both' || this . props . axis === 'y' ;
183
+ const canDragX = ( this . props . axis === 'both' || this . props . axis === 'x' ) && [ 'n' , 's' ] . indexOf ( axis ) === - 1 ;
184
+ const canDragY = ( this . props . axis === 'both' || this . props . axis === 'y' ) && [ 'e' , 'w' ] . indexOf ( axis ) === - 1 ;
185
+
186
+ if ( axis [ 0 ] === 'n' ) {
187
+ deltaY = - deltaY ;
188
+ }
189
+ if ( axis [ axis . length - 1 ] === 'w' ) {
190
+ deltaX = - deltaX ;
191
+ }
170
192
171
193
// Update w/h
172
194
let width = this . state . width + ( canDragX ? deltaX : 0 ) ;
@@ -202,9 +224,27 @@ export default class Resizable extends React.Component<Props, State> {
202
224
} ;
203
225
}
204
226
227
+ renderResizeHandles ( ) : ReactNode {
228
+ const { draggableOpts, handle, resizeHandles} = this . props ;
229
+ if ( handle ) {
230
+ return handle ;
231
+ }
232
+ return resizeHandles . map ( h => (
233
+ < DraggableCore
234
+ { ...draggableOpts }
235
+ key = { `resizableHandle-${ h } ` }
236
+ onStop = { this . resizeHandler ( 'onResizeStop' , h ) }
237
+ onStart = { this . resizeHandler ( 'onResizeStart' , h ) }
238
+ onDrag = { this . resizeHandler ( 'onResize' , h ) }
239
+ >
240
+ < span key = { h } className = { `react-resizable-handle react-resizable-handle-${ h } ` } />
241
+ </ DraggableCore >
242
+ ) ) ;
243
+ }
244
+
205
245
render ( ) : ReactNode {
206
246
// eslint-disable-next-line no-unused-vars
207
- const { children, draggableOpts , width, height, handle, handleSize,
247
+ const { children, width, height, handle, handleSize,
208
248
lockAspectRatio, axis, minConstraints, maxConstraints, onResize,
209
249
onResizeStop, onResizeStart, ...p } = this . props ;
210
250
@@ -215,21 +255,13 @@ export default class Resizable extends React.Component<Props, State> {
215
255
// What we're doing here is getting the child of this element, and cloning it with this element's props.
216
256
// We are then defining its children as:
217
257
// Its original children (resizable's child's children), and
218
- // A draggable handle .
258
+ // One or more draggable handles .
219
259
return cloneElement ( children , {
220
260
...p ,
221
261
className,
222
262
children : [
223
263
children . props . children ,
224
- < DraggableCore
225
- { ...draggableOpts }
226
- key = "resizableHandle"
227
- onStop = { this . resizeHandler ( 'onResizeStop' ) }
228
- onStart = { this . resizeHandler ( 'onResizeStart' ) }
229
- onDrag = { this . resizeHandler ( 'onResize' ) }
230
- >
231
- { handle || < span className = "react-resizable-handle" /> }
232
- </ DraggableCore >
264
+ this . renderResizeHandles ( )
233
265
]
234
266
} ) ;
235
267
}
0 commit comments