@automattic/newspack-blocks 2.6.2 → 3.0.0-alpha.1

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 (99) hide show
  1. package/.cache/babel/135eb7c6e583be53418b26a29fcc4d81.json.gz +0 -0
  2. package/.cache/babel/2bec24377bb9890c2268bcd4c8f3953c.json.gz +0 -0
  3. package/.cache/babel/9ba57ee86df44178ceb255eaf0e770e3.json.gz +0 -0
  4. package/.cache/babel/a804bf1963e56137e59e37a567cb5e2e.json.gz +0 -0
  5. package/.cache/babel/b94e6dc0852876a37bd23ec88c5b2583.json.gz +0 -0
  6. package/.cache/babel/c04d2af94bb0f10f408a15534301cc86.json.gz +0 -0
  7. package/.cache/babel/c8d4b9ae4be3002e8507d71f1136ebc6.json.gz +0 -0
  8. package/.cache/babel/d21f5515648ce2a2349b0ee5cc787fce.json.gz +0 -0
  9. package/.cache/babel/d3eee0c40fc44bc734dee21a645a4f7d.json.gz +0 -0
  10. package/.cache/babel/d661309b03e38954105e706a32ef09f6.json.gz +0 -0
  11. package/.cache/babel/e2dd36051554e75a2bf087b85c11e43d.json.gz +0 -0
  12. package/.hooks/pre-push +2 -2
  13. package/CHANGELOG.md +21 -0
  14. package/composer.lock +38 -36
  15. package/dist/donate/view.asset.php +1 -1
  16. package/dist/donate/view.css +1 -1
  17. package/dist/donate/view.rtl.css +1 -1
  18. package/dist/editor.asset.php +1 -1
  19. package/dist/editor.css +1 -1
  20. package/dist/editor.js +11 -11
  21. package/dist/editor.rtl.css +1 -1
  22. package/dist/frequencyBased.asset.php +1 -1
  23. package/dist/frequencyBased.css +1 -1
  24. package/dist/frequencyBased.rtl.css +1 -1
  25. package/dist/modalCheckout.asset.php +1 -1
  26. package/dist/modalCheckout.css +1 -1
  27. package/dist/modalCheckout.rtl.css +1 -1
  28. package/dist/tiersBased.asset.php +1 -1
  29. package/dist/tiersBased.css +1 -1
  30. package/dist/tiersBased.js +1 -1
  31. package/dist/tiersBased.rtl.css +1 -1
  32. package/includes/class-modal-checkout.php +11 -14
  33. package/includes/class-newspack-blocks.php +87 -43
  34. package/languages/newspack-blocks-de_DE.po +0 -40
  35. package/languages/newspack-blocks-es_ES.po +0 -40
  36. package/languages/newspack-blocks-fr_BE.po +0 -40
  37. package/languages/newspack-blocks-pt_PT.po +0 -40
  38. package/languages/newspack-blocks.pot +0 -38
  39. package/newspack-blocks.php +2 -14
  40. package/package.json +7 -8
  41. package/src/blocks/checkout-button/edit.js +5 -1
  42. package/src/blocks/donate/block.json +0 -12
  43. package/src/blocks/donate/edit/FrequencyBasedLayout.tsx +61 -106
  44. package/src/blocks/donate/edit/TierBasedLayout.tsx +7 -26
  45. package/src/blocks/donate/edit/components/index.tsx +0 -1
  46. package/src/blocks/donate/edit/index.tsx +157 -152
  47. package/src/blocks/donate/frequency-based/style.scss +5 -0
  48. package/src/blocks/donate/frontend/class-newspack-blocks-donate-renderer-base.php +33 -147
  49. package/src/blocks/donate/frontend/class-newspack-blocks-donate-renderer-frequency-based.php +21 -10
  50. package/src/blocks/donate/frontend/class-newspack-blocks-donate-renderer-tiers-based.php +3 -50
  51. package/src/blocks/donate/frontend/class-newspack-blocks-donate-renderer.php +1 -14
  52. package/src/blocks/donate/styles/editor.scss +6 -28
  53. package/src/blocks/donate/styles/style-variations.scss +17 -8
  54. package/src/blocks/donate/styles/view.scss +9 -0
  55. package/src/blocks/donate/tiers-based/style.scss +0 -11
  56. package/src/blocks/donate/tiers-based/utils.test.js +38 -0
  57. package/src/blocks/donate/tiers-based/utils.ts +1 -2
  58. package/src/blocks/donate/tiers-based/view.ts +0 -33
  59. package/src/blocks/donate/types.ts +0 -16
  60. package/src/blocks/donate/utils.ts +31 -0
  61. package/src/blocks/homepage-articles/block.json +18 -0
  62. package/src/blocks/homepage-articles/class-wp-rest-newspack-articles-controller.php +1 -1
  63. package/src/blocks/homepage-articles/edit.js +3 -0
  64. package/src/blocks/homepage-articles/utils.ts +4 -0
  65. package/src/blocks/homepage-articles/view.php +4 -4
  66. package/src/components/query-controls.js +41 -8
  67. package/src/modal-checkout/checkout.scss +4 -5
  68. package/src/types/index.d.ts +4 -3
  69. package/vendor/autoload.php +1 -1
  70. package/vendor/composer/autoload_real.php +4 -4
  71. package/vendor/composer/autoload_static.php +2 -2
  72. package/vendor/composer/installed.php +2 -2
  73. package/webpack.config.js +0 -1
  74. package/.cache/babel/18dda1142078f066419138e7284f03bf.json.gz +0 -0
  75. package/.cache/babel/1f43960564787ebde7c6d44957cddf0e.json.gz +0 -0
  76. package/.cache/babel/225618337c609eed2be110274ff82be1.json.gz +0 -0
  77. package/.cache/babel/29d960d2fc51492a4bea1f4f165810fb.json.gz +0 -0
  78. package/.cache/babel/2f22325668b5763f8f2c9557833af36f.json.gz +0 -0
  79. package/.cache/babel/39bcc541624feefe54d1493493ae1ce8.json.gz +0 -0
  80. package/.cache/babel/4d450b37d365154f05b17cbf6a009255.json.gz +0 -0
  81. package/.cache/babel/87e2dc4a961b25b0de8d1a8ac88eea13.json.gz +0 -0
  82. package/.cache/babel/91884d41523f3790da70ea305ee187f2.json.gz +0 -0
  83. package/.cache/babel/b1ac90699e641ff99e1449b5d7b686e5.json.gz +0 -0
  84. package/.cache/babel/c5a441fdf7d90d45d2cbeb89967c61fe.json.gz +0 -0
  85. package/.cache/babel/c7cfb8590e887722a3e715c72ee99bac.json.gz +0 -0
  86. package/.cache/babel/e1d8932bb19afa36f476f107dbc6ca39.json.gz +0 -0
  87. package/.cache/babel/f60f8c23ec2b4448cb2815d79207d8c0.json.gz +0 -0
  88. package/dist/donateStreamlined.asset.php +0 -1
  89. package/dist/donateStreamlined.css +0 -1
  90. package/dist/donateStreamlined.js +0 -1
  91. package/dist/donateStreamlined.rtl.css +0 -1
  92. package/src/blocks/donate/class-wp-rest-newspack-donate-controller.php +0 -206
  93. package/src/blocks/donate/edit/components/AdditionalFields.tsx +0 -282
  94. package/src/blocks/donate/streamlined/index.test.js +0 -132
  95. package/src/blocks/donate/streamlined/index.ts +0 -356
  96. package/src/blocks/donate/streamlined/style.scss +0 -306
  97. package/src/blocks/donate/streamlined/utils.test.js +0 -18
  98. package/src/blocks/donate/streamlined/utils.ts +0 -217
  99. package/src/blocks/donate/tiers-based/view.test.js +0 -209
