Skip to content

Commit fb1b017

Browse files
committed
2 parents a609426 + cbc684a commit fb1b017

File tree

2 files changed

+88
-28
lines changed

2 files changed

+88
-28
lines changed

src/core/web/inspect-element/inspect-state-machine.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,26 @@ import {
99
updateCanvasSize,
1010
} from './overlay';
1111
import { getCompositeComponentFromElement, hasValidParent } from './utils';
12+
import { restoreSizeFromLocalStorage } from '../toolbar';
1213

1314
export type States =
1415
| {
15-
kind: 'inspecting';
16-
hoveredDomElement: HTMLElement | null;
17-
propContainer: HTMLDivElement;
18-
}
16+
kind: 'inspecting';
17+
hoveredDomElement: HTMLElement | null;
18+
propContainer: HTMLDivElement;
19+
}
1920
| {
20-
kind: 'inspect-off';
21-
propContainer: HTMLDivElement;
22-
}
21+
kind: 'inspect-off';
22+
propContainer: HTMLDivElement;
23+
}
2324
| {
24-
kind: 'focused';
25-
focusedDomElement: HTMLElement;
26-
propContainer: HTMLDivElement;
27-
}
25+
kind: 'focused';
26+
focusedDomElement: HTMLElement;
27+
propContainer: HTMLDivElement;
28+
}
2829
| {
29-
kind: 'uninitialized';
30-
};
30+
kind: 'uninitialized';
31+
};
3132

3233
export const INSPECT_TOGGLE_ID = 'react-scan-inspect-element-toggle';
3334
export const INSPECT_OVERLAY_CANVAS_ID = 'react-scan-inspect-canvas';
@@ -73,6 +74,7 @@ export const createInspectElementStateMachine = () => {
7374
}
7475

