@rebilly/instruments 2.1.1-beta.0 → 3.1.1-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.
Files changed (192) hide show
  1. package/dist/index.js +88 -107
  2. package/dist/index.min.js +88 -0
  3. package/package.json +18 -5
  4. package/rollup.config.js +84 -0
  5. package/src/functions/mount/fetch-data.js +16 -0
  6. package/src/functions/mount/index.js +8 -42
  7. package/src/functions/mount/mount.spec.js +3 -5
  8. package/src/functions/mount/setup-framepay-theme.js +82 -0
  9. package/src/functions/mount/setup-options.js +6 -0
  10. package/src/functions/mount/setup-user-flow.js +49 -0
  11. package/src/functions/purchase.js +1 -1
  12. package/src/functions/setup.js +1 -1
  13. package/src/functions/show.spec.js +1 -1
  14. package/src/i18n/en.json +4 -1
  15. package/src/i18n/index.js +1 -1
  16. package/src/index.js +1 -61
  17. package/src/instance.js +65 -0
  18. package/src/{index.spec.js → instance.spec.js} +2 -1
  19. package/src/loader/index.js +21 -1
  20. package/src/storefront/models/ready-to-pay-model.js +13 -2
  21. package/src/storefront/plans.js +8 -4
  22. package/src/storefront/plans.spec.js +8 -2
  23. package/src/storefront/products.js +8 -4
  24. package/src/storefront/products.spec.js +8 -2
  25. package/src/storefront/ready-to-pay.js +5 -4
  26. package/src/style/base/__snapshots__/theme.spec.js.snap +220 -45
  27. package/src/style/base/default-theme.js +777 -0
  28. package/src/style/base/index.js +48 -16
  29. package/src/style/base/theme.js +17 -47
  30. package/src/style/base/theme.spec.js +4 -16
  31. package/src/style/components/address.js +3 -3
  32. package/src/style/components/button.js +48 -24
  33. package/src/style/components/divider.js +9 -9
  34. package/src/style/components/forms/checkbox.js +11 -11
  35. package/src/style/components/forms/field.js +18 -6
  36. package/src/style/components/forms/form.js +2 -2
  37. package/src/style/components/forms/input.js +54 -13
  38. package/src/style/components/forms/label.js +39 -18
  39. package/src/style/components/forms/select.js +54 -22
  40. package/src/style/components/forms/validation.js +53 -6
  41. package/src/style/components/icons.js +4 -4
  42. package/src/style/components/loader.js +6 -6
  43. package/src/style/components/methods.js +18 -15
  44. package/src/style/components/overlay.js +5 -5
  45. package/src/style/helpers/index.js +46 -46
  46. package/src/style/index.js +2 -1
  47. package/src/style/payment-instruments/payment-card.js +6 -5
  48. package/src/style/utils/border.js +34 -0
  49. package/src/style/utils/color-values.js +27 -1
  50. package/src/style/utils/remove-empty-null.js +10 -0
  51. package/src/style/vendor/framepay.js +11 -8
  52. package/src/style/vendor/postmate.js +15 -2
  53. package/src/style/views/confirmation.js +15 -14
  54. package/src/style/views/method-selector.js +2 -2
  55. package/src/style/views/modal.js +6 -6
  56. package/src/style/views/result.js +4 -4
  57. package/src/style/views/summary.js +23 -23
  58. package/src/views/__snapshots__/summary.spec.js.snap +4 -40
  59. package/src/views/common/iframe/base-iframe.js +2 -0
  60. package/src/views/common/iframe/event-listeners.js +10 -0
  61. package/src/views/common/iframe/method-iframe.js +3 -1
  62. package/src/views/common/iframe/modal-iframe.js +7 -1
  63. package/src/views/confirmation.js +1 -0
  64. package/src/views/method-selector/express-methods/{google-pay.js → index.js} +3 -2
  65. package/src/views/method-selector/mount-express-methods.js +6 -18
  66. package/src/views/result.js +1 -0
  67. package/src/views/summary.js +17 -11
  68. package/tests/mocks/rebilly-instruments-mock.js +2 -2
  69. package/dist/events/base-event.js +0 -66
  70. package/dist/events/events.spec.js +0 -18
  71. package/dist/events/index.js +0 -22
  72. package/dist/functions/destroy.js +0 -34
  73. package/dist/functions/destroy.spec.js +0 -69
  74. package/dist/functions/mount/fetch-data.js +0 -183
  75. package/dist/functions/mount/fetch-data.spec.js +0 -189
  76. package/dist/functions/mount/index.js +0 -212
  77. package/dist/functions/mount/mount.spec.js +0 -66
  78. package/dist/functions/mount/setup-element.js +0 -40
  79. package/dist/functions/mount/setup-framepay.js +0 -46
  80. package/dist/functions/mount/setup-i18n.js +0 -33
  81. package/dist/functions/mount/setup-options.js +0 -96
  82. package/dist/functions/mount/setup-options.spec.js +0 -66
  83. package/dist/functions/mount/setup-storefront.js +0 -34
  84. package/dist/functions/mount/setup-styles.js +0 -43
  85. package/dist/functions/on.js +0 -40
  86. package/dist/functions/on.spec.js +0 -55
  87. package/dist/functions/purchase.js +0 -158
  88. package/dist/functions/purchase.spec.js +0 -74
  89. package/dist/functions/setup.js +0 -85
  90. package/dist/functions/setup.spec.js +0 -87
  91. package/dist/functions/show.js +0 -55
  92. package/dist/functions/show.spec.js +0 -61
  93. package/dist/functions/update.js +0 -74
  94. package/dist/functions/update.spec.js +0 -86
  95. package/dist/i18n/en.json +0 -22
  96. package/dist/i18n/es.json +0 -22
  97. package/dist/i18n/i18n.spec.js +0 -22
  98. package/dist/i18n/index.js +0 -72
  99. package/dist/index.spec.js +0 -35
  100. package/dist/loader/index.js +0 -94
  101. package/dist/loader/loader.spec.js +0 -69
  102. package/dist/storefront/index.js +0 -73
  103. package/dist/storefront/invoices.js +0 -27
  104. package/dist/storefront/models/base-model.js +0 -18
  105. package/dist/storefront/models/invoice-model.js +0 -14
  106. package/dist/storefront/models/plan-model.js +0 -14
  107. package/dist/storefront/models/product-model.js +0 -14
  108. package/dist/storefront/models/ready-to-pay-model.js +0 -46
  109. package/dist/storefront/models/summary-model.js +0 -79
  110. package/dist/storefront/models/transaction-model.js +0 -31
  111. package/dist/storefront/payment-instruments.js +0 -47
  112. package/dist/storefront/payment-instruments.spec.js +0 -55
  113. package/dist/storefront/plans.js +0 -37
  114. package/dist/storefront/plans.spec.js +0 -64
  115. package/dist/storefront/products.js +0 -40
  116. package/dist/storefront/products.spec.js +0 -65
  117. package/dist/storefront/purchase.js +0 -43
  118. package/dist/storefront/purchase.spec.js +0 -48
  119. package/dist/storefront/ready-to-pay.js +0 -58
  120. package/dist/storefront/ready-to-pay.spec.js +0 -69
  121. package/dist/storefront/storefront.spec.js +0 -15
  122. package/dist/storefront/summary.js +0 -55
  123. package/dist/storefront/summary.spec.js +0 -124
  124. package/dist/storefront/transactions.js +0 -27
  125. package/dist/style/base/__snapshots__/theme.spec.js.snap +0 -52
  126. package/dist/style/base/index.js +0 -72
  127. package/dist/style/base/theme.js +0 -74
  128. package/dist/style/base/theme.spec.js +0 -30
  129. package/dist/style/browserslist.js +0 -8
  130. package/dist/style/components/address.js +0 -64
  131. package/dist/style/components/button.js +0 -61
  132. package/dist/style/components/divider.js +0 -48
  133. package/dist/style/components/forms/checkbox.js +0 -83
  134. package/dist/style/components/forms/field.js +0 -53
  135. package/dist/style/components/forms/form.js +0 -28
  136. package/dist/style/components/forms/input.js +0 -45
  137. package/dist/style/components/forms/label.js +0 -43
  138. package/dist/style/components/forms/select.js +0 -63
  139. package/dist/style/components/forms/validation.js +0 -34
  140. package/dist/style/components/icons.js +0 -22
  141. package/dist/style/components/index.js +0 -57
  142. package/dist/style/components/loader.js +0 -48
  143. package/dist/style/components/methods.js +0 -105
  144. package/dist/style/components/overlay.js +0 -33
  145. package/dist/style/helpers/index.js +0 -59
  146. package/dist/style/index.js +0 -48
  147. package/dist/style/payment-instruments/content.js +0 -17
  148. package/dist/style/payment-instruments/index.js +0 -20
  149. package/dist/style/payment-instruments/payment-card.js +0 -35
  150. package/dist/style/utils/color-values.js +0 -22
  151. package/dist/style/vendor/framepay.js +0 -34
  152. package/dist/style/vendor/postmate.js +0 -17
  153. package/dist/style/views/confirmation.js +0 -85
  154. package/dist/style/views/index.js +0 -29
  155. package/dist/style/views/method-selector.js +0 -20
  156. package/dist/style/views/modal.js +0 -93
  157. package/dist/style/views/result.js +0 -61
  158. package/dist/style/views/summary.js +0 -127
  159. package/dist/utils/add-dom-element.js +0 -26
  160. package/dist/utils/format-currency.js +0 -15
  161. package/dist/utils/has-valid-css-selector.js +0 -11
  162. package/dist/utils/index.js +0 -55
  163. package/dist/utils/is-dom-element.js +0 -10
  164. package/dist/utils/process-property-as-dom-element.js +0 -38
  165. package/dist/utils/sleep.js +0 -10
  166. package/dist/views/__snapshots__/summary.spec.js.snap +0 -282
  167. package/dist/views/common/iframe/base-iframe.js +0 -59
  168. package/dist/views/common/iframe/event-listeners.js +0 -50
  169. package/dist/views/common/iframe/index.js +0 -19
  170. package/dist/views/common/iframe/method-iframe.js +0 -33
  171. package/dist/views/common/iframe/modal-iframe.js +0 -79
  172. package/dist/views/common/iframe/view-iframe.js +0 -31
  173. package/dist/views/common/render-utilities.js +0 -11
  174. package/dist/views/confirmation.js +0 -92
  175. package/dist/views/method-selector/__snapshots__/method-selector.spec.js.snap +0 -3
  176. package/dist/views/method-selector/express-methods/apple-pay.js +0 -92
  177. package/dist/views/method-selector/express-methods/google-pay.js +0 -31
  178. package/dist/views/method-selector/express-methods/paypal.js +0 -19
  179. package/dist/views/method-selector/generate-digital-wallet.js +0 -68
  180. package/dist/views/method-selector/generate-digital-wallet.spec.js +0 -135
  181. package/dist/views/method-selector/get-method-data.js +0 -25
  182. package/dist/views/method-selector/get-payment-methods.js +0 -66
  183. package/dist/views/method-selector/get-payment-methods.spec.js +0 -46
  184. package/dist/views/method-selector/index.js +0 -122
  185. package/dist/views/method-selector/method-selector.spec.js +0 -124
  186. package/dist/views/method-selector/mount-express-methods.js +0 -69
  187. package/dist/views/method-selector/mount-methods.js +0 -74
  188. package/dist/views/modal.js +0 -88
  189. package/dist/views/result.js +0 -40
  190. package/dist/views/summary.js +0 -209
  191. package/dist/views/summary.spec.js +0 -134
  192. package/src/views/method-selector/express-methods/paypal.js +0 -7
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@rebilly/instruments",
3
- "version": "2.1.1-beta.0",
3
+ "version": "3.1.1-beta.0",
4
4
  "author": "Rebilly",
