react-native-screen-transitions 3.3.0-beta.2 → 3.3.0-beta.4
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/README.md +95 -31
- package/lib/commonjs/shared/animation/snap-to.js +17 -10
- package/lib/commonjs/shared/animation/snap-to.js.map +1 -1
- package/lib/commonjs/shared/components/create-transition-aware-component.js +20 -18
- package/lib/commonjs/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/commonjs/shared/components/screen-container.js +68 -9
- package/lib/commonjs/shared/components/screen-container.js.map +1 -1
- package/lib/commonjs/shared/constants.js +8 -1
- package/lib/commonjs/shared/constants.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js +49 -39
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js +110 -61
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js +67 -70
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/commonjs/shared/providers/gestures.provider.js +113 -25
- package/lib/commonjs/shared/providers/gestures.provider.js.map +1 -1
- package/lib/commonjs/shared/types/ownership.types.js +71 -0
- package/lib/commonjs/shared/types/ownership.types.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js +72 -128
- package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/compute-claimed-directions.js +81 -0
- package/lib/commonjs/shared/utils/gesture/compute-claimed-directions.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js +1 -1
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/find-collapse-target.js +48 -0
- package/lib/commonjs/shared/utils/gesture/find-collapse-target.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/resolve-ownership.js +87 -0
- package/lib/commonjs/shared/utils/gesture/resolve-ownership.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/velocity.js +16 -5
- package/lib/commonjs/shared/utils/gesture/velocity.js.map +1 -1
- package/lib/module/shared/animation/snap-to.js +16 -10
- package/lib/module/shared/animation/snap-to.js.map +1 -1
- package/lib/module/shared/components/create-transition-aware-component.js +20 -18
- package/lib/module/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/module/shared/components/screen-container.js +68 -10
- package/lib/module/shared/components/screen-container.js.map +1 -1
- package/lib/module/shared/constants.js +7 -0
- package/lib/module/shared/constants.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-build-gestures.js +49 -39
- package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js +112 -63
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js +68 -70
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/module/shared/providers/gestures.provider.js +113 -25
- package/lib/module/shared/providers/gestures.provider.js.map +1 -1
- package/lib/module/shared/types/ownership.types.js +67 -0
- package/lib/module/shared/types/ownership.types.js.map +1 -0
- package/lib/module/shared/utils/gesture/check-gesture-activation.js +70 -126
- package/lib/module/shared/utils/gesture/check-gesture-activation.js.map +1 -1
- package/lib/module/shared/utils/gesture/compute-claimed-directions.js +77 -0
- package/lib/module/shared/utils/gesture/compute-claimed-directions.js.map +1 -0
- package/lib/module/shared/utils/gesture/determine-snap-target.js +1 -1
- package/lib/module/shared/utils/gesture/determine-snap-target.js.map +1 -1
- package/lib/module/shared/utils/gesture/find-collapse-target.js +44 -0
- package/lib/module/shared/utils/gesture/find-collapse-target.js.map +1 -0
- package/lib/module/shared/utils/gesture/resolve-ownership.js +83 -0
- package/lib/module/shared/utils/gesture/resolve-ownership.js.map +1 -0
- package/lib/module/shared/utils/gesture/velocity.js +16 -5
- package/lib/module/shared/utils/gesture/velocity.js.map +1 -1
- package/lib/typescript/shared/animation/snap-to.d.ts.map +1 -1
- package/lib/typescript/shared/components/create-transition-aware-component.d.ts.map +1 -1
- package/lib/typescript/shared/components/screen-container.d.ts.map +1 -1
- package/lib/typescript/shared/constants.d.ts +6 -0
- package/lib/typescript/shared/constants.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts +15 -3
- package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts +52 -2
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts +11 -6
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts +1 -1
- package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts.map +1 -1
- package/lib/typescript/shared/providers/gestures.provider.d.ts +28 -3
- package/lib/typescript/shared/providers/gestures.provider.d.ts.map +1 -1
- package/lib/typescript/shared/types/ownership.types.d.ts +52 -0
- package/lib/typescript/shared/types/ownership.types.d.ts.map +1 -0
- package/lib/typescript/shared/types/screen.types.d.ts +22 -1
- package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts +23 -19
- package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/compute-claimed-directions.d.ts +23 -0
- package/lib/typescript/shared/utils/gesture/compute-claimed-directions.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts +5 -1
- package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/find-collapse-target.d.ts +17 -0
- package/lib/typescript/shared/utils/gesture/find-collapse-target.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/resolve-ownership.d.ts +36 -0
- package/lib/typescript/shared/utils/gesture/resolve-ownership.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/velocity.d.ts.map +1 -1
- package/package.json +121 -120
- package/src/shared/animation/snap-to.ts +17 -11
- package/src/shared/components/create-transition-aware-component.tsx +28 -25
- package/src/shared/components/screen-container.tsx +79 -12
- package/src/shared/constants.ts +7 -0
- package/src/shared/hooks/gestures/use-build-gestures.tsx +80 -44
- package/src/shared/hooks/gestures/use-screen-gesture-handlers.ts +147 -71
- package/src/shared/hooks/gestures/use-scroll-registry.tsx +94 -86
- package/src/shared/hooks/use-backdrop-pointer-events.ts +1 -1
- package/src/shared/providers/gestures.provider.tsx +168 -25
- package/src/shared/types/ownership.types.ts +77 -0
- package/src/shared/types/screen.types.ts +24 -1
- package/src/shared/utils/gesture/check-gesture-activation.ts +82 -116
- package/src/shared/utils/gesture/compute-claimed-directions.ts +93 -0
- package/src/shared/utils/gesture/determine-snap-target.ts +6 -2
- package/src/shared/utils/gesture/find-collapse-target.ts +42 -0
- package/src/shared/utils/gesture/resolve-ownership.ts +110 -0
- package/src/shared/utils/gesture/velocity.ts +16 -6
- package/src/shared/__tests__/bounds.store.test.ts +0 -394
- package/src/shared/__tests__/derivations.test.ts +0 -156
- package/src/shared/__tests__/determine-dismissal.test.ts +0 -111
- package/src/shared/__tests__/determine-snap-target.test.ts +0 -268
- package/src/shared/__tests__/geometry.test.ts +0 -130
- package/src/shared/__tests__/gesture-activation.test.ts +0 -471
- package/src/shared/__tests__/gesture.velocity.test.ts +0 -131
- package/src/shared/__tests__/history.store.test.ts +0 -550
- package/src/shared/__tests__/sync-routes-with-removed.test.ts +0 -137
- package/src/shared/__tests__/validate-snap-points.test.ts +0 -125
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import type { ScrollConfig } from "../providers/gestures.provider";
|
|
3
|
-
import {
|
|
4
|
-
normalizeSides,
|
|
5
|
-
computeEdgeConstraints,
|
|
6
|
-
calculateSwipeDirs,
|
|
7
|
-
shouldActivateOrFail,
|
|
8
|
-
checkScrollAwareActivation,
|
|
9
|
-
} from "../utils/gesture/check-gesture-activation";
|
|
10
|
-
|
|
11
|
-
/** Helper to create ScrollConfig with sensible defaults */
|
|
12
|
-
const createScrollConfig = (
|
|
13
|
-
overrides: Partial<ScrollConfig> = {},
|
|
14
|
-
): ScrollConfig => ({
|
|
15
|
-
x: 0,
|
|
16
|
-
y: 0,
|
|
17
|
-
contentWidth: 0,
|
|
18
|
-
contentHeight: 0,
|
|
19
|
-
layoutWidth: 0,
|
|
20
|
-
layoutHeight: 0,
|
|
21
|
-
isTouched: true,
|
|
22
|
-
...overrides,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe("normalizeSides", () => {
|
|
26
|
-
it("returns all sides as 'screen' when no area provided", () => {
|
|
27
|
-
const result = normalizeSides();
|
|
28
|
-
expect(result).toEqual({
|
|
29
|
-
left: "screen",
|
|
30
|
-
right: "screen",
|
|
31
|
-
top: "screen",
|
|
32
|
-
bottom: "screen",
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("normalizes string input to all sides", () => {
|
|
37
|
-
const result = normalizeSides("edge");
|
|
38
|
-
expect(result).toEqual({
|
|
39
|
-
left: "edge",
|
|
40
|
-
right: "edge",
|
|
41
|
-
top: "edge",
|
|
42
|
-
bottom: "edge",
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("handles per-side object input", () => {
|
|
47
|
-
const result = normalizeSides({
|
|
48
|
-
left: "edge",
|
|
49
|
-
right: "screen",
|
|
50
|
-
top: "edge",
|
|
51
|
-
});
|
|
52
|
-
expect(result).toEqual({
|
|
53
|
-
left: "edge",
|
|
54
|
-
right: "screen",
|
|
55
|
-
top: "edge",
|
|
56
|
-
bottom: "screen", // defaults to screen
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("defaults missing sides to screen", () => {
|
|
61
|
-
const result = normalizeSides({ left: "edge" });
|
|
62
|
-
expect(result.left).toBe("edge");
|
|
63
|
-
expect(result.right).toBe("screen");
|
|
64
|
-
expect(result.top).toBe("screen");
|
|
65
|
-
expect(result.bottom).toBe("screen");
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe("computeEdgeConstraints", () => {
|
|
70
|
-
const dimensions = { width: 375, height: 812 };
|
|
71
|
-
const allScreen = { left: "screen", right: "screen", top: "screen", bottom: "screen" } as const;
|
|
72
|
-
const allEdge = { left: "edge", right: "edge", top: "edge", bottom: "edge" } as const;
|
|
73
|
-
|
|
74
|
-
it("allows all directions when all sides are 'screen'", () => {
|
|
75
|
-
const result = computeEdgeConstraints({ x: 200, y: 400 }, dimensions, allScreen);
|
|
76
|
-
expect(result.horizontalRight).toBe(true);
|
|
77
|
-
expect(result.horizontalLeft).toBe(true);
|
|
78
|
-
expect(result.verticalDown).toBe(true);
|
|
79
|
-
expect(result.verticalUp).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("restricts to left edge for horizontal-right when edge mode", () => {
|
|
83
|
-
// Touch at x=200 (center) should NOT allow right swipe with edge activation
|
|
84
|
-
const center = computeEdgeConstraints({ x: 200, y: 400 }, dimensions, allEdge);
|
|
85
|
-
expect(center.horizontalRight).toBe(false);
|
|
86
|
-
|
|
87
|
-
// Touch at x=30 (within 50px edge) should allow right swipe
|
|
88
|
-
const edge = computeEdgeConstraints({ x: 30, y: 400 }, dimensions, allEdge);
|
|
89
|
-
expect(edge.horizontalRight).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("restricts to right edge for horizontal-left when edge mode", () => {
|
|
93
|
-
// Touch at x=200 (center) should NOT allow left swipe
|
|
94
|
-
const center = computeEdgeConstraints({ x: 200, y: 400 }, dimensions, allEdge);
|
|
95
|
-
expect(center.horizontalLeft).toBe(false);
|
|
96
|
-
|
|
97
|
-
// Touch at x=350 (within 50px of right edge) should allow left swipe
|
|
98
|
-
const edge = computeEdgeConstraints({ x: 350, y: 400 }, dimensions, allEdge);
|
|
99
|
-
expect(edge.horizontalLeft).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("restricts to top edge for vertical-down when edge mode", () => {
|
|
103
|
-
// Touch at y=400 (center) should NOT allow down swipe
|
|
104
|
-
const center = computeEdgeConstraints({ x: 200, y: 400 }, dimensions, allEdge);
|
|
105
|
-
expect(center.verticalDown).toBe(false);
|
|
106
|
-
|
|
107
|
-
// Touch at y=100 (within 135px edge) should allow down swipe
|
|
108
|
-
const edge = computeEdgeConstraints({ x: 200, y: 100 }, dimensions, allEdge);
|
|
109
|
-
expect(edge.verticalDown).toBe(true);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("uses custom responseDistance", () => {
|
|
113
|
-
// With custom distance of 100px
|
|
114
|
-
const result = computeEdgeConstraints({ x: 80, y: 400 }, dimensions, allEdge, 100);
|
|
115
|
-
expect(result.horizontalRight).toBe(true); // 80 < 100
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
describe("calculateSwipeDirs", () => {
|
|
120
|
-
it("detects horizontal swipe right", () => {
|
|
121
|
-
const result = calculateSwipeDirs(50, 10);
|
|
122
|
-
expect(result.isHorizontalSwipe).toBe(true);
|
|
123
|
-
expect(result.isVerticalSwipe).toBe(false);
|
|
124
|
-
expect(result.isSwipingRight).toBe(true);
|
|
125
|
-
expect(result.isSwipingLeft).toBe(false);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("detects horizontal swipe left", () => {
|
|
129
|
-
const result = calculateSwipeDirs(-50, 10);
|
|
130
|
-
expect(result.isHorizontalSwipe).toBe(true);
|
|
131
|
-
expect(result.isSwipingLeft).toBe(true);
|
|
132
|
-
expect(result.isSwipingRight).toBe(false);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it("detects vertical swipe down", () => {
|
|
136
|
-
const result = calculateSwipeDirs(10, 50);
|
|
137
|
-
expect(result.isVerticalSwipe).toBe(true);
|
|
138
|
-
expect(result.isHorizontalSwipe).toBe(false);
|
|
139
|
-
expect(result.isSwipingDown).toBe(true);
|
|
140
|
-
expect(result.isSwipingUp).toBe(false);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("detects vertical swipe up", () => {
|
|
144
|
-
const result = calculateSwipeDirs(10, -50);
|
|
145
|
-
expect(result.isVerticalSwipe).toBe(true);
|
|
146
|
-
expect(result.isSwipingUp).toBe(true);
|
|
147
|
-
expect(result.isSwipingDown).toBe(false);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("horizontal wins when equal deltas", () => {
|
|
151
|
-
// When deltaX === deltaY, neither wins (both false)
|
|
152
|
-
const result = calculateSwipeDirs(50, 50);
|
|
153
|
-
expect(result.isHorizontalSwipe).toBe(false);
|
|
154
|
-
expect(result.isVerticalSwipe).toBe(false);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe("shouldActivateOrFail", () => {
|
|
159
|
-
const baseParams = {
|
|
160
|
-
deltaX: 0,
|
|
161
|
-
deltaY: 0,
|
|
162
|
-
hasHorizontal: true,
|
|
163
|
-
hasVertical: true,
|
|
164
|
-
isHorizontalSwipe: false,
|
|
165
|
-
isVerticalSwipe: false,
|
|
166
|
-
allowedRight: true,
|
|
167
|
-
allowedLeft: true,
|
|
168
|
-
allowedUp: true,
|
|
169
|
-
allowedDown: true,
|
|
170
|
-
horizontalGateRight: true,
|
|
171
|
-
horizontalGateLeft: true,
|
|
172
|
-
verticalGateUp: true,
|
|
173
|
-
verticalGateDown: true,
|
|
174
|
-
isSwipingRight: false,
|
|
175
|
-
isSwipingLeft: false,
|
|
176
|
-
isSwipingUp: false,
|
|
177
|
-
isSwipingDown: false,
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
it("activates on valid horizontal right swipe", () => {
|
|
181
|
-
const result = shouldActivateOrFail({
|
|
182
|
-
...baseParams,
|
|
183
|
-
deltaX: 15, // above threshold (10)
|
|
184
|
-
deltaY: 5, // within tolerance (15)
|
|
185
|
-
isHorizontalSwipe: true,
|
|
186
|
-
isSwipingRight: true,
|
|
187
|
-
});
|
|
188
|
-
expect(result.shouldActivate).toBe(true);
|
|
189
|
-
expect(result.shouldFail).toBe(false);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("activates on valid vertical down swipe", () => {
|
|
193
|
-
const result = shouldActivateOrFail({
|
|
194
|
-
...baseParams,
|
|
195
|
-
deltaX: 5, // within tolerance (20)
|
|
196
|
-
deltaY: 15, // above threshold (10)
|
|
197
|
-
isVerticalSwipe: true,
|
|
198
|
-
isSwipingDown: true,
|
|
199
|
-
});
|
|
200
|
-
expect(result.shouldActivate).toBe(true);
|
|
201
|
-
expect(result.shouldFail).toBe(false);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("fails when swiping in disallowed direction", () => {
|
|
205
|
-
const result = shouldActivateOrFail({
|
|
206
|
-
...baseParams,
|
|
207
|
-
deltaX: 15,
|
|
208
|
-
deltaY: 5,
|
|
209
|
-
isHorizontalSwipe: true,
|
|
210
|
-
isSwipingRight: true,
|
|
211
|
-
allowedRight: false, // direction not allowed
|
|
212
|
-
});
|
|
213
|
-
expect(result.shouldActivate).toBe(false);
|
|
214
|
-
expect(result.shouldFail).toBe(true);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it("fails when edge gate blocks the swipe", () => {
|
|
218
|
-
const result = shouldActivateOrFail({
|
|
219
|
-
...baseParams,
|
|
220
|
-
deltaX: 15,
|
|
221
|
-
deltaY: 5,
|
|
222
|
-
isHorizontalSwipe: true,
|
|
223
|
-
isSwipingRight: true,
|
|
224
|
-
horizontalGateRight: false, // edge gate blocks
|
|
225
|
-
});
|
|
226
|
-
expect(result.shouldActivate).toBe(false);
|
|
227
|
-
expect(result.shouldFail).toBe(true);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("fails when vertical deviation exceeds tolerance during horizontal swipe", () => {
|
|
231
|
-
const result = shouldActivateOrFail({
|
|
232
|
-
...baseParams,
|
|
233
|
-
deltaX: 15,
|
|
234
|
-
deltaY: 20, // exceeds GESTURE_FAIL_TOLERANCE_X (15)
|
|
235
|
-
isHorizontalSwipe: true,
|
|
236
|
-
isSwipingRight: true,
|
|
237
|
-
});
|
|
238
|
-
expect(result.shouldActivate).toBe(false);
|
|
239
|
-
expect(result.shouldFail).toBe(true);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it("does not activate when movement is below threshold", () => {
|
|
243
|
-
const result = shouldActivateOrFail({
|
|
244
|
-
...baseParams,
|
|
245
|
-
deltaX: 5, // below threshold (10)
|
|
246
|
-
deltaY: 2,
|
|
247
|
-
isHorizontalSwipe: true,
|
|
248
|
-
isSwipingRight: true,
|
|
249
|
-
});
|
|
250
|
-
expect(result.shouldActivate).toBe(false);
|
|
251
|
-
expect(result.shouldFail).toBe(false);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("handles bidirectional gesture activation", () => {
|
|
255
|
-
// Both horizontal and vertical allowed, vertical swipe detected
|
|
256
|
-
const result = shouldActivateOrFail({
|
|
257
|
-
...baseParams,
|
|
258
|
-
hasHorizontal: true,
|
|
259
|
-
hasVertical: true,
|
|
260
|
-
deltaX: 5,
|
|
261
|
-
deltaY: 15,
|
|
262
|
-
isVerticalSwipe: true,
|
|
263
|
-
isSwipingDown: true,
|
|
264
|
-
});
|
|
265
|
-
expect(result.shouldActivate).toBe(true);
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
describe("checkScrollAwareActivation", () => {
|
|
270
|
-
const baseDirections = {
|
|
271
|
-
vertical: true,
|
|
272
|
-
verticalInverted: false,
|
|
273
|
-
horizontal: false,
|
|
274
|
-
horizontalInverted: false,
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const noSwipe = {
|
|
278
|
-
isSwipingDown: false,
|
|
279
|
-
isSwipingUp: false,
|
|
280
|
-
isSwipingRight: false,
|
|
281
|
-
isSwipingLeft: false,
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
describe("vertical sheet (dismiss down)", () => {
|
|
285
|
-
it("activates when swiping down at scroll top", () => {
|
|
286
|
-
const result = checkScrollAwareActivation({
|
|
287
|
-
swipeInfo: { ...noSwipe, isSwipingDown: true },
|
|
288
|
-
directions: baseDirections,
|
|
289
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
290
|
-
});
|
|
291
|
-
expect(result.shouldActivate).toBe(true);
|
|
292
|
-
expect(result.direction).toBe("vertical");
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it("does not activate when swiping down but scroll is not at top", () => {
|
|
296
|
-
const result = checkScrollAwareActivation({
|
|
297
|
-
swipeInfo: { ...noSwipe, isSwipingDown: true },
|
|
298
|
-
directions: baseDirections,
|
|
299
|
-
scrollConfig: createScrollConfig({ y: 100, contentHeight: 500, layoutHeight: 0 }),
|
|
300
|
-
});
|
|
301
|
-
expect(result.shouldActivate).toBe(false);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it("does not activate when swiping up without snap points", () => {
|
|
305
|
-
const result = checkScrollAwareActivation({
|
|
306
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
307
|
-
directions: baseDirections,
|
|
308
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
309
|
-
});
|
|
310
|
-
expect(result.shouldActivate).toBe(false);
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe("vertical inverted sheet (dismiss up)", () => {
|
|
315
|
-
const invertedDirections = {
|
|
316
|
-
vertical: false,
|
|
317
|
-
verticalInverted: true,
|
|
318
|
-
horizontal: false,
|
|
319
|
-
horizontalInverted: false,
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
it("activates when swiping up at scroll bottom", () => {
|
|
323
|
-
const result = checkScrollAwareActivation({
|
|
324
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
325
|
-
directions: invertedDirections,
|
|
326
|
-
scrollConfig: createScrollConfig({ y: 500, contentHeight: 500, layoutHeight: 0 }),
|
|
327
|
-
});
|
|
328
|
-
expect(result.shouldActivate).toBe(true);
|
|
329
|
-
expect(result.direction).toBe("vertical-inverted");
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
it("does not activate when swiping up but scroll is not at bottom", () => {
|
|
333
|
-
const result = checkScrollAwareActivation({
|
|
334
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
335
|
-
directions: invertedDirections,
|
|
336
|
-
scrollConfig: createScrollConfig({ y: 200, contentHeight: 500, layoutHeight: 0 }),
|
|
337
|
-
});
|
|
338
|
-
expect(result.shouldActivate).toBe(false);
|
|
339
|
-
});
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
describe("horizontal sheet (dismiss right)", () => {
|
|
343
|
-
const horizontalDirections = {
|
|
344
|
-
vertical: false,
|
|
345
|
-
verticalInverted: false,
|
|
346
|
-
horizontal: true,
|
|
347
|
-
horizontalInverted: false,
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
it("activates when swiping right at scroll left edge", () => {
|
|
351
|
-
const result = checkScrollAwareActivation({
|
|
352
|
-
swipeInfo: { ...noSwipe, isSwipingRight: true },
|
|
353
|
-
directions: horizontalDirections,
|
|
354
|
-
scrollConfig: createScrollConfig({ contentWidth: 500, layoutWidth: 0 }),
|
|
355
|
-
});
|
|
356
|
-
expect(result.shouldActivate).toBe(true);
|
|
357
|
-
expect(result.direction).toBe("horizontal");
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
it("does not activate when scroll is not at left edge", () => {
|
|
361
|
-
const result = checkScrollAwareActivation({
|
|
362
|
-
swipeInfo: { ...noSwipe, isSwipingRight: true },
|
|
363
|
-
directions: horizontalDirections,
|
|
364
|
-
scrollConfig: createScrollConfig({ x: 100, contentWidth: 500, layoutWidth: 0 }),
|
|
365
|
-
});
|
|
366
|
-
expect(result.shouldActivate).toBe(false);
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
describe("horizontal inverted sheet (dismiss left)", () => {
|
|
371
|
-
const invertedHorizontalDirections = {
|
|
372
|
-
vertical: false,
|
|
373
|
-
verticalInverted: false,
|
|
374
|
-
horizontal: false,
|
|
375
|
-
horizontalInverted: true,
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
it("activates when swiping left at scroll right edge", () => {
|
|
379
|
-
const result = checkScrollAwareActivation({
|
|
380
|
-
swipeInfo: { ...noSwipe, isSwipingLeft: true },
|
|
381
|
-
directions: invertedHorizontalDirections,
|
|
382
|
-
scrollConfig: createScrollConfig({ x: 500, contentWidth: 500, layoutWidth: 0 }),
|
|
383
|
-
});
|
|
384
|
-
expect(result.shouldActivate).toBe(true);
|
|
385
|
-
expect(result.direction).toBe("horizontal-inverted");
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
describe("snap points behavior", () => {
|
|
390
|
-
it("activates for swipe up (expand) at scroll top when hasSnapPoints and canExpandMore", () => {
|
|
391
|
-
const result = checkScrollAwareActivation({
|
|
392
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
393
|
-
directions: baseDirections,
|
|
394
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
395
|
-
hasSnapPoints: true,
|
|
396
|
-
canExpandMore: true,
|
|
397
|
-
});
|
|
398
|
-
expect(result.shouldActivate).toBe(true);
|
|
399
|
-
expect(result.direction).toBe("vertical-inverted");
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
it("does not activate for swipe up when canExpandMore is false", () => {
|
|
403
|
-
const result = checkScrollAwareActivation({
|
|
404
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
405
|
-
directions: baseDirections,
|
|
406
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
407
|
-
hasSnapPoints: true,
|
|
408
|
-
canExpandMore: false,
|
|
409
|
-
});
|
|
410
|
-
expect(result.shouldActivate).toBe(false);
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it("does not activate for swipe up when scroll is not at top", () => {
|
|
414
|
-
const result = checkScrollAwareActivation({
|
|
415
|
-
swipeInfo: { ...noSwipe, isSwipingUp: true },
|
|
416
|
-
directions: baseDirections,
|
|
417
|
-
scrollConfig: createScrollConfig({ y: 100, contentHeight: 500, layoutHeight: 0 }),
|
|
418
|
-
hasSnapPoints: true,
|
|
419
|
-
canExpandMore: true,
|
|
420
|
-
});
|
|
421
|
-
expect(result.shouldActivate).toBe(false);
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
it("activates for swipe left (expand) on horizontal sheet with snap points", () => {
|
|
425
|
-
const horizontalDirections = {
|
|
426
|
-
vertical: false,
|
|
427
|
-
verticalInverted: false,
|
|
428
|
-
horizontal: true,
|
|
429
|
-
horizontalInverted: false,
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
const result = checkScrollAwareActivation({
|
|
433
|
-
swipeInfo: { ...noSwipe, isSwipingLeft: true },
|
|
434
|
-
directions: horizontalDirections,
|
|
435
|
-
scrollConfig: createScrollConfig({ contentWidth: 500, layoutWidth: 0 }),
|
|
436
|
-
hasSnapPoints: true,
|
|
437
|
-
canExpandMore: true,
|
|
438
|
-
});
|
|
439
|
-
expect(result.shouldActivate).toBe(true);
|
|
440
|
-
expect(result.direction).toBe("horizontal-inverted");
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
describe("no activation cases", () => {
|
|
445
|
-
it("returns false when no swipe is detected", () => {
|
|
446
|
-
const result = checkScrollAwareActivation({
|
|
447
|
-
swipeInfo: noSwipe,
|
|
448
|
-
directions: baseDirections,
|
|
449
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
450
|
-
});
|
|
451
|
-
expect(result.shouldActivate).toBe(false);
|
|
452
|
-
expect(result.direction).toBe(null);
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
it("returns false when direction is disabled", () => {
|
|
456
|
-
const disabledDirections = {
|
|
457
|
-
vertical: false,
|
|
458
|
-
verticalInverted: false,
|
|
459
|
-
horizontal: false,
|
|
460
|
-
horizontalInverted: false,
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
const result = checkScrollAwareActivation({
|
|
464
|
-
swipeInfo: { ...noSwipe, isSwipingDown: true },
|
|
465
|
-
directions: disabledDirections,
|
|
466
|
-
scrollConfig: createScrollConfig({ contentHeight: 500, layoutHeight: 0 }),
|
|
467
|
-
});
|
|
468
|
-
expect(result.shouldActivate).toBe(false);
|
|
469
|
-
});
|
|
470
|
-
});
|
|
471
|
-
});
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { velocity } from "../utils/gesture/velocity";
|
|
3
|
-
|
|
4
|
-
type Directions = {
|
|
5
|
-
horizontal: boolean;
|
|
6
|
-
horizontalInverted: boolean;
|
|
7
|
-
vertical: boolean;
|
|
8
|
-
verticalInverted: boolean;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type GestureEventInit = {
|
|
12
|
-
translationX?: number;
|
|
13
|
-
translationY?: number;
|
|
14
|
-
velocityX?: number;
|
|
15
|
-
velocityY?: number;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const createAnimations = (progress: number) =>
|
|
19
|
-
({
|
|
20
|
-
progress: { value: progress },
|
|
21
|
-
closing: { value: 0 },
|
|
22
|
-
animating: { value: 0 },
|
|
23
|
-
}) as const;
|
|
24
|
-
|
|
25
|
-
const createEvent = ({
|
|
26
|
-
translationX = 0,
|
|
27
|
-
translationY = 0,
|
|
28
|
-
velocityX = 0,
|
|
29
|
-
velocityY = 0,
|
|
30
|
-
}: GestureEventInit) =>
|
|
31
|
-
({ translationX, translationY, velocityX, velocityY }) as any;
|
|
32
|
-
|
|
33
|
-
const createDirections = (overrides: Partial<Directions> = {}) => ({
|
|
34
|
-
horizontal: false,
|
|
35
|
-
horizontalInverted: false,
|
|
36
|
-
vertical: false,
|
|
37
|
-
verticalInverted: false,
|
|
38
|
-
...overrides,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe("velocity.normalize", () => {
|
|
42
|
-
it("clamps values to the configured range", () => {
|
|
43
|
-
expect(velocity.normalize(6400, 320)).toBeCloseTo(3.2, 5);
|
|
44
|
-
expect(velocity.normalize(-6400, 320)).toBeCloseTo(-3.2, 5);
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe("velocity.calculateProgressVelocity", () => {
|
|
49
|
-
const dimensions = { width: 320, height: 640 };
|
|
50
|
-
|
|
51
|
-
it("returns positive magnitude when progressing toward open target", () => {
|
|
52
|
-
const animations = createAnimations(0.25);
|
|
53
|
-
const event = createEvent({
|
|
54
|
-
translationX: 48,
|
|
55
|
-
translationY: 6,
|
|
56
|
-
velocityX: 800,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const result = velocity.calculateProgressVelocity({
|
|
60
|
-
animations: animations as any,
|
|
61
|
-
shouldDismiss: false,
|
|
62
|
-
event,
|
|
63
|
-
dimensions,
|
|
64
|
-
directions: createDirections({ horizontal: true }),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
expect(result).toBeCloseTo(2.5, 5);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("prefers the axis with greater normalized translation", () => {
|
|
71
|
-
const animations = createAnimations(0.8);
|
|
72
|
-
const event = createEvent({
|
|
73
|
-
translationX: 24,
|
|
74
|
-
translationY: -140,
|
|
75
|
-
velocityX: 120,
|
|
76
|
-
velocityY: -900,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const result = velocity.calculateProgressVelocity({
|
|
80
|
-
animations: animations as any,
|
|
81
|
-
shouldDismiss: true,
|
|
82
|
-
event,
|
|
83
|
-
dimensions,
|
|
84
|
-
directions: createDirections({
|
|
85
|
-
horizontal: true,
|
|
86
|
-
verticalInverted: true,
|
|
87
|
-
}),
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
expect(result).toBeLessThan(0);
|
|
91
|
-
expect(Math.abs(result)).toBeCloseTo(1.406, 3);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("caps the returned magnitude using clamp", () => {
|
|
95
|
-
const animations = createAnimations(0.5);
|
|
96
|
-
const event = createEvent({
|
|
97
|
-
translationX: 10,
|
|
98
|
-
velocityX: 5000,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const result = velocity.calculateProgressVelocity({
|
|
102
|
-
animations: animations as any,
|
|
103
|
-
shouldDismiss: false,
|
|
104
|
-
event,
|
|
105
|
-
dimensions,
|
|
106
|
-
directions: createDirections({ horizontal: true }),
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
expect(result).toBeCloseTo(3.2, 5);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe("velocity.shouldPassDismissalThreshold", () => {
|
|
114
|
-
const width = 320;
|
|
115
|
-
|
|
116
|
-
it("returns true once translation alone crosses half the screen", () => {
|
|
117
|
-
expect(velocity.shouldPassDismissalThreshold(170, 0, width, 0.3)).toBe(
|
|
118
|
-
true,
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("combines translation with weighted velocity", () => {
|
|
123
|
-
expect(velocity.shouldPassDismissalThreshold(40, 2500, width, 0.5)).toBe(
|
|
124
|
-
true,
|
|
125
|
-
);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("returns false when movement is negligible", () => {
|
|
129
|
-
expect(velocity.shouldPassDismissalThreshold(0, 0, width, 0.3)).toBe(false);
|
|
130
|
-
});
|
|
131
|
-
});
|