@@ -322,3 +322,79 @@ describe("DomEditSelectionChrome with body drag off", () => {
322322 act ( ( ) => root . unmount ( ) ) ;
323323 } ) ;
324324} ) ;
325+
326+ describe ( "DomEditSelectionChrome rect variables" , ( ) => {
327+ const rectA = { left : 40 , top : 30 , width : 200 , height : 100 , editScaleX : 1 , editScaleY : 1 } ;
328+ const rectB = { left : 75.5 , top : 12 , width : 120 , height : 64 , editScaleX : 1 , editScaleY : 1 } ;
329+
330+ function renderAt ( rect : typeof rectA ) {
331+ const element = document . createElement ( "div" ) ;
332+ document . body . append ( element ) ;
333+ const { selection, host, root } = selectionFixture ( element , "#el" , true ) ;
334+ act ( ( ) => {
335+ root . render (
336+ < DomEditSelectionChrome
337+ selection = { selection }
338+ overlayRect = { rect }
339+ allowCanvasMovement
340+ allowBodyDrag
341+ boxRef = { createRef ( ) }
342+ boxChromeClass = ""
343+ boxClipPath = { undefined }
344+ selectionKey = "el"
345+ groupSelectionCount = { 0 }
346+ gestures = { { startGesture : vi . fn ( ) } as never }
347+ onStyleCommit = { vi . fn ( ) }
348+ onBoxClick = { vi . fn ( ) }
349+ /> ,
350+ ) ;
351+ } ) ;
352+ const wrapper = host . firstElementChild as HTMLElement ;
353+ const handles = [
354+ ...host . querySelectorAll < HTMLElement > ( '[aria-label="Rotate selection"], .h-4.w-4' ) ,
355+ host . querySelector < HTMLElement > ( "[data-dom-edit-crop-frame]" ) ! ,
356+ ] ;
357+ // Resolves a handle's position against the wrapper's variables, as the browser does.
358+ const at = ( value : string ) => {
359+ const expr = value
360+ . replace ( / v a r \( ( - - [ \w - ] + ) \) / g, ( _ , name ) => wrapper . style . getPropertyValue ( name ) )
361+ . replace ( / m a x \( / g, "Math.max(" )
362+ . replace ( / c a l c \( / g, "(" )
363+ . replace ( / p x / g, "" ) ;
364+ return Number ( new Function ( `return ${ expr } ` ) ( ) ) ;
365+ } ;
366+ const done = ( ) => {
367+ act ( ( ) => root . unmount ( ) ) ;
368+ host . remove ( ) ;
369+ } ;
370+ return { handles, at, done } ;
371+ }
372+
373+ it ( "moves every handle with the rect while their own styles stay the same" , ( ) => {
374+ const a = renderAt ( rectA ) ;
375+ const b = renderAt ( rectB ) ;
376+ try {
377+ expect ( a . handles ) . toHaveLength ( 6 ) ;
378+ const styleOf = ( el : HTMLElement ) => [ el . style . left , el . style . top ] ;
379+ expect ( b . handles . map ( styleOf ) ) . toEqual ( a . handles . map ( styleOf ) ) ;
380+ const places = ( r : ReturnType < typeof renderAt > ) =>
381+ r . handles . map ( ( el ) => [ r . at ( el . style . left ) , r . at ( el . style . top ) ] ) ;
382+ const dots = ( r : typeof rectA ) => [
383+ [ r . left - 8 , r . top - 8 ] ,
384+ [ r . left + r . width - 8 , r . top - 8 ] ,
385+ [ r . left - 8 , r . top + r . height - 8 ] ,
386+ [ r . left + r . width - 8 , r . top + r . height - 8 ] ,
387+ ] ;
388+ const expected = ( r : typeof rectA ) => [
389+ [ r . left + r . width / 2 , r . top + r . height + 12 ] ,
390+ ...dots ( r ) ,
391+ [ r . left , r . top ] ,
392+ ] ;
393+ expect ( places ( a ) ) . toEqual ( expected ( rectA ) ) ;
394+ expect ( places ( b ) ) . toEqual ( expected ( rectB ) ) ;
395+ } finally {
396+ a . done ( ) ;
397+ b . done ( ) ;
398+ }
399+ } ) ;
400+ } ) ;
0 commit comments