@evervault/react-native 2.1.0 → 2.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/android/build.gradle +6 -1
- package/build/Card/schema.d.ts +2 -12
- package/build/Card/schema.d.ts.map +1 -1
- package/build/Card/types.d.ts +6 -0
- package/build/Card/types.d.ts.map +1 -1
- package/build/Card/utils.d.ts.map +1 -1
- package/build/index.cjs.js +5 -16
- package/build/index.cjs.js.map +1 -1
- package/build/index.esm.js +5 -16
- package/package.json +1 -1
- package/src/Card/Root.test.tsx +81 -0
- package/src/Card/schema.ts +25 -35
- package/src/Card/types.ts +6 -0
- package/src/Card/utils.ts +2 -0
package/build/index.esm.js
CHANGED
|
@@ -7105,6 +7105,8 @@ function areValuesComplete(values) {
|
|
|
7105
7105
|
function isAcceptedBrand(acceptedBrands, cardNumberValidationResult) {
|
|
7106
7106
|
if (!acceptedBrands?.length)
|
|
7107
7107
|
return true;
|
|
7108
|
+
if (!cardNumberValidationResult.isValid)
|
|
7109
|
+
return false;
|
|
7108
7110
|
const { brand, localBrands } = cardNumberValidationResult;
|
|
7109
7111
|
const acceptedBrandsSet = new Set(acceptedBrands);
|
|
7110
7112
|
const isBrandAccepted = brand !== null && acceptedBrandsSet.has(brand);
|
|
@@ -7123,15 +7125,15 @@ function formatExpiry(expiry) {
|
|
|
7123
7125
|
}
|
|
7124
7126
|
|
|
7125
7127
|
function getCardFormSchema(acceptedBrands) {
|
|
7126
|
-
return z
|
|
7127
|
-
.object({
|
|
7128
|
+
return z.object({
|
|
7128
7129
|
name: z.string().min(1, "Missing name"),
|
|
7129
7130
|
number: z
|
|
7130
7131
|
.string()
|
|
7131
7132
|
.min(1, "Required")
|
|
7132
7133
|
.refine((value) => f(value).isValid, {
|
|
7133
7134
|
message: "Invalid card number",
|
|
7134
|
-
})
|
|
7135
|
+
})
|
|
7136
|
+
.refine((value) => isAcceptedBrand(acceptedBrands, f(value)), { message: "Brand not accepted" }),
|
|
7135
7137
|
expiry: z
|
|
7136
7138
|
.string()
|
|
7137
7139
|
.min(1, "Required")
|
|
@@ -7144,19 +7146,6 @@ function getCardFormSchema(acceptedBrands) {
|
|
|
7144
7146
|
.refine((value) => C(value).isValid, {
|
|
7145
7147
|
message: "Invalid CVC",
|
|
7146
7148
|
}),
|
|
7147
|
-
})
|
|
7148
|
-
.superRefine((value, ctx) => {
|
|
7149
|
-
const validation = f(value.number);
|
|
7150
|
-
if (!validation.isValid)
|
|
7151
|
-
return;
|
|
7152
|
-
const isAccepted = isAcceptedBrand(acceptedBrands, validation);
|
|
7153
|
-
if (!isAccepted) {
|
|
7154
|
-
ctx.addIssue({
|
|
7155
|
-
code: z.ZodIssueCode.custom,
|
|
7156
|
-
message: "Brand not accepted",
|
|
7157
|
-
path: ["number"],
|
|
7158
|
-
});
|
|
7159
|
-
}
|
|
7160
7149
|
});
|
|
7161
7150
|
}
|
|
7162
7151
|
|
package/package.json
CHANGED
package/src/Card/Root.test.tsx
CHANGED
|
@@ -258,3 +258,84 @@ it("adds Invalid error when input is blurred with an invalid value", async () =>
|
|
|
258
258
|
});
|
|
259
259
|
});
|
|
260
260
|
});
|
|
261
|
+
|
|
262
|
+
it("adds 'Brand not accepted' error when brand is not accepted", async () => {
|
|
263
|
+
const onChange = vi.fn();
|
|
264
|
+
const { getByTestId } = render(
|
|
265
|
+
<Card onChange={onChange} acceptedBrands={["american-express"]}>
|
|
266
|
+
<CardNumber testID="number" />
|
|
267
|
+
</Card>,
|
|
268
|
+
{ wrapper }
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
const number = getByTestId("number");
|
|
272
|
+
|
|
273
|
+
const user = userEvent.setup();
|
|
274
|
+
await user.type(number, "4242");
|
|
275
|
+
fireEvent(number, "blur");
|
|
276
|
+
|
|
277
|
+
await waitFor(() => {
|
|
278
|
+
expect(onChange).toHaveBeenLastCalledWith({
|
|
279
|
+
card: {
|
|
280
|
+
name: null,
|
|
281
|
+
brand: "visa",
|
|
282
|
+
localBrands: [],
|
|
283
|
+
number: null,
|
|
284
|
+
lastFour: null,
|
|
285
|
+
bin: null,
|
|
286
|
+
expiry: null,
|
|
287
|
+
cvc: null,
|
|
288
|
+
},
|
|
289
|
+
isValid: false,
|
|
290
|
+
isComplete: false,
|
|
291
|
+
errors: {
|
|
292
|
+
number: "Invalid card number",
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
await user.type(number, "4242 4242 4242");
|
|
298
|
+
fireEvent(number, "blur");
|
|
299
|
+
|
|
300
|
+
await waitFor(() => {
|
|
301
|
+
expect(onChange).toHaveBeenLastCalledWith({
|
|
302
|
+
card: {
|
|
303
|
+
name: null,
|
|
304
|
+
brand: "visa",
|
|
305
|
+
localBrands: [],
|
|
306
|
+
number: expect.any(String),
|
|
307
|
+
lastFour: "4242",
|
|
308
|
+
bin: "42424242",
|
|
309
|
+
expiry: null,
|
|
310
|
+
cvc: null,
|
|
311
|
+
},
|
|
312
|
+
isValid: false,
|
|
313
|
+
isComplete: true,
|
|
314
|
+
errors: {
|
|
315
|
+
number: "Brand not accepted",
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
await user.clear(number);
|
|
321
|
+
await user.type(number, "3782 822463 10005");
|
|
322
|
+
fireEvent(number, "blur");
|
|
323
|
+
|
|
324
|
+
await waitFor(() => {
|
|
325
|
+
expect(onChange).toHaveBeenLastCalledWith({
|
|
326
|
+
card: {
|
|
327
|
+
name: null,
|
|
328
|
+
brand: "american-express",
|
|
329
|
+
localBrands: [],
|
|
330
|
+
number: expect.any(String),
|
|
331
|
+
lastFour: "0005",
|
|
332
|
+
bin: "378282",
|
|
333
|
+
expiry: null,
|
|
334
|
+
cvc: null,
|
|
335
|
+
},
|
|
336
|
+
isValid: true,
|
|
337
|
+
isComplete: true,
|
|
338
|
+
errors: {},
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
});
|
package/src/Card/schema.ts
CHANGED
|
@@ -8,44 +8,34 @@ import { CardBrandName } from "./types";
|
|
|
8
8
|
import { isAcceptedBrand } from "./utils";
|
|
9
9
|
|
|
10
10
|
export function getCardFormSchema(acceptedBrands: CardBrandName[]) {
|
|
11
|
-
return z
|
|
12
|
-
.
|
|
13
|
-
name: z.string().min(1, "Missing name"),
|
|
11
|
+
return z.object({
|
|
12
|
+
name: z.string().min(1, "Missing name"),
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
number: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1, "Required")
|
|
17
|
+
.refine((value) => validateNumber(value).isValid, {
|
|
18
|
+
message: "Invalid card number",
|
|
19
|
+
})
|
|
20
|
+
.refine(
|
|
21
|
+
(value) => isAcceptedBrand(acceptedBrands, validateNumber(value)),
|
|
22
|
+
{ message: "Brand not accepted" }
|
|
23
|
+
),
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
expiry: z
|
|
26
|
+
.string()
|
|
27
|
+
.min(1, "Required")
|
|
28
|
+
.refine((value) => validateExpiry(value).isValid, {
|
|
29
|
+
message: "Invalid expiry",
|
|
30
|
+
}),
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.superRefine((value, ctx) => {
|
|
37
|
-
const validation = validateNumber(value.number);
|
|
38
|
-
if (!validation.isValid) return;
|
|
39
|
-
|
|
40
|
-
const isAccepted = isAcceptedBrand(acceptedBrands, validation);
|
|
41
|
-
if (!isAccepted) {
|
|
42
|
-
ctx.addIssue({
|
|
43
|
-
code: z.ZodIssueCode.custom,
|
|
44
|
-
message: "Brand not accepted",
|
|
45
|
-
path: ["number"],
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
32
|
+
cvc: z
|
|
33
|
+
.string()
|
|
34
|
+
.min(1, "Required")
|
|
35
|
+
.refine((value) => validateCVC(value).isValid, {
|
|
36
|
+
message: "Invalid CVC",
|
|
37
|
+
}),
|
|
38
|
+
});
|
|
49
39
|
}
|
|
50
40
|
|
|
51
41
|
export type CardFormValues = z.infer<ReturnType<typeof getCardFormSchema>>;
|
package/src/Card/types.ts
CHANGED
|
@@ -18,6 +18,12 @@ export const CARD_BRAND_NAMES = [
|
|
|
18
18
|
export type CardBrandName = (typeof CARD_BRAND_NAMES)[number];
|
|
19
19
|
|
|
20
20
|
export interface CardConfig {
|
|
21
|
+
/**
|
|
22
|
+
* The brands that are accepted by the card form.
|
|
23
|
+
* Pass an empty array to accept all brands.
|
|
24
|
+
*
|
|
25
|
+
* @default []
|
|
26
|
+
*/
|
|
21
27
|
acceptedBrands?: CardBrandName[];
|
|
22
28
|
}
|
|
23
29
|
|
package/src/Card/utils.ts
CHANGED
|
@@ -101,6 +101,8 @@ export function isAcceptedBrand(
|
|
|
101
101
|
cardNumberValidationResult: CardNumberValidationResult
|
|
102
102
|
): boolean {
|
|
103
103
|
if (!acceptedBrands?.length) return true;
|
|
104
|
+
|
|
105
|
+
if (!cardNumberValidationResult.isValid) return false;
|
|
104
106
|
const { brand, localBrands } = cardNumberValidationResult;
|
|
105
107
|
|
|
106
108
|
const acceptedBrandsSet = new Set(acceptedBrands);
|