Cart Mechanics
This page explains how the bundle selector manages cart state. You don't need to read this to get started — it's useful when debugging unexpected swap behavior or building on top of the bundle selector.
Tagged Items and the Retain-Replace Pattern
Every cart item written by the bundle selector is tagged with the selector's selectorId. This tag is what makes safe swapping possible when multiple bundles share the same package — items are identified for replacement by tag, not by package ID.
When a bundle is applied:
- Every item currently in the cart is read
- Items tagged to this selector are marked for replacement; all others are kept
- The new bundle's items are built and tagged with this
selectorId - A single
window.next.cart.swapCart([...retained, ...newItems])call replaces the full cart
Example — switching from "Starter" to "Duo" on selector-a:
Before swap:
| Package | Qty | Tagged to | Action |
|---|---|---|---|
| 10 | 1 | selector-a | Replaced |
| 99 | 1 | — | Kept (toggle item) |
| 42 | 2 | selector-b | Kept (other selector) |
After swap:
| Package | Qty | Tagged to | |
|---|---|---|---|
| 99 | 1 | — | Kept |
| 42 | 2 | selector-b | Kept |
| 10 | 1 | selector-a | New |
| 20 | 1 | selector-a | New |
Re-Entrant Guard
While a cart write is in flight, any further click or variant change is silently dropped. This prevents overlapping cart writes from a double-click or rapid selection.
| Trigger | Behavior |
|---|---|
| Card clicked — no write in progress | Cart write starts |
| Card clicked — write already in progress | Silently ignored |
| Variant changed — no write in progress | Cart write starts |
| Variant changed — write already in progress | Silently ignored |
Failure Recovery
If a cart write fails (network error or API rejection):
| Step | What happens |
|---|---|
| 1 | Visual selection reverts to the previous card (or clears if this was the first selection) |
| 2 | The previous card's vouchers are re-applied |
| 3 | The error is logged |
A card only appears selected when its items are actually in the cart — the UI is always kept consistent with actual cart state.
Shipping Method Apply
When a bundle card has data-next-shipping-id, shipping is applied as part of the swap sequence:
| Step | What happens |
|---|---|
| 1 | swapCart writes the new bundle items to the cart |
| 2 | If the cart write succeeds and the card has a shipping ID, cartStore.setShippingMethod(id) is called |
| 3 | calculateTotals fires once (debounced) with both the new items and the selected shipping method |
If the cart write fails, shipping is not changed. If the shipping method itself fails (invalid ID, no shipping methods available), the error is logged and the cart items remain — only the shipping update is skipped.
When switching from a card with a shipping ID to a card without one, the previously set shipping method persists.
Variant Change Apply
When the visitor changes a variant on a slot in the currently selected bundle (swap mode):
| Step | What happens |
|---|---|
| 1 | The new package is resolved by matching all selected attribute values against the available packages |
| 2 | The current slot state is saved as a snapshot |
| 3 | The retain-replace pattern runs with the updated item list |
| 4 (on failure) | The slot snapshot is restored and the UI re-renders to match the previous state |