react-native-skia-gesture 0.2.0 → 0.3.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/README.md +71 -20
- package/lib/commonjs/canvas/canvas.js +57 -56
- package/lib/commonjs/canvas/canvas.js.map +1 -1
- package/lib/commonjs/canvas/context.js +1 -1
- package/lib/commonjs/canvas/context.js.map +1 -1
- package/lib/commonjs/components/index.js +4 -4
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/hoc/with-touchable-handler.js +29 -34
- package/lib/commonjs/hoc/with-touchable-handler.js.map +1 -1
- package/lib/commonjs/hooks/use-gesture-handler.js +11 -5
- package/lib/commonjs/hooks/use-gesture-handler.js.map +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/get-circle-path.js +2 -0
- package/lib/commonjs/utils/get-circle-path.js.map +1 -1
- package/lib/commonjs/utils/get-rect-path.js +8 -5
- package/lib/commonjs/utils/get-rect-path.js.map +1 -1
- package/lib/commonjs/utils/unwrap-animated-value.js +7 -0
- package/lib/commonjs/utils/unwrap-animated-value.js.map +1 -1
- package/lib/module/canvas/canvas.js +59 -58
- package/lib/module/canvas/canvas.js.map +1 -1
- package/lib/module/canvas/context.js +1 -1
- package/lib/module/canvas/context.js.map +1 -1
- package/lib/module/components/index.js +4 -4
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/hoc/with-touchable-handler.js +28 -34
- package/lib/module/hoc/with-touchable-handler.js.map +1 -1
- package/lib/module/hooks/use-gesture-handler.js +11 -5
- package/lib/module/hooks/use-gesture-handler.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/get-circle-path.js +2 -0
- package/lib/module/utils/get-circle-path.js.map +1 -1
- package/lib/module/utils/get-rect-path.js +9 -6
- package/lib/module/utils/get-rect-path.js.map +1 -1
- package/lib/module/utils/unwrap-animated-value.js +7 -0
- package/lib/module/utils/unwrap-animated-value.js.map +1 -1
- package/lib/typescript/canvas/canvas.d.ts +6 -2
- package/lib/typescript/canvas/canvas.d.ts.map +1 -1
- package/lib/typescript/canvas/context.d.ts +6 -5
- package/lib/typescript/canvas/context.d.ts.map +1 -1
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/hoc/with-touchable-handler.d.ts +7 -9
- package/lib/typescript/hoc/with-touchable-handler.d.ts.map +1 -1
- package/lib/typescript/hooks/use-gesture-handler.d.ts +7 -8
- package/lib/typescript/hooks/use-gesture-handler.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/get-circle-path.d.ts.map +1 -1
- package/lib/typescript/utils/get-rect-path.d.ts.map +1 -1
- package/lib/typescript/utils/unwrap-animated-value.d.ts +2 -1
- package/lib/typescript/utils/unwrap-animated-value.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/canvas/canvas.tsx +96 -80
- package/src/canvas/context.tsx +19 -10
- package/src/components/index.ts +5 -4
- package/src/hoc/with-touchable-handler.tsx +40 -35
- package/src/hooks/use-gesture-handler.ts +25 -16
- package/src/index.ts +1 -1
- package/src/utils/get-circle-path.ts +1 -0
- package/src/utils/get-rect-path.ts +11 -6
- package/src/utils/unwrap-animated-value.ts +9 -1
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"with-touchable-handler.d.ts","sourceRoot":"","sources":["../../../src/hoc/with-touchable-handler.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,
|
1
|
+
{"version":3,"file":"with-touchable-handler.d.ts","sourceRoot":"","sources":["../../../src/hoc/with-touchable-handler.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,MAAM,EAEZ,MAAM,4BAA4B,CAAC;AAWpC,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,6BAA6B,EAC9B,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,CACP,SAAS,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,KAC9D,IAAI,CAAC;IACV,QAAQ,EAAE,CACR,SAAS,EAAE,kBAAkB,CAAC,6BAA6B,CAAC,KACzD,IAAI,CAAC;IACV,KAAK,EAAE,CACL,SAAS,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,KAC9D,IAAI,CAAC;IACV,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;CAC3C,CAAC;AAEF,KAAK,yBAAyB,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;AAEvE,eAAO,MAAM,WAAW,QAAS,MAAM,SAAS,GAAG,QAgBlD,CAAC;AAEF,QAAA,MAAM,oBAAoB,0DAC4B,WAAW,kBAC/C,MAAM,+IAyEvB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
@@ -1,14 +1,13 @@
|
|
1
|
-
import {
|
2
|
-
import type { TranslationInfo } from '../hoc';
|
1
|
+
import type { GestureStateChangeEvent, GestureUpdateEvent, PanGestureHandlerEventPayload } from 'react-native-gesture-handler';
|
3
2
|
type UseGestureHandlerParams<ContextType> = {
|
4
|
-
onStart?: (touchInfo:
|
5
|
-
onActive?: (
|
6
|
-
onEnd?: (
|
3
|
+
onStart?: (touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>, context: ContextType) => void;
|
4
|
+
onActive?: (touchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>, context: ContextType) => void;
|
5
|
+
onEnd?: (touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>, context: ContextType) => void;
|
7
6
|
};
|
8
7
|
declare const useGestureHandler: <ContextType>(gestureHandlers: UseGestureHandlerParams<ContextType>) => {
|
9
|
-
onStart: (touchInfo:
|
10
|
-
onActive: (extendedTouchInfo:
|
11
|
-
onEnd: (extendedTouchInfo:
|
8
|
+
onStart: (touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => void;
|
9
|
+
onActive: (extendedTouchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>) => void;
|
10
|
+
onEnd: (extendedTouchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => void;
|
12
11
|
};
|
13
12
|
export { useGestureHandler };
|
14
13
|
//# sourceMappingURL=use-gesture-handler.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"use-gesture-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-gesture-handler.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"use-gesture-handler.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-gesture-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,6BAA6B,EAC9B,MAAM,8BAA8B,CAAC;AAEtC,KAAK,uBAAuB,CAAC,WAAW,IAAI;IAC1C,OAAO,CAAC,EAAE,CACR,SAAS,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,EACjE,OAAO,EAAE,WAAW,KACjB,IAAI,CAAC;IACV,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,kBAAkB,CAAC,6BAA6B,CAAC,EAC5D,OAAO,EAAE,WAAW,KACjB,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,CACN,SAAS,EAAE,uBAAuB,CAAC,6BAA6B,CAAC,EACjE,OAAO,EAAE,WAAW,KACjB,IAAI,CAAC;CACX,CAAC;AAEF,QAAA,MAAM,iBAAiB;yBAQP,wBAAwB,6BAA6B,CAAC;kCAS9C,mBAAmB,6BAA6B,CAAC;+BAUhD,wBAAwB,6BAA6B,CAAC;CAc9E,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,cAAc,CAAC;AAC1C,cAAc,OAAO,CAAC;AACtB,cAAc,6BAA6B,CAAC;AAE5C,eAAe,SAAS,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"get-circle-path.d.ts","sourceRoot":"","sources":["../../../src/utils/get-circle-path.ts"],"names":[],"mappings":"AAEA,KAAK,mBAAmB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,eAAO,MAAM,aAAa,kBAAmB,mBAAmB,
|
1
|
+
{"version":3,"file":"get-circle-path.d.ts","sourceRoot":"","sources":["../../../src/utils/get-circle-path.ts"],"names":[],"mappings":"AAEA,KAAK,mBAAmB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,eAAO,MAAM,aAAa,kBAAmB,mBAAmB,gDAG/D,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"get-rect-path.d.ts","sourceRoot":"","sources":["../../../src/utils/get-rect-path.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"get-rect-path.d.ts","sourceRoot":"","sources":["../../../src/utils/get-rect-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAE/D,KAAK,iBAAiB,GAClB;IACE,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,QAAA,MAAM,WAAW,WAAY,iBAAiB,gDAc7C,CAAC;AAEF,KAAK,wBAAwB,GAAG,iBAAiB,GAAG;IAClD,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,QAAA,MAAM,kBAAkB,WAAY,wBAAwB,gDAgB3D,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC"}
|
@@ -1,9 +1,10 @@
|
|
1
1
|
import type { SkiaValue } from '@shopify/react-native-skia';
|
2
|
+
import type Animated from 'react-native-reanimated';
|
2
3
|
type SkiaValueWithSelector<T> = {
|
3
4
|
value: SkiaValue<T>;
|
4
5
|
selector: (v: T) => T;
|
5
6
|
};
|
6
|
-
declare const unwrapAnimatedValue: <T>(value: T | SkiaValue<T> | SkiaValueWithSelector<T>) => T;
|
7
|
+
declare const unwrapAnimatedValue: <T>(value: T | SkiaValue<T> | SkiaValueWithSelector<T> | Animated.SharedValue<T>) => T;
|
7
8
|
declare const unwrapAnimatedValueObject: <T>(value: Record<any, T | SkiaValue<T>>) => Record<any, T>;
|
8
9
|
export { unwrapAnimatedValue, unwrapAnimatedValueObject };
|
9
10
|
//# sourceMappingURL=unwrap-animated-value.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"unwrap-animated-value.d.ts","sourceRoot":"","sources":["../../../src/utils/unwrap-animated-value.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;
|
1
|
+
{"version":3,"file":"unwrap-animated-value.d.ts","sourceRoot":"","sources":["../../../src/utils/unwrap-animated-value.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAEpD,KAAK,qBAAqB,CAAC,CAAC,IAAI;IAC9B,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;CACvB,CAAC;AACF,QAAA,MAAM,mBAAmB,wFAmBxB,CAAC;AAEF,QAAA,MAAM,yBAAyB,6DAO9B,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-native-skia-gesture",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.1",
|
4
4
|
"description": "A detection system for React Native Skia components",
|
5
5
|
"main": "lib/commonjs/index",
|
6
6
|
"module": "lib/module/index",
|
@@ -55,7 +55,7 @@
|
|
55
55
|
"@evilmartians/lefthook": "^1.2.2",
|
56
56
|
"@react-native-community/eslint-config": "^3.0.2",
|
57
57
|
"@release-it/conventional-changelog": "^5.0.0",
|
58
|
-
"@shopify/react-native-skia": "0.1.
|
58
|
+
"@shopify/react-native-skia": "0.1.221",
|
59
59
|
"@types/jest": "^28.1.2",
|
60
60
|
"@types/react": "18.0.26",
|
61
61
|
"@types/react-native": "0.70.0",
|
@@ -70,6 +70,8 @@
|
|
70
70
|
"react": "18.1.0",
|
71
71
|
"react-native": "0.70.5",
|
72
72
|
"react-native-builder-bob": "^0.20.0",
|
73
|
+
"react-native-gesture-handler": "~2.14.0",
|
74
|
+
"react-native-reanimated": "~3.6.2",
|
73
75
|
"release-it": "^15.0.0",
|
74
76
|
"typescript": "^4.5.2"
|
75
77
|
},
|
@@ -81,9 +83,9 @@
|
|
81
83
|
"react-native": "*"
|
82
84
|
},
|
83
85
|
"engines": {
|
84
|
-
"node": ">=
|
86
|
+
"node": ">= 18.0.0"
|
85
87
|
},
|
86
|
-
"packageManager": "
|
88
|
+
"packageManager": "yarn@1.22.21",
|
87
89
|
"jest": {
|
88
90
|
"preset": "react-native",
|
89
91
|
"modulePathIgnorePatterns": [
|
package/src/canvas/canvas.tsx
CHANGED
@@ -1,92 +1,108 @@
|
|
1
|
+
import { Canvas as SkiaCanvas } from '@shopify/react-native-skia';
|
2
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
1
3
|
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
import React, { useEffect } from 'react';
|
4
|
+
Gesture,
|
5
|
+
GestureDetector,
|
6
|
+
PanGesture,
|
7
|
+
} from 'react-native-gesture-handler';
|
8
|
+
import Animated, { useSharedValue } from 'react-native-reanimated';
|
9
|
+
|
9
10
|
import {
|
10
11
|
TouchHandlerContext,
|
11
12
|
type TouchableHandlerContextType,
|
12
13
|
} from './context';
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
import type { CanvasProps } from '@shopify/react-native-skia';
|
16
|
+
|
17
|
+
type TouchableCanvasProps = CanvasProps & {
|
18
|
+
panGesture?: PanGesture;
|
19
|
+
};
|
20
|
+
|
21
|
+
const Canvas: React.FC<TouchableCanvasProps> = ({
|
22
|
+
children,
|
23
|
+
panGesture = Gesture.Pan(),
|
24
|
+
...props
|
25
|
+
}) => {
|
26
|
+
// Instead of value, provide a subscribe method and reload the refs
|
27
|
+
const touchableRefs: TouchableHandlerContextType = useMemo(() => {
|
28
|
+
return { value: {} };
|
29
|
+
}, []);
|
30
|
+
|
31
|
+
const activeKey = useSharedValue<string[]>([]);
|
32
|
+
|
33
|
+
const [loadedRefs, prepareLoadedRefs] = useState<
|
34
|
+
TouchableHandlerContextType['value']
|
35
|
+
>({});
|
36
|
+
|
37
|
+
setTimeout(() => {
|
38
|
+
prepareLoadedRefs(touchableRefs.value);
|
39
|
+
}, 1000);
|
40
|
+
|
41
|
+
const mainGesture = panGesture
|
42
|
+
.onBegin((event) => {
|
43
|
+
const keys = Object.keys(loadedRefs);
|
44
|
+
for (let i = 0; i < keys.length; i++) {
|
45
|
+
const key = keys[i] as string;
|
46
|
+
const touchableItem = loadedRefs[key];
|
47
|
+
const isPointInPath = touchableItem?.isPointInPath(event);
|
48
|
+
if (isPointInPath && touchableItem?.onStart) {
|
49
|
+
activeKey.value.push(`${key}__${event.handlerTag}`);
|
50
|
+
touchableItem.onStart?.(event);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
})
|
54
|
+
.onUpdate((event) => {
|
55
|
+
const activatedKey = activeKey.value.find((key) =>
|
56
|
+
key.includes(event.handlerTag.toString())
|
57
|
+
);
|
58
|
+
|
59
|
+
if (!activatedKey) {
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
const indexedKey = activatedKey.split('__')?.[0];
|
17
63
|
|
18
|
-
|
64
|
+
if (!indexedKey) {
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
const touchableItem = loadedRefs[indexedKey];
|
19
68
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
return;
|
40
|
-
}
|
41
|
-
const indexedKey = activatedKey.split('__')?.[0];
|
42
|
-
if (!indexedKey) {
|
43
|
-
return;
|
44
|
-
}
|
45
|
-
const touchableItem = touchableRefs.current[indexedKey];
|
46
|
-
return touchableItem?.onActive?.(event);
|
47
|
-
},
|
48
|
-
onEnd: (event) => {
|
49
|
-
const activatedKey = activeKey.current.find((key) =>
|
50
|
-
key.includes(event.id.toString())
|
51
|
-
);
|
52
|
-
if (!activatedKey) {
|
53
|
-
return;
|
54
|
-
}
|
55
|
-
const indexedKey = activatedKey.split('__')?.[0];
|
56
|
-
if (!indexedKey) {
|
57
|
-
return;
|
58
|
-
}
|
59
|
-
const touchableItem = touchableRefs.current[indexedKey];
|
60
|
-
activeKey.current = activeKey.current.filter(
|
61
|
-
(key) => !key.includes(event.id.toString())
|
62
|
-
);
|
63
|
-
return touchableItem?.onEnd?.(event);
|
64
|
-
},
|
65
|
-
},
|
66
|
-
[touchableRefs, activeKey]
|
67
|
-
);
|
69
|
+
return touchableItem?.onActive?.(event);
|
70
|
+
})
|
71
|
+
.onFinalize((event) => {
|
72
|
+
const activatedKey = activeKey.value.find((key) =>
|
73
|
+
key.includes(event.handlerTag.toString())
|
74
|
+
);
|
75
|
+
if (!activatedKey) {
|
76
|
+
return;
|
77
|
+
}
|
78
|
+
const indexedKey = activatedKey.split('__')?.[0];
|
79
|
+
if (!indexedKey) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
const touchableItem = loadedRefs[indexedKey];
|
83
|
+
activeKey.value = activeKey.value.filter(
|
84
|
+
(key) => !key.includes(event.handlerTag.toString())
|
85
|
+
);
|
86
|
+
return touchableItem?.onEnd?.(event as any);
|
87
|
+
});
|
68
88
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
89
|
+
useEffect(() => {
|
90
|
+
return () => {
|
91
|
+
touchableRefs.value = {};
|
92
|
+
};
|
93
|
+
}, [touchableRefs]);
|
74
94
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
{...props}
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
>
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
</SkiaCanvas>
|
88
|
-
);
|
89
|
-
}
|
90
|
-
);
|
95
|
+
return (
|
96
|
+
<GestureDetector gesture={mainGesture}>
|
97
|
+
<Animated.View>
|
98
|
+
<SkiaCanvas {...props}>
|
99
|
+
<TouchHandlerContext.Provider value={touchableRefs}>
|
100
|
+
{children}
|
101
|
+
</TouchHandlerContext.Provider>
|
102
|
+
</SkiaCanvas>
|
103
|
+
</Animated.View>
|
104
|
+
</GestureDetector>
|
105
|
+
);
|
106
|
+
};
|
91
107
|
|
92
108
|
export { Canvas };
|
package/src/canvas/context.tsx
CHANGED
@@ -1,23 +1,32 @@
|
|
1
|
-
import type {
|
2
|
-
ExtendedTouchInfo,
|
3
|
-
TouchInfo,
|
4
|
-
Vector,
|
5
|
-
} from '@shopify/react-native-skia';
|
6
1
|
import React, { useContext } from 'react';
|
7
2
|
|
3
|
+
import type { Vector } from '@shopify/react-native-skia';
|
4
|
+
import type {
|
5
|
+
GestureStateChangeEvent,
|
6
|
+
GestureUpdateEvent,
|
7
|
+
PanGestureHandlerEventPayload,
|
8
|
+
} from 'react-native-gesture-handler';
|
9
|
+
|
8
10
|
export type TouchableHandlerContextType = {
|
9
|
-
|
11
|
+
value: Record<
|
10
12
|
string,
|
11
13
|
{
|
12
|
-
onStart: (
|
13
|
-
|
14
|
-
|
14
|
+
onStart: (
|
15
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>
|
16
|
+
) => void;
|
17
|
+
onActive: (
|
18
|
+
touchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>
|
19
|
+
) => void;
|
20
|
+
onEnd: (
|
21
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>
|
22
|
+
) => void;
|
15
23
|
isPointInPath: (point: Vector) => boolean;
|
16
24
|
}
|
17
25
|
>;
|
18
26
|
};
|
27
|
+
|
19
28
|
const TouchHandlerContext = React.createContext<TouchableHandlerContextType>({
|
20
|
-
|
29
|
+
value: {},
|
21
30
|
});
|
22
31
|
|
23
32
|
const useTouchHandlerContext = () => {
|
package/src/components/index.ts
CHANGED
@@ -4,11 +4,12 @@ import {
|
|
4
4
|
Rect as SkiaRect,
|
5
5
|
Path as SkiaPath,
|
6
6
|
} from '@shopify/react-native-skia';
|
7
|
+
|
7
8
|
import { withTouchableHandler } from '../hoc';
|
8
9
|
|
9
10
|
export { Canvas } from '../canvas';
|
10
11
|
|
11
|
-
export const Circle = withTouchableHandler(SkiaCircle);
|
12
|
-
export const RoundedRect = withTouchableHandler(SkiaRoundedRect);
|
13
|
-
export const Rect = withTouchableHandler(SkiaRect);
|
14
|
-
export const Path = withTouchableHandler(SkiaPath);
|
12
|
+
export const Circle = withTouchableHandler(SkiaCircle, 'Circle');
|
13
|
+
export const RoundedRect = withTouchableHandler(SkiaRoundedRect, 'RoundedRect');
|
14
|
+
export const Rect = withTouchableHandler(SkiaRect, 'Rect');
|
15
|
+
export const Path = withTouchableHandler(SkiaPath, 'Path');
|
@@ -1,37 +1,43 @@
|
|
1
1
|
import {
|
2
|
-
type ExtendedTouchInfo,
|
3
2
|
type SkiaValue,
|
4
3
|
type SkPath,
|
5
|
-
type TouchInfo,
|
6
4
|
type Vector,
|
7
|
-
useValue,
|
8
5
|
} from '@shopify/react-native-skia';
|
9
6
|
import { useCallback, useEffect, useId } from 'react';
|
7
|
+
|
8
|
+
import { useTouchHandlerContext } from '../canvas/context';
|
10
9
|
import { getCirclePath } from '../utils/get-circle-path';
|
11
10
|
import { getRectPath, getRoundedRectPath } from '../utils/get-rect-path';
|
12
11
|
import {
|
13
12
|
unwrapAnimatedValue,
|
14
13
|
unwrapAnimatedValueObject,
|
15
14
|
} from '../utils/unwrap-animated-value';
|
16
|
-
import { useTouchHandlerContext } from '../canvas/context';
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
import type {
|
17
|
+
GestureStateChangeEvent,
|
18
|
+
GestureUpdateEvent,
|
19
|
+
PanGestureHandlerEventPayload,
|
20
|
+
} from 'react-native-gesture-handler';
|
22
21
|
|
23
22
|
export type TouchableHandlerProps = {
|
24
|
-
onStart: (
|
25
|
-
|
26
|
-
|
23
|
+
onStart: (
|
24
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>
|
25
|
+
) => void;
|
26
|
+
onActive: (
|
27
|
+
touchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>
|
28
|
+
) => void;
|
29
|
+
onEnd: (
|
30
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>
|
31
|
+
) => void;
|
27
32
|
touchablePath: SkPath | SkiaValue<SkPath>;
|
28
33
|
};
|
29
34
|
|
30
35
|
type WithTouchableHandlerProps<T> = T & Partial<TouchableHandlerProps>;
|
31
36
|
|
32
|
-
const getSkiaPath = (key: string, props: any) => {
|
33
|
-
|
37
|
+
export const getSkiaPath = (key: string, props: any) => {
|
38
|
+
'worklet';
|
34
39
|
|
40
|
+
const unwrappedProps = unwrapAnimatedValueObject(props) as any;
|
35
41
|
switch (key) {
|
36
42
|
case 'Circle':
|
37
43
|
return getCirclePath(unwrappedProps);
|
@@ -47,7 +53,8 @@ const getSkiaPath = (key: string, props: any) => {
|
|
47
53
|
};
|
48
54
|
|
49
55
|
const withTouchableHandler = <T,>(
|
50
|
-
Component: (props: WithTouchableHandlerProps<T>) => JSX.Element
|
56
|
+
Component: (props: WithTouchableHandlerProps<T>) => JSX.Element,
|
57
|
+
componentName?: string
|
51
58
|
) => {
|
52
59
|
return ({
|
53
60
|
onStart: onStartProp,
|
@@ -59,42 +66,37 @@ const withTouchableHandler = <T,>(
|
|
59
66
|
const id = useId();
|
60
67
|
const ref = useTouchHandlerContext();
|
61
68
|
|
62
|
-
const startingPoint = useValue<Vector | null>(null);
|
63
|
-
|
64
69
|
const onStart: TouchableHandlerProps['onStart'] = useCallback(
|
65
70
|
(event) => {
|
66
|
-
|
71
|
+
'worklet';
|
67
72
|
return onStartProp?.(event);
|
68
73
|
},
|
69
|
-
[onStartProp
|
74
|
+
[onStartProp]
|
70
75
|
);
|
71
76
|
const onActive: TouchableHandlerProps['onActive'] = useCallback(
|
72
77
|
(event) => {
|
73
|
-
|
74
|
-
|
75
|
-
return onActiveProp?.({
|
76
|
-
...event,
|
77
|
-
translationX,
|
78
|
-
translationY,
|
79
|
-
});
|
78
|
+
'worklet';
|
79
|
+
return onActiveProp?.(event);
|
80
80
|
},
|
81
|
-
[onActiveProp
|
81
|
+
[onActiveProp]
|
82
82
|
);
|
83
83
|
const onEnd: TouchableHandlerProps['onEnd'] = useCallback(
|
84
84
|
(event) => {
|
85
|
-
|
86
|
-
|
87
|
-
return onEndProp?.({ ...event, translationX, translationY });
|
85
|
+
'worklet';
|
86
|
+
return onEndProp?.(event);
|
88
87
|
},
|
89
|
-
[onEndProp
|
88
|
+
[onEndProp]
|
90
89
|
);
|
91
90
|
|
92
91
|
const isPointInPath = useCallback(
|
93
92
|
(point: Vector) => {
|
93
|
+
'worklet';
|
94
94
|
if (touchablePath) {
|
95
95
|
return unwrapAnimatedValue(touchablePath).contains(point.x, point.y);
|
96
96
|
}
|
97
|
-
|
97
|
+
|
98
|
+
if (!componentName) return false;
|
99
|
+
const path = getSkiaPath(componentName, props);
|
98
100
|
|
99
101
|
if (!path) {
|
100
102
|
throw Error('No touchablePath provided');
|
@@ -105,20 +107,23 @@ const withTouchableHandler = <T,>(
|
|
105
107
|
);
|
106
108
|
|
107
109
|
useEffect(() => {
|
108
|
-
ref.
|
110
|
+
ref.value = {
|
109
111
|
[`id:${id}`]: {
|
110
112
|
isPointInPath,
|
111
113
|
onStart,
|
112
114
|
onActive,
|
113
115
|
onEnd,
|
114
116
|
},
|
115
|
-
...ref.
|
117
|
+
...ref.value,
|
116
118
|
} as any;
|
119
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
120
|
+
}, [id, isPointInPath, onActive, onEnd, onStart]);
|
117
121
|
|
122
|
+
useEffect(() => {
|
118
123
|
return () => {
|
119
|
-
delete ref.
|
124
|
+
delete ref.value?.[`id:${id}`];
|
120
125
|
};
|
121
|
-
}, [id,
|
126
|
+
}, [id, props, ref, touchablePath]);
|
122
127
|
|
123
128
|
return Component(props as any);
|
124
129
|
};
|
@@ -1,19 +1,23 @@
|
|
1
|
-
import {
|
2
|
-
type ExtendedTouchInfo,
|
3
|
-
type TouchInfo,
|
4
|
-
useValue,
|
5
|
-
} from '@shopify/react-native-skia';
|
6
1
|
import { useCallback } from 'react';
|
7
|
-
import
|
2
|
+
import { useSharedValue } from 'react-native-reanimated';
|
3
|
+
|
4
|
+
import type {
|
5
|
+
GestureStateChangeEvent,
|
6
|
+
GestureUpdateEvent,
|
7
|
+
PanGestureHandlerEventPayload,
|
8
|
+
} from 'react-native-gesture-handler';
|
8
9
|
|
9
10
|
type UseGestureHandlerParams<ContextType> = {
|
10
|
-
onStart?: (
|
11
|
+
onStart?: (
|
12
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>,
|
13
|
+
context: ContextType
|
14
|
+
) => void;
|
11
15
|
onActive?: (
|
12
|
-
|
16
|
+
touchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>,
|
13
17
|
context: ContextType
|
14
18
|
) => void;
|
15
19
|
onEnd?: (
|
16
|
-
|
20
|
+
touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>,
|
17
21
|
context: ContextType
|
18
22
|
) => void;
|
19
23
|
};
|
@@ -23,28 +27,33 @@ const useGestureHandler = <ContextType>(
|
|
23
27
|
) => {
|
24
28
|
const { onStart, onActive, onEnd } = gestureHandlers;
|
25
29
|
|
26
|
-
const context =
|
30
|
+
const context = useSharedValue<ContextType>({} as any);
|
27
31
|
|
28
32
|
const handleStart = useCallback(
|
29
|
-
(touchInfo:
|
33
|
+
(touchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => {
|
34
|
+
'worklet';
|
30
35
|
if (!onStart) return;
|
31
|
-
return onStart(touchInfo, context.
|
36
|
+
return onStart(touchInfo, context.value);
|
32
37
|
},
|
33
38
|
[context, onStart]
|
34
39
|
);
|
35
40
|
|
36
41
|
const handleActive = useCallback(
|
37
|
-
(extendedTouchInfo:
|
42
|
+
(extendedTouchInfo: GestureUpdateEvent<PanGestureHandlerEventPayload>) => {
|
43
|
+
'worklet';
|
38
44
|
if (!onActive) return;
|
39
|
-
return onActive(extendedTouchInfo, context.
|
45
|
+
return onActive(extendedTouchInfo, context.value);
|
40
46
|
},
|
41
47
|
[context, onActive]
|
42
48
|
);
|
43
49
|
|
44
50
|
const handleEnd = useCallback(
|
45
|
-
(
|
51
|
+
(
|
52
|
+
extendedTouchInfo: GestureStateChangeEvent<PanGestureHandlerEventPayload>
|
53
|
+
) => {
|
54
|
+
'worklet';
|
46
55
|
if (!onEnd) return;
|
47
|
-
return onEnd(extendedTouchInfo, context.
|
56
|
+
return onEnd(extendedTouchInfo, context.value);
|
48
57
|
},
|
49
58
|
[context, onEnd]
|
50
59
|
);
|
package/src/index.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { Skia, type SkRect } from '@shopify/react-native-skia';
|
2
2
|
|
3
3
|
type GetRectPathParams =
|
4
4
|
| {
|
@@ -10,16 +10,18 @@ type GetRectPathParams =
|
|
10
10
|
| { rect: SkRect };
|
11
11
|
|
12
12
|
const getRectPath = (params: GetRectPathParams) => {
|
13
|
+
'worklet';
|
14
|
+
|
13
15
|
const skPath = Skia.Path.Make();
|
14
16
|
if ('rect' in params) {
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
16
17
|
const { rect } = params;
|
17
18
|
|
18
19
|
skPath.addRect(rect);
|
19
20
|
return skPath;
|
20
21
|
}
|
21
22
|
const { x, y, width, height } = params;
|
22
|
-
|
23
|
+
|
24
|
+
skPath.addRect(Skia.XYWHRect(x, y, width, height));
|
23
25
|
return skPath;
|
24
26
|
};
|
25
27
|
|
@@ -28,17 +30,20 @@ type GetRoundedRectPathParams = GetRectPathParams & {
|
|
28
30
|
};
|
29
31
|
|
30
32
|
const getRoundedRectPath = (params: GetRoundedRectPathParams) => {
|
33
|
+
'worklet';
|
34
|
+
|
31
35
|
const { r } = params;
|
32
36
|
const skPath = Skia.Path.Make();
|
33
37
|
if ('rect' in params) {
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
35
38
|
const { rect } = params;
|
36
|
-
|
39
|
+
|
40
|
+
skPath.addRRect(Skia.RRectXY(rect, r, r));
|
37
41
|
return skPath;
|
38
42
|
}
|
39
43
|
const { x, y, width, height } = params;
|
40
44
|
|
41
|
-
|
45
|
+
const roundedRect = Skia.RRectXY(Skia.XYWHRect(x, y, width, height), r, r);
|
46
|
+
skPath.addRRect(roundedRect);
|
42
47
|
return skPath;
|
43
48
|
};
|
44
49
|
|