@rebilly/instruments 3.36.1 → 3.37.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 (34) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/index.js +15 -15
  3. package/dist/index.min.js +15 -15
  4. package/package.json +1 -1
  5. package/src/data/options-schema/schemas/options-schema.js +7 -3
  6. package/src/functions/mount/fetch-data.js +15 -3
  7. package/src/functions/mount/index.js +4 -70
  8. package/src/functions/mount/mount.spec.js +6 -1
  9. package/src/functions/mount/setup-options.js +19 -6
  10. package/src/functions/mount/setup-options.spec.js +3 -3
  11. package/src/functions/purchase.js +10 -4
  12. package/src/functions/show.js +3 -4
  13. package/src/functions/show.spec.js +0 -2
  14. package/src/i18n/en.json +3 -0
  15. package/src/i18n/es.json +3 -0
  16. package/src/storefront/deposit-requests.js +12 -0
  17. package/src/storefront/models/deposit-request-model.js +15 -0
  18. package/src/storefront/ready-to-pay.js +5 -0
  19. package/src/storefront/summary.js +1 -1
  20. package/src/style/base/__snapshots__/theme.spec.js.snap +1 -1
  21. package/src/style/base/default-theme.js +1 -1
  22. package/src/views/amount-selector.js +47 -0
  23. package/src/views/common/iframe/base-iframe.js +7 -1
  24. package/src/views/confirmation.js +14 -15
  25. package/src/views/form.js +52 -0
  26. package/src/views/method-selector/__snapshots__/method-selector.spec.js.snap +10 -59
  27. package/src/views/method-selector/generate-digital-wallet.js +2 -2
  28. package/src/views/method-selector/generate-digital-wallet.spec.js +2 -13
  29. package/src/views/method-selector/get-payment-methods.js +5 -5
  30. package/src/views/method-selector/get-payment-methods.spec.js +4 -3
  31. package/src/views/method-selector/index.js +151 -86
  32. package/src/views/method-selector/method-selector.spec.js +1 -1
  33. package/src/views/result.js +8 -18
  34. package/src/views/summary.js +11 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebilly/instruments",
3
- "version": "3.36.1",
3
+ "version": "3.37.0",
4
4
  "author": "Rebilly",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -78,7 +78,9 @@ export default {
78
78
  money: {
79
79
  type: 'object',
80
80
  properties: {
81
- amount: {type: 'number'},
81
+ amount: {
82
+ type: 'number'
83
+ },
82
84
  currency: {
83
85
  type: 'string',
84
86
  minLength: 3,
@@ -105,7 +107,9 @@ export default {
105
107
  minLength: 3,
106
108
  maxLength: 3,
107
109
  },
108
- amount: {type: 'number'},
110
+ amount: {
111
+ type: 'number'
112
+ },
109
113
  buttons: {
110
114
  type: 'array',
111
115
  items: {
@@ -118,7 +122,7 @@ export default {
118
122
  properties: {
119
123
  minimum: {type: 'number'},
120
124
  maximum: {type: 'number'},
121
- increment: {type: 'number'}
125
+ multipleOf: {type: 'number'}
122
126
  },
123
127
  }
124
128
  },
@@ -8,6 +8,8 @@ import { fetchInvoiceAndProducts as FetchInvoiceAndProducts } from '../../storef
8
8
  import { fetchTransaction as FetchTransaction } from '../../storefront/transactions';
9
9
  import { fetchAccountAndWebsite as FetchAccountAndWebsite } from '../../storefront/account-and-website';
10
10
  import { fetchPaymentInstrument as FetchInstruments } from '../../storefront/payment-instruments';
11
+ import { fetchDepositRequest as FetchDepositRequest } from '../../storefront/deposit-requests';
12
+ import DepositRequestModel from '../../storefront/models/deposit-request-model';
11
13
 
12
14
  export class DataInstance {
13
15
  constructor({
@@ -126,11 +128,22 @@ export async function fetchData({
126
128
  fetchInvoiceAndProducts = FetchInvoiceAndProducts,
127
129
  fetchTransaction = FetchTransaction,
128
130
  fetchAccountAndWebsite = FetchAccountAndWebsite,
129
- fetchInstruments = FetchInstruments
131
+ fetchInstruments = FetchInstruments,
132
+ fetchDepositRequest = FetchDepositRequest,
130
133
  } = {}) {
131
134
  try {
132
135
  state.data = new DataInstance();
133
136
 
137
+ if (state.options?.deposit) {
138
+ if (state.options.deposit.depositRequestId) {
139
+ state.data.deposit = await fetchDepositRequest({data: {
140
+ id: state.options.deposit.depositRequestId,
141
+ }});
142
+ } else {
143
+ state.data.deposit = new DepositRequestModel(state.options.deposit);
144
+ }
145
+ }
146
+
134
147
  let readyToPayPromise = Promise.resolve(null);
135
148
 
136
149
  let availableInstrumentsPromise = null;
@@ -149,8 +162,7 @@ export async function fetchData({
149
162
  state.data.transaction = await fetchTransaction({
150
163
  data: {
151
164
  id: state.options.transactionId
152
- }, state
153
- });
165
+ }});
154
166
  }
155
167
 
156
168
  let productsPromise;
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable max-len */
2
2
  import state from '../../state';
3
3
  import { mountSummary } from '../../views/summary';
4
- import { mountMethodSelector } from '../../views/method-selector';
4
+ import { mountForm, determineFirstView } from '../../views/form';
5
5
  import { fetchData } from './fetch-data';
6
6
  import Events from '../../events';
7
7
  import setupElement from './setup-element';
@@ -14,74 +14,7 @@ import setupFramepayTheme from './setup-framepay-theme';
14
14
  import setupUserFlow from './setup-user-flow';
15
15
  import { showError } from '../../views/errors';
16
16
 
17
- /**
18
- * @typedef {object} ItemQuantity - Item quantity
19
- * @property {number} default - The initial quantity value
20
- * @property {number} [minimum=1] - minimum allowed quantity. if minimum, maximum or multipleOf are present, quantity will be "variable"
21
- * @property {number} [maximum=Number.MAX_SAFE_INTEGER] - maximum allowed quantity
22
- * @property {number} [multipleOf=1]
23
- *
24
- * @typedef {object} Item
25
- * @property {string} planId - The Rebilly id of the plan.
26
- * @property {number | ItemQuantity} quantity - The number of the plans to be purchased.
27
- * @property {string} thumbnail - The source img for the product. Recommend 100px by 100px.
28
- *
29
- * @typedef {object} GooglePayDisplayOptions
30
- * @property {"back" | "white"} [buttonColor=black] - Color of google pay button
31
- * @property {"book" | "buy" | "checkout" | "donate" | "order" | "pay" | "plain" | "subscribe" | "short" | "long"} [buttonType=plain] - The length of the button
32
- * @property {string} [buttonHeight=48px] - The value and units of the button to match other payment buttons
33
- *
34
- * @typedef {object} ApplePayDisplayOptions
35
- * @property {"back" | "white"} [buttonColor=black] - Color of apple pay button
36
- * @property {"short" | "long"} [buttonType=short] - The length of the button
37
- * @property {string} [buttonHeight=48px] - The value and units of the button to match other payment buttons
38
- *
39
- * @typedef {object} ApplePayMerchantOptions
40
- * @property {string} merchantName - The name of the merchant store.
41
- *
42
- * @typedef {object} GooglePay
43
- * @property {GooglePayDisplayOptions} displayOptions - display options for google pay instrument
44
- *
45
- * @typedef {object} ApplePay
46
- * @property {ApplePayDisplayOptions} displayOptions - display options for apple pay instrument
47
- * @property {ApplePayMerchantOptions} merchantOptions - merchant options for apple pay instrument
48
- *
49
- * @typedef {object} PaymentCard
50
- * @property {boolean} [popup=true] - Show method as a button with a form popup. Otherwise the form will be mounted inline.
51
- *
52
- * @typedef {object} Address
53
- * @property {string} [name=default] - One of default, combined, or stacked.
54
- * @property {string} [region=default] - One of default, split, or stacked.
55
- * @property {Array.<"organization" | "phoneNumber">} show - Show extra fields listed.
56
- * @property {Array.<"address" | "address2" | "email | "country" | "region" | "postalCode"">} hide - Hide the listed fields.
57
- * @property {Array.<"organization" | "address" | "address2" | "email" | "phoneNumber" | "country" | "region" | "postalCode">} require - Require the listed fields.
58
- *
59
- * @typedef {object} PaymentInstruments
60
- * @property {boolean} [compactExpressInstruments=true] - Show express methods as inline pill buttons, or list of full width button.
61
- * @property {PaymentCard} paymentCard - settings for payment card instruments
62
- * @property {GooglePay} googlePay - settings for google pay instruments
63
- * @property {ApplePay} applePay - settings for apple pay instruments
64
- * @property {Address} address - customization for address components for all payment instruments.
65
- *
66
- * @typedef {object} Features
67
- * @property {boolean} [autoConfirmation=true] - Will mount the confirmation screen after `instrument-ready` event is triggered.
68
- * @property {boolean} [autoResult=true] - Show results of transaction after `purchase-completed` event is triggered
69
- */
70
-
71
- /**
72
- * Mount library with configurations.
73
- * @param {object} options - The options object
74
- * @param {function} options.setupFramepayInstance - Helper for adding FramePay scripts to the DOM
75
- * @param {string | HTMLElement} options.form - The CSS class or HTML element were the form will be mounted.
76
- * @param {string | HTMLElement} options.summary - The CSS class or HTML element were the summary will be mounted.
77
- * @param {Item[]} options.items - Which plans the customer is purchasing.
78
- * @param {string} options.invoiceId - The Rebilly id of the invoice used for purchasing.
79
- * @param {string} options.jwt - The customer token to access the invoice.
80
- * @param {string} [options.countryCode=USD] - The country code for the transaction
81
- * @param {PaymentInstruments} options.paymentInstruments - settings for various payment instruments
82
- * @param {Features} options.features - flags to enable and disable different features
83
- * @param {string} options.locale - default: auto. Language to render component text
84
- */
17
+ /** See src/data/options-schema for options structure */
85
18
  export async function mount({
86
19
  setupFramepay = setupFramepayInstance,
87
20
  ...options
@@ -133,7 +66,8 @@ export async function mount({
133
66
 
134
67
  // Mount content
135
68
  if (state.form) {
136
- mountMethodSelector();
69
+ mountForm()
70
+ .then(() => determineFirstView());
137
71
  }
138
72
  if (state.summary) {
139
73
  mountSummary();
@@ -35,7 +35,12 @@ describe('RebillyInstruments instance', () => {
35
35
 
36
36
  // Mounts form and summary
37
37
  const summarySelector = document.querySelector('.summary-selector');
38
- expect(summarySelector.innerHTML).toContain('<iframe name="rebilly-instruments-summary" class="rebilly-instruments-iframe" loading="lazy" allow="payment" src="https://forms.test.rebilly.dev/summary"></iframe>');
38
+ const iframe = summarySelector.querySelector('iframe');
39
+ expect(iframe.getAttribute('name')).toEqual('rebilly-instruments-summary');
40
+ expect(iframe.getAttribute('class')).toEqual('rebilly-instruments-iframe');
41
+ expect(iframe.getAttribute('loading')).toEqual('lazy');
42
+ expect(iframe.getAttribute('allow')).toEqual('payment');
43
+ expect(iframe.getAttribute('src')).toEqual('https://forms.test.rebilly.dev?name=rebilly-instruments-summary');
39
44
 
40
45
  // Theme config overrides initial styles
41
46
  const STYLE_VARS = document.querySelectorAll('style[type="text/css"]')[0];
@@ -4,10 +4,9 @@ import { parseQuantity } from '../../utils/quantity';
4
4
  import { validateOptions } from '../../data/options-schema';
5
5
 
6
6
  export function handleComputedProperty(options) {
7
- const _computed = {
7
+ options._computed = {
8
8
  paymentMethodsUrl: options._dev?.paymentMethodsUrl ?? 'https://forms.secure-payments.app'
9
9
  };
10
- options._computed = _computed;
11
10
  return options
12
11
  }
13
12
 
@@ -25,8 +24,16 @@ export function handleNestedPropertiesDefaultValues(options) {
25
24
  buttons: [],
26
25
  customAmount: {
27
26
  minimum: 1,
28
- maximum: Number.MAX_SAFE_INTEGER,
29
- increment: 1,
27
+ maximum: 1000000000000,
28
+ multipleOf: 1,
29
+ }
30
+ }, (options.deposit || {}));
31
+ } else if (options.deposit?.depositRequestId) {
32
+ options.deposit = merge({
33
+ customAmount: {
34
+ minimum: 1,
35
+ maximum: 1000000000000,
36
+ multipleOf: 1,
30
37
  }
31
38
  }, (options.deposit || {}));
32
39
  }
@@ -49,6 +56,7 @@ export function handleJwtDestructuring(options) {
49
56
  transactionId,
50
57
  invoiceId,
51
58
  websiteId,
59
+ cashierRequestId
52
60
  }
53
61
  } = decodeJwt(options.jwt);
54
62
  Object.entries({
@@ -61,6 +69,10 @@ export function handleJwtDestructuring(options) {
61
69
  options[key] = value;
62
70
  }
63
71
  });
72
+ if (cashierRequestId && !options.deposit) {
73
+ options.deposit = {};
74
+ options.deposit.depositRequestId = cashierRequestId;
75
+ }
64
76
  }
65
77
 
66
78
  return options;
@@ -71,9 +83,10 @@ export default ({
71
83
  } = {}) => {
72
84
  let validOptions = validateOptions(options);
73
85
  if (validOptions) {
74
- validOptions = handleComputedProperty(validOptions);
75
- validOptions = handleNestedPropertiesDefaultValues(validOptions);
76
86
  validOptions = handleJwtDestructuring(validOptions);
87
+ validOptions = handleNestedPropertiesDefaultValues(validOptions);
88
+ validOptions = handleComputedProperty(validOptions);
77
89
  }
90
+
78
91
  return validOptions;
79
92
  }
@@ -217,7 +217,7 @@ describe('Setup options handleNestedPropertiesDefaultValues function', () => {
217
217
  buttons: [],
218
218
  customAmount: {
219
219
  minimum: 1,
220
- maximum: Number.MAX_SAFE_INTEGER,
220
+ maximum: 1000000000000,
221
221
  increment: 1,
222
222
  },
223
223
  currency: 'USD'
@@ -253,9 +253,9 @@ describe('Setup options handleNestedPropertiesDefaultValues function', () => {
253
253
  items: [{
254
254
  planId: 'plan_TEST',
255
255
  quantity: {
256
- minimum: 1,
256
+ minimum: 0.1,
257
257
  maximum: Number.MAX_SAFE_INTEGER,
258
- multipleOf: 1
258
+ multipleOf: 0.1
259
259
  }
260
260
  }]
261
261
  });
@@ -27,21 +27,27 @@ export async function makePayment({ payload }) {
27
27
  data.token = id;
28
28
  }
29
29
 
30
- if (state.options.invoiceId) {
30
+ if (state.options?.invoiceId) {
31
31
  data.invoiceId = state.options.invoiceId;
32
32
  }
33
33
 
34
- if (state.options.transactionId) {
34
+ if (state.options?.transactionId) {
35
35
  data.transactionId = state.options.transactionId;
36
36
  }
37
37
 
38
- if (state.options.money) {
38
+ if (state.options?.money) {
39
39
  data.websiteId = state.options.websiteId;
40
40
  data.amount = state.options.money.amount;
41
41
  data.currency = state.options.money.currency;
42
42
  }
43
+
44
+ if (state.options?.deposit) {
45
+ data.websiteId = state.options.websiteId;
46
+ data.amount = state.data.amountAndCurrency.amount;
47
+ data.currency = state.data.amountAndCurrency.currency;
48
+ }
43
49
 
44
- if (state.data.couponIds && Array.isArray(state.data.couponIds)) {
50
+ if (state.data?.couponIds && Array.isArray(state.data.couponIds)) {
45
51
  data.couponIds = state.data.couponIds
46
52
  }
47
53
 
@@ -1,6 +1,7 @@
1
1
  import iframes from '../state/iframes';
2
2
  import { mountConfirmation } from '../views/confirmation';
3
3
  import { mountResult } from '../views/result';
4
+ import { hideExtraUI as hideMethodSelectorUI} from '../views/method-selector'
4
5
 
5
6
  /**
6
7
  @typedef ShowParams
@@ -17,13 +18,11 @@ import { mountResult } from '../views/result';
17
18
  export async function show({ componentName, payload }) {
18
19
  switch (componentName) {
19
20
  case 'result':
20
- if (iframes.hasFrame('form')) {
21
- iframes.form.destroy();
22
- iframes.form = null;
23
- }
21
+ hideMethodSelectorUI();
24
22
  mountResult({ payload });
25
23
  break;
26
24
  case 'confirmation':
25
+ hideMethodSelectorUI();
27
26
  mountConfirmation({ payload });
28
27
  break;
29
28
  default:
@@ -12,7 +12,6 @@ describe('RebillyInstruments show', () => {
12
12
  .mockReturnValue(Promise.resolve());
13
13
 
14
14
  const instance = new RebillyInstrumentsInstance();
15
- iframes.form = iframeMock;
16
15
 
17
16
  const payload = {
18
17
  test: 'value'
@@ -24,7 +23,6 @@ describe('RebillyInstruments show', () => {
24
23
  expect(mountResult).toBeCalledWith(
25
24
  expect.objectContaining({ payload })
26
25
  );
27
- expect(iframes.form).toEqual(null);
28
26
  });
29
27
 
30
28
  it('should show confirmation component', async () => {
package/src/i18n/en.json CHANGED
@@ -7,6 +7,9 @@
7
7
  "shipping": "Shipping",
8
8
  "total": "Total"
9
9
  },
10
+ "deposit": {
11
+ "goBack": "Choose another amount"
12
+ },
10
13
  "form": {
11
14
  "expressCheckout": "Express checkout",
12
15
  "or": "Or",
package/src/i18n/es.json CHANGED
@@ -7,6 +7,9 @@
7
7
  "shipping": "Envío",
8
8
  "total": "Total"
9
9
  },
10
+ "deposit": {
11
+ "goBack": "Elija otro monto a depositar"
12
+ },
10
13
  "form": {
11
14
  "expressCheckout": "Chequeo rápido",
12
15
  "or": "O pague con",
@@ -0,0 +1,12 @@
1
+ import { Endpoint } from './index';
2
+ import state from '../state';
3
+ import DepositRequestModel from './models/deposit-request-model';
4
+
5
+ export async function fetchDepositRequest({data = null}) {
6
+ return Endpoint(async () => {
7
+ state.storefront.setSessionToken(state.options.jwt);
8
+ const {fields} = await state.storefront.cashierRequests.get(data);
9
+
10
+ return new DepositRequestModel(fields);
11
+ });
12
+ }
@@ -0,0 +1,15 @@
1
+ import BaseModel from './base-model';
2
+ import merge from 'lodash.merge';
3
+ export default class DepositRequestModel extends BaseModel {
4
+ constructor(fields) {
5
+ super(fields);
6
+ this.amount = Array.isArray(fields.amount) ? fields.amount[0] : fields.amount;
7
+ this.buttons = fields.buttons ?? [...fields.amounts];
8
+ this.editable = typeof fields.editable === "boolean" ? fields.editable : Boolean(fields.customAmount);
9
+ this.customAmount = merge({
10
+ minimum: 1,
11
+ maximum: 1000000000000,
12
+ multipleOf: 1,
13
+ }, (fields.customAmount || {}));
14
+ }
15
+ }
@@ -85,6 +85,11 @@ export async function fetchReadyToPay({
85
85
  data.billingAddress = state.data.account.address;
86
86
  }
87
87
 
88
+ if (state.data?.deposit) {
89
+ data.amount = state.data.deposit.amount;
90
+ data.currency = state.data.deposit.currency;
91
+ }
92
+
88
93
  const { fields: readyToPayFields } = await state.storefront.purchase.readyToPay({ data });
89
94
  const readyToPay = Object.values(readyToPayFields);
90
95
 
@@ -16,7 +16,6 @@ export async function fetchSummary({ data = null } = {}) {
16
16
  }
17
17
  };
18
18
 
19
-
20
19
  const isBumpOfferSummary = () => state.data.summaryLineItems.every(
21
20
  item => bumpOfferProductsIds.includes(item.planId)
22
21
  );
@@ -50,6 +49,7 @@ export async function fetchSummary({ data = null } = {}) {
50
49
  if (data?.billingAddress) {
51
50
  payload.data.billingAddress = data.billingAddress;
52
51
  }
52
+
53
53
  if (data?.deliveryAddress) {
54
54
  payload.data.deliveryAddress = data.deliveryAddress;
55
55
  }
@@ -8,7 +8,7 @@ Object {
8
8
  --rebilly-colorMutedText: rgba(13, 43, 62, 0.5);
9
9
  --rebilly-colorMutedBorder: #DCE3EA;
10
10
  --rebilly-colorDanger: #CD5C5C;
11
- --rebilly-fontFamily: Avenir, Helvetica, Arial, sans-serif;
11
+ --rebilly-fontFamily: -apple-system,system-ui,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial sans-serif;
12
12
  --rebilly-fontSizeBase: 16px;
13
13
  --rebilly-fontWeightBase: 500;
14
14
  --rebilly-fontLineHeightBase: calc(16px * 1.5);
@@ -49,7 +49,7 @@ const properties = {
49
49
  fontFamily: {
50
50
  fallback: {
51
51
  type: 'static',
52
- value: 'Avenir, Helvetica, Arial, sans-serif',
52
+ value: "-apple-system,system-ui,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial sans-serif",
53
53
  }
54
54
  },
55
55
  fontSizeBase: {
@@ -0,0 +1,47 @@
1
+ import state from '../state';
2
+ import iframes from '../state/iframes';
3
+ import { mountMethodSelector } from './method-selector';
4
+ import { fetchReadyToPay } from '../storefront/ready-to-pay';
5
+
6
+ export async function mountAmountSelector() {
7
+ if (state.data.money) {
8
+ state.data.money.amount = null;
9
+ state.data.money.currency = null;
10
+ state.updateModel();
11
+ }
12
+
13
+ const iframe = iframes.form;
14
+ if (!iframe) {
15
+ await mountForm();
16
+ }
17
+
18
+ const modelSafeState = state.toModel();
19
+ const model = {
20
+ options: modelSafeState.options,
21
+ data: modelSafeState.data,
22
+ mainStyleVars: modelSafeState.mainStyleVars,
23
+ };
24
+
25
+ iframe.component?.call('route', {
26
+ name: 'amount-selector'
27
+ });
28
+
29
+ iframe.component?.call('update', model);
30
+
31
+ iframe?.component?.on('confirm-amount', async (data) => {
32
+ const { amount, currency } = data;
33
+ state.data.money = {
34
+ amount,
35
+ currency,
36
+ };
37
+
38
+ const readyToPayUpdated = await fetchReadyToPay({
39
+ riskMetadata: state.data.riskMetadata
40
+ });
41
+
42
+ state.data.readyToPay = readyToPayUpdated;
43
+
44
+ state.updateModel();
45
+ mountMethodSelector();
46
+ });
47
+ }
@@ -6,7 +6,8 @@ export default class BaseIframe {
6
6
  url = '',
7
7
  model = {},
8
8
  container = null,
9
- classListArray = []
9
+ classListArray = [],
10
+ route = null,
10
11
  } = {}) {
11
12
  classListArray = Array.isArray(classListArray) ? classListArray : [];
12
13
  if (!classListArray.includes('rebilly-instruments-iframe')) {
@@ -22,6 +23,11 @@ export default class BaseIframe {
22
23
 
23
24
  return (async () => {
24
25
  this.component = await this.createComponent();
26
+
27
+ if (route) {
28
+ this.component.call('route', route);
29
+ }
30
+
25
31
  return this;
26
32
  })();
27
33
  }
@@ -1,9 +1,9 @@
1
1
  import state from '../state';
2
2
  import iframes from '../state/iframes';
3
+ import { mountForm } from './form';
3
4
  import { updateSummary } from './summary';
4
-
5
- export const baseConfirmationHTML =
6
- '<div class="rebilly-instruments-confirmation"></div>';
5
+ import { purchase} from '../functions/purchase';
6
+ import { setup } from '../functions/setup';
7
7
 
8
8
  export async function mountConfirmation({ payload: instrument }) {
9
9
  if (
@@ -14,7 +14,10 @@ export async function mountConfirmation({ payload: instrument }) {
14
14
  }
15
15
 
16
16
  const iframe = iframes.form;
17
-
17
+ if (!iframe) {
18
+ await mountForm();
19
+ }
20
+
18
21
  const modelSafeState = state.toModel();
19
22
  const model = {
20
23
  options: modelSafeState.options,
@@ -29,15 +32,11 @@ export async function mountConfirmation({ payload: instrument }) {
29
32
 
30
33
  iframe?.component?.call('update', model);
31
34
 
32
- document.querySelectorAll('[data-rebilly-instruments="express-method"]')
33
- .forEach(el => {
34
- el.style.overflow = 'hidden';
35
- el.style.height = '0px';
36
- });
37
- document.querySelectorAll('[data-rebilly-instruments="bump-offer"]')
38
- .forEach(el => {
39
- el.style.overflow = 'hidden';
40
- el.style.height = '0px';
41
- el.style.marginBottom = '0px';
42
- })
35
+ iframe?.component?.on(`${iframe.name}-confirm-purchase`, (confirmedInstrument) => {
36
+ purchase({ payload: confirmedInstrument });
37
+ });
38
+
39
+ iframe?.component?.on(`${iframe.name}-confirm-setup`, (confirmedInstrument) => {
40
+ setup({ payload: confirmedInstrument });
41
+ });
43
42
  }
@@ -0,0 +1,52 @@
1
+ import state from '../state';
2
+ import iframes from '../state/iframes';
3
+ import { ViewIframe } from './common/iframe';
4
+ import { mountMethodSelector } from './method-selector';
5
+ import { mountAmountSelector } from './amount-selector';
6
+
7
+ export const baseMethodSelectorHTML = () => `
8
+ <div data-rebilly-instruments="content" class="rebilly-instruments-content">
9
+ <div data-rebilly-instruments="content-error" id="rebilly-instruments-error"></div>
10
+ <div data-rebilly-instruments="form"></div>
11
+ </div>
12
+ `;
13
+
14
+ export async function mountForm() {
15
+ state.form.innerHTML += baseMethodSelectorHTML();
16
+ const container = document.querySelector('[data-rebilly-instruments="form"]');
17
+ const { paymentMethodsUrl: url } = state.options?._computed;
18
+ const name = 'rebilly-instruments-form';
19
+
20
+ const modelSafeState = state.toModel();
21
+ const model = {
22
+ options: modelSafeState.options,
23
+ data: modelSafeState.data,
24
+ mainStyleVars: modelSafeState.mainStyleVars,
25
+ };
26
+
27
+ const args = {
28
+ name,
29
+ url: `${url}?name=${name}`,
30
+ container,
31
+ model,
32
+ };
33
+
34
+ const iframe = await new ViewIframe(args);
35
+ iframe.bindEventListeners({loader: state.loader});
36
+
37
+ iframes.form = iframe;
38
+
39
+ state.loader.stopLoading({id: 'rebilly-instruments-form'});
40
+
41
+ return {
42
+ then: (callback) => callback()
43
+ }
44
+ }
45
+
46
+ export function determineFirstView() {
47
+ if (state.options?.deposit) {
48
+ mountAmountSelector();
49
+ } else {
50
+ mountMethodSelector();
51
+ }
52
+ }