@rebilly/instruments 3.13.4-beta.0 → 3.14.3-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 (84) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +43 -66
  3. package/dist/index.min.js +43 -66
  4. package/package.json +3 -6
  5. package/src/functions/destroy.js +8 -2
  6. package/src/functions/mount/fetch-data.js +9 -2
  7. package/src/functions/mount/index.js +17 -10
  8. package/src/functions/mount/mount.spec.js +10 -11
  9. package/src/functions/mount/setup-framepay-theme.js +30 -72
  10. package/src/functions/mount/setup-options.js +2 -2
  11. package/src/functions/mount/{setup-styles.js → setup-styles-vars.js} +9 -7
  12. package/src/functions/purchase.js +2 -5
  13. package/src/functions/setup.js +3 -6
  14. package/src/functions/show.js +2 -2
  15. package/src/functions/show.spec.js +4 -4
  16. package/src/functions/update.spec.js +4 -3
  17. package/src/instance.js +4 -1
  18. package/src/loader/index.js +57 -33
  19. package/src/storefront/index.js +2 -5
  20. package/src/storefront/payment-instruments.js +7 -0
  21. package/src/style/base/__snapshots__/theme.spec.js.snap +136 -220
  22. package/src/style/base/default-theme.js +187 -14
  23. package/src/style/base/index.js +487 -79
  24. package/src/style/base/theme.js +3 -4
  25. package/src/style/base/theme.spec.js +2 -3
  26. package/src/style/index.js +4 -24
  27. package/src/style/utils/color-values.js +1 -1
  28. package/src/style/utils/minifyCss.js +14 -0
  29. package/src/views/common/iframe/base-iframe.js +3 -2
  30. package/src/views/common/iframe/event-listeners.js +12 -9
  31. package/src/views/common/iframe/method-iframe.js +3 -1
  32. package/src/views/common/iframe/modal-iframe.js +4 -2
  33. package/src/views/common/iframe/view-iframe.js +3 -1
  34. package/src/views/confirmation.js +12 -7
  35. package/src/views/errors.js +95 -0
  36. package/src/views/method-selector/express-methods.js +51 -0
  37. package/src/views/method-selector/generate-framepay-config.js +54 -0
  38. package/src/views/method-selector/generate-framepay-config.spec.js +195 -0
  39. package/src/views/method-selector/get-payment-methods.js +0 -1
  40. package/src/views/method-selector/index.js +48 -59
  41. package/src/views/method-selector/method-selector.spec.js +1 -1
  42. package/src/views/method-selector/mount-express-methods.js +66 -26
  43. package/src/views/modal.js +1 -1
  44. package/src/views/result.js +3 -3
  45. package/src/views/summary.js +24 -190
  46. package/tests/mocks/storefront-api-mock.js +48 -27
  47. package/src/style/browserslist.js +0 -1
  48. package/src/style/components/accordion.js +0 -140
  49. package/src/style/components/address.js +0 -55
  50. package/src/style/components/button.js +0 -117
  51. package/src/style/components/divider.js +0 -39
  52. package/src/style/components/forms/checkbox.js +0 -75
  53. package/src/style/components/forms/field.js +0 -56
  54. package/src/style/components/forms/form.js +0 -18
  55. package/src/style/components/forms/input.js +0 -77
  56. package/src/style/components/forms/label.js +0 -55
  57. package/src/style/components/forms/radio.js +0 -80
  58. package/src/style/components/forms/select.js +0 -86
  59. package/src/style/components/forms/validation.js +0 -72
  60. package/src/style/components/icons.js +0 -13
  61. package/src/style/components/index.js +0 -39
  62. package/src/style/components/loader.js +0 -41
  63. package/src/style/components/methods.js +0 -97
  64. package/src/style/components/overlay.js +0 -24
  65. package/src/style/helpers/index.js +0 -54
  66. package/src/style/payment-instruments/content.js +0 -8
  67. package/src/style/payment-instruments/index.js +0 -14
  68. package/src/style/payment-instruments/payment-card.js +0 -27
  69. package/src/style/payment-instruments/payment-instrument-list.js +0 -44
  70. package/src/style/payment-instruments/payment-instrument.js +0 -55
  71. package/src/style/utils/remove-empty-null.js +0 -10
  72. package/src/style/vendor/framepay.js +0 -28
  73. package/src/style/vendor/postmate.js +0 -18
  74. package/src/style/views/confirmation.js +0 -26
  75. package/src/style/views/index.js +0 -16
  76. package/src/style/views/method-selector.js +0 -11
  77. package/src/style/views/modal.js +0 -91
  78. package/src/style/views/result.js +0 -52
  79. package/src/style/views/summary.js +0 -118
  80. package/src/views/__snapshots__/summary.spec.js.snap +0 -246
  81. package/src/views/method-selector/express-methods/apple-pay.js +0 -92
  82. package/src/views/method-selector/express-methods/index.js +0 -25
  83. package/src/views/method-selector/mount-methods.js +0 -178
  84. package/src/views/summary.spec.js +0 -145
@@ -1,25 +0,0 @@
1
- import { MethodIframe } from '../../common/iframe';
2
-
3
- export default async function mountExpressMethod({ state, METHOD_ID }) {
4
- const container = document.querySelector(`.rebilly-instruments-${METHOD_ID}-method`);
5
-
6
- const { paymentMethodsUrl } = state.options._computed;
7
-
8
- const model = {
9
- options: state.options,
10
- data: state.data.toPostmatesModel()
11
- };
12
-
13
- const iframe = await new MethodIframe({
14
- name: METHOD_ID,
15
- url: `${paymentMethodsUrl}/${METHOD_ID}`,
16
- container,
17
- model
18
- });
19
-
20
- iframe.bindEventListeners({
21
- loader: state.loader
22
- });
23
-
24
- state.iframeComponents.push(iframe);
25
- }
@@ -1,178 +0,0 @@
1
- import camelCase from 'lodash.camelcase';
2
- import { mountModal } from '../modal';
3
- import { MethodIframe } from '../common/iframe';
4
- import { getMethodData } from './get-method-data';
5
-
6
- async function mountInline(state, {
7
- methodId,
8
- paymentMethodsUrl,
9
- container,
10
- model,
11
- method
12
- }) {
13
- const iframe = await new MethodIframe({
14
- name: methodId,
15
- url: `${paymentMethodsUrl}/${methodId}`,
16
- container,
17
- model
18
- });
19
- iframe.bindEventListeners({
20
- loader: state.loader,
21
- id: method.method
22
- });
23
- state.iframeComponents.push(iframe);
24
- }
25
-
26
- function displayBrands({summary, method}) {
27
- function renderBrand(brand) {
28
- return `
29
- <figure>
30
- <img alt="${brand}" src="https://forms.secure-payments.app/payment-instruments/brand/${brand.replace(/\s/, '')}.svg" />
31
- </figure>
32
- `;
33
- }
34
-
35
- const {brands} = method;
36
- summary.querySelector('.rebilly-instruments-accordion-title').insertAdjacentHTML(
37
- 'afterend',
38
- `<div class="rebilly-instruments-accordion-brands">${(() => {
39
- if (brands.length >= 4) {
40
- const truncatedBrands = brands.slice(0, 3);
41
- return `${truncatedBrands.map(brand => renderBrand(brand)).join('')}
42
- <span data-rebilly-i18n="forms.andMore">and more</span>
43
- `
44
- }
45
- return brands.map(brand => renderBrand(brand)).join('');
46
- })()}</div>`
47
- );
48
- }
49
-
50
- export function MountMethods({
51
- state,
52
- METHODS_CONTAINER,
53
- METHODS
54
- }) {
55
- const isAccordion = METHODS.length > 1;
56
-
57
- METHODS.forEach(async (method) => {
58
- const { METHOD_ID: methodId, METHOD_TYPE: methodType } =
59
- getMethodData(method);
60
- const { paymentMethodsUrl } =
61
- state.options._computed || 'https://www.example.com';
62
-
63
- const selector = `rebilly-instruments-${methodId}`;
64
- const isPopup = [
65
- 'payment-card'
66
- ].includes(methodId) && state.options.paymentInstruments[methodType]?.popup;
67
- const model = {
68
- account: state.data?.account,
69
- options: state.options,
70
- mainStyle: state.mainStyle,
71
- plans: state.data.plans,
72
- products: state.data.products,
73
- method,
74
- readyToPay: state.data.readyToPay,
75
- };
76
-
77
- if (isAccordion) {
78
- METHODS_CONTAINER.insertAdjacentHTML(
79
- 'beforeend',
80
- `<details class="rebilly-instruments-accordion for-${methodId}">
81
- <summary class="rebilly-instruments-accordion-summary">
82
- <img class="rebilly-instruments-accordion-${method.method}-img" src="${method.metadata.logo}" alt="${method.method}"/>
83
- <span class="rebilly-instruments-accordion-title" data-rebilly-i18n="paymentMethods.${method.method}">${method.metadata.name}</span>
84
- <span class="rebilly-instruments-accordion-summary-checkmark"></span>
85
- </summary>
86
- <div id="${selector}" data-rebilly-instruments-type="${methodId}" style="position: relative"></div>
87
- </details>`
88
- );
89
-
90
- if ([
91
- 'payment-card'
92
- ].includes(method.method)) {
93
- const summary = document.querySelector(`.for-${methodId} > .rebilly-instruments-accordion-summary`);
94
- displayBrands({summary, method});
95
- }
96
- state.loader.stopLoading({ id: method.method });
97
-
98
- METHODS_CONTAINER.insertAdjacentHTML(
99
- 'beforeend',
100
- `<div id="${selector}" data-rebilly-instruments-type="${methodId}"></div>`
101
- );
102
- const container = document.querySelector(`#${selector}`);
103
-
104
- state.loader.stopLoading({ id: method.method });
105
- mountInline(state, {
106
- methodId,
107
- paymentMethodsUrl,
108
- container,
109
- model,
110
- method
111
- });
112
- } else if (isPopup) {
113
- METHODS_CONTAINER.insertAdjacentHTML(
114
- 'beforeend',
115
- `<div id="${selector}" data-rebilly-instruments-type="${methodId}"></div>`
116
- );
117
- const container = document.querySelector(`#${selector}`);
118
-
119
- container.insertAdjacentHTML(
120
- 'beforeend',
121
- `<button class="${selector} rebilly-instruments-button" data-rebilly-i18n="paymentMethods.${
122
- method.method
123
- }">${camelCase(method.method)}</button>`
124
- );
125
- const button = document.querySelector(`.${selector}`);
126
- button.addEventListener('click', async () => {
127
- const iframe = await mountModal({
128
- state,
129
- name: methodId,
130
- url: `${paymentMethodsUrl}/${methodId}`,
131
- model
132
- });
133
- state.iframeComponents.push(iframe);
134
- });
135
- } else {
136
- METHODS_CONTAINER.insertAdjacentHTML(
137
- 'beforeend',
138
- `<div id="${selector}" data-rebilly-instruments-type="${methodId}"></div>`
139
- );
140
- const container = document.querySelector(`#${selector}`);
141
-
142
- mountInline(state, {
143
- methodId,
144
- paymentMethodsUrl,
145
- container,
146
- model,
147
- method
148
- });
149
- }
150
- state.loader.stopLoading({ id: method.method });
151
- });
152
-
153
- if (isAccordion) {
154
- // Fetch all the accordion elements.
155
- const details = document.querySelectorAll('.rebilly-instruments-accordion');
156
- // Add the onclick listeners.
157
- details.forEach((targetDetail) => {
158
- // set to open by default, will be closed by timeout below
159
- targetDetail.open = true;
160
- targetDetail.querySelector('summary').addEventListener('click', () => {
161
- // Close all the accordion that are not targetDetail.
162
- details.forEach((detail) => {
163
- detail.removeAttribute('open');
164
- });
165
- });
166
- });
167
-
168
- // All details must be open to connect to Postmate than closed
169
- setTimeout(() => {
170
- details.forEach((detail) => {
171
- detail.removeAttribute('open');
172
- });
173
- details[0].open = true;
174
- }, 100);
175
- }
176
-
177
- state.translate.translateItems();
178
- }
@@ -1,145 +0,0 @@
1
- import SummaryModel from '@/storefront/models/summary-model';
2
- import PlanModel from '@/storefront/models/plan-model';
3
- import ProductModel from '@/storefront/models/product-model';
4
- import { Loader } from '../loader';
5
- import { Translate } from '../i18n';
6
- import { mountSummary } from './summary';
7
- import { DataInstance } from '../functions/mount/fetch-data';
8
-
9
- describe('Summary component', () => {
10
- let summaryElement;
11
- beforeEach(() => {
12
- document.body.innerHTML = '';
13
- summaryElement = document.createElement('div');
14
- document.body.append(summaryElement);
15
- });
16
-
17
- class TestMountSummaryInstance {
18
- constructor({
19
- options = {},
20
- summary = summaryElement,
21
- loader = new Loader(),
22
- translate = new Translate(),
23
- data = {},
24
- } = {}) {
25
- this.options = options;
26
- this.summary = summary;
27
- this.loader = loader;
28
- this.translate = translate;
29
- this.data = new DataInstance({
30
- state: {options},
31
- previewPurchase: new SummaryModel({
32
- currency: 'USD',
33
- lineItems: [
34
- {
35
- type: 'debit',
36
- description: 'My Awesome Product',
37
- unitPrice: 30,
38
- quantity: 1,
39
- price: 30,
40
- productId: 'test-product-1',
41
- planId: 'my-awesome-product'
42
- },
43
- {
44
- type: 'debit',
45
- description: 'Awesome T-Shirt',
46
- unitPrice: 20,
47
- quantity: 2,
48
- price: 40,
49
- productId: 'test-product-2',
50
- planId: 'awesome-t-shirt'
51
- }
52
- ],
53
- subtotalAmount: 70,
54
- taxAmount: 0,
55
- shippingAmount: 0,
56
- discountsAmount: 0,
57
- total: 70
58
- }),
59
- plans: [
60
- new PlanModel({
61
- name: 'My Awesome Product',
62
- id: 'my-awesome-product',
63
- productId: 'test-product-1'
64
- }),
65
- new PlanModel({
66
- name: 'My Awesome T-Shirt',
67
- id: 'awesome-t-shirt',
68
- productId: 'test-product-2'
69
- })
70
- ],
71
- products: [
72
- new ProductModel({
73
- name: 'My Awesome Product',
74
- id: 'test-product-1'
75
- }),
76
- new ProductModel({
77
- name: 'My Awesome T-Shirt',
78
- id: 'test-product-2'
79
- })
80
- ],
81
- ...data
82
- });
83
- }
84
- }
85
-
86
- const options = {
87
- websiteId: 'test-website-id',
88
- countryCode: 'US',
89
- items: [
90
- {
91
- planId: 'my-awesome-product',
92
- quantity: 1,
93
- thumbnail: ''
94
- },
95
- {
96
- planId: 'awesome-t-shirt',
97
- quantity: 2,
98
- thumbnail: ''
99
- }
100
- ]
101
- };
102
-
103
- it('should render the summary correctly', () => {
104
- const mountSummaryInstance = new TestMountSummaryInstance({
105
- options
106
- });
107
-
108
- //TODO: improve design to avoid this manual change
109
- mountSummaryInstance.loader.DOM.summary = mountSummaryInstance.summary;
110
-
111
- mountSummary({ state: mountSummaryInstance });
112
-
113
- // Number of line items
114
- const itemsContainer = document.querySelector(
115
- '.rebilly-instruments-summary-line-items'
116
- );
117
- expect(itemsContainer).toMatchSnapshot();
118
-
119
- // Breakdown
120
- const summaryBreakdown = document.querySelector(
121
- '.rebilly-instruments-summary-breakdown'
122
- );
123
- expect(summaryBreakdown).toMatchSnapshot();
124
- });
125
-
126
- it('should not render the plan description if its falsy', () => {
127
- const mountSummaryInstance = new TestMountSummaryInstance({
128
- options
129
- });
130
-
131
- // Making one product description falsy
132
- mountSummaryInstance.data.previewPurchase.lineItems[0].description = null;
133
-
134
- //TODO: improve design to avoid this manual change
135
- mountSummaryInstance.loader.DOM.summary = mountSummaryInstance.summary;
136
-
137
- mountSummary({ state: mountSummaryInstance });
138
-
139
- // Check that only one description is render
140
- const itemsSynopsysDescription = document.querySelectorAll(
141
- '.rebilly-instruments-summary-line-item-synopsis-description'
142
- );
143
- expect(itemsSynopsysDescription.length).toEqual(1);
144
- });
145
- });