# Shipping Selector

> ShippingMethodSelector modes, package-aware rate values, and cart total updates.

<!-- Sources: src/Components/Woo/ShippingMethodSelector/ShippingMethodSelector.php; src/Woo/WooSelectorDynamicSource.php; client/src/domains/woo/components/shipping-method-selector.ts; client/src/domains/woo/components/ui-choice-mode.ts; client/src/domains/woo/cart-store.ts; src/Testing/E2E/Woo/WooScenarioProvider.php; tests/e2e/components/woo/behavior.spec.ts; tests/e2e/components/woo/lifecycle.spec.ts -->

# Shipping Selector

`ShippingMethodSelector` renders Woo shipping rates and lets the customer select one.

## Component

| Component key | Role |
| --- | --- |
| `OmeWooShippingMethodSelector` | Reads `shippingRates`, binds UIChoice, calls Store API to select a package rate, and refreshes totals. |

## Props

| Prop | Meaning |
| --- | --- |
| `ui.mode` | `radio`, `button-radio`, or `select`. Default is radio. |
| `ui.aria_label` | Accessible selector label. |
| `ui.default_label` | Select trigger text before selected rate is resolved. |
| `content.show_price` | Whether rate rows include formatted price text. |
| `content.price_separator` | Text between rate name and price. |

## Rate Values

Shipping selection is package-aware:

| Attribute | Value |
| --- | --- |
| `data-ome-value` | `{package_id}:{rate_id}` |
| Hidden radio `name` | `shipping_method_{package_id}` |
| Hidden radio `value` | Raw Woo `rate_id` |
| Runtime request | `select_shipping_rate(package_id, rate_id)` |

This preserves Woo's package-specific shipping behavior.

## Modes

| Mode | Behavior |
| --- | --- |
| `radio` | In-tree radiogroup with indicators. |
| `button-radio` | In-tree radiogroup without indicators. |
| `select` | Trigger plus hidden listbox content. Runtime positions list content through shared UIChoice helpers. |

If the cart does not need shipping, the selector state becomes `hidden` and no rate rows render.

## Runtime Behavior

The runtime:

1. Reads shipping packages and rates from the cart response.
2. Deduplicates package/rate keys.
3. Normalizes server-rendered rate rows when they exist.
4. Clones template rows when Store API data changes.
5. Updates selected input and UIChoice state.
6. Calls Store API on rate change and refreshes cart totals.

## Scenario Coverage

| Scenario | Covered behavior |
| --- | --- |
| `shipping_selector` | Selecting free shipping updates selected rate, cart totals, and order summary totals. |
| `shipping_selector_button_radio` | Button-radio mode uses radiogroup semantics and updates totals. |
| `shipping_selector_select` | Select mode uses trigger/listbox structure and updates trigger label. |
| `shipping_selector_select_content_props` | `show_price: false` removes price display from row and trigger. |
| `no_shipping_selector` | No-shipping cart hides the selector. |
| Lifecycle pricing test | Native Woo pricing hooks still affect rendered totals around shipping selection. |
