@rebilly/instruments 2.1.0-beta.0 → 3.1.0-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/dist/functions/mount/fetch-data.js +70 -56
- package/dist/functions/mount/fetch-data.spec.js +58 -34
- package/dist/functions/mount/index.js +6 -0
- package/dist/functions/mount/mount.spec.js +2 -4
- package/dist/functions/mount/setup-framepay-theme.js +95 -0
- package/dist/functions/mount/setup-options.js +3 -0
- package/dist/i18n/en.json +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/style/base/__snapshots__/theme.spec.js.snap +220 -45
- package/dist/style/base/default-theme.js +804 -0
- package/dist/style/base/index.js +48 -16
- package/dist/style/base/theme.js +16 -49
- package/dist/style/base/theme.spec.js +4 -15
- package/dist/style/components/address.js +3 -3
- package/dist/style/components/button.js +48 -22
- package/dist/style/components/divider.js +9 -9
- package/dist/style/components/forms/checkbox.js +12 -9
- package/dist/style/components/forms/field.js +18 -6
- package/dist/style/components/forms/form.js +2 -2
- package/dist/style/components/forms/input.js +54 -13
- package/dist/style/components/forms/label.js +39 -18
- package/dist/style/components/forms/select.js +54 -22
- package/dist/style/components/forms/validation.js +53 -6
- package/dist/style/components/icons.js +4 -4
- package/dist/style/components/loader.js +5 -3
- package/dist/style/components/methods.js +18 -15
- package/dist/style/components/overlay.js +5 -5
- package/dist/style/helpers/index.js +46 -46
- package/dist/style/index.js +3 -1
- package/dist/style/payment-instruments/payment-card.js +4 -4
- package/dist/style/utils/border.js +47 -0
- package/dist/style/utils/color-values.js +39 -3
- package/dist/style/utils/remove-empty-null.js +20 -0
- package/dist/style/vendor/framepay.js +11 -8
- package/dist/style/vendor/postmate.js +2 -2
- package/dist/style/views/confirmation.js +13 -13
- package/dist/style/views/method-selector.js +2 -2
- package/dist/style/views/modal.js +6 -6
- package/dist/style/views/result.js +4 -4
- package/dist/style/views/summary.js +23 -23
- package/dist/views/__snapshots__/summary.spec.js.snap +4 -40
- package/dist/views/common/iframe/modal-iframe.js +6 -1
- package/dist/views/summary.js +17 -11
- package/package.json +3 -1
- package/src/functions/mount/fetch-data.js +60 -46
- package/src/functions/mount/fetch-data.spec.js +67 -33
- package/src/functions/mount/index.js +2 -0
- package/src/functions/mount/mount.spec.js +3 -5
- package/src/functions/mount/setup-framepay-theme.js +82 -0
- package/src/functions/mount/setup-options.js +3 -0
- package/src/i18n/en.json +1 -1
- package/src/i18n/index.js +1 -1
- package/src/style/base/__snapshots__/theme.spec.js.snap +220 -45
- package/src/style/base/default-theme.js +777 -0
- package/src/style/base/index.js +48 -16
- package/src/style/base/theme.js +17 -47
- package/src/style/base/theme.spec.js +4 -16
- package/src/style/components/address.js +3 -3
- package/src/style/components/button.js +48 -24
- package/src/style/components/divider.js +9 -9
- package/src/style/components/forms/checkbox.js +11 -11
- package/src/style/components/forms/field.js +18 -6
- package/src/style/components/forms/form.js +2 -2
- package/src/style/components/forms/input.js +54 -13
- package/src/style/components/forms/label.js +39 -18
- package/src/style/components/forms/select.js +54 -22
- package/src/style/components/forms/validation.js +53 -6
- package/src/style/components/icons.js +4 -4
- package/src/style/components/loader.js +4 -5
- package/src/style/components/methods.js +18 -15
- package/src/style/components/overlay.js +5 -5
- package/src/style/helpers/index.js +46 -46
- package/src/style/index.js +2 -1
- package/src/style/payment-instruments/payment-card.js +4 -4
- package/src/style/utils/border.js +34 -0
- package/src/style/utils/color-values.js +27 -1
- package/src/style/utils/remove-empty-null.js +10 -0
- package/src/style/vendor/framepay.js +11 -8
- package/src/style/vendor/postmate.js +2 -2
- package/src/style/views/confirmation.js +13 -13
- package/src/style/views/method-selector.js +2 -2
- package/src/style/views/modal.js +6 -6
- package/src/style/views/result.js +4 -4
- package/src/style/views/summary.js +23 -23
- package/src/views/__snapshots__/summary.spec.js.snap +4 -40
- package/src/views/common/iframe/modal-iframe.js +7 -1
- package/src/views/summary.js +17 -11
|
@@ -98,6 +98,10 @@ class DataInstance {
|
|
|
98
98
|
return lineItems;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
get isShippingRequired() {
|
|
102
|
+
return this.products.some(product => product.requiresShipping);
|
|
103
|
+
}
|
|
104
|
+
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
exports.DataInstance = DataInstance;
|
|
@@ -105,69 +109,79 @@ exports.DataInstance = DataInstance;
|
|
|
105
109
|
async function fetchData({
|
|
106
110
|
state = null,
|
|
107
111
|
riskMetadata = null,
|
|
108
|
-
summaryPayload = null
|
|
112
|
+
summaryPayload = null,
|
|
113
|
+
// Dependancy injectable functions
|
|
114
|
+
fetchInvoice = _invoices.fetchInvoice,
|
|
115
|
+
fetchTransaction = _transactions.fetchTransaction
|
|
109
116
|
}) {
|
|
110
|
-
|
|
117
|
+
try {
|
|
118
|
+
var _state$options2, _state$options3, _state$data, _state$data$transacti, _state$data3;
|
|
119
|
+
|
|
120
|
+
let transaction = null;
|
|
121
|
+
|
|
122
|
+
if ((_state$options2 = state.options) !== null && _state$options2 !== void 0 && _state$options2.transactionId) {
|
|
123
|
+
transaction = await fetchTransaction({
|
|
124
|
+
data: {
|
|
125
|
+
id: state.options.transactionId
|
|
126
|
+
},
|
|
127
|
+
state
|
|
128
|
+
});
|
|
129
|
+
state.data.transaction = transaction;
|
|
130
|
+
}
|
|
111
131
|
|
|
112
|
-
|
|
132
|
+
let invoice = null;
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
134
|
+
if ((_state$options3 = state.options) !== null && _state$options3 !== void 0 && _state$options3.invoiceId || (_state$data = state.data) !== null && _state$data !== void 0 && (_state$data$transacti = _state$data.transaction) !== null && _state$data$transacti !== void 0 && _state$data$transacti.hasInvoice) {
|
|
135
|
+
var _state$options4, _state$data2, _state$data2$transact;
|
|
136
|
+
|
|
137
|
+
invoice = await fetchInvoice({
|
|
138
|
+
data: {
|
|
139
|
+
id: ((_state$options4 = state.options) === null || _state$options4 === void 0 ? void 0 : _state$options4.invoiceId) || ((_state$data2 = state.data) === null || _state$data2 === void 0 ? void 0 : (_state$data2$transact = _state$data2.transaction) === null || _state$data2$transact === void 0 ? void 0 : _state$data2$transact.invoiceId)
|
|
140
|
+
},
|
|
141
|
+
state
|
|
142
|
+
});
|
|
143
|
+
state.data.invoice = invoice;
|
|
144
|
+
}
|
|
123
145
|
|
|
124
|
-
|
|
146
|
+
if (!riskMetadata) {
|
|
147
|
+
const {
|
|
148
|
+
riskMetadata: data
|
|
149
|
+
} = await (0, _riskDataCollector.collectData)();
|
|
150
|
+
riskMetadata = data;
|
|
151
|
+
}
|
|
125
152
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
153
|
+
state.data = new DataInstance({
|
|
154
|
+
state,
|
|
155
|
+
invoice,
|
|
156
|
+
transaction,
|
|
157
|
+
riskMetadata
|
|
158
|
+
});
|
|
159
|
+
const [readyToPay, previewPurchase] = await Promise.all([((_state$data3 = state.data) === null || _state$data3 === void 0 ? void 0 : _state$data3.readyToPay) || (0, _readyToPay.fetchReadyToPay)({
|
|
160
|
+
riskMetadata,
|
|
161
|
+
state
|
|
162
|
+
}), state.options.items ? (0, _summary.fetchSummary)({
|
|
163
|
+
data: summaryPayload,
|
|
164
|
+
state
|
|
165
|
+
}) : null]);
|
|
166
|
+
const plans = await (0, _plans.fetchPlans)({
|
|
131
167
|
state
|
|
132
168
|
});
|
|
133
|
-
state.data.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
169
|
+
state.data.plans = plans;
|
|
170
|
+
const products = await (0, _products.fetchProducts)({
|
|
171
|
+
state
|
|
172
|
+
});
|
|
173
|
+
return new DataInstance({
|
|
174
|
+
state,
|
|
175
|
+
readyToPay,
|
|
176
|
+
previewPurchase,
|
|
177
|
+
plans,
|
|
178
|
+
products,
|
|
179
|
+
invoice,
|
|
180
|
+
transaction,
|
|
181
|
+
riskMetadata
|
|
182
|
+
});
|
|
183
|
+
} catch (error) {// console.log(error);
|
|
141
184
|
}
|
|
142
185
|
|
|
143
|
-
|
|
144
|
-
state,
|
|
145
|
-
invoice,
|
|
146
|
-
transaction,
|
|
147
|
-
riskMetadata
|
|
148
|
-
});
|
|
149
|
-
const [readyToPay, previewPurchase] = await Promise.all([((_state$data2 = state.data) === null || _state$data2 === void 0 ? void 0 : _state$data2.readyToPay) || (0, _readyToPay.fetchReadyToPay)({
|
|
150
|
-
riskMetadata,
|
|
151
|
-
state
|
|
152
|
-
}), state.options.items ? (0, _summary.fetchSummary)({
|
|
153
|
-
data: summaryPayload,
|
|
154
|
-
state
|
|
155
|
-
}) : null]);
|
|
156
|
-
const plans = await (0, _plans.fetchPlans)({
|
|
157
|
-
state
|
|
158
|
-
});
|
|
159
|
-
state.data.plans = plans;
|
|
160
|
-
const products = await (0, _products.fetchProducts)({
|
|
161
|
-
state
|
|
162
|
-
});
|
|
163
|
-
return new DataInstance({
|
|
164
|
-
state,
|
|
165
|
-
readyToPay,
|
|
166
|
-
previewPurchase,
|
|
167
|
-
plans,
|
|
168
|
-
products,
|
|
169
|
-
invoice,
|
|
170
|
-
transaction,
|
|
171
|
-
riskMetadata
|
|
172
|
-
});
|
|
186
|
+
return new DataInstance({});
|
|
173
187
|
}
|
|
@@ -2,43 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
var _fetchData = require("./fetch-data");
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
class TestInstance {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.storefront = jest.fn();
|
|
9
|
-
this.options = jest.fn();
|
|
10
|
-
this._fetchSummary = jest.fn(() => {
|
|
11
|
-
return new Promise(resolve => resolve({}));
|
|
12
|
-
});
|
|
13
|
-
this._fetchProducts = jest.fn();
|
|
14
|
-
}
|
|
5
|
+
var _transactionModel = _interopRequireDefault(require("../../storefront/models/transaction-model"));
|
|
15
6
|
|
|
16
|
-
|
|
7
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
8
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
9
|
+
describe('fetchData function', () => {
|
|
10
|
+
it('Should use correct invoice id for invoiceId', async () => {
|
|
11
|
+
const mockFetchInvoice = jest.fn();
|
|
12
|
+
const invoiceId = 'test-invoice-id';
|
|
13
|
+
const invoiceState = {
|
|
14
|
+
options: {
|
|
15
|
+
invoiceId
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
(0, _fetchData.fetchData)({
|
|
19
|
+
state: invoiceState,
|
|
20
|
+
fetchInvoice: mockFetchInvoice
|
|
21
|
+
});
|
|
22
|
+
expect(mockFetchInvoice).toBeCalledTimes(1);
|
|
23
|
+
expect(mockFetchInvoice).toBeCalledWith(expect.objectContaining({
|
|
24
|
+
data: {
|
|
25
|
+
id: invoiceId
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
29
|
+
it('Should use correct invoice id for transaction with invoiceIds', async () => {
|
|
30
|
+
const mockFetchInvoice = jest.fn();
|
|
31
|
+
const invoiceId = 'test-invoice-id';
|
|
32
|
+
const invoiceState = {
|
|
33
|
+
options: {},
|
|
34
|
+
data: {
|
|
35
|
+
transaction: new _transactionModel.default({
|
|
36
|
+
invoiceIds: [invoiceId]
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
(0, _fetchData.fetchData)({
|
|
41
|
+
state: invoiceState,
|
|
42
|
+
fetchInvoice: mockFetchInvoice
|
|
43
|
+
});
|
|
44
|
+
expect(mockFetchInvoice).toBeCalledTimes(1);
|
|
45
|
+
expect(mockFetchInvoice).toBeCalledWith(expect.objectContaining({
|
|
46
|
+
data: {
|
|
47
|
+
id: invoiceId
|
|
48
|
+
}
|
|
49
|
+
}));
|
|
28
50
|
});
|
|
29
|
-
it('
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
it('Should not fetch invoice for transaction with no invoice Ids', async () => {
|
|
52
|
+
const mockFetchInvoice = jest.fn();
|
|
53
|
+
const invoiceState = {
|
|
54
|
+
options: {},
|
|
55
|
+
data: {
|
|
56
|
+
transaction: new _transactionModel.default({
|
|
57
|
+
invoiceIds: []
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
(0, _fetchData.fetchData)({
|
|
62
|
+
state: invoiceState,
|
|
63
|
+
fetchInvoice: mockFetchInvoice
|
|
64
|
+
});
|
|
65
|
+
expect(mockFetchInvoice).toBeCalledTimes(0);
|
|
42
66
|
});
|
|
43
67
|
});
|
|
44
68
|
describe('DataInstance', () => {
|
|
@@ -27,6 +27,8 @@ var _setupStyles = _interopRequireDefault(require("./setup-styles"));
|
|
|
27
27
|
|
|
28
28
|
var _setupI18n = _interopRequireDefault(require("./setup-i18n"));
|
|
29
29
|
|
|
30
|
+
var _setupFramepayTheme = _interopRequireDefault(require("./setup-framepay-theme"));
|
|
31
|
+
|
|
30
32
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
31
33
|
|
|
32
34
|
/* eslint-disable max-len */
|
|
@@ -139,6 +141,10 @@ async function mount({
|
|
|
139
141
|
state.data = await (0, _fetchData.fetchData)({
|
|
140
142
|
state
|
|
141
143
|
});
|
|
144
|
+
state.options.themeFramepay = await (0, _setupFramepayTheme.default)({
|
|
145
|
+
state,
|
|
146
|
+
options
|
|
147
|
+
});
|
|
142
148
|
const i18n = (0, _setupI18n.default)({
|
|
143
149
|
state
|
|
144
150
|
});
|
|
@@ -31,9 +31,7 @@ describe('RebillyInstruments instance', () => {
|
|
|
31
31
|
quantity: 1
|
|
32
32
|
}],
|
|
33
33
|
theme: {
|
|
34
|
-
|
|
35
|
-
background: '#000'
|
|
36
|
-
}
|
|
34
|
+
colorBackground: '#000'
|
|
37
35
|
},
|
|
38
36
|
css: `
|
|
39
37
|
.rebilly-instruments-summary-line-item-synopsis-title {
|
|
@@ -50,7 +48,7 @@ describe('RebillyInstruments instance', () => {
|
|
|
50
48
|
expect(summarySelector.innerHTML).toMatch('My Product'); // Theme config overrides initial styles
|
|
51
49
|
|
|
52
50
|
const SUMMARY_CONTAINER = summarySelector.querySelector('.rebilly-instruments-content');
|
|
53
|
-
expect(getComputedStyle(SUMMARY_CONTAINER).
|
|
51
|
+
expect(getComputedStyle(SUMMARY_CONTAINER).getPropertyValue('--rebilly-colorBackground')).toEqual('#000'); // CSS config property overrides initial styles
|
|
54
52
|
|
|
55
53
|
const LINE_ITEM_TITLE = document.querySelector('.rebilly-instruments-summary-line-item-synopsis-title');
|
|
56
54
|
expect(getComputedStyle(LINE_ITEM_TITLE).color).toEqual('rgb(0, 68, 212)'); // Mounts default FramePay script
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _css = _interopRequireDefault(require("css"));
|
|
9
|
+
|
|
10
|
+
var _postcss = _interopRequireDefault(require("postcss"));
|
|
11
|
+
|
|
12
|
+
var _postcssCustomProperties = _interopRequireDefault(require("postcss-custom-properties"));
|
|
13
|
+
|
|
14
|
+
var _lodash = _interopRequireDefault(require("lodash.camelcase"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
const resolveCssVars = async rawCss => (0, _postcss.default)([(0, _postcssCustomProperties.default)({
|
|
19
|
+
preserve: false
|
|
20
|
+
})]).process(rawCss, {
|
|
21
|
+
from: undefined
|
|
22
|
+
}).then(output => output.css);
|
|
23
|
+
|
|
24
|
+
const getStyleProps = (ast, selector) => {
|
|
25
|
+
const {
|
|
26
|
+
rules
|
|
27
|
+
} = ast.stylesheet;
|
|
28
|
+
const output = {
|
|
29
|
+
color: null,
|
|
30
|
+
fontFamily: null,
|
|
31
|
+
fontSize: null,
|
|
32
|
+
lineHeight: null,
|
|
33
|
+
fontWeight: null,
|
|
34
|
+
background: null
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < rules.length; i += 1) {
|
|
38
|
+
const rule = rules[i];
|
|
39
|
+
|
|
40
|
+
if (rule.type === 'rule' && rule.selectors.includes(selector)) {
|
|
41
|
+
rule.declarations.forEach(decl => {
|
|
42
|
+
const propName = (0, _lodash.default)(decl.property);
|
|
43
|
+
|
|
44
|
+
if (typeof output[propName] !== 'undefined') {
|
|
45
|
+
output[propName] = decl.value;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return output;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
var _default = async ({
|
|
55
|
+
state,
|
|
56
|
+
options = {}
|
|
57
|
+
}) => {
|
|
58
|
+
const fullCss = `
|
|
59
|
+
${state.mainStyle}
|
|
60
|
+
${options.css || ''}
|
|
61
|
+
`;
|
|
62
|
+
const resolvedCss = await resolveCssVars(fullCss);
|
|
63
|
+
|
|
64
|
+
const cssAst = _css.default.parse(resolvedCss);
|
|
65
|
+
|
|
66
|
+
const cssSelectors = {
|
|
67
|
+
base: '.rebilly-instruments-form-field-input',
|
|
68
|
+
baseHover: '.rebilly-instruments-form-field-input:hover',
|
|
69
|
+
baseFocus: '.rebilly-instruments-form-field-input:focus',
|
|
70
|
+
basePlaceholder: '.rebilly-instruments-form-field-input::placeholder',
|
|
71
|
+
baseSelection: '.rebilly-instruments-form-field-input::selection',
|
|
72
|
+
invalid: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input',
|
|
73
|
+
invalidHover: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:hover',
|
|
74
|
+
invalidFocus: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:focus',
|
|
75
|
+
invalidPlaceholder: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::placeholder',
|
|
76
|
+
invalidSelection: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::selection'
|
|
77
|
+
};
|
|
78
|
+
const framepayStyle = {
|
|
79
|
+
base: { ...getStyleProps(cssAst, cssSelectors.base),
|
|
80
|
+
':hover': getStyleProps(cssAst, cssSelectors.baseHover),
|
|
81
|
+
':focus': getStyleProps(cssAst, cssSelectors.baseFocus),
|
|
82
|
+
'::placeholder': getStyleProps(cssAst, cssSelectors.basePlaceholder),
|
|
83
|
+
'::selection': getStyleProps(cssAst, cssSelectors.baseSelection)
|
|
84
|
+
},
|
|
85
|
+
invalid: { ...getStyleProps(cssAst, cssSelectors.invalid),
|
|
86
|
+
':hover': getStyleProps(cssAst, cssSelectors.invalidHover),
|
|
87
|
+
':focus': getStyleProps(cssAst, cssSelectors.invalidFocus),
|
|
88
|
+
'::placeholder': getStyleProps(cssAst, cssSelectors.invalidPlaceholder),
|
|
89
|
+
'::selection': getStyleProps(cssAst, cssSelectors.invalidSelection)
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
return framepayStyle;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
exports.default = _default;
|
package/dist/i18n/en.json
CHANGED
package/dist/i18n/index.js
CHANGED
|
@@ -23,7 +23,7 @@ class Translate {
|
|
|
23
23
|
init(locale, messages) {
|
|
24
24
|
this.items = document.querySelectorAll('[data-rebilly-i18n]');
|
|
25
25
|
this.locale = this.getLocale(locale);
|
|
26
|
-
this.languages = (0, _lodash.default)({ ..._en.default,
|
|
26
|
+
this.languages = (0, _lodash.default)({}, { ..._en.default,
|
|
27
27
|
..._es.default
|
|
28
28
|
}, messages);
|
|
29
29
|
}
|