Skip to content

Commit b46e017

Browse files
committed
Clean up shared code a bit
1 parent 592cb47 commit b46e017

File tree

3 files changed

+142
-126
lines changed

3 files changed

+142
-126
lines changed

lib/global/event-handlers/onGroupPointerLeave.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
import { read } from "../mutableState";
2-
import { onWindowPointerMove } from "./onWindowPointerMove";
2+
import { updateActiveHitRegions } from "../utils/updateActiveHitRegion";
33

44
export function onGroupPointerLeave(event: PointerEvent) {
5-
const { interactionState } = read();
5+
if (event.defaultPrevented) {
6+
return;
7+
} else if (event.relatedTarget !== null) {
8+
return;
9+
}
10+
11+
const { interactionState, mountedGroups } = read();
612

13+
// The "pointerleave" event is not reliably triggered when the pointer exits a window or iframe
14+
// To account for this, we listen for "pointerleave" events on the Group element itself
715
switch (interactionState.state) {
816
case "active": {
917
interactionState.hitRegions.forEach((hitRegion) => {
1018
if (event.currentTarget === hitRegion.group.element) {
11-
// The "pointerleave" event is not reliably triggered when the pointer exits a window or iframe
12-
// To account for this, we listen for "pointerleave" events on the Group element itself
13-
// The easiest way to handle these is to reuse the same logic as the Window "pointermove" event
14-
onWindowPointerMove(event);
19+
updateActiveHitRegions({
20+
event,
21+
hitRegions: interactionState.hitRegions,
22+
initialLayoutMap: interactionState.initialLayoutMap,
23+
mountedGroups
24+
});
1525
}
1626
});
1727
}

lib/global/event-handlers/onWindowPointerMove.ts

Lines changed: 7 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
import {
2-
CURSOR_FLAG_HORIZONTAL_MAX,
3-
CURSOR_FLAG_HORIZONTAL_MIN,
4-
CURSOR_FLAG_VERTICAL_MAX,
5-
CURSOR_FLAG_VERTICAL_MIN
6-
} from "../../constants";
7-
import { updateCursorStyle } from "../cursor/updateCursorStyle";
81
import { read, update } from "../mutableState";
9-
import { adjustLayoutByDelta } from "../utils/adjustLayoutByDelta";
10-
import { findMatchingHitRegions } from "../utils/findMatchingHitRegions";
11-
import { layoutsEqual } from "../utils/layoutsEqual";
2+
import { updateActiveHitRegions } from "../utils/updateActiveHitRegion";
123

134
export function onWindowPointerMove(event: PointerEvent) {
145
if (event.defaultPrevented) {
@@ -40,117 +31,13 @@ export function onWindowPointerMove(event: PointerEvent) {
4031
return;
4132
}
4233

43-
let cursorFlags = 0;
44-
const nextMountedGroups = new Map(mountedGroups);
45-
46-
// Note that HitRegions are frozen once a drag has started
47-
// Modify the Group layouts for all matching HitRegions though
48-
interactionState.hitRegions.forEach((current) => {
49-
const { disableCursor, element, orientation, panels } = current.group;
50-
51-
let deltaAsPercentage = 0;
52-
if (interactionState.state === "active") {
53-
if (orientation === "horizontal") {
54-
deltaAsPercentage =
55-
((event.clientX - interactionState.pointerDownAtPoint.x) /
56-
element.offsetWidth) *
57-
100;
58-
} else {
59-
deltaAsPercentage =
60-
((event.clientY - interactionState.pointerDownAtPoint.y) /
61-
element.offsetHeight) *
62-
100;
63-
}
64-
}
65-
66-
const initialLayout = interactionState.initialLayoutMap.get(
67-
current.group
68-
);
69-
const {
70-
derivedPanelConstraints,
71-
layout: prevLayout,
72-
separatorToPanels
73-
} = mountedGroups.get(current.group) ?? {};
74-
if (
75-
derivedPanelConstraints &&
76-
initialLayout &&
77-
prevLayout &&
78-
separatorToPanels
79-
) {
80-
const nextLayout = adjustLayoutByDelta({
81-
delta: deltaAsPercentage,
82-
initialLayout,
83-
panelConstraints: derivedPanelConstraints,
84-
pivotIndices: current.panels.map((panel) => panels.indexOf(panel)),
85-
prevLayout,
86-
trigger: "mouse-or-touch"
87-
});
88-
89-
if (layoutsEqual(nextLayout, prevLayout)) {
90-
if (deltaAsPercentage !== 0 && !disableCursor) {
91-
// An unchanged means the cursor has exceeded the allowed bounds
92-
switch (orientation) {
93-
case "horizontal": {
94-
cursorFlags |=
95-
deltaAsPercentage < 0
96-
? CURSOR_FLAG_HORIZONTAL_MIN
97-
: CURSOR_FLAG_HORIZONTAL_MAX;
98-
break;
99-
}
100-
case "vertical": {
101-
cursorFlags |=
102-
deltaAsPercentage < 0
103-
? CURSOR_FLAG_VERTICAL_MIN
104-
: CURSOR_FLAG_VERTICAL_MAX;
105-
break;
106-
}
107-
}
108-
}
109-
} else {
110-
nextMountedGroups.set(current.group, {
111-
derivedPanelConstraints: derivedPanelConstraints,
112-
layout: nextLayout,
113-
separatorToPanels
114-
});
115-
116-
// Save the most recent layout for this group of panels in-memory
117-
// so that layouts will be remembered between different sets of conditionally rendered panels
118-
const panelIdsKey = current.group.panels
119-
.map(({ id }) => id)
120-
.join(",");
121-
current.group.inMemoryLayouts[panelIdsKey] = nextLayout;
122-
}
123-
}
34+
updateActiveHitRegions({
35+
event,
36+
hitRegions: interactionState.hitRegions,
37+
initialLayoutMap: interactionState.initialLayoutMap,
38+
mountedGroups,
39+
pointerDownAtPoint: interactionState.pointerDownAtPoint
12440
});
125-
126-
update({
127-
cursorFlags,
128-
mountedGroups: nextMountedGroups
129-
});
130-
131-
updateCursorStyle();
132-
break;
133-
}
134-
default: {
135-
// Update HitRegions if a drag has not been started
136-
const hitRegions = findMatchingHitRegions(event, mountedGroups);
137-
138-
if (hitRegions.length === 0) {
139-
if (interactionState.state !== "inactive") {
140-
update({
141-
interactionState: { state: "inactive" }
142-
});
143-
}
144-
} else {
145-
update({
146-
interactionState: {
147-
hitRegions,
148-
state: "hover"
149-
}
150-
});
151-
}
152-
153-
updateCursorStyle();
15441
break;
15542
}
15643
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import type { Layout, RegisteredGroup } from "../../components/group/types";
2+
import {
3+
CURSOR_FLAG_HORIZONTAL_MAX,
4+
CURSOR_FLAG_HORIZONTAL_MIN,
5+
CURSOR_FLAG_VERTICAL_MAX,
6+
CURSOR_FLAG_VERTICAL_MIN
7+
} from "../../constants";
8+
import type { Point } from "../../types";
9+
import { updateCursorStyle } from "../cursor/updateCursorStyle";
10+
import type { HitRegion } from "../dom/calculateHitRegions";
11+
import { update, type MountedGroupMap } from "../mutableState";
12+
import { adjustLayoutByDelta } from "./adjustLayoutByDelta";
13+
import { layoutsEqual } from "./layoutsEqual";
14+
15+
export function updateActiveHitRegions({
16+
event,
17+
hitRegions,
18+
initialLayoutMap,
19+
mountedGroups,
20+
pointerDownAtPoint
21+
}: {
22+
event: {
23+
clientX: number;
24+
clientY: number;
25+
};
26+
hitRegions: HitRegion[];
27+
initialLayoutMap: Map<RegisteredGroup, Layout>;
28+
mountedGroups: MountedGroupMap;
29+
pointerDownAtPoint?: Point;
30+
}) {
31+
let cursorFlags = 0;
32+
const nextMountedGroups = new Map(mountedGroups);
33+
34+
// Note that HitRegions are frozen once a drag has started
35+
// Modify the Group layouts for all matching HitRegions though
36+
hitRegions.forEach((current) => {
37+
const { disableCursor, element, orientation, panels } = current.group;
38+
39+
let deltaAsPercentage = 0;
40+
if (pointerDownAtPoint) {
41+
if (orientation === "horizontal") {
42+
deltaAsPercentage =
43+
((event.clientX - pointerDownAtPoint.x) / element.offsetWidth) * 100;
44+
} else {
45+
deltaAsPercentage =
46+
((event.clientY - pointerDownAtPoint.y) / element.offsetHeight) * 100;
47+
}
48+
} else {
49+
if (orientation === "horizontal") {
50+
deltaAsPercentage = event.clientX < 0 ? -100 : 100;
51+
} else {
52+
deltaAsPercentage = event.clientY < 0 ? -100 : 100;
53+
}
54+
}
55+
56+
const initialLayout = initialLayoutMap.get(current.group);
57+
58+
const {
59+
derivedPanelConstraints,
60+
layout: prevLayout,
61+
separatorToPanels
62+
} = mountedGroups.get(current.group) ?? {};
63+
if (
64+
derivedPanelConstraints &&
65+
initialLayout &&
66+
prevLayout &&
67+
separatorToPanels
68+
) {
69+
const nextLayout = adjustLayoutByDelta({
70+
delta: deltaAsPercentage,
71+
initialLayout,
72+
panelConstraints: derivedPanelConstraints,
73+
pivotIndices: current.panels.map((panel) => panels.indexOf(panel)),
74+
prevLayout,
75+
trigger: "mouse-or-touch"
76+
});
77+
78+
if (layoutsEqual(nextLayout, prevLayout)) {
79+
if (deltaAsPercentage !== 0 && !disableCursor) {
80+
// An unchanged means the cursor has exceeded the allowed bounds
81+
switch (orientation) {
82+
case "horizontal": {
83+
cursorFlags |=
84+
deltaAsPercentage < 0
85+
? CURSOR_FLAG_HORIZONTAL_MIN
86+
: CURSOR_FLAG_HORIZONTAL_MAX;
87+
break;
88+
}
89+
case "vertical": {
90+
cursorFlags |=
91+
deltaAsPercentage < 0
92+
? CURSOR_FLAG_VERTICAL_MIN
93+
: CURSOR_FLAG_VERTICAL_MAX;
94+
break;
95+
}
96+
}
97+
}
98+
} else {
99+
nextMountedGroups.set(current.group, {
100+
derivedPanelConstraints: derivedPanelConstraints,
101+
layout: nextLayout,
102+
separatorToPanels
103+
});
104+
105+
// Save the most recent layout for this group of panels in-memory
106+
// so that layouts will be remembered between different sets of conditionally rendered panels
107+
const panelIdsKey = current.group.panels.map(({ id }) => id).join(",");
108+
current.group.inMemoryLayouts[panelIdsKey] = nextLayout;
109+
}
110+
}
111+
});
112+
113+
update({
114+
cursorFlags,
115+
mountedGroups: nextMountedGroups
116+
});
117+
118+
updateCursorStyle();
119+
}

0 commit comments

Comments
 (0)