import {useCallback} from 'react' import {useShopIntent} from '../../internal/useShopIntent' import type { IntentResult, SelectProductVariantParams, SelectProductVariantResult, } from '@shopify/shop-minis-platform/actions' /** * Params accepted by `useSelectVariant().selectVariant()`. * * Direct alias for the shared `SelectProductVariantParams` intent payload * (which already requires `productId` and accepts all the optional sheet * customization fields). * * @publicDocs */ export type SelectVariantParams = SelectProductVariantParams /** * Successful payload returned from `useSelectVariant().selectVariant()`. * Alias for `SelectProductVariantResult` so SDK consumers can import it from * the same place as the hook. * * @publicDocs */ export type SelectVariantResult = SelectProductVariantResult export interface UseSelectVariantReturns { /** * Opens the native variant selector sheet on top of the mini WebView. * * Resolves with: * - `{code: 'ok', data: SelectVariantResult}` when the user confirms a variant * - `{code: 'closed'}` when the user dismisses the sheet (swipe, backdrop, X) * - `{code: 'error', message}` for any host-side failure */ selectVariant: ( params: SelectVariantParams ) => Promise> } /** * Prompts the user to pick a product variant (and quantity) via a native * bottom sheet rendered on top of the mini WebView. Use this when your mini * has a product GID but not a variant GID and needs the user to choose * before adding to cart or buying. * * The sheet renders the same option pickers used inside Shop's PDP, and * automatically: * * - skips the sheet for single-variant products (pass `forceShow: true` to * keep the sheet visible regardless) * - filters to a subset via `includedProductVariantGIDs` * - resolves immediately with the only variant when filtered to one item * * The success payload includes `source`: `'user'` when the user picked the * variant in the sheet, `'auto'` when the host resolved the selection * without showing UI. * * Internally this is a typed wrapper around the * `select:shopify/ProductVariant` intent. * * @example * ```tsx * const {selectVariant} = useSelectVariant() * * const result = await selectVariant({productId}) * if (result.code === 'ok') { * // result.data.outcome === 'selected' * // result.data.productVariantId / variant / quantity / source * } else if (result.code === 'closed') { * // user dismissed the sheet * } else { * // result.message * } * ``` * * @publicDocs */ export function useSelectVariant(): UseSelectVariantReturns { const {invokeQuery} = useShopIntent() const selectVariant = useCallback( async ( params: SelectVariantParams ): Promise> => { const result = await invokeQuery({ action: 'select', type: 'shopify/ProductVariant', // Selection has no pre-existing variant resource (→ value omitted), // the input context (productId) travels in `data` instead. data: params, }) // The bridge returns untyped data; the host handler guarantees the // shape matches SelectVariantResult for this action+type. return result as IntentResult }, [invokeQuery] ) return {selectVariant} } /** * The `useSelectVariant` hook prompts the user to choose a product variant * (and quantity) via a native bottom sheet rendered on top of the mini * WebView. Resolves with an `IntentResult` whose `code` is `'ok'` (success), * `'closed'` (user dismissed), or `'error'` (host failure). * * @publicDocs */ export type UseSelectVariantGeneratedType = () => UseSelectVariantReturns