@rebilly/instruments 3.12.3-beta.0 → 3.13.2-beta.0
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 +1 -1
- package/dist/index.js +43 -66
- package/dist/index.min.js +43 -66
- package/package.json +3 -6
- package/src/functions/destroy.js +8 -2
- package/src/functions/mount/fetch-data.js +9 -2
- package/src/functions/mount/index.js +15 -10
- package/src/functions/mount/mount.spec.js +10 -11
- package/src/functions/mount/setup-framepay-theme.js +30 -72
- package/src/functions/mount/setup-options.js +2 -2
- package/src/functions/mount/{setup-styles.js → setup-styles-vars.js} +9 -7
- package/src/functions/purchase.js +2 -5
- package/src/functions/setup.js +3 -6
- package/src/functions/show.js +2 -2
- package/src/functions/show.spec.js +4 -4
- package/src/functions/update.spec.js +4 -3
- package/src/instance.js +4 -1
- package/src/loader/index.js +57 -33
- package/src/storefront/index.js +2 -5
- package/src/storefront/payment-instruments.js +7 -0
- package/src/style/base/__snapshots__/theme.spec.js.snap +136 -220
- package/src/style/base/default-theme.js +187 -14
- package/src/style/base/index.js +487 -79
- package/src/style/base/theme.js +3 -4
- package/src/style/base/theme.spec.js +2 -3
- package/src/style/index.js +4 -24
- package/src/style/utils/color-values.js +1 -1
- package/src/style/utils/minifyCss.js +14 -0
- package/src/views/common/iframe/base-iframe.js +3 -2
- package/src/views/common/iframe/event-listeners.js +12 -9
- package/src/views/common/iframe/method-iframe.js +3 -1
- package/src/views/common/iframe/modal-iframe.js +4 -2
- package/src/views/common/iframe/view-iframe.js +3 -1
- package/src/views/confirmation.js +12 -7
- package/src/views/errors.js +95 -0
- package/src/views/method-selector/express-methods.js +51 -0
- package/src/views/method-selector/generate-framepay-config.js +54 -0
- package/src/views/method-selector/generate-framepay-config.spec.js +195 -0
- package/src/views/method-selector/get-payment-methods.js +0 -1
- package/src/views/method-selector/index.js +45 -58
- package/src/views/method-selector/method-selector.spec.js +1 -1
- package/src/views/method-selector/mount-express-methods.js +66 -26
- package/src/views/modal.js +1 -1
- package/src/views/result.js +3 -3
- package/src/views/summary.js +24 -190
- package/tests/mocks/storefront-api-mock.js +48 -27
- package/src/style/browserslist.js +0 -1
- package/src/style/components/accordion.js +0 -140
- package/src/style/components/address.js +0 -55
- package/src/style/components/button.js +0 -117
- package/src/style/components/divider.js +0 -39
- package/src/style/components/forms/checkbox.js +0 -75
- package/src/style/components/forms/field.js +0 -56
- package/src/style/components/forms/form.js +0 -18
- package/src/style/components/forms/input.js +0 -77
- package/src/style/components/forms/label.js +0 -55
- package/src/style/components/forms/radio.js +0 -80
- package/src/style/components/forms/select.js +0 -86
- package/src/style/components/forms/validation.js +0 -72
- package/src/style/components/icons.js +0 -13
- package/src/style/components/index.js +0 -39
- package/src/style/components/loader.js +0 -41
- package/src/style/components/methods.js +0 -97
- package/src/style/components/overlay.js +0 -24
- package/src/style/helpers/index.js +0 -54
- package/src/style/payment-instruments/content.js +0 -8
- package/src/style/payment-instruments/index.js +0 -14
- package/src/style/payment-instruments/payment-card.js +0 -27
- package/src/style/payment-instruments/payment-instrument-list.js +0 -44
- package/src/style/payment-instruments/payment-instrument.js +0 -55
- package/src/style/utils/remove-empty-null.js +0 -10
- package/src/style/vendor/framepay.js +0 -28
- package/src/style/vendor/postmate.js +0 -18
- package/src/style/views/confirmation.js +0 -26
- package/src/style/views/index.js +0 -16
- package/src/style/views/method-selector.js +0 -11
- package/src/style/views/modal.js +0 -91
- package/src/style/views/result.js +0 -52
- package/src/style/views/summary.js +0 -118
- package/src/views/__snapshots__/summary.spec.js.snap +0 -246
- package/src/views/method-selector/express-methods/apple-pay.js +0 -92
- package/src/views/method-selector/express-methods/index.js +0 -25
- package/src/views/method-selector/mount-methods.js +0 -178
- package/src/views/summary.spec.js +0 -145
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebilly/instruments",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.2-beta.0",
|
|
4
4
|
"author": "Rebilly",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"unpkg": "dist/index.min.js",
|
|
7
|
-
"license": "MIT",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "yarn rollup -c --environment NODE_ENV:production",
|
|
10
10
|
"dev": "yarn rollup -c --watch --environment NODE_ENV:development",
|
|
@@ -16,16 +16,13 @@
|
|
|
16
16
|
"@babel/core": "^7.14.6",
|
|
17
17
|
"@babel/preset-env": "^7.14.7",
|
|
18
18
|
"@rebilly/risk-data-collector": "^2.3.0",
|
|
19
|
-
"autoprefixer": "^10.3.4",
|
|
20
|
-
"css": "^3.0.0",
|
|
21
19
|
"jwt-decode": "^3.1.2",
|
|
22
20
|
"lodash.camelcase": "^4.3.0",
|
|
23
21
|
"lodash.isequal": "^4.5.0",
|
|
24
22
|
"lodash.kebabcase": "^4.1.1",
|
|
25
23
|
"lodash.merge": "^4.6.2",
|
|
26
24
|
"popostmate": "^1.6.4",
|
|
27
|
-
"
|
|
28
|
-
"rebilly-js-sdk": "^44.4.0",
|
|
25
|
+
"rebilly-js-sdk": "^47.3.1",
|
|
29
26
|
"values.js": "^2.0.0"
|
|
30
27
|
},
|
|
31
28
|
"devDependencies": {
|
package/src/functions/destroy.js
CHANGED
|
@@ -6,13 +6,19 @@ export async function destroy({ state }) {
|
|
|
6
6
|
// wait to allow for cancellation to catch any pending api requests
|
|
7
7
|
const sleepMilliseconds = 1000;
|
|
8
8
|
await sleep(sleepMilliseconds);
|
|
9
|
-
[
|
|
9
|
+
[
|
|
10
|
+
...(state.iframeComponents?.form || []),
|
|
11
|
+
...(state.iframeComponents?.summary || [])
|
|
12
|
+
].forEach((iframe) => {
|
|
10
13
|
iframe.destroy();
|
|
11
14
|
});
|
|
12
15
|
|
|
13
16
|
registeredListeners.removeAll(document);
|
|
14
17
|
|
|
15
|
-
state.iframeComponents =
|
|
18
|
+
state.iframeComponents = {
|
|
19
|
+
summary: [],
|
|
20
|
+
form: [],
|
|
21
|
+
};
|
|
16
22
|
state.hasMounted = false;
|
|
17
23
|
|
|
18
24
|
state.summary.textContent = '';
|
|
@@ -6,6 +6,7 @@ import { fetchSummary } from '../../storefront/summary';
|
|
|
6
6
|
import { fetchInvoice as FetchInvoice } from '../../storefront/invoices';
|
|
7
7
|
import { fetchTransaction as FetchTransaction } from '../../storefront/transactions';
|
|
8
8
|
import { fetchAccount as FetchAccount } from '../../storefront/account';
|
|
9
|
+
import { fetchPaymentInstrument as FetchInstruments } from '../../storefront/payment-instruments';
|
|
9
10
|
|
|
10
11
|
export class DataInstance {
|
|
11
12
|
constructor({
|
|
@@ -108,11 +109,13 @@ export async function fetchData({
|
|
|
108
109
|
// Dependency injectable functions
|
|
109
110
|
fetchInvoice = FetchInvoice,
|
|
110
111
|
fetchTransaction = FetchTransaction,
|
|
111
|
-
fetchAccount = FetchAccount
|
|
112
|
+
fetchAccount = FetchAccount,
|
|
113
|
+
fetchInstruments = FetchInstruments
|
|
112
114
|
}) {
|
|
113
115
|
try {
|
|
114
116
|
let transaction = null;
|
|
115
117
|
let account = null;
|
|
118
|
+
let availableInstruments = null;
|
|
116
119
|
if (state.options?.transactionId) {
|
|
117
120
|
transaction = await fetchTransaction({data: {
|
|
118
121
|
id: state.options.transactionId
|
|
@@ -134,7 +137,10 @@ export async function fetchData({
|
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
if (state.options?.jwt) {
|
|
137
|
-
account = await
|
|
140
|
+
[account, availableInstruments] = await Promise.all([
|
|
141
|
+
fetchAccount({state}),
|
|
142
|
+
fetchInstruments({state})
|
|
143
|
+
]);
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
state.data = new DataInstance({
|
|
@@ -143,6 +149,7 @@ export async function fetchData({
|
|
|
143
149
|
transaction,
|
|
144
150
|
riskMetadata,
|
|
145
151
|
account,
|
|
152
|
+
availableInstruments,
|
|
146
153
|
});
|
|
147
154
|
|
|
148
155
|
const [readyToPay, previewPurchase] = await Promise.all([
|
|
@@ -7,10 +7,11 @@ import setupElement from './setup-element';
|
|
|
7
7
|
import setupStorefront from './setup-storefront';
|
|
8
8
|
import setupOptions from './setup-options';
|
|
9
9
|
import setupFramepayInstance from './setup-framepay';
|
|
10
|
-
import
|
|
10
|
+
import setupStylesVars from './setup-styles-vars';
|
|
11
11
|
import setupI18n from './setup-i18n';
|
|
12
12
|
import setupFramepayTheme from './setup-framepay-theme';
|
|
13
13
|
import setupUserFlow from './setup-user-flow';
|
|
14
|
+
import { showError } from '../../views/errors';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* @typedef {object} Item
|
|
@@ -87,23 +88,26 @@ export async function mount({
|
|
|
87
88
|
// Setup DOM
|
|
88
89
|
state.form = setupElement({ element: 'form', options });
|
|
89
90
|
state.summary = setupElement({ element: 'summary', options });
|
|
91
|
+
// hardcode max-width to not break UX
|
|
92
|
+
// PayPal button cannot exceed 750px;
|
|
93
|
+
state.form.style.maxWidth = '750px';
|
|
94
|
+
state.summary.style.maxWidth = '750px';
|
|
95
|
+
|
|
96
|
+
// Setup state
|
|
97
|
+
state.options = setupOptions({ options });
|
|
98
|
+
state.storefront = setupStorefront({ options });
|
|
99
|
+
state.mainStyleVars = setupStylesVars({ options });
|
|
100
|
+
state.options.themeFramepay = setupFramepayTheme({ state, options });
|
|
90
101
|
|
|
91
102
|
// Setup loader
|
|
92
103
|
state.loader.addDOMElement({ el: state.form });
|
|
93
104
|
state.loader.addDOMElement({ section: 'summary', el: state.summary });
|
|
94
|
-
state.loader.startLoading({ section: 'summary', id: '
|
|
95
|
-
state.loader.startLoading({ id: '
|
|
105
|
+
state.loader.startLoading({ state, section: 'summary', id: 'rebilly-instruments-summary' });
|
|
106
|
+
state.loader.startLoading({ state, id: 'rebilly-instruments-methods' });
|
|
96
107
|
|
|
97
|
-
// Setup state
|
|
98
|
-
state.options = setupOptions({ options });
|
|
99
|
-
state.storefront = setupStorefront({ options });
|
|
100
|
-
|
|
101
|
-
state.mainStyle = await setupStyles({ options });
|
|
102
|
-
|
|
103
108
|
state.data = await fetchData({ state });
|
|
104
109
|
Events.dataReady.dispatch(state.data);
|
|
105
110
|
|
|
106
|
-
state.options.themeFramepay = await setupFramepayTheme({ state, options });
|
|
107
111
|
state.i18n = setupI18n({ state });
|
|
108
112
|
|
|
109
113
|
await setupFramepay(state);
|
|
@@ -128,6 +132,7 @@ export async function mount({
|
|
|
128
132
|
state.i18n({state});
|
|
129
133
|
state.hasMounted = true;
|
|
130
134
|
} catch (error) {
|
|
135
|
+
showError(error);
|
|
131
136
|
throw error;
|
|
132
137
|
}
|
|
133
138
|
|
|
@@ -29,23 +29,22 @@ describe('RebillyInstruments instance', () => {
|
|
|
29
29
|
};
|
|
30
30
|
await RenderMockRebillyInstruments(options);
|
|
31
31
|
|
|
32
|
+
await new Promise((resolve) => {
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
resolve();
|
|
35
|
+
}, 100);
|
|
36
|
+
})
|
|
37
|
+
|
|
32
38
|
// Mounts form and summary
|
|
33
39
|
const summarySelector = document.querySelector('.summary-selector');
|
|
34
|
-
expect(summarySelector.innerHTML).
|
|
40
|
+
expect(summarySelector.innerHTML).toContain('<iframe name="rebilly-instruments-summary" class="rebilly-instruments-iframe" loading="lazy" allow="payment" scrolling="no" src="https://forms.local.rebilly.dev:3000/summary"></iframe>');
|
|
35
41
|
|
|
36
42
|
// Theme config overrides initial styles
|
|
37
|
-
const
|
|
38
|
-
'.rebilly-instruments-content'
|
|
39
|
-
);
|
|
40
|
-
expect(getComputedStyle(SUMMARY_CONTAINER).getPropertyValue('--rebilly-colorBackground')).toEqual(
|
|
41
|
-
'#000'
|
|
42
|
-
);
|
|
43
|
+
const STYLE_VARS = document.querySelectorAll('style[type="text/css"]')[0];
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'.rebilly-instruments-summary-line-item-synopsis-title'
|
|
45
|
+
expect(STYLE_VARS.innerHTML).toMatch(
|
|
46
|
+
'--rebilly-colorBackground: #000;'
|
|
47
47
|
);
|
|
48
|
-
expect(getComputedStyle(LINE_ITEM_TITLE).color).toEqual('rgb(0, 68, 212)');
|
|
49
48
|
|
|
50
49
|
// Mounts default FramePay script
|
|
51
50
|
const SCRIPTS = [...document.querySelectorAll('head script')];
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import css from 'css';
|
|
2
|
-
import camelCase from 'lodash.camelcase';
|
|
3
|
-
|
|
4
1
|
function processCSS(rawCss) {
|
|
5
2
|
const cssMap = {};
|
|
6
3
|
[...rawCss.matchAll(/(--rebilly.*(?=:))[:\s](.*(?=;))/g)]
|
|
@@ -26,101 +23,62 @@ function processCSS(rawCss) {
|
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
function replaceCssVars(rawCss) {
|
|
26
|
+
const CssVarsObj = {}
|
|
29
27
|
processCSS(rawCss).forEach(([key, value]) => {
|
|
30
|
-
|
|
28
|
+
CssVarsObj[key] = value;
|
|
31
29
|
});
|
|
32
|
-
|
|
33
|
-
return rawCss;
|
|
30
|
+
return CssVarsObj;
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
const getStyleProps = (
|
|
37
|
-
const { rules } = ast.stylesheet;
|
|
33
|
+
const getStyleProps = (obj, particle = '') => {
|
|
38
34
|
const output = {
|
|
39
|
-
color:
|
|
40
|
-
fontFamily:
|
|
41
|
-
fontSize:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
background:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
for(let i = 0; i < rules.length; i += 1) {
|
|
48
|
-
const rule = rules[i];
|
|
49
|
-
|
|
50
|
-
if(rule.type === 'rule' && rule.selectors.includes(selector)) {
|
|
51
|
-
rule.declarations.forEach(decl => {
|
|
52
|
-
const propName = camelCase(decl.property);
|
|
53
|
-
if(typeof output[propName] !== 'undefined') {
|
|
54
|
-
output[propName] = decl.value;
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
}
|
|
35
|
+
color: obj[`--rebilly-${particle}ColorText`],
|
|
36
|
+
fontFamily: obj[`--rebilly-${particle}FontFamily`],
|
|
37
|
+
fontSize: obj[`--rebilly-${particle}FontSize`],
|
|
38
|
+
fontWeight: obj[`--rebilly-${particle}FontWeight`],
|
|
39
|
+
lineHeight: obj[`--rebilly-${particle}FontLineHeight`],
|
|
40
|
+
background: obj[`--rebilly-${particle}ColorBackground`],
|
|
41
|
+
boxShadow: obj[`--rebilly-${particle}BoxShadow`],
|
|
58
42
|
}
|
|
59
43
|
return output;
|
|
60
44
|
}
|
|
61
45
|
|
|
62
|
-
export default
|
|
46
|
+
export default ({
|
|
63
47
|
state,
|
|
64
48
|
options = {}
|
|
65
49
|
}) => {
|
|
66
50
|
const fullCss = `
|
|
67
|
-
${state.
|
|
51
|
+
${state.mainStyleVars}
|
|
68
52
|
${options.css || ''}
|
|
69
53
|
`;
|
|
70
54
|
|
|
71
|
-
const
|
|
72
|
-
const cssAst = css.parse(resolvedCss);
|
|
73
|
-
|
|
74
|
-
const cssSelectors = {
|
|
75
|
-
input: {
|
|
76
|
-
base: '.rebilly-instruments-form-field-input',
|
|
77
|
-
baseHover: '.rebilly-instruments-form-field-input:hover',
|
|
78
|
-
baseFocus: '.rebilly-instruments-form-field-input:focus',
|
|
79
|
-
basePlaceholder: '.rebilly-instruments-form-field-input::placeholder',
|
|
80
|
-
baseSelection: '.rebilly-instruments-form-field-input::selection',
|
|
81
|
-
|
|
82
|
-
invalid: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input',
|
|
83
|
-
invalidHover: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:hover',
|
|
84
|
-
invalidFocus: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:focus',
|
|
85
|
-
invalidPlaceholder: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::placeholder',
|
|
86
|
-
invalidSelection: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::selection'
|
|
87
|
-
},
|
|
88
|
-
button: {
|
|
89
|
-
base: '.rebilly-instruments-button.rebilly-instruments-button-secondary',
|
|
90
|
-
baseHover: '.rebilly-instruments-button.rebilly-instruments-button-secondary:not([disabled]):hover',
|
|
91
|
-
baseFocus: '.rebilly-instruments-button.rebilly-instruments-button-secondary:not([disabled]):active',
|
|
92
|
-
|
|
93
|
-
active: '.rebilly-instruments-button',
|
|
94
|
-
activeHover: '.rebilly-instruments-button:not([disabled]):hover',
|
|
95
|
-
activeFocus: '.rebilly-instruments-button:not([disabled]):active',
|
|
96
|
-
}
|
|
97
|
-
}
|
|
55
|
+
const resolvedCssVarsObj = replaceCssVars(fullCss);
|
|
98
56
|
|
|
99
57
|
const framepayStyle = {
|
|
100
58
|
base: {
|
|
101
|
-
...getStyleProps(
|
|
102
|
-
':hover': getStyleProps(
|
|
103
|
-
':focus': getStyleProps(
|
|
104
|
-
'::placeholder': getStyleProps(
|
|
105
|
-
'::selection': getStyleProps(
|
|
59
|
+
...getStyleProps(resolvedCssVarsObj, 'input'),
|
|
60
|
+
':hover': getStyleProps(resolvedCssVarsObj, 'inputHover'),
|
|
61
|
+
':focus': getStyleProps(resolvedCssVarsObj, 'inputFocus'),
|
|
62
|
+
'::placeholder': getStyleProps(resolvedCssVarsObj, 'inputPlaceholder'),
|
|
63
|
+
'::selection': getStyleProps(resolvedCssVarsObj, 'inputSelection'),
|
|
106
64
|
},
|
|
107
65
|
invalid: {
|
|
108
|
-
...getStyleProps(
|
|
109
|
-
':hover': getStyleProps(
|
|
110
|
-
':focus': getStyleProps(
|
|
111
|
-
'::placeholder': getStyleProps(
|
|
112
|
-
'::selection': getStyleProps(
|
|
66
|
+
...getStyleProps(resolvedCssVarsObj, 'inputError'),
|
|
67
|
+
':hover': getStyleProps(resolvedCssVarsObj, 'inputErrorHover'),
|
|
68
|
+
':focus': getStyleProps(resolvedCssVarsObj, 'inputErrorFocus'),
|
|
69
|
+
'::placeholder': getStyleProps(resolvedCssVarsObj, 'inputErrorPlaceholder'),
|
|
70
|
+
'::selection': getStyleProps(resolvedCssVarsObj, 'inputErrorSelection'),
|
|
113
71
|
},
|
|
114
72
|
buttons: {
|
|
115
73
|
base: {
|
|
116
|
-
...getStyleProps(
|
|
117
|
-
':hover': getStyleProps(
|
|
118
|
-
':focus': getStyleProps(
|
|
74
|
+
...getStyleProps(resolvedCssVarsObj, 'buttonSecondary'),
|
|
75
|
+
':hover': getStyleProps(resolvedCssVarsObj, 'buttonSecondaryHover'),
|
|
76
|
+
':focus': getStyleProps(resolvedCssVarsObj, 'buttonSecondaryActive'),
|
|
119
77
|
},
|
|
120
78
|
active: {
|
|
121
|
-
...getStyleProps(
|
|
122
|
-
':hover': getStyleProps(
|
|
123
|
-
':focus': getStyleProps(
|
|
79
|
+
...getStyleProps(resolvedCssVarsObj, 'button'),
|
|
80
|
+
':hover': getStyleProps(resolvedCssVarsObj, 'buttonHover'),
|
|
81
|
+
':focus': getStyleProps(resolvedCssVarsObj, 'buttonActive'),
|
|
124
82
|
}
|
|
125
83
|
}
|
|
126
84
|
}
|
|
@@ -5,7 +5,7 @@ export const defaults = {
|
|
|
5
5
|
countryCode: 'US',
|
|
6
6
|
locale: 'auto',
|
|
7
7
|
theme: {
|
|
8
|
-
labels: '
|
|
8
|
+
labels: 'stacked'
|
|
9
9
|
},
|
|
10
10
|
paymentInstruments: {
|
|
11
11
|
address: {
|
|
@@ -15,7 +15,7 @@ export const defaults = {
|
|
|
15
15
|
show: [],
|
|
16
16
|
require: []
|
|
17
17
|
},
|
|
18
|
-
compactExpressInstruments:
|
|
18
|
+
compactExpressInstruments: false,
|
|
19
19
|
googlePay: {
|
|
20
20
|
displayOptions: {
|
|
21
21
|
buttonColor: 'black',
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mainStyleVars } from '../../style';
|
|
2
2
|
import { addDOMElement } from '../../utils';
|
|
3
|
+
import { minifyCss } from '../../style/utils/minifyCss';
|
|
3
4
|
|
|
4
|
-
export default
|
|
5
|
+
export default ({
|
|
5
6
|
options: {
|
|
6
7
|
theme = {},
|
|
7
8
|
css,
|
|
8
9
|
}
|
|
9
10
|
} = {}) => {
|
|
10
|
-
// Adds base stylesheet
|
|
11
|
-
const
|
|
11
|
+
// Adds base CSS vars stylesheet
|
|
12
|
+
const styleVars = mainStyleVars(theme || {});
|
|
13
|
+
|
|
12
14
|
addDOMElement({
|
|
13
15
|
element: 'style',
|
|
14
16
|
attributes: { type: 'text/css' },
|
|
15
|
-
content:
|
|
17
|
+
content: minifyCss(styleVars),
|
|
16
18
|
target: 'head'
|
|
17
19
|
});
|
|
18
20
|
|
|
@@ -21,10 +23,10 @@ export default async ({
|
|
|
21
23
|
addDOMElement({
|
|
22
24
|
element: 'style',
|
|
23
25
|
attributes: { type: 'text/css' },
|
|
24
|
-
content: css,
|
|
26
|
+
content: minifyCss(css),
|
|
25
27
|
target: 'head'
|
|
26
28
|
});
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
return
|
|
31
|
+
return styleVars;
|
|
30
32
|
}
|
|
@@ -2,6 +2,7 @@ import { postPurchase, postPayment } from '../storefront/purchase';
|
|
|
2
2
|
import Events from '../events';
|
|
3
3
|
import { mountModal } from '../views/modal';
|
|
4
4
|
import { DataInstance } from './mount/fetch-data';
|
|
5
|
+
import { showError } from '../views/errors';
|
|
5
6
|
|
|
6
7
|
export async function makePayment({ state, payload }) {
|
|
7
8
|
const {
|
|
@@ -109,11 +110,7 @@ export async function purchase({ state, payload }) {
|
|
|
109
110
|
}
|
|
110
111
|
return fields;
|
|
111
112
|
} catch (error) {
|
|
112
|
-
|
|
113
|
-
console.error(error);
|
|
114
|
-
if(error.status === 422) {
|
|
115
|
-
error.details.forEach(e => console.error(e));
|
|
116
|
-
}
|
|
113
|
+
showError(error);
|
|
117
114
|
return error;
|
|
118
115
|
}
|
|
119
116
|
}
|
package/src/functions/setup.js
CHANGED
|
@@ -2,7 +2,8 @@ import { setupPaymentInstrument } from '../storefront/payment-instruments';
|
|
|
2
2
|
import Events from '../events';
|
|
3
3
|
import { mountModal } from '../views/modal';
|
|
4
4
|
import { DataInstance } from './mount/fetch-data';
|
|
5
|
-
|
|
5
|
+
import { showError } from '../views/errors';
|
|
6
|
+
|
|
6
7
|
export async function setup({ state, payload }) {
|
|
7
8
|
try {
|
|
8
9
|
const {
|
|
@@ -56,11 +57,7 @@ export async function setup({ state, payload }) {
|
|
|
56
57
|
|
|
57
58
|
return {instrument, transaction};
|
|
58
59
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
console.error(error);
|
|
61
|
-
if(error.status === 422) {
|
|
62
|
-
error.details.forEach(e => console.error(e));
|
|
63
|
-
}
|
|
60
|
+
showError(error);
|
|
64
61
|
return error;
|
|
65
62
|
}
|
|
66
63
|
}
|
package/src/functions/show.js
CHANGED
|
@@ -16,14 +16,14 @@ import { mountResult } from '../views/result';
|
|
|
16
16
|
export async function show({ componentName, payload, state }) {
|
|
17
17
|
switch (componentName) {
|
|
18
18
|
case 'result':
|
|
19
|
-
state.iframeComponents = state.iframeComponents.filter((iframe) => {
|
|
19
|
+
state.iframeComponents.form = state.iframeComponents.form.filter((iframe) => {
|
|
20
20
|
iframe.destroy();
|
|
21
21
|
return false;
|
|
22
22
|
});
|
|
23
23
|
mountResult({payload, state});
|
|
24
24
|
break;
|
|
25
25
|
case 'confirmation':
|
|
26
|
-
state.iframeComponents = state.iframeComponents.filter((iframe) => {
|
|
26
|
+
state.iframeComponents.form = state.iframeComponents.form.filter((iframe) => {
|
|
27
27
|
iframe.destroy();
|
|
28
28
|
return false;
|
|
29
29
|
});
|
|
@@ -12,7 +12,7 @@ describe('RebillyInstruments show', () => {
|
|
|
12
12
|
.mockReturnValue(Promise.resolve());
|
|
13
13
|
|
|
14
14
|
const instance = new RebillyInstrumentsInstance();
|
|
15
|
-
instance.state.iframeComponents.push(iframeMock);
|
|
15
|
+
instance.state.iframeComponents.form.push(iframeMock);
|
|
16
16
|
|
|
17
17
|
const payload = {
|
|
18
18
|
test: 'value'
|
|
@@ -22,7 +22,7 @@ describe('RebillyInstruments show', () => {
|
|
|
22
22
|
|
|
23
23
|
expect(mountResult).toBeCalledTimes(1);
|
|
24
24
|
expect(mountResult).toBeCalledWith({payload, state: instance.state});
|
|
25
|
-
expect(instance.state.iframeComponents).toEqual([]);
|
|
25
|
+
expect(instance.state.iframeComponents.form).toEqual([]);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it('should show confirmation component', async () => {
|
|
@@ -31,7 +31,7 @@ describe('RebillyInstruments show', () => {
|
|
|
31
31
|
.mockReturnValue(Promise.resolve());
|
|
32
32
|
|
|
33
33
|
const instance = new RebillyInstrumentsInstance();
|
|
34
|
-
instance.state.iframeComponents.push(iframeMock);
|
|
34
|
+
instance.state.iframeComponents.form.push(iframeMock);
|
|
35
35
|
|
|
36
36
|
const payload = {
|
|
37
37
|
test: 'value'
|
|
@@ -41,7 +41,7 @@ describe('RebillyInstruments show', () => {
|
|
|
41
41
|
|
|
42
42
|
expect(mountConfirmation).toBeCalledTimes(1);
|
|
43
43
|
expect(mountConfirmation).toBeCalledWith({payload, state: instance.state});
|
|
44
|
-
expect(instance.state.iframeComponents).toEqual([]);
|
|
44
|
+
expect(instance.state.iframeComponents.form).toEqual([]);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
it('should fail for non supported component', async () => {
|
|
@@ -31,7 +31,7 @@ describe('RebillyInstruments Update', () => {
|
|
|
31
31
|
call
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
-
rebillyInstruments.state.iframeComponents = [fakeIFrameComponent];
|
|
34
|
+
rebillyInstruments.state.iframeComponents.form = [fakeIFrameComponent];
|
|
35
35
|
|
|
36
36
|
await rebillyInstruments.update({ locale: 'ja' });
|
|
37
37
|
|
|
@@ -58,7 +58,7 @@ describe('RebillyInstruments Update', () => {
|
|
|
58
58
|
call
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
|
-
rebillyInstruments.state.iframeComponents = [fakeIFrameComponent];
|
|
61
|
+
rebillyInstruments.state.iframeComponents.form = [fakeIFrameComponent];
|
|
62
62
|
|
|
63
63
|
await rebillyInstruments.update({
|
|
64
64
|
countryCode: 'ES'
|
|
@@ -83,7 +83,8 @@ describe('RebillyInstruments Update', () => {
|
|
|
83
83
|
call
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
|
|
87
|
+
rebillyInstruments.state.iframeComponents.form = [fakeIFrameComponent];
|
|
87
88
|
|
|
88
89
|
await rebillyInstruments.update({
|
|
89
90
|
items: [
|
package/src/instance.js
CHANGED
|
@@ -18,7 +18,10 @@ export class InstrumentsState {
|
|
|
18
18
|
this.summary = null;
|
|
19
19
|
this.loader = new Loader();
|
|
20
20
|
this.translate = new Translate();
|
|
21
|
-
this.iframeComponents =
|
|
21
|
+
this.iframeComponents = {
|
|
22
|
+
summary: [],
|
|
23
|
+
form: [],
|
|
24
|
+
};
|
|
22
25
|
this.hasMounted = false;
|
|
23
26
|
}
|
|
24
27
|
}
|
package/src/loader/index.js
CHANGED
|
@@ -1,54 +1,86 @@
|
|
|
1
1
|
import isDOMElement from '../utils/is-dom-element';
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
<div class="rebilly-instruments-loader
|
|
5
|
-
<div class="
|
|
6
|
-
<
|
|
3
|
+
export const summaryLoaderHTML = `
|
|
4
|
+
<div class="rebilly-instruments-summary-loader-total rebilly-instruments-loader-display-flex rebilly-instruments-loader-align-center rebilly-instruments-loader-justify-space-between">
|
|
5
|
+
<div><p class="is-el-loading">Total</p></div>
|
|
6
|
+
<p class="total is-el-loading">$99.99</p>
|
|
7
7
|
</div>
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
export const methodsLoaderHTML = `
|
|
11
|
+
<div class="rebilly-instruments-methods-loader">
|
|
12
|
+
<div class="rebilly-instruments-loader-form-el is-el-loading"></div>
|
|
13
|
+
<div class="rebilly-instruments-divider">
|
|
14
|
+
<span class="rebilly-instruments-divider-label"><span class="is-el-loading">Divi</span></span>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="rebilly-instruments-loader-display-flex rebilly-instruments-loader-justify-end">
|
|
17
|
+
<div class="rebilly-instruments-methods-loader-card-icon is-el-loading"></div>
|
|
18
|
+
<div class="rebilly-instruments-methods-loader-card-icon is-el-loading"></div>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="rebilly-instruments-loader-form-el is-el-loading"></div>
|
|
21
|
+
<div class="rebilly-instruments-methods-loader-form-fields">
|
|
22
|
+
<div class="rebilly-instruments-loader-form-label"><small class="is-el-loading">Card holder name</small></div>
|
|
23
|
+
<div class="rebilly-instruments-loader-form-el is-el-loading"></div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="rebilly-instruments-loader-form-el is-button">Continue</div>
|
|
26
|
+
</div>
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const loaderContainer = (padding = '0px') => `
|
|
30
|
+
<div class="rebilly-instruments-loader is-active" style="padding: ${padding}"></div>
|
|
8
31
|
`
|
|
9
32
|
|
|
33
|
+
export const basicLoaderHTML = `
|
|
34
|
+
<div class="rebilly-instruments-loader-spinner"></div>
|
|
35
|
+
`;
|
|
36
|
+
|
|
10
37
|
export class Loader {
|
|
11
38
|
constructor() {
|
|
12
39
|
this.summary = [];
|
|
13
40
|
this.form = [];
|
|
14
41
|
this.modal = [];
|
|
15
42
|
this.DOM = {
|
|
16
|
-
|
|
43
|
+
loaderContainer,
|
|
44
|
+
summaryLoaderHTML,
|
|
45
|
+
methodsLoaderHTML,
|
|
46
|
+
basicLoaderHTML
|
|
17
47
|
};
|
|
18
48
|
}
|
|
19
49
|
|
|
20
50
|
addDOMElement({ section = 'form', el = null } = {}) {
|
|
21
51
|
if (isDOMElement(el)) {
|
|
22
52
|
el.style.position = 'relative';
|
|
23
|
-
|
|
24
53
|
this.DOM[section] = el;
|
|
25
54
|
}
|
|
26
55
|
}
|
|
27
56
|
|
|
28
|
-
startLoading({
|
|
29
|
-
const minHeight = '200px';
|
|
57
|
+
startLoading({section = 'form', id = ''} = {}) {
|
|
30
58
|
this[section].push(id);
|
|
31
59
|
|
|
60
|
+
const rootEl = document.querySelector(':root');
|
|
61
|
+
const contentPadding = 2;
|
|
62
|
+
let minHeight = '240px';
|
|
63
|
+
|
|
32
64
|
if (this.DOM?.[section]) {
|
|
33
|
-
|
|
34
|
-
|
|
65
|
+
let loaderEl = this.DOM[section].querySelector('.rebilly-instruments-loader');
|
|
66
|
+
const { padding, paddingTop, paddingBottom } = getComputedStyle(this.DOM?.[section]);
|
|
67
|
+
if (!loaderEl) {
|
|
68
|
+
this.DOM[section].innerHTML = loaderContainer(`${parseFloat(padding) + contentPadding}px`);
|
|
69
|
+
loaderEl = this.DOM[section].querySelector('.rebilly-instruments-loader');
|
|
70
|
+
if (section === 'form') {
|
|
71
|
+
loaderEl.insertAdjacentHTML('afterbegin', this.DOM.methodsLoaderHTML);
|
|
72
|
+
minHeight = getComputedStyle(rootEl).getPropertyValue('--rebilly-methodLoaderMinHeight');
|
|
73
|
+
} else if (section === 'summary') {
|
|
74
|
+
loaderEl.insertAdjacentHTML('afterbegin', this.DOM.summaryLoaderHTML);
|
|
75
|
+
minHeight = getComputedStyle(rootEl).getPropertyValue('--rebilly-summaryLoaderMinHeight');
|
|
76
|
+
}
|
|
35
77
|
} else {
|
|
36
|
-
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.DOM[section].style.minHeight = minHeight;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (message) {
|
|
44
|
-
const loaderMessage = this.DOM[section].querySelector('.rebilly-instuments-loader-message');
|
|
45
|
-
if (loaderMessage) {
|
|
46
|
-
loaderMessage.innerHTML = message;
|
|
47
|
-
loaderMessage.style.marginTop = '10px';
|
|
48
|
-
loaderMessage.setAttribute('data-message-id', id);
|
|
49
|
-
loaderMessage.setAttribute('data-rebilly-i18n', message);
|
|
50
|
-
state.i18n({state});
|
|
78
|
+
if (id.includes('confirmation') || id.includes('result') || id.includes('modal')) {
|
|
79
|
+
loaderEl.innerHTML = this.DOM.basicLoaderHTML;
|
|
80
|
+
}
|
|
81
|
+
loaderEl.classList.add('is-active');
|
|
51
82
|
}
|
|
83
|
+
this.DOM[section].style.minHeight = `calc(${minHeight} + ${paddingTop} + ${paddingBottom} + ${contentPadding * 2}px)`;
|
|
52
84
|
}
|
|
53
85
|
}
|
|
54
86
|
|
|
@@ -68,14 +100,6 @@ export class Loader {
|
|
|
68
100
|
.classList.remove('is-active');
|
|
69
101
|
this.DOM[section].style.minHeight = '';
|
|
70
102
|
}
|
|
71
|
-
|
|
72
|
-
const loaderMessage = this.DOM[section].querySelector(`.rebilly-instuments-loader-message[data-message-id="${id}"]`);
|
|
73
|
-
if (loaderMessage) {
|
|
74
|
-
loaderMessage.innerHTML = null;
|
|
75
|
-
loaderMessage.style.marginTop = '0px';
|
|
76
|
-
loaderMessage.removeAttribute('data-message-id');
|
|
77
|
-
loaderMessage.removeAttribute('data-rebilly-i18n');
|
|
78
|
-
}
|
|
79
103
|
}
|
|
80
104
|
|
|
81
105
|
clearAll() {
|