@shopify/hydrogen-react
Version:
React components, hooks, and utilities for creating custom Shopify storefronts
160 lines (159 loc) • 5.67 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const React = require("react");
const ShopifyProvider = require("./ShopifyProvider.js");
function useMoney(money) {
const { countryIsoCode, languageIsoCode } = ShopifyProvider.useShop();
const locale = languageIsoCode.includes("_") ? languageIsoCode.replace("_", "-") : `${languageIsoCode}-${countryIsoCode}`;
if (!locale) {
throw new Error(
`useMoney(): Unable to get 'locale' from 'useShop()', which means that 'locale' was not passed to '<ShopifyProvider/>'. 'locale' is required for 'useMoney()' to work`
);
}
const amount = parseFloat(money.amount);
let isCurrencySupported = true;
try {
new Intl.NumberFormat(locale, {
style: "currency",
currency: money.currencyCode
});
} catch (e) {
if (e instanceof RangeError && e.message.includes("currency")) {
isCurrencySupported = false;
}
}
const {
defaultFormatter,
nameFormatter,
narrowSymbolFormatter,
withoutTrailingZerosFormatter,
withoutCurrencyFormatter,
withoutTrailingZerosOrCurrencyFormatter
} = React.useMemo(() => {
const options = isCurrencySupported ? {
style: "currency",
currency: money.currencyCode
} : {
style: "decimal",
minimumFractionDigits: 2,
maximumFractionDigits: 2
};
return {
defaultFormatter: getLazyFormatter(locale, options),
nameFormatter: getLazyFormatter(locale, {
...options,
currencyDisplay: "name"
}),
narrowSymbolFormatter: getLazyFormatter(locale, {
...options,
currencyDisplay: "narrowSymbol"
}),
withoutTrailingZerosFormatter: getLazyFormatter(locale, {
...options,
minimumFractionDigits: 0,
maximumFractionDigits: 0
}),
withoutCurrencyFormatter: getLazyFormatter(locale, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}),
withoutTrailingZerosOrCurrencyFormatter: getLazyFormatter(locale, {
minimumFractionDigits: 0,
maximumFractionDigits: 0
})
};
}, [money.currencyCode, locale, isCurrencySupported]);
const isPartCurrency = (part) => part.type === "currency";
const lazyFormatters = React.useMemo(
() => ({
original: () => money,
currencyCode: () => money.currencyCode,
localizedString: () => {
const formatted = defaultFormatter().format(amount);
return isCurrencySupported ? formatted : `${formatted} ${money.currencyCode}`;
},
parts: () => {
const parts = defaultFormatter().formatToParts(amount);
if (!isCurrencySupported) {
parts.push(
{ type: "literal", value: " " },
{ type: "currency", value: money.currencyCode }
);
}
return parts;
},
withoutTrailingZeros: () => {
const formatted = amount % 1 === 0 ? withoutTrailingZerosFormatter().format(amount) : defaultFormatter().format(amount);
return isCurrencySupported ? formatted : `${formatted} ${money.currencyCode}`;
},
withoutTrailingZerosAndCurrency: () => amount % 1 === 0 ? withoutTrailingZerosOrCurrencyFormatter().format(amount) : withoutCurrencyFormatter().format(amount),
currencyName: () => {
var _a;
return ((_a = nameFormatter().formatToParts(amount).find(isPartCurrency)) == null ? void 0 : _a.value) ?? money.currencyCode;
},
// e.g. "US dollars"
currencySymbol: () => {
var _a;
return ((_a = defaultFormatter().formatToParts(amount).find(isPartCurrency)) == null ? void 0 : _a.value) ?? money.currencyCode;
},
// e.g. "USD"
currencyNarrowSymbol: () => {
var _a;
return ((_a = narrowSymbolFormatter().formatToParts(amount).find(isPartCurrency)) == null ? void 0 : _a.value) ?? "";
},
// e.g. "$"
amount: () => defaultFormatter().formatToParts(amount).filter(
(part) => ["decimal", "fraction", "group", "integer", "literal"].includes(
part.type
)
).map((part) => part.value).join("")
}),
[
money,
amount,
isCurrencySupported,
nameFormatter,
defaultFormatter,
narrowSymbolFormatter,
withoutCurrencyFormatter,
withoutTrailingZerosFormatter,
withoutTrailingZerosOrCurrencyFormatter
]
);
return React.useMemo(
() => new Proxy(lazyFormatters, {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
get: (target, key) => {
var _a;
return (_a = Reflect.get(target, key)) == null ? void 0 : _a.call(null);
}
}),
[lazyFormatters]
);
}
const formatterCache = /* @__PURE__ */ new Map();
function getLazyFormatter(locale, options) {
const key = JSON.stringify([locale, options]);
return function() {
let formatter = formatterCache.get(key);
if (!formatter) {
try {
formatter = new Intl.NumberFormat(locale, options);
} catch (error) {
if (error instanceof RangeError && error.message.includes("currency")) {
const fallbackOptions = { ...options };
delete fallbackOptions.currency;
delete fallbackOptions.currencyDisplay;
delete fallbackOptions.currencySign;
formatter = new Intl.NumberFormat(locale, fallbackOptions);
} else {
throw error;
}
}
formatterCache.set(key, formatter);
}
return formatter;
};
}
exports.useMoney = useMoney;
//# sourceMappingURL=useMoney.js.map