@test-glide/payment-react-native 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +1 -1
  2. package/lib/module/components/BivoCVCInput.js +21 -28
  3. package/lib/module/components/BivoCVCInput.js.map +1 -1
  4. package/lib/module/components/BivoCardInput.js +27 -34
  5. package/lib/module/components/BivoCardInput.js.map +1 -1
  6. package/lib/module/components/BivoTextInput.js +22 -29
  7. package/lib/module/components/BivoTextInput.js.map +1 -1
  8. package/lib/module/core/{Collector.js → BivoSecureStore.js} +40 -27
  9. package/lib/module/core/BivoSecureStore.js.map +1 -0
  10. package/lib/module/index.js +1 -1
  11. package/lib/module/index.js.map +1 -1
  12. package/lib/typescript/src/components/BivoCVCInput.d.ts +4 -4
  13. package/lib/typescript/src/components/BivoCVCInput.d.ts.map +1 -1
  14. package/lib/typescript/src/components/BivoCardInput.d.ts +4 -4
  15. package/lib/typescript/src/components/BivoCardInput.d.ts.map +1 -1
  16. package/lib/typescript/src/components/BivoTextInput.d.ts +4 -4
  17. package/lib/typescript/src/components/BivoTextInput.d.ts.map +1 -1
  18. package/lib/typescript/src/core/{Collector.d.ts → BivoSecureStore.d.ts} +5 -13
  19. package/lib/typescript/src/core/BivoSecureStore.d.ts.map +1 -0
  20. package/lib/typescript/src/index.d.ts +1 -1
  21. package/lib/typescript/src/index.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/src/components/BivoCVCInput.tsx +41 -26
  24. package/src/components/BivoCardInput.tsx +60 -38
  25. package/src/components/BivoTextInput.tsx +80 -66
  26. package/src/core/BivoSecureStore.ts +164 -0
  27. package/src/index.ts +1 -1
  28. package/lib/module/core/Collector.js.map +0 -1
  29. package/lib/typescript/src/core/Collector.d.ts.map +0 -1
  30. package/src/core/Collector.ts +0 -130
@@ -1,8 +1,8 @@
1
- import React from "react";
2
- import type { ViewStyle, TextStyle } from "react-native";
3
- import type { BivoCollect } from "../core/Collector";
1
+ import React from 'react';
2
+ import type { ViewStyle, TextStyle } from 'react-native';
3
+ import type { BivoSecureStore } from '../core/BivoSecureStore';
4
4
  interface Props {
5
- collector: BivoCollect;
5
+ bivoStore: BivoSecureStore;
6
6
  fieldName: string;
7
7
  placeholder?: string;
8
8
  onStateChange?: (state: any) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"BivoTextInput.d.ts","sourceRoot":"","sources":["../../../../src/components/BivoTextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD,UAAU,KAAK;IACX,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAmDzC,CAAC"}
1
+ {"version":3,"file":"BivoTextInput.d.ts","sourceRoot":"","sources":["../../../../src/components/BivoTextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,UAAU,KAAK;IACb,SAAS,EAAE,eAAe,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA6DzC,CAAC"}
@@ -2,9 +2,9 @@ type FieldState = {
2
2
  value: string;
3
3
  error?: string;
4
4
  };
5
- export declare class BivoCollect {
5
+ export declare class BivoSecureStore {
6
6
  vaultId: string;
7
- environment: "sandbox" | "live";
7
+ environment: 'sandbox' | 'live';
8
8
  form: Record<string, string>;
9
9
  errors: Record<string, string>;
10
10
  fieldConfig: Record<string, {
@@ -12,19 +12,11 @@ export declare class BivoCollect {
12
12
  regex?: RegExp;
13
13
  errorMsg?: string;
14
14
  }>;
15
- constructor(vaultId: string, environment: "sandbox" | "live");
15
+ constructor(vaultId: string, environment: 'sandbox' | 'live');
16
16
  setField(fieldName: string, value: string, onStateChange?: (state: FieldState) => void, required?: boolean, regex?: RegExp, errorMsg?: string): void;
17
17
  validateField(fieldName: string, value: string, required?: boolean, regex?: RegExp, errorMsg?: string): string;
18
18
  isSubmitDisabled(fieldNames: string[]): boolean;
19
- submit(endpoint: string, token: string): Promise<{
20
- success: boolean;
21
- error: string;
22
- data?: undefined;
23
- } | {
24
- success: boolean;
25
- data: unknown;
26
- error?: undefined;
27
- }>;
19
+ submit(endpoint: string, token: string): Promise<any>;
28
20
  }
29
21
  export {};
30
- //# sourceMappingURL=Collector.d.ts.map
22
+ //# sourceMappingURL=BivoSecureStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BivoSecureStore.d.ts","sourceRoot":"","sources":["../../../../src/core/BivoSecureStore.ts"],"names":[],"mappings":"AAGA,KAAK,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,qBAAa,eAAe;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IACpC,WAAW,EAAE,MAAM,CACjB,MAAM,EACN;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAC1D,CAAM;gBAEK,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,GAAG,MAAM;IAK5D,QAAQ,CACN,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EAC3C,QAAQ,GAAE,OAAe,EACzB,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM;IA2BnB,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,OAAO,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM;IAqEnB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE;IAQ/B,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAE,OAAO,CAAC,GAAG,CAAC;CA4B3D"}
@@ -1,4 +1,4 @@
1
- export { BivoCollect } from "./core/Collector";
1
+ export { BivoSecureStore } from "./core/BivoSecureStore";
2
2
  export { BivoTextInput } from "./components/BivoTextInput";
3
3
  export { BivoCardInput } from "./components/BivoCardInput";
4
4
  export { BivoCVCInput } from "./components/BivoCVCInput";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@test-glide/payment-react-native",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "bivo payment",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -1,11 +1,11 @@
1
- import React, { useState } from "react";
2
- import { View, TextInput, Text, StyleSheet, Image } from "react-native";
3
- import type { ViewStyle, TextStyle } from "react-native";
4
- import { BivoCollect } from "../core/Collector";
5
- import { Icons } from "../assets";
1
+ import React, { useState } from 'react';
2
+ import { View, TextInput, Text, StyleSheet, Image } from 'react-native';
3
+ import type { ViewStyle, TextStyle } from 'react-native';
4
+ import { BivoSecureStore } from '../core/BivoSecureStore';
5
+ import { Icons } from '../assets';
6
6
 
7
7
  interface Props {
8
- collector: BivoCollect;
8
+ bivoStore: BivoSecureStore;
9
9
  fieldName: string;
10
10
  placeholder?: string;
11
11
  onStateChange?: (state: any) => void;
@@ -17,7 +17,7 @@ interface Props {
17
17
  }
18
18
 
19
19
  export const BivoCVCInput: React.FC<Props> = ({
20
- collector,
20
+ bivoStore,
21
21
  fieldName,
22
22
  placeholder,
23
23
  onStateChange,
@@ -27,18 +27,32 @@ export const BivoCVCInput: React.FC<Props> = ({
27
27
  containerStyle,
28
28
  textStyle,
29
29
  }) => {
30
- const [value, setValue] = useState("");
30
+ const [value, setValue] = useState('');
31
31
 
32
32
  const handleChange = (text: string) => {
33
33
  setValue(text);
34
- collector.setField(fieldName, text, onStateChange, required, regex, errorMsg);
34
+ bivoStore.setField(
35
+ fieldName,
36
+ text,
37
+ onStateChange,
38
+ required,
39
+ regex,
40
+ errorMsg
41
+ );
35
42
  };
36
43
 
37
44
  const handleBlur = () => {
38
- collector.setField(fieldName, value, onStateChange, required, regex, errorMsg);
45
+ bivoStore.setField(
46
+ fieldName,
47
+ value,
48
+ onStateChange,
49
+ required,
50
+ regex,
51
+ errorMsg
52
+ );
39
53
  };
40
54
 
41
- const error = collector.errors[fieldName];
55
+ const error = bivoStore.errors[fieldName];
42
56
 
43
57
  return (
44
58
  <View style={[styles.container, containerStyle]}>
@@ -49,26 +63,27 @@ export const BivoCVCInput: React.FC<Props> = ({
49
63
  placeholder={placeholder}
50
64
  secureTextEntry
51
65
  keyboardType="number-pad"
52
- style={[styles.input, textStyle, error ? { borderColor: "red" } : {}]}
66
+ style={[styles.input, textStyle, error ? { borderColor: 'red' } : {}]}
53
67
  />
54
- <View style={styles.errorContainer}>
55
- {error ? (
56
- <>
57
- <Image source={Icons.alert} style={styles.errorIcon} />
58
- <Text style={styles.error}>{error}</Text>
59
- </>
60
- ) : (
61
- <Text style={[styles.error, { opacity: 0 }]}>placeholder</Text>
62
- )}
63
- </View>
68
+ {error && (
69
+ <View style={styles.errorContainer}>
70
+ <Image source={Icons.alert} style={styles.errorIcon} />
71
+ <Text style={styles.error}>{error}</Text>
72
+ </View>
73
+ )}
64
74
  </View>
65
75
  );
66
76
  };
67
77
 
68
78
  const styles = StyleSheet.create({
69
79
  container: { marginVertical: 8 },
70
- input: { borderWidth: 1, borderColor: "#ccc", borderRadius: 6, padding: 10 },
71
- errorContainer: { flexDirection: "row", alignItems: "center", marginTop: 4, minHeight: 12 },
80
+ input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 6, padding: 10 },
81
+ errorContainer: {
82
+ flexDirection: 'row',
83
+ alignItems: 'center',
84
+ marginTop: 4,
85
+ minHeight: 12,
86
+ },
72
87
  errorIcon: { width: 12, height: 12, marginRight: 4 },
73
- error: { color: "red", fontSize: 12 },
74
- });
88
+ error: { color: 'red', fontSize: 12 },
89
+ });
@@ -1,12 +1,12 @@
1
- import React, { useState } from "react";
2
- import { View, TextInput, Image, Text, StyleSheet} from "react-native";
3
- import type { ViewStyle, TextStyle } from "react-native";
4
- import { BivoCollect } from "../core/Collector";
5
- import { Icons } from "../assets";
6
- import { formatCardNumber } from "../utils/utils";
1
+ import React, { useState } from 'react';
2
+ import { View, TextInput, Image, Text, StyleSheet } from 'react-native';
3
+ import type { ViewStyle, TextStyle } from 'react-native';
4
+ import { BivoSecureStore } from '../core/BivoSecureStore';
5
+ import { Icons } from '../assets';
6
+ import { formatCardNumber } from '../utils/utils';
7
7
 
8
8
  interface Props {
9
- collector: BivoCollect;
9
+ bivoStore: BivoSecureStore;
10
10
  fieldName: string;
11
11
  placeholder?: string;
12
12
  onStateChange?: (state: any) => void;
@@ -17,8 +17,8 @@ interface Props {
17
17
  textStyle?: TextStyle;
18
18
  }
19
19
 
20
- const cardIcons:any = {
21
- visa:Icons.visa,
20
+ const cardIcons: any = {
21
+ visa: Icons.visa,
22
22
  mastercard: Icons.mastercard,
23
23
  amex: Icons.amex,
24
24
  discover: Icons.discover,
@@ -26,7 +26,7 @@ const cardIcons:any = {
26
26
  };
27
27
 
28
28
  export const BivoCardInput: React.FC<Props> = ({
29
- collector,
29
+ bivoStore,
30
30
  fieldName,
31
31
  placeholder,
32
32
  onStateChange,
@@ -36,27 +36,41 @@ export const BivoCardInput: React.FC<Props> = ({
36
36
  containerStyle,
37
37
  textStyle,
38
38
  }) => {
39
- const [value, setValue] = useState("");
40
- const [cardType, setCardType] = useState("unknown"); //cardType
39
+ const [value, setValue] = useState('');
40
+ const [cardType, setCardType] = useState('unknown'); //cardType
41
41
 
42
42
  const handleChange = (text: string) => {
43
43
  const formatted = formatCardNumber(text);
44
44
  setValue(formatted);
45
- const cleaned = text.replace(/\D/g, "");
46
- if (/^4/.test(cleaned)) setCardType("visa");
47
- else if (/^5[1-5]/.test(cleaned)) setCardType("mastercard");
48
- else if (/^3[47]/.test(cleaned)) setCardType("amex");
49
- else if (/^6(?:011|5)/.test(cleaned)) setCardType("discover");
50
- else setCardType("unknown");
45
+ const cleaned = text.replace(/\D/g, '');
46
+ if (/^4/.test(cleaned)) setCardType('visa');
47
+ else if (/^5[1-5]/.test(cleaned)) setCardType('mastercard');
48
+ else if (/^3[47]/.test(cleaned)) setCardType('amex');
49
+ else if (/^6(?:011|5)/.test(cleaned)) setCardType('discover');
50
+ else setCardType('unknown');
51
51
 
52
- collector.setField(fieldName, text, onStateChange, required, regex, errorMsg);
52
+ bivoStore.setField(
53
+ fieldName,
54
+ text,
55
+ onStateChange,
56
+ required,
57
+ regex,
58
+ errorMsg
59
+ );
53
60
  };
54
61
 
55
62
  const handleBlur = () => {
56
- collector.setField(fieldName, value, onStateChange, required, regex, errorMsg);
63
+ bivoStore.setField(
64
+ fieldName,
65
+ value,
66
+ onStateChange,
67
+ required,
68
+ regex,
69
+ errorMsg
70
+ );
57
71
  };
58
72
 
59
- const error = collector.errors[fieldName];
73
+ const error = bivoStore.errors[fieldName];
60
74
 
61
75
  return (
62
76
  <View style={[styles.container, containerStyle]}>
@@ -68,29 +82,37 @@ export const BivoCardInput: React.FC<Props> = ({
68
82
  onBlur={handleBlur}
69
83
  placeholder={placeholder}
70
84
  keyboardType="number-pad"
71
- style={[styles.input, textStyle, error ? { borderColor: "red" } : {}]}
85
+ style={[styles.input, textStyle, error ? { borderColor: 'red' } : {}]}
72
86
  />
73
87
  </View>
74
- <View style={styles.errorContainer}>
75
- {error ? (
76
- <>
77
- <Image source={Icons.alert} style={styles.errorIcon} />
78
- <Text style={styles.error}>{error}</Text>
79
- </>
80
- ) : (
81
- <Text style={[styles.error, { opacity: 0 }]}>placeholder</Text>
82
- )}
83
- </View>
88
+ {error && (
89
+ <View style={styles.errorContainer}>
90
+ <Image source={Icons.alert} style={styles.errorIcon} />
91
+ <Text style={styles.error}>{error}</Text>
92
+ </View>
93
+ )}
84
94
  </View>
85
95
  );
86
96
  };
87
97
 
88
98
  const styles = StyleSheet.create({
89
99
  container: { marginVertical: 8 },
90
- row: { flexDirection: "row", alignItems: "center" },
91
- input: { flex: 1, borderWidth: 1, borderColor: "#ccc", borderRadius: 6, padding: 10 },
92
- icon: { width: 40, height: 25, resizeMode: "contain", marginRight: 8 },
93
- errorContainer: { flexDirection: "row", alignItems: "center",marginLeft:40, marginTop: 4, minHeight: 12 },
100
+ row: { flexDirection: 'row', alignItems: 'center' },
101
+ input: {
102
+ flex: 1,
103
+ borderWidth: 1,
104
+ borderColor: '#ccc',
105
+ borderRadius: 6,
106
+ padding: 10,
107
+ },
108
+ icon: { width: 40, height: 25, resizeMode: 'contain', marginRight: 8 },
109
+ errorContainer: {
110
+ flexDirection: 'row',
111
+ alignItems: 'center',
112
+ marginLeft: 40,
113
+ marginTop: 4,
114
+ minHeight: 12,
115
+ },
94
116
  errorIcon: { width: 12, height: 12, marginRight: 4 },
95
- error: { color: "red", fontSize: 12 },
96
- });
117
+ error: { color: 'red', fontSize: 12 },
118
+ });
@@ -1,80 +1,94 @@
1
- import React, { useState } from "react";
2
- import { View, TextInput, Text, StyleSheet, Image } from "react-native";
3
- import type { ViewStyle, TextStyle } from "react-native";
4
- import type { BivoCollect } from "../core/Collector";
5
- import { Icons } from "../assets";
6
- import { formatExpiry } from "../utils/utils";
7
-
1
+ import React, { useState } from 'react';
2
+ import { View, TextInput, Text, StyleSheet, Image } from 'react-native';
3
+ import type { ViewStyle, TextStyle } from 'react-native';
4
+ import type { BivoSecureStore } from '../core/BivoSecureStore';
5
+ import { Icons } from '../assets';
6
+ import { formatExpiry } from '../utils/utils';
8
7
 
9
8
  interface Props {
10
- collector: BivoCollect;
11
- fieldName: string;
12
- placeholder?: string;
13
- onStateChange?: (state: any) => void;
14
- required?: boolean;
15
- regex?: RegExp;
16
- errorMsg?: string;
17
- containerStyle?: ViewStyle;
18
- textStyle?: TextStyle;
9
+ bivoStore: BivoSecureStore;
10
+ fieldName: string;
11
+ placeholder?: string;
12
+ onStateChange?: (state: any) => void;
13
+ required?: boolean;
14
+ regex?: RegExp;
15
+ errorMsg?: string;
16
+ containerStyle?: ViewStyle;
17
+ textStyle?: TextStyle;
19
18
  }
20
19
 
21
20
  export const BivoTextInput: React.FC<Props> = ({
22
- collector,
23
- fieldName,
24
- placeholder,
25
- onStateChange,
26
- required,
27
- regex,
28
- errorMsg,
29
- containerStyle,
30
- textStyle,
21
+ bivoStore,
22
+ fieldName,
23
+ placeholder,
24
+ onStateChange,
25
+ required,
26
+ regex,
27
+ errorMsg,
28
+ containerStyle,
29
+ textStyle,
31
30
  }) => {
32
- const [value, setValue] = useState("");
31
+ const [value, setValue] = useState('');
33
32
 
34
- const handleChange = (text: string) => {
35
- let updatedValue;
36
- if (fieldName === "exp") {
37
- updatedValue = formatExpiry(text);
38
- } else {
39
- updatedValue = text;
40
- }
41
- setValue(updatedValue);
42
- collector.setField(fieldName, updatedValue, onStateChange, required, regex, errorMsg);
43
- };
33
+ const handleChange = (text: string) => {
34
+ let updatedValue;
35
+ if (fieldName === 'exp') {
36
+ updatedValue = formatExpiry(text);
37
+ } else {
38
+ updatedValue = text;
39
+ }
40
+ setValue(updatedValue);
41
+ bivoStore.setField(
42
+ fieldName,
43
+ updatedValue,
44
+ onStateChange,
45
+ required,
46
+ regex,
47
+ errorMsg
48
+ );
49
+ };
44
50
 
45
- const handleBlur = () => {
46
- collector.setField(fieldName, value, onStateChange, required, regex, errorMsg);
47
- };
51
+ const handleBlur = () => {
52
+ bivoStore.setField(
53
+ fieldName,
54
+ value,
55
+ onStateChange,
56
+ required,
57
+ regex,
58
+ errorMsg
59
+ );
60
+ };
48
61
 
49
- const error = collector.errors[fieldName];
62
+ const error = bivoStore.errors[fieldName];
50
63
 
51
- return (
52
- <View style={[styles.container, containerStyle]}>
53
- <TextInput
54
- value={value}
55
- onChangeText={handleChange}
56
- onBlur={handleBlur}
57
- placeholder={placeholder}
58
- style={[styles.input, textStyle, error ? { borderColor: "red" } : {}]}
59
- />
60
- <View style={styles.errorContainer}>
61
- {error ? (
62
- <>
63
- <Image source={Icons.alert} style={styles.errorIcon} />
64
- <Text style={styles.error}>{error}</Text>
65
- </>
66
- ) : (
67
- <Text style={[styles.error, { opacity: 0 }]}>placeholder</Text>
68
- )}
69
- </View>
64
+ return (
65
+ <View style={[styles.container, containerStyle]}>
66
+ <TextInput
67
+ value={value}
68
+ onChangeText={handleChange}
69
+ onBlur={handleBlur}
70
+ placeholder={placeholder}
71
+ style={[styles.input, textStyle, error ? { borderColor: 'red' } : {}]}
72
+ />
73
+ {error && (
74
+ <View style={styles.errorContainer}>
75
+ <Image source={Icons.alert} style={styles.errorIcon} />
76
+ <Text style={styles.error}>{error}</Text>
70
77
  </View>
71
- );
78
+ )}
79
+ </View>
80
+ );
72
81
  };
73
82
 
74
83
  const styles = StyleSheet.create({
75
- container: { marginVertical: 8 },
76
- input: { borderWidth: 1, borderColor: "#ccc", borderRadius: 6, padding: 10 },
77
- errorContainer: { flexDirection: "row", alignItems: "center", marginTop: 4, minHeight: 12 },
78
- errorIcon: { width: 12, height: 12, marginRight: 4 },
79
- error: { color: "red", fontSize: 12 },
80
- });
84
+ container: { marginVertical: 8 },
85
+ input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 6, padding: 10 },
86
+ errorContainer: {
87
+ flexDirection: 'row',
88
+ alignItems: 'center',
89
+ marginTop: 4,
90
+ minHeight: 12,
91
+ },
92
+ errorIcon: { width: 12, height: 12, marginRight: 4 },
93
+ error: { color: 'red', fontSize: 12 },
94
+ });
@@ -0,0 +1,164 @@
1
+ import { fetchData } from '../utils/fetch';
2
+ import { formatCardYear, formatString } from '../utils/utils';
3
+
4
+ type FieldState = { value: string; error?: string };
5
+
6
+ export class BivoSecureStore {
7
+ vaultId: string;
8
+ environment: 'sandbox' | 'live';
9
+ form: Record<string, string> = {};
10
+ errors: Record<string, string> = {};
11
+ fieldConfig: Record<
12
+ string,
13
+ { required?: boolean; regex?: RegExp; errorMsg?: string }
14
+ > = {};
15
+
16
+ constructor(vaultId: string, environment: 'sandbox' | 'live') {
17
+ this.vaultId = vaultId;
18
+ this.environment = environment;
19
+ }
20
+
21
+ setField(
22
+ fieldName: string,
23
+ value: string,
24
+ onStateChange?: (state: FieldState) => void,
25
+ required: boolean = false,
26
+ regex?: RegExp,
27
+ errorMsg?: string
28
+ ) {
29
+ this.form[fieldName] = value;
30
+ // convert string regex to RegExp
31
+ let parsedRegex: RegExp | undefined = undefined;
32
+
33
+ if (typeof regex === 'string') {
34
+ try {
35
+ parsedRegex = new RegExp(regex);
36
+ } catch (e) {
37
+ console.error('Invalid regex:', regex, e);
38
+ }
39
+ } else {
40
+ parsedRegex = regex;
41
+ }
42
+ this.fieldConfig[fieldName] = { required, regex: parsedRegex, errorMsg };
43
+ const error = this.validateField(
44
+ fieldName,
45
+ value,
46
+ required,
47
+ parsedRegex,
48
+ errorMsg
49
+ );
50
+ this.errors[fieldName] = error || '';
51
+ onStateChange?.({ value, error });
52
+ }
53
+
54
+ validateField(
55
+ fieldName: string,
56
+ value: string,
57
+ required?: boolean,
58
+ regex?: RegExp,
59
+ errorMsg?: string
60
+ ) {
61
+ const trimmedValue = value?.trim();
62
+
63
+ // Required check
64
+ if (!trimmedValue && required) return 'Required';
65
+
66
+ // If custom regex is provided → use it first
67
+ if (regex && trimmedValue) {
68
+ if (!regex.test(trimmedValue)) {
69
+ return errorMsg || 'Invalid value';
70
+ }
71
+ return '';
72
+ }
73
+
74
+ // Default validations
75
+ switch (fieldName) {
76
+ case 'card': {
77
+ const digits = trimmedValue.replace(/\D/g, '');
78
+ if (digits.length < 12) return 'Invalid card number';
79
+ break;
80
+ }
81
+
82
+ case 'cvv': {
83
+ if (!/^\d{3,4}$/.test(trimmedValue)) {
84
+ return 'Invalid CVV';
85
+ }
86
+ break;
87
+ }
88
+
89
+ case 'exp': {
90
+ // Format check MM/YY
91
+ if (!/^\d{2}\/\d{2}$/.test(trimmedValue)) {
92
+ return 'Invalid expiry';
93
+ }
94
+
95
+ const [monthStr, yearStr] = trimmedValue.split('/');
96
+ if (!monthStr || !yearStr) {
97
+ return 'Invalid expiry';
98
+ }
99
+ const month = parseInt(monthStr, 10);
100
+ const year = parseInt(yearStr, 10);
101
+
102
+ if (month < 1 || month > 12) {
103
+ return 'Invalid month';
104
+ }
105
+
106
+ // Convert YY → YYYY (assume 2000-2099)
107
+ const fullYear = 2000 + year;
108
+
109
+ const now = new Date();
110
+ const currentMonth = now.getMonth() + 1;
111
+ const currentYear = now.getFullYear();
112
+
113
+ // Expiry check
114
+ if (
115
+ fullYear < currentYear ||
116
+ (fullYear === currentYear && month < currentMonth)
117
+ ) {
118
+ return 'Card expired';
119
+ }
120
+
121
+ break;
122
+ }
123
+ }
124
+
125
+ return '';
126
+ }
127
+
128
+ isSubmitDisabled(fieldNames: string[]) {
129
+ return fieldNames.some((fieldName) => {
130
+ const value = this.form[fieldName]?.trim() ?? '';
131
+ const error = this.errors[fieldName];
132
+ return !value || !!error;
133
+ });
134
+ }
135
+
136
+ async submit(endpoint: string, token: string):Promise<any> {
137
+ // console.log("Submitting form:", this.form, this.errors);
138
+ const expiry = this.form.expiryDate?.split('/') || [];
139
+
140
+ // Replace fetchData with your API call
141
+ const response = await fetchData(endpoint, {
142
+ method: 'POST',
143
+ body: {
144
+ token,
145
+ pan: formatString(this.form.cardNumber || ''),
146
+ expiry_month: Number(expiry[0] || 0) || null,
147
+ expiry_year: formatCardYear(expiry[1] || '') || null,
148
+ cvv: this.form.cvc ? formatString(this.form.cvc) : null,
149
+ address: {
150
+ postal_code: this.form.zipCode
151
+ ? formatString(this.form.zipCode)
152
+ : null,
153
+ },
154
+ },
155
+ });
156
+
157
+ if (response.error) {
158
+ return { success: false, error: response.error, data:response };
159
+ } else {
160
+ return { success: true, data: response.data, info:response };
161
+ }
162
+ // return response.json();
163
+ }
164
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { BivoCollect } from "./core/Collector";
1
+ export { BivoSecureStore } from "./core/BivoSecureStore";
2
2
 
3
3
  export { BivoTextInput } from "./components/BivoTextInput";
4
4
  export { BivoCardInput } from "./components/BivoCardInput";