diff --git a/modules/ppcp-applepay/resources/css/styles.scss b/modules/ppcp-applepay/resources/css/styles.scss index 215a7888e..858094433 100644 --- a/modules/ppcp-applepay/resources/css/styles.scss +++ b/modules/ppcp-applepay/resources/css/styles.scss @@ -1,58 +1,44 @@ -#applepay-container, .ppcp-button-applepay { +.ppcp-button-applepay { + // Should replicate apm-button.scss sizes. --apple-pay-button-height: 45px; - --apple-pay-button-min-height: 40px; + --apple-pay-button-min-height: 35px; --apple-pay-button-width: 100%; --apple-pay-button-max-width: 750px; --apple-pay-button-border-radius: 4px; --apple-pay-button-overflow: hidden; - margin:7px 0; + + .ppcp-width-min & { + --apple-pay-button-height: 35px; + } + .ppcp-width-300 & { + --apple-pay-button-height: 45px; + } + .ppcp-width-500 & { + --apple-pay-button-height: 55px; + } + &.ppcp-button-pill { --apple-pay-button-border-radius: 50px; } &.ppcp-button-minicart { --apple-pay-button-display: block; - --apple-pay-button-height: 40px; - } -} - -.woocommerce-checkout { - #applepay-container, .ppcp-button-applepay { - margin-top: 0; - --apple-pay-button-border-radius: 4px; - --apple-pay-button-height: 45px; - &.ppcp-button-pill { - --apple-pay-button-border-radius: 50px; - } } } -.ppcp-has-applepay-block { - - .wp-block-woocommerce-checkout { - #applepay-container, .ppcp-button-applepay { - margin: 0; - --apple-pay-button-margin: 0; - --apple-pay-button-height: 48px; - &.ppcp-button-pill { - --apple-pay-button-border-radius: 50px; - } - } - } +.wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { + .ppcp-button-applepay { + --apple-pay-button-margin: 0; - .wp-block-woocommerce-cart { - #applepay-container, .ppcp-button-applepay { - margin: 0; - --apple-pay-button-margin: 0; - --apple-pay-button-height: 48px; + apple-pay-button { + min-width: 0; + width: 100%; + --apple-pay-button-width-default: 100%; } } } .wp-admin { - .ppcp-button-applepay { - pointer-events: none; - } &.ppcp-non-ios-device { .ppcp-button-applepay { apple-pay-button { diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index c6e05cf35..babca29f3 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -5,10 +5,13 @@ import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/Butto import FormValidator from "../../../ppcp-button/resources/js/modules/Helper/FormValidator"; import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler'; import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; +import {apmButtonsInit} from "../../../ppcp-button/resources/js/modules/Helper/ApmButtons"; class ApplepayButton { constructor(context, externalHandler, buttonConfig, ppcpConfig) { + apmButtonsInit(); + this.isInitialized = false; this.context = context; @@ -60,7 +63,7 @@ class ApplepayButton { this.initEventHandlers(); this.isInitialized = true; this.applePayConfig = config; - const isEligible = this.applePayConfig.isEligible; + const isEligible = (this.applePayConfig.isEligible && window.ApplePaySession) || this.buttonConfig.is_admin; if (isEligible) { this.fetchTransactionInfo().then(() => { @@ -84,6 +87,10 @@ class ApplepayButton { }); } }); + } else { + jQuery('#' + this.buttonConfig.button.wrapper).hide(); + jQuery('#' + this.buttonConfig.button.mini_cart_wrapper).hide(); + jQuery('#express-payment-method-ppcp-applepay').hide(); } } @@ -179,13 +186,13 @@ class ApplepayButton { appleContainer.innerHTML = ``; } - jQuery('#' + wrapper).addClass('ppcp-button-' + ppcpStyle.shape); + const $wrapper = jQuery('#' + wrapper); + $wrapper.addClass('ppcp-button-' + ppcpStyle.shape); if (ppcpStyle.height) { - jQuery('#' + wrapper).css('--apple-pay-button-height', `${ppcpStyle.height}px`) + $wrapper.css('--apple-pay-button-height', `${ppcpStyle.height}px`) + $wrapper.css('height', `${ppcpStyle.height}px`) } - - jQuery(wrapper).append(appleContainer); } //------------------------ diff --git a/modules/ppcp-applepay/resources/js/boot-admin.js b/modules/ppcp-applepay/resources/js/boot-admin.js index 30032f56b..f584ce41b 100644 --- a/modules/ppcp-applepay/resources/js/boot-admin.js +++ b/modules/ppcp-applepay/resources/js/boot-admin.js @@ -65,7 +65,7 @@ import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/Wi buttonConfig.button.wrapper = selector.replace('#', ''); applyConfigOptions(buttonConfig); - const wrapperElement = `
`; + const wrapperElement = `
`; if (!jQuery(selector).length) { jQuery(ppcpConfig.button.wrapper).after(wrapperElement); diff --git a/modules/ppcp-applepay/resources/js/boot-block.js b/modules/ppcp-applepay/resources/js/boot-block.js index 2e6b99124..b8f905b6d 100644 --- a/modules/ppcp-applepay/resources/js/boot-block.js +++ b/modules/ppcp-applepay/resources/js/boot-block.js @@ -23,12 +23,6 @@ const ApplePayComponent = () => { const manager = new ApplepayManager(buttonConfig, ppcpConfig); manager.init(); }; - useEffect(() => { - const bodyClass = 'ppcp-has-applepay-block'; - if (!document.body.classList.contains(bodyClass)) { - document.body.classList.add(bodyClass); - } - }, []); useEffect(() => { // Load ApplePay SDK @@ -50,7 +44,7 @@ const ApplePayComponent = () => { }, [paypalLoaded, applePayLoaded]); return ( -
+
); } diff --git a/modules/ppcp-applepay/src/Assets/ApplePayButton.php b/modules/ppcp-applepay/src/Assets/ApplePayButton.php index c34a9fc6c..f8ce67bd6 100644 --- a/modules/ppcp-applepay/src/Assets/ApplePayButton.php +++ b/modules/ppcp-applepay/src/Assets/ApplePayButton.php @@ -968,7 +968,7 @@ function () { add_action( $render_placeholder, function () { - echo ''; + echo ''; }, 21 ); @@ -981,7 +981,7 @@ function () { */ protected function applepay_button(): void { ?> -
+
$this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => false, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), @@ -204,6 +205,7 @@ protected function data_for_cart_page( return array( 'sdk_url' => $this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => false, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), @@ -252,6 +254,7 @@ protected function data_for_admin_page( return array( 'sdk_url' => $this->sdk_url, 'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false, + 'is_admin' => true, 'preferences' => array( 'checkout_data_mode' => $checkout_data_mode, ), diff --git a/modules/ppcp-blocks/resources/css/gateway.scss b/modules/ppcp-blocks/resources/css/gateway.scss new file mode 100644 index 000000000..1268f6379 --- /dev/null +++ b/modules/ppcp-blocks/resources/css/gateway.scss @@ -0,0 +1,15 @@ +@use "../../../ppcp-button/resources/css/mixins/apm-button" as apm-button; + +li[id^="express-payment-method-ppcp-"] { + line-height: 0; + + // Set min-width to 0 as the buttons need to fit in a tight grid. + .paypal-buttons { + min-width: 0 !important; + } +} + +.ppcp-button-apm { + @include apm-button.button; +} + diff --git a/modules/ppcp-blocks/src/BlocksModule.php b/modules/ppcp-blocks/src/BlocksModule.php index 1766806b7..9b00d61bc 100644 --- a/modules/ppcp-blocks/src/BlocksModule.php +++ b/modules/ppcp-blocks/src/BlocksModule.php @@ -88,6 +88,28 @@ static function () use ( $c ) { $endpoint->handle_request(); } ); + + // Enqueue frontend scripts. + add_action( + 'wp_enqueue_scripts', + static function () use ( $c ) { + if ( ! has_block( 'woocommerce/checkout' ) && ! has_block( 'woocommerce/cart' ) ) { + return; + } + + $module_url = $c->get( 'blocks.url' ); + $asset_version = $c->get( 'ppcp.asset-version' ); + + wp_register_style( + 'wc-ppcp-blocks', + untrailingslashit( $module_url ) . '/assets/css/gateway.css', + array(), + $asset_version + ); + wp_enqueue_style( 'wc-ppcp-blocks' ); + } + ); + } /** diff --git a/modules/ppcp-blocks/webpack.config.js b/modules/ppcp-blocks/webpack.config.js index 4695769ed..bdf508fba 100644 --- a/modules/ppcp-blocks/webpack.config.js +++ b/modules/ppcp-blocks/webpack.config.js @@ -9,7 +9,8 @@ module.exports = { target: 'web', plugins: [ new DependencyExtractionWebpackPlugin() ], entry: { - 'checkout-block': path.resolve('./resources/js/checkout-block.js') + 'checkout-block': path.resolve('./resources/js/checkout-block.js'), + "gateway": path.resolve('./resources/css/gateway.scss') }, output: { path: path.resolve(__dirname, 'assets/'), diff --git a/modules/ppcp-button/resources/css/gateway.scss b/modules/ppcp-button/resources/css/gateway.scss index 42b216e92..40326c921 100644 --- a/modules/ppcp-button/resources/css/gateway.scss +++ b/modules/ppcp-button/resources/css/gateway.scss @@ -1,3 +1,5 @@ +@use "mixins/apm-button" as apm-button; + #place_order.ppcp-hidden { display: none !important; } @@ -15,3 +17,17 @@ .ppc-button-wrapper #ppcp-messages:first-child { padding-top: 10px; } + +// Prevents spacing after button group. +#ppc-button-ppcp-gateway { + line-height: 0; +} + +#ppc-button-minicart { + line-height: 0; + display: block; +} + +.ppcp-button-apm { + @include apm-button.button; +} diff --git a/modules/ppcp-button/resources/css/mixins/apm-button.scss b/modules/ppcp-button/resources/css/mixins/apm-button.scss new file mode 100644 index 000000000..5c9e73921 --- /dev/null +++ b/modules/ppcp-button/resources/css/mixins/apm-button.scss @@ -0,0 +1,42 @@ + +@mixin button { + overflow: hidden; + min-width: 0; + max-width: 750px; + line-height: 0; + border-radius: 4px; + + // Defaults + height: 45px; + margin-top: 14px; + + &.ppcp-button-pill { + border-radius: 50px; + } + + &.ppcp-button-minicart { + display: block; + } + + .ppcp-width-min & { + height: 35px; + } + + .ppcp-width-300 & { + height: 45px; + } + + .ppcp-width-500 & { + height: 55px; + } + + // No margin on block layout. + .wp-block-woocommerce-checkout &, .wp-block-woocommerce-cart & { + margin: 0; + min-width: 0; + } + + .wp-admin & { + pointer-events: none; + } +} diff --git a/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js b/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js new file mode 100644 index 000000000..97242f615 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/Helper/ApmButtons.js @@ -0,0 +1,94 @@ + +export const apmButtonsInit = (selector = '.ppcp-button-apm') => { + if (window.ppcpApmButtons) { + return; + } + window.ppcpApmButtons = new ApmButtons(selector); +} + +export class ApmButtons { + + constructor(selector) { + this.selector = selector; + this.containers = []; + + // Reloads button containers. + this.reloadContainers(); + + // Refresh button layout. + jQuery(window).resize(() => { + this.refresh(); + }).resize(); + + // Observes for new buttons. + (new MutationObserver(this.observeElementsCallback.bind(this))) + .observe(document.body, { childList: true, subtree: true }); + } + + observeElementsCallback(mutationsList, observer) { + const observeSelector = this.selector + ', .widget_shopping_cart, .widget_shopping_cart_content'; + + let shouldReload = false; + for (let mutation of mutationsList) { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach(node => { + if (node.matches && node.matches(observeSelector)) { + shouldReload = true; + } + }); + } + } + + if (shouldReload) { + this.reloadContainers(); + this.refresh(); + } + }; + + reloadContainers() { + jQuery(this.selector).each((index, el) => { + const parent = jQuery(el).parent(); + if (!this.containers.some($el => $el.is(parent))) { + this.containers.push(parent); + } + }); + console.log('this.containers', this.containers); + } + + refresh() { + for (const container of this.containers) { + const $container = jQuery(container); + + // Check width and add classes + const width = $container.width(); + + $container.removeClass('ppcp-width-500 ppcp-width-300 ppcp-width-min'); + + if (width >= 500) { + $container.addClass('ppcp-width-500'); + } else if (width >= 300) { + $container.addClass('ppcp-width-300'); + } else { + $container.addClass('ppcp-width-min'); + } + + // Check first apm button + const $firstElement = $container.children(':visible').first(); + + // Assign margins to buttons + $container.find(this.selector).each((index, el) => { + const $el = jQuery(el); + + if ($el.is($firstElement)) { + $el.css('margin-top', `0px`); + return true; + } + + const height = $el.height(); + $el.css('margin-top', `${Math.round(height * 0.3)}px`); + }); + + } + } + +} diff --git a/modules/ppcp-googlepay/resources/css/styles.scss b/modules/ppcp-googlepay/resources/css/styles.scss index 82755efd8..0747a2a91 100644 --- a/modules/ppcp-googlepay/resources/css/styles.scss +++ b/modules/ppcp-googlepay/resources/css/styles.scss @@ -1,45 +1,9 @@ .ppcp-button-googlepay { - margin: 7px 0; - overflow: hidden; min-height: 40px; - height: 45px; - - &.ppcp-button-pill { - border-radius: 50px; - } - - &.ppcp-button-minicart { - display: block; - height: 40px; - } -} - -.woocommerce-checkout { - .ppcp-button-googlepay { - margin-top: 0; - } -} - -.ppcp-has-googlepay-block { - - .wp-block-woocommerce-checkout { - .ppcp-button-googlepay { - margin: 0; - height: 48px; - } - } - - .wp-block-woocommerce-cart { - .ppcp-button-googlepay { - margin: 0; - height: 48px; - } - } - } -.wp-admin { - .ppcp-button-googlepay { - pointer-events: none; +.wp-block-woocommerce-checkout, .wp-block-woocommerce-cart { + .gpay-button { + min-width: 0 !important; } } diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 9197cd5a5..5200743a0 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -3,10 +3,13 @@ import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hidin import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler'; import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder"; import UpdatePaymentData from "./Helper/UpdatePaymentData"; +import {apmButtonsInit} from "../../../ppcp-button/resources/js/modules/Helper/ApmButtons"; class GooglepayButton { constructor(context, externalHandler, buttonConfig, ppcpConfig) { + apmButtonsInit(); + this.isInitialized = false; this.context = context; diff --git a/modules/ppcp-googlepay/resources/js/boot-admin.js b/modules/ppcp-googlepay/resources/js/boot-admin.js index 577733b6b..3b971986f 100644 --- a/modules/ppcp-googlepay/resources/js/boot-admin.js +++ b/modules/ppcp-googlepay/resources/js/boot-admin.js @@ -67,7 +67,7 @@ import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/Wi buttonConfig.button.wrapper = selector; applyConfigOptions(buttonConfig); - const wrapperElement = `
`; + const wrapperElement = `
`; if (!jQuery(selector).length) { jQuery(ppcpConfig.button.wrapper).after(wrapperElement); diff --git a/modules/ppcp-googlepay/resources/js/boot-block.js b/modules/ppcp-googlepay/resources/js/boot-block.js index 69baf2d5e..bc117357a 100644 --- a/modules/ppcp-googlepay/resources/js/boot-block.js +++ b/modules/ppcp-googlepay/resources/js/boot-block.js @@ -24,13 +24,6 @@ const GooglePayComponent = () => { manager.init(); }; - useEffect(() => { - const bodyClass = 'ppcp-has-googlepay-block'; - if (!document.body.classList.contains(bodyClass)) { - document.body.classList.add(bodyClass); - } - }, []); - useEffect(() => { // Load GooglePay SDK loadCustomScript({ url: buttonConfig.sdk_url }).then(() => { @@ -51,7 +44,7 @@ const GooglePayComponent = () => { }, [paypalLoaded, googlePayLoaded]); return ( -
+
); } diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index df482c73f..15f16e381 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -311,7 +311,7 @@ function () { add_action( $render_placeholder, function () { - echo ''; + echo ''; }, 21 ); @@ -325,7 +325,7 @@ function () { */ private function googlepay_button(): void { ?> -
+
{ const rules = jQuery(el).data('ppcpDisplay'); - - // console.log('rules', rules); - for (const rule of rules) { displayManager.addRule(rule); }