Forced inner blocks
Unwan registers two blocks:
Both are registered as forced inner blocks (
inserter: false, locked against removal or moving) of WooCommerce’s own address blocks, so they render automatically, in the right place, on any checkout page built from Checkout Blocks — store owners don’t need to manually add anything in the block editor, and can’t accidentally delete the selector while editing the page.
Store API extension data
Unwan registers a writable extension namespace,unwan, on the Checkout endpoint via woocommerce_store_api_register_endpoint_data(), with two fields:
"new". This is the same Store API mechanism any other Blocks-aware extension uses to add data to the checkout request — Unwan isn’t reading or writing anything outside of WooCommerce’s supported extension surface.
Keeping order-specific choices from leaking into account defaults
This is the trickiest part of the integration, and worth understanding if you’re debugging address behavior: WooCommerce’s Store API updates the customer’s billing/shipping profile fields as a normal side effect of processing checkout, even when a shopper only meant to use an address for this order. Left alone, that would silently overwrite the account default — exactly what Checkout Overview promises won’t happen. Unwan works around this without fighting WooCommerce’s own checkout flow:1
Capture, before the overwrite
On every signed-in checkout request (
woocommerce_store_api_checkout_update_customer_from_request), Unwan takes a copy of both stored profile defaults, whatever the request contains. WooCommerce also rewrites the shipping default with the billing address for carts that need no shipping, and express payment buttons write it without Unwan’s picker involved, so both are always captured.2
Let WooCommerce finish
WooCommerce is allowed to write the submitted address to its normal place — it has to, so the draft order can copy the correct address for this order before anything is restored.
3
Restore the account default afterward
Once the full Store API request has completed — including WooCommerce’s own final customer sync — Unwan writes back only the values that changed, via a
rest_request_after_callbacks filter, with a shutdown-time fallback in case the primary hook doesn’t fire (payment failures, validation errors, etc.). If nothing changed, nothing is saved: saving the customer would make WooCommerce discard its session copy and price shipping and tax for the default address on the next request.4
Save the new address afterward, if applicable
If the shopper explicitly chose “Enter a new address,” the finalized address is read back off the processed order (not the raw request) and added to the address book only once it’s known to be complete and valid.
Collapsing rows without hiding what’s needed
When a saved address is selected, Unwan collapses each standard address row individually, never the whole form, so fields other plugins place inside it stay visible. The list of collapsed rows lives on Unwan’s own picker element (data-unwan-collapse) and the stylesheet hides the matching rows with :has(). WooCommerce re-renders its own form wrapper (for example while an order is processing), so state kept there would be wiped and every field would reappear after a failed payment.
A row stays visible when WooCommerce’s validation store reports an error for it — a required field the saved address lacks, or a value that fails the store’s rules — and once shown, it stays shown until the customer picks another address. Browsers without :has() support simply show every field.
Compatibility
Unwan declares compatibility with bothcustom_order_tables (HPOS) and cart_checkout_blocks via FeaturesUtil::declare_compatibility() before WooCommerce initializes its feature system, and registers its block scripts through the Checkout integration registry rather than assuming WooCommerce Blocks has already finished bootstrapping — it checks did_action( 'woocommerce_blocks_loaded' ) and registers immediately if Blocks already loaded, or hooks the action if not.