Skip to content

Commit 3fd6291

Browse files
Merge pull request #52 from skyflowapi/release/23.6.3-beta
SK-345 Release/23.6.3 - composable element changes.
2 parents c8d2724 + e4a80b0 commit 3fd6291

27 files changed

Lines changed: 584 additions & 83 deletions

File tree

__tests__/components/__snapshots__/components.test.js.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ exports[`test Collect And Reveal Elements Components test CardHolderNameElement
2222
onFocus={[Function]}
2323
placeholder="CardHolder Name"
2424
style={Object {}}
25+
value=""
2526
/>
2627
<Text
2728
style={Object {}}
@@ -85,6 +86,7 @@ exports[`test Collect And Reveal Elements Components test CvvElement component 1
8586
onFocus={[Function]}
8687
placeholder="cvv"
8788
style={Object {}}
89+
value=""
8890
/>
8991
<Text
9092
style={Object {}}
@@ -180,6 +182,7 @@ exports[`test Collect And Reveal Elements Components test ExpirationYearElement
180182
onFocus={[Function]}
181183
placeholder="expiration year"
182184
style={Object {}}
185+
value=""
183186
/>
184187
<Text
185188
style={Object {}}
@@ -209,6 +212,7 @@ exports[`test Collect And Reveal Elements Components test InputFieldElement comp
209212
onFocus={[Function]}
210213
placeholder="first name"
211214
style={Object {}}
215+
value=""
212216
/>
213217
<Text
214218
style={Object {}}
@@ -240,6 +244,7 @@ exports[`test Collect And Reveal Elements Components test PinElement component 1
240244
onFocus={[Function]}
241245
placeholder="pin"
242246
style={Object {}}
247+
value=""
243248
/>
244249
<Text
245250
style={Object {}}

__tests__/components/components.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import SkyflowProvider from '../../src/components/SkyflowProvider';
2020
import { Text } from 'react-native';
2121
import SkyflowError from '../../src/utils/skyflow-error';
2222
import SKYFLOW_ERROR_CODE from '../../src/utils/skyflow-error-code';
23-
import { ElementType } from '../../src/utils/constants';
23+
import { ContainerType, ElementType } from '../../src/utils/constants';
2424

2525
const testSkyflowClient = new Skyflow({
2626
vaultID: '1234',
@@ -54,6 +54,7 @@ describe('test Collect And Reveal Elements Components', () => {
5454
getInternalState: () => ({}),
5555
getCardType: () => CardType.VISA,
5656
setMethods: jest.fn(),
57+
type: ContainerType.COLLECT,
5758
}));
5859
});
5960

__tests__/core/collectElement.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
DEFAULT_VALIDATION_ERROR_TEXT,
99
} from '../../src/core/constants';
1010
import {
11+
ContainerType,
1112
ElementType,
1213
Env,
1314
LogLevel,
@@ -38,6 +39,7 @@ describe('test Collect Element class', () => {
3839
type: ElementType.CARD_NUMBER,
3940
label: 'Card Number',
4041
onChange: onChangeMock,
42+
containerType: ContainerType.COLLECT,
4143
};
4244
const cardNumberElement = new CollectElement(
4345
elementInput,
@@ -73,6 +75,7 @@ describe('test Collect Element class', () => {
7375
onChange: onChangeMock,
7476
onBlur: onBlurMock,
7577
onFocus: onFocusMock,
78+
containerType: ContainerType.COLLECT,
7679
},
7780
{ required: true },
7881
context
@@ -149,6 +152,7 @@ describe('test Collect Element class', () => {
149152
label: 'Expiration Date',
150153
type: ElementType.EXPIRATION_DATE,
151154
onChange: onChangeMock,
155+
containerType: ContainerType.COLLECT,
152156
},
153157
{
154158
format: 'YYYY/MM',
@@ -184,6 +188,7 @@ describe('test Collect Element class', () => {
184188
type: ElementType.PIN,
185189
onChange: onChangeMock,
186190
onBlur: onBlurMock,
191+
containerType: ContainerType.COLLECT,
187192
},
188193
{},
189194
context
@@ -257,6 +262,7 @@ describe('test Collect Element class', () => {
257262
collectElement = new CollectElement(
258263
{
259264
type: ElementType.CVV,
265+
containerType: ContainerType.COLLECT,
260266
},
261267
{},
262268
context
@@ -276,6 +282,7 @@ describe('test Collect Element class', () => {
276282
collectElement = new CollectElement(
277283
{
278284
type: ElementType.CVV,
285+
containerType: ContainerType.COLLECT,
279286
inputStyles: {
280287
base: baseStyles,
281288
focus: focusStyles,
@@ -327,6 +334,7 @@ describe('test Collect Element class', () => {
327334
collectElement = new CollectElement(
328335
{
329336
type: ElementType.CARDHOLDER_NAME,
337+
containerType: ContainerType.COLLECT,
330338
},
331339
{},
332340
context
@@ -337,6 +345,7 @@ describe('test Collect Element class', () => {
337345
{
338346
type: ElementType.CARDHOLDER_NAME,
339347
labelStyles: { base: baseStyles },
348+
containerType: ContainerType.COLLECT,
340349
},
341350
{},
342351
context
@@ -348,6 +357,7 @@ describe('test Collect Element class', () => {
348357
type: ElementType.CARDHOLDER_NAME,
349358
labelStyles: { base: baseStyles, focus: focusStyles },
350359
label: 'CardHolder Name',
360+
containerType: ContainerType.COLLECT,
351361
},
352362
{},
353363
context
@@ -374,6 +384,7 @@ describe('test Collect Element class', () => {
374384
collectElement = new CollectElement(
375385
{
376386
type: ElementType.INPUT_FIELD,
387+
containerType: ContainerType.COLLECT,
377388
validations: [
378389
{
379390
type: ValidationRuleType.LENGTH_MATCH_RULE,
@@ -404,6 +415,7 @@ describe('test Collect Element class', () => {
404415
collectElement = new CollectElement(
405416
{
406417
type: ElementType.INPUT_FIELD,
418+
containerType: ContainerType.COLLECT,
407419
validations: [
408420
{
409421
type: ValidationRuleType.REGEX_MATCH_RULE,
@@ -427,6 +439,7 @@ describe('test Collect Element class', () => {
427439
collectElement = new CollectElement(
428440
{
429441
type: ElementType.INPUT_FIELD,
442+
containerType: ContainerType.COLLECT,
430443
validations: [
431444
{
432445
type: undefined,
@@ -445,6 +458,7 @@ describe('test Collect Element class', () => {
445458
collectElement = new CollectElement(
446459
{
447460
type: ElementType.EXPIRATION_YEAR,
461+
containerType: ContainerType.COLLECT,
448462
},
449463
{
450464
required: true,
@@ -463,6 +477,7 @@ describe('test Collect Element class', () => {
463477
collectElement = new CollectElement(
464478
{
465479
type: ElementType.EXPIRATION_YEAR,
480+
containerType: ContainerType.COLLECT,
466481
},
467482
{
468483
required: true,

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "skyflow-react-native",
3-
"version": "1.3.0",
3+
"version": "1.3.0-dev.c211c0b",
44
"description": "Skyflow React Native SDK",
55
"main": "lib/commonjs/index",
66
"module": "lib/module/index",
@@ -70,7 +70,7 @@
7070
},
7171
"peerDependencies": {
7272
"react": "^17.0.2 || ^18.0.0",
73-
"react-native": "^0.65.3 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.69.0 || ^0.70.0"
73+
"react-native": "^0.65.3 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.69.0 || ^0.70.0 || ^0.71.0 || ^0.72.0"
7474
},
7575
"jest": {
7676
"preset": "react-native",
@@ -132,7 +132,7 @@
132132
"dependencies": {
133133
"jwt-decode": "^3.1.2",
134134
"lodash": "^4.17.21",
135-
"set-value": "^4.1.0",
136-
"uuid": "^9.0.0"
135+
"react-native-uuid": "^2.0.1",
136+
"set-value": "^4.1.0"
137137
}
138138
}

src/components/CardHolderNameElement/index.tsx

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
/*
22
Copyright (c) 2022 Skyflow, Inc.
33
*/
4-
import React, { useEffect } from "react";
4+
import React, { useEffect, useRef } from "react";
55
import { Text, TextInput, View } from "react-native";
66
import type CollectElement from "../../core/CollectElement";
7-
import { CollectElementProps, ElementType, ELEMENT_REQUIRED_ASTERISK, REQUIRED_MARK_DEFAULT_STYLE } from "../../utils/constants";
7+
import { CollectElementProps, ElementType, ELEMENT_REQUIRED_ASTERISK, REQUIRED_MARK_DEFAULT_STYLE, ContainerType } from "../../utils/constants";
88
import SkyflowError from "../../utils/skyflow-error";
99
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
10+
import uuid from 'react-native-uuid';
1011

1112
const CardHolderNameElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
1213
const [element, setElement] = React.useState<CollectElement>();
14+
const [elementValue, setElementValue] = React.useState<string>('');
1315
const [errorText, setErrorText] = React.useState<string>('');
1416
const [labelStyles, setLabelStyles] = React.useState(rest?.labelStyles?.base || {});
1517
const [inputStyles, setInputStyles] = React.useState(rest?.inputStyles?.base || {});
18+
const textInputRef = useRef();
19+
const uniqueElementID = useRef(uuid.v4() as string);
1620

1721
useEffect(() => {
1822
if (container) {
19-
const element: CollectElement = container.create({ ...rest, type: ElementType.CARDHOLDER_NAME }, options);
23+
const element: CollectElement = container.create({ ...rest, type: ElementType.CARDHOLDER_NAME, containerType: container.type }, options);
2024
setElement(element);
21-
element.setMethods(setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles });
25+
if (container.type === ContainerType.COLLECT)
26+
element.setMethods(setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles });
27+
else if (container.type === ContainerType.COMPOSABLE) {
28+
element.setMethods(rest.containerMethods.setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles })
29+
rest.containerMethods.setRef(textInputRef, uniqueElementID.current);
30+
}
2231
if (rest.onReady) {
2332
rest.onReady(element.getClientState());
2433
}
@@ -29,17 +38,20 @@ const CardHolderNameElement: React.FC<CollectElementProps> = ({ container, optio
2938

3039
return (<View>
3140
{
32-
rest.label && ( <Text style={labelStyles}>
41+
rest.label && (<Text style={labelStyles}>
3342
{rest.label}
34-
<Text style={{ ...REQUIRED_MARK_DEFAULT_STYLE, ...rest?.labelStyles?.requiredAsterisk } }>
43+
<Text style={{ ...REQUIRED_MARK_DEFAULT_STYLE, ...rest?.labelStyles?.requiredAsterisk }}>
3544
{options.required ? ELEMENT_REQUIRED_ASTERISK : ''}
3645
</Text>
3746
</Text>)
3847
}
3948
<TextInput
49+
ref={textInputRef}
50+
value={elementValue}
4051
placeholder={rest.placeholder}
4152
onChangeText={(text) => {
4253
element?.onChangeElement(text)
54+
setElementValue(element.getInternalState().value)
4355
}}
4456
onFocus={() => {
4557
element?.onFocusElement()
@@ -48,13 +60,24 @@ const CardHolderNameElement: React.FC<CollectElementProps> = ({ container, optio
4860
}}
4961
onBlur={() => {
5062
element?.onBlurElement();
51-
setErrorText(element?.getErrorText() || '');
63+
if (container.type === ContainerType.COLLECT) {
64+
setErrorText(element?.getErrorText() || '');
65+
} else if (container.type === ContainerType.COMPOSABLE) {
66+
rest.containerMethods.setErrorText(element?.getErrorText() || '')
67+
}
68+
setElementValue(element.getInternalState().value);
5269
setLabelStyles(element.updateLabelStyles());
5370
setInputStyles(element.updateInputStyles());
5471
}}
5572
style={inputStyles}
5673
/>
57-
<Text style={rest?.errorTextStyles?.base || {}}>{errorText}</Text>
74+
75+
{
76+
container && container?.type === ContainerType.COLLECT
77+
&&
78+
<Text style={rest?.errorTextStyles?.base || {}}>{errorText}</Text>
79+
}
80+
5881
</View>);
5982
}
6083

src/components/CardNumberElement/index.tsx

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/*
22
Copyright (c) 2022 Skyflow, Inc.
33
*/
4-
import React, { useEffect } from "react";
4+
import React, { useEffect, useRef } from "react";
55
import { Text, TextInput, View } from "react-native";
66
import type CollectElement from "../../core/CollectElement";
77
import { CARD_NUMBER_MASK, DEFAULT_CARD_INPUT_MAX_LENGTH } from "../../core/constants";
8-
import { CollectElementProps, ElementType, ELEMENT_REQUIRED_ASTERISK, REQUIRED_MARK_DEFAULT_STYLE } from "../../utils/constants";
8+
import { CollectElementProps, ElementType, ELEMENT_REQUIRED_ASTERISK, REQUIRED_MARK_DEFAULT_STYLE, ContainerType } from "../../utils/constants";
99
import SkyflowError from "../../utils/skyflow-error";
1010
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
11+
import uuid from 'react-native-uuid';
1112

1213
const CardNumberElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
1314
const [element, setElement] = React.useState<CollectElement>(undefined);
@@ -16,12 +17,19 @@ const CardNumberElement: React.FC<CollectElementProps> = ({ container, options =
1617
const [maxLength, setMaxLength] = React.useState<number>(DEFAULT_CARD_INPUT_MAX_LENGTH);
1718
const [labelStyles, setLabelStyles] = React.useState(rest?.labelStyles?.base || {});
1819
const [inputStyles, setInputStyles] = React.useState(rest?.inputStyles?.base || {});
20+
const textInputRef = useRef();
21+
const uniqueElementID = useRef(uuid.v4() as string);
1922

2023
useEffect(() => {
2124
if (container) {
22-
const element: CollectElement = container.create({ ...rest, type: ElementType.CARD_NUMBER }, options);
25+
const element: CollectElement = container.create({ ...rest, type: ElementType.CARD_NUMBER, containerType: container.type }, options);
2326
setElement(element);
24-
element.setMethods(setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles });
27+
if (container.type === ContainerType.COLLECT)
28+
element.setMethods(setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles });
29+
else if (container.type === ContainerType.COMPOSABLE) {
30+
element.setMethods(rest.containerMethods.setErrorText, { setInputStyles: setInputStyles, setLabelStyles: setLabelStyles })
31+
rest.containerMethods.setRef(textInputRef, uniqueElementID.current);
32+
}
2533
if (rest.onReady) {
2634
rest.onReady(element.getClientState());
2735
}
@@ -31,21 +39,25 @@ const CardNumberElement: React.FC<CollectElementProps> = ({ container, options =
3139
}, []);
3240
return (<View>
3341
{
34-
rest.label && ( <Text style={labelStyles}>
42+
rest.label && (<Text style={labelStyles}>
3543
{rest.label}
36-
<Text style={{ ...REQUIRED_MARK_DEFAULT_STYLE, ...rest?.labelStyles?.requiredAsterisk } }>
44+
<Text style={{ ...REQUIRED_MARK_DEFAULT_STYLE, ...rest?.labelStyles?.requiredAsterisk }}>
3745
{options.required ? ELEMENT_REQUIRED_ASTERISK : ''}
3846
</Text>
3947
</Text>)
4048
}
4149

4250
<TextInput
51+
ref={textInputRef}
4352
value={elementValue}
4453
placeholder={rest.placeholder}
4554
onChangeText={(text) => {
4655
element?.onChangeElement(text)
4756
setElementValue(element.getInternalState().value)
4857
setMaxLength(CARD_NUMBER_MASK[element.getCardType()].length || DEFAULT_CARD_INPUT_MAX_LENGTH);
58+
if (container.type === ContainerType.COMPOSABLE && (!element.getInternalState().isEmpty) && element.getInternalState().isValid) {
59+
rest.containerMethods.shiftFocus(uniqueElementID);
60+
}
4961
}}
5062
onFocus={() => {
5163
element?.onFocusElement();
@@ -54,7 +66,11 @@ const CardNumberElement: React.FC<CollectElementProps> = ({ container, options =
5466
}}
5567
onBlur={() => {
5668
element?.onBlurElement();
57-
setErrorText(element?.getErrorText() || '');
69+
if (container.type === ContainerType.COLLECT) {
70+
setErrorText(element?.getErrorText() || '');
71+
} else if (container.type === ContainerType.COMPOSABLE) {
72+
rest.containerMethods.setErrorText(element?.getErrorText() || '')
73+
}
5874
setElementValue(element.getInternalState().value);
5975
setLabelStyles(element.updateLabelStyles());
6076
setInputStyles(element.updateInputStyles());
@@ -63,9 +79,11 @@ const CardNumberElement: React.FC<CollectElementProps> = ({ container, options =
6379
maxLength={maxLength}
6480
style={inputStyles}
6581
/>
66-
<Text style={rest?.errorTextStyles?.base || {}}>
67-
{errorText}
68-
</Text>
82+
{
83+
container && container?.type === ContainerType.COLLECT
84+
&&
85+
<Text style={rest?.errorTextStyles?.base || {}}>{errorText}</Text>
86+
}
6987
</View>);
7088
}
7189

0 commit comments

Comments
 (0)