7576
const clearCanvas = () => {
77+
cancelAnimationFrame(animationId)
7678
ctx.save();
7779

7880
ctx.setTransform(1, 0, 0, 1, 0, 0);
@@ -191,6 +193,7 @@ export const createInspectElementStateMachine = () => {
191193

192194
drawHoverOverlay(el as HTMLElement, canvas, ctx, 'locked');
193195

196+
restoreSizeFromLocalStorage(inspectState.propContainer)
194197
ReactScanInternals.inspectState = {
195198
kind: 'focused',
196199
focusedDomElement: el as HTMLElement,
@@ -255,13 +258,16 @@ export const createInspectElementStateMachine = () => {
255258
);
256259
});
257260
if (!document.contains(inspectState.focusedDomElement)) {
258-
clearCanvas();
261+
setTimeout(() => {
262+
263+
// potential race condition solution for some websites
264+
clearCanvas();
265+
}, 500)
259266
inspectState.propContainer.style.maxHeight = '0';
260267
inspectState.propContainer.style.width = 'fit-content';
261268
inspectState.propContainer.innerHTML = '';
262269
ReactScanInternals.inspectState = {
263-
kind: 'inspecting',
264-
hoveredDomElement: null,
270+
kind: 'inspect-off',
265271
propContainer: inspectState.propContainer,
266272
};
267273
return;
@@ -333,7 +339,7 @@ export const createInspectElementStateMachine = () => {
333339
if (
334340
adjustedX >= currentLockIconRect.x &&
335341
adjustedX <=
336-
currentLockIconRect.x + currentLockIconRect.width &&
342+
currentLockIconRect.x + currentLockIconRect.width &&
337343
adjustedY >= currentLockIconRect.y &&
338344
adjustedY <= currentLockIconRect.y + currentLockIconRect.height
339345
) {

src/core/web/toolbar.ts

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ReactScanInternals } from '../../index';
2-
import { createElement } from './utils';
2+
import { createElement, throttle } from './utils';
33
import { MONO_FONT } from './outline';
44
import { INSPECT_TOGGLE_ID } from './inspect-element/inspect-state-machine';
55
import {
@@ -8,6 +8,21 @@ import {
88
} from './inspect-element/utils';
99

1010
let isDragging = false;
11+
let isResizing = false;
12+
let initialWidth = 0;
13+
let initialMouseX = 0;
14+
15+
export const persistSizeToLocalStorage = throttle((width: number) => {
16+
localStorage.setItem('react-scan-toolbar-width', String(width));
17+
}, 100);
18+
19+
20+
export const restoreSizeFromLocalStorage = (el: HTMLDivElement) => {
21+
const width = localStorage.getItem('react-scan-toolbar-width');
22+
el.style.width = `${width ?? 360}px`;
23+
24+
};
25+
1126
export const createToolbar = () => {
1227
if (typeof window === 'undefined') {
1328
return;
@@ -52,6 +67,7 @@ export const createToolbar = () => {
5267
overflow: hidden;
5368
width: fit-content;
5469
min-width: min-content;
70+
position: relative;
5571
">
5672
<div style="display: flex; align-items: center; height: 36px; width: 100%;">
5773
<button id="${INSPECT_TOGGLE_ID}" style="
@@ -136,13 +152,23 @@ export const createToolbar = () => {
136152
pointer-events: auto;
137153
background: #000;
138154
border-top: 1px solid rgba(255, 255, 255, 0.1);
155+
min-width: 100%;
139156
width: 360px;
140157
overflow: auto;
141158
max-height: 0;
142159
transition: max-height 500ms cubic-bezier(0, 0.95, 0.1, 1);
143160
">
144161
<!-- Props content will be injected here -->
145162
</div>
163+
<div id="react-scan-resize-handle" style="
164+
position: absolute;
165+
left: 0;
166+
top: 0;
167+
bottom: 0;
168+
width: 4px;
169+
cursor: ew-resize;
170+
dis
171+
"></div>
146172
</div>
147173
</div>
148174
`) as HTMLDivElement;
@@ -153,10 +179,12 @@ export const createToolbar = () => {
153179
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
154180
}
155181
182+
156183
.react-scan-inspector {
157184
font-size: 13px;
158185
width: 360px;
159186
color: #fff;
187+
width: 100%;
160188
}
161189
162190
.react-scan-header {
@@ -388,6 +416,11 @@ export const createToolbar = () => {
388416
const toolbarContent = toolbar.querySelector<HTMLElement>(
389417
'#react-scan-toolbar-content',
390418
)!;
419+
const resizeHandle = toolbar.querySelector<HTMLElement>(
420+
'#react-scan-resize-handle',
421+
)!;
422+
423+
391424

392425
let isActive = !ReactScanInternals.isPaused;
393426

@@ -408,7 +441,8 @@ export const createToolbar = () => {
408441
if (
409442
event.target === inspectBtn ||
410443
event.target === powerBtn ||
411-
event.target === parentFocusBtn
444+
event.target === parentFocusBtn ||
445+
event.target === resizeHandle
412446
)
413447
return;
414448

@@ -424,21 +458,38 @@ export const createToolbar = () => {
424458
event.preventDefault();
425459
});
426460

461+
resizeHandle.addEventListener('mousedown', (e) => {
462+
isResizing = true;
463+
initialWidth = propContainer.offsetWidth;
464+
initialMouseX = e.clientX;
465+
e.preventDefault();
466+
});
467+
427468
document.addEventListener('mousemove', (e) => {
428-
if (!isDragging) return;
469+
if (isDragging) {
470+
const x = e.clientX - initialX;
471+
const y = e.clientY - initialY;
429472

430-
const x = e.clientX - initialX;
431-
const y = e.clientY - initialY;
473+
currentX = x;
474+
currentY = y;
475+
updateToolbarPosition(x, y);
476+
}
432477

433-
currentX = x;
434-
currentY = y;
435-
updateToolbarPosition(x, y);
478+
if (isResizing) {
479+
const width = initialWidth - (e.clientX - initialMouseX);
480+
propContainer.style.width = `${Math.max(360, width)}px`;
481+
persistSizeToLocalStorage(width);
482+
}
436483
});
437484

438485
document.addEventListener('mouseup', () => {
439-
if (!isDragging) return;
440-
isDragging = false;
441-
toolbar.style.transition = '';
486+
if (isDragging) {
487+
isDragging = false;
488+
toolbar.style.transition = '';
489+
}
490+
if (isResizing) {
491+
isResizing = false;
492+
}
442493
});
443494

444495
const updateNavigationButtons = () => {
@@ -486,6 +537,9 @@ export const createToolbar = () => {
486537
propContainer.style.maxHeight = '0';
487538
propContainer.style.width = 'fit-content';
488539
propContainer.innerHTML = '';
540+
resizeHandle.style.display = 'none';
541+
} else if (focusActive) {
542+
resizeHandle.style.display = 'block';
489543
}
490544

491545
updateNavigationButtons();

0 commit comments

Comments
 (0)