UNPKG

@shopify/hydrogen-react

Version:

React components, hooks, and utilities for creating custom Shopify storefronts

252 lines (251 loc) • 8.88 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const optionValueDecoder = require("./optionValueDecoder.js"); function mapProductOptions(options) { return Object.assign( {}, ...options.map((option) => { return { [option.name]: Object.assign( {}, ...(option == null ? void 0 : option.optionValues) ? option.optionValues.map((value, index) => { return { [value.name]: index }; }) : [] ) }; }) ); } function mapSelectedProductOptionToObject(options) { return Object.assign( {}, ...options.map((key) => { return { [key.name]: key.value }; }) ); } function mapSelectedProductOptionToObjectAsString(options) { return JSON.stringify(mapSelectedProductOptionToObject(options)); } function encodeSelectedProductOptionAsKey(selectedOption) { if (Array.isArray(selectedOption)) { return JSON.stringify( Object.assign( {}, ...selectedOption.map((option) => ({ [option.name]: option.value })) ) ); } else { return JSON.stringify(selectedOption); } } function buildEncodingArrayFromSelectedOptions(selectedOption, productOptionMappings) { const encoding = Object.keys(selectedOption).map((key) => { return productOptionMappings[key] ? productOptionMappings[key][selectedOption[key]] : null; }); return encoding.filter((code) => code !== null); } function mapVariants(variants) { return Object.assign( {}, ...variants.map((variant) => { const variantKey = encodeSelectedProductOptionAsKey( variant.selectedOptions || [] ); return { [variantKey]: variant }; }) ); } const PRODUCT_INPUTS = [ "options", "selectedOrFirstAvailableVariant", "adjacentVariants" ]; const PRODUCT_INPUTS_EXTRA = [ "handle", "encodedVariantExistence", "encodedVariantAvailability" ]; function logErrorAndReturnFalse(key) { console.error( `[h2:error:getProductOptions] product.${key} is missing. Make sure you query for this field from the Storefront API.` ); return false; } function checkProductParam(product, checkAll = false) { var _a; let validParam = true; const productKeys = Object.keys(product); (checkAll ? [...PRODUCT_INPUTS, ...PRODUCT_INPUTS_EXTRA] : PRODUCT_INPUTS).forEach((key) => { if (!productKeys.includes(key)) { validParam = logErrorAndReturnFalse(key); } }); if (product.options) { const firstOption = product == null ? void 0 : product.options[0]; if (checkAll && !(firstOption == null ? void 0 : firstOption.name)) { validParam = logErrorAndReturnFalse("options.name"); } if ((_a = product == null ? void 0 : product.options[0]) == null ? void 0 : _a.optionValues) { let firstOptionValues = product.options[0].optionValues[0]; if (checkAll && !(firstOptionValues == null ? void 0 : firstOptionValues.name)) { validParam = logErrorAndReturnFalse("options.optionValues.name"); } firstOptionValues = product.options[0].optionValues.filter( (value) => !!(value == null ? void 0 : value.firstSelectableVariant) )[0]; if (firstOptionValues == null ? void 0 : firstOptionValues.firstSelectableVariant) { validParam = checkProductVariantParam( firstOptionValues.firstSelectableVariant, "options.optionValues.firstSelectableVariant", validParam, checkAll ); } } else { validParam = logErrorAndReturnFalse("options.optionValues"); } } if (product.selectedOrFirstAvailableVariant) { validParam = checkProductVariantParam( product.selectedOrFirstAvailableVariant, "selectedOrFirstAvailableVariant", validParam, checkAll ); } if (!!product.adjacentVariants && product.adjacentVariants[0]) { validParam = checkProductVariantParam( product.adjacentVariants[0], "adjacentVariants", validParam, checkAll ); } return validParam ? product : {}; } function checkProductVariantParam(variant, key, currentValidParamState, checkAll) { var _a; let validParam = currentValidParamState; if (checkAll && !((_a = variant.product) == null ? void 0 : _a.handle)) { validParam = logErrorAndReturnFalse(`${key}.product.handle`); } if (variant.selectedOptions) { const firstSelectedOption = variant.selectedOptions[0]; if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.name)) { validParam = logErrorAndReturnFalse(`${key}.selectedOptions.name`); } if (!(firstSelectedOption == null ? void 0 : firstSelectedOption.value)) { validParam = logErrorAndReturnFalse(`${key}.selectedOptions.value`); } } else { validParam = logErrorAndReturnFalse(`${key}.selectedOptions`); } return validParam; } function getAdjacentAndFirstAvailableVariants(product) { const checkedProduct = checkProductParam(product); if (!checkedProduct.options) return []; const availableVariants = {}; checkedProduct.options.map((option) => { var _a; (_a = option.optionValues) == null ? void 0 : _a.map((value) => { if (value.firstSelectableVariant) { const variantKey = mapSelectedProductOptionToObjectAsString( value.firstSelectableVariant.selectedOptions ); availableVariants[variantKey] = value.firstSelectableVariant; } }); }); checkedProduct.adjacentVariants.map((variant) => { const variantKey = mapSelectedProductOptionToObjectAsString( variant.selectedOptions ); availableVariants[variantKey] = variant; }); const selectedVariant = checkedProduct.selectedOrFirstAvailableVariant; if (selectedVariant) { const variantKey = mapSelectedProductOptionToObjectAsString( selectedVariant.selectedOptions ); availableVariants[variantKey] = selectedVariant; } return Object.values(availableVariants); } function getProductOptions(product) { const checkedProduct = checkProductParam(product, true); if (!checkedProduct.options) return []; const { options, selectedOrFirstAvailableVariant: selectedVariant, adjacentVariants, encodedVariantExistence, encodedVariantAvailability, handle: productHandle } = checkedProduct; const selectedOptionKeys = selectedVariant == null ? void 0 : selectedVariant.selectedOptions.map( (option) => option.name ); const filteredOptions = options.filter((option) => { return selectedOptionKeys && selectedOptionKeys.indexOf(option.name) >= 0; }); const productOptionMappings = mapProductOptions(options); const variants = mapVariants( selectedVariant ? [selectedVariant, ...adjacentVariants] : adjacentVariants ); const selectedOptions = mapSelectedProductOptionToObject( selectedVariant ? selectedVariant.selectedOptions : [] ); const productOptions = filteredOptions.map((option, optionIndex) => { return { ...option, optionValues: option.optionValues.map((value) => { var _a; const targetOptionParams = { ...selectedOptions }; targetOptionParams[option.name] = value.name; const targetKey = encodeSelectedProductOptionAsKey( targetOptionParams || [] ); const encodingKey = buildEncodingArrayFromSelectedOptions( targetOptionParams || [], productOptionMappings ); const topDownKey = encodingKey.slice(0, optionIndex + 1); const exists = optionValueDecoder.isOptionValueCombinationInEncodedVariant( topDownKey, encodedVariantExistence || "" ); const available = optionValueDecoder.isOptionValueCombinationInEncodedVariant( topDownKey, encodedVariantAvailability || "" ); const variant = variants[targetKey] || value.firstSelectableVariant; let variantOptionParam = {}; if (variant) { variantOptionParam = mapSelectedProductOptionToObject( variant.selectedOptions || [] ); } const searchParams = new URLSearchParams(variantOptionParam); const handle = ((_a = variant == null ? void 0 : variant.product) == null ? void 0 : _a.handle) || productHandle; return { ...value, variant, handle, variantUriQuery: searchParams.toString(), selected: selectedOptions[option.name] === value.name, exists, available, isDifferentProduct: handle !== productHandle }; }) }; }); return productOptions; } exports.checkProductParam = checkProductParam; exports.getAdjacentAndFirstAvailableVariants = getAdjacentAndFirstAvailableVariants; exports.getProductOptions = getProductOptions; exports.mapSelectedProductOptionToObject = mapSelectedProductOptionToObject; //# sourceMappingURL=getProductOptions.js.map