UNPKG

1.98 kBJavaScriptView Raw
1import React, { PureComponent, Fragment } from 'react';
2import { number, string, shape } from 'prop-types';
3import patches from '../util/intlPatches';
4
5/**
6 * The **Price** component is used anywhere a price needs to be displayed.
7 *
8 * Formatting of prices and currency symbol selection is handled entirely by the ECMAScript Internationalization API available in modern browsers.
9 *
10 * A [polyfill][] is required for any JavaScript runtime that does not have [Intl.NumberFormat.prototype.formatToParts][].
11 *
12 * [polyfill]: https://www.npmjs.com/package/intl
13 * [Intl.NumberFormat.prototype.formatToParts]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts
14 */
15export default class Price extends PureComponent {
16 static propTypes = {
17 /**
18 * The numeric price
19 */
20 value: number.isRequired,
21 /**
22 * A string with any of the currency code supported by Intl.NumberFormat
23 */
24 currencyCode: string.isRequired,
25 /**
26 * Class names to use when styling this component
27 */
28 classes: shape({
29 currency: string,
30 integer: string,
31 decimal: string,
32 fraction: string
33 })
34 };
35
36 static defaultProps = {
37 classes: {}
38 };
39
40 render() {
41 const { value, currencyCode, classes } = this.props;
42
43 const parts = patches.toParts.call(
44 Intl.NumberFormat(undefined, {
45 style: 'currency',
46 currency: currencyCode
47 }),
48 value
49 );
50
51 const children = parts.map((part, i) => {
52 const partClass = classes[part.type];
53 const key = `${i}-${part.value}`;
54
55 return (
56 <span key={key} className={partClass}>
57 {part.value}
58 </span>
59 );
60 });
61
62 return <Fragment>{children}</Fragment>;
63 }
64}