11<!doctype html>  
22< html > 
3-   < head > 
4-     < meta  charset ="utf8 "> 
5-     < title > React DevTools</ title > 
6-     < meta  name ="viewport " content ="width=device-width, initial-scale=1 "> 
7-     < style > 
8-       # target  {
9-         flex :  1 ;
10-         border :  none;
11-       }
12-       # devtools  {
13-         height :  400px  ;
14-         max-height :  50%  ;
15-         overflow :  hidden;
16-         z-index :  10000001 ;
17-       }
18-       body  {
19-         display :  flex;
20-         flex-direction :  column;
21-         position :  absolute;
22-         top :  0 ;
23-         left :  0 ;
24-         right :  0 ;
25-         bottom :  0 ;
26-         margin :  0 ;
27-         padding :  0 ;
28-         font-family :  -apple-system,  BlinkMacSystemFont,  Segoe UI,  Helvetica,  Arial, 
29-           sans-serif,  Apple Color Emoji,  Segoe UI Emoji,  Segoe UI Symbol;
30-         font-size :  12px  ;
31-         line-height :  1.5 ;
32-       }
33-       .optionsRow  {
34-         width :  100%  ;
35-         display :  flex;
36-         padding :  0.25rem  ;
37-         background :  aliceblue;
38-         border-bottom :  1px   solid lightblue;
39-         box-sizing :  border-box;
40-       }
41-       .optionsRowSpacer  {
42-         flex :  1 ;
43-       }
44-     </ style > 
45-   </ head > 
46-   < body > 
47-     < div  class ="optionsRow "> 
48-       < button  id ="mountButton "> Unmount test app</ button > 
49-       < div  class ="optionsRowSpacer ">  </ div > 
50-       < span > 
51-         < a  href ="/multi.html "> multi DevTools</ a > 
52-         |
53-         < a  href ="/e2e.html "> e2e tests</ a > 
54-         |
55-         < a  href ="/e2e-regression.html "> e2e regression tests</ a > 
56-         |
57-         < a  href ="/perf-regression.html "> perf regression tests</ a > 
58-       </ span > 
59-     </ div > 
603
4+ < head > 
5+   < meta  charset ="utf8 "> 
6+   < title > React DevTools</ title > 
7+   < meta  name ="viewport " content ="width=device-width, initial-scale=1 "> 
8+   < style > 
9+     # panes  {
10+       display :  grid;
11+       height :  100%  ;
12+       width :  100%  ;
13+       position :  relative;
14+     }
15+ 
16+     # divider  {
17+       position :  absolute;
18+       z-index :  10000002 ;
19+       background-color :  # ccc
20+       transition :  background-color 0.2s  ;
21+     }
22+ 
23+     # divider : hover , 
24+     # divider .dragging  {
25+       background-color :  # aaa
26+     }
27+ 
28+     # divider .horizontal-divider  {
29+       width :  100%  ;
30+       height :  5px  ;
31+       cursor :  row-resize;
32+     }
33+ 
34+     # divider .vertical-divider  {
35+       width :  5px  ;
36+       height :  100%  ;
37+       cursor :  col-resize;
38+     }
39+ 
40+     # target  {
41+       height :  100%  ;
42+       width :  100%  ;
43+       border :  none;
44+     }
45+ 
46+     # devtools  {
47+       height :  100%  ;
48+       width :  100%  ;
49+       overflow :  hidden;
50+       z-index :  10000001 ;
51+     }
52+ 
53+     body  {
54+       display :  flex;
55+       height :  100vh  ;
56+       width :  100vw  ;
57+       contain :  strict;
58+       flex-direction :  column;
59+       margin :  0 ;
60+       padding :  0 ;
61+       font-family :  -apple-system,  BlinkMacSystemFont,  Segoe UI,  Helvetica,  Arial, 
62+         sans-serif,  Apple Color Emoji,  Segoe UI Emoji,  Segoe UI Symbol;
63+       font-size :  12px  ;
64+       line-height :  1.5 ;
65+     }
66+ 
67+     .optionsRow  {
68+       width :  100%  ;
69+       display :  flex;
70+       padding :  0.25rem  ;
71+       background :  aliceblue;
72+       border-bottom :  1px   solid lightblue;
73+       box-sizing :  border-box;
74+     }
75+ 
76+     .optionsRowSpacer  {
77+       flex :  1 ;
78+     }
79+   </ style > 
80+ </ head > 
81+ 
82+ < body > 
83+   < div  class ="optionsRow "> 
84+     < button  id ="mountButton "> Unmount test app</ button > 
85+     < div  class ="optionsRowSpacer ">  </ div > 
86+     < span > 
87+       < a  href ="/multi.html "> multi DevTools</ a > 
88+       |
89+       < a  href ="/e2e.html "> e2e tests</ a > 
90+       |
91+       < a  href ="/e2e-regression.html "> e2e regression tests</ a > 
92+       |
93+       < a  href ="/perf-regression.html "> perf regression tests</ a > 
94+     </ span > 
95+ 
96+     < label  style ="margin-left: 4px "> 
97+       Layout:
98+       < select  id ="layout "> 
99+         < option  value ="leftright "> Left/Right Split</ option > 
100+         < option  value ="topbottom "> Top/Bottom Split</ option > 
101+       </ select > </ label > 
102+   </ div > 
103+ 
104+   < div  id ="panes "> 
61105    <!-- React test app (shells/dev/app) is injected here --> 
62106    <!-- DevTools backend (shells/dev/src) is injected here --> 
63107    <!-- global "hook" is defined on the iframe's contentWindow --> 
64108    < iframe  id ="target "> </ iframe > 
65109
110+     <!-- Draggable divider between panes --> 
111+     < div  id ="divider "> </ div > 
112+ 
66113    <!-- DevTools frontend UI (shells/dev/src) renders here --> 
67114    < div  id ="devtools "> </ div > 
115+   </ div > 
116+ 
117+   <!-- This script installs the hook, injects the backend, and renders the DevTools UI --> 
118+   <!-- In DEV mode, this file is served by the Webpack dev server --> 
119+   <!-- For production builds, it's built by Webpack and uploaded from the local file system --> 
120+   < script  src ="dist/app-devtools.js "> </ script > 
121+   < script  type ="module "> 
122+     let  layoutType  =  'leftright' ; 
123+     let  splitRatio  =  0.5 ; 
124+     let  isDragging  =  false ; 
125+ 
126+     // handle layout changes 
127+     const  layout  =  document . getElementById ( 'layout' ) ; 
128+     function  setLayout ( layoutType ,  splitRatio )  { 
129+       const  panes  =  document . getElementById ( 'panes' ) ; 
130+       if  ( layoutType  ===  'topbottom' )  { 
131+         panes . style . gridTemplateColumns  =  '100%' ;  // Full width for each row 
132+         panes . style . gridTemplateRows  =  `${ splitRatio  *  100 } ${ ( 1  -  splitRatio )  *  100 }  ; 
133+       }  else  if  ( layoutType  ===  'leftright' )  { 
134+         panes . style . gridTemplateRows  =  '100%' ;  // Full height for each column 
135+         panes . style . gridTemplateColumns  =  `${ splitRatio  *  100 } ${ ( 1  -  splitRatio )  *  100 }  ; 
136+       } 
137+     } 
138+     layout . addEventListener ( 'change' ,  ( )  =>  { 
139+       layoutType  =  layout . value ; 
140+       setLayout ( layoutType ,  splitRatio ) ; 
141+       updateDividerPosition ( ) ;  // Ensure divider updates when layout changes 
142+     } ) ; 
143+ 
144+     // handle changing the split ratio 
145+     const  divider  =  document . getElementById ( 'divider' ) ; 
146+     function  updateDividerPosition ( )  { 
147+       if  ( layoutType  ===  'topbottom' )  { 
148+         // For top/bottom layout, divider should be horizontal (spanning across) 
149+         divider . className  =  'horizontal-divider' ; 
150+         divider . style . top  =  `calc(${ splitRatio  *  100 }  ; 
151+         divider . style . left  =  '0' ; 
152+       }  else  { 
153+         // For left/right layout, divider should be vertical (spanning down) 
154+         divider . className  =  'vertical-divider' ; 
155+         divider . style . left  =  `calc(${ splitRatio  *  100 }  ; 
156+         divider . style . top  =  '0' ; 
157+       } 
158+     } 
159+ 
160+     // Add event listeners for dragging 
161+     divider . addEventListener ( 'mousedown' ,  ( e )  =>  { 
162+       isDragging  =  true ; 
163+       divider . classList . add ( 'dragging' ) ; 
164+ 
165+       // Disable pointer events on the iframe to prevent it from capturing mouse events 
166+       const  iframe  =  document . getElementById ( 'target' ) ; 
167+       iframe . style . pointerEvents  =  'none' ; 
168+ 
169+       e . preventDefault ( ) ;  // Prevent text selection during drag 
170+     } ) ; 
171+ 
172+     document . addEventListener ( 'mousemove' ,  ( e )  =>  { 
173+       if  ( ! isDragging )  return ; 
174+ 
175+       const  panes  =  document . getElementById ( 'panes' ) ; 
176+       const  rect  =  panes . getBoundingClientRect ( ) ; 
177+ 
178+       if  ( layoutType  ===  'topbottom' )  { 
179+         // Calculate new split ratio based on vertical position 
180+         const  newRatio  =  Math . max ( 0.1 ,  Math . min ( 0.9 ,  ( e . clientY  -  rect . top )  /  rect . height ) ) ; 
181+         splitRatio  =  newRatio ; 
182+       }  else  { 
183+         // Calculate new split ratio based on horizontal position 
184+         const  newRatio  =  Math . max ( 0.1 ,  Math . min ( 0.9 ,  ( e . clientX  -  rect . left )  /  rect . width ) ) ; 
185+         splitRatio  =  newRatio ; 
186+       } 
187+ 
188+       // Update layout and divider position 
189+       setLayout ( layoutType ,  splitRatio ) ; 
190+       updateDividerPosition ( ) ; 
191+     } ) ; 
192+ 
193+     document . addEventListener ( 'mouseup' ,  ( )  =>  { 
194+       if  ( isDragging )  { 
195+         isDragging  =  false ; 
196+         divider . classList . remove ( 'dragging' ) ; 
197+ 
198+         // Re-enable pointer events on the iframe 
199+         const  iframe  =  document . getElementById ( 'target' ) ; 
200+         iframe . style . pointerEvents  =  'auto' ; 
201+       } 
202+     } ) ; 
203+ 
204+     // Initialize 
205+     setLayout ( 
206+       layoutType , 
207+       splitRatio , 
208+     ) ; 
209+     updateDividerPosition ( ) ; 
210+   </ script > 
211+ </ body > 
68212
69-     <!-- This script installs the hook, injects the backend, and renders the DevTools UI --> 
70-     <!-- In DEV mode, this file is served by the Webpack dev server --> 
71-     <!-- For production builds, it's built by Webpack and uploaded from the local file system --> 
72-     < script  src ="dist/app-devtools.js "> </ script > 
73-   </ body > 
74- </ html > 
213+ </ html > 
0 commit comments