@shopify/hydrogen-react
Version:
React components, hooks, and utilities for creating custom Shopify storefronts
252 lines (251 loc) • 8.65 kB
JavaScript
import { isOptionValueCombinationInEncodedVariant } from "./optionValueDecoder.mjs";
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 = isOptionValueCombinationInEncodedVariant(
topDownKey,
encodedVariantExistence || ""
);
const available = 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;
}
export {
checkProductParam,
getAdjacentAndFirstAvailableVariants,
getProductOptions,
mapSelectedProductOptionToObject
};
//# sourceMappingURL=getProductOptions.mjs.map