@tonder.io/ionic-full-sdk 0.0.62 → 1.0.0-beta.develop.fcbbea8
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 +750 -781
- package/dist/classes/3dsHandler.d.ts +39 -0
- package/dist/classes/checkout.d.ts +31 -0
- package/dist/classes/inlineCheckout.d.ts +2 -2
- package/dist/helpers/skyflow.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/types/commons.d.ts +57 -1
- package/package.json +2 -2
- package/src/classes/inlineCheckout.ts +10 -6
- package/src/helpers/skyflow.ts +273 -252
- package/src/types/commons.ts +56 -1
package/src/helpers/skyflow.ts
CHANGED
|
@@ -4,54 +4,123 @@ import Skyflow from "skyflow-js";
|
|
|
4
4
|
import { CollectorIds } from "./template";
|
|
5
5
|
import RevealElement from "skyflow-js/types/core/external/reveal/reveal-element";
|
|
6
6
|
import ComposableElement from "skyflow-js/types/core/external/collect/compose-collect-element";
|
|
7
|
-
import {IEvents, IInputEvents, InCollectorContainer} from "../types/commons";
|
|
7
|
+
import { IEvents, IInputEvents, InCollectorContainer, ICardStyles, ICardFieldStyles } from "../types/commons";
|
|
8
8
|
import get from "lodash.get";
|
|
9
9
|
import { StylesBaseVariant } from "@tonder.io/ionic-lite-sdk/dist/types/commons";
|
|
10
10
|
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Style helpers
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
/** Maps Skyflow column names to ICardStyles per-field keys. */
|
|
16
|
+
const fieldToStyleKey: Record<string, keyof ICardStyles> = {
|
|
17
|
+
cardholder_name: "cardholderName",
|
|
18
|
+
card_number: "cardNumber",
|
|
19
|
+
cvv: "cvv",
|
|
20
|
+
expiration_month: "expirationMonth",
|
|
21
|
+
expiration_year: "expirationYear",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Backward-compat normalizer.
|
|
26
|
+
* If the developer passed the old flat format (`{ inputStyles, labelStyles, errorTextStyles, labels, placeholders }`)
|
|
27
|
+
* it is transparently wrapped as `{ cardForm: { inputStyles, labelStyles, errorStyles }, labels, placeholders }`.
|
|
28
|
+
* New-format objects (with `cardForm` or any per-field key) are returned as-is.
|
|
29
|
+
*/
|
|
30
|
+
function normalizeStyles(styles: any): ICardStyles {
|
|
31
|
+
if (!styles || Object.keys(styles).length === 0) return {};
|
|
32
|
+
const isNewFormat = !!(
|
|
33
|
+
styles.cardForm ||
|
|
34
|
+
styles.cardholderName ||
|
|
35
|
+
styles.cardNumber ||
|
|
36
|
+
styles.cvv ||
|
|
37
|
+
styles.expirationMonth ||
|
|
38
|
+
styles.expirationYear
|
|
39
|
+
);
|
|
40
|
+
if (isNewFormat) return styles as ICardStyles;
|
|
41
|
+
// Legacy flat: inputStyles at root level → wrap as cardForm
|
|
42
|
+
if (styles.inputStyles) {
|
|
43
|
+
return {
|
|
44
|
+
cardForm: {
|
|
45
|
+
inputStyles: styles.inputStyles,
|
|
46
|
+
labelStyles: styles.labelStyles,
|
|
47
|
+
errorStyles: styles.errorTextStyles, // translate key name
|
|
48
|
+
},
|
|
49
|
+
labels: styles.labels,
|
|
50
|
+
placeholders: styles.placeholders,
|
|
51
|
+
enableCardIcon: styles.enableCardIcon, // pass through if present
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return styles as ICardStyles;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolves styles for a single field with precedence: per-field → cardForm → defaultStyles.
|
|
59
|
+
* Translates the developer-facing `errorStyles` key to Skyflow's `errorTextStyles`.
|
|
60
|
+
* Injects `textIndent` on card_number so text doesn't overlap the card icon.
|
|
61
|
+
*/
|
|
62
|
+
function getFieldStyles(field: string, styles: ICardStyles) {
|
|
63
|
+
const key = fieldToStyleKey[field];
|
|
64
|
+
const perField = key ? (styles[key] as ICardFieldStyles | undefined) : undefined;
|
|
65
|
+
const form = styles.cardForm;
|
|
66
|
+
|
|
67
|
+
const resolvedInputStyles =
|
|
68
|
+
perField?.inputStyles || form?.inputStyles || defaultStyles.inputStyles;
|
|
69
|
+
|
|
70
|
+
// card_number: inject textIndent so text doesn't overlap the card icon,
|
|
71
|
+
// but only when the icon is actually visible (enableCardIcon !== false).
|
|
72
|
+
const iconVisible = field === "card_number" && styles.enableCardIcon !== false;
|
|
73
|
+
const inputStyles = iconVisible
|
|
74
|
+
? {
|
|
75
|
+
...resolvedInputStyles,
|
|
76
|
+
base: { textIndent: "44px", ...(resolvedInputStyles.base || {}) },
|
|
77
|
+
}
|
|
78
|
+
: resolvedInputStyles;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
inputStyles,
|
|
82
|
+
labelStyles: perField?.labelStyles || form?.labelStyles || defaultStyles.labelStyles,
|
|
83
|
+
errorTextStyles: perField?.errorStyles || form?.errorStyles || defaultStyles.errorTextStyles,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Public init functions
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
11
91
|
export async function initSkyflow(
|
|
12
92
|
vaultId: string,
|
|
13
93
|
vaultUrl: string,
|
|
14
94
|
baseUrl: string,
|
|
15
95
|
signal: AbortSignal,
|
|
16
|
-
customStyles:
|
|
96
|
+
customStyles: ICardStyles | any,
|
|
17
97
|
collectorIds: CollectorIds,
|
|
18
98
|
apiKey: string,
|
|
19
|
-
events?: IEvents
|
|
99
|
+
events?: IEvents,
|
|
100
|
+
mode: string = "stage",
|
|
20
101
|
): Promise<InCollectorContainer> {
|
|
21
|
-
const skyflow = await initializeSkyflow(
|
|
22
|
-
vaultId,
|
|
23
|
-
vaultUrl,
|
|
24
|
-
baseUrl,
|
|
25
|
-
apiKey,
|
|
26
|
-
signal,
|
|
27
|
-
);
|
|
102
|
+
const skyflow = await initializeSkyflow(vaultId, vaultUrl, baseUrl, apiKey, signal, mode);
|
|
28
103
|
|
|
29
|
-
// Create collect
|
|
104
|
+
// Create collect container.
|
|
30
105
|
const collectContainer = skyflow.container(Skyflow.ContainerType.COLLECT);
|
|
31
106
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
expiryYearPlaceholder: customStyles?.placeholders?.expiryYearPlaceholder && customStyles?.placeholders?.expiryYearPlaceholder !== "" ? customStyles?.placeholders?.expiryYearPlaceholder: defaultStyles.placeholders.expiryYearPlaceholder,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const stylesForCardNumber = { ...collectStylesOptions.inputStyles.base };
|
|
54
|
-
stylesForCardNumber.textIndent = "44px";
|
|
107
|
+
// Normalize to new format (handles legacy flat styles transparently).
|
|
108
|
+
const normalizedStyles = normalizeStyles(customStyles);
|
|
109
|
+
|
|
110
|
+
// Resolve labels & placeholders with per-field overrides falling back to defaults.
|
|
111
|
+
const labels = {
|
|
112
|
+
nameLabel: normalizedStyles.labels?.nameLabel || defaultStyles.labels.nameLabel,
|
|
113
|
+
cardLabel: normalizedStyles.labels?.cardLabel || defaultStyles.labels.cardLabel,
|
|
114
|
+
cvvLabel: normalizedStyles.labels?.cvvLabel || defaultStyles.labels.cvvLabel,
|
|
115
|
+
expiryDateLabel: normalizedStyles.labels?.expiryDateLabel || defaultStyles.labels.expiryDateLabel,
|
|
116
|
+
};
|
|
117
|
+
const placeholders = {
|
|
118
|
+
namePlaceholder: normalizedStyles.placeholders?.namePlaceholder || defaultStyles.placeholders.namePlaceholder,
|
|
119
|
+
cardPlaceholder: normalizedStyles.placeholders?.cardPlaceholder || defaultStyles.placeholders.cardPlaceholder,
|
|
120
|
+
cvvPlaceholder: normalizedStyles.placeholders?.cvvPlaceholder || defaultStyles.placeholders.cvvPlaceholder,
|
|
121
|
+
expiryMonthPlaceholder: normalizedStyles.placeholders?.expiryMonthPlaceholder || defaultStyles.placeholders.expiryMonthPlaceholder,
|
|
122
|
+
expiryYearPlaceholder: normalizedStyles.placeholders?.expiryYearPlaceholder || defaultStyles.placeholders.expiryYearPlaceholder,
|
|
123
|
+
};
|
|
55
124
|
|
|
56
125
|
const lengthMatchRule = {
|
|
57
126
|
type: Skyflow.ValidationRuleType.LENGTH_MATCH_RULE,
|
|
@@ -61,122 +130,107 @@ export async function initSkyflow(
|
|
|
61
130
|
},
|
|
62
131
|
};
|
|
63
132
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
133
|
+
// ── cardHolderName ──────────────────────────────────────────────────────
|
|
134
|
+
const cardHolderNameElement: CollectElement | RevealElement | ComposableElement =
|
|
135
|
+
collectContainer.create({
|
|
136
|
+
table: "cards",
|
|
137
|
+
column: "cardholder_name",
|
|
138
|
+
...getFieldStyles("cardholder_name", normalizedStyles),
|
|
139
|
+
label: labels.nameLabel,
|
|
140
|
+
placeholder: placeholders.namePlaceholder,
|
|
141
|
+
type: Skyflow.ElementType.CARDHOLDER_NAME,
|
|
142
|
+
validations: [lengthMatchRule, regexMatchRule],
|
|
143
|
+
});
|
|
144
|
+
handleSkyflowElementEvents({
|
|
145
|
+
element: cardHolderNameElement,
|
|
146
|
+
errorStyles: getFieldStyles("cardholder_name", normalizedStyles).errorTextStyles,
|
|
147
|
+
fieldMessage: labels.nameLabel,
|
|
148
|
+
events: events?.cardHolderEvents,
|
|
75
149
|
});
|
|
76
|
-
handleSkyflowElementEvents({
|
|
77
|
-
element: cardHolderNameElement,
|
|
78
|
-
errorStyles: collectStylesOptions?.errorTextStyles,
|
|
79
|
-
fieldMessage: collectStylesOptions?.labels?.nameLabel,
|
|
80
|
-
events: events?.cardHolderEvents,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
150
|
|
|
151
|
+
// ── cardNumber ───────────────────────────────────────────────────────────
|
|
84
152
|
const cardNumberElement: CollectElement | RevealElement | ComposableElement =
|
|
85
|
-
collectContainer.create(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
153
|
+
collectContainer.create(
|
|
154
|
+
{
|
|
155
|
+
table: "cards",
|
|
156
|
+
column: "card_number",
|
|
157
|
+
...getFieldStyles("card_number", normalizedStyles),
|
|
158
|
+
label: labels.cardLabel,
|
|
159
|
+
placeholder: placeholders.cardPlaceholder,
|
|
160
|
+
type: Skyflow.ElementType.CARD_NUMBER,
|
|
161
|
+
validations: [regexMatchRule],
|
|
92
162
|
},
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
type: Skyflow.ElementType.CARD_NUMBER,
|
|
96
|
-
validations: [regexMatchRule],
|
|
97
|
-
});
|
|
98
|
-
|
|
163
|
+
{ enableCardIcon: normalizedStyles.enableCardIcon ?? true },
|
|
164
|
+
);
|
|
99
165
|
handleSkyflowElementEvents({
|
|
100
|
-
element:
|
|
101
|
-
errorStyles:
|
|
102
|
-
fieldMessage:
|
|
103
|
-
events:
|
|
166
|
+
element: cardNumberElement,
|
|
167
|
+
errorStyles: getFieldStyles("card_number", normalizedStyles).errorTextStyles,
|
|
168
|
+
fieldMessage: labels.cardLabel,
|
|
169
|
+
events: events?.cardNumberEvents,
|
|
104
170
|
});
|
|
105
171
|
|
|
172
|
+
// ── cvv ─────────────────────────────────────────────────────────────────
|
|
106
173
|
const cvvElement: CollectElement | RevealElement | ComposableElement =
|
|
107
174
|
collectContainer.create({
|
|
108
|
-
table:
|
|
109
|
-
column:
|
|
110
|
-
...
|
|
111
|
-
label:
|
|
112
|
-
placeholder:
|
|
113
|
-
type:
|
|
175
|
+
table: "cards",
|
|
176
|
+
column: "cvv",
|
|
177
|
+
...getFieldStyles("cvv", normalizedStyles),
|
|
178
|
+
label: labels.cvvLabel,
|
|
179
|
+
placeholder: placeholders.cvvPlaceholder,
|
|
180
|
+
type: Skyflow.ElementType.CVV,
|
|
114
181
|
validations: [regexMatchRule],
|
|
115
182
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
183
|
+
handleSkyflowElementEvents({
|
|
184
|
+
element: cvvElement,
|
|
185
|
+
errorStyles: getFieldStyles("cvv", normalizedStyles).errorTextStyles,
|
|
186
|
+
fieldMessage: "",
|
|
187
|
+
events: events?.cvvEvents,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ── expirationMonth ──────────────────────────────────────────────────────
|
|
191
|
+
const expiryMonthElement: CollectElement | RevealElement | ComposableElement =
|
|
192
|
+
collectContainer.create({
|
|
193
|
+
table: "cards",
|
|
194
|
+
column: "expiration_month",
|
|
195
|
+
...getFieldStyles("expiration_month", normalizedStyles),
|
|
196
|
+
label: labels.expiryDateLabel,
|
|
197
|
+
placeholder: placeholders.expiryMonthPlaceholder,
|
|
198
|
+
type: Skyflow.ElementType.EXPIRATION_MONTH,
|
|
130
199
|
validations: [regexMatchRule],
|
|
131
200
|
});
|
|
201
|
+
handleSkyflowElementEvents({
|
|
202
|
+
element: expiryMonthElement,
|
|
203
|
+
errorStyles: getFieldStyles("expiration_month", normalizedStyles).errorTextStyles,
|
|
204
|
+
fieldMessage: "",
|
|
205
|
+
events: events?.monthEvents,
|
|
206
|
+
});
|
|
132
207
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
column: "expiration_year",
|
|
143
|
-
...collectStylesOptions,
|
|
144
|
-
label: "",
|
|
145
|
-
placeholder: collectStylesOptions.placeholders?.expiryYearPlaceholder,
|
|
146
|
-
type: Skyflow.ElementType.EXPIRATION_YEAR,
|
|
208
|
+
// ── expirationYear ───────────────────────────────────────────────────────
|
|
209
|
+
const expiryYearElement: CollectElement | RevealElement | ComposableElement =
|
|
210
|
+
collectContainer.create({
|
|
211
|
+
table: "cards",
|
|
212
|
+
column: "expiration_year",
|
|
213
|
+
...getFieldStyles("expiration_year", normalizedStyles),
|
|
214
|
+
label: "",
|
|
215
|
+
placeholder: placeholders.expiryYearPlaceholder,
|
|
216
|
+
type: Skyflow.ElementType.EXPIRATION_YEAR,
|
|
147
217
|
validations: [regexMatchRule],
|
|
148
218
|
});
|
|
219
|
+
handleSkyflowElementEvents({
|
|
220
|
+
element: expiryYearElement,
|
|
221
|
+
errorStyles: getFieldStyles("expiration_year", normalizedStyles).errorTextStyles,
|
|
222
|
+
fieldMessage: "",
|
|
223
|
+
events: events?.yearEvents,
|
|
224
|
+
});
|
|
149
225
|
|
|
150
|
-
|
|
151
|
-
element: expiryYearElement,
|
|
152
|
-
errorStyles: collectStylesOptions?.errorTextStyles,
|
|
153
|
-
fieldMessage: "",
|
|
154
|
-
events: events?.yearEvents,
|
|
155
|
-
});
|
|
156
|
-
|
|
226
|
+
// ── Mount all elements ───────────────────────────────────────────────────
|
|
157
227
|
const elementsConfig = {
|
|
158
|
-
cardNumber: {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
element: cvvElement,
|
|
164
|
-
container: `#${collectorIds.cvv}`,
|
|
165
|
-
},
|
|
166
|
-
expiryMonth: {
|
|
167
|
-
element: expiryMonthElement,
|
|
168
|
-
container: `#${collectorIds.expirationMonth}`,
|
|
169
|
-
},
|
|
170
|
-
expiryYear: {
|
|
171
|
-
element: expiryYearElement,
|
|
172
|
-
container: `#${collectorIds.expirationYear}`,
|
|
173
|
-
},
|
|
174
|
-
cardHolderName: {
|
|
175
|
-
element: cardHolderNameElement,
|
|
176
|
-
container: `#${collectorIds.holderName}`,
|
|
177
|
-
},
|
|
228
|
+
cardNumber: { element: cardNumberElement, container: `#${collectorIds.cardNumber}` },
|
|
229
|
+
cvv: { element: cvvElement, container: `#${collectorIds.cvv}` },
|
|
230
|
+
expiryMonth: { element: expiryMonthElement, container: `#${collectorIds.expirationMonth}` },
|
|
231
|
+
expiryYear: { element: expiryYearElement, container: `#${collectorIds.expirationYear}` },
|
|
232
|
+
cardHolderName: { element: cardHolderNameElement, container: `#${collectorIds.holderName}` },
|
|
178
233
|
};
|
|
179
|
-
|
|
180
234
|
await mountElements(elementsConfig);
|
|
181
235
|
|
|
182
236
|
return {
|
|
@@ -197,96 +251,78 @@ export async function initUpdateSkyflow(
|
|
|
197
251
|
vaultUrl: string,
|
|
198
252
|
baseUrl: string,
|
|
199
253
|
signal: AbortSignal,
|
|
200
|
-
customStyles:
|
|
254
|
+
customStyles: ICardStyles | any,
|
|
201
255
|
collectorIds: CollectorIds,
|
|
202
256
|
apiKey: string,
|
|
203
|
-
events?: IEvents
|
|
257
|
+
events?: IEvents,
|
|
258
|
+
mode: string = "stage",
|
|
204
259
|
) {
|
|
205
|
-
const skyflow = await initializeSkyflow(
|
|
206
|
-
vaultId,
|
|
207
|
-
vaultUrl,
|
|
208
|
-
baseUrl,
|
|
209
|
-
apiKey,
|
|
210
|
-
signal,
|
|
211
|
-
);
|
|
260
|
+
const skyflow = await initializeSkyflow(vaultId, vaultUrl, baseUrl, apiKey, signal, mode);
|
|
212
261
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
cardLabel: customStyles?.labels?.cardLabel && customStyles?.labels?.cardLabel !== "" ? customStyles?.labels?.cardLabel: defaultStyles.labels.cardLabel,
|
|
221
|
-
cvvLabel: customStyles?.labels?.cvvLabel && customStyles?.labels?.cvvLabel !== "" ? customStyles?.labels?.cvvLabel: defaultStyles.labels.cvvLabel,
|
|
222
|
-
expiryDateLabel: customStyles?.labels?.expiryDateLabel && customStyles?.labels?.expiryDateLabel !== "" ? customStyles?.labels?.expiryDateLabel: defaultStyles.labels.expiryDateLabel,
|
|
223
|
-
},
|
|
224
|
-
placeholders: {
|
|
225
|
-
namePlaceholder: customStyles?.placeholders?.namePlaceholder && customStyles?.placeholders?.namePlaceholder !== "" ? customStyles?.placeholders?.namePlaceholder: defaultStyles.placeholders.namePlaceholder,
|
|
226
|
-
cardPlaceholder: customStyles?.placeholders?.cardPlaceholder && customStyles?.placeholders?.cardPlaceholder !== "" ? customStyles?.placeholders?.cardPlaceholder: defaultStyles.placeholders.cardPlaceholder,
|
|
227
|
-
cvvPlaceholder: customStyles?.placeholders?.cvvPlaceholder && customStyles?.placeholders?.cvvPlaceholder !== "" ? customStyles?.placeholders?.cvvPlaceholder: defaultStyles.placeholders.cvvPlaceholder,
|
|
228
|
-
expiryMonthPlaceholder: customStyles?.placeholders?.expiryMonthPlaceholder && customStyles?.placeholders?.expiryMonthPlaceholder !== "" ? customStyles?.placeholders?.expiryMonthPlaceholder: defaultStyles.placeholders.expiryMonthPlaceholder,
|
|
229
|
-
expiryYearPlaceholder: customStyles?.placeholders?.expiryYearPlaceholder && customStyles?.placeholders?.expiryYearPlaceholder !== "" ? customStyles?.placeholders?.expiryYearPlaceholder: defaultStyles.placeholders.expiryYearPlaceholder,
|
|
230
|
-
},
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
// Create collect Container.
|
|
262
|
+
const normalizedStyles = normalizeStyles(customStyles);
|
|
263
|
+
|
|
264
|
+
const placeholders = {
|
|
265
|
+
cvvPlaceholder: normalizedStyles.placeholders?.cvvPlaceholder || defaultStyles.placeholders.cvvPlaceholder,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Create collect container.
|
|
234
269
|
const collectContainer = skyflow.container(Skyflow.ContainerType.COLLECT);
|
|
270
|
+
|
|
235
271
|
const cvvElement: CollectElement | RevealElement | ComposableElement =
|
|
236
272
|
collectContainer.create({
|
|
237
|
-
table:
|
|
238
|
-
column:
|
|
239
|
-
...
|
|
240
|
-
label:
|
|
241
|
-
placeholder:
|
|
242
|
-
type:
|
|
273
|
+
table: "cards",
|
|
274
|
+
column: "cvv",
|
|
275
|
+
...getFieldStyles("cvv", normalizedStyles),
|
|
276
|
+
label: "",
|
|
277
|
+
placeholder: placeholders.cvvPlaceholder,
|
|
278
|
+
type: Skyflow.ElementType.CVV,
|
|
243
279
|
validations: [regexMatchRule],
|
|
244
|
-
skyflowID:
|
|
280
|
+
skyflowID: skyflowId,
|
|
245
281
|
});
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
});
|
|
282
|
+
handleSkyflowElementEvents({
|
|
283
|
+
element: cvvElement,
|
|
284
|
+
errorStyles: getFieldStyles("cvv", normalizedStyles).errorTextStyles,
|
|
285
|
+
fieldMessage: "",
|
|
286
|
+
events: events?.cvvEvents,
|
|
287
|
+
});
|
|
253
288
|
|
|
254
289
|
const elementsConfig = {
|
|
255
|
-
cvv: {
|
|
256
|
-
element: cvvElement,
|
|
257
|
-
container: `#${collectorIds.cvv}${skyflowId}`,
|
|
258
|
-
},
|
|
290
|
+
cvv: { element: cvvElement, container: `#${collectorIds.cvv}${skyflowId}` },
|
|
259
291
|
};
|
|
260
292
|
await mountElements(elementsConfig);
|
|
261
293
|
|
|
262
294
|
return {
|
|
263
295
|
container: collectContainer,
|
|
264
|
-
elements: {
|
|
265
|
-
cvvElement,
|
|
266
|
-
},
|
|
296
|
+
elements: { cvvElement },
|
|
267
297
|
};
|
|
268
298
|
}
|
|
269
299
|
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Private helpers
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Initializes a Skyflow instance.
|
|
306
|
+
* @param mode - 'production' maps to Skyflow.Env.PROD; all other values use DEV.
|
|
307
|
+
*/
|
|
270
308
|
async function initializeSkyflow(
|
|
271
309
|
vaultId: string,
|
|
272
310
|
vaultUrl: string,
|
|
273
311
|
baseUrl: string,
|
|
274
312
|
apiKey: string,
|
|
275
313
|
signal: AbortSignal,
|
|
314
|
+
mode: string,
|
|
276
315
|
) {
|
|
316
|
+
const env = mode === "production" ? Skyflow.Env.PROD : Skyflow.Env.DEV;
|
|
277
317
|
return Skyflow.init({
|
|
278
|
-
vaultID:
|
|
318
|
+
vaultID: vaultId,
|
|
279
319
|
vaultURL: vaultUrl,
|
|
280
320
|
getBearerToken: async () => {
|
|
281
|
-
// Pass the signal to the fetch call
|
|
282
321
|
const response = await fetch(`${baseUrl}/api/v1/vault-token/`, {
|
|
283
|
-
method:
|
|
284
|
-
headers: {
|
|
285
|
-
|
|
286
|
-
},
|
|
287
|
-
signal: signal,
|
|
322
|
+
method: "GET",
|
|
323
|
+
headers: { Authorization: `Token ${apiKey}` },
|
|
324
|
+
signal,
|
|
288
325
|
});
|
|
289
|
-
|
|
290
326
|
if (response.ok) {
|
|
291
327
|
const responseBody = await response.json();
|
|
292
328
|
return responseBody.token;
|
|
@@ -296,7 +332,7 @@ async function initializeSkyflow(
|
|
|
296
332
|
},
|
|
297
333
|
options: {
|
|
298
334
|
logLevel: Skyflow.LogLevel.ERROR,
|
|
299
|
-
env
|
|
335
|
+
env,
|
|
300
336
|
},
|
|
301
337
|
});
|
|
302
338
|
}
|
|
@@ -307,16 +343,11 @@ async function mountElements(elementsConfig: {
|
|
|
307
343
|
if (typeof elementsConfig !== "object" || elementsConfig === null) {
|
|
308
344
|
throw new Error("Invalid configuration object");
|
|
309
345
|
}
|
|
310
|
-
|
|
311
|
-
for (const [elementKey, { element, container }] of Object.entries(
|
|
312
|
-
elementsConfig,
|
|
313
|
-
)) {
|
|
346
|
+
for (const [elementKey, { element, container }] of Object.entries(elementsConfig)) {
|
|
314
347
|
if (element && container) {
|
|
315
348
|
element.mount(container);
|
|
316
349
|
} else {
|
|
317
|
-
console.warn(
|
|
318
|
-
`Skipping mount for '${elementKey}' due to missing element or container.`,
|
|
319
|
-
);
|
|
350
|
+
console.warn(`Skipping mount for '${elementKey}' due to missing element or container.`);
|
|
320
351
|
}
|
|
321
352
|
}
|
|
322
353
|
}
|
|
@@ -331,63 +362,53 @@ const regexMatchRule = {
|
|
|
331
362
|
};
|
|
332
363
|
|
|
333
364
|
function handleSkyflowElementEvents(event: {
|
|
334
|
-
element:
|
|
365
|
+
element: CollectElement;
|
|
335
366
|
fieldMessage?: string;
|
|
336
|
-
errorStyles?:
|
|
367
|
+
errorStyles?: StylesBaseVariant;
|
|
337
368
|
requiredMessage?: string;
|
|
338
|
-
invalidMessage?:
|
|
339
|
-
events?:
|
|
369
|
+
invalidMessage?: string;
|
|
370
|
+
events?: IInputEvents;
|
|
340
371
|
}) {
|
|
341
372
|
const {
|
|
342
373
|
element,
|
|
343
|
-
fieldMessage
|
|
344
|
-
errorStyles
|
|
374
|
+
fieldMessage = "",
|
|
375
|
+
errorStyles = {},
|
|
345
376
|
requiredMessage = "Campo requerido",
|
|
346
|
-
invalidMessage
|
|
377
|
+
invalidMessage = "Campo no válido",
|
|
347
378
|
events,
|
|
348
379
|
} = event;
|
|
349
|
-
if ("on" in element) {
|
|
350
|
-
element.on(Skyflow.EventName.CHANGE, (state: SkyflowEventData) => {
|
|
351
|
-
executeEvent({eventName: "onChange", data: state, events});
|
|
352
|
-
updateErrorLabel({
|
|
353
|
-
element,
|
|
354
|
-
errorStyles,
|
|
355
|
-
color: "transparent",
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
380
|
|
|
359
|
-
|
|
360
|
-
executeEvent({eventName: "onBlur", data: state, events});
|
|
361
|
-
if (!state.isValid) {
|
|
362
|
-
const msj_error = state.isEmpty
|
|
363
|
-
? requiredMessage
|
|
364
|
-
: fieldMessage != ""
|
|
365
|
-
? `El campo ${fieldMessage} no es válido`
|
|
366
|
-
: invalidMessage;
|
|
367
|
-
element.setError(msj_error);
|
|
368
|
-
}
|
|
369
|
-
updateErrorLabel({
|
|
370
|
-
element,
|
|
371
|
-
errorStyles,
|
|
372
|
-
});
|
|
373
|
-
});
|
|
381
|
+
if (!("on" in element)) return;
|
|
374
382
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
element.on(Skyflow.EventName.CHANGE, (state: SkyflowEventData) => {
|
|
384
|
+
executeEvent({ eventName: "onChange", data: state, events });
|
|
385
|
+
updateErrorLabel({ element, errorStyles, color: "transparent" });
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
element.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
389
|
+
executeEvent({ eventName: "onBlur", data: state, events });
|
|
390
|
+
if (!state.isValid) {
|
|
391
|
+
const msj_error = state.isEmpty
|
|
392
|
+
? requiredMessage
|
|
393
|
+
: fieldMessage !== ""
|
|
394
|
+
? `El campo ${fieldMessage} no es válido`
|
|
395
|
+
: invalidMessage;
|
|
396
|
+
element.setError(msj_error);
|
|
397
|
+
}
|
|
398
|
+
updateErrorLabel({ element, errorStyles });
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
element.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
402
|
+
executeEvent({ eventName: "onFocus", data: state, events });
|
|
403
|
+
updateErrorLabel({ element, errorStyles, color: "transparent" });
|
|
404
|
+
element.resetError();
|
|
405
|
+
});
|
|
385
406
|
}
|
|
386
407
|
|
|
387
408
|
function updateErrorLabel(event: {
|
|
388
|
-
element:
|
|
409
|
+
element: CollectElement;
|
|
389
410
|
errorStyles?: StylesBaseVariant;
|
|
390
|
-
color?:
|
|
411
|
+
color?: string;
|
|
391
412
|
}) {
|
|
392
413
|
const { element, errorStyles = {}, color = "" } = event;
|
|
393
414
|
if (Object.keys(errorStyles).length > 0) {
|
|
@@ -397,7 +418,7 @@ function updateErrorLabel(event: {
|
|
|
397
418
|
base: {
|
|
398
419
|
// @ts-ignore
|
|
399
420
|
...(errorStyles.base && { ...errorStyles.base }),
|
|
400
|
-
...(color
|
|
421
|
+
...(color !== "" && { color }),
|
|
401
422
|
},
|
|
402
423
|
},
|
|
403
424
|
});
|
|
@@ -406,15 +427,16 @@ function updateErrorLabel(event: {
|
|
|
406
427
|
|
|
407
428
|
interface SkyflowEventData {
|
|
408
429
|
elementType?: string;
|
|
409
|
-
isEmpty?:
|
|
410
|
-
isFocused?:
|
|
411
|
-
isValid?:
|
|
430
|
+
isEmpty?: boolean;
|
|
431
|
+
isFocused?: boolean;
|
|
432
|
+
isValid?: boolean;
|
|
433
|
+
value?: string;
|
|
412
434
|
}
|
|
413
435
|
|
|
414
436
|
const executeEvent = (event: {
|
|
415
437
|
eventName: "onChange" | "onBlur" | "onFocus";
|
|
416
|
-
data:
|
|
417
|
-
events?:
|
|
438
|
+
data: SkyflowEventData;
|
|
439
|
+
events?: IInputEvents;
|
|
418
440
|
}) => {
|
|
419
441
|
const { eventName, data, events } = event;
|
|
420
442
|
if (events && eventName in events) {
|
|
@@ -422,12 +444,11 @@ const executeEvent = (event: {
|
|
|
422
444
|
if (typeof eventHandler === "function") {
|
|
423
445
|
eventHandler({
|
|
424
446
|
elementType: get(data, "elementType", ""),
|
|
425
|
-
isEmpty:
|
|
426
|
-
isFocused:
|
|
427
|
-
isValid:
|
|
447
|
+
isEmpty: get(data, "isEmpty", false),
|
|
448
|
+
isFocused: get(data, "isFocused", false),
|
|
449
|
+
isValid: get(data, "isValid", false),
|
|
450
|
+
value: get(data, "value", ""),
|
|
428
451
|
});
|
|
429
452
|
}
|
|
430
453
|
}
|
|
431
454
|
};
|
|
432
|
-
|
|
433
|
-
|