react-resizable-panels 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/react-resizable-panels.d.ts.map +1 -1
- package/dist/react-resizable-panels.js +80 -131
- package/dist/react-resizable-panels.js.map +1 -1
- package/dist/react-resizable-panels.module.js +80 -131
- package/dist/react-resizable-panels.module.js.map +1 -1
- package/package.json +1 -1
- package/src/PanelGroup.tsx +3 -21
- package/src/PanelResizeHandle.tsx +28 -9
- package/src/utils/coordinates.ts +31 -69
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ReactNode,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
2
9
|
|
|
3
10
|
import useUniqueId from "./hooks/useUniqueId";
|
|
4
11
|
import { useWindowSplitterResizeHandlerBehavior } from "./hooks/useWindowSplitterBehavior";
|
|
@@ -16,6 +23,8 @@ export default function PanelResizeHandle({
|
|
|
16
23
|
disabled?: boolean;
|
|
17
24
|
id?: string | null;
|
|
18
25
|
}) {
|
|
26
|
+
const divElementRef = useRef<HTMLDivElement>(null);
|
|
27
|
+
|
|
19
28
|
const panelContext = useContext(PanelContext);
|
|
20
29
|
const panelGroupContext = useContext(PanelGroupContext);
|
|
21
30
|
if (panelContext === null || panelGroupContext === null) {
|
|
@@ -41,6 +50,15 @@ export default function PanelResizeHandle({
|
|
|
41
50
|
null
|
|
42
51
|
);
|
|
43
52
|
|
|
53
|
+
const stopDraggingAndBlur = useCallback(() => {
|
|
54
|
+
// Clicking on the drag handle shouldn't leave it focused;
|
|
55
|
+
// That would cause the PanelGroup to think it was still active.
|
|
56
|
+
const div = divElementRef.current!;
|
|
57
|
+
div.blur();
|
|
58
|
+
|
|
59
|
+
stopDragging();
|
|
60
|
+
}, [stopDragging]);
|
|
61
|
+
|
|
44
62
|
useEffect(() => {
|
|
45
63
|
if (disabled) {
|
|
46
64
|
setResizeHandler(null);
|
|
@@ -62,20 +80,20 @@ export default function PanelResizeHandle({
|
|
|
62
80
|
resizeHandler(event);
|
|
63
81
|
};
|
|
64
82
|
|
|
65
|
-
document.body.addEventListener("mouseleave",
|
|
83
|
+
document.body.addEventListener("mouseleave", stopDraggingAndBlur);
|
|
66
84
|
document.body.addEventListener("mousemove", onMove);
|
|
67
85
|
document.body.addEventListener("touchmove", onMove);
|
|
68
|
-
document.body.addEventListener("mouseup",
|
|
86
|
+
document.body.addEventListener("mouseup", stopDraggingAndBlur);
|
|
69
87
|
|
|
70
88
|
return () => {
|
|
71
89
|
document.body.style.cursor = "";
|
|
72
90
|
|
|
73
|
-
document.body.removeEventListener("mouseleave",
|
|
91
|
+
document.body.removeEventListener("mouseleave", stopDraggingAndBlur);
|
|
74
92
|
document.body.removeEventListener("mousemove", onMove);
|
|
75
93
|
document.body.removeEventListener("touchmove", onMove);
|
|
76
|
-
document.body.removeEventListener("mouseup",
|
|
94
|
+
document.body.removeEventListener("mouseup", stopDraggingAndBlur);
|
|
77
95
|
};
|
|
78
|
-
}, [direction, disabled, isDragging, resizeHandler,
|
|
96
|
+
}, [direction, disabled, isDragging, resizeHandler, stopDraggingAndBlur]);
|
|
79
97
|
|
|
80
98
|
useWindowSplitterResizeHandlerBehavior({
|
|
81
99
|
disabled,
|
|
@@ -90,10 +108,11 @@ export default function PanelResizeHandle({
|
|
|
90
108
|
data-panel-resize-handle-enabled={!disabled}
|
|
91
109
|
data-panel-resize-handle-id={id}
|
|
92
110
|
onMouseDown={() => startDragging(id)}
|
|
93
|
-
onMouseUp={
|
|
94
|
-
onTouchCancel={
|
|
95
|
-
onTouchEnd={
|
|
111
|
+
onMouseUp={stopDraggingAndBlur}
|
|
112
|
+
onTouchCancel={stopDraggingAndBlur}
|
|
113
|
+
onTouchEnd={stopDraggingAndBlur}
|
|
96
114
|
onTouchStart={() => startDragging(id)}
|
|
115
|
+
ref={divElementRef}
|
|
97
116
|
role="separator"
|
|
98
117
|
style={{
|
|
99
118
|
cursor: direction === "horizontal" ? "ew-resize" : "ns-resize",
|
package/src/utils/coordinates.ts
CHANGED
|
@@ -1,107 +1,69 @@
|
|
|
1
1
|
import { Direction, ResizeEvent } from "../types";
|
|
2
|
+
import { getResizeHandle } from "./group";
|
|
2
3
|
|
|
3
4
|
export type Coordinates = {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
movement: number;
|
|
6
|
+
offset: number;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
|
-
export type
|
|
9
|
+
export type Size = {
|
|
9
10
|
height: number;
|
|
10
11
|
width: number;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
|
-
export type Movement = {
|
|
14
|
-
movementX: number;
|
|
15
|
-
movementY: number;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
14
|
const element = document.createElement("div");
|
|
19
15
|
element.getBoundingClientRect();
|
|
20
16
|
|
|
21
17
|
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/movementX
|
|
22
|
-
export function
|
|
18
|
+
export function getMovement(
|
|
23
19
|
event: ResizeEvent,
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
handleId: string,
|
|
21
|
+
{ height, width }: Size,
|
|
26
22
|
direction: Direction
|
|
27
|
-
):
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const getMovementBetween = (current: number, prev: number) =>
|
|
32
|
-
prev === 0 ? 0 : current - prev;
|
|
23
|
+
): number {
|
|
24
|
+
const isHorizontal = direction === "horizontal";
|
|
25
|
+
const size = isHorizontal ? width : height;
|
|
33
26
|
|
|
34
27
|
if (isKeyDown(event)) {
|
|
35
|
-
let movementX = 0;
|
|
36
|
-
let movementY = 0;
|
|
37
|
-
|
|
38
|
-
const size = direction === "horizontal" ? width : height;
|
|
39
28
|
const denominator = event.shiftKey ? 10 : 100;
|
|
40
29
|
const delta = size / denominator;
|
|
41
30
|
|
|
42
31
|
switch (event.key) {
|
|
43
32
|
case "ArrowDown":
|
|
44
|
-
|
|
45
|
-
break;
|
|
33
|
+
return delta;
|
|
46
34
|
case "ArrowLeft":
|
|
47
|
-
|
|
48
|
-
break;
|
|
35
|
+
return -delta;
|
|
49
36
|
case "ArrowRight":
|
|
50
|
-
|
|
51
|
-
break;
|
|
37
|
+
return delta;
|
|
52
38
|
case "ArrowUp":
|
|
53
|
-
|
|
54
|
-
break;
|
|
39
|
+
return -delta;
|
|
55
40
|
case "End":
|
|
56
|
-
if (
|
|
57
|
-
|
|
41
|
+
if (isHorizontal) {
|
|
42
|
+
return size;
|
|
58
43
|
} else {
|
|
59
|
-
|
|
44
|
+
return size;
|
|
60
45
|
}
|
|
61
|
-
break;
|
|
62
46
|
case "Home":
|
|
63
|
-
if (
|
|
64
|
-
|
|
47
|
+
if (isHorizontal) {
|
|
48
|
+
return -size;
|
|
65
49
|
} else {
|
|
66
|
-
|
|
50
|
+
return -size;
|
|
67
51
|
}
|
|
68
|
-
break;
|
|
69
52
|
}
|
|
53
|
+
} else {
|
|
54
|
+
const handleElement = getResizeHandle(handleId)!;
|
|
55
|
+
const rect = handleElement.getBoundingClientRect();
|
|
56
|
+
const elementOffset = isHorizontal ? rect.left : rect.top;
|
|
70
57
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
screenX = rect.left + rect.width / 2;
|
|
78
|
-
screenY = rect.top + rect.height / 2;
|
|
58
|
+
let pointerOffset = 0;
|
|
59
|
+
if (isMouseMoveEvent(event)) {
|
|
60
|
+
pointerOffset = isHorizontal ? event.clientX : event.clientY;
|
|
61
|
+
} else {
|
|
62
|
+
const firstTouch = event.touches[0];
|
|
63
|
+
pointerOffset = isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
79
64
|
}
|
|
80
65
|
|
|
81
|
-
return
|
|
82
|
-
movementX,
|
|
83
|
-
movementY,
|
|
84
|
-
screenX,
|
|
85
|
-
screenY,
|
|
86
|
-
};
|
|
87
|
-
} else if (isTouchMoveEvent(event)) {
|
|
88
|
-
const firstTouch = event.touches[0];
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
movementX: getMovementBetween(firstTouch.screenX, prevScreenX),
|
|
92
|
-
movementY: getMovementBetween(firstTouch.screenY, prevScreenY),
|
|
93
|
-
screenX: firstTouch.screenX,
|
|
94
|
-
screenY: firstTouch.screenY,
|
|
95
|
-
};
|
|
96
|
-
} else if (isMouseMoveEvent(event)) {
|
|
97
|
-
return {
|
|
98
|
-
movementX: getMovementBetween(event.screenX, prevScreenX),
|
|
99
|
-
movementY: getMovementBetween(event.screenY, prevScreenY),
|
|
100
|
-
screenX: event.screenX,
|
|
101
|
-
screenY: event.screenY,
|
|
102
|
-
};
|
|
103
|
-
} else {
|
|
104
|
-
throw Error(`Unsupported event type: "${(event as any).type}"`);
|
|
66
|
+
return pointerOffset - elementOffset;
|
|
105
67
|
}
|
|
106
68
|
}
|
|
107
69
|
|