@tamagui/react-native-pan-responder 0.0.0-bootstrap.0 → 3.0.0-beta.1097.1
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/LICENSE +21 -0
- package/dist/cjs/PanResponder.cjs +151 -0
- package/dist/cjs/PanResponder.native.cjs +155 -0
- package/dist/cjs/PanResponder.native.js +157 -0
- package/dist/cjs/PanResponder.native.js.map +1 -0
- package/dist/cjs/TouchHistoryMath.cjs +81 -0
- package/dist/cjs/TouchHistoryMath.native.cjs +83 -0
- package/dist/cjs/TouchHistoryMath.native.js +85 -0
- package/dist/cjs/TouchHistoryMath.native.js.map +1 -0
- package/dist/cjs/index.cjs +19 -0
- package/dist/cjs/index.native.cjs +21 -0
- package/dist/cjs/index.native.js +23 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/types.cjs +16 -0
- package/dist/cjs/types.native.cjs +18 -0
- package/dist/cjs/types.native.js +20 -0
- package/dist/cjs/types.native.js.map +1 -0
- package/dist/esm/PanResponder.mjs +132 -0
- package/dist/esm/PanResponder.mjs.map +1 -0
- package/dist/esm/PanResponder.native.js +134 -0
- package/dist/esm/PanResponder.native.js.map +1 -0
- package/dist/esm/TouchHistoryMath.mjs +53 -0
- package/dist/esm/TouchHistoryMath.mjs.map +1 -0
- package/dist/esm/TouchHistoryMath.native.js +53 -0
- package/dist/esm/TouchHistoryMath.native.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.mjs +3 -0
- package/dist/esm/index.native.js +3 -0
- package/dist/esm/types.mjs +0 -0
- package/dist/esm/types.native.js +0 -0
- package/package.json +43 -7
- package/src/PanResponder.ts +218 -0
- package/src/TouchHistoryMath.ts +106 -0
- package/src/index.ts +2 -0
- package/src/types.ts +44 -0
- package/types/PanResponder.d.ts +21 -0
- package/types/PanResponder.d.ts.map +1 -0
- package/types/TouchHistoryMath.d.ts +15 -0
- package/types/TouchHistoryMath.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
- package/types/types.d.ts +34 -0
- package/types/types.d.ts.map +1 -0
- package/README.md +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var noCentroid = -1;
|
|
2
|
+
function centroidDimension(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) {
|
|
3
|
+
var touchBank = touchHistory.touchBank;
|
|
4
|
+
var total = 0;
|
|
5
|
+
var count = 0;
|
|
6
|
+
var oneTouchData = touchHistory.numberActiveTouches === 1 ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] : null;
|
|
7
|
+
if (oneTouchData !== null) {
|
|
8
|
+
if (oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter) {
|
|
9
|
+
total += ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis ? oneTouchData.currentPageY : !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY;
|
|
10
|
+
count = 1;
|
|
11
|
+
}
|
|
12
|
+
} else {
|
|
13
|
+
for (var i = 0; i < touchBank.length; i++) {
|
|
14
|
+
var touchTrack = touchBank[i];
|
|
15
|
+
if (touchTrack !== null && touchTrack !== void 0 && touchTrack.touchActive && touchTrack.currentTimeStamp >= touchesChangedAfter) {
|
|
16
|
+
var toAdd = void 0;
|
|
17
|
+
if (ofCurrent && isXAxis) {
|
|
18
|
+
toAdd = touchTrack.currentPageX;
|
|
19
|
+
} else if (ofCurrent && !isXAxis) {
|
|
20
|
+
toAdd = touchTrack.currentPageY;
|
|
21
|
+
} else if (!ofCurrent && isXAxis) {
|
|
22
|
+
toAdd = touchTrack.previousPageX;
|
|
23
|
+
} else {
|
|
24
|
+
toAdd = touchTrack.previousPageY;
|
|
25
|
+
}
|
|
26
|
+
total += toAdd;
|
|
27
|
+
count++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return count > 0 ? total / count : -1;
|
|
32
|
+
}
|
|
33
|
+
function currentCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
34
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, true);
|
|
35
|
+
}
|
|
36
|
+
function currentCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
37
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, true);
|
|
38
|
+
}
|
|
39
|
+
function previousCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
40
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, false);
|
|
41
|
+
}
|
|
42
|
+
function previousCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {
|
|
43
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, false);
|
|
44
|
+
}
|
|
45
|
+
function currentCentroidX(touchHistory) {
|
|
46
|
+
return centroidDimension(touchHistory, 0, true, true);
|
|
47
|
+
}
|
|
48
|
+
function currentCentroidY(touchHistory) {
|
|
49
|
+
return centroidDimension(touchHistory, 0, false, true);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { currentCentroidX, currentCentroidXOfTouchesChangedAfter, currentCentroidY, currentCentroidYOfTouchesChangedAfter, noCentroid, previousCentroidXOfTouchesChangedAfter, previousCentroidYOfTouchesChangedAfter };
|
|
53
|
+
//# sourceMappingURL=TouchHistoryMath.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TouchHistoryMath.native.js","names":[],"sources":["esm/TouchHistoryMath.native.js"],"sourcesContent":["var noCentroid = -1;\nfunction centroidDimension(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) {\n var touchBank = touchHistory.touchBank;\n var total = 0;\n var count = 0;\n var oneTouchData = touchHistory.numberActiveTouches === 1 ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch] : null;\n if (oneTouchData !== null) {\n if (oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter) {\n total += ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis ? oneTouchData.currentPageY : !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY;\n count = 1;\n }\n } else {\n for (var i = 0; i < touchBank.length; i++) {\n var touchTrack = touchBank[i];\n if (touchTrack !== null && touchTrack !== void 0 && touchTrack.touchActive && touchTrack.currentTimeStamp >= touchesChangedAfter) {\n var toAdd = void 0;\n if (ofCurrent && isXAxis) {\n toAdd = touchTrack.currentPageX;\n } else if (ofCurrent && !isXAxis) {\n toAdd = touchTrack.currentPageY;\n } else if (!ofCurrent && isXAxis) {\n toAdd = touchTrack.previousPageX;\n } else {\n toAdd = touchTrack.previousPageY;\n }\n total += toAdd;\n count++;\n }\n }\n }\n return count > 0 ? total / count : noCentroid;\n}\nfunction currentCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {\n return centroidDimension(touchHistory, touchesChangedAfter, true, true);\n}\nfunction currentCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {\n return centroidDimension(touchHistory, touchesChangedAfter, false, true);\n}\nfunction previousCentroidXOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {\n return centroidDimension(touchHistory, touchesChangedAfter, true, false);\n}\nfunction previousCentroidYOfTouchesChangedAfter(touchHistory, touchesChangedAfter) {\n return centroidDimension(touchHistory, touchesChangedAfter, false, false);\n}\nfunction currentCentroidX(touchHistory) {\n return centroidDimension(touchHistory, 0, true, true);\n}\nfunction currentCentroidY(touchHistory) {\n return centroidDimension(touchHistory, 0, false, true);\n}\nexport {\n currentCentroidX,\n currentCentroidXOfTouchesChangedAfter,\n currentCentroidY,\n currentCentroidYOfTouchesChangedAfter,\n noCentroid,\n previousCentroidXOfTouchesChangedAfter,\n previousCentroidYOfTouchesChangedAfter\n};\n//# sourceMappingURL=TouchHistoryMath.js.map\n"],"mappings":";AAAA,IAAI,aAAa,CAAC;AAClB,SAAS,kBAAkB,cAAc,qBAAqB,SAAS,WAAW;CAChF,IAAI,YAAY,aAAa;CAC7B,IAAI,QAAQ;CACZ,IAAI,QAAQ;CACZ,IAAI,eAAe,aAAa,wBAAwB,IAAI,aAAa,UAAU,aAAa,4BAA4B;CAC5H,IAAI,iBAAiB,MAAM;EACzB,IAAI,aAAa,eAAe,aAAa,mBAAmB,qBAAqB;GACnF,SAAS,aAAa,UAAU,aAAa,eAAe,aAAa,CAAC,UAAU,aAAa,eAAe,CAAC,aAAa,UAAU,aAAa,gBAAgB,aAAa;GAClL,QAAQ;EACV;CACF,OAAO;EACL,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;GACzC,IAAI,aAAa,UAAU;GAC3B,IAAI,eAAe,QAAQ,eAAe,KAAK,KAAK,WAAW,eAAe,WAAW,oBAAoB,qBAAqB;IAChI,IAAI,QAAQ,KAAK;IACjB,IAAI,aAAa,SAAS;KACxB,QAAQ,WAAW;IACrB,OAAO,IAAI,aAAa,CAAC,SAAS;KAChC,QAAQ,WAAW;IACrB,OAAO,IAAI,CAAC,aAAa,SAAS;KAChC,QAAQ,WAAW;IACrB,OAAO;KACL,QAAQ,WAAW;IACrB;IACA,SAAS;IACT;GACF;EACF;CACF;CACA,OAAO,QAAQ,IAAI,QAAQ;AAC7B;AACA,SAAS,sCAAsC,cAAc,qBAAqB;CAChF,OAAO,kBAAkB,cAAc,qBAAqB,MAAM,IAAI;AACxE;AACA,SAAS,sCAAsC,cAAc,qBAAqB;CAChF,OAAO,kBAAkB,cAAc,qBAAqB,OAAO,IAAI;AACzE;AACA,SAAS,uCAAuC,cAAc,qBAAqB;CACjF,OAAO,kBAAkB,cAAc,qBAAqB,MAAM,KAAK;AACzE;AACA,SAAS,uCAAuC,cAAc,qBAAqB;CACjF,OAAO,kBAAkB,cAAc,qBAAqB,OAAO,KAAK;AAC1E;AACA,SAAS,iBAAiB,cAAc;CACtC,OAAO,kBAAkB,cAAc,GAAG,MAAM,IAAI;AACtD;AACA,SAAS,iBAAiB,cAAc;CACtC,OAAO,kBAAkB,cAAc,GAAG,OAAO,IAAI;AACvD"}
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,16 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/react-native-pan-responder",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Tamagui v3 package bootstrap",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/tamagui/tamagui.git"
|
|
8
|
-
},
|
|
3
|
+
"version": "3.0.0-beta.1097.1",
|
|
9
4
|
"license": "MIT",
|
|
10
5
|
"files": [
|
|
11
|
-
"
|
|
6
|
+
"src",
|
|
7
|
+
"types",
|
|
8
|
+
"dist"
|
|
12
9
|
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"main": "dist/cjs",
|
|
13
|
+
"module": "dist/esm",
|
|
14
|
+
"types": "./types/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./package.json": "./package.json",
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./types/index.d.ts",
|
|
19
|
+
"react-native": "./dist/esm/index.native.js",
|
|
20
|
+
"browser": "./dist/esm/index.mjs",
|
|
21
|
+
"module": "./dist/esm/index.mjs",
|
|
22
|
+
"import": "./dist/esm/index.mjs",
|
|
23
|
+
"require": "./dist/cjs/index.cjs",
|
|
24
|
+
"default": "./dist/esm/index.mjs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
13
27
|
"publishConfig": {
|
|
14
28
|
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tamagui-build",
|
|
32
|
+
"watch": "tamagui-build --watch",
|
|
33
|
+
"clean": "tamagui-build clean",
|
|
34
|
+
"clean:build": "tamagui-build clean:build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@tamagui/react-native-types": "3.0.0-beta.1097.1",
|
|
38
|
+
"@tamagui/react-native-use-responder-events": "3.0.0-beta.1097.1"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@tamagui/build": "3.0.0-beta.1097.1",
|
|
42
|
+
"react": "19.2.3"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": ">=19"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/tamagui/tamagui.git",
|
|
50
|
+
"directory": "code/core/react-native-pan-responder"
|
|
15
51
|
}
|
|
16
52
|
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ResponderEvent,
|
|
10
|
+
TouchHistory,
|
|
11
|
+
} from '@tamagui/react-native-use-responder-events'
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
PanResponderConfig,
|
|
15
|
+
PanResponderGestureState,
|
|
16
|
+
PanResponderHandlers,
|
|
17
|
+
PanResponderInstance,
|
|
18
|
+
} from './types'
|
|
19
|
+
import {
|
|
20
|
+
currentCentroidX,
|
|
21
|
+
currentCentroidXOfTouchesChangedAfter,
|
|
22
|
+
currentCentroidY,
|
|
23
|
+
currentCentroidYOfTouchesChangedAfter,
|
|
24
|
+
previousCentroidXOfTouchesChangedAfter,
|
|
25
|
+
previousCentroidYOfTouchesChangedAfter,
|
|
26
|
+
} from './TouchHistoryMath'
|
|
27
|
+
|
|
28
|
+
// react-native types the callbacks with its own synthetic event, which is what
|
|
29
|
+
// callers write against. the responder system hands us its own event, and the
|
|
30
|
+
// only field this reads off it is `touchHistory`.
|
|
31
|
+
type Handler = (event: ResponderEvent) => any
|
|
32
|
+
|
|
33
|
+
function initializeGestureState(gestureState: PanResponderGestureState) {
|
|
34
|
+
gestureState.moveX = 0
|
|
35
|
+
gestureState.moveY = 0
|
|
36
|
+
gestureState.x0 = 0
|
|
37
|
+
gestureState.y0 = 0
|
|
38
|
+
gestureState.dx = 0
|
|
39
|
+
gestureState.dy = 0
|
|
40
|
+
gestureState.vx = 0
|
|
41
|
+
gestureState.vy = 0
|
|
42
|
+
gestureState.numberActiveTouches = 0
|
|
43
|
+
gestureState._accountsForMovesUpTo = 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function updateGestureStateOnMove(
|
|
47
|
+
gestureState: PanResponderGestureState,
|
|
48
|
+
touchHistory: TouchHistory
|
|
49
|
+
) {
|
|
50
|
+
gestureState.numberActiveTouches = touchHistory.numberActiveTouches
|
|
51
|
+
gestureState.moveX = currentCentroidXOfTouchesChangedAfter(
|
|
52
|
+
touchHistory,
|
|
53
|
+
gestureState._accountsForMovesUpTo
|
|
54
|
+
)
|
|
55
|
+
gestureState.moveY = currentCentroidYOfTouchesChangedAfter(
|
|
56
|
+
touchHistory,
|
|
57
|
+
gestureState._accountsForMovesUpTo
|
|
58
|
+
)
|
|
59
|
+
const movedAfter = gestureState._accountsForMovesUpTo
|
|
60
|
+
const prevX = previousCentroidXOfTouchesChangedAfter(touchHistory, movedAfter)
|
|
61
|
+
const x = currentCentroidXOfTouchesChangedAfter(touchHistory, movedAfter)
|
|
62
|
+
const prevY = previousCentroidYOfTouchesChangedAfter(touchHistory, movedAfter)
|
|
63
|
+
const y = currentCentroidYOfTouchesChangedAfter(touchHistory, movedAfter)
|
|
64
|
+
const nextDX = gestureState.dx + (x - prevX)
|
|
65
|
+
const nextDY = gestureState.dy + (y - prevY)
|
|
66
|
+
|
|
67
|
+
const dt = touchHistory.mostRecentTimeStamp - gestureState._accountsForMovesUpTo
|
|
68
|
+
gestureState.vx = (nextDX - gestureState.dx) / dt
|
|
69
|
+
gestureState.vy = (nextDY - gestureState.dy) / dt
|
|
70
|
+
|
|
71
|
+
gestureState.dx = nextDX
|
|
72
|
+
gestureState.dy = nextDY
|
|
73
|
+
gestureState._accountsForMovesUpTo = touchHistory.mostRecentTimeStamp
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The same PanResponder react-native ships, over the responder system in
|
|
78
|
+
* `@tamagui/react-native-use-responder-events`, so a drag can be written once
|
|
79
|
+
* and behave the same on both platforms without the web build importing
|
|
80
|
+
* react-native.
|
|
81
|
+
*
|
|
82
|
+
* `create` returns `panHandlers`, which go straight into `useResponderEvents`,
|
|
83
|
+
* except `onClickCapture`: it is a plain React prop that swallows the click a
|
|
84
|
+
* finished drag would otherwise fire.
|
|
85
|
+
*/
|
|
86
|
+
export const PanResponder = {
|
|
87
|
+
create(config: PanResponderConfig): PanResponderInstance {
|
|
88
|
+
// a drag ends with a click the caller never wanted, so grant arms a
|
|
89
|
+
// suppressor and release disarms it a beat later
|
|
90
|
+
const clickState = {
|
|
91
|
+
shouldCancelClick: false,
|
|
92
|
+
timeout: undefined as ReturnType<typeof setTimeout> | undefined,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const gestureState: PanResponderGestureState = {
|
|
96
|
+
stateID: Math.random(),
|
|
97
|
+
moveX: 0,
|
|
98
|
+
moveY: 0,
|
|
99
|
+
x0: 0,
|
|
100
|
+
y0: 0,
|
|
101
|
+
dx: 0,
|
|
102
|
+
dy: 0,
|
|
103
|
+
vx: 0,
|
|
104
|
+
vy: 0,
|
|
105
|
+
numberActiveTouches: 0,
|
|
106
|
+
_accountsForMovesUpTo: 0,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const call = (
|
|
110
|
+
callback: ((event: any, gestureState: PanResponderGestureState) => any) | undefined,
|
|
111
|
+
event: ResponderEvent
|
|
112
|
+
) => callback?.(event, gestureState)
|
|
113
|
+
|
|
114
|
+
const panHandlers: Record<string, Handler> = {
|
|
115
|
+
onStartShouldSetResponder(event) {
|
|
116
|
+
return config.onStartShouldSetPanResponder == null
|
|
117
|
+
? false
|
|
118
|
+
: call(config.onStartShouldSetPanResponder, event)
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
onMoveShouldSetResponder(event) {
|
|
122
|
+
return config.onMoveShouldSetPanResponder == null
|
|
123
|
+
? false
|
|
124
|
+
: call(config.onMoveShouldSetPanResponder, event)
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
onStartShouldSetResponderCapture(event) {
|
|
128
|
+
if (event.nativeEvent.touches.length === 1) {
|
|
129
|
+
initializeGestureState(gestureState)
|
|
130
|
+
}
|
|
131
|
+
gestureState.numberActiveTouches = event.touchHistory.numberActiveTouches
|
|
132
|
+
return config.onStartShouldSetPanResponderCapture != null
|
|
133
|
+
? call(config.onStartShouldSetPanResponderCapture, event)
|
|
134
|
+
: false
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
onMoveShouldSetResponderCapture(event) {
|
|
138
|
+
const touchHistory = event.touchHistory
|
|
139
|
+
if (gestureState._accountsForMovesUpTo === touchHistory.mostRecentTimeStamp) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
updateGestureStateOnMove(gestureState, touchHistory)
|
|
143
|
+
return config.onMoveShouldSetPanResponderCapture
|
|
144
|
+
? call(config.onMoveShouldSetPanResponderCapture, event)
|
|
145
|
+
: false
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
onResponderGrant(event) {
|
|
149
|
+
clearTimeout(clickState.timeout)
|
|
150
|
+
clickState.shouldCancelClick = true
|
|
151
|
+
gestureState.x0 = currentCentroidX(event.touchHistory)
|
|
152
|
+
gestureState.y0 = currentCentroidY(event.touchHistory)
|
|
153
|
+
gestureState.dx = 0
|
|
154
|
+
gestureState.dy = 0
|
|
155
|
+
call(config.onPanResponderGrant, event)
|
|
156
|
+
return config.onShouldBlockNativeResponder == null
|
|
157
|
+
? true
|
|
158
|
+
: call(config.onShouldBlockNativeResponder, event)
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
onResponderReject(event) {
|
|
162
|
+
call(config.onPanResponderReject, event)
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
onResponderRelease(event) {
|
|
166
|
+
call(config.onPanResponderRelease, event)
|
|
167
|
+
allowClicksAgainSoon()
|
|
168
|
+
initializeGestureState(gestureState)
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
onResponderStart(event) {
|
|
172
|
+
gestureState.numberActiveTouches = event.touchHistory.numberActiveTouches
|
|
173
|
+
call(config.onPanResponderStart, event)
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
onResponderMove(event) {
|
|
177
|
+
const touchHistory = event.touchHistory
|
|
178
|
+
if (gestureState._accountsForMovesUpTo === touchHistory.mostRecentTimeStamp) {
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
updateGestureStateOnMove(gestureState, touchHistory)
|
|
182
|
+
call(config.onPanResponderMove, event)
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
onResponderEnd(event) {
|
|
186
|
+
gestureState.numberActiveTouches = event.touchHistory.numberActiveTouches
|
|
187
|
+
call(config.onPanResponderEnd, event)
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
onResponderTerminate(event) {
|
|
191
|
+
call(config.onPanResponderTerminate, event)
|
|
192
|
+
allowClicksAgainSoon()
|
|
193
|
+
initializeGestureState(gestureState)
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
onResponderTerminationRequest(event) {
|
|
197
|
+
return config.onPanResponderTerminationRequest == null
|
|
198
|
+
? true
|
|
199
|
+
: call(config.onPanResponderTerminationRequest, event)
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
onClickCapture(event: any) {
|
|
203
|
+
if (clickState.shouldCancelClick === true) {
|
|
204
|
+
event.stopPropagation()
|
|
205
|
+
event.preventDefault()
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function allowClicksAgainSoon() {
|
|
211
|
+
clickState.timeout = setTimeout(() => {
|
|
212
|
+
clickState.shouldCancelClick = false
|
|
213
|
+
}, 250)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return { panHandlers: panHandlers as unknown as PanResponderHandlers }
|
|
217
|
+
},
|
|
218
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TouchHistory } from '@tamagui/react-native-use-responder-events'
|
|
9
|
+
|
|
10
|
+
export const noCentroid = -1
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Centroid of the touches that moved after `touchesChangedAfter`, in one
|
|
14
|
+
* dimension. `ofCurrent` picks the current position over the previous one, so
|
|
15
|
+
* the two together give the delta a pan is built from.
|
|
16
|
+
*/
|
|
17
|
+
function centroidDimension(
|
|
18
|
+
touchHistory: TouchHistory,
|
|
19
|
+
touchesChangedAfter: number,
|
|
20
|
+
isXAxis: boolean,
|
|
21
|
+
ofCurrent: boolean
|
|
22
|
+
): number {
|
|
23
|
+
const touchBank = touchHistory.touchBank
|
|
24
|
+
let total = 0
|
|
25
|
+
let count = 0
|
|
26
|
+
|
|
27
|
+
const oneTouchData =
|
|
28
|
+
touchHistory.numberActiveTouches === 1
|
|
29
|
+
? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch]
|
|
30
|
+
: null
|
|
31
|
+
|
|
32
|
+
if (oneTouchData !== null) {
|
|
33
|
+
if (oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter) {
|
|
34
|
+
total +=
|
|
35
|
+
ofCurrent && isXAxis
|
|
36
|
+
? oneTouchData.currentPageX
|
|
37
|
+
: ofCurrent && !isXAxis
|
|
38
|
+
? oneTouchData.currentPageY
|
|
39
|
+
: !ofCurrent && isXAxis
|
|
40
|
+
? oneTouchData.previousPageX
|
|
41
|
+
: oneTouchData.previousPageY
|
|
42
|
+
count = 1
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
for (let i = 0; i < touchBank.length; i++) {
|
|
46
|
+
const touchTrack = touchBank[i]
|
|
47
|
+
if (
|
|
48
|
+
touchTrack !== null &&
|
|
49
|
+
touchTrack !== undefined &&
|
|
50
|
+
touchTrack.touchActive &&
|
|
51
|
+
touchTrack.currentTimeStamp >= touchesChangedAfter
|
|
52
|
+
) {
|
|
53
|
+
let toAdd: number
|
|
54
|
+
if (ofCurrent && isXAxis) {
|
|
55
|
+
toAdd = touchTrack.currentPageX
|
|
56
|
+
} else if (ofCurrent && !isXAxis) {
|
|
57
|
+
toAdd = touchTrack.currentPageY
|
|
58
|
+
} else if (!ofCurrent && isXAxis) {
|
|
59
|
+
toAdd = touchTrack.previousPageX
|
|
60
|
+
} else {
|
|
61
|
+
toAdd = touchTrack.previousPageY
|
|
62
|
+
}
|
|
63
|
+
total += toAdd
|
|
64
|
+
count++
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return count > 0 ? total / count : noCentroid
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function currentCentroidXOfTouchesChangedAfter(
|
|
73
|
+
touchHistory: TouchHistory,
|
|
74
|
+
touchesChangedAfter: number
|
|
75
|
+
): number {
|
|
76
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, true)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function currentCentroidYOfTouchesChangedAfter(
|
|
80
|
+
touchHistory: TouchHistory,
|
|
81
|
+
touchesChangedAfter: number
|
|
82
|
+
): number {
|
|
83
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, true)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function previousCentroidXOfTouchesChangedAfter(
|
|
87
|
+
touchHistory: TouchHistory,
|
|
88
|
+
touchesChangedAfter: number
|
|
89
|
+
): number {
|
|
90
|
+
return centroidDimension(touchHistory, touchesChangedAfter, true, false)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function previousCentroidYOfTouchesChangedAfter(
|
|
94
|
+
touchHistory: TouchHistory,
|
|
95
|
+
touchesChangedAfter: number
|
|
96
|
+
): number {
|
|
97
|
+
return centroidDimension(touchHistory, touchesChangedAfter, false, false)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function currentCentroidX(touchHistory: TouchHistory): number {
|
|
101
|
+
return centroidDimension(touchHistory, 0, true, true)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function currentCentroidY(touchHistory: TouchHistory): number {
|
|
105
|
+
return centroidDimension(touchHistory, 0, false, true)
|
|
106
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GestureResponderEvent,
|
|
3
|
+
PanResponderGestureState,
|
|
4
|
+
} from '@tamagui/react-native-types'
|
|
5
|
+
import type { ResponderConfig } from '@tamagui/react-native-use-responder-events'
|
|
6
|
+
|
|
7
|
+
export type { PanResponderGestureState }
|
|
8
|
+
|
|
9
|
+
type PanResponderCallback<T> = (
|
|
10
|
+
event: GestureResponderEvent,
|
|
11
|
+
gestureState: PanResponderGestureState
|
|
12
|
+
) => T
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The config react-native's `PanResponder.create` takes, so a caller can move
|
|
16
|
+
* between the two without rewriting a handler.
|
|
17
|
+
*/
|
|
18
|
+
export type PanResponderConfig = {
|
|
19
|
+
onMoveShouldSetPanResponder?: PanResponderCallback<boolean>
|
|
20
|
+
onMoveShouldSetPanResponderCapture?: PanResponderCallback<boolean>
|
|
21
|
+
onStartShouldSetPanResponder?: PanResponderCallback<boolean>
|
|
22
|
+
onStartShouldSetPanResponderCapture?: PanResponderCallback<boolean>
|
|
23
|
+
onPanResponderReject?: PanResponderCallback<void>
|
|
24
|
+
onPanResponderGrant?: PanResponderCallback<void>
|
|
25
|
+
onPanResponderStart?: PanResponderCallback<void>
|
|
26
|
+
onPanResponderEnd?: PanResponderCallback<void>
|
|
27
|
+
onPanResponderRelease?: PanResponderCallback<void>
|
|
28
|
+
onPanResponderMove?: PanResponderCallback<void>
|
|
29
|
+
onPanResponderTerminate?: PanResponderCallback<void>
|
|
30
|
+
onPanResponderTerminationRequest?: PanResponderCallback<boolean>
|
|
31
|
+
onShouldBlockNativeResponder?: PanResponderCallback<boolean>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Everything but `onClickCapture` goes into `useResponderEvents`; that one is a
|
|
36
|
+
* plain React prop on the element.
|
|
37
|
+
*/
|
|
38
|
+
export type PanResponderHandlers = ResponderConfig & {
|
|
39
|
+
onClickCapture: (event: any) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type PanResponderInstance = {
|
|
43
|
+
panHandlers: PanResponderHandlers
|
|
44
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { PanResponderConfig, PanResponderInstance } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* The same PanResponder react-native ships, over the responder system in
|
|
10
|
+
* `@tamagui/react-native-use-responder-events`, so a drag can be written once
|
|
11
|
+
* and behave the same on both platforms without the web build importing
|
|
12
|
+
* react-native.
|
|
13
|
+
*
|
|
14
|
+
* `create` returns `panHandlers`, which go straight into `useResponderEvents`,
|
|
15
|
+
* except `onClickCapture`: it is a plain React prop that swallows the click a
|
|
16
|
+
* finished drag would otherwise fire.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PanResponder: {
|
|
19
|
+
create(config: PanResponderConfig): PanResponderInstance;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=PanResponder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanResponder.d.ts","sourceRoot":"","sources":["../src/PanResponder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EACV,kBAAkB,EAGlB,oBAAoB,EACrB,MAAM,SAAS,CAAA;AA0DhB;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY;IACvB,MAAM,SAAS,kBAAkB,GAAG,oBAAoB;CAmIzD,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { TouchHistory } from '@tamagui/react-native-use-responder-events';
|
|
8
|
+
export declare const noCentroid = -1;
|
|
9
|
+
export declare function currentCentroidXOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
10
|
+
export declare function currentCentroidYOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
11
|
+
export declare function previousCentroidXOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
12
|
+
export declare function previousCentroidYOfTouchesChangedAfter(touchHistory: TouchHistory, touchesChangedAfter: number): number;
|
|
13
|
+
export declare function currentCentroidX(touchHistory: TouchHistory): number;
|
|
14
|
+
export declare function currentCentroidY(touchHistory: TouchHistory): number;
|
|
15
|
+
//# sourceMappingURL=TouchHistoryMath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TouchHistoryMath.d.ts","sourceRoot":"","sources":["../src/TouchHistoryMath.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAE9E,eAAO,MAAM,UAAU,KAAK,CAAA;AA8D5B,wBAAgB,qCAAqC,CACnD,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAER;AAED,wBAAgB,qCAAqC,CACnD,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAER;AAED,wBAAgB,sCAAsC,CACpD,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAER;AAED,wBAAgB,sCAAsC,CACpD,YAAY,EAAE,YAAY,EAC1B,mBAAmB,EAAE,MAAM,GAC1B,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAEnE;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAEnE"}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA"}
|
package/types/types.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { GestureResponderEvent, PanResponderGestureState } from '@tamagui/react-native-types';
|
|
2
|
+
import type { ResponderConfig } from '@tamagui/react-native-use-responder-events';
|
|
3
|
+
export type { PanResponderGestureState };
|
|
4
|
+
type PanResponderCallback<T> = (event: GestureResponderEvent, gestureState: PanResponderGestureState) => T;
|
|
5
|
+
/**
|
|
6
|
+
* The config react-native's `PanResponder.create` takes, so a caller can move
|
|
7
|
+
* between the two without rewriting a handler.
|
|
8
|
+
*/
|
|
9
|
+
export type PanResponderConfig = {
|
|
10
|
+
onMoveShouldSetPanResponder?: PanResponderCallback<boolean>;
|
|
11
|
+
onMoveShouldSetPanResponderCapture?: PanResponderCallback<boolean>;
|
|
12
|
+
onStartShouldSetPanResponder?: PanResponderCallback<boolean>;
|
|
13
|
+
onStartShouldSetPanResponderCapture?: PanResponderCallback<boolean>;
|
|
14
|
+
onPanResponderReject?: PanResponderCallback<void>;
|
|
15
|
+
onPanResponderGrant?: PanResponderCallback<void>;
|
|
16
|
+
onPanResponderStart?: PanResponderCallback<void>;
|
|
17
|
+
onPanResponderEnd?: PanResponderCallback<void>;
|
|
18
|
+
onPanResponderRelease?: PanResponderCallback<void>;
|
|
19
|
+
onPanResponderMove?: PanResponderCallback<void>;
|
|
20
|
+
onPanResponderTerminate?: PanResponderCallback<void>;
|
|
21
|
+
onPanResponderTerminationRequest?: PanResponderCallback<boolean>;
|
|
22
|
+
onShouldBlockNativeResponder?: PanResponderCallback<boolean>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Everything but `onClickCapture` goes into `useResponderEvents`; that one is a
|
|
26
|
+
* plain React prop on the element.
|
|
27
|
+
*/
|
|
28
|
+
export type PanResponderHandlers = ResponderConfig & {
|
|
29
|
+
onClickCapture: (event: any) => void;
|
|
30
|
+
};
|
|
31
|
+
export type PanResponderInstance = {
|
|
32
|
+
panHandlers: PanResponderHandlers;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,6BAA6B,CAAA;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAEjF,YAAY,EAAE,wBAAwB,EAAE,CAAA;AAExC,KAAK,oBAAoB,CAAC,CAAC,IAAI,CAC7B,KAAK,EAAE,qBAAqB,EAC5B,YAAY,EAAE,wBAAwB,KACnC,CAAC,CAAA;AAEN;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,2BAA2B,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC3D,kCAAkC,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAClE,4BAA4B,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC5D,mCAAmC,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACnE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IACjD,mBAAmB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAChD,mBAAmB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAChD,iBAAiB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAC9C,qBAAqB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAClD,kBAAkB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAC/C,uBAAuB,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAA;IACpD,gCAAgC,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAChE,4BAA4B,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;CAC7D,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG;IACnD,cAAc,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,oBAAoB,CAAA;CAClC,CAAA"}
|
package/README.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# @tamagui/react-native-pan-responder
|