# How Woo Components Work

> Runtime, rendering, Store API, and composition rules for Woo components.

<!-- Sources: src/Woo/Woo.php; src/Woo/StoreApiExtension.php; src/Woo/CartItemsDynamicSource.php; src/Woo/WooSelectorDynamicSource.php; src/Woo/CartItemAtomHydrator.php; client/src/services/woo/index.ts; client/src/domains/woo/bootstrap.ts; client/src/domains/woo/woo-runtime.ts; client/src/domains/woo/cart-store.ts; client/src/domains/woo/checkout-store.ts; tests/e2e/components/woo/behavior.spec.ts -->

# How Woo Components Work

Woo components have two cooperating layers:

1. PHP component markup renders the authored Etch block tree, data attributes, slots, preview branches, and server-known dynamic data.
2. The Woo runtime binds those data attributes, reads Store API state, mutates Woo through Store API endpoints, and updates the same live DOM.

## Boot Flow

`Woo::maybe_boot()` registers the Woo service when WooCommerce is available. The service is triggered by any Woo component key listed in `Woo.php`, and it localizes:

| Localized key | Runtime use |
| --- | --- |
| `storeApiBase` | Base URL for `/wc/store/v1` requests. |
| `nonce` | Store API nonce header. |
| `checkoutUrl` | Fallback redirect target for `BuyNowButton`. |
| `isAvailable` and `diagnostics` | Runtime availability state. |
| `paymentMethods` | Simple enabled payment methods for `PaymentMethodSelector`. |
| `checkoutFields` | Woo checkout field rules, countries, states, locale overrides, and defaults. |

The browser service creates one `WooCartStore` and one `WooCheckoutStore`. Cart components subscribe to the cart store. Checkout components subscribe to the checkout store only when checkout UI is present.

## SSR and Runtime Updates

The Woo line follows this rule:

| Surface | First visible state |
| --- | --- |
| Product purchase forms | Authored server markup with product props and optional variation data. |
| Cart items and totals | Server dynamic sources when the block tree references cart data, then runtime refresh. |
| Shipping and payment selectors | Server rows when dynamic sources are available, then runtime normalization and selection binding. |
| Checkout fields | Server-authored fields, then runtime applies Woo field schema and country/state logic. |
| Notices | Runtime feedback regions. |

Server markup is not thrown away. The runtime updates text, input values, row state, and cloned rows in place. Templates remain inert blueprints for rows that need to be cloned after a Store API response.

## Store API Requests

The cart store serializes cart mutations through `RequestQueue`, then refreshes subscribers:

| Action | Store API endpoint |
| --- | --- |
| Add item | `POST /cart/add-item` |
| Update quantity | `POST /cart/update-item` |
| Remove item | `POST /cart/remove-item` |
| Apply coupon | `POST /cart/apply-coupon` |
| Remove coupon | `DELETE /cart/coupons?code=...` |
| Select shipping | `POST /cart/select-shipping-rate` |

The checkout store also serializes requests:

| Action | Store API endpoint |
| --- | --- |
| Load checkout | `GET /checkout` |
| Persist fields | `PUT /checkout?__experimental_calc_totals=true` |
| Place order | `POST /checkout` |

## Component Binding Order

`WooRuntime.boot()` binds display components, action components, product purchase controls, checkout components, and selectors. This order matters because some render callbacks re-bind child actions:

| Parent render | Follow-up binding |
| --- | --- |
| `CartItems` row render | Binds item quantity inputs and remove buttons in the rendered rows. |
| `CouponAppliedList` row render | Binds coupon remove buttons in the rendered rows. |
| `OrderSummary` render | Binds read-only summary rows and any row-level actions that are present. |

## Composition Rules

| Component | Needs |
| --- | --- |
| `AddToCartButton` with `trigger: standalone` | A direct `product_id` prop or a scoped product quantity input. It is ignored when placed inside `AddToCartForm`; the form owns submission there. |
| `AddToCartButton` with `trigger: form_submit` | A parent `AddToCartForm`; it renders as the form submit control. |
| `BuyNowButton` | A parent `AddToCartForm`; it serializes the form then redirects. |
| `AttributeSelector` | A parent purchase form and a bound `props.target.attribute` object. |
| Cart item atoms | A `CartItems` row or `OrderSummary` product row. |
| `CouponRemoveButton` | A `CouponAppliedList` row with a coupon code. |
| `PlaceOrderButton` | A parent checkout form scope. |

## Events

The runtime dispatches:

| Event | Fired from |
| --- | --- |
| `ome-woo:cart-loaded` | Cart count, totals, cart items, cart notices, or body after cart boot. |
| `ome-woo:checkout-loaded` | Checkout provider, checkout form, checkout notices, or body after checkout boot. |
| `ome-woo:checkout-started` | Checkout form before submit. |
| `ome-woo:checkout-complete` | Checkout form after Store API checkout success. |
| `ome-woo:checkout-error` | Checkout form after local validation or Store API failure. |

Product add events are dispatched by the add-item helpers after successful or failed add-to-cart actions.