5
5
  "main": "dist/index.js",
6
+ "unpkg": "dist/index.min.js",
6
7
  "license": "MIT",
7
8
  "scripts": {
8
- "build": "yarn babel src --out-dir dist --copy-files",
9
- "dev": "yarn babel src --watch --out-dir dist",
9
+ "build": "yarn rollup -c --environment NODE_ENV:production",
10
+ "dev": "yarn rollup -c --watch --environment NODE_ENV:development",
10
11
  "test": "yarn jest",
11
12
  "test:watch": "yarn jest --watchAll"
12
13
  },
@@ -16,20 +17,32 @@
16
17
  "@babel/preset-env": "^7.14.7",
17
18
  "@rebilly/risk-data-collector": "^2.0.1",
18
19
  "autoprefixer": "^10.3.4",
20
+ "css": "^3.0.0",
19
21
  "lodash.camelcase": "^4.3.0",
20
22
  "lodash.isequal": "^4.5.0",
21
23
  "lodash.kebabcase": "^4.1.1",
22
24
  "lodash.merge": "^4.6.2",
23
25
  "popostmate": "^1.6.4",
24
- "postcss": "^8.3.6",
26
+ "postcss": "^8.4.5",
27
+ "postcss-css-variables": "^0.18.0",
25
28
  "rebilly-js-sdk": "^44.4.0",
26
29
  "values.js": "^2.0.0"
27
30
  },
28
31
  "devDependencies": {
32
+ "@rollup/plugin-babel": "^5.1.0",
33
+ "@rollup/plugin-commonjs": "^14.0.0",
34
+ "@rollup/plugin-json": "^4.1.0",
35
+ "@rollup/plugin-node-resolve": "^8.4.0",
36
+ "@rollup/plugin-replace": "^3.0.0",
29
37
  "babel-plugin-module-resolver": "^4.1.0",
30
38
  "component-emitter": "^1.3.0",
31
39
  "jest": "^27.0.6",
32
40
  "msw": "^0.23.0",
33
- "msw-when-then": "^1.4.0"
41
+ "msw-when-then": "^1.4.0",
42
+ "rollup": "^2.35.1",
43
+ "rollup-plugin-ignore": "^1.0.10",
44
+ "rollup-plugin-polyfill-node": "^0.8.0",
45
+ "rollup-plugin-terser": "^7.0.2",
46
+ "rollup-plugin-version-injector": "^1.3.3"
34
47
  }
35
48
  }
@@ -0,0 +1,84 @@
1
+ import babel from '@rollup/plugin-babel';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import commonjs from '@rollup/plugin-commonjs';
4
+ import json from '@rollup/plugin-json';
5
+ import replace from '@rollup/plugin-replace';
6
+ import nodePolyfills from 'rollup-plugin-polyfill-node';
7
+ import ignore from 'rollup-plugin-ignore';
8
+ import versionInjector from 'rollup-plugin-version-injector';
9
+ import { builtinModules } from 'module'
10
+ import { terser } from 'rollup-plugin-terser';
11
+
12
+ const isDevMode = (process.env.NODE_ENV === 'development');
13
+
14
+ const buildOptions = () => {
15
+ const options = [
16
+ // Locates a module in the project's node_modules
17
+ resolve({
18
+ extensions: [ '.mjs', '.js', '.jsx', '.json' ],
19
+ preferBuiltins: true,
20
+ mainFields: ['browser', 'jsnext:main', 'module', 'main']
21
+ }),
22
+ // Converts CommonJS to ES6 modules
23
+ commonjs(),
24
+ // Fix commonjs issues with virtual node
25
+ // https://github.com/proteriax/rollup-plugin-ignore/issues/3
26
+ // https://github.com/rollup/plugins/issues/248
27
+ // https://github.com/rollup/rollup-plugin-commonjs/issues/315
28
+ ignore(builtinModules, { commonjsBugFix: true }),
29
+ // Replace values at bundle time
30
+ replace({
31
+ preventAssignment: true,
32
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
33
+ }),
34
+ // Allows the use of named imports in addition to the default import on node modules
35
+ nodePolyfills(),
36
+ // Babel transpiling
37
+ babel({
38
+ exclude: 'node_modules/**',
39
+ babelHelpers: 'runtime',
40
+ skipPreflightCheck: true
41
+ }),
42
+ // Converts .json files to ES6 modules
43
+ json(),
44
+ ]
45
+ if (!isDevMode) {
46
+ options.push(
47
+ // Inject version from package.json (RebillyInstruments.version)
48
+ versionInjector(),
49
+ // Minify and reduce bundle file sizes
50
+ terser())
51
+ }
52
+ return options;
53
+ }
54
+
55
+ const buildOutput = () => {
56
+ const output = [
57
+ {
58
+ file: 'dist/index.js',
59
+ format: 'es',
60
+ sourcemap: isDevMode ? 'inline' : false,
61
+ },
62
+ ]
63
+ if (!isDevMode) {
64
+ output.push(
65
+ {
66
+ file: 'dist/index.min.js',
67
+ format: 'iife',
68
+ name: 'RebillyInstruments',
69
+ exports: 'default'
70
+ },
71
+ )
72
+ }
73
+ return output;
74
+ }
75
+
76
+ export default {
77
+ input: 'src/index.js',
78
+ output: [
79
+ ...buildOutput(),
80
+ ],
81
+ plugins: [
82
+ ...buildOptions(),
83
+ ],
84
+ };
@@ -81,6 +81,22 @@ export class DataInstance {
81
81
 
82
82
  return lineItems;
83
83
  }
84
+
85
+ get isShippingRequired() {
86
+ return (this.products || []).some(product => product.requiresShipping);
87
+ }
88
+
89
+ toPostmatesModel() {
90
+ return {
91
+ ...this,
92
+ amountAndCurrency: this.amountAndCurrency,
93
+ isPayment: this.isPayment,
94
+ isPurchase: this.isPurchase,
95
+ summaryItems: this.summaryItems,
96
+ summaryLineItems: this.summaryLineItems,
97
+ isShippingRequired: this.isShippingRequired
98
+ }
99
+ }
84
100
  }
85
101
 
86
102
  export async function fetchData({
@@ -2,14 +2,14 @@
2
2
  import { mountSummary } from '../../views/summary';
3
3
  import { mountMethodSelector } from '../../views/method-selector';
4
4
  import { fetchData } from './fetch-data';
5
- import { show } from '../show';
6
- import { on } from '../on';
7
5
  import setupElement from './setup-element';
8
6
  import setupStorefront from './setup-storefront';
9
7
  import setupOptions from './setup-options';
10
8
  import setupFramepay from './setup-framepay';
11
9
  import setupStyles from './setup-styles';
12
10
  import setupI18n from './setup-i18n';
11
+ import setupFramepayTheme from './setup-framepay-theme';
12
+ import setupUserFlow from './setup-user-flow';
13
13
 
14
14
  /**
15
15
  * @typedef {object} Item
@@ -80,6 +80,7 @@ export async function mount({
80
80
  try {
81
81
  state.data = {};
82
82
  state.options = {};
83
+
83
84
  // Setup DOM
84
85
  state.form = setupElement({ element: 'form', options });
85
86
  state.summary = setupElement({ element: 'summary', options });
@@ -95,7 +96,9 @@ export async function mount({
95
96
  state.options = setupOptions({ options });
96
97
  state.mainStyle = await setupStyles({ options });
97
98
  state.data = await fetchData({ state });
98
- const i18n = setupI18n({ state });
99
+ state.options.themeFramepay = await setupFramepayTheme({ state, options });
100
+ state.i18n = setupI18n({ state });
101
+
99
102
  setupFramepay({ state });
100
103
 
101
104
  if (state.data.transaction && state.data.transaction?.type === 'setup') {
@@ -109,48 +112,11 @@ export async function mount({
109
112
  if (state.summary) {
110
113
  mountSummary({ state });
111
114
  }
112
- i18n({state});
115
+ state.i18n({state});
113
116
  state.hasMounted = true;
114
117
  } catch (error) {
115
118
  throw error;
116
119
  }
117
120
 
118
- if (state.options.features.autoConfirmation) {
119
- on({
120
- eventName: 'instrument-ready',
121
- callback: (payload) => {
122
- show({
123
- componentName: 'confirmation',
124
- payload,
125
- state
126
- });
127
- }
128
- });
129
- }
130
-
131
- if (state.options.features.autoResult) {
132
- if (state.options.transactionType === 'setup') {
133
- on({
134
- eventName: 'setup-completed',
135
- callback: (payload) => {
136
- show({
137
- componentName: 'result',
138
- payload,
139
- state
140
- });
141
- }
142
- });
143
- } else {
144
- on({
145
- eventName: 'purchase-completed',
146
- callback: (payload) => {
147
- show({
148
- componentName: 'result',
149
- payload,
150
- state
151
- });
152
- }
153
- });
154
- }
155
- }
121
+ setupUserFlow({state});
156
122
  }
@@ -23,9 +23,7 @@ describe('RebillyInstruments instance', () => {
23
23
  }
24
24
  ],
25
25
  theme: {
26
- color: {
27
- background: '#000'
28
- }
26
+ colorBackground: '#000'
29
27
  },
30
28
  css: `
31
29
  .rebilly-instruments-summary-line-item-synopsis-title {
@@ -47,8 +45,8 @@ describe('RebillyInstruments instance', () => {
47
45
  const SUMMARY_CONTAINER = summarySelector.querySelector(
48
46
  '.rebilly-instruments-content'
49
47
  );
50
- expect(getComputedStyle(SUMMARY_CONTAINER).background).toEqual(
51
- 'rgb(0, 0, 0)'
48
+ expect(getComputedStyle(SUMMARY_CONTAINER).getPropertyValue('--rebilly-colorBackground')).toEqual(
49
+ '#000'
52
50
  );
53
51
 
54
52
  // CSS config property overrides initial styles
@@ -0,0 +1,82 @@
1
+ import css from 'css';
2
+ import postcss from 'postcss';
3
+ import cssvariables from 'postcss-css-variables';
4
+ import camelCase from 'lodash.camelcase';
5
+
6
+ const resolveCssVars = async (rawCss) => postcss([
7
+ cssvariables({ preserve: false })
8
+ ])
9
+ .process(rawCss, { from: undefined })
10
+ .then(output => output.css);
11
+
12
+ const getStyleProps = (ast, selector) => {
13
+ const { rules } = ast.stylesheet;
14
+ const output = {
15
+ color: null,
16
+ fontFamily: null,
17
+ fontSize: null,
18
+ lineHeight: null,
19
+ fontWeight: null,
20
+ background: null
21
+ }
22
+
23
+ for(let i = 0; i < rules.length; i += 1) {
24
+ const rule = rules[i];
25
+
26
+ if(rule.type === 'rule' && rule.selectors.includes(selector)) {
27
+ rule.declarations.forEach(decl => {
28
+ const propName = camelCase(decl.property);
29
+ if(typeof output[propName] !== 'undefined') {
30
+ output[propName] = decl.value;
31
+ }
32
+ })
33
+ }
34
+ }
35
+ return output;
36
+ }
37
+
38
+ export default async ({
39
+ state,
40
+ options = {}
41
+ }) => {
42
+ const fullCss = `
43
+ ${state.mainStyle}
44
+ ${options.css || ''}
45
+ `;
46
+
47
+ const resolvedCss = await resolveCssVars(fullCss);
48
+ const cssAst = css.parse(resolvedCss);
49
+
50
+ const cssSelectors = {
51
+ base: '.rebilly-instruments-form-field-input',
52
+ baseHover: '.rebilly-instruments-form-field-input:hover',
53
+ baseFocus: '.rebilly-instruments-form-field-input:focus',
54
+ basePlaceholder: '.rebilly-instruments-form-field-input::placeholder',
55
+ baseSelection: '.rebilly-instruments-form-field-input::selection',
56
+
57
+ invalid: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input',
58
+ invalidHover: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:hover',
59
+ invalidFocus: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:focus',
60
+ invalidPlaceholder: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::placeholder',
61
+ invalidSelection: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::selection'
62
+ }
63
+
64
+ const framepayStyle = {
65
+ base: {
66
+ ...getStyleProps(cssAst, cssSelectors.base),
67
+ ':hover': getStyleProps(cssAst, cssSelectors.baseHover),
68
+ ':focus': getStyleProps(cssAst, cssSelectors.baseFocus),
69
+ '::placeholder': getStyleProps(cssAst, cssSelectors.basePlaceholder),
70
+ '::selection': getStyleProps(cssAst, cssSelectors.baseSelection),
71
+ },
72
+ invalid: {
73
+ ...getStyleProps(cssAst, cssSelectors.invalid),
74
+ ':hover': getStyleProps(cssAst, cssSelectors.invalidHover),
75
+ ':focus': getStyleProps(cssAst, cssSelectors.invalidFocus),
76
+ '::placeholder': getStyleProps(cssAst, cssSelectors.invalidPlaceholder),
77
+ '::selection': getStyleProps(cssAst, cssSelectors.invalidSelection),
78
+ }
79
+ }
80
+
81
+ return framepayStyle;
82
+ }
@@ -3,6 +3,9 @@ import merge from 'lodash.merge';
3
3
  export const defaults = {
4
4
  countryCode: 'US',
5
5
  locale: 'auto',
6
+ theme: {
7
+ labels: 'floating'
8
+ },
6
9
  paymentInstruments: {
7
10
  address: {
8
11
  name: 'default',
@@ -28,6 +31,9 @@ export const defaults = {
28
31
  },
29
32
  paymentCard: {
30
33
  popup: false
34
+ },
35
+ paypal: {
36
+ buttonHeight: 44,
31
37
  }
32
38
  },
33
39
  transactionType: 'purchase',
@@ -0,0 +1,49 @@
1
+ import { on } from '../on';
2
+ import { show } from '../show';
3
+ import { purchase } from '../purchase';
4
+ import { setup } from '../setup';
5
+
6
+ function showResult({state, payload}) {
7
+ show({
8
+ componentName: 'result',
9
+ payload,
10
+ state
11
+ });
12
+ }
13
+
14
+ export default ({state = {}}) => {
15
+ if (state.options.features.autoConfirmation) {
16
+ on({
17
+ eventName: 'instrument-ready',
18
+ callback: (payload) => {
19
+ // Alternate flow for paypal.
20
+ if (payload._raw?.method === 'paypal') {
21
+ if (!state.data.isShippingRequired) {
22
+ if (state.options.transactionType === 'setup') {
23
+ setup({state, payload});
24
+ } else {
25
+ purchase({state, payload});
26
+ }
27
+ state.loader.startLoading({state, id: 'express-purchase', message: 'form.loaderMessages.processingPayment' });
28
+ return;
29
+ }
30
+ }
31
+ show({
32
+ componentName: 'confirmation',
33
+ payload,
34
+ state
35
+ });
36
+ }
37
+ });
38
+ }
39
+
40
+ if (state.options.features.autoResult) {
41
+ on({
42
+ eventName: state.options.transactionType === 'setup' ?
43
+ 'setup-completed' : 'purchase-completed',
44
+ callback: (payload) => {
45
+ showResult({state, payload});
46
+ }
47
+ });
48
+ }
49
+ }
@@ -93,7 +93,7 @@ export async function purchase({ state, payload }) {
93
93
  fields = await makePurchase({ state, payload });
94
94
  }
95
95
 
96
- if (fields.transaction?.approvalUrl) {
96
+ if (fields.transaction?.approvalUrl && fields.transaction?.result === 'unknown') {
97
97
  handleApprovalUrl({state, fields});
98
98
  } else {
99
99
  Events.purchaseCompleted.dispatch(fields);
@@ -16,7 +16,7 @@ export async function setup({ state, payload }) {
16
16
 
17
17
  state.data = new DataInstance({state, instrument, transaction});
18
18
 
19
- if (transaction.approvalUrl) {
19
+ if (transaction.approvalUrl && transaction.result === 'unknown') {
20
20
  const { paymentMethodsUrl } = state.options._computed;
21
21
  mountModal({
22
22
  state,
@@ -1,7 +1,7 @@
1
1
  import * as result from '@/views/result';
2
2
  import * as confirmation from '@/views/confirmation';
3
3
  import { RenderMockRebillyInstruments } from 'tests/mocks/rebilly-instruments-mock';
4
- import { RebillyInstrumentsInstance } from '../index';
4
+ import { RebillyInstrumentsInstance } from '../instance';
5
5
 
6
6
  const iframeMock = { destroy: jest.fn() };
7
7
 
package/src/i18n/en.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "en": {
3
3
  "summary": {
4
4
  "subTotal": "Sub Total",
5
- "discounts": "Discouts",
5
+ "discounts": "Discounts",
6
6
  "taxes": "Taxes",
7
7
  "shipping": "Shipping",
8
8
  "total": "Total"
@@ -13,6 +13,9 @@
13
13
  "popupOverlayText": "Click here to show popup window",
14
14
  "error": {
15
15
  "noPaymentMethods": "No payment methods available for this transaction, please contact support."
16
+ },
17
+ "loaderMessages": {
18
+ "processingPayment": "Processing payment instrument."
16
19
  }
17
20
  },
18
21
  "paymentMethods": {
package/src/i18n/index.js CHANGED
@@ -12,7 +12,7 @@ export class Translate {
12
12
  init(locale, messages) {
13
13
  this.items = document.querySelectorAll('[data-rebilly-i18n]');
14
14
  this.locale = this.getLocale(locale);
15
- this.languages = merge({ ...en, ...es }, messages);
15
+ this.languages = merge({}, { ...en, ...es }, messages);
16
16
  }
17
17
 
18
18
  translateItems() {
package/src/index.js CHANGED
@@ -1,63 +1,3 @@
1
- import { mount } from './functions/mount';
2
- import { purchase } from './functions/purchase';
3
- import { setup } from './functions/setup';
4
- import { on } from './functions/on';
5
- import { update } from './functions/update';
6
- import { destroy } from './functions/destroy';
7
- import { Loader } from './loader';
8
- import { Translate } from './i18n';
9
- import { show } from './functions/show';
10
-
11
- export class InstrumentsState {
12
- constructor() {
13
- this.options = null;
14
- this.data = {};
15
- this.mountingPoints = null;
16
- this.storefront = null;
17
- this.form = null;
18
- this.summary = null;
19
- this.loader = new Loader();
20
- this.translate = new Translate();
21
- this.iframeComponents = [];
22
- this.hasMounted = false;
23
- }
24
- }
25
-
26
- export class RebillyInstrumentsInstance {
27
- constructor() {
28
- this.state = new InstrumentsState();
29
- // TODO: mountConfirmation, mountResult have different contract shape when they look similar
30
- // TODO: review test coverage of UpdateSummary and UpdateMethodSelector as no tests were broken
31
- // when commenting them
32
- }
33
-
34
- async mount(options) {
35
- await mount({ state: this.state, ...options });
36
- }
37
-
38
- async destroy() {
39
- await destroy({ state: this.state });
40
- }
41
-
42
- async update(newOptions) {
43
- await update({state: this.state, newOptions});
44
- }
45
-
46
- async purchase(payload) {
47
- await purchase({ state: this.state, payload });
48
- }
49
-
50
- async setup(payload) {
51
- await setup({ state: this.state, payload });
52
- }
53
-
54
- async show(componentName, payload) {
55
- await show({ state: this.state, componentName, payload });
56
- }
57
-
58
- on(eventName, callback) {
59
- on({ state: this.state, eventName, callback });
60
- }
61
- }
1
+ import { RebillyInstrumentsInstance } from './instance';
62
2
 
63
3
  export default new RebillyInstrumentsInstance();
@@ -0,0 +1,65 @@
1
+ import { mount } from './functions/mount';
2
+ import { purchase } from './functions/purchase';
3
+ import { setup } from './functions/setup';
4
+ import { on } from './functions/on';
5
+ import { update } from './functions/update';
6
+ import { destroy } from './functions/destroy';
7
+ import { Loader } from './loader';
8
+ import { Translate } from './i18n';
9
+ import { show } from './functions/show';
10
+
11
+ export class InstrumentsState {
12
+ constructor() {
13
+ this.options = null;
14
+ this.data = {};
15
+ this.mountingPoints = null;
16
+ this.storefront = null;
17
+ this.form = null;
18
+ this.summary = null;
19
+ this.loader = new Loader();
20
+ this.translate = new Translate();
21
+ this.iframeComponents = [];
22
+ this.hasMounted = false;
23
+ }
24
+ }
25
+
26
+ export class RebillyInstrumentsInstance {
27
+ constructor() {
28
+ this.state = new InstrumentsState();
29
+ // TODO: mountConfirmation, mountResult have different contract shape when they look similar
30
+ // TODO: review test coverage of UpdateSummary and UpdateMethodSelector as no tests were broken
31
+ // when commenting them
32
+ }
33
+
34
+ async mount(options) {
35
+ await mount({ state: this.state, ...options });
36
+ }
37
+
38
+ async destroy() {
39
+ await destroy({ state: this.state });
40
+ }
41
+
42
+ async update(newOptions) {
43
+ await update({state: this.state, newOptions});
44
+ }
45
+
46
+ async purchase(payload) {
47
+ await purchase({ state: this.state, payload });
48
+ }
49
+
50
+ async setup(payload) {
51
+ await setup({ state: this.state, payload });
52
+ }
53
+
54
+ async show(componentName, payload) {
55
+ await show({ state: this.state, componentName, payload });
56
+ }
57
+
58
+ get version() {
59
+ return 'RebillyInstruments Ver.[VI]{version}[/VI]';
60
+ }
61
+
62
+ on(eventName, callback) {
63
+ on({ state: this.state, eventName, callback });
64
+ }
65
+ }
@@ -1,4 +1,5 @@
1
- import RebillyInstruments, { RebillyInstrumentsInstance } from './index';
1
+ import RebillyInstruments from './index';
2
+ import { RebillyInstrumentsInstance } from './instance';
2
3
  import { avoidUnhandledPromises } from 'tests/async-utilities';
3
4
 
4
5
  describe('RebillyInstruments instance', () => {
@@ -9,6 +9,7 @@ export class Loader {
9
9
  loading: `
10
10
  <div class="rebilly-instruments-loader is-active">
11
11
  <div class="rebilly-instruments-loader-spinner"></div>
12
+ <span class="rebilly-instuments-loader-message"><span>
12
13
  </div>
13
14
  `
14
15
  };
@@ -22,7 +23,7 @@ export class Loader {
22
23
  }
23
24
  }
24
25
 
25
- startLoading({ section = 'form', id = '' } = {}) {
26
+ startLoading({state, section = 'form', id = '', message = null } = {}) {
26
27
  const minHeight = '200px';
27
28
  this[section].push(id);
28
29
 
@@ -36,6 +37,17 @@ export class Loader {
36
37
  }
37
38
  this.DOM[section].style.minHeight = minHeight;
38
39
  }
40
+
41
+ if (message) {
42
+ const loaderMessage = this.DOM[section].querySelector('.rebilly-instuments-loader-message');
43
+ if (loaderMessage) {
44
+ loaderMessage.innerHTML = message;
45
+ loaderMessage.style.marginTop = '10px';
46
+ loaderMessage.setAttribute('data-message-id', id);
47
+ loaderMessage.setAttribute('data-rebilly-i18n', message);
48
+ state.i18n({state});
49
+ }
50
+ }
39
51
  }
40
52
 
41
53
  stopLoading({ section = 'form', id = '' } = {}) {
@@ -54,6 +66,14 @@ export class Loader {
54
66
  .classList.remove('is-active');
55
67
  this.DOM[section].style.minHeight = '';
56
68
  }
69
+
70
+ const loaderMessage = this.DOM[section].querySelector(`.rebilly-instuments-loader-message[data-message-id="${id}"]`);
71
+ if (loaderMessage) {
72
+ loaderMessage.innerHTML = null;
73
+ loaderMessage.style.marginTop = '0px';
74
+ loaderMessage.removeAttribute('data-message-id');
75
+ loaderMessage.removeAttribute('data-rebilly-i18n');
76
+ }
57
77
  }
58
78
 
59
79
  clearAll() {