Commit 6249fee3fdc for woocommerce

commit 6249fee3fdcaccdd56dbd613d33915831f8d7c46
Author: ragulka <illimar.tambek@gmail.com>
Date:   Wed Oct 7 23:34:19 2026 +0300

    Introduce additional cart events (#45952)

    * Add mini cart open/close events

    * Add cart render event

    * Add changefile(s) from automation for the following project(s): woocommerce-blocks

    * Use dispatchCheckoutEvent for view/open/close cart hooks

    * Add new events to docs

    * Update plugins/woocommerce-blocks/assets/js/blocks/cart/block.js

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Fix Mini-Cart event dispatch in script modules

    * Update changelog for cart events

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Update plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts

    Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

    * update changelog

    * Dispatch Mini-Cart events only on state changes

    ---------

    Co-authored-by: github-actions <github-actions@github.com>
    Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>
    Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
    Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>
    Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

diff --git a/plugins/woocommerce/changelog/45952-additional-cart-events b/plugins/woocommerce/changelog/45952-additional-cart-events
new file mode 100644
index 00000000000..8571cfa3625
--- /dev/null
+++ b/plugins/woocommerce/changelog/45952-additional-cart-events
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Add additional frontend events to Cart and Mini Cart blocks.
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/block.js b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/block.js
index 2f42502cf37..5fb0c134dd2 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/cart/block.js
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/cart/block.js
@@ -2,6 +2,7 @@
  * External dependencies
  */
 import { __ } from '@wordpress/i18n';
+import { useStoreEvents } from '@woocommerce/base-context/hooks';
 import { useEffect } from '@wordpress/element';
 import { CURRENT_USER_IS_ADMIN } from '@woocommerce/settings';
 import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
@@ -26,6 +27,14 @@ import './style.scss';
 const Cart = ( { children, attributes = {} } ) => {
 	const { hasDarkControls } = attributes;

+	const { dispatchCheckoutEvent } = useStoreEvents();
+
+	// Ignore changes to dispatchCheckoutEvent callback so this is ran on first mount only.
+	useEffect( () => {
+		dispatchCheckoutEvent( 'cart-render' );
+		// eslint-disable-next-line react-hooks/exhaustive-deps
+	}, [] );
+
 	return (
 		<CartBlockContext.Provider
 			value={ {
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
index 490e0aa2146..820b6ba3d3d 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/mini-cart/frontend.ts
@@ -173,6 +173,20 @@ const { state: woocommerceState, actions } = store< WooCommerce >(
 	{ lock: universalLock }
 );

+const dispatchCheckoutEvent = ( eventName: string ) => {
+	try {
+		window.wp.hooks.doAction(
+			`experimental__woocommerce_blocks-checkout-${ eventName }`,
+			{ storeCart: woocommerceState.cart }
+		);
+	} catch ( e ) {
+		// eslint-disable-next-line no-console
+		console.error( e );
+	}
+};
+
+let previousIsOpen: boolean | undefined;
+
 const { state: miniCartState, actions: miniCartActions } = store< MiniCart >(
 	'woocommerce/mini-cart',
 	{},
@@ -382,12 +396,20 @@ store< MiniCart >(
 							document.documentElement.clientWidth +
 							'px',
 					} );
+					if ( previousIsOpen === false ) {
+						dispatchCheckoutEvent( 'mini-cart-open' );
+					}
 				} else {
 					Object.assign( document.body.style, {
 						overflow: '',
 						paddingRight: 0,
 					} );
+					if ( previousIsOpen === true ) {
+						dispatchCheckoutEvent( 'mini-cart-close' );
+					}
 				}
+
+				previousIsOpen = state.isOpen;
 			},

 			focusFirstElement() {
diff --git a/plugins/woocommerce/client/blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md b/plugins/woocommerce/client/blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md
index 70fec879e22..3dbb481e3f3 100644
--- a/plugins/woocommerce/client/blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md
+++ b/plugins/woocommerce/client/blocks/docs/internal-developers/blocks/feature-flags-and-experimental-interfaces.md
@@ -147,6 +147,9 @@ Checkout events use the `experimental__woocommerce_blocks-checkout-` prefix. `di
 | Action | Additional parameters |
 | --- | --- |
 | `experimental__woocommerce_blocks-checkout-submit` | None |
+| `experimental__woocommerce_blocks-checkout-cart-render` | None |
+| `experimental__woocommerce_blocks-checkout-mini-cart-open` | None |
+| `experimental__woocommerce_blocks-checkout-mini-cart-close` | None |
 | `experimental__woocommerce_blocks-checkout-set-selected-shipping-rate` | `shippingRateId` |
 | `experimental__woocommerce_blocks-checkout-set-active-payment-method` | `paymentMethodSlug` |
 | `experimental__woocommerce_blocks-checkout-render-checkout-form` | None |
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
index 540194291d8..89bd72be34d 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/MiniCart.php
@@ -300,6 +300,8 @@ class MiniCart extends AbstractBlock {

 		// The view script module is deliberately not declared in block.json, so it is only
 		// enqueued here and never on the cart and checkout pages handled above.
+		// Classic WordPress scripts cannot be imported into script modules, so expose wp-hooks through its global.
+		wp_enqueue_script( 'wp-hooks' );
 		wp_enqueue_script_module( $this->get_full_block_name() );

 		// Enqueue all integration scripts registered for this block.