react-resizable-panels 1.0.9 → 2.0.0
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 +9 -0
- package/README.md +29 -104
- package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
- package/dist/declarations/src/PanelResizeHandleRegistry.d.ts +20 -0
- package/dist/react-resizable-panels.browser.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.esm.js +367 -140
- package/dist/react-resizable-panels.browser.esm.js +367 -140
- package/dist/react-resizable-panels.cjs.js +367 -140
- package/dist/react-resizable-panels.development.cjs.js +367 -140
- package/dist/react-resizable-panels.development.esm.js +367 -140
- package/dist/react-resizable-panels.development.node.cjs.js +367 -140
- package/dist/react-resizable-panels.development.node.esm.js +367 -140
- package/dist/react-resizable-panels.esm.js +367 -140
- package/dist/react-resizable-panels.node.cjs.js +367 -140
- package/dist/react-resizable-panels.node.esm.js +367 -140
- package/package.json +1 -1
- package/src/Panel.test.tsx +52 -0
- package/src/PanelGroup.ts +23 -16
- package/src/PanelResizeHandle.ts +64 -82
- package/src/PanelResizeHandleRegistry.ts +263 -0
- package/src/utils/calculateDragOffsetPercentage.ts +1 -1
- package/src/utils/cursor.ts +63 -33
- package/src/utils/events/getResizeEventCoordinates.ts +24 -0
- package/src/utils/events/getResizeEventCursorPosition.ts +14 -0
- package/src/utils/{events.ts → events/index.ts} +1 -1
- package/src/utils/getInputType.ts +5 -0
- package/src/utils/getResizeEventCursorPosition.ts +0 -21
package/src/PanelGroup.ts
CHANGED
|
@@ -6,6 +6,13 @@ import {
|
|
|
6
6
|
ResizeEvent,
|
|
7
7
|
TPanelGroupContext,
|
|
8
8
|
} from "./PanelGroupContext";
|
|
9
|
+
import {
|
|
10
|
+
EXCEEDED_HORIZONTAL_MAX,
|
|
11
|
+
EXCEEDED_HORIZONTAL_MIN,
|
|
12
|
+
EXCEEDED_VERTICAL_MAX,
|
|
13
|
+
EXCEEDED_VERTICAL_MIN,
|
|
14
|
+
reportConstraintsViolation,
|
|
15
|
+
} from "./PanelResizeHandleRegistry";
|
|
9
16
|
import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
|
|
10
17
|
import useUniqueId from "./hooks/useUniqueId";
|
|
11
18
|
import { useWindowSplitterPanelGroupBehavior } from "./hooks/useWindowSplitterPanelGroupBehavior";
|
|
@@ -23,7 +30,7 @@ import debounce from "./utils/debounce";
|
|
|
23
30
|
import { determinePivotIndices } from "./utils/determinePivotIndices";
|
|
24
31
|
import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement";
|
|
25
32
|
import { isKeyDown, isMouseEvent, isTouchEvent } from "./utils/events";
|
|
26
|
-
import { getResizeEventCursorPosition } from "./utils/getResizeEventCursorPosition";
|
|
33
|
+
import { getResizeEventCursorPosition } from "./utils/events/getResizeEventCursorPosition";
|
|
27
34
|
import { initializeDefaultStorage } from "./utils/initializeDefaultStorage";
|
|
28
35
|
import {
|
|
29
36
|
loadPanelGroupState,
|
|
@@ -571,6 +578,7 @@ function PanelGroupWithForwardedRef({
|
|
|
571
578
|
if (!panelGroupElement) {
|
|
572
579
|
return () => null;
|
|
573
580
|
}
|
|
581
|
+
|
|
574
582
|
const {
|
|
575
583
|
direction,
|
|
576
584
|
dragState,
|
|
@@ -630,20 +638,21 @@ function PanelGroupWithForwardedRef({
|
|
|
630
638
|
prevDeltaRef.current = delta;
|
|
631
639
|
|
|
632
640
|
if (!layoutChanged) {
|
|
633
|
-
// If the pointer has moved too far to resize the panel any further,
|
|
634
|
-
// update the cursor style for a visual clue.
|
|
641
|
+
// If the pointer has moved too far to resize the panel any further, note this so we can update the cursor.
|
|
635
642
|
// This mimics VS Code behavior.
|
|
636
|
-
|
|
637
643
|
if (isHorizontal) {
|
|
638
|
-
|
|
639
|
-
|
|
644
|
+
reportConstraintsViolation(
|
|
645
|
+
dragHandleId,
|
|
646
|
+
delta < 0 ? EXCEEDED_HORIZONTAL_MIN : EXCEEDED_HORIZONTAL_MAX
|
|
640
647
|
);
|
|
641
648
|
} else {
|
|
642
|
-
|
|
649
|
+
reportConstraintsViolation(
|
|
650
|
+
dragHandleId,
|
|
651
|
+
delta < 0 ? EXCEEDED_VERTICAL_MIN : EXCEEDED_VERTICAL_MAX
|
|
652
|
+
);
|
|
643
653
|
}
|
|
644
654
|
} else {
|
|
645
|
-
|
|
646
|
-
setGlobalCursorStyle(isHorizontal ? "horizontal" : "vertical");
|
|
655
|
+
reportConstraintsViolation(dragHandleId, 0);
|
|
647
656
|
}
|
|
648
657
|
}
|
|
649
658
|
}
|
|
@@ -726,15 +735,11 @@ function PanelGroupWithForwardedRef({
|
|
|
726
735
|
const {
|
|
727
736
|
collapsedSize: prevCollapsedSize = 0,
|
|
728
737
|
collapsible: prevCollapsible,
|
|
729
|
-
defaultSize: prevDefaultSize,
|
|
730
|
-
maxSize: prevMaxSize = 100,
|
|
731
|
-
minSize: prevMinSize = 0,
|
|
732
738
|
} = prevConstraints;
|
|
733
739
|
|
|
734
740
|
const {
|
|
735
741
|
collapsedSize: nextCollapsedSize = 0,
|
|
736
742
|
collapsible: nextCollapsible,
|
|
737
|
-
defaultSize: nextDefaultSize,
|
|
738
743
|
maxSize: nextMaxSize = 100,
|
|
739
744
|
minSize: nextMinSize = 0,
|
|
740
745
|
} = panelData.constraints;
|
|
@@ -749,10 +754,13 @@ function PanelGroupWithForwardedRef({
|
|
|
749
754
|
if (
|
|
750
755
|
prevCollapsible &&
|
|
751
756
|
nextCollapsible &&
|
|
752
|
-
prevCollapsedSize !== nextCollapsedSize &&
|
|
753
757
|
prevPanelSize === prevCollapsedSize
|
|
754
758
|
) {
|
|
755
|
-
|
|
759
|
+
if (prevCollapsedSize !== nextCollapsedSize) {
|
|
760
|
+
resizePanel(panelData, nextCollapsedSize);
|
|
761
|
+
} else {
|
|
762
|
+
// Stay collapsed
|
|
763
|
+
}
|
|
756
764
|
} else if (prevPanelSize < nextMinSize) {
|
|
757
765
|
resizePanel(panelData, nextMinSize);
|
|
758
766
|
} else if (prevPanelSize > nextMaxSize) {
|
|
@@ -791,7 +799,6 @@ function PanelGroupWithForwardedRef({
|
|
|
791
799
|
);
|
|
792
800
|
|
|
793
801
|
const stopDragging = useCallback(() => {
|
|
794
|
-
resetGlobalCursorStyle();
|
|
795
802
|
setDragState(null);
|
|
796
803
|
}, []);
|
|
797
804
|
|
package/src/PanelResizeHandle.ts
CHANGED
|
@@ -5,9 +5,6 @@ import {
|
|
|
5
5
|
HTMLAttributes,
|
|
6
6
|
PropsWithChildren,
|
|
7
7
|
ReactElement,
|
|
8
|
-
MouseEvent as ReactMouseEvent,
|
|
9
|
-
TouchEvent,
|
|
10
|
-
useCallback,
|
|
11
8
|
useContext,
|
|
12
9
|
useEffect,
|
|
13
10
|
useRef,
|
|
@@ -20,8 +17,13 @@ import {
|
|
|
20
17
|
ResizeEvent,
|
|
21
18
|
ResizeHandler,
|
|
22
19
|
} from "./PanelGroupContext";
|
|
20
|
+
import {
|
|
21
|
+
PointerHitAreaMargins,
|
|
22
|
+
registerResizeHandle,
|
|
23
|
+
ResizeHandlerAction,
|
|
24
|
+
ResizeHandlerState,
|
|
25
|
+
} from "./PanelResizeHandleRegistry";
|
|
23
26
|
import { assert } from "./utils/assert";
|
|
24
|
-
import { getCursorStyle } from "./utils/cursor";
|
|
25
27
|
|
|
26
28
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
27
29
|
|
|
@@ -32,6 +34,7 @@ export type PanelResizeHandleProps = Omit<
|
|
|
32
34
|
PropsWithChildren<{
|
|
33
35
|
className?: string;
|
|
34
36
|
disabled?: boolean;
|
|
37
|
+
hitAreaMargins?: PointerHitAreaMargins;
|
|
35
38
|
id?: string | null;
|
|
36
39
|
onDragging?: PanelResizeHandleOnDragging;
|
|
37
40
|
style?: CSSProperties;
|
|
@@ -43,6 +46,7 @@ export function PanelResizeHandle({
|
|
|
43
46
|
children = null,
|
|
44
47
|
className: classNameFromProps = "",
|
|
45
48
|
disabled = false,
|
|
49
|
+
hitAreaMargins,
|
|
46
50
|
id: idFromProps,
|
|
47
51
|
onDragging,
|
|
48
52
|
style: styleFromProps = {},
|
|
@@ -69,16 +73,16 @@ export function PanelResizeHandle({
|
|
|
69
73
|
|
|
70
74
|
const {
|
|
71
75
|
direction,
|
|
72
|
-
dragState,
|
|
73
76
|
groupId,
|
|
74
|
-
registerResizeHandle,
|
|
77
|
+
registerResizeHandle: registerResizeHandleWithParentGroup,
|
|
75
78
|
startDragging,
|
|
76
79
|
stopDragging,
|
|
77
80
|
panelGroupElement,
|
|
78
81
|
} = panelGroupContext;
|
|
79
82
|
|
|
80
83
|
const resizeHandleId = useUniqueId(idFromProps);
|
|
81
|
-
|
|
84
|
+
|
|
85
|
+
const [state, setState] = useState<ResizeHandlerState>("inactive");
|
|
82
86
|
|
|
83
87
|
const [isFocused, setIsFocused] = useState(false);
|
|
84
88
|
|
|
@@ -86,67 +90,71 @@ export function PanelResizeHandle({
|
|
|
86
90
|
null
|
|
87
91
|
);
|
|
88
92
|
|
|
89
|
-
const stopDraggingAndBlur = useCallback(() => {
|
|
90
|
-
// Clicking on the drag handle shouldn't leave it focused;
|
|
91
|
-
// That would cause the PanelGroup to think it was still active.
|
|
92
|
-
const element = elementRef.current;
|
|
93
|
-
assert(element);
|
|
94
|
-
element.blur();
|
|
95
|
-
|
|
96
|
-
stopDragging();
|
|
97
|
-
|
|
98
|
-
const { onDragging } = callbacksRef.current;
|
|
99
|
-
if (onDragging) {
|
|
100
|
-
onDragging(false);
|
|
101
|
-
}
|
|
102
|
-
}, [stopDragging]);
|
|
103
|
-
|
|
104
93
|
useEffect(() => {
|
|
105
94
|
if (disabled) {
|
|
106
95
|
setResizeHandler(null);
|
|
107
96
|
} else {
|
|
108
|
-
const resizeHandler =
|
|
97
|
+
const resizeHandler = registerResizeHandleWithParentGroup(resizeHandleId);
|
|
109
98
|
setResizeHandler(() => resizeHandler);
|
|
110
99
|
}
|
|
111
|
-
}, [disabled, resizeHandleId,
|
|
100
|
+
}, [disabled, resizeHandleId, registerResizeHandleWithParentGroup]);
|
|
112
101
|
|
|
113
102
|
useEffect(() => {
|
|
114
|
-
if (disabled || resizeHandler == null
|
|
103
|
+
if (disabled || resizeHandler == null) {
|
|
115
104
|
return;
|
|
116
105
|
}
|
|
117
106
|
|
|
118
|
-
const onMove = (event: ResizeEvent) => {
|
|
119
|
-
resizeHandler(event);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const onMouseLeave = (event: MouseEvent) => {
|
|
123
|
-
resizeHandler(event);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
107
|
const element = elementRef.current;
|
|
127
108
|
assert(element);
|
|
128
109
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
110
|
+
const setResizeHandlerState = (
|
|
111
|
+
action: ResizeHandlerAction,
|
|
112
|
+
state: ResizeHandlerState,
|
|
113
|
+
event: ResizeEvent
|
|
114
|
+
) => {
|
|
115
|
+
setState(state);
|
|
116
|
+
|
|
117
|
+
switch (action) {
|
|
118
|
+
case "down": {
|
|
119
|
+
startDragging(resizeHandleId, event);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
case "up": {
|
|
123
|
+
stopDragging();
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
switch (state) {
|
|
129
|
+
case "drag": {
|
|
130
|
+
resizeHandler(event);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
148
134
|
};
|
|
149
|
-
|
|
135
|
+
|
|
136
|
+
return registerResizeHandle(
|
|
137
|
+
resizeHandleId,
|
|
138
|
+
element,
|
|
139
|
+
direction,
|
|
140
|
+
{
|
|
141
|
+
// Coarse inputs (e.g. finger/touch)
|
|
142
|
+
coarse: hitAreaMargins?.coarse ?? 15,
|
|
143
|
+
// Fine inputs (e.g. mouse)
|
|
144
|
+
fine: hitAreaMargins?.fine ?? 5,
|
|
145
|
+
},
|
|
146
|
+
setResizeHandlerState
|
|
147
|
+
);
|
|
148
|
+
}, [
|
|
149
|
+
direction,
|
|
150
|
+
disabled,
|
|
151
|
+
hitAreaMargins,
|
|
152
|
+
registerResizeHandleWithParentGroup,
|
|
153
|
+
resizeHandleId,
|
|
154
|
+
resizeHandler,
|
|
155
|
+
startDragging,
|
|
156
|
+
stopDragging,
|
|
157
|
+
]);
|
|
150
158
|
|
|
151
159
|
useWindowSplitterResizeHandlerBehavior({
|
|
152
160
|
disabled,
|
|
@@ -156,7 +164,6 @@ export function PanelResizeHandle({
|
|
|
156
164
|
});
|
|
157
165
|
|
|
158
166
|
const style: CSSProperties = {
|
|
159
|
-
cursor: getCursorStyle(direction),
|
|
160
167
|
touchAction: "none",
|
|
161
168
|
userSelect: "none",
|
|
162
169
|
};
|
|
@@ -168,29 +175,6 @@ export function PanelResizeHandle({
|
|
|
168
175
|
className: classNameFromProps,
|
|
169
176
|
onBlur: () => setIsFocused(false),
|
|
170
177
|
onFocus: () => setIsFocused(true),
|
|
171
|
-
onMouseDown: (event: ReactMouseEvent) => {
|
|
172
|
-
startDragging(resizeHandleId, event.nativeEvent);
|
|
173
|
-
|
|
174
|
-
const callbacks = callbacksRef.current;
|
|
175
|
-
assert(callbacks);
|
|
176
|
-
const { onDragging } = callbacks;
|
|
177
|
-
if (onDragging) {
|
|
178
|
-
onDragging(true);
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
onMouseUp: stopDraggingAndBlur,
|
|
182
|
-
onTouchCancel: stopDraggingAndBlur,
|
|
183
|
-
onTouchEnd: stopDraggingAndBlur,
|
|
184
|
-
onTouchStart: (event: TouchEvent) => {
|
|
185
|
-
startDragging(resizeHandleId, event.nativeEvent);
|
|
186
|
-
|
|
187
|
-
const callbacks = callbacksRef.current;
|
|
188
|
-
assert(callbacks);
|
|
189
|
-
const { onDragging } = callbacks;
|
|
190
|
-
if (onDragging) {
|
|
191
|
-
onDragging(true);
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
178
|
ref: elementRef,
|
|
195
179
|
role: "separator",
|
|
196
180
|
style: {
|
|
@@ -203,11 +187,9 @@ export function PanelResizeHandle({
|
|
|
203
187
|
"data-panel-group-direction": direction,
|
|
204
188
|
"data-panel-group-id": groupId,
|
|
205
189
|
"data-resize-handle": "",
|
|
206
|
-
"data-resize-handle-active":
|
|
207
|
-
? "pointer"
|
|
208
|
-
|
|
209
|
-
? "keyboard"
|
|
210
|
-
: undefined,
|
|
190
|
+
"data-resize-handle-active":
|
|
191
|
+
state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
|
|
192
|
+
"data-resize-handle-state": state,
|
|
211
193
|
"data-panel-resize-handle-enabled": !disabled,
|
|
212
194
|
"data-panel-resize-handle-id": resizeHandleId,
|
|
213
195
|
});
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { Direction, ResizeEvent } from "./types";
|
|
2
|
+
import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
|
|
3
|
+
import { getResizeEventCoordinates } from "./utils/events/getResizeEventCoordinates";
|
|
4
|
+
import { getInputType } from "./utils/getInputType";
|
|
5
|
+
|
|
6
|
+
export type ResizeHandlerAction = "down" | "move" | "up";
|
|
7
|
+
export type ResizeHandlerState = "drag" | "hover" | "inactive";
|
|
8
|
+
export type SetResizeHandlerState = (
|
|
9
|
+
action: ResizeHandlerAction,
|
|
10
|
+
state: ResizeHandlerState,
|
|
11
|
+
event: ResizeEvent
|
|
12
|
+
) => void;
|
|
13
|
+
|
|
14
|
+
export type PointerHitAreaMargins = {
|
|
15
|
+
coarse: number;
|
|
16
|
+
fine: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type ResizeHandlerData = {
|
|
20
|
+
direction: Direction;
|
|
21
|
+
element: HTMLElement;
|
|
22
|
+
hitAreaMargins: PointerHitAreaMargins;
|
|
23
|
+
setResizeHandlerState: SetResizeHandlerState;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
27
|
+
export const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
28
|
+
export const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
29
|
+
export const EXCEEDED_VERTICAL_MAX = 0b1000;
|
|
30
|
+
|
|
31
|
+
const isCoarsePointer = getInputType() === "coarse";
|
|
32
|
+
|
|
33
|
+
let intersectingHandles: ResizeHandlerData[] = [];
|
|
34
|
+
let isPointerDown = false;
|
|
35
|
+
let ownerDocumentCounts: Map<Document, number> = new Map();
|
|
36
|
+
let panelConstraintFlags: Map<string, number> = new Map();
|
|
37
|
+
|
|
38
|
+
const registeredResizeHandlers = new Set<ResizeHandlerData>();
|
|
39
|
+
|
|
40
|
+
export function registerResizeHandle(
|
|
41
|
+
resizeHandleId: string,
|
|
42
|
+
element: HTMLElement,
|
|
43
|
+
direction: Direction,
|
|
44
|
+
hitAreaMargins: PointerHitAreaMargins,
|
|
45
|
+
setResizeHandlerState: SetResizeHandlerState
|
|
46
|
+
) {
|
|
47
|
+
const { ownerDocument } = element;
|
|
48
|
+
|
|
49
|
+
const data: ResizeHandlerData = {
|
|
50
|
+
direction,
|
|
51
|
+
element,
|
|
52
|
+
hitAreaMargins,
|
|
53
|
+
setResizeHandlerState,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const count = ownerDocumentCounts.get(ownerDocument) ?? 0;
|
|
57
|
+
ownerDocumentCounts.set(ownerDocument, count + 1);
|
|
58
|
+
|
|
59
|
+
registeredResizeHandlers.add(data);
|
|
60
|
+
|
|
61
|
+
updateListeners();
|
|
62
|
+
|
|
63
|
+
return function unregisterResizeHandle() {
|
|
64
|
+
panelConstraintFlags.delete(resizeHandleId);
|
|
65
|
+
registeredResizeHandlers.delete(data);
|
|
66
|
+
|
|
67
|
+
const count = ownerDocumentCounts.get(ownerDocument) ?? 1;
|
|
68
|
+
ownerDocumentCounts.set(ownerDocument, count - 1);
|
|
69
|
+
|
|
70
|
+
updateListeners();
|
|
71
|
+
|
|
72
|
+
if (count === 1) {
|
|
73
|
+
ownerDocumentCounts.delete(ownerDocument);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function handlePointerDown(event: ResizeEvent) {
|
|
79
|
+
const { x, y } = getResizeEventCoordinates(event);
|
|
80
|
+
|
|
81
|
+
isPointerDown = true;
|
|
82
|
+
|
|
83
|
+
updateResizeHandlerStates("down", event);
|
|
84
|
+
|
|
85
|
+
recalculateIntersectingHandles({ x, y });
|
|
86
|
+
updateListeners();
|
|
87
|
+
|
|
88
|
+
if (intersectingHandles.length > 0) {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handlePointerMove(event: ResizeEvent) {
|
|
94
|
+
const { x, y } = getResizeEventCoordinates(event);
|
|
95
|
+
|
|
96
|
+
if (isPointerDown) {
|
|
97
|
+
intersectingHandles.forEach((data) => {
|
|
98
|
+
const { setResizeHandlerState } = data;
|
|
99
|
+
|
|
100
|
+
setResizeHandlerState("move", "drag", event);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Update cursor based on return value(s) from active handles
|
|
104
|
+
updateCursor();
|
|
105
|
+
} else {
|
|
106
|
+
recalculateIntersectingHandles({ x, y });
|
|
107
|
+
updateResizeHandlerStates("move", event);
|
|
108
|
+
updateCursor();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (intersectingHandles.length > 0) {
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function handlePointerUp(event: ResizeEvent) {
|
|
117
|
+
const { x, y } = getResizeEventCoordinates(event);
|
|
118
|
+
|
|
119
|
+
panelConstraintFlags.clear();
|
|
120
|
+
isPointerDown = false;
|
|
121
|
+
|
|
122
|
+
if (intersectingHandles.length > 0) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
recalculateIntersectingHandles({ x, y });
|
|
127
|
+
updateResizeHandlerStates("up", event);
|
|
128
|
+
updateCursor();
|
|
129
|
+
|
|
130
|
+
updateListeners();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function recalculateIntersectingHandles({ x, y }: { x: number; y: number }) {
|
|
134
|
+
intersectingHandles.splice(0);
|
|
135
|
+
|
|
136
|
+
registeredResizeHandlers.forEach((data) => {
|
|
137
|
+
const { element, hitAreaMargins } = data;
|
|
138
|
+
const { bottom, left, right, top } = element.getBoundingClientRect();
|
|
139
|
+
|
|
140
|
+
const margin = isCoarsePointer
|
|
141
|
+
? hitAreaMargins.coarse
|
|
142
|
+
: hitAreaMargins.fine;
|
|
143
|
+
|
|
144
|
+
const intersects =
|
|
145
|
+
x >= left - margin &&
|
|
146
|
+
x <= right + margin &&
|
|
147
|
+
y >= top - margin &&
|
|
148
|
+
y <= bottom + margin;
|
|
149
|
+
|
|
150
|
+
if (intersects) {
|
|
151
|
+
intersectingHandles.push(data);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function reportConstraintsViolation(
|
|
157
|
+
resizeHandleId: string,
|
|
158
|
+
flag: number
|
|
159
|
+
) {
|
|
160
|
+
panelConstraintFlags.set(resizeHandleId, flag);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function updateCursor() {
|
|
164
|
+
let intersectsHorizontal = false;
|
|
165
|
+
let intersectsVertical = false;
|
|
166
|
+
|
|
167
|
+
intersectingHandles.forEach((data) => {
|
|
168
|
+
const { direction } = data;
|
|
169
|
+
|
|
170
|
+
if (direction === "horizontal") {
|
|
171
|
+
intersectsHorizontal = true;
|
|
172
|
+
} else {
|
|
173
|
+
intersectsVertical = true;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
let constraintFlags = 0;
|
|
178
|
+
panelConstraintFlags.forEach((flag) => {
|
|
179
|
+
constraintFlags |= flag;
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (intersectsHorizontal && intersectsVertical) {
|
|
183
|
+
setGlobalCursorStyle("intersection", constraintFlags);
|
|
184
|
+
} else if (intersectsHorizontal) {
|
|
185
|
+
setGlobalCursorStyle("horizontal", constraintFlags);
|
|
186
|
+
} else if (intersectsVertical) {
|
|
187
|
+
setGlobalCursorStyle("vertical", constraintFlags);
|
|
188
|
+
} else {
|
|
189
|
+
resetGlobalCursorStyle();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function updateListeners() {
|
|
194
|
+
ownerDocumentCounts.forEach((_, ownerDocument) => {
|
|
195
|
+
const { body } = ownerDocument;
|
|
196
|
+
|
|
197
|
+
body.removeEventListener("contextmenu", handlePointerUp);
|
|
198
|
+
body.removeEventListener("mousedown", handlePointerDown);
|
|
199
|
+
body.removeEventListener("mouseleave", handlePointerMove);
|
|
200
|
+
body.removeEventListener("mousemove", handlePointerMove);
|
|
201
|
+
body.removeEventListener("touchmove", handlePointerMove);
|
|
202
|
+
body.removeEventListener("touchstart", handlePointerDown);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
window.removeEventListener("mouseup", handlePointerUp);
|
|
206
|
+
window.removeEventListener("touchcancel", handlePointerUp);
|
|
207
|
+
window.removeEventListener("touchend", handlePointerUp);
|
|
208
|
+
|
|
209
|
+
if (registerResizeHandle.length > 0) {
|
|
210
|
+
if (isPointerDown) {
|
|
211
|
+
if (intersectingHandles.length > 0) {
|
|
212
|
+
ownerDocumentCounts.forEach((count, ownerDocument) => {
|
|
213
|
+
const { body } = ownerDocument;
|
|
214
|
+
|
|
215
|
+
if (count > 0) {
|
|
216
|
+
body.addEventListener("contextmenu", handlePointerUp);
|
|
217
|
+
body.addEventListener("mouseleave", handlePointerMove);
|
|
218
|
+
body.addEventListener("mousemove", handlePointerMove);
|
|
219
|
+
body.addEventListener("touchmove", handlePointerMove, {
|
|
220
|
+
passive: false,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
window.addEventListener("mouseup", handlePointerUp);
|
|
227
|
+
window.addEventListener("touchcancel", handlePointerUp);
|
|
228
|
+
window.addEventListener("touchend", handlePointerUp);
|
|
229
|
+
} else {
|
|
230
|
+
ownerDocumentCounts.forEach((count, ownerDocument) => {
|
|
231
|
+
const { body } = ownerDocument;
|
|
232
|
+
|
|
233
|
+
if (count > 0) {
|
|
234
|
+
body.addEventListener("mousedown", handlePointerDown);
|
|
235
|
+
body.addEventListener("mousemove", handlePointerMove);
|
|
236
|
+
body.addEventListener("touchmove", handlePointerMove, {
|
|
237
|
+
passive: false,
|
|
238
|
+
});
|
|
239
|
+
body.addEventListener("touchstart", handlePointerDown);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function updateResizeHandlerStates(
|
|
247
|
+
action: ResizeHandlerAction,
|
|
248
|
+
event: ResizeEvent
|
|
249
|
+
) {
|
|
250
|
+
registeredResizeHandlers.forEach((data) => {
|
|
251
|
+
const { setResizeHandlerState } = data;
|
|
252
|
+
|
|
253
|
+
if (intersectingHandles.includes(data)) {
|
|
254
|
+
if (isPointerDown) {
|
|
255
|
+
setResizeHandlerState(action, "drag", event);
|
|
256
|
+
} else {
|
|
257
|
+
setResizeHandlerState(action, "hover", event);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
setResizeHandlerState(action, "inactive", event);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
@@ -3,7 +3,7 @@ import { Direction } from "../types";
|
|
|
3
3
|
import { assert } from "./assert";
|
|
4
4
|
import { getPanelGroupElement } from "./dom/getPanelGroupElement";
|
|
5
5
|
import { getResizeHandleElement } from "./dom/getResizeHandleElement";
|
|
6
|
-
import { getResizeEventCursorPosition } from "./getResizeEventCursorPosition";
|
|
6
|
+
import { getResizeEventCursorPosition } from "./events/getResizeEventCursorPosition";
|
|
7
7
|
|
|
8
8
|
export function calculateDragOffsetPercentage(
|
|
9
9
|
event: ResizeEvent,
|