
import SubblyCartFields from "../../../src/reference/cart-widget/types/SubblyCart.mdx";
import CartModelMethods from "../../../src/reference/cart-widget/types/CartModel.mdx";
import SubblyShopFields from "../../../src/reference/cart-widget/types/SubblyShop.mdx";

<CartWidgetPage group="properties" />

<Method id="cart" signature="subblyCart.cart">

The current cart: every cart field, plus the cart methods of the SDK. It is one
live object, not a snapshot — the SDK writes the new data into the same object
after every call, so a reference you store keeps showing current data. Clone it
when you need a snapshot.

Treat it as read-only and change the cart through the widget methods. The SDK
methods on it skip the widget's own store, so the panel does not refresh and no
event fires.

The cart is ready as soon as the widget is initialized.

<Params title="Cart properties">
  <Param name="cart" type="CartModel">
    The cart.

    <Properties label="cart" collapsed>
      <SubblyCartFields />
    </Properties>
  </Param>
</Params>

<Params title="Cart methods">
  <CartModelMethods />
</Params>

<Example>

```js title="Read the cart"
const { items, total, currencyCode } = subblyCart.cart

// Amounts live on the summary items, joined on itemId
const amount = subblyCart.cart.summaryItems.find(
  (summaryItem) => summaryItem.itemId === items[0].id
).total
```

</Example>

</Method>

<Method id="shop" signature="subblyCart.shop">

Public information about the shop: branding, currencies, languages, settings,
plan limits and shipping countries. The widget loads it once while it starts.
Like the cart, it is one live object; `loadShop()` refreshes it in place.

<Params title="Shop properties">
  <Param name="shop" type="SubblyShop">
    The shop.

    <Properties label="shop" collapsed>
      <SubblyShopFields />
    </Properties>
  </Param>
</Params>

<Example>

```js title="List the currencies the shop sells in"
const codes = subblyCart.shop.currencies.map(
  (currency) => currency.abbreviation
)
```

</Example>

</Method>

<Method id="state" signature="subblyCart.state">

The currency and the language the widget runs on. Reading it builds a fresh
plain object every time, so what you get is a snapshot.

<Params title="Properties">
  <Param name="currencyCode" type="string">
    Currency of the cart, as an ISO 4217 code. It falls back to the shop's
    default currency while the cart has none.
  </Param>
  <Param name="languageCode" type="string">
    Two-letter code of the language the widget shows, such as `en`.
  </Param>
</Params>

<Example>

```js title="Read the state"
const { currencyCode, languageCode } = subblyCart.state
```

</Example>

</Method>

<Method id="sdk" signature="subblyCart.sdk">

The [Subbly.js](/reference/subbly-sdk) client the widget uses, for Storefront
API calls of your own. Sharing one client keeps the widget and your code on the
same cart, customer, language and currency.

Calls you make on the client do not go through the widget's store, so the panel
does not refresh and no widget event fires. Use the widget methods to change
the cart.

<Params title="Properties">
  <Param name="VERSION" type="string">
    Version of the SDK.
  </Param>
  <Param name="config" type="object">
    The client configuration: `apiKey`, `apiUrl` and `lang`.
  </Param>
  <Param name="setCurrency" type="(code: string) => void">
    Re-prices the products, bundles and surveys the client loads next. It does
    not change the cart; use `subblyCart.setCurrency` for that.
  </Param>
  <Param name="setLanguage" type="(code: string) => void">
    Sets the language the API answers in.
  </Param>
</Params>

<Params title="Modules">
  <Param name="addresses" type="module">
    `list`, `store`, `delete`.
  </Param>
  <Param name="auth" type="module">
    `isAuthenticated`, `checkAuthenticated`, `login`, `registered`, `register`,
    `otp`, `otpLogin`, `social`, `logout`, `getAccessToken`.
  </Param>
  <Param name="bundles" type="module">
    `list`, `load`, `loadItems`, `loadGroups`, `quote`, `setCurrency`.
  </Param>
  <Param name="cart" type="module">
    The same object as `subblyCart.cart`.
  </Param>
  <Param name="checkout" type="module">
    `purchase`.
  </Param>
  <Param name="countries" type="module">
    `list`.
  </Param>
  <Param name="customers" type="module">
    `update`, `me`, `referral`. All three need a signed-in customer.
  </Param>
  <Param name="funnels" type="module">
    `prePurchaseFetch`, `prePurchaseRefresh`, `prePurchaseAccept`,
    `prePurchaseReject`, `midPurchaseFetch`, `midPurchaseAccept`,
    `midPurchaseReject`, `postPurchaseFetch`, `postPurchaseAccept`,
    `postPurchaseReject`.
  </Param>
  <Param name="lead" type="module">
    `subscribe`.
  </Param>
  <Param name="metafield" type="module">
    `list`.
  </Param>
  <Param name="paymentIntents" type="module">
    `getPaymentIntent`, `confirm`.
  </Param>
  <Param name="pickupInfo" type="module">
    `list`, `store`, `delete`.
  </Param>
  <Param name="products" type="module">
    `list`, `load`, `loadVariant`, `loadPlan`, `setCurrency`.
  </Param>
  <Param name="shop" type="module">
    `load`. The same object as `subblyCart.shop`.
  </Param>
  <Param name="stock" type="module">
    `subscribe`.
  </Param>
  <Param name="subscriptions" type="module">
    `list`, `load`, `update`, `updatePreferences`, `updateBundle`, `loadItem`,
    `updateItem`, `updateItemBundle`, `updateItemPreferences`.
  </Param>
  <Param name="surveys" type="module">
    `load`, `setCurrency`.
  </Param>
  <Param name="wallet" type="module">
    `store`, `list`, `setup`, `setupIntent`.
  </Param>
</Params>

<Example>

```js title="Call the Storefront API"
const { data } = await subblyCart.sdk.products.list({ perPage: 100 })
```

</Example>

</Method>

<Method id="events" signature="subblyCart.events">

The event emitter of the widget. `events.type` holds the event names, and every
name equals its own value, so `events.type.CART_OPEN` is `'CART_OPEN'`. The
emitter comes from `tiny-typed-emitter`, which follows the Node
`EventEmitter` API.

<Params title="Properties">
  <Param name="type" type="object">
    The event names: `CART_READY`, `CART_UPDATED`, `CART_OPEN`, `CART_CLOSE`,
    `CART_RESET`, `EMAIL_COLLECTED`, `PURCHASE_COMPLETED`, `SIGN_IN`,
    `SIGN_UP` and `SIGN_OUT`.
  </Param>
  <Param name="on" type="(type, handler) => this">
    Adds a handler. `addListener` is an alias.
  </Param>
  <Param name="once" type="(type, handler) => this">
    Adds a handler that runs for one emission.
  </Param>
  <Param name="off" type="(type, handler) => this">
    Removes a handler. `removeListener` is an alias.
  </Param>
  <Param name="removeAllListeners" type="(type?) => this">
    Removes every handler, of one event or of all of them.
  </Param>
  <Param name="prependListener" type="(type, handler) => this">
    Adds a handler at the front of the list. `prependOnceListener` does the
    same for one emission.
  </Param>
  <Param name="eventNames" type="() => string[]">
    Lists the events that have handlers.
  </Param>
  <Param name="listenerCount" type="(type) => number">
    Counts the handlers of an event.
  </Param>
  <Param name="listeners" type="(type) => handler[]">
    Lists the handlers of an event. `rawListeners` keeps the `once` wrappers.
  </Param>
  <Param name="setMaxListeners" type="(count) => this">
    Sets how many handlers one event takes before Node warns.
    `getMaxListeners` reads it back.
  </Param>
  <Param name="emit" type="(type, ...args) => boolean">
    Internal. The widget emits its own events; do not call this.
  </Param>
</Params>

<Example>

```js title="Subscribe and unsubscribe"
const { events } = subblyCart

const onUpdate = (err, cart) => console.log(cart.items.length)

events.on(events.type.CART_UPDATED, onUpdate)
events.off(events.type.CART_UPDATED, onUpdate)
```

</Example>

</Method>