@@ -1,356 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { __ } from '@wordpress/i18n';
5
-
6
- /**
7
- * External dependencies
8
- */
9
- import { loadStripe } from '@stripe/stripe-js/pure';
10
- import type * as Stripe from '@stripe/stripe-js/types';
11
- import 'regenerator-runtime'; // Required in WP >=5.8.
12
-
13
- /**
14
- * Internal dependencies
15
- */
16
- import * as utils from './utils';
17
- import './style.scss';
18
-
19
- const getAdditionalFieldsValues = ( formElement: HTMLFormElement ) => {
20
- const fields = [
21
- ...formElement.querySelectorAll( 'input[data-is-additional-field]' ),
22
- ] as HTMLInputElement[];
23
- return fields.map( field => ( { name: field.name, value: field.value } ) );
24
- };
25
-
26
- export const processStreamlinedElements = ( parentElement = document ) =>
27
- [ ...parentElement.querySelectorAll( '.stripe-payment' ) ].forEach( async el => {
28
- let stripe: Stripe.Stripe | null,
29
- cardElement: Stripe.StripeCardElement,
30
- paymentRequest: Stripe.PaymentRequest,
31
- paymentRequestToken: Stripe.Token,
32
- isCardUIVisible = false;
33
-
34
- const formElement: HTMLFormElement | null = el.closest( 'form' );
35
- const messagesEl: HTMLDivElement | null = el.querySelector( '.stripe-payment__messages' );
36
- if ( ! formElement || ! messagesEl ) {
37
- return;
38
- }
39
-
40
- const blockWrapperElement = el.closest( '.wpbnbd' );
41
- const paymentFlowCompleteEventName = `newspackPaymentFlowComplete-${
42
- blockWrapperElement?.id || ''
43
- }`;
44
-
45
- const settings = utils.getSettings( formElement );
46
-
47
- const disableForm = () => el.classList.add( 'stripe-payment--disabled' );
48
- const enableForm = () => el.classList.remove( 'stripe-payment--disabled' );
49
- enableForm();
50
-
51
- // Display CC UI.
52
- const displayCardUI = () => {
53
- if ( isCardUIVisible ) {
54
- return;
55
- }
56
- const inputsHiddenEl = el.querySelector( '.stripe-payment__inputs.stripe-payment--hidden' );
57
- if ( inputsHiddenEl ) {
58
- inputsHiddenEl.classList.remove( 'stripe-payment--hidden' );
59
- isCardUIVisible = true;
60
- }
61
- };
62
-
63
- const getCaptchaToken = async ( captchaSiteKey: string ) => {
64
- return new Promise( ( res, rej ) => {
65
- const { grecaptcha } = window;
66
- if ( ! grecaptcha ) {
67
- return res( '' );
68
- }
69
-
70
- if ( ! grecaptcha?.ready || ! captchaSiteKey ) {
71
- rej( __( 'Error loading the reCaptcha library.', 'newspack-blocks' ) );
72
- }
73
-
74
- grecaptcha.ready( async () => {
75
- try {
76
- const token = await grecaptcha.execute( captchaSiteKey, { action: 'submit' } );
77
- return res( token );
78
- } catch ( e ) {
79
- rej( e );
80
- }
81
- } );
82
- } );
83
- };
84
-
85
- // Universal payment handling, for both card and payment request button flows.
86
- // In card flow, this will happen after user submits their card data in the HTML form.
87
- // In payment request flow, this will happen after the user validates the payment in
88
- // the browser/OS UI.
89
- const payWithSource = async (
90
- source: Stripe.Source,
91
- token: Stripe.Token | undefined = undefined,
92
- /**
93
- * Overrides for sent donation data. In a card flow the data is
94
- * provided explicitly by the user (via the form), but in payment request flow
95
- * the data is from the payment request event.
96
- */
97
- requestPayloadOverrides = {}
98
- ) => {
99
- if ( ! stripe ) {
100
- return;
101
- }
102
-
103
- // Add reCaptcha challenge to form submission, if available.
104
- const captchaSiteKey = settings?.captchaSiteKey;
105
- let captchaToken;
106
- if ( captchaSiteKey ) {
107
- try {
108
- captchaToken = await getCaptchaToken( captchaSiteKey );
109
- } catch ( e ) {
110
- const errorMessage =
111
- e instanceof Error
112
- ? e.message
113
- : __( 'Error processing captcha request.', 'newspack-blocks' );
114
- utils.renderMessages( [ errorMessage ], messagesEl );
115
- return { error: true };
116
- }
117
- }
118
- const formValues = utils.getDonationFormValues( formElement );
119
-
120
- const additionalFields: { name: string; value: string }[] =
121
- getAdditionalFieldsValues( formElement );
122
-
123
- const apiRequestPayload = {
124
- captchaToken,
125
- stripe_tokenization_method: token ? token.card?.tokenization_method : 'card',
126
- stripe_source_id: source.id,
127
- amount: utils.getTotalAmount( formElement ),
128
- email: formValues.email,
129
- full_name: formValues.full_name,
130
- frequency: formValues.donation_frequency,
131
- newsletter_opt_in: Boolean( formValues.newsletter_opt_in ),
132
- newspack_popup_id: formValues.newspack_popup_id,
133
- _wp_http_referer: formValues._wp_http_referer,
134
- clientId: formValues.cid,
135
- additional_fields: additionalFields,
136
- ...requestPayloadOverrides,
137
- };
138
-
139
- const chargeResultData = await utils.sendAPIRequest( '/donate', apiRequestPayload );
140
-
141
- // Error handling.
142
- if ( chargeResultData.data?.status !== 200 && chargeResultData.message ) {
143
- utils.renderMessages( [ chargeResultData.message ], messagesEl );
144
- return { error: true };
145
- }
146
- if ( chargeResultData.error ) {
147
- utils.renderMessages( [ chargeResultData.error ], messagesEl );
148
- return { error: true };
149
- }
150
-
151
- const exitWithError = ( errorMessage: Stripe.StripeError[ 'message' ] ) => {
152
- utils.renderMessages( [ errorMessage ], messagesEl );
153
- enableForm();
154
- window.dispatchEvent( new Event( paymentFlowCompleteEventName ) );
155
- return { error: true };
156
- };
157
-
158
- // Additional steps handling.
159
- if ( chargeResultData.client_secret ) {
160
- const confirmationResult = await stripe.confirmCardPayment(
161
- chargeResultData.client_secret
162
- );
163
-
164
- if ( confirmationResult.error ) {
165
- return exitWithError( confirmationResult.error.message );
166
- } else if ( confirmationResult.paymentIntent.status === 'succeeded' ) {
167
- utils.renderSuccessMessageWithEmail( apiRequestPayload.email, messagesEl );
168
- } else if ( confirmationResult.paymentIntent.status === 'requires_action' ) {
169
- // Could not test this flow (with 3D Secure test cards), but it's listed in the docs:
170
- // https://stripe.com/docs/stripe-js/elements/payment-request-button#html-js-complete-payment
171
- const { error: confirmationError } = await stripe.confirmCardPayment(
172
- chargeResultData.client_secret
173
- );
174
- if ( confirmationError ) {
175
- return exitWithError( confirmationError.message );
176
- }
177
- utils.renderSuccessMessageWithEmail( apiRequestPayload.email, messagesEl );
178
- } else {
179
- return exitWithError(
180
- __(
181
- 'Something went wrong with the payment. Please try again later.',
182
- 'newspack-blocks'
183
- )
184
- );
185
- }
186
- }
187
-
188
- if ( chargeResultData.status === 'success' ) {
189
- utils.renderSuccessMessageWithEmail( apiRequestPayload.email, messagesEl );
190
- }
191
- window.dispatchEvent( new Event( paymentFlowCompleteEventName ) );
192
- return {};
193
- };
194
-
195
- const initStripe = async () => {
196
- stripe = await loadStripe( settings.stripePublishableKey );
197
- if ( ! stripe ) {
198
- return;
199
- }
200
- const cardElementContainer: HTMLElement | null = el.querySelector( '.stripe-payment__card' );
201
- if ( ! cardElementContainer ) {
202
- return;
203
- }
204
- const elements = stripe.elements();
205
-
206
- // Handle card element.
207
- cardElement = elements.create( 'card' );
208
- cardElement.mount( cardElementContainer );
209
-
210
- // Handle payment request button (Apple/Google Pay). This has to be initialised to see if
211
- // such payments are available in the browser (canMakePayment method).
212
- paymentRequest = stripe.paymentRequest( {
213
- country: settings.countryCode,
214
- currency: settings.currency,
215
- total: utils.getPaymentRequestTotal( formElement ),
216
- // Docs: Use the requestPayerName parameter to collect the payer’s billing address for Apple Pay.
217
- requestPayerName: true,
218
- requestPayerEmail: true,
219
- } );
220
-
221
- const rendersPaymentRequestButton = await paymentRequest.canMakePayment();
222
- if ( rendersPaymentRequestButton ) {
223
- paymentRequest.on( 'source', async event => {
224
- const result = await payWithSource( event.source, paymentRequestToken, {
225
- email: event.payerEmail,
226
- full_name: event.payerName,
227
- } );
228
- // The UI messages are handled in payWithSource, this event listener only
229
- // has to notify the browser that the payment is done.
230
- event.complete( result?.error ? 'fail' : 'success' );
231
- } );
232
- paymentRequest.on( 'token', async event => {
233
- paymentRequestToken = event.token;
234
- } );
235
- // Update payment request when the form values are updated.
236
- formElement.addEventListener( 'change', () => {
237
- paymentRequest.update( {
238
- total: utils.getPaymentRequestTotal( formElement ),
239
- } );
240
- } );
241
- // Create and mount the payment request button.
242
- const prButton = elements.create( 'paymentRequestButton', {
243
- paymentRequest,
244
- style: {
245
- paymentRequestButton: {
246
- type: settings.paymentRequestType,
247
- height: '46px',
248
- },
249
- },
250
- } );
251
- const prButtonElement: HTMLButtonElement | null = el.querySelector(
252
- '.stripe-payment__request-button'
253
- );
254
- if ( ! prButtonElement ) {
255
- return;
256
- }
257
- prButton.mount( prButtonElement );
258
- prButtonElement.classList.remove( 'stripe-payment--hidden' );
259
- setTimeout( () => {
260
- prButtonElement.classList.remove( 'stripe-payment__request-button--invisible' );
261
- }, 0 );
262
- } else {
263
- displayCardUI();
264
- }
265
-
266
- el.classList.remove( 'stripe-payment--invisible' );
267
- };
268
-
269
- // Initialise Stripe once the element is visible.
270
- const observer = new IntersectionObserver( entries => {
271
- if ( entries[ 0 ].isIntersecting ) {
272
- initStripe();
273
- }
274
- } );
275
- observer.observe( el );
276
-
277
- // Card form unravelling.
278
- const submitButtonEl: HTMLButtonElement | null = el.querySelector( 'button[type="submit"]' );
279
- if ( submitButtonEl ) {
280
- submitButtonEl.onclick = e => {
281
- if ( ! isCardUIVisible ) {
282
- e.preventDefault();
283
- displayCardUI();
284
- }
285
- };
286
- }
287
-
288
- const updateFeesAmount = () => {
289
- const feesAmountEl = el.querySelector( '#stripe-fees-amount' );
290
- if ( feesAmountEl ) {
291
- const formValues = Object.fromEntries( new FormData( formElement ) );
292
- const feeAmount = utils.getFeeAmount( formElement );
293
- if ( feeAmount === 0 ) {
294
- const feesAmountContainerEl: HTMLElement | null = el.querySelector(
295
- '#stripe-fees-amount-container'
296
- );
297
- if ( feesAmountContainerEl ) {
298
- feesAmountContainerEl.style.display = 'none';
299
- }
300
- }
301
- if ( typeof formValues.donation_frequency === 'string' ) {
302
- feesAmountEl.innerHTML = `(${ settings.currencySymbol }${ feeAmount.toFixed(
303
- 2
304
- ) } ${ settings.frequencies[ formValues.donation_frequency ].toLowerCase() })`;
305
- }
306
- }
307
- };
308
-
309
- updateFeesAmount();
310
- formElement.addEventListener( 'change', updateFeesAmount );
311
-
312
- // Card payment flow – on form submission.
313
- formElement.addEventListener( 'submit', async e => {
314
- if ( ! stripe ) {
315
- return;
316
- }
317
- e.preventDefault();
318
- disableForm();
319
- utils.renderMessages(
320
- [ __( 'Processing payment…', 'newspack-blocks' ) ],
321
- messagesEl,
322
- 'info'
323
- );
324
-
325
- const formValues = utils.getDonationFormValues( formElement );
326
- const validationErrors = Object.values( utils.validateFormData( formValues, settings ) );
327
- if ( validationErrors.length > 0 ) {
328
- utils.renderMessages( validationErrors, messagesEl );
329
- enableForm();
330
- return;
331
- }
332
-
333
- const handleStripeSDKError = ( error: Stripe.StripeError ) => {
334
- if ( error.message ) {
335
- validationErrors.push( error.message );
336
- }
337
- utils.renderMessages( validationErrors, messagesEl );
338
- enableForm();
339
- };
340
-
341
- const sourceCreationResult = await stripe.createSource( cardElement, {
342
- type: 'card',
343
- owner: { name: formValues.full_name, email: formValues.email },
344
- } );
345
- if ( sourceCreationResult.error ) {
346
- handleStripeSDKError( sourceCreationResult.error );
347
- return;
348
- }
349
- await payWithSource( sourceCreationResult.source );
350
- if ( window.newspackReaderActivation?.refreshAuthentication ) {
351
- window.newspackReaderActivation.refreshAuthentication();
352
- }
353
- } );
354
- } );
355
-
356
- processStreamlinedElements();
@@ -1,306 +0,0 @@
1
- @use '../../../shared/sass/colors';
2
- @use '../../../shared/sass/mixins';
3
- @use '../../../shared/sass/variables';
4
-
5
- @keyframes loader {
6
- 0% {
7
- background-position: 0% 50%;
8
- }
9
- 50% {
10
- background-position: 100% 50%;
11
- }
12
- 100% {
13
- background-position: 0% 50%;
14
- }
15
- }
16
-
17
- .wp-block-newspack-blocks-donate {
18
- .stripe-payment {
19
- // For the initial unravelling animation.
20
- position: relative;
21
- &,
22
- &--transition,
23
- &::after {
24
- transition: all 300ms ease-out;
25
- }
26
- &::after {
27
- content: '';
28
- opacity: 0;
29
- pointer-events: none;
30
- position: absolute;
31
- top: 0;
32
- left: 0;
33
- width: 100%;
34
- height: 100%;
35
- background: linear-gradient( 318deg, #d5d5d5, #fff );
36
- background-size: 400% 400%;
37
- animation: loader 3s ease infinite;
38
- border-radius: 5px;
39
- }
40
-
41
- &__card {
42
- padding: 0.34rem 0.66rem;
43
- min-height: 32px;
44
- }
45
- input[type='text'],
46
- input[type='email'],
47
- &__card {
48
- border: 1px solid variables.$color__border;
49
- border-radius: 3px;
50
- }
51
- input[type='text'],
52
- input[type='email'],
53
- &__checkbox,
54
- button,
55
- .submit-button {
56
- font-size: 0.7em;
57
- }
58
- input[type='text'],
59
- input[type='email'],
60
- &__messages {
61
- width: 100%;
62
- }
63
- input[type='text'],
64
- input[type='email'] {
65
- border-radius: 3px;
66
- font-family: sans-serif;
67
-
68
- @include mixins.media( tablet ) {
69
- font-size: 14px;
70
- line-height: 1.2;
71
- }
72
- }
73
-
74
- &--invisible {
75
- > * {
76
- opacity: 0;
77
- }
78
- &::after {
79
- opacity: 1;
80
- }
81
- }
82
- &--hidden {
83
- display: none;
84
- }
85
-
86
- &__checkbox {
87
- align-items: center;
88
- display: inline-flex;
89
- cursor: pointer;
90
-
91
- input {
92
- height: 1em;
93
- width: 1em;
94
- margin-right: 0.5em;
95
- }
96
- }
97
-
98
- &__messages {
99
- margin-bottom: 10px;
100
- > div {
101
- border: 0 solid colors.$color__info;
102
- border-left-width: 4px;
103
- font-size: variables.$font__size-sm;
104
- margin-top: 0.76rem;
105
- padding: 0.38rem 0.76rem;
106
- &:empty {
107
- border: 0;
108
- margin: 0;
109
- padding: 0;
110
- }
111
- &.type-error {
112
- background-color: rgba( colors.$color__error, 0.075 );
113
- border-color: colors.$color__error;
114
- }
115
- &.type-success {
116
- background-color: rgba( colors.$color__success, 0.075 );
117
- border-color: colors.$color__success;
118
- margin: 1.12rem;
119
- }
120
- }
121
- }
122
-
123
- &--disabled {
124
- button,
125
- input {
126
- pointer-events: none;
127
- opacity: 0.4;
128
- }
129
- }
130
-
131
- &__element {
132
- margin-bottom: 0.4rem;
133
- }
134
-
135
- &__row {
136
- margin-bottom: 0.5rem;
137
- &--small {
138
- margin-bottom: 5px;
139
- line-height: 1.2;
140
- }
141
- &--flex {
142
- display: flex;
143
- align-items: flex-end;
144
- justify-content: space-between;
145
- flex-wrap: wrap;
146
- @include mixins.media( tablet ) {
147
- flex-wrap: nowrap;
148
- }
149
- input {
150
- margin-bottom: 0.5rem;
151
- @include mixins.media( tablet ) {
152
- margin-bottom: 0;
153
- width: 50%;
154
- + input {
155
- margin-left: 0.5rem;
156
- }
157
- }
158
- }
159
- }
160
- &--additional-fields {
161
- display: flex;
162
- flex-wrap: wrap;
163
- margin-left: -0.25rem;
164
- margin-right: -0.25rem;
165
- > input {
166
- margin-bottom: 0.5rem;
167
- margin-left: 0.25rem;
168
- margin-right: 0.25rem;
169
- }
170
- }
171
- }
172
-
173
- &__info {
174
- color: colors.$color__text-light;
175
- font-size: 0.7em;
176
- font-style: italic;
177
- padding-left: 1.5em;
178
- display: none;
179
- @include mixins.media( mobile ) {
180
- display: block;
181
- }
182
- }
183
-
184
- &__footer {
185
- align-items: flex-end;
186
- margin-bottom: 1.32rem;
187
- margin-left: -10px;
188
- margin-right: -10px;
189
- > * {
190
- padding-left: 10px;
191
- padding-right: 10px;
192
- }
193
- }
194
-
195
- &__methods {
196
- display: flex;
197
- flex-wrap: wrap;
198
- width: 100%;
199
- @include mixins.media( mobile ) {
200
- width: auto;
201
- }
202
- button,
203
- .submit-button {
204
- margin-left: 0;
205
- margin-right: 0;
206
- margin-bottom: 0;
207
- height: 46px;
208
- }
209
- > * {
210
- &:not( :last-child ) {
211
- margin-bottom: 10px;
212
- }
213
-
214
- width: 100%;
215
- @include mixins.media( mobile ) {
216
- width: auto;
217
- }
218
- }
219
- }
220
-
221
- &__request-button {
222
- min-width: 190px;
223
- @include mixins.media( mobile ) {
224
- margin-right: 1em;
225
- }
226
- &--invisible {
227
- opacity: 0;
228
- }
229
- }
230
- }
231
-
232
- &__stripe {
233
- margin: 0.38rem 0.76rem 0.76rem;
234
-
235
- @include mixins.media( tablet ) {
236
- margin-left: 1.5rem;
237
- margin-right: 1.5rem;
238
- }
239
- &--editor {
240
- input:first-child {
241
- margin-top: 0;
242
- }
243
- }
244
- }
245
- }
246
-
247
- #stripe-fees-amount {
248
- padding-left: 3px;
249
- }
250
-
251
- /* Alternate Style */
252
-
253
- .wpbnbd.is-style-alternate {
254
- .wp-block-newspack-blocks-donate__stripe {
255
- margin: 1.12rem 1.12rem 0;
256
- }
257
-
258
- .stripe-payment {
259
- &__row {
260
- margin-bottom: 0.56rem;
261
- }
262
-
263
- &__footer {
264
- margin: 0 0 1.12rem;
265
-
266
- > * {
267
- padding: 0;
268
- }
269
-
270
- button,
271
- .submit-button {
272
- border-top-left-radius: 5px;
273
- border-top-right-radius: 5px;
274
- margin: 0;
275
- width: auto;
276
- }
277
- }
278
- }
279
- }
280
-
281
- /* Minimal Style */
282
-
283
- .wpbnbd.is-style-minimal {
284
- .wp-block-newspack-blocks-donate__stripe {
285
- margin: 0;
286
- text-align: left;
287
- }
288
-
289
- .stripe-payment {
290
- &__row {
291
- margin-bottom: 0.56rem;
292
- }
293
-
294
- &__inputs {
295
- margin-bottom: 1.12rem;
296
- }
297
-
298
- &__footer {
299
- margin: 0 0 1.12rem;
300
-
301
- > * {
302
- padding: 0;
303
- }
304
- }
305
- }
306
- }
@@ -1,18 +0,0 @@
1
- import 'regenerator-runtime';
2
-
3
- import { computeFeeAmount } from './utils';
4
-
5
- describe( 'Fee computation', () => {
6
- it( 'computes fee with default values', () => {
7
- expect( computeFeeAmount( 1, 2.9, 0.3 ) ).toBe( 0.34 );
8
- expect( computeFeeAmount( 15, 2.9, 0.3 ) ).toBe( 0.76 );
9
- expect( computeFeeAmount( 100, 2.9, 0.3 ) ).toBe( 3.3 );
10
- } );
11
- it( 'computes fee with other values', () => {
12
- expect( computeFeeAmount( 15, 0, 0 ) ).toBe( 0 );
13
- expect( computeFeeAmount( 15, 2.3, 0.3 ) ).toBe( 0.66 );
14
- expect( computeFeeAmount( 15, 2.3, 0 ) ).toBe( 0.35 );
15
- expect( computeFeeAmount( 15, 50, 0 ) ).toBe( 15 );
16
- expect( computeFeeAmount( 15, 50, 10 ) ).toBe( 35 );
17
- } );
18
- } );