initial commit
This commit is contained in:
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import NumberFormat, {
|
||||
NumberFormatValues,
|
||||
NumberFormatProps,
|
||||
} from 'react-number-format';
|
||||
import classNames from 'classnames';
|
||||
import type { Currency } from '@woocommerce/price-format';
|
||||
import type { ReactElement } from 'react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
interface FormattedMonetaryAmountProps {
|
||||
className?: string;
|
||||
displayType?: NumberFormatProps[ 'displayType' ];
|
||||
value: number | string; // Value of money amount.
|
||||
currency: Currency | Record< string, never >; // Currency configuration object.
|
||||
onValueChange?: ( unit: number ) => void; // Function to call when value changes.
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats currency data into the expected format for NumberFormat.
|
||||
*/
|
||||
const currencyToNumberFormat = (
|
||||
currency: FormattedMonetaryAmountProps[ 'currency' ]
|
||||
) => {
|
||||
return {
|
||||
thousandSeparator: currency.thousandSeparator,
|
||||
decimalSeparator: currency.decimalSeparator,
|
||||
decimalScale: currency.minorUnit,
|
||||
fixedDecimalScale: true,
|
||||
prefix: currency.prefix,
|
||||
suffix: currency.suffix,
|
||||
isNumericString: true,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* FormattedMonetaryAmount component.
|
||||
*
|
||||
* Takes a price and returns a formatted price using the NumberFormat component.
|
||||
*/
|
||||
const FormattedMonetaryAmount = ( {
|
||||
className,
|
||||
value: rawValue,
|
||||
currency,
|
||||
onValueChange,
|
||||
displayType = 'text',
|
||||
...props
|
||||
}: FormattedMonetaryAmountProps ): ReactElement | null => {
|
||||
const value =
|
||||
typeof rawValue === 'string' ? parseInt( rawValue, 10 ) : rawValue;
|
||||
|
||||
if ( ! Number.isFinite( value ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const priceValue = value / 10 ** currency.minorUnit;
|
||||
|
||||
if ( ! Number.isFinite( priceValue ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classes = classNames(
|
||||
'wc-block-formatted-money-amount',
|
||||
'wc-block-components-formatted-money-amount',
|
||||
className
|
||||
);
|
||||
const numberFormatProps = {
|
||||
...props,
|
||||
...currencyToNumberFormat( currency ),
|
||||
value: undefined,
|
||||
currency: undefined,
|
||||
onValueChange: undefined,
|
||||
};
|
||||
|
||||
// Wrapper for NumberFormat onValueChange which handles subunit conversion.
|
||||
const onValueChangeWrapper = onValueChange
|
||||
? ( values: NumberFormatValues ) => {
|
||||
const minorUnitValue =
|
||||
( ( values.value as unknown ) as number ) *
|
||||
10 ** currency.minorUnit;
|
||||
onValueChange( minorUnitValue );
|
||||
}
|
||||
: () => {
|
||||
/* not used */
|
||||
};
|
||||
|
||||
return (
|
||||
<NumberFormat
|
||||
className={ classes }
|
||||
displayType={ displayType }
|
||||
{ ...numberFormatProps }
|
||||
value={ priceValue }
|
||||
onValueChange={ onValueChangeWrapper }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default FormattedMonetaryAmount;
|
@ -0,0 +1,3 @@
|
||||
.wc-block-components-formatted-money-amount {
|
||||
white-space: nowrap;
|
||||
}
|
Reference in New Issue
Block a user