# Types: VariantOptionProps to BundleSelectorProps (/themes/sdk/reference/product/types-4)

```ts
import { … } from '@poltura/theme-sdk/product';
```

## `VariantOptionProps` [#variantoptionprops]

Props of [`VariantOption`](/themes/sdk/reference/product/parts-1#variantoption).

<TypeTable type={{"option":{"description":"The option.","type":"VariantPickerOption","required":true},"display":{"description":"How to show the values; the option's own display by default.","type":"ProductOptionDisplay","required":false},"showTitle":{"description":"Shows the option's name; on by default, and kept for screen readers when off.","type":"boolean","required":false},"children":{"description":"The option's values, as {@link VariantOptionValue} parts.","type":"ReactNode","required":true},"titleSlot":{"description":"Content aligned to the end of the option's title row, such as a size guide link.","type":"ReactNode","required":false},"classes":{"description":"Classes added to the pieces; `value` is applied by {@link VariantPicker}, not here.","type":"VariantPickerClasses","required":false},"className":{"description":"Classes added to the option.","type":"string","required":false}}} />

## `VariantOptionValueProps` [#variantoptionvalueprops]

Props of [`VariantOptionValue`](/themes/sdk/reference/product/parts-1#variantoptionvalue).

<TypeTable type={{"value":{"description":"The value.","type":"VariantPickerValue","required":true},"onSelect":{"description":"Chooses the value.","type":"() => void","required":true},"className":{"description":"Classes added to the value.","type":"string","required":false}}} />

## `VariantSwatchProps` [#variantswatchprops]

Props of [`VariantSwatch`](/themes/sdk/reference/product/parts-1#variantswatch).

<TypeTable type={{"swatch":{"description":"The swatch to draw.","type":"Swatch","required":true},"className":{"description":"Classes added to the swatch.","type":"string","required":false}}} />

## `ProductGalleryState` [#productgallerystate]

The image viewer of a product page: its images, the one shown and the zoomed view.

<TypeTable type={{"images":{"description":"The product's images, in order.","type":"readonly MediaImageRef[]","required":true},"active":{"description":"The index of the image shown.","type":"number","required":true},"select":{"description":"Shows the image at an index.","type":"(index: number) => void","required":true},"next":{"description":"Shows the next image, from the last back to the first.","type":"() => void","required":true},"previous":{"description":"Shows the previous image, from the first on to the last.","type":"() => void","required":true},"zoom":{"description":"The full-screen view of the shown image.","type":"{ readonly open: boolean; show(): void; close(): void; }","required":true}}} />

## `QuantityStepperProps` [#quantitystepperprops]

Props of [`QuantityStepper`](/themes/sdk/reference/product/parts-1#quantitystepper).

<TypeTable type={{"value":{"description":"The quantity.","type":"number","required":true},"min":{"description":"The fewest that may be ordered, or null for one.","type":"number | null","required":false},"max":{"description":"The most that may be ordered, or null for no limit.","type":"number | null","required":false},"step":{"description":"The pack size quantities move in, or null for one.","type":"number | null","required":false},"inCart":{"description":"How many the cart already holds, which the limits count.","type":"number","required":false},"onChange":{"description":"Receives the new quantity, already within the limits.","type":"(next: number) => void","required":true},"className":{"description":"Classes added to the stepper.","type":"string","required":false}}} />

## `AddToCartButtonProps` [#addtocartbuttonprops]

Props of [`AddToCartButton`](/themes/sdk/reference/product/parts-1#addtocartbutton).

<TypeTable type={{"label":{"description":"The button text, such as \"Add to cart\" or \"Pre-order\".","type":"string","required":true},"onAdd":{"description":"Adds the item to the cart.","type":"() => void","required":true},"disabled":{"description":"Whether the item cannot be added now.","type":"boolean","required":false},"busy":{"description":"Whether the item is being added.","type":"boolean","required":false},"error":{"description":"Why the last add failed, shown under the button, or null.","type":"string | null","required":false},"fullWidth":{"description":"Stretches the button over its row.","type":"boolean","required":false},"className":{"description":"Classes added to the button.","type":"string","required":false}}} />

## `WalletButtonsProps` [#walletbuttonsprops]

Props of [`WalletButtons`](/themes/sdk/reference/product/parts-1#walletbuttons).

<TypeTable type={{"className":{"description":"Classes added to the wallet row.","type":"string","required":false}}} />

## `WholesaleBreak` [#wholesalebreak]

One quantity break of a wholesale price list.

<TypeTable type={{"minQuantity":{"description":"The quantity the break starts at.","type":"number","required":true},"unitPrice":{"description":"One unit's price from that quantity on.","type":"Money","required":true}}} />

## `WholesaleTiersView` [#wholesaletiersview]

What a wholesale buyer sees beside the price: the list price and the quantity breaks.

<TypeTable type={{"listPrice":{"description":"The consumer price when the buyer's is lower, otherwise null.","type":"Money | null","required":true},"unitPrice":{"description":"One unit's price below the first break.","type":"Money","required":true},"breaks":{"description":"The quantity breaks, smallest first.","type":"readonly WholesaleBreak[]","required":true},"tierOnly":{"description":"Whether the product is sold to wholesale buyers only.","type":"boolean","required":true},"basis":{"description":"Whether the amounts are net or gross.","type":"'gross' | 'net'","required":true}}} />

## `WholesaleTiersProps` [#wholesaletiersprops]

Props of [`WholesaleTiers`](/themes/sdk/reference/product/parts-1#wholesaletiers).

<TypeTable type={{"tiers":{"description":"The buyer's tier prices.","type":"WholesaleTiersView","required":true},"quantity":{"description":"The quantity chosen, whose break is highlighted.","type":"number","required":false},"className":{"description":"Classes added to the tiers.","type":"string","required":false}}} />

## `AvailabilityBadgeProps` [#availabilitybadgeprops]

Props of [`AvailabilityBadge`](/themes/sdk/reference/product/parts-1#availabilitybadge).

<TypeTable type={{"availability":{"description":"The product's or variant's availability.","type":"Availability","required":true},"className":{"description":"Classes added to the badge.","type":"string","required":false}}} />

## `BuyFieldsProps` [#buyfieldsprops]

Props of [`PersonalizationFields`](/themes/sdk/reference/product/parts-1#personalizationfields) and [`GiftCardFields`](/themes/sdk/reference/product/parts-1#giftcardfields).

<TypeTable type={{"className":{"description":"Classes added to the fields.","type":"string","required":false}}} />

## `BundleSelectionGroup` [#bundleselectiongroup]

A group of bundle items the shopper picks a number of, such as "Choose 2 sauces".

<TypeTable type={{"id":{"description":"The group's id.","type":"string","required":true},"label":{"description":"The group's label in the page language.","type":"string","required":true},"min":{"description":"The fewest items to choose.","type":"number","required":true},"max":{"description":"The most items to choose.","type":"number","required":true},"chosen":{"description":"How many are chosen.","type":"number","required":true},"complete":{"description":"Whether the choice meets the group's limits.","type":"boolean","required":true}}} />

## `BundleSelectionItem` [#bundleselectionitem]

One item a bundle offers with the product page's product.

<TypeTable type={{"id":{"description":"The bundle item's id; pass it to `toggle`.","type":"string","required":true},"productId":{"description":"The item's product id.","type":"string","required":true},"variantId":{"description":"The item's variant id.","type":"string","required":true},"title":{"description":"The item's product title.","type":"string","required":true},"variantTitle":{"description":"The variant's title, or null for a single-variant product.","type":"string | null","required":true},"image":{"description":"The item's image, or null.","type":"MediaImageRef | null","required":true},"quantity":{"description":"How many of it the bundle holds.","type":"number","required":true},"groupId":{"description":"The group the item is chosen in, or null for an ungrouped item.","type":"string | null","required":true},"optional":{"description":"Whether the shopper may leave it out.","type":"boolean","required":true},"selected":{"description":"Whether it is chosen.","type":"boolean","required":true},"selectable":{"description":"Whether choosing it now keeps the bundle within its limits.","type":"boolean","required":true}}} />

## `BundleSelectionState` [#bundleselectionstate]

The bundle offered on the product page and the shopper's choice in it.

<TypeTable type={{"bundleId":{"description":"The bundle's id.","type":"string","required":true},"title":{"description":"The bundle's title.","type":"string","required":true},"mode":{"description":"How the bundle sells.","type":"BundleMode","required":true},"offers":{"description":"The other bundles the product is offered in, this one included.","type":"readonly { readonly id: string; readonly title: string; }[]","required":true},"chooseOffer":{"description":"Switches to another offer.","type":"(bundleId: string) => void","required":true},"items":{"description":"The items, in the merchant's order.","type":"readonly BundleSelectionItem[]","required":true},"groups":{"description":"The groups items are chosen in.","type":"readonly BundleSelectionGroup[]","required":true},"toggle":{"description":"Chooses or leaves out an item.","type":"(itemId: string, next: boolean) => void","required":true},"complete":{"description":"Whether the choice makes a complete bundle.","type":"boolean","required":true},"savings":{"description":"What the choice saves against buying the items alone, or null while unknown.","type":"Money | null","required":true},"quote":{"description":"The priced choice: `loading` while the host prices it, `unavailable` when it cannot.","type":"{ readonly status: 'loading' | 'ready' | 'unavailable'; readonly total: Money | null; readonly compareAt: Money | null; }","required":true}}} />

## `BundleSelectorProps` [#bundleselectorprops]

Props of [`BundleSelector`](/themes/sdk/reference/product/defaults-1#bundleselector).

<TypeTable type={{"className":{"description":"Classes added to the selector.","type":"string","required":false},"placement":{"description":"Where the offer sits: `aside` in the buy box (the default), or `below` across the page under both columns.","type":"'aside' | 'below'","required":false}}} />
