main
html 215 lines 6.02 KB
Raw
1 <!doctype html>
2 <html>
3
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 gap: 5px;
12 position: relative;
13 overflow: hidden;
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 overflow-y: auto;
45 }
46
47 #devtools {
48 height: 100%;
49 width: 100%;
50 overflow-y: auto;
51 z-index: 10000001;
52 }
53
54 body {
55 height: 100vh;
56 width: 100vw;
57 display: grid;
58 grid-template-rows: auto 1fr;
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">&nbsp;</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">
105 <!-- React test app (shells/dev/app) is injected here -->
106 <!-- DevTools backend (shells/dev/src) is injected here -->
107 <!-- global "hook" is defined on the iframe's contentWindow -->
108 <iframe id="target"></iframe>
109
110 <!-- Draggable divider between panes -->
111 <div id="divider"></div>
112
113 <!-- DevTools frontend UI (shells/dev/src) renders here -->
114 <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.setProperty('--top-row-height', `${splitRatio * 100}%`);
132 panes.style.gridTemplateRows = "var(--top-row-height) 1fr";
133 panes.style.gridTemplateColumns = null;
134 } else if (layoutType === 'leftright') {
135 panes.style.setProperty('--left-column-width', `${splitRatio * 100}%`);
136 panes.style.gridTemplateRows = null;
137 panes.style.gridTemplateColumns = "var(--left-column-width) 1fr";
138 }
139 }
140 layout.addEventListener('change', () => {
141 layoutType = layout.value;
142 setLayout(layoutType, splitRatio);
143 updateDividerPosition(); // Ensure divider updates when layout changes
144 });
145
146 // handle changing the split ratio
147 const divider = document.getElementById('divider');
148 function updateDividerPosition() {
149 if (layoutType === 'topbottom') {
150 // For top/bottom layout, divider should be horizontal (spanning across)
151 divider.className = 'horizontal-divider';
152 divider.style.top = `calc(${splitRatio * 100}%)`;
153 divider.style.left = '0';
154 } else {
155 // For left/right layout, divider should be vertical (spanning down)
156 divider.className = 'vertical-divider';
157 divider.style.left = `calc(${splitRatio * 100}%)`;
158 divider.style.top = '0';
159 }
160 }
161
162 // Add event listeners for dragging
163 divider.addEventListener('mousedown', (e) => {
164 isDragging = true;
165 divider.classList.add('dragging');
166
167 // Disable pointer events on the iframe to prevent it from capturing mouse events
168 const iframe = document.getElementById('target');
169 iframe.style.pointerEvents = 'none';
170
171 e.preventDefault(); // Prevent text selection during drag
172 });
173
174 document.addEventListener('mousemove', (e) => {
175 if (!isDragging) return;
176
177 const panes = document.getElementById('panes');
178 const rect = panes.getBoundingClientRect();
179
180 if (layoutType === 'topbottom') {
181 // Calculate new split ratio based on vertical position
182 const newRatio = Math.max(0.1, Math.min(0.9, (e.clientY - rect.top) / rect.height));
183 splitRatio = newRatio;
184 } else {
185 // Calculate new split ratio based on horizontal position
186 const newRatio = Math.max(0.1, Math.min(0.9, (e.clientX - rect.left) / rect.width));
187 splitRatio = newRatio;
188 }
189
190 // Update layout and divider position
191 setLayout(layoutType, splitRatio);
192 updateDividerPosition();
193 });
194
195 document.addEventListener('mouseup', () => {
196 if (isDragging) {
197 isDragging = false;
198 divider.classList.remove('dragging');
199
200 // Re-enable pointer events on the iframe
201 const iframe = document.getElementById('target');
202 iframe.style.pointerEvents = 'auto';
203 }
204 });
205
206 // Initialize
207 setLayout(
208 layoutType,
209 splitRatio,
210 );
211 updateDividerPosition();
212 </script>
213 </body>
214
215 </html>