66import { DDResizableHandle } from './dd-resizable-handle' ;
77import { DDBaseImplement , HTMLElementExtendOpt } from './dd-base-impl' ;
88import { Utils } from './utils' ;
9- import { DDResizeOpt , DDUIData , GridItemHTMLElement , GridStackMouseEvent , Rect , Size } from './types' ;
9+ import { DDResizeOpt , DDUIData , GridItemHTMLElement , GridStackMouseEvent , Size } from './types' ;
1010import { DDManager } from './dd-manager' ;
1111
1212// import { GridItemHTMLElement } from './types'; let count = 0; // TEST
@@ -22,22 +22,31 @@ export interface DDResizableOpt extends DDResizeOpt {
2222 start ?: ( event : Event , ui : DDUIData ) => void ;
2323 stop ?: ( event : Event ) => void ;
2424 resize ?: ( event : Event , ui : DDUIData ) => void ;
25+ rtl ?: boolean ;
2526}
2627
2728interface RectScaleReciprocal {
2829 x : number ;
2930 y : number ;
3031}
3132
33+ interface TemporalRect {
34+ width : number ;
35+ height : number ;
36+ left : number ;
37+ right : number ;
38+ top : number ;
39+ }
40+
3241export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt < DDResizableOpt > {
3342 /** @internal */
3443 protected handlers : DDResizableHandle [ ] ;
3544 /** @internal */
36- protected originalRect : Rect ;
45+ protected originalRect : DOMRectReadOnly ;
3746 /** @internal */
3847 protected rectScale : RectScaleReciprocal = { x : 1 , y : 1 } ;
3948 /** @internal */
40- protected temporalRect : Rect ;
49+ protected temporalRect : TemporalRect ;
4150 /** @internal */
4251 protected scrollY : number ;
4352 /** @internal */
@@ -51,7 +60,7 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
5160 /** @internal */
5261 protected parentOriginStylePosition : string ;
5362 /** @internal */
54- protected static _originStyleProp = [ 'width' , 'height' , 'position' , 'left' , 'top' , 'opacity' , 'zIndex' ] ;
63+ protected static _originStyleProp = [ 'width' , 'height' , 'position' , 'left' , 'right' , ' top', 'opacity' , 'zIndex' ] ;
5564 /** @internal */
5665 protected sizeToContent : boolean ;
5766
@@ -185,6 +194,8 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
185194 this . _applyChange ( ) ;
186195 const ev = Utils . initEvent < GridStackMouseEvent > ( event , { type : 'resize' , target : this . el } ) ;
187196 ev . resizeDir = dir ; // expose handle direction so _dragOrResize can avoid position drift
197+ ev . hasMovedX = this . option . rtl ? dir . includes ( 'e' ) : dir . includes ( 'w' ) ;
198+ ev . hasMovedY = dir . includes ( 'n' ) ;
188199 if ( this . option . resize ) {
189200 this . option . resize ( ev , this . _ui ( ) ) ;
190201 }
@@ -240,38 +251,51 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
240251 }
241252
242253 /** @internal */
243- protected _getChange ( event : MouseEvent , dir : string ) : Rect {
254+ protected _getChange ( event : MouseEvent , dir : string ) : TemporalRect {
244255 const oEvent = this . startEvent ;
245256 const newRect = { // Note: originalRect is a complex object, not a simple Rect, so copy out.
246257 width : this . originalRect . width ,
247258 height : this . originalRect . height + this . scrolled ,
248259 left : this . originalRect . left ,
249- top : this . originalRect . top - this . scrolled
260+ right : this . originalRect . right ,
261+ top : this . originalRect . top - this . scrolled ,
250262 } ;
251263
252264 const offsetX = event . clientX - oEvent . clientX ;
253265 const offsetY = this . sizeToContent ? 0 : event . clientY - oEvent . clientY ; // prevent vert resize
254266 let moveLeft : boolean ;
255267 let moveUp : boolean ;
256268
257- if ( dir . indexOf ( 'e' ) > - 1 ) {
269+ const isRtl = this . option . rtl ;
270+
271+ if ( ! isRtl && dir . indexOf ( 'e' ) > - 1 ) {
258272 newRect . width += offsetX ;
259- } else if ( dir . indexOf ( 'w' ) > - 1 ) {
273+ } else if ( isRtl && dir . indexOf ( 'w' ) > - 1 ) {
274+ newRect . width -= offsetX ;
275+ } else if ( ! isRtl && dir . indexOf ( 'w' ) > - 1 ) {
260276 newRect . width -= offsetX ;
261277 newRect . left += offsetX ;
262278 moveLeft = true ;
279+ } else if ( isRtl && dir . indexOf ( 'e' ) > - 1 ) {
280+ newRect . width += offsetX ;
281+ newRect . right += offsetX ;
282+ moveLeft = true ;
263283 }
284+
264285 if ( dir . indexOf ( 's' ) > - 1 ) {
265286 newRect . height += offsetY ;
266287 } else if ( dir . indexOf ( 'n' ) > - 1 ) {
267288 newRect . height -= offsetY ;
268289 newRect . top += offsetY
269290 moveUp = true ;
270291 }
292+
271293 const constrain = this . _constrainSize ( newRect . width , newRect . height , moveLeft , moveUp ) ;
272294 if ( Math . round ( newRect . width ) !== Math . round ( constrain . width ) ) { // round to ignore slight round-off errors
273- if ( dir . indexOf ( 'w' ) > - 1 ) {
295+ if ( ! isRtl && dir . indexOf ( 'w' ) > - 1 ) {
274296 newRect . left += newRect . width - constrain . width ;
297+ } else if ( isRtl && dir . indexOf ( 'e' ) > - 1 ) {
298+ newRect . right -= newRect . width - constrain . width ;
275299 }
276300 newRect . width = constrain . width ;
277301 }
@@ -298,17 +322,29 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
298322
299323 /** @internal */
300324 protected _applyChange ( ) : DDResizable {
301- let containmentRect = { left : 0 , top : 0 , width : 0 , height : 0 } ;
325+ let containmentRect = { left : 0 , right : 0 , top : 0 , width : 0 , height : 0 } ;
302326 if ( this . el . style . position === 'absolute' ) {
303327 const containmentEl = this . el . parentElement ;
304- const { left, top } = containmentEl . getBoundingClientRect ( ) ;
305- containmentRect = { left, top, width : 0 , height : 0 } ;
328+ const { left, right , top } = containmentEl . getBoundingClientRect ( ) ;
329+ containmentRect = { left, right , top, width : 0 , height : 0 } ;
306330 }
307331 if ( ! this . temporalRect ) return this ;
308- Object . keys ( this . temporalRect ) . forEach ( key => {
309- const value = this . temporalRect [ key ] ;
310- const scaleReciprocal = key === 'width' || key === 'left' ? this . rectScale . x : key === 'height' || key === 'top' ? this . rectScale . y : 1 ;
311- this . el . style [ key ] = ( value - containmentRect [ key ] ) * scaleReciprocal + 'px' ;
332+ Object . entries ( this . temporalRect ) . forEach ( ( [ key , value ] ) => {
333+ if ( this . option . rtl ? key === 'left' : key === 'right' )
334+ return ;
335+
336+ const scaleReciprocal = key === 'width' || key === 'left' || key === 'right'
337+ ? this . rectScale . x
338+ : key === 'height' || key === 'top'
339+ ? this . rectScale . y
340+ : 1 ;
341+ let finalValue : string ;
342+ if ( key === 'right' ) {
343+ finalValue = ( containmentRect . right - value ) * this . rectScale . x + 'px' ;
344+ } else {
345+ finalValue = ( value - containmentRect [ key ] ) * scaleReciprocal + 'px' ;
346+ }
347+ this . el . style [ key ] = finalValue ;
312348 } ) ;
313349 return this ;
314350 }
@@ -328,12 +364,17 @@ export class DDResizable extends DDBaseImplement implements HTMLElementExtendOpt
328364 width : this . originalRect . width ,
329365 height : this . originalRect . height + this . scrolled ,
330366 left : this . originalRect . left ,
367+ right : this . originalRect . right ,
331368 top : this . originalRect . top - this . scrolled
332369 } ;
333370 const rect = this . temporalRect || newRect ;
371+
372+ const leftPos = this . option . rtl
373+ ? ( containmentRect . right - rect . right ) * this . rectScale . x
374+ : ( rect . left - containmentRect . left ) * this . rectScale . x ;
334375 return {
335376 position : {
336- left : ( rect . left - containmentRect . left ) * this . rectScale . x ,
377+ left : leftPos ,
337378 top : ( rect . top - containmentRect . top ) * this . rectScale . y
338379 } ,
339380 size : {
0 commit comments