@rick427/react-native-liveness 0.2.0 → 0.2.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 CHANGED
@@ -16,10 +16,13 @@ The library scores each camera frame against a set of liveness signals (face siz
16
16
 
17
17
  - Real-time passive liveness detection (no gestures required)
18
18
  - On-device ML — works fully offline (ML Kit)
19
- - Face guide oval with live feedback hints
20
- - Animated countdown (React Native built-in `Animated`)
19
+ - Circle guide with animated scanner — sweeping scan line, rotating corner brackets, confidence progress arc
20
+ - Score-driven border colour: white yellow → green
21
+ - Built-in modal via `LivenessCameraModal` — one import, zero wiring
22
+ - Configurable animation type, close button style, and font
21
23
  - Auto photo capture via Vision Camera's `takePhoto()`
22
- - Optional shutter sound
24
+ - 60 fps preview, ML Kit capped at 20 fps via `runAtTargetFps`
25
+ - Optional shutter sound (respects silent mode)
23
26
  - Fully typed TypeScript API
24
27
 
25
28
  ---
@@ -41,29 +44,30 @@ Install these if you don't already have them:
41
44
  | `react-native-vision-camera` | `>= 4.0.0` |
42
45
  | `react-native-svg` | `>= 13.0.0` |
43
46
  | `react-native-worklets-core` | `>= 1.0.0` |
47
+ | `react-native-reanimated` | `>= 4.0.0` |
44
48
 
45
49
  ```sh
46
- npm install react-native-vision-camera react-native-svg react-native-worklets-core
50
+ npm install react-native-vision-camera react-native-svg react-native-worklets-core react-native-reanimated
47
51
  ```
48
52
 
49
53
  ### Configure worklets Babel plugin
50
54
 
51
- The library uses Vision Camera frame processors which run in a worklet context. Add the appropriate plugin to your `babel.config.js` depending on which package you have installed:
55
+ The library uses Vision Camera frame processors which run in a worklet context. Add the appropriate plugin to your `babel.config.js`:
52
56
 
53
57
  ```js
54
58
  // babel.config.js
55
59
  module.exports = {
56
60
  presets: ['module:@react-native/babel-preset'], // or 'babel-preset-expo'
57
61
  plugins: [
58
- ['react-native-worklets-core/plugin'], // if using react-native-worklets-core
59
- // ['react-native-worklets/plugin'], // if using react-native-worklets
62
+ 'react-native-worklets-core/plugin', // frame processor worklets
63
+ 'react-native-reanimated/plugin', // SVG animations (must come last)
60
64
  ],
61
65
  };
62
66
  ```
63
67
 
64
- > **Already have worklets configured?** Just confirm the relevant plugin line is present — no further changes needed.
68
+ > **Already have both plugins?** Just confirm both lines are present — order matters, Reanimated must come after worklets-core.
65
69
 
66
- After updating the Babel config, clear the Metro cache:
70
+ After updating Babel config, clear the Metro cache:
67
71
 
68
72
  ```sh
69
73
  npx react-native start --reset-cache
@@ -86,22 +90,84 @@ Add `NSCameraUsageDescription` to your `Info.plist`:
86
90
 
87
91
  ### Android
88
92
 
89
- The ML Kit dependency is included in `build.gradle` automatically. No extra steps needed.
93
+ ML Kit and all native dependencies are included automatically via `build.gradle`. No extra steps needed.
90
94
 
91
95
  ---
92
96
 
93
97
  ## Usage
94
98
 
95
- ### Drop-in component
99
+ There are two ways to use the library depending on how much control you need.
100
+
101
+ ---
102
+
103
+ ### Option 1 — `LivenessCameraModal` (recommended)
104
+
105
+ The easiest integration. Pass `visible` / `onClose` and you're done — the modal, close button, and full-screen layout are all handled for you.
96
106
 
97
107
  ```tsx
98
- import { LivenessCamera } from '@rick427/react-native-liveness';
108
+ import { useState } from 'react';
109
+ import { LivenessCameraModal } from '@rick427/react-native-liveness';
99
110
  import type { CaptureResult } from '@rick427/react-native-liveness';
100
111
 
101
112
  export default function VerificationScreen() {
113
+ const [showLiveness, setShowLiveness] = useState(false);
114
+
102
115
  const handleCapture = (result: CaptureResult) => {
103
116
  console.log('Photo path:', result.photo.path);
104
117
  console.log('Liveness score:', result.livenessScore); // 0.0 – 1.0
118
+ setShowLiveness(false);
119
+ };
120
+
121
+ return (
122
+ <>
123
+ {/* Trigger however you like */}
124
+ <Button title="Verify Identity" onPress={() => setShowLiveness(true)} />
125
+
126
+ <LivenessCameraModal
127
+ visible={showLiveness}
128
+ onClose={() => setShowLiveness(false)}
129
+ onCapture={handleCapture}
130
+ onLivenessConfirmed={() => console.log('Live face confirmed!')}
131
+ onError={(err) => console.error(err)}
132
+ />
133
+ </>
134
+ );
135
+ }
136
+ ```
137
+
138
+ #### `LivenessCameraModal` props
139
+
140
+ | Prop | Type | Default | Description |
141
+ |---|---|---|---|
142
+ | `visible` | `boolean` | **required** | Controls modal visibility. |
143
+ | `onClose` | `() => void` | **required** | Called when the × button is pressed or Android back is fired. |
144
+ | `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is captured. |
145
+ | `animationType` | `'slide' \| 'fade' \| 'none'` | `'slide'` | Modal entrance/exit animation. |
146
+ | `closeButtonStyle` | `ViewStyle` | — | Override the close button container style (position, size, colours). |
147
+ | `closeButtonIconColor` | `string` | `'#fff'` | Colour of the × icon. |
148
+ | `closeButtonIconSize` | `number` | `18` | Size of the × icon in dp. |
149
+ | `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before countdown. |
150
+ | `onError` | `(err: Error) => void` | — | Fired on unrecoverable errors. |
151
+ | `countdownFrom` | `number` | `3` | Countdown start value. |
152
+ | `livenessThreshold` | `number` | `0.75` | Score (0–1) required to confirm liveness. |
153
+ | `confirmFrames` | `number` | `10` | Consecutive high-score frames required (~500 ms at 20 fps). |
154
+ | `soundEnabled` | `boolean` | `true` | Play native shutter sound on capture. |
155
+ | `fontFamily` | `string` | `'Baloo-Medium'` | Font applied to all text inside the component. |
156
+
157
+ ---
158
+
159
+ ### Option 2 — `LivenessCamera` (embedded)
160
+
161
+ Use this when you want full layout control — embed the camera directly inside your own screen or custom modal.
162
+
163
+ ```tsx
164
+ import { LivenessCamera } from '@rick427/react-native-liveness';
165
+ import type { CaptureResult } from '@rick427/react-native-liveness';
166
+
167
+ export default function VerificationScreen() {
168
+ const handleCapture = (result: CaptureResult) => {
169
+ console.log('Photo path:', result.photo.path);
170
+ console.log('Liveness score:', result.livenessScore);
105
171
  };
106
172
 
107
173
  return (
@@ -115,20 +181,23 @@ export default function VerificationScreen() {
115
181
  }
116
182
  ```
117
183
 
118
- ### Props
184
+ #### `LivenessCamera` props
119
185
 
120
186
  | Prop | Type | Default | Description |
121
187
  |---|---|---|---|
122
- | `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is taken. |
123
- | `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before the countdown. |
188
+ | `onCapture` | `(result: CaptureResult) => void` | **required** | Fired after photo is captured. |
189
+ | `onLivenessConfirmed` | `() => void` | — | Fired the moment liveness is confirmed, before countdown. |
124
190
  | `onError` | `(err: Error) => void` | — | Fired on unrecoverable errors. |
125
191
  | `countdownFrom` | `number` | `3` | Countdown start value. |
126
- | `livenessThreshold` | `number` | `0.75` | Score (0–1) required per frame to be considered live. |
127
- | `confirmFrames` | `number` | `15` | Consecutive high-score frames required (~500 ms at 30 fps). |
128
- | `soundEnabled` | `boolean` | `true` | Play the native system shutter sound on capture. Respects silent mode. |
192
+ | `livenessThreshold` | `number` | `0.75` | Score (0–1) required to confirm liveness. |
193
+ | `confirmFrames` | `number` | `10` | Consecutive high-score frames required (~500 ms at 20 fps). |
194
+ | `soundEnabled` | `boolean` | `true` | Play native shutter sound on capture. |
195
+ | `fontFamily` | `string` | `'Baloo-Medium'` | Font applied to all text inside the component. |
129
196
  | `style` | `ViewStyle` | — | Style for the root container. |
130
197
 
131
- ### CaptureResult
198
+ ---
199
+
200
+ ### `CaptureResult`
132
201
 
133
202
  ```ts
134
203
  type CaptureResult = {
@@ -140,34 +209,48 @@ type CaptureResult = {
140
209
 
141
210
  ---
142
211
 
212
+ ## Scanner animation
213
+
214
+ The circle guide layers three animations built entirely with `Animated` + `react-native-svg` — no extra dependencies.
215
+
216
+ | Layer | Behaviour |
217
+ |---|---|
218
+ | **Dim base ring** | Always visible; gives a positioning target before any progress starts. |
219
+ | **Sweep scan line** | A gradient bar ping-pongs top → bottom inside the circle (1.8 s/leg). Fades out on confirm. |
220
+ | **Rotating brackets** | Four corner arcs rotate slowly (1 rev / 6 s), suggesting the circle boundary during scanning. Freeze in place on confirm. |
221
+ | **Progress arc** | The circle border draws itself in clockwise from 12 o'clock as `livenessScore / livenessThreshold` builds. White → yellow → green. |
222
+
223
+ ---
224
+
143
225
  ## How liveness scoring works
144
226
 
145
- Each camera frame is scored across four signals:
227
+ Each camera frame is scored across four signals at up to **20 fps** (ML Kit is throttled via `runAtTargetFps` while the preview renders at 60 fps):
146
228
 
147
229
  | Signal | Weight | Detail |
148
230
  |---|---|---|
149
- | Face detected | 20% | ML Kit found a face in the frame |
150
- | Face size | 20% | Face width is 20%–65% of the frame (not too far, not too close) |
151
- | Head pose | 30% | Yaw < ±20° and pitch < ±20° from frontal |
152
- | Eyes open | 30% | Average of left/right eye open probability from ML Kit |
231
+ | Face detected | 20% | ML Kit found a face in the frame. |
232
+ | Face size | 20% | Face width is 15–80% of the frame. Soft-edge scoring at boundaries. |
233
+ | Head pose | 30% | Yaw < ±25° and pitch < ±25° from frontal. Soft decay outside range. |
234
+ | Eyes open | 30% | Average of left/right eye open probability from ML Kit. |
153
235
 
154
- A rolling window of the last 20 frame scores is maintained. Liveness is confirmed once `confirmFrames` consecutive frames all score above `livenessThreshold`.
236
+ A rolling window of the last 20 frame scores is maintained. Liveness is confirmed once `confirmFrames` consecutive frames all score above `livenessThreshold`. Bad frames **decay** the streak by 2 instead of resetting it, making detection resilient to momentary noise.
155
237
 
156
238
  ---
157
239
 
158
240
  ## Architecture
159
241
 
160
242
  ```
161
- Camera frame (30fps)
243
+ Camera (60 fps preview)
162
244
  ↓ [worklet thread — Vision Camera frame processor]
163
- Native plugin (Swift / Kotlin)
164
- → ML Kit Face Detection
165
- → { bounds, yawAngle, pitchAngle, leftEyeOpenProbability, … }
166
- ↓ [runOnJS → JS thread]
245
+ runAtTargetFps(20) → Native plugin (Swift / Kotlin)
246
+ → ML Kit Face Detection
247
+ → { bounds, yawAngle, pitchAngle, leftEyeOpenProbability, … }
248
+ ↓ [Worklets.createRunOnJS → JS thread, ~20×/sec]
167
249
  useLivenessCamera hook
168
- → scoreFrame() per frame
250
+ → scoreFrame() soft-edge signals, weighted sum
169
251
  → rolling 20-frame window
170
- 15 consecutive frames > threshold liveness confirmed
252
+ consecutiveGood++ on pass, decay -2 on fail
253
+ → 10 consecutive frames > threshold → liveness confirmed
171
254
 
172
255
  Countdown 3 → 2 → 1 (React Native Animated)
173
256
 
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
 
3
3
  import { useCallback, useEffect, useRef, useState } from 'react';
4
- import { Animated, Easing, StyleSheet, Text, View } from 'react-native';
4
+ import { Animated as RNAnimated, StyleSheet, Text, View } from 'react-native';
5
+ import Animated, { cancelAnimation, Easing, useAnimatedProps, useSharedValue, withRepeat, withSequence, withTiming } from 'react-native-reanimated';
5
6
  import { Camera, useCameraDevice, useCameraFormat, useCameraPermission } from 'react-native-vision-camera';
6
7
  import { Circle, ClipPath, Defs, G, LinearGradient, Path, Rect, Stop, Svg } from 'react-native-svg';
7
8
  import { useLivenessCamera } from "./useLivenessCamera.js";
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
- // ─── Animated SVG components ─────────────────────────────────────────────────
10
- // Created once at module level so React never recreates the component class.
10
+ // ─── Animated SVG components (Reanimated) ────────────────────────────────────
11
+ // createAnimatedComponent from react-native-reanimated properly drives SVG
12
+ // presentation attributes (strokeDashoffset, y, rotation) on the UI thread.
11
13
  const AnimatedCircle = Animated.createAnimatedComponent(Circle);
12
14
  const AnimatedG = Animated.createAnimatedComponent(G);
13
15
  const AnimatedRect = Animated.createAnimatedComponent(Rect);
@@ -61,6 +63,21 @@ function bracketArcPath(cx, cy, r, centerDeg, spanDeg) {
61
63
  }
62
64
 
63
65
  // ─── CircleOverlay ────────────────────────────────────────────────────────────
66
+ const _worklet_15111972513221_init_data = {
67
+ code: "function LivenessCameraTsx1(){const{cy,r,scanProgress,SCAN_LINE_HEIGHT,scanOpacity}=this.__closure;return{y:cy-r+2+scanProgress.value*(2*r-SCAN_LINE_HEIGHT-4),opacity:scanOpacity.value};}",
68
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
69
+ sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx1\",\"cy\",\"r\",\"scanProgress\",\"SCAN_LINE_HEIGHT\",\"scanOpacity\",\"__closure\",\"y\",\"value\",\"opacity\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AAmII,SAAAA,mBAAA,QAAAC,EAAA,CAAAC,CAAA,CAAAC,YAAA,CAAAC,gBAAA,CAAAC,WAAA,OAAAC,SAAA,OAAO,CAELC,CAAC,CAAEN,EAAE,CAAGC,CAAC,CAAG,CAAC,CAAGC,YAAY,CAACK,KAAK,EAAI,CAAC,CAAGN,CAAC,CAAGE,gBAAgB,CAAG,CAAC,CAAC,CACnEK,OAAO,CAAEJ,WAAW,CAACG,KACvB,CAAC\",\"ignoreList\":[]}"
70
+ };
71
+ const _worklet_14693916078586_init_data = {
72
+ code: "function LivenessCameraTsx2(){const{bracketRot,cx,cy}=this.__closure;return{rotation:bracketRot.value%360,originX:cx,originY:cy};}",
73
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
74
+ sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx2\",\"bracketRot\",\"cx\",\"cy\",\"__closure\",\"rotation\",\"value\",\"originX\",\"originY\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AA4II,SAAAA,mBAAA,QAAAC,UAAA,CAAAC,EAAA,CAAAC,EAAA,OAAAC,SAAA,OAAO,CAELC,QAAQ,CAAEJ,UAAU,CAACK,KAAK,CAAG,GAAG,CAChCC,OAAO,CAAEL,EAAE,CACXM,OAAO,CAAEL,EACX,CAAC\",\"ignoreList\":[]}"
75
+ };
76
+ const _worklet_1688522500078_init_data = {
77
+ code: "function LivenessCameraTsx3(){const{circumference,livenessProgress,livenessThreshold}=this.__closure;return{strokeDashoffset:circumference-livenessProgress.value/livenessThreshold*circumference};}",
78
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx",
79
+ sourceMap: "{\"version\":3,\"names\":[\"LivenessCameraTsx3\",\"circumference\",\"livenessProgress\",\"livenessThreshold\",\"__closure\",\"strokeDashoffset\",\"value\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessCamera.tsx\"],\"mappings\":\"AAsJI,SAAAA,mBAAA,QAAAC,aAAA,CAAAC,gBAAA,CAAAC,iBAAA,OAAAC,SAAA,OAAO,CACLC,gBAAgB,CACdJ,aAAa,CACZC,gBAAgB,CAACI,KAAK,CAAGH,iBAAiB,CAAIF,aACnD,CAAC\",\"ignoreList\":[]}"
80
+ };
64
81
  function CircleOverlay({
65
82
  width,
66
83
  height,
@@ -68,99 +85,156 @@ function CircleOverlay({
68
85
  score,
69
86
  livenessThreshold
70
87
  }) {
71
- // ── Animation values (must be declared before any early return) ────────────
72
- const scanAnim = useRef(new Animated.Value(0)).current;
73
- const scanOpacity = useRef(new Animated.Value(1)).current;
74
- const progressAnim = useRef(new Animated.Value(0)).current;
75
- const bracketAnim = useRef(new Animated.Value(0)).current;
76
- const scanLoopRef = useRef(null);
77
- const bracketLoopRef = useRef(null);
88
+ // ── Shared values all hooks before any early return ─────────────────────
89
+ // scanProgress 0=top 1=bottom, ping-pongs continuously
90
+ const scanProgress = useSharedValue(0);
91
+ const scanOpacity = useSharedValue(1);
92
+ // bracketRot drives the slow bracket rotation in degrees
93
+ const bracketRot = useSharedValue(0);
94
+ // livenessProgress tracks smoothed score for the arc
95
+ const livenessProgress = useSharedValue(0);
96
+
97
+ // ── Geometry — computed before useAnimatedProps (safe when 0) ─────────────
98
+ const cx = width / 2;
99
+ const cy = height * 0.42;
100
+ const r = width * CIRCLE_DIAMETER_RATIO / 2;
101
+ const circumference = 2 * Math.PI * r;
102
+ const color = getCircleColor(state, score);
103
+
104
+ // ── Animated props — UI-thread worklets, deps rebuilt when geometry changes
105
+ const scanAnimProps = useAnimatedProps(function LivenessCameraTsx1Factory({
106
+ _worklet_15111972513221_init_data,
107
+ cy,
108
+ r,
109
+ scanProgress,
110
+ SCAN_LINE_HEIGHT,
111
+ scanOpacity
112
+ }) {
113
+ const _e = [new global.Error(), -6, -27];
114
+ const LivenessCameraTsx1 = () => ({
115
+ // Map 0→1 progress onto the pixel range inside the circle
116
+ y: cy - r + 2 + scanProgress.value * (2 * r - SCAN_LINE_HEIGHT - 4),
117
+ opacity: scanOpacity.value
118
+ });
119
+ LivenessCameraTsx1.__closure = {
120
+ cy,
121
+ r,
122
+ scanProgress,
123
+ SCAN_LINE_HEIGHT,
124
+ scanOpacity
125
+ };
126
+ LivenessCameraTsx1.__workletHash = 15111972513221;
127
+ LivenessCameraTsx1.__pluginVersion = "0.8.3";
128
+ LivenessCameraTsx1.__initData = _worklet_15111972513221_init_data;
129
+ LivenessCameraTsx1.__stackDetails = _e;
130
+ return LivenessCameraTsx1;
131
+ }({
132
+ _worklet_15111972513221_init_data,
133
+ cy,
134
+ r,
135
+ scanProgress,
136
+ SCAN_LINE_HEIGHT,
137
+ scanOpacity
138
+ }), [cy, r]);
139
+ const bracketAnimProps = useAnimatedProps(function LivenessCameraTsx2Factory({
140
+ _worklet_14693916078586_init_data,
141
+ bracketRot,
142
+ cx,
143
+ cy
144
+ }) {
145
+ const _e = [new global.Error(), -4, -27];
146
+ const LivenessCameraTsx2 = () => ({
147
+ // react-native-svg accepts numeric rotation + origin instead of a string
148
+ rotation: bracketRot.value % 360,
149
+ originX: cx,
150
+ originY: cy
151
+ });
152
+ LivenessCameraTsx2.__closure = {
153
+ bracketRot,
154
+ cx,
155
+ cy
156
+ };
157
+ LivenessCameraTsx2.__workletHash = 14693916078586;
158
+ LivenessCameraTsx2.__pluginVersion = "0.8.3";
159
+ LivenessCameraTsx2.__initData = _worklet_14693916078586_init_data;
160
+ LivenessCameraTsx2.__stackDetails = _e;
161
+ return LivenessCameraTsx2;
162
+ }({
163
+ _worklet_14693916078586_init_data,
164
+ bracketRot,
165
+ cx,
166
+ cy
167
+ }), [cx, cy]);
168
+ const progressAnimProps = useAnimatedProps(function LivenessCameraTsx3Factory({
169
+ _worklet_1688522500078_init_data,
170
+ circumference,
171
+ livenessProgress,
172
+ livenessThreshold
173
+ }) {
174
+ const _e = [new global.Error(), -4, -27];
175
+ const LivenessCameraTsx3 = () => ({
176
+ strokeDashoffset: circumference - livenessProgress.value / livenessThreshold * circumference
177
+ });
178
+ LivenessCameraTsx3.__closure = {
179
+ circumference,
180
+ livenessProgress,
181
+ livenessThreshold
182
+ };
183
+ LivenessCameraTsx3.__workletHash = 1688522500078;
184
+ LivenessCameraTsx3.__pluginVersion = "0.8.3";
185
+ LivenessCameraTsx3.__initData = _worklet_1688522500078_init_data;
186
+ LivenessCameraTsx3.__stackDetails = _e;
187
+ return LivenessCameraTsx3;
188
+ }({
189
+ _worklet_1688522500078_init_data,
190
+ circumference,
191
+ livenessProgress,
192
+ livenessThreshold
193
+ }), [circumference, livenessThreshold]);
78
194
 
79
195
  // ── Start scan line + bracket rotation on mount ───────────────────────────
80
196
  useEffect(() => {
81
- // Scan line: ping-pong top → bottom → top, 1.8 s each leg
82
- scanLoopRef.current = Animated.loop(Animated.sequence([Animated.timing(scanAnim, {
83
- toValue: 1,
197
+ scanProgress.value = withRepeat(withSequence(withTiming(1, {
84
198
  duration: 1800,
85
- easing: Easing.linear,
86
- useNativeDriver: false
87
- }), Animated.timing(scanAnim, {
88
- toValue: 0,
199
+ easing: Easing.linear
200
+ }), withTiming(0, {
89
201
  duration: 1800,
90
- easing: Easing.linear,
91
- useNativeDriver: false
92
- })]));
93
- scanLoopRef.current.start();
94
-
95
- // Brackets: one full rotation every 6 s — slow, atmospheric
96
- bracketLoopRef.current = Animated.loop(Animated.timing(bracketAnim, {
97
- toValue: 360,
202
+ easing: Easing.linear
203
+ })), -1, false);
204
+ bracketRot.value = withRepeat(withTiming(360, {
98
205
  duration: 6000,
99
- easing: Easing.linear,
100
- useNativeDriver: false
101
- }));
102
- bracketLoopRef.current.start();
206
+ easing: Easing.linear
207
+ }), -1, false);
103
208
  return () => {
104
- scanLoopRef.current?.stop();
105
- bracketLoopRef.current?.stop();
209
+ cancelAnimation(scanProgress);
210
+ cancelAnimation(bracketRot);
106
211
  };
107
212
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
108
213
 
109
- // ── On confirmed: stop scan + brackets, fade out scan line ────────────────
214
+ // ── On liveness confirmed: freeze brackets, fade scan line out ────────────
110
215
  useEffect(() => {
111
- const isActive = state === 'scanning';
112
- if (!isActive) {
113
- scanLoopRef.current?.stop();
114
- bracketLoopRef.current?.stop();
115
- Animated.timing(scanOpacity, {
116
- toValue: 0,
117
- duration: 350,
118
- useNativeDriver: false
119
- }).start();
216
+ if (state !== 'scanning') {
217
+ cancelAnimation(scanProgress);
218
+ cancelAnimation(bracketRot);
219
+ scanOpacity.value = withTiming(0, {
220
+ duration: 350
221
+ });
120
222
  }
121
- }, [state, scanOpacity]);
223
+ }, [state]); // eslint-disable-line react-hooks/exhaustive-deps
122
224
 
123
225
  // ── Drive progress arc from live score ────────────────────────────────────
124
226
  useEffect(() => {
125
- Animated.timing(progressAnim, {
126
- toValue: Math.min(score, livenessThreshold),
127
- duration: 180,
128
- useNativeDriver: false
129
- }).start();
130
- }, [score, livenessThreshold, progressAnim]);
227
+ livenessProgress.value = withTiming(Math.min(score, livenessThreshold), {
228
+ duration: 180
229
+ });
230
+ }, [score, livenessThreshold]); // eslint-disable-line react-hooks/exhaustive-deps
131
231
 
132
232
  // ── Guard — render nothing until dimensions are known ─────────────────────
133
233
  if (width === 0 || height === 0) return null;
134
234
 
135
- // ── Geometry ──────────────────────────────────────────────────────────────
136
- const cx = width / 2;
137
- const cy = height * 0.42;
138
- const r = width * CIRCLE_DIAMETER_RATIO / 2;
139
- const circumference = 2 * Math.PI * r;
140
- const color = getCircleColor(state, score);
141
-
142
- // Scrim: full-screen dark rect with transparent circle hole
235
+ // Scrim: full-screen rect with transparent circle cutout (evenodd rule)
143
236
  const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
144
237
 
145
- // Scan line Y: sweeps from just inside top to just inside bottom of circle
146
- const scanLineY = scanAnim.interpolate({
147
- inputRange: [0, 1],
148
- outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2]
149
- });
150
-
151
- // Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
152
- const strokeDashoffset = progressAnim.interpolate({
153
- inputRange: [0, livenessThreshold],
154
- outputRange: [circumference, 0],
155
- extrapolate: 'clamp'
156
- });
157
-
158
- // Bracket group rotation — centred on the circle
159
- const bracketTransform = bracketAnim.interpolate({
160
- inputRange: [0, 360],
161
- outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`]
162
- });
163
-
164
238
  // 4 corner brackets at NE / SE / SW / NW diagonal positions
165
239
  const bracketD = [45, 135, 225, 315].map(deg => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG)).join(' ');
166
240
  return /*#__PURE__*/_jsxs(Svg, {
@@ -214,14 +288,13 @@ function CircleOverlay({
214
288
  clipPath: "url(#liveness-circle-clip)",
215
289
  children: /*#__PURE__*/_jsx(AnimatedRect, {
216
290
  x: cx - r,
217
- y: scanLineY,
218
291
  width: r * 2,
219
292
  height: SCAN_LINE_HEIGHT,
220
293
  fill: "url(#scan-gradient)",
221
- opacity: scanOpacity
294
+ animatedProps: scanAnimProps
222
295
  })
223
296
  }), /*#__PURE__*/_jsx(AnimatedG, {
224
- transform: bracketTransform,
297
+ animatedProps: bracketAnimProps,
225
298
  children: /*#__PURE__*/_jsx(Path, {
226
299
  d: bracketD,
227
300
  fill: "none",
@@ -238,9 +311,9 @@ function CircleOverlay({
238
311
  stroke: color,
239
312
  strokeWidth: STROKE_WIDTH,
240
313
  strokeDasharray: circumference,
241
- strokeDashoffset: strokeDashoffset,
242
314
  strokeLinecap: "round",
243
- transform: `rotate(-90, ${cx}, ${cy})`
315
+ transform: `rotate(-90, ${cx}, ${cy})`,
316
+ animatedProps: progressAnimProps
244
317
  })]
245
318
  });
246
319
  }
@@ -250,26 +323,26 @@ function CountdownBubble({
250
323
  value,
251
324
  fontFamily
252
325
  }) {
253
- const scale = useRef(new Animated.Value(0)).current;
254
- const opacity = useRef(new Animated.Value(0)).current;
326
+ const scale = useRef(new RNAnimated.Value(0)).current;
327
+ const opacity = useRef(new RNAnimated.Value(0)).current;
255
328
  useEffect(() => {
256
- Animated.parallel([Animated.sequence([Animated.spring(scale, {
329
+ RNAnimated.parallel([RNAnimated.sequence([RNAnimated.spring(scale, {
257
330
  toValue: 1.2,
258
331
  stiffness: 200,
259
332
  damping: 6,
260
333
  useNativeDriver: true
261
- }), Animated.spring(scale, {
334
+ }), RNAnimated.spring(scale, {
262
335
  toValue: 1.0,
263
336
  stiffness: 150,
264
337
  damping: 8,
265
338
  useNativeDriver: true
266
- })]), Animated.timing(opacity, {
339
+ })]), RNAnimated.timing(opacity, {
267
340
  toValue: 1,
268
341
  duration: 150,
269
342
  useNativeDriver: true
270
343
  })]).start();
271
344
  return () => {
272
- Animated.timing(opacity, {
345
+ RNAnimated.timing(opacity, {
273
346
  toValue: 0,
274
347
  duration: 200,
275
348
  useNativeDriver: true
@@ -277,7 +350,7 @@ function CountdownBubble({
277
350
  };
278
351
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
279
352
 
280
- return /*#__PURE__*/_jsx(Animated.View, {
353
+ return /*#__PURE__*/_jsx(RNAnimated.View, {
281
354
  style: [styles.countdownBubble, {
282
355
  opacity,
283
356
  transform: [{
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","Easing","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","ClipPath","Defs","G","LinearGradient","Path","Rect","Stop","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","AnimatedCircle","createAnimatedComponent","AnimatedG","AnimatedRect","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","SCAN_LINE_HEIGHT","BRACKET_SPAN_DEG","BRACKET_STROKE","getCircleColor","state","score","circlePath","cx","cy","r","join","bracketArcPath","centerDeg","spanDeg","toRad","d","Math","PI","a1","a2","x1","cos","y1","sin","x2","y2","CircleOverlay","width","height","livenessThreshold","scanAnim","Value","current","scanOpacity","progressAnim","bracketAnim","scanLoopRef","bracketLoopRef","loop","sequence","timing","toValue","duration","easing","linear","useNativeDriver","start","stop","isActive","min","circumference","color","scrimD","scanLineY","interpolate","inputRange","outputRange","strokeDashoffset","extrapolate","bracketTransform","bracketD","map","deg","style","absoluteFill","children","id","offset","stopColor","stopOpacity","fill","fillRule","stroke","strokeWidth","clipPath","x","y","opacity","transform","strokeLinecap","strokeDasharray","CountdownBubble","value","fontFamily","scale","parallel","spring","stiffness","damping","styles","countdownBubble","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","root","centered","permissionText","onLayout","ref","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","RNAnimated","StyleSheet","Text","View","cancelAnimation","Easing","useAnimatedProps","useSharedValue","withRepeat","withSequence","withTiming","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","ClipPath","Defs","G","LinearGradient","Path","Rect","Stop","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","AnimatedCircle","createAnimatedComponent","AnimatedG","AnimatedRect","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","SCAN_LINE_HEIGHT","BRACKET_SPAN_DEG","BRACKET_STROKE","getCircleColor","state","score","circlePath","cx","cy","r","join","bracketArcPath","centerDeg","spanDeg","toRad","d","Math","PI","a1","a2","x1","cos","y1","sin","x2","y2","_worklet_15111972513221_init_data","code","location","sourceMap","_worklet_14693916078586_init_data","_worklet_1688522500078_init_data","CircleOverlay","width","height","livenessThreshold","scanProgress","scanOpacity","bracketRot","livenessProgress","circumference","color","scanAnimProps","LivenessCameraTsx1Factory","_e","global","Error","LivenessCameraTsx1","y","value","opacity","__closure","__workletHash","__pluginVersion","__initData","__stackDetails","bracketAnimProps","LivenessCameraTsx2Factory","LivenessCameraTsx2","rotation","originX","originY","progressAnimProps","LivenessCameraTsx3Factory","LivenessCameraTsx3","strokeDashoffset","duration","easing","linear","min","scrimD","bracketD","map","deg","style","absoluteFill","children","id","offset","stopColor","stopOpacity","fill","fillRule","stroke","strokeWidth","clipPath","x","animatedProps","strokeLinecap","strokeDasharray","transform","CountdownBubble","fontFamily","scale","Value","current","parallel","sequence","spring","toValue","stiffness","damping","useNativeDriver","timing","start","styles","countdownBubble","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","root","centered","permissionText","onLayout","ref","isActive","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
@@ -2,19 +2,39 @@
2
2
 
3
3
  import { useMemo } from 'react';
4
4
  import { VisionCameraProxy } from 'react-native-vision-camera';
5
+ const _worklet_4012480599600_init_data = {
6
+ code: "function LivenessDetectorTs1(frame){const{plugin}=this.__closure;const result=plugin.call(frame);return result;}",
7
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessDetector.ts",
8
+ sourceMap: "{\"version\":3,\"names\":[\"LivenessDetectorTs1\",\"frame\",\"plugin\",\"__closure\",\"result\",\"call\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/LivenessDetector.ts\"],\"mappings\":\"AAsBoB,QAAC,CAAAA,mBAAkCA,CAAAC,KAAA,QAAAC,MAAA,OAAAC,SAAA,CAEjD,KAAM,CAAAC,MAAM,CAAGF,MAAM,CAACG,IAAI,CAACJ,KAAK,CAAC,CAEjC,MAAO,CAAAG,MAAM,CACf\",\"ignoreList\":[]}"
9
+ };
5
10
  function createPlugin() {
6
11
  const plugin = VisionCameraProxy.initFrameProcessorPlugin('detectLiveness', {});
7
12
  if (!plugin) {
8
13
  throw new Error('[LivenessCamera] Frame Processor Plugin "detectLiveness" not found. ' + 'Make sure the native module is linked correctly.');
9
14
  }
10
15
  return {
11
- detectLiveness: frame => {
12
- 'worklet';
13
-
14
- const result = plugin.call(frame);
15
- // plugin.call returns a loosely-typed BasicParameterType — cast via unknown
16
- return result;
17
- }
16
+ detectLiveness: function LivenessDetectorTs1Factory({
17
+ _worklet_4012480599600_init_data,
18
+ plugin
19
+ }) {
20
+ const _e = [new global.Error(), -2, -27];
21
+ const LivenessDetectorTs1 = function (frame) {
22
+ const result = plugin.call(frame);
23
+ // plugin.call returns a loosely-typed BasicParameterType — cast via unknown
24
+ return result;
25
+ };
26
+ LivenessDetectorTs1.__closure = {
27
+ plugin
28
+ };
29
+ LivenessDetectorTs1.__workletHash = 4012480599600;
30
+ LivenessDetectorTs1.__pluginVersion = "0.8.3";
31
+ LivenessDetectorTs1.__initData = _worklet_4012480599600_init_data;
32
+ LivenessDetectorTs1.__stackDetails = _e;
33
+ return LivenessDetectorTs1;
34
+ }({
35
+ _worklet_4012480599600_init_data,
36
+ plugin
37
+ })
18
38
  };
19
39
  }
20
40
  export function useLivenessPlugin() {
@@ -1 +1 @@
1
- {"version":3,"names":["useMemo","VisionCameraProxy","createPlugin","plugin","initFrameProcessorPlugin","Error","detectLiveness","frame","result","call","useLivenessPlugin"],"sourceRoot":"../../src","sources":["LivenessDetector.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,iBAAiB,QAAoB,4BAA4B;AAO1E,SAASC,YAAYA,CAAA,EAAmB;EACtC,MAAMC,MAAM,GAAGF,iBAAiB,CAACG,wBAAwB,CACvD,gBAAgB,EAChB,CAAC,CACH,CAAC;EAED,IAAI,CAACD,MAAM,EAAE;IACX,MAAM,IAAIE,KAAK,CACb,sEAAsE,GACpE,kDACJ,CAAC;EACH;EAEA,OAAO;IACLC,cAAc,EAAGC,KAAY,IAAsB;MACjD,SAAS;;MACT,MAAMC,MAAM,GAAGL,MAAM,CAACM,IAAI,CAACF,KAAK,CAAC;MACjC;MACA,OAAOC,MAAM;IACf;EACF,CAAC;AACH;AAEA,OAAO,SAASE,iBAAiBA,CAAA,EAAmB;EAClD,OAAOV,OAAO,CAAC,MAAME,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC;AAC1C","ignoreList":[]}
1
+ {"version":3,"names":["useMemo","VisionCameraProxy","_worklet_4012480599600_init_data","code","location","sourceMap","createPlugin","plugin","initFrameProcessorPlugin","Error","detectLiveness","LivenessDetectorTs1Factory","_e","global","LivenessDetectorTs1","frame","result","call","__closure","__workletHash","__pluginVersion","__initData","__stackDetails","useLivenessPlugin"],"sourceRoot":"../../src","sources":["LivenessDetector.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,iBAAiB,QAAoB,4BAA4B;AAAC,MAAAC,gCAAA;EAAAC,IAAA;EAAAC,QAAA;EAAAC,SAAA;AAAA;AAO3E,SAASC,YAAYA,CAAA,EAAmB;EACtC,MAAMC,MAAM,GAAGN,iBAAiB,CAACO,wBAAwB,CACvD,gBAAgB,EAChB,CAAC,CACH,CAAC;EAED,IAAI,CAACD,MAAM,EAAE;IACX,MAAM,IAAIE,KAAK,CACb,sEAAsE,GACpE,kDACJ,CAAC;EACH;EAEA,OAAO;IACLC,cAAc,EAAE,SAAAC,2BAAA;MAAAT,gCAAA;MAECK;IAAM;MAAA,MAAAK,EAAA,QAAAC,MAAA,CAAAJ,KAAA;MAAA,MAAAK,mBAAA,YAAAA,CAFNC,KAAY,EAAsB;QAEjD,MAAMC,MAAM,GAAGT,MAAM,CAACU,IAAI,CAACF,KAAK,CAAC;QACjC;QACA,OAAOC,MAAM;MACf,CAAC;MAAAF,mBAAA,CAAAI,SAAA;QAHgBX;MAAM;MAAAO,mBAAA,CAAAK,aAAA;MAAAL,mBAAA,CAAAM,eAAA;MAAAN,mBAAA,CAAAO,UAAA,GAAAnB,gCAAA;MAAAY,mBAAA,CAAAQ,cAAA,GAAAV,EAAA;MAAA,OAAAE,mBAAA;IAAA,CAFP;MAAAZ,gCAAA;MAECK;IAAM;EAIzB,CAAC;AACH;AAEA,OAAO,SAASgB,iBAAiBA,CAAA,EAAmB;EAClD,OAAOvB,OAAO,CAAC,MAAMM,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC;AAC1C","ignoreList":[]}
@@ -9,6 +9,16 @@ const WINDOW_SIZE = 20;
9
9
  // How many frames to decay consecutiveGood by on a bad frame.
10
10
  // Decay (not hard reset) means one noisy frame won't erase all progress.
11
11
  const CONSECUTIVE_DECAY = 2;
12
+ const _worklet_11184642299290_init_data = {
13
+ code: "function useLivenessCameraTs1(){const{plugin,frame,handleFaceDataJS}=this.__closure;const face=plugin.detectLiveness(frame);handleFaceDataJS(face,frame.width);}",
14
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts",
15
+ sourceMap: "{\"version\":3,\"names\":[\"useLivenessCameraTs1\",\"plugin\",\"frame\",\"handleFaceDataJS\",\"__closure\",\"face\",\"detectLiveness\",\"width\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts\"],\"mappings\":\"AAuNyB,SAAAA,oBAAMA,CAAA,QAAAC,MAAA,CAAAC,KAAA,CAAAC,gBAAA,OAAAC,SAAA,CAEvB,KAAM,CAAAC,IAAI,CAAGJ,MAAM,CAACK,cAAc,CAACJ,KAAK,CAAC,CACzCC,gBAAgB,CAACE,IAAI,CAAEH,KAAK,CAACK,KAAK,CAAC,CACrC\",\"ignoreList\":[]}"
16
+ };
17
+ const _worklet_14471027507603_init_data = {
18
+ code: "function useLivenessCameraTs2(frame){const{runAtTargetFps,_worklet_11184642299290_init_data,plugin,handleFaceDataJS}=this.__closure;runAtTargetFps(20,function useLivenessCameraTs1Factory({_worklet_11184642299290_init_data:_worklet_11184642299290_init_data,plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS}){const _e=[new global.Error(),-4,-27];const useLivenessCameraTs1=function(){const face=plugin.detectLiveness(frame);handleFaceDataJS(face,frame.width);};useLivenessCameraTs1.__closure={plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS};useLivenessCameraTs1.__workletHash=11184642299290;useLivenessCameraTs1.__pluginVersion=\"0.8.3\";useLivenessCameraTs1.__initData=_worklet_11184642299290_init_data;useLivenessCameraTs1.__stackDetails=_e;return useLivenessCameraTs1;}({_worklet_11184642299290_init_data:_worklet_11184642299290_init_data,plugin:plugin,frame:frame,handleFaceDataJS:handleFaceDataJS}));}",
19
+ location: "/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts",
20
+ sourceMap: "{\"version\":3,\"names\":[\"useLivenessCameraTs2\",\"frame\",\"runAtTargetFps\",\"_worklet_11184642299290_init_data\",\"plugin\",\"handleFaceDataJS\",\"__closure\",\"useLivenessCameraTs1Factory\",\"_e\",\"global\",\"Error\",\"useLivenessCameraTs1\",\"face\",\"detectLiveness\",\"width\",\"__workletHash\",\"__pluginVersion\",\"__initData\",\"__stackDetails\"],\"sources\":[\"/home/runner/work/react-native-liveness/react-native-liveness/src/useLivenessCamera.ts\"],\"mappings\":\"AAmNI,QAAC,CAAAA,oBAAiBA,CAAAC,KAAA,QAAAC,cAAA,CAAAC,iCAAA,CAAAC,MAAA,CAAAC,gBAAA,OAAAC,SAAA,CAIhBJ,cAAc,CAAC,EAAE,CAAE,SAAAK,4BAAA,CAAAJ,iCAAA,CAAAA,iCAAA,CAEJC,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,SAAAG,EAAA,MAAAC,MAAA,CAAAC,KAAA,iBAAAC,oBAAA,SAAAA,CAAA,CAHO,CAEvB,KAAM,CAAAC,IAAI,CAAGR,MAAM,CAACS,cAAc,CAACZ,KAAK,CAAC,CACzCI,gBAAgB,CAACO,IAAI,CAAEX,KAAK,CAACa,KAAK,CAAC,CACrC,CAAC,CAAAH,oBAAA,CAAAL,SAAA,EAFcF,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,EAAAM,oBAAA,CAAAI,aAAA,gBAAAJ,oBAAA,CAAAK,eAAA,SAAAL,oBAAA,CAAAM,UAAA,CAAAd,iCAAA,CAAAQ,oBAAA,CAAAO,cAAA,CAAAV,EAAA,QAAAG,oBAAA,EAHC,EAAAR,iCAAA,CAAAA,iCAAA,CAEJC,MAAM,CAANA,MAAM,CAAgBH,KAAK,CAALA,KAAK,CACxCI,gBAAA,CAAAA,gBAAgB,EACjB,CAAC,CACJ\",\"ignoreList\":[]}"
21
+ };
12
22
  export function useLivenessCamera(options) {
13
23
  const {
14
24
  livenessThreshold,
@@ -168,18 +178,63 @@ export function useLivenessCamera(options) {
168
178
  // ─── Frame processor ──────────────────────────────────────────────────────
169
179
 
170
180
  const handleFaceDataJS = useMemo(() => Worklets.createRunOnJS(handleFaceData), [handleFaceData]);
171
- const frameProcessor = useFrameProcessor(frame => {
172
- 'worklet';
173
-
174
- // Camera preview renders at full fps (60). ML Kit only needs ~20fps —
175
- // running it on every frame would block the render thread unnecessarily.
176
- runAtTargetFps(20, () => {
177
- 'worklet';
178
-
179
- const face = plugin.detectLiveness(frame);
180
- handleFaceDataJS(face, frame.width);
181
- });
182
- }, [plugin, handleFaceDataJS]);
181
+ const frameProcessor = useFrameProcessor(function useLivenessCameraTs2Factory({
182
+ _worklet_14471027507603_init_data,
183
+ runAtTargetFps,
184
+ _worklet_11184642299290_init_data,
185
+ plugin,
186
+ handleFaceDataJS
187
+ }) {
188
+ const _e = [new global.Error(), -5, -27];
189
+ const useLivenessCameraTs2 = function (frame) {
190
+ // Camera preview renders at full fps (60). ML Kit only needs ~20fps —
191
+ // running it on every frame would block the render thread unnecessarily.
192
+ runAtTargetFps(20, function useLivenessCameraTs1Factory({
193
+ _worklet_11184642299290_init_data,
194
+ plugin,
195
+ frame,
196
+ handleFaceDataJS
197
+ }) {
198
+ const _e = [new global.Error(), -4, -27];
199
+ const useLivenessCameraTs1 = function () {
200
+ const face = plugin.detectLiveness(frame);
201
+ handleFaceDataJS(face, frame.width);
202
+ };
203
+ useLivenessCameraTs1.__closure = {
204
+ plugin,
205
+ frame,
206
+ handleFaceDataJS
207
+ };
208
+ useLivenessCameraTs1.__workletHash = 11184642299290;
209
+ useLivenessCameraTs1.__pluginVersion = "0.8.3";
210
+ useLivenessCameraTs1.__initData = _worklet_11184642299290_init_data;
211
+ useLivenessCameraTs1.__stackDetails = _e;
212
+ return useLivenessCameraTs1;
213
+ }({
214
+ _worklet_11184642299290_init_data,
215
+ plugin,
216
+ frame,
217
+ handleFaceDataJS
218
+ }));
219
+ };
220
+ useLivenessCameraTs2.__closure = {
221
+ runAtTargetFps,
222
+ _worklet_11184642299290_init_data,
223
+ plugin,
224
+ handleFaceDataJS
225
+ };
226
+ useLivenessCameraTs2.__workletHash = 14471027507603;
227
+ useLivenessCameraTs2.__pluginVersion = "0.8.3";
228
+ useLivenessCameraTs2.__initData = _worklet_14471027507603_init_data;
229
+ useLivenessCameraTs2.__stackDetails = _e;
230
+ return useLivenessCameraTs2;
231
+ }({
232
+ _worklet_14471027507603_init_data,
233
+ runAtTargetFps,
234
+ _worklet_11184642299290_init_data,
235
+ plugin,
236
+ handleFaceDataJS
237
+ }), [plugin, handleFaceDataJS]);
183
238
  useEffect(() => {
184
239
  return () => {
185
240
  frameScores.current = [];
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","runAtTargetFps","useFrameProcessor","Worklets","useLivenessPlugin","getFeedback","rollingAverage","scoreFrame","WINDOW_SIZE","CONSECUTIVE_DECAY","useLivenessCamera","options","livenessThreshold","confirmFrames","countdownFrom","soundEnabled","cameraRef","onCapture","onLivenessConfirmed","onError","plugin","frameScores","consecutiveGood","frameWidth","stateRef","isCaptured","FEEDBACK_DEBOUNCE_MS","feedbackTimer","pendingFeedback","state","setState","livenessState","livenessScore","countdown","feedback","setLivenessState","next","current","prev","capture","photo","takePhoto","flash","enableShutterSound","score","timestamp","Date","now","err","Error","String","startCountdown","tick","interval","setInterval","clearInterval","handleFaceData","face","width","safeFace","detected","bounds","x","y","height","yawAngle","pitchAngle","rollAngle","leftEyeOpenProbability","rightEyeOpenProbability","smilingProbability","total","push","length","shift","avgScore","Math","max","isLive","newFeedback","clearTimeout","setTimeout","handleFaceDataJS","createRunOnJS","frameProcessor","frame","detectLiveness"],"sourceRoot":"../../src","sources":["useLivenessCamera.ts"],"mappings":";;AAAA,SAASA,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAEzE,SAASC,cAAc,EAAEC,iBAAiB,QAAQ,4BAA4B;AAC9E,SAASC,QAAQ,QAAQ,4BAA4B;AACrD,SAASC,iBAAiB,QAAQ,uBAAoB;AACtD,SAASC,WAAW,EAAEC,cAAc,EAAEC,UAAU,QAAQ,sBAAmB;AAQ3E,MAAMC,WAAW,GAAG,EAAE;AACtB;AACA;AACA,MAAMC,iBAAiB,GAAG,CAAC;AAoB3B,OAAO,SAASC,iBAAiBA,CAACC,OAAgB,EAAE;EAClD,MAAM;IACJC,iBAAiB;IACjBC,aAAa;IACbC,aAAa;IACbC,YAAY;IACZC,SAAS;IACTC,SAAS;IACTC,mBAAmB;IACnBC;EACF,CAAC,GAAGR,OAAO;EAEX,MAAMS,MAAM,GAAGhB,iBAAiB,CAAC,CAAC;;EAElC;EACA,MAAMiB,WAAW,GAAGtB,MAAM,CAAW,EAAE,CAAC;EACxC,MAAMuB,eAAe,GAAGvB,MAAM,CAAC,CAAC,CAAC;EACjC,MAAMwB,UAAU,GAAGxB,MAAM,CAAC,CAAC,CAAC;EAC5B,MAAMyB,QAAQ,GAAGzB,MAAM,CAAgB,UAAU,CAAC;EAClD,MAAM0B,UAAU,GAAG1B,MAAM,CAAC,KAAK,CAAC;;EAEhC;EACA;EACA;EACA,MAAM2B,oBAAoB,GAAG,GAAG;EAChC,MAAMC,aAAa,GAAG5B,MAAM,CAAuC,IAAI,CAAC;EACxE,MAAM6B,eAAe,GAAG7B,MAAM,CAC5B,kCACF,CAAC;EAED,MAAM,CAAC8B,KAAK,EAAEC,QAAQ,CAAC,GAAG9B,QAAQ,CAAsB;IACtD+B,aAAa,EAAE,UAAU;IACzBC,aAAa,EAAE,CAAC;IAChBC,SAAS,EAAE,IAAI;IACfC,QAAQ,EAAE;EACZ,CAAC,CAAC;EAEF,MAAMC,gBAAgB,GAAGvC,WAAW,CAAEwC,IAAmB,IAAK;IAC5DZ,QAAQ,CAACa,OAAO,GAAGD,IAAI;IACvBN,QAAQ,CAAEQ,IAAI,KAAM;MAAE,GAAGA,IAAI;MAAEP,aAAa,EAAEK;IAAK,CAAC,CAAC,CAAC;EACxD,CAAC,EAAE,EAAE,CAAC;;EAEN;;EAEA,MAAMG,OAAO,GAAG3C,WAAW,CAAC,YAAY;IACtC,IAAI6B,UAAU,CAACY,OAAO,IAAI,CAACrB,SAAS,CAACqB,OAAO,EAAE;IAC9CZ,UAAU,CAACY,OAAO,GAAG,IAAI;IAEzBF,gBAAgB,CAAC,WAAW,CAAC;IAE7B,IAAI;MACF,MAAMK,KAAK,GAAG,MAAMxB,SAAS,CAACqB,OAAO,CAACI,SAAS,CAAC;QAC9CC,KAAK,EAAE,KAAK;QACZC,kBAAkB,EAAE5B;MACtB,CAAC,CAAC;MACF,MAAM6B,KAAK,GAAGtC,cAAc,CAACe,WAAW,CAACgB,OAAO,CAAC;MAEjDF,gBAAgB,CAAC,MAAM,CAAC;MACxBlB,SAAS,CAAC;QAAEuB,KAAK;QAAER,aAAa,EAAEY,KAAK;QAAEC,SAAS,EAAEC,IAAI,CAACC,GAAG,CAAC;MAAE,CAAC,CAAC;IACnE,CAAC,CAAC,OAAOC,GAAG,EAAE;MACZb,gBAAgB,CAAC,OAAO,CAAC;MACzBhB,OAAO,GAAG6B,GAAG,YAAYC,KAAK,GAAGD,GAAG,GAAG,IAAIC,KAAK,CAACC,MAAM,CAACF,GAAG,CAAC,CAAC,CAAC;IAChE;EACF,CAAC,EAAE,CAAChC,SAAS,EAAEC,SAAS,EAAEE,OAAO,EAAEJ,YAAY,EAAEoB,gBAAgB,CAAC,CAAC;;EAEnE;;EAEA,MAAMgB,cAAc,GAAGvD,WAAW,CAAC,MAAM;IACvCuC,gBAAgB,CAAC,WAAW,CAAC;IAC7B,IAAIiB,IAAI,GAAGtC,aAAa;IAExBgB,QAAQ,CAAEQ,IAAI,KAAM;MAAE,GAAGA,IAAI;MAAEL,SAAS,EAAEmB;IAAK,CAAC,CAAC,CAAC;IAElD,MAAMC,QAAQ,GAAGC,WAAW,CAAC,MAAM;MACjCF,IAAI,IAAI,CAAC;MACT,IAAIA,IAAI,IAAI,CAAC,EAAE;QACbG,aAAa,CAACF,QAAQ,CAAC;QACvBvB,QAAQ,CAAEQ,IAAI,KAAM;UAAE,GAAGA,IAAI;UAAEL,SAAS,EAAE;QAAK,CAAC,CAAC,CAAC;QAClDM,OAAO,CAAC,CAAC;MACX,CAAC,MAAM;QACLT,QAAQ,CAAEQ,IAAI,KAAM;UAAE,GAAGA,IAAI;UAAEL,SAAS,EAAEmB;QAAK,CAAC,CAAC,CAAC;MACpD;IACF,CAAC,EAAE,IAAI,CAAC;IAER,OAAO,MAAMG,aAAa,CAACF,QAAQ,CAAC;EACtC,CAAC,EAAE,CAACd,OAAO,EAAEzB,aAAa,EAAEqB,gBAAgB,CAAC,CAAC;;EAE9C;;EAEA,MAAMqB,cAAc,GAAG5D,WAAW,CAChC,CAAC6D,IAAqB,EAAEC,KAAa,KAAK;IACxC,IACElC,QAAQ,CAACa,OAAO,KAAK,WAAW,IAChCb,QAAQ,CAACa,OAAO,KAAK,MAAM,IAC3Bb,QAAQ,CAACa,OAAO,KAAK,OAAO,EAC5B;MACA;IACF;IAEAd,UAAU,CAACc,OAAO,GAAGqB,KAAK;IAE1B,MAAMC,QAAkB,GAAGF,IAAI,IAAI;MACjCG,QAAQ,EAAE,KAAK;MACfC,MAAM,EAAE;QAAEC,CAAC,EAAE,CAAC;QAAEC,CAAC,EAAE,CAAC;QAAEL,KAAK,EAAE,CAAC;QAAEM,MAAM,EAAE;MAAE,CAAC;MAC3CC,QAAQ,EAAE,CAAC;MACXC,UAAU,EAAE,CAAC;MACbC,SAAS,EAAE,CAAC;MACZC,sBAAsB,EAAE,CAAC,CAAC;MAC1BC,uBAAuB,EAAE,CAAC,CAAC;MAC3BC,kBAAkB,EAAE,CAAC;IACvB,CAAC;IAED,MAAM;MAAEC;IAAM,CAAC,GAAGhE,UAAU,CAACoD,QAAQ,EAAED,KAAK,CAAC;IAE7CrC,WAAW,CAACgB,OAAO,CAACmC,IAAI,CAACD,KAAK,CAAC;IAC/B,IAAIlD,WAAW,CAACgB,OAAO,CAACoC,MAAM,GAAGjE,WAAW,EAAE;MAC5Ca,WAAW,CAACgB,OAAO,CAACqC,KAAK,CAAC,CAAC;IAC7B;IAEA,MAAMC,QAAQ,GAAGrE,cAAc,CAACe,WAAW,CAACgB,OAAO,CAAC;;IAEpD;IACA;IACA,IAAIkC,KAAK,IAAI3D,iBAAiB,EAAE;MAC9BU,eAAe,CAACe,OAAO,IAAI,CAAC;IAC9B,CAAC,MAAM;MACLf,eAAe,CAACe,OAAO,GAAGuC,IAAI,CAACC,GAAG,CAChC,CAAC,EACDvD,eAAe,CAACe,OAAO,GAAG5B,iBAC5B,CAAC;IACH;IAEA,MAAMqE,MAAM,GACVxD,eAAe,CAACe,OAAO,IAAIxB,aAAa,IACxC8D,QAAQ,IAAI/D,iBAAiB;;IAE/B;IACA;IACA,MAAMmE,WAAW,GAAG1E,WAAW,CAACsD,QAAQ,EAAED,KAAK,EAAEoB,MAAM,CAAC;IACxD,IAAIC,WAAW,KAAKnD,eAAe,CAACS,OAAO,EAAE;MAC3CT,eAAe,CAACS,OAAO,GAAG0C,WAAW;MACrC,IAAIpD,aAAa,CAACU,OAAO,EAAE2C,YAAY,CAACrD,aAAa,CAACU,OAAO,CAAC;MAC9DV,aAAa,CAACU,OAAO,GAAG4C,UAAU,CAAC,MAAM;QACvCnD,QAAQ,CAAEQ,IAAI,KAAM;UAClB,GAAGA,IAAI;UACPJ,QAAQ,EAAEN,eAAe,CAACS;QAC5B,CAAC,CAAC,CAAC;MACL,CAAC,EAAEX,oBAAoB,CAAC;IAC1B;IAEAI,QAAQ,CAAEQ,IAAI,KAAM;MAAE,GAAGA,IAAI;MAAEN,aAAa,EAAE2C;IAAS,CAAC,CAAC,CAAC;IAE1D,IAAIG,MAAM,IAAItD,QAAQ,CAACa,OAAO,KAAK,UAAU,EAAE;MAC7CF,gBAAgB,CAAC,WAAW,CAAC;MAC7BjB,mBAAmB,GAAG,CAAC;MACvBiC,cAAc,CAAC,CAAC;IAClB;EACF,CAAC,EACD,CACEtC,aAAa,EACbD,iBAAiB,EACjBM,mBAAmB,EACnBiB,gBAAgB,EAChBgB,cAAc,CAElB,CAAC;;EAED;;EAEA,MAAM+B,gBAAgB,GAAGpF,OAAO,CAC9B,MAAMK,QAAQ,CAACgF,aAAa,CAAC3B,cAAc,CAAC,EAC5C,CAACA,cAAc,CACjB,CAAC;EAED,MAAM4B,cAAc,GAAGlF,iBAAiB,CACrCmF,KAAY,IAAK;IAChB,SAAS;;IACT;IACA;IACApF,cAAc,CAAC,EAAE,EAAE,MAAM;MACvB,SAAS;;MACT,MAAMwD,IAAI,GAAGrC,MAAM,CAACkE,cAAc,CAACD,KAAK,CAAC;MACzCH,gBAAgB,CAACzB,IAAI,EAAE4B,KAAK,CAAC3B,KAAK,CAAC;IACrC,CAAC,CAAC;EACJ,CAAC,EACD,CAACtC,MAAM,EAAE8D,gBAAgB,CAC3B,CAAC;EAEDrF,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACXwB,WAAW,CAACgB,OAAO,GAAG,EAAE;MACxBf,eAAe,CAACe,OAAO,GAAG,CAAC;MAC3BZ,UAAU,CAACY,OAAO,GAAG,KAAK;MAC1B,IAAIV,aAAa,CAACU,OAAO,EAAE2C,YAAY,CAACrD,aAAa,CAACU,OAAO,CAAC;IAChE,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAO;IACL+C,cAAc;IACdrD,aAAa,EAAEF,KAAK,CAACE,aAAa;IAClCC,aAAa,EAAEH,KAAK,CAACG,aAAa;IAClCC,SAAS,EAAEJ,KAAK,CAACI,SAAS;IAC1BC,QAAQ,EAAEL,KAAK,CAACK;EAClB,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","runAtTargetFps","useFrameProcessor","Worklets","useLivenessPlugin","getFeedback","rollingAverage","scoreFrame","WINDOW_SIZE","CONSECUTIVE_DECAY","_worklet_11184642299290_init_data","code","location","sourceMap","_worklet_14471027507603_init_data","useLivenessCamera","options","livenessThreshold","confirmFrames","countdownFrom","soundEnabled","cameraRef","onCapture","onLivenessConfirmed","onError","plugin","frameScores","consecutiveGood","frameWidth","stateRef","isCaptured","FEEDBACK_DEBOUNCE_MS","feedbackTimer","pendingFeedback","state","setState","livenessState","livenessScore","countdown","feedback","setLivenessState","next","current","prev","capture","photo","takePhoto","flash","enableShutterSound","score","timestamp","Date","now","err","Error","String","startCountdown","tick","interval","setInterval","clearInterval","handleFaceData","face","width","safeFace","detected","bounds","x","y","height","yawAngle","pitchAngle","rollAngle","leftEyeOpenProbability","rightEyeOpenProbability","smilingProbability","total","push","length","shift","avgScore","Math","max","isLive","newFeedback","clearTimeout","setTimeout","handleFaceDataJS","createRunOnJS","frameProcessor","useLivenessCameraTs2Factory","_e","global","useLivenessCameraTs2","frame","useLivenessCameraTs1Factory","useLivenessCameraTs1","detectLiveness","__closure","__workletHash","__pluginVersion","__initData","__stackDetails"],"sourceRoot":"../../src","sources":["useLivenessCamera.ts"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AA4TlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,UAAyB,EACzB,KAAK,GACN,EAAE,mBAAmB,2CA+FrB"}
1
+ {"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AA8SlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,UAAyB,EACzB,KAAK,GACN,EAAE,mBAAmB,2CA+FrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rick427/react-native-liveness",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Liveness detection library for React Native using Vision Camera v4 and ML Kit",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -75,8 +75,10 @@
75
75
  "react": "19.2.0",
76
76
  "react-native": "0.83.6",
77
77
  "react-native-builder-bob": "^0.41.0",
78
+ "react-native-reanimated": "^4.3.0",
78
79
  "react-native-svg": "^15.0.0",
79
80
  "react-native-vision-camera": "^4.0.0",
81
+ "react-native-worklets": "0.8.x",
80
82
  "react-native-worklets-core": "^1.3.3",
81
83
  "turbo": "^2.8.21",
82
84
  "typescript": "^6.0.2"
@@ -84,6 +86,7 @@
84
86
  "peerDependencies": {
85
87
  "react": "*",
86
88
  "react-native": "*",
89
+ "react-native-reanimated": ">=4.0.0",
87
90
  "react-native-svg": ">=13.0.0",
88
91
  "react-native-vision-camera": ">=4.0.0",
89
92
  "react-native-worklets-core": ">=1.0.0"
@@ -99,7 +102,8 @@
99
102
  [
100
103
  "module",
101
104
  {
102
- "esm": true
105
+ "esm": true,
106
+ "configFile": true
103
107
  }
104
108
  ],
105
109
  [
@@ -1,5 +1,14 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
- import { Animated, Easing, StyleSheet, Text, View } from 'react-native';
2
+ import { Animated as RNAnimated, StyleSheet, Text, View } from 'react-native';
3
+ import Animated, {
4
+ cancelAnimation,
5
+ Easing,
6
+ useAnimatedProps,
7
+ useSharedValue,
8
+ withRepeat,
9
+ withSequence,
10
+ withTiming,
11
+ } from 'react-native-reanimated';
3
12
  import {
4
13
  Camera,
5
14
  useCameraDevice,
@@ -20,8 +29,9 @@ import {
20
29
  import { useLivenessCamera } from './useLivenessCamera';
21
30
  import type { LivenessCameraProps, LivenessState } from './types';
22
31
 
23
- // ─── Animated SVG components ─────────────────────────────────────────────────
24
- // Created once at module level so React never recreates the component class.
32
+ // ─── Animated SVG components (Reanimated) ────────────────────────────────────
33
+ // createAnimatedComponent from react-native-reanimated properly drives SVG
34
+ // presentation attributes (strokeDashoffset, y, rotation) on the UI thread.
25
35
  const AnimatedCircle = Animated.createAnimatedComponent(Circle);
26
36
  const AnimatedG = Animated.createAnimatedComponent(G);
27
37
  const AnimatedRect = Animated.createAnimatedComponent(Rect);
@@ -101,108 +111,94 @@ function CircleOverlay({
101
111
  score: number;
102
112
  livenessThreshold: number;
103
113
  }) {
104
- // ── Animation values (must be declared before any early return) ────────────
105
- const scanAnim = useRef(new Animated.Value(0)).current;
106
- const scanOpacity = useRef(new Animated.Value(1)).current;
107
- const progressAnim = useRef(new Animated.Value(0)).current;
108
- const bracketAnim = useRef(new Animated.Value(0)).current;
114
+ // ── Shared values all hooks before any early return ─────────────────────
115
+ // scanProgress 0=top 1=bottom, ping-pongs continuously
116
+ const scanProgress = useSharedValue(0);
117
+ const scanOpacity = useSharedValue(1);
118
+ // bracketRot drives the slow bracket rotation in degrees
119
+ const bracketRot = useSharedValue(0);
120
+ // livenessProgress tracks smoothed score for the arc
121
+ const livenessProgress = useSharedValue(0);
122
+
123
+ // ── Geometry — computed before useAnimatedProps (safe when 0) ─────────────
124
+ const cx = width / 2;
125
+ const cy = height * 0.42;
126
+ const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
127
+ const circumference = 2 * Math.PI * r;
128
+ const color = getCircleColor(state, score);
129
+
130
+ // ── Animated props — UI-thread worklets, deps rebuilt when geometry changes
131
+ const scanAnimProps = useAnimatedProps(
132
+ () => ({
133
+ // Map 0→1 progress onto the pixel range inside the circle
134
+ y: cy - r + 2 + scanProgress.value * (2 * r - SCAN_LINE_HEIGHT - 4),
135
+ opacity: scanOpacity.value,
136
+ }),
137
+ [cy, r]
138
+ );
139
+
140
+ const bracketAnimProps = useAnimatedProps(
141
+ () => ({
142
+ // react-native-svg accepts numeric rotation + origin instead of a string
143
+ rotation: bracketRot.value % 360,
144
+ originX: cx,
145
+ originY: cy,
146
+ }),
147
+ [cx, cy]
148
+ );
109
149
 
110
- const scanLoopRef = useRef<Animated.CompositeAnimation | null>(null);
111
- const bracketLoopRef = useRef<Animated.CompositeAnimation | null>(null);
150
+ const progressAnimProps = useAnimatedProps(
151
+ () => ({
152
+ strokeDashoffset:
153
+ circumference -
154
+ (livenessProgress.value / livenessThreshold) * circumference,
155
+ }),
156
+ [circumference, livenessThreshold]
157
+ );
112
158
 
113
159
  // ── Start scan line + bracket rotation on mount ───────────────────────────
114
160
  useEffect(() => {
115
- // Scan line: ping-pong top → bottom → top, 1.8 s each leg
116
- scanLoopRef.current = Animated.loop(
117
- Animated.sequence([
118
- Animated.timing(scanAnim, {
119
- toValue: 1,
120
- duration: 1800,
121
- easing: Easing.linear,
122
- useNativeDriver: false,
123
- }),
124
- Animated.timing(scanAnim, {
125
- toValue: 0,
126
- duration: 1800,
127
- easing: Easing.linear,
128
- useNativeDriver: false,
129
- }),
130
- ])
161
+ scanProgress.value = withRepeat(
162
+ withSequence(
163
+ withTiming(1, { duration: 1800, easing: Easing.linear }),
164
+ withTiming(0, { duration: 1800, easing: Easing.linear })
165
+ ),
166
+ -1,
167
+ false
131
168
  );
132
- scanLoopRef.current.start();
133
-
134
- // Brackets: one full rotation every 6 s — slow, atmospheric
135
- bracketLoopRef.current = Animated.loop(
136
- Animated.timing(bracketAnim, {
137
- toValue: 360,
138
- duration: 6000,
139
- easing: Easing.linear,
140
- useNativeDriver: false,
141
- })
169
+ bracketRot.value = withRepeat(
170
+ withTiming(360, { duration: 6000, easing: Easing.linear }),
171
+ -1,
172
+ false
142
173
  );
143
- bracketLoopRef.current.start();
144
-
145
174
  return () => {
146
- scanLoopRef.current?.stop();
147
- bracketLoopRef.current?.stop();
175
+ cancelAnimation(scanProgress);
176
+ cancelAnimation(bracketRot);
148
177
  };
149
178
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
150
179
 
151
- // ── On confirmed: stop scan + brackets, fade out scan line ────────────────
180
+ // ── On liveness confirmed: freeze brackets, fade scan line out ────────────
152
181
  useEffect(() => {
153
- const isActive = state === 'scanning';
154
- if (!isActive) {
155
- scanLoopRef.current?.stop();
156
- bracketLoopRef.current?.stop();
157
- Animated.timing(scanOpacity, {
158
- toValue: 0,
159
- duration: 350,
160
- useNativeDriver: false,
161
- }).start();
182
+ if (state !== 'scanning') {
183
+ cancelAnimation(scanProgress);
184
+ cancelAnimation(bracketRot);
185
+ scanOpacity.value = withTiming(0, { duration: 350 });
162
186
  }
163
- }, [state, scanOpacity]);
187
+ }, [state]); // eslint-disable-line react-hooks/exhaustive-deps
164
188
 
165
189
  // ── Drive progress arc from live score ────────────────────────────────────
166
190
  useEffect(() => {
167
- Animated.timing(progressAnim, {
168
- toValue: Math.min(score, livenessThreshold),
191
+ livenessProgress.value = withTiming(Math.min(score, livenessThreshold), {
169
192
  duration: 180,
170
- useNativeDriver: false,
171
- }).start();
172
- }, [score, livenessThreshold, progressAnim]);
193
+ });
194
+ }, [score, livenessThreshold]); // eslint-disable-line react-hooks/exhaustive-deps
173
195
 
174
196
  // ── Guard — render nothing until dimensions are known ─────────────────────
175
197
  if (width === 0 || height === 0) return null;
176
198
 
177
- // ── Geometry ──────────────────────────────────────────────────────────────
178
- const cx = width / 2;
179
- const cy = height * 0.42;
180
- const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
181
- const circumference = 2 * Math.PI * r;
182
- const color = getCircleColor(state, score);
183
-
184
- // Scrim: full-screen dark rect with transparent circle hole
199
+ // Scrim: full-screen rect with transparent circle cutout (evenodd rule)
185
200
  const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
186
201
 
187
- // Scan line Y: sweeps from just inside top to just inside bottom of circle
188
- const scanLineY = scanAnim.interpolate({
189
- inputRange: [0, 1],
190
- outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2],
191
- });
192
-
193
- // Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
194
- const strokeDashoffset = progressAnim.interpolate({
195
- inputRange: [0, livenessThreshold],
196
- outputRange: [circumference, 0],
197
- extrapolate: 'clamp',
198
- });
199
-
200
- // Bracket group rotation — centred on the circle
201
- const bracketTransform = bracketAnim.interpolate({
202
- inputRange: [0, 360],
203
- outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`],
204
- });
205
-
206
202
  // 4 corner brackets at NE / SE / SW / NW diagonal positions
207
203
  const bracketD = [45, 135, 225, 315]
208
204
  .map((deg) => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG))
@@ -243,16 +239,15 @@ function CircleOverlay({
243
239
  <G clipPath="url(#liveness-circle-clip)">
244
240
  <AnimatedRect
245
241
  x={cx - r}
246
- y={scanLineY}
247
242
  width={r * 2}
248
243
  height={SCAN_LINE_HEIGHT}
249
244
  fill="url(#scan-gradient)"
250
- opacity={scanOpacity}
245
+ animatedProps={scanAnimProps}
251
246
  />
252
247
  </G>
253
248
 
254
249
  {/* ── Rotating corner brackets ─────────────────────────────────────── */}
255
- <AnimatedG transform={bracketTransform}>
250
+ <AnimatedG animatedProps={bracketAnimProps}>
256
251
  <Path
257
252
  d={bracketD}
258
253
  fill="none"
@@ -264,7 +259,7 @@ function CircleOverlay({
264
259
  </AnimatedG>
265
260
 
266
261
  {/* ── Progress arc — draws in as liveness confidence builds ────────── */}
267
- {/* Rotated -90° so it starts at 12 o'clock and goes clockwise */}
262
+ {/* transform rotates -90° so arc starts at 12 o'clock, goes clockwise */}
268
263
  <AnimatedCircle
269
264
  cx={cx}
270
265
  cy={cy}
@@ -273,9 +268,9 @@ function CircleOverlay({
273
268
  stroke={color}
274
269
  strokeWidth={STROKE_WIDTH}
275
270
  strokeDasharray={circumference}
276
- strokeDashoffset={strokeDashoffset}
277
271
  strokeLinecap="round"
278
272
  transform={`rotate(-90, ${cx}, ${cy})`}
273
+ animatedProps={progressAnimProps}
279
274
  />
280
275
  </Svg>
281
276
  );
@@ -289,26 +284,26 @@ function CountdownBubble({
289
284
  value: number;
290
285
  fontFamily: string;
291
286
  }) {
292
- const scale = useRef(new Animated.Value(0)).current;
293
- const opacity = useRef(new Animated.Value(0)).current;
287
+ const scale = useRef(new RNAnimated.Value(0)).current;
288
+ const opacity = useRef(new RNAnimated.Value(0)).current;
294
289
 
295
290
  useEffect(() => {
296
- Animated.parallel([
297
- Animated.sequence([
298
- Animated.spring(scale, {
291
+ RNAnimated.parallel([
292
+ RNAnimated.sequence([
293
+ RNAnimated.spring(scale, {
299
294
  toValue: 1.2,
300
295
  stiffness: 200,
301
296
  damping: 6,
302
297
  useNativeDriver: true,
303
298
  }),
304
- Animated.spring(scale, {
299
+ RNAnimated.spring(scale, {
305
300
  toValue: 1.0,
306
301
  stiffness: 150,
307
302
  damping: 8,
308
303
  useNativeDriver: true,
309
304
  }),
310
305
  ]),
311
- Animated.timing(opacity, {
306
+ RNAnimated.timing(opacity, {
312
307
  toValue: 1,
313
308
  duration: 150,
314
309
  useNativeDriver: true,
@@ -316,7 +311,7 @@ function CountdownBubble({
316
311
  ]).start();
317
312
 
318
313
  return () => {
319
- Animated.timing(opacity, {
314
+ RNAnimated.timing(opacity, {
320
315
  toValue: 0,
321
316
  duration: 200,
322
317
  useNativeDriver: true,
@@ -325,11 +320,11 @@ function CountdownBubble({
325
320
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
326
321
 
327
322
  return (
328
- <Animated.View
323
+ <RNAnimated.View
329
324
  style={[styles.countdownBubble, { opacity, transform: [{ scale }] }]}
330
325
  >
331
326
  <Text style={[styles.countdownText, { fontFamily }]}>{value}</Text>
332
- </Animated.View>
327
+ </RNAnimated.View>
333
328
  );
334
329
  }
335
330