@rick427/react-native-liveness 0.1.8 → 0.1.9

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.
@@ -6,6 +6,8 @@ import { Camera, useCameraDevice, useCameraFormat, useCameraPermission } from 'r
6
6
  import { Circle, Path, Svg } from 'react-native-svg';
7
7
  import { useLivenessCamera } from "./useLivenessCamera.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ const DEFAULT_FONT = 'Baloo-Medium';
10
+
9
11
  // Circle diameter = 82 % of container width — large enough to fit any face
10
12
  // comfortably without the user needing to fiddle with distance.
11
13
  const CIRCLE_DIAMETER_RATIO = 0.82;
@@ -51,13 +53,9 @@ function CircleOverlay({
51
53
  }) {
52
54
  if (width === 0 || height === 0) return null;
53
55
  const cx = width / 2;
54
- // Centre the circle slightly above midpoint so the face sits naturally
55
56
  const cy = height * 0.42;
56
57
  const r = width * CIRCLE_DIAMETER_RATIO / 2;
57
58
  const color = getCircleColor(state, score);
58
-
59
- // Compound path: full-screen rect + circle cutout.
60
- // evenodd fill rule makes the circle area transparent.
61
59
  const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
62
60
  return /*#__PURE__*/_jsxs(Svg, {
63
61
  style: StyleSheet.absoluteFill,
@@ -78,10 +76,9 @@ function CircleOverlay({
78
76
  });
79
77
  }
80
78
  function CountdownBubble({
81
- value
79
+ value,
80
+ fontFamily
82
81
  }) {
83
- // key={countdown} in the parent remounts this component on every tick,
84
- // so [] deps are correct — each mount runs a fresh animation.
85
82
  const scale = useRef(new Animated.Value(0)).current;
86
83
  const opacity = useRef(new Animated.Value(0)).current;
87
84
  useEffect(() => {
@@ -117,7 +114,9 @@ function CountdownBubble({
117
114
  }]
118
115
  }],
119
116
  children: /*#__PURE__*/_jsx(Text, {
120
- style: styles.countdownText,
117
+ style: [styles.countdownText, {
118
+ fontFamily
119
+ }],
121
120
  children: value
122
121
  })
123
122
  });
@@ -130,6 +129,7 @@ export function LivenessCamera({
130
129
  livenessThreshold = 0.75,
131
130
  confirmFrames = 10,
132
131
  soundEnabled = true,
132
+ fontFamily = DEFAULT_FONT,
133
133
  style
134
134
  }) {
135
135
  const {
@@ -137,8 +137,6 @@ export function LivenessCamera({
137
137
  requestPermission
138
138
  } = useCameraPermission();
139
139
  const device = useCameraDevice('front');
140
- // Pick the best format that supports up to 60 fps. Falls back gracefully
141
- // to whatever the device offers if 60 fps isn't available.
142
140
  const format = useCameraFormat(device, [{
143
141
  fps: 60
144
142
  }]);
@@ -185,7 +183,9 @@ export function LivenessCamera({
185
183
  return /*#__PURE__*/_jsx(View, {
186
184
  style: [styles.root, style, styles.centered],
187
185
  children: /*#__PURE__*/_jsx(Text, {
188
- style: styles.permissionText,
186
+ style: [styles.permissionText, {
187
+ fontFamily
188
+ }],
189
189
  children: "Camera permission required"
190
190
  })
191
191
  });
@@ -194,7 +194,9 @@ export function LivenessCamera({
194
194
  return /*#__PURE__*/_jsx(View, {
195
195
  style: [styles.root, style, styles.centered],
196
196
  children: /*#__PURE__*/_jsx(Text, {
197
- style: styles.permissionText,
197
+ style: [styles.permissionText, {
198
+ fontFamily
199
+ }],
198
200
  children: "No front camera found"
199
201
  })
200
202
  });
@@ -220,13 +222,16 @@ export function LivenessCamera({
220
222
  }), livenessState !== 'done' && /*#__PURE__*/_jsx(View, {
221
223
  style: styles.feedbackContainer,
222
224
  children: /*#__PURE__*/_jsx(Text, {
223
- style: styles.feedbackText,
225
+ style: [styles.feedbackText, {
226
+ fontFamily
227
+ }],
224
228
  children: feedback
225
229
  })
226
230
  }), livenessState === 'countdown' && countdown !== null && /*#__PURE__*/_jsx(View, {
227
231
  style: styles.countdownContainer,
228
232
  children: /*#__PURE__*/_jsx(CountdownBubble, {
229
- value: countdown
233
+ value: countdown,
234
+ fontFamily: fontFamily
230
235
  }, countdown)
231
236
  }), livenessState === 'capturing' && /*#__PURE__*/_jsx(View, {
232
237
  style: styles.captureFlash,
@@ -261,7 +266,6 @@ const styles = StyleSheet.create({
261
266
  feedbackText: {
262
267
  color: '#fff',
263
268
  fontSize: 16,
264
- fontWeight: '600',
265
269
  textAlign: 'center',
266
270
  textShadowColor: 'rgba(0,0,0,0.8)',
267
271
  textShadowOffset: {
@@ -288,7 +292,6 @@ const styles = StyleSheet.create({
288
292
  countdownText: {
289
293
  color: '#fff',
290
294
  fontSize: 52,
291
- fontWeight: '700',
292
295
  lineHeight: 60
293
296
  },
294
297
  captureFlash: {
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","Path","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","getCircleColor","state","score","circlePath","cx","cy","r","join","CircleOverlay","width","height","color","scrimD","style","absoluteFill","children","d","fill","fillRule","stroke","strokeWidth","CountdownBubble","value","scale","Value","current","opacity","parallel","sequence","spring","toValue","stiffness","damping","useNativeDriver","timing","duration","start","styles","countdownBubble","transform","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","livenessThreshold","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","Math","min","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","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","fontWeight","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","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","Path","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","getCircleColor","state","score","circlePath","cx","cy","r","join","CircleOverlay","width","height","color","scrimD","style","absoluteFill","children","d","fill","fillRule","stroke","strokeWidth","CountdownBubble","value","fontFamily","scale","Value","current","opacity","parallel","sequence","spring","toValue","stiffness","damping","useNativeDriver","timing","duration","start","styles","countdownBubble","transform","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","livenessThreshold","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","Math","min","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","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":[]}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+
3
+ import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native';
4
+ import { Path, Svg } from 'react-native-svg';
5
+ import { LivenessCamera } from "./LivenessCamera.js";
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ /** × icon drawn with SVG — no external icon library required. */
8
+ function CloseIcon({
9
+ color = '#fff',
10
+ size = 18
11
+ }) {
12
+ const pad = size * 0.1;
13
+ const end = size - pad;
14
+ return /*#__PURE__*/_jsx(Svg, {
15
+ width: size,
16
+ height: size,
17
+ viewBox: `0 0 ${size} ${size}`,
18
+ children: /*#__PURE__*/_jsx(Path, {
19
+ d: `M${pad} ${pad} L${end} ${end} M${end} ${pad} L${pad} ${end}`,
20
+ stroke: color,
21
+ strokeWidth: size * 0.14,
22
+ strokeLinecap: "round"
23
+ })
24
+ });
25
+ }
26
+
27
+ /**
28
+ * Drop-in liveness detection modal.
29
+ *
30
+ * ```tsx
31
+ * <LivenessCameraModal
32
+ * visible={showLiveness}
33
+ * onClose={() => setShowLiveness(false)}
34
+ * onCapture={(result) => console.log(result.photo.path)}
35
+ * animationType="slide"
36
+ * />
37
+ * ```
38
+ */
39
+ export function LivenessCameraModal({
40
+ visible,
41
+ onClose,
42
+ animationType = 'slide',
43
+ closeButtonStyle,
44
+ closeButtonIconColor = '#fff',
45
+ closeButtonIconSize = 18,
46
+ // forward all LivenessCamera props
47
+ onCapture,
48
+ onLivenessConfirmed,
49
+ onError,
50
+ countdownFrom,
51
+ livenessThreshold,
52
+ confirmFrames,
53
+ soundEnabled,
54
+ fontFamily
55
+ }) {
56
+ const handleCapture = result => {
57
+ onCapture(result);
58
+ // Modal stays open — consumer decides when to close via onCapture callback
59
+ };
60
+ return /*#__PURE__*/_jsx(Modal, {
61
+ visible: visible,
62
+ animationType: animationType,
63
+ statusBarTranslucent: true,
64
+ onRequestClose: onClose,
65
+ children: /*#__PURE__*/_jsxs(View, {
66
+ style: styles.container,
67
+ children: [/*#__PURE__*/_jsx(LivenessCamera, {
68
+ style: styles.camera,
69
+ onCapture: handleCapture,
70
+ onLivenessConfirmed: onLivenessConfirmed,
71
+ onError: onError,
72
+ countdownFrom: countdownFrom,
73
+ livenessThreshold: livenessThreshold,
74
+ confirmFrames: confirmFrames,
75
+ soundEnabled: soundEnabled,
76
+ fontFamily: fontFamily
77
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
78
+ style: [styles.closeButton, closeButtonStyle],
79
+ onPress: onClose,
80
+ activeOpacity: 0.7,
81
+ hitSlop: {
82
+ top: 8,
83
+ bottom: 8,
84
+ left: 8,
85
+ right: 8
86
+ },
87
+ children: /*#__PURE__*/_jsx(CloseIcon, {
88
+ color: closeButtonIconColor,
89
+ size: closeButtonIconSize
90
+ })
91
+ })]
92
+ })
93
+ });
94
+ }
95
+ const styles = StyleSheet.create({
96
+ container: {
97
+ flex: 1,
98
+ backgroundColor: '#000'
99
+ },
100
+ camera: {
101
+ flex: 1
102
+ },
103
+ closeButton: {
104
+ position: 'absolute',
105
+ top: 52,
106
+ left: 16,
107
+ width: 48,
108
+ height: 48,
109
+ borderRadius: 24,
110
+ justifyContent: 'center',
111
+ alignItems: 'center',
112
+ backgroundColor: 'rgba(0,0,0,0.5)',
113
+ borderWidth: 1,
114
+ borderColor: 'rgba(255,255,255,0.3)'
115
+ }
116
+ });
117
+ //# sourceMappingURL=LivenessCameraModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Modal","StyleSheet","TouchableOpacity","View","Path","Svg","LivenessCamera","jsx","_jsx","jsxs","_jsxs","CloseIcon","color","size","pad","end","width","height","viewBox","children","d","stroke","strokeWidth","strokeLinecap","LivenessCameraModal","visible","onClose","animationType","closeButtonStyle","closeButtonIconColor","closeButtonIconSize","onCapture","onLivenessConfirmed","onError","countdownFrom","livenessThreshold","confirmFrames","soundEnabled","fontFamily","handleCapture","result","statusBarTranslucent","onRequestClose","style","styles","container","camera","closeButton","onPress","activeOpacity","hitSlop","top","bottom","left","right","create","flex","backgroundColor","position","borderRadius","justifyContent","alignItems","borderWidth","borderColor"],"sourceRoot":"../../src","sources":["LivenessCameraModal.tsx"],"mappings":";;AAAA,SAASA,KAAK,EAAEC,UAAU,EAAEC,gBAAgB,EAAEC,IAAI,QAAQ,cAAc;AACxE,SAASC,IAAI,EAAEC,GAAG,QAAQ,kBAAkB;AAC5C,SAASC,cAAc,QAAQ,qBAAkB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAGlD;AACA,SAASC,SAASA,CAAC;EACjBC,KAAK,GAAG,MAAM;EACdC,IAAI,GAAG;AAIT,CAAC,EAAE;EACD,MAAMC,GAAG,GAAGD,IAAI,GAAG,GAAG;EACtB,MAAME,GAAG,GAAGF,IAAI,GAAGC,GAAG;EACtB,oBACEN,IAAA,CAACH,GAAG;IAACW,KAAK,EAAEH,IAAK;IAACI,MAAM,EAAEJ,IAAK;IAACK,OAAO,EAAE,OAAOL,IAAI,IAAIA,IAAI,EAAG;IAAAM,QAAA,eAC7DX,IAAA,CAACJ,IAAI;MACHgB,CAAC,EAAE,IAAIN,GAAG,IAAIA,GAAG,KAAKC,GAAG,IAAIA,GAAG,KAAKA,GAAG,IAAID,GAAG,KAAKA,GAAG,IAAIC,GAAG,EAAG;MACjEM,MAAM,EAAET,KAAM;MACdU,WAAW,EAAET,IAAI,GAAG,IAAK;MACzBU,aAAa,EAAC;IAAO,CACtB;EAAC,CACC,CAAC;AAEV;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,mBAAmBA,CAAC;EAClCC,OAAO;EACPC,OAAO;EACPC,aAAa,GAAG,OAAO;EACvBC,gBAAgB;EAChBC,oBAAoB,GAAG,MAAM;EAC7BC,mBAAmB,GAAG,EAAE;EACxB;EACAC,SAAS;EACTC,mBAAmB;EACnBC,OAAO;EACPC,aAAa;EACbC,iBAAiB;EACjBC,aAAa;EACbC,YAAY;EACZC;AACwB,CAAC,EAAE;EAC3B,MAAMC,aAAoD,GAAIC,MAAM,IAAK;IACvET,SAAS,CAACS,MAAM,CAAC;IACjB;EACF,CAAC;EAED,oBACEhC,IAAA,CAACR,KAAK;IACJyB,OAAO,EAAEA,OAAQ;IACjBE,aAAa,EAAEA,aAAc;IAC7Bc,oBAAoB;IACpBC,cAAc,EAAEhB,OAAQ;IAAAP,QAAA,eAExBT,KAAA,CAACP,IAAI;MAACwC,KAAK,EAAEC,MAAM,CAACC,SAAU;MAAA1B,QAAA,gBAC5BX,IAAA,CAACF,cAAc;QACbqC,KAAK,EAAEC,MAAM,CAACE,MAAO;QACrBf,SAAS,EAAEQ,aAAc;QACzBP,mBAAmB,EAAEA,mBAAoB;QACzCC,OAAO,EAAEA,OAAQ;QACjBC,aAAa,EAAEA,aAAc;QAC7BC,iBAAiB,EAAEA,iBAAkB;QACrCC,aAAa,EAAEA,aAAc;QAC7BC,YAAY,EAAEA,YAAa;QAC3BC,UAAU,EAAEA;MAAW,CACxB,CAAC,eAEF9B,IAAA,CAACN,gBAAgB;QACfyC,KAAK,EAAE,CAACC,MAAM,CAACG,WAAW,EAAEnB,gBAAgB,CAAE;QAC9CoB,OAAO,EAAEtB,OAAQ;QACjBuB,aAAa,EAAE,GAAI;QACnBC,OAAO,EAAE;UAAEC,GAAG,EAAE,CAAC;UAAEC,MAAM,EAAE,CAAC;UAAEC,IAAI,EAAE,CAAC;UAAEC,KAAK,EAAE;QAAE,CAAE;QAAAnC,QAAA,eAElDX,IAAA,CAACG,SAAS;UAACC,KAAK,EAAEiB,oBAAqB;UAAChB,IAAI,EAAEiB;QAAoB,CAAE;MAAC,CACrD,CAAC;IAAA,CACf;EAAC,CACF,CAAC;AAEZ;AAEA,MAAMc,MAAM,GAAG3C,UAAU,CAACsD,MAAM,CAAC;EAC/BV,SAAS,EAAE;IACTW,IAAI,EAAE,CAAC;IACPC,eAAe,EAAE;EACnB,CAAC;EACDX,MAAM,EAAE;IACNU,IAAI,EAAE;EACR,CAAC;EACDT,WAAW,EAAE;IACXW,QAAQ,EAAE,UAAU;IACpBP,GAAG,EAAE,EAAE;IACPE,IAAI,EAAE,EAAE;IACRrC,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACV0C,YAAY,EAAE,EAAE;IAChBC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBJ,eAAe,EAAE,iBAAiB;IAClCK,WAAW,EAAE,CAAC;IACdC,WAAW,EAAE;EACf;AACF,CAAC,CAAC","ignoreList":[]}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
3
  export { LivenessCamera } from "./LivenessCamera.js";
4
+ export { LivenessCameraModal } from "./LivenessCameraModal.js";
4
5
  export { useLivenessCamera } from "./useLivenessCamera.js";
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["LivenessCamera","useLivenessCamera"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,qBAAkB;AACjD,SAASC,iBAAiB,QAAQ,wBAAqB","ignoreList":[]}
1
+ {"version":3,"names":["LivenessCamera","LivenessCameraModal","useLivenessCamera"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,qBAAkB;AACjD,SAASC,mBAAmB,QAAQ,0BAAuB;AAC3D,SAASC,iBAAiB,QAAQ,wBAAqB","ignoreList":[]}
@@ -1,3 +1,3 @@
1
1
  import type { LivenessCameraProps } from './types';
2
- export declare function LivenessCamera({ onCapture, onLivenessConfirmed, onError, countdownFrom, livenessThreshold, confirmFrames, soundEnabled, style, }: LivenessCameraProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function LivenessCamera({ onCapture, onLivenessConfirmed, onError, countdownFrom, livenessThreshold, confirmFrames, soundEnabled, fontFamily, style, }: LivenessCameraProps): import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=LivenessCamera.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAoIlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,KAAK,GACN,EAAE,mBAAmB,2CAwFrB"}
1
+ {"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAuIlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,UAAyB,EACzB,KAAK,GACN,EAAE,mBAAmB,2CA8FrB"}
@@ -0,0 +1,15 @@
1
+ import type { LivenessCameraModalProps } from './types';
2
+ /**
3
+ * Drop-in liveness detection modal.
4
+ *
5
+ * ```tsx
6
+ * <LivenessCameraModal
7
+ * visible={showLiveness}
8
+ * onClose={() => setShowLiveness(false)}
9
+ * onCapture={(result) => console.log(result.photo.path)}
10
+ * animationType="slide"
11
+ * />
12
+ * ```
13
+ */
14
+ export declare function LivenessCameraModal({ visible, onClose, animationType, closeButtonStyle, closeButtonIconColor, closeButtonIconSize, onCapture, onLivenessConfirmed, onError, countdownFrom, livenessThreshold, confirmFrames, soundEnabled, fontFamily, }: LivenessCameraModalProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=LivenessCameraModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LivenessCameraModal.d.ts","sourceRoot":"","sources":["../../../src/LivenessCameraModal.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAwBxD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,OAAO,EACP,aAAuB,EACvB,gBAAgB,EAChB,oBAA6B,EAC7B,mBAAwB,EAExB,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,UAAU,GACX,EAAE,wBAAwB,2CAqC1B"}
@@ -1,4 +1,5 @@
1
1
  export { LivenessCamera } from './LivenessCamera';
2
+ export { LivenessCameraModal } from './LivenessCameraModal';
2
3
  export { useLivenessCamera } from './useLivenessCamera';
3
- export type { CaptureResult, FaceData, FeedbackMessage, LivenessCameraProps, LivenessState, } from './types';
4
+ export type { CaptureResult, FaceData, FeedbackMessage, LivenessCameraModalProps, LivenessCameraProps, LivenessState, } from './types';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EACV,aAAa,EACb,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EACV,aAAa,EACb,QAAQ,EACR,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { ViewStyle } from 'react-native';
1
+ import type { ModalProps, ViewStyle } from 'react-native';
2
2
  import type { PhotoFile } from 'react-native-vision-camera';
3
3
  export type FaceData = {
4
4
  detected: boolean;
@@ -53,9 +53,41 @@ export type LivenessCameraProps = {
53
53
  */
54
54
  style?: ViewStyle;
55
55
  /**
56
- * Whether to play a shutter sound on capture. Requires react-native-sound
57
- * to be installed. Defaults to true.
56
+ * Whether to play a shutter sound on capture. Defaults to true.
58
57
  */
59
58
  soundEnabled?: boolean;
59
+ /**
60
+ * Font family applied to all text inside the component.
61
+ * Defaults to 'Baloo-Medium'. Set to undefined to use the system font.
62
+ */
63
+ fontFamily?: string;
64
+ };
65
+ export type LivenessCameraModalProps = Omit<LivenessCameraProps, 'style'> & {
66
+ /**
67
+ * Controls modal visibility — pass your own boolean state.
68
+ */
69
+ visible: boolean;
70
+ /**
71
+ * Called when the close button is pressed or the Android back button fires.
72
+ * Use this to set your visible state to false.
73
+ */
74
+ onClose: () => void;
75
+ /**
76
+ * Modal entrance/exit animation. Defaults to 'slide'.
77
+ */
78
+ animationType?: ModalProps['animationType'];
79
+ /**
80
+ * Override styles on the close button container.
81
+ * Useful for adjusting position or size to match your design system.
82
+ */
83
+ closeButtonStyle?: ViewStyle;
84
+ /**
85
+ * Colour of the × icon inside the close button. Defaults to '#fff'.
86
+ */
87
+ closeButtonIconColor?: string;
88
+ /**
89
+ * Size of the × icon in dp. Defaults to 18.
90
+ */
91
+ closeButtonIconSize?: number;
60
92
  };
61
93
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,eAAe,GACvB,kCAAkC,GAClC,aAAa,GACb,mBAAmB,GACnB,qBAAqB,GACrB,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,oBAAoB,GACpB,EAAE,CAAC;AAEP,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE;QACN,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,eAAe,GACvB,kCAAkC,GAClC,aAAa,GACb,mBAAmB,GACnB,qBAAqB,GACrB,eAAe,GACf,YAAY,GACZ,gBAAgB,GAChB,oBAAoB,GACpB,EAAE,CAAC;AAEP,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IAC1E;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;IAE5C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAE7B;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rick427/react-native-liveness",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
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",
@@ -10,6 +10,8 @@ import { Circle, Path, Svg } from 'react-native-svg';
10
10
  import { useLivenessCamera } from './useLivenessCamera';
11
11
  import type { LivenessCameraProps, LivenessState } from './types';
12
12
 
13
+ const DEFAULT_FONT = 'Baloo-Medium';
14
+
13
15
  // Circle diameter = 82 % of container width — large enough to fit any face
14
16
  // comfortably without the user needing to fiddle with distance.
15
17
  const CIRCLE_DIAMETER_RATIO = 0.82;
@@ -69,13 +71,10 @@ function CircleOverlay({
69
71
  if (width === 0 || height === 0) return null;
70
72
 
71
73
  const cx = width / 2;
72
- // Centre the circle slightly above midpoint so the face sits naturally
73
74
  const cy = height * 0.42;
74
75
  const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
75
76
  const color = getCircleColor(state, score);
76
77
 
77
- // Compound path: full-screen rect + circle cutout.
78
- // evenodd fill rule makes the circle area transparent.
79
78
  const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
80
79
 
81
80
  return (
@@ -93,9 +92,13 @@ function CircleOverlay({
93
92
  );
94
93
  }
95
94
 
96
- function CountdownBubble({ value }: { value: number }) {
97
- // key={countdown} in the parent remounts this component on every tick,
98
- // so [] deps are correct — each mount runs a fresh animation.
95
+ function CountdownBubble({
96
+ value,
97
+ fontFamily,
98
+ }: {
99
+ value: number;
100
+ fontFamily: string;
101
+ }) {
99
102
  const scale = useRef(new Animated.Value(0)).current;
100
103
  const opacity = useRef(new Animated.Value(0)).current;
101
104
 
@@ -135,7 +138,7 @@ function CountdownBubble({ value }: { value: number }) {
135
138
  <Animated.View
136
139
  style={[styles.countdownBubble, { opacity, transform: [{ scale }] }]}
137
140
  >
138
- <Text style={styles.countdownText}>{value}</Text>
141
+ <Text style={[styles.countdownText, { fontFamily }]}>{value}</Text>
139
142
  </Animated.View>
140
143
  );
141
144
  }
@@ -148,12 +151,11 @@ export function LivenessCamera({
148
151
  livenessThreshold = 0.75,
149
152
  confirmFrames = 10,
150
153
  soundEnabled = true,
154
+ fontFamily = DEFAULT_FONT,
151
155
  style,
152
156
  }: LivenessCameraProps) {
153
157
  const { hasPermission, requestPermission } = useCameraPermission();
154
158
  const device = useCameraDevice('front');
155
- // Pick the best format that supports up to 60 fps. Falls back gracefully
156
- // to whatever the device offers if 60 fps isn't available.
157
159
  const format = useCameraFormat(device, [{ fps: 60 }]);
158
160
  const fps = Math.min(format?.maxFps ?? 30, 60);
159
161
  const cameraRef = useRef<Camera>(null);
@@ -190,7 +192,9 @@ export function LivenessCamera({
190
192
  if (!hasPermission) {
191
193
  return (
192
194
  <View style={[styles.root, style, styles.centered]}>
193
- <Text style={styles.permissionText}>Camera permission required</Text>
195
+ <Text style={[styles.permissionText, { fontFamily }]}>
196
+ Camera permission required
197
+ </Text>
194
198
  </View>
195
199
  );
196
200
  }
@@ -198,7 +202,9 @@ export function LivenessCamera({
198
202
  if (!device) {
199
203
  return (
200
204
  <View style={[styles.root, style, styles.centered]}>
201
- <Text style={styles.permissionText}>No front camera found</Text>
205
+ <Text style={[styles.permissionText, { fontFamily }]}>
206
+ No front camera found
207
+ </Text>
202
208
  </View>
203
209
  );
204
210
  }
@@ -224,12 +230,16 @@ export function LivenessCamera({
224
230
  />
225
231
  {livenessState !== 'done' && (
226
232
  <View style={styles.feedbackContainer}>
227
- <Text style={styles.feedbackText}>{feedback}</Text>
233
+ <Text style={[styles.feedbackText, { fontFamily }]}>{feedback}</Text>
228
234
  </View>
229
235
  )}
230
236
  {livenessState === 'countdown' && countdown !== null && (
231
237
  <View style={styles.countdownContainer}>
232
- <CountdownBubble key={countdown} value={countdown} />
238
+ <CountdownBubble
239
+ key={countdown}
240
+ value={countdown}
241
+ fontFamily={fontFamily}
242
+ />
233
243
  </View>
234
244
  )}
235
245
  {livenessState === 'capturing' && (
@@ -266,7 +276,6 @@ const styles = StyleSheet.create({
266
276
  feedbackText: {
267
277
  color: '#fff',
268
278
  fontSize: 16,
269
- fontWeight: '600',
270
279
  textAlign: 'center',
271
280
  textShadowColor: 'rgba(0,0,0,0.8)',
272
281
  textShadowOffset: { width: 0, height: 1 },
@@ -290,7 +299,6 @@ const styles = StyleSheet.create({
290
299
  countdownText: {
291
300
  color: '#fff',
292
301
  fontSize: 52,
293
- fontWeight: '700',
294
302
  lineHeight: 60,
295
303
  },
296
304
  captureFlash: {
@@ -0,0 +1,116 @@
1
+ import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native';
2
+ import { Path, Svg } from 'react-native-svg';
3
+ import { LivenessCamera } from './LivenessCamera';
4
+ import type { LivenessCameraModalProps } from './types';
5
+
6
+ /** × icon drawn with SVG — no external icon library required. */
7
+ function CloseIcon({
8
+ color = '#fff',
9
+ size = 18,
10
+ }: {
11
+ color?: string;
12
+ size?: number;
13
+ }) {
14
+ const pad = size * 0.1;
15
+ const end = size - pad;
16
+ return (
17
+ <Svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
18
+ <Path
19
+ d={`M${pad} ${pad} L${end} ${end} M${end} ${pad} L${pad} ${end}`}
20
+ stroke={color}
21
+ strokeWidth={size * 0.14}
22
+ strokeLinecap="round"
23
+ />
24
+ </Svg>
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Drop-in liveness detection modal.
30
+ *
31
+ * ```tsx
32
+ * <LivenessCameraModal
33
+ * visible={showLiveness}
34
+ * onClose={() => setShowLiveness(false)}
35
+ * onCapture={(result) => console.log(result.photo.path)}
36
+ * animationType="slide"
37
+ * />
38
+ * ```
39
+ */
40
+ export function LivenessCameraModal({
41
+ visible,
42
+ onClose,
43
+ animationType = 'slide',
44
+ closeButtonStyle,
45
+ closeButtonIconColor = '#fff',
46
+ closeButtonIconSize = 18,
47
+ // forward all LivenessCamera props
48
+ onCapture,
49
+ onLivenessConfirmed,
50
+ onError,
51
+ countdownFrom,
52
+ livenessThreshold,
53
+ confirmFrames,
54
+ soundEnabled,
55
+ fontFamily,
56
+ }: LivenessCameraModalProps) {
57
+ const handleCapture: LivenessCameraModalProps['onCapture'] = (result) => {
58
+ onCapture(result);
59
+ // Modal stays open — consumer decides when to close via onCapture callback
60
+ };
61
+
62
+ return (
63
+ <Modal
64
+ visible={visible}
65
+ animationType={animationType}
66
+ statusBarTranslucent
67
+ onRequestClose={onClose}
68
+ >
69
+ <View style={styles.container}>
70
+ <LivenessCamera
71
+ style={styles.camera}
72
+ onCapture={handleCapture}
73
+ onLivenessConfirmed={onLivenessConfirmed}
74
+ onError={onError}
75
+ countdownFrom={countdownFrom}
76
+ livenessThreshold={livenessThreshold}
77
+ confirmFrames={confirmFrames}
78
+ soundEnabled={soundEnabled}
79
+ fontFamily={fontFamily}
80
+ />
81
+
82
+ <TouchableOpacity
83
+ style={[styles.closeButton, closeButtonStyle]}
84
+ onPress={onClose}
85
+ activeOpacity={0.7}
86
+ hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
87
+ >
88
+ <CloseIcon color={closeButtonIconColor} size={closeButtonIconSize} />
89
+ </TouchableOpacity>
90
+ </View>
91
+ </Modal>
92
+ );
93
+ }
94
+
95
+ const styles = StyleSheet.create({
96
+ container: {
97
+ flex: 1,
98
+ backgroundColor: '#000',
99
+ },
100
+ camera: {
101
+ flex: 1,
102
+ },
103
+ closeButton: {
104
+ position: 'absolute',
105
+ top: 52,
106
+ left: 16,
107
+ width: 48,
108
+ height: 48,
109
+ borderRadius: 24,
110
+ justifyContent: 'center',
111
+ alignItems: 'center',
112
+ backgroundColor: 'rgba(0,0,0,0.5)',
113
+ borderWidth: 1,
114
+ borderColor: 'rgba(255,255,255,0.3)',
115
+ },
116
+ });
package/src/index.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export { LivenessCamera } from './LivenessCamera';
2
+ export { LivenessCameraModal } from './LivenessCameraModal';
2
3
  export { useLivenessCamera } from './useLivenessCamera';
3
4
  export type {
4
5
  CaptureResult,
5
6
  FaceData,
6
7
  FeedbackMessage,
8
+ LivenessCameraModalProps,
7
9
  LivenessCameraProps,
8
10
  LivenessState,
9
11
  } from './types';
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ViewStyle } from 'react-native';
1
+ import type { ModalProps, ViewStyle } from 'react-native';
2
2
  import type { PhotoFile } from 'react-native-vision-camera';
3
3
 
4
4
  export type FaceData = {
@@ -81,8 +81,47 @@ export type LivenessCameraProps = {
81
81
  style?: ViewStyle;
82
82
 
83
83
  /**
84
- * Whether to play a shutter sound on capture. Requires react-native-sound
85
- * to be installed. Defaults to true.
84
+ * Whether to play a shutter sound on capture. Defaults to true.
86
85
  */
87
86
  soundEnabled?: boolean;
87
+
88
+ /**
89
+ * Font family applied to all text inside the component.
90
+ * Defaults to 'Baloo-Medium'. Set to undefined to use the system font.
91
+ */
92
+ fontFamily?: string;
93
+ };
94
+
95
+ export type LivenessCameraModalProps = Omit<LivenessCameraProps, 'style'> & {
96
+ /**
97
+ * Controls modal visibility — pass your own boolean state.
98
+ */
99
+ visible: boolean;
100
+
101
+ /**
102
+ * Called when the close button is pressed or the Android back button fires.
103
+ * Use this to set your visible state to false.
104
+ */
105
+ onClose: () => void;
106
+
107
+ /**
108
+ * Modal entrance/exit animation. Defaults to 'slide'.
109
+ */
110
+ animationType?: ModalProps['animationType'];
111
+
112
+ /**
113
+ * Override styles on the close button container.
114
+ * Useful for adjusting position or size to match your design system.
115
+ */
116
+ closeButtonStyle?: ViewStyle;
117
+
118
+ /**
119
+ * Colour of the × icon inside the close button. Defaults to '#fff'.
120
+ */
121
+ closeButtonIconColor?: string;
122
+
123
+ /**
124
+ * Size of the × icon in dp. Defaults to 18.
125
+ */
126
+ closeButtonIconSize?: number;
88
127
  };