@@ -41,9 +41,19 @@ type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = (
4141 h : number ,
4242 Data
4343) => void ;
44+ type GridItemResizeCallback = (
45+ e : Event ,
46+ data : ResizeCallbackData ,
47+ position : Position
48+ ) => void ;
49+ type ResizeCallbackData = {
50+ node : HTMLElement ,
51+ size : Position ,
52+ handle : string
53+ } ;
4454
4555type State = {
46- resizing : ?{ width : number , height : number } ,
56+ resizing : ?{ top : number , left : number , width : number , height : number } ,
4757 dragging : ?{ top : number , left : number } ,
4858 className : string
4959} ;
@@ -356,6 +366,15 @@ export default class GridItem extends React.Component<Props, State> {
356366 ) ;
357367 }
358368
369+ /**
370+ * Utility function to setup callback handler definitions for
371+ * similarily structured resize events.
372+ */
373+ curryResizeHandler ( position : Position , handler : function ) : function {
374+ return ( e : Event , data : ResizeCallbackData ) : function =>
375+ handler ( e , data , position ) ;
376+ }
377+
359378 /**
360379 * Mix a Resizable instance into a child.
361380 * @param {Element } child Child element.
@@ -381,13 +400,7 @@ export default class GridItem extends React.Component<Props, State> {
381400 const positionParams = this . getPositionParams ( ) ;
382401
383402 // This is the max possible width - doesn't go to infinity because of the width of the window
384- const maxWidth = calcGridItemPosition (
385- positionParams ,
386- 0 ,
387- 0 ,
388- cols - x ,
389- 0
390- ) . width ;
403+ const maxWidth = calcGridItemPosition ( positionParams , 0 , 0 , cols , 0 ) . width ;
391404
392405 // Calculate min/max constraints using our min & maxes
393406 const mins = calcGridItemPosition ( positionParams , 0 , 0 , minW , minH ) ;
@@ -408,9 +421,9 @@ export default class GridItem extends React.Component<Props, State> {
408421 height = { position . height }
409422 minConstraints = { minConstraints }
410423 maxConstraints = { maxConstraints }
411- onResizeStop = { this . onResizeStop }
412- onResizeStart = { this . onResizeStart }
413- onResize = { this . onResize }
424+ onResizeStop = { this . curryResizeHandler ( position , this . onResizeStop ) }
425+ onResizeStart = { this . curryResizeHandler ( position , this . onResizeStart ) }
426+ onResize = { this . curryResizeHandler ( position , this . onResize ) }
414427 transformScale = { transformScale }
415428 resizeHandles = { resizeHandles }
416429 handle = { resizeHandle }
@@ -541,53 +554,31 @@ export default class GridItem extends React.Component<Props, State> {
541554 * @param {Event } e event data
542555 * @param {Object } callbackData an object with node and size information
543556 */
544- onResizeStop : ( Event , { node : HTMLElement , size : Position } ) = > void = (
545- e ,
546- callbackData
547- ) => {
548- this . onResizeHandler ( e , callbackData , "onResizeStop" ) ;
549- } ;
557+ onResizeStop : GridItemResizeCallback = ( e , callbackData , position ) = >
558+ this . onResizeHandler ( e , callbackData , position , "onResizeStop" ) ;
550559
551- /**
552- * onResizeStart event handler
553- * @param {Event } e event data
554- * @param {Object } callbackData an object with node and size information
555- */
556- onResizeStart : ( Event , { node : HTMLElement , size : Position } ) = > void = (
557- e ,
558- callbackData
559- ) => {
560- this . onResizeHandler ( e , callbackData , "onResizeStart" ) ;
561- } ;
560+ // onResizeStart event handler
561+ onResizeStart : GridItemResizeCallback = ( e , callbackData , position ) = >
562+ this . onResizeHandler ( e , callbackData , position , "onResizeStart" ) ;
562563
563- /**
564- * onResize event handler
565- * @param {Event } e event data
566- * @param {Object } callbackData an object with node and size information
567- */
568- onResize : ( Event , { node : HTMLElement , size : Position } ) = > void = (
569- e ,
570- callbackData
571- ) => {
572- this . onResizeHandler ( e , callbackData , "onResize" ) ;
573- } ;
564+ // onResize event handler
565+ onResize : GridItemResizeCallback = ( e , callbackData , position ) = >
566+ this . onResizeHandler ( e , callbackData , position , "onResize" ) ;
574567
575568 /**
576569 * Wrapper around drag events to provide more useful data.
577570 * All drag events call the function with the given handler name,
578571 * with the signature (index, x, y).
579- *
580- * @param {String } handlerName Handler name to wrap.
581- * @return {Function } Handler function.
582572 */
583573 onResizeHandler (
584574 e : Event ,
585- { node, size } : { node : HTMLElement , size : Position } ,
575+ { node, size, handle } : ResizeCallbackData ,
576+ position : Position ,
586577 handlerName : string
587578 ) : void {
588579 const handler = this . props [ handlerName ] ;
589580 if ( ! handler ) return ;
590- const { cols , x , y , i , maxH , minH } = this . props ;
581+ const { x , y , i , maxH , minH } = this . props ;
591582 let { minW, maxW } = this . props ;
592583
593584 // Get new XY
@@ -596,22 +587,121 @@ export default class GridItem extends React.Component<Props, State> {
596587 size . width ,
597588 size . height ,
598589 x ,
599- y
590+ y ,
591+ handle
600592 ) ;
601593
602594 // minW should be at least 1 (TODO propTypes validation?)
603595 minW = Math . max ( minW , 1 ) ;
604596
605- // maxW should be at most (cols - x)
606- maxW = Math . min ( maxW , cols - x ) ;
607-
608597 // Min/max capping
609598 w = clamp ( w , minW , maxW ) ;
610599 h = clamp ( h , minH , maxH ) ;
611600
612- this . setState ( { resizing : handlerName === "onResizeStop" ? null : size } ) ;
601+ let updatedSize = size ;
602+ if ( node ) {
603+ const currentLeft = position . left ;
604+ const currentTop = position . top ;
605+ const currentWidth = position . width ;
606+ const currentHeight = position . height ;
607+
608+ const resizeNorth = ( { left, height, width } ) => {
609+ const top = currentTop - ( height - currentHeight ) ;
610+
611+ return {
612+ top,
613+ left,
614+ width,
615+ height : this . constrainHeight ( top , currentHeight , height ) ,
616+ top : this . constrainTop ( top )
617+ } ;
618+ } ;
619+
620+ const resizeEast = ( { top, left, height, width } ) => ( {
621+ top,
622+ height,
623+ width : this . constrainWidth ( currentLeft , currentWidth , width ) ,
624+ left : this . constrainLeft ( left )
625+ } ) ;
626+
627+ const resizeWest = ( { top, height, width } ) => {
628+ const left = currentLeft - ( width - currentWidth ) ;
629+
630+ return {
631+ height,
632+ width :
633+ left <= 0
634+ ? currentWidth
635+ : this . constrainWidth ( currentLeft , currentWidth , width ) ,
636+ top : this . constrainTop ( top ) ,
637+ left : this . constrainLeft ( left )
638+ } ;
639+ } ;
640+
641+ const resizeSouth = ( { top, left, height, width } ) = > ( {
642+ width,
643+ left,
644+ height : this . constrainHeight ( top , currentHeight , height ) ,
645+ top : this . constrainTop ( top )
646+ } ) ;
647+
648+ const resizeNorthEast = ( ...args ) = > resizeNorth ( resizeEast ( ...args ) ) ;
649+ const resizeNorthWest = ( ...args ) = > resizeNorth ( resizeWest ( ...args ) ) ;
650+ const resizeSouthEast = ( ...args ) = > resizeSouth ( resizeEast ( ...args ) ) ;
651+ const resizeSouthWest = ( ...args ) = > resizeSouth ( resizeWest ( ...args ) ) ;
652+
653+ const ordinalResizeHandlerMap = {
654+ n : resizeNorth ,
655+ ne : resizeNorthEast ,
656+ e : resizeEast ,
657+ se : resizeSouthEast ,
658+ s : resizeSouth ,
659+ sw : resizeSouthWest ,
660+ w : resizeWest ,
661+ nw : resizeNorthWest
662+ } ;
663+
664+ const resizeHandler = ordinalResizeHandlerMap [ handle ] ;
665+ updatedSize = resizeHandler
666+ ? resizeHandler ( {
667+ top : currentTop ,
668+ left : currentLeft ,
669+ height : currentHeight ,
670+ width : currentWidth ,
671+ ...size
672+ } )
673+ : size ;
674+ this . setState ( {
675+ resizing : handlerName === "onResizeStop" ? null : updatedSize
676+ } ) ;
677+ }
678+
679+ handler . call ( this , i , w , h , { e, node, size : updatedSize , handle } ) ;
680+ }
681+
682+ /**
683+ * Helper functions to constrain dimensions of a GridItem
684+ */
685+ constrainWidth ( left : number , currentWidth : number , newWidth : number ) : number {
686+ return left + newWidth > this . props . containerWidth
687+ ? currentWidth
688+ : newWidth ;
689+ }
690+
691+ constrainHeight (
692+ top : number ,
693+ currentHeight : number ,
694+ newHeight : number
695+ ) : number {
696+ return top <= 0 ? currentHeight : newHeight ;
697+ }
698+
699+ constrainLeft ( left : number ) : number {
700+ return Math . max ( 0 , left ) ;
701+ }
613702
614- handler . call ( this , i , w , h , { e, node, size } ) ;
703+ constrainTop ( top : number ) : number {
704+ return Math . max ( 0 , top ) ;
615705 }
616706
617707 render ( ) : ReactNode {
0 commit comments