Convert components to Typescript (https://github.com/woocommerce/woocommerce-blocks/pull/5241)
* Convert ReturnToCartButton component to TS * Convert FormStep component to TS * Remoe proptypes from FormStep and AddressFormn components * Converted order-summary component to TS * Convert product-price component to TS * alias path to type-defs * Fix errors * Changes from Thomas feedback * Change minPrice maxPrice logic to be more robust * Changed types from inline to interface in ReturnToCartButton component * Check for string type in order-summary-item * add missing isString check
This commit is contained in:
parent
c067e990b4
commit
d9bf1ba94c
|
@ -1,7 +1,6 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import PropTypes from 'prop-types';
|
||||
import { ValidatedTextInput } from '@woocommerce/base-components/text-input';
|
||||
import {
|
||||
BillingCountryInput,
|
||||
|
@ -241,14 +240,4 @@ const AddressForm = ( {
|
|||
);
|
||||
};
|
||||
|
||||
AddressForm.propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
values: PropTypes.object.isRequired,
|
||||
fields: PropTypes.arrayOf(
|
||||
PropTypes.oneOf( Object.keys( defaultAddressFields ) )
|
||||
),
|
||||
fieldConfig: PropTypes.object,
|
||||
type: PropTypes.oneOf( [ 'billing', 'shipping' ] ),
|
||||
};
|
||||
|
||||
export default withInstanceId( AddressForm );
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import Title from '@woocommerce/base-components/title';
|
||||
|
||||
/**
|
||||
|
@ -10,7 +9,12 @@ import Title from '@woocommerce/base-components/title';
|
|||
*/
|
||||
import './style.scss';
|
||||
|
||||
const StepHeading = ( { title, stepHeadingContent } ) => (
|
||||
interface StepHeadingProps {
|
||||
title: string;
|
||||
stepHeadingContent?: JSX.Element;
|
||||
}
|
||||
|
||||
const StepHeading = ( { title, stepHeadingContent }: StepHeadingProps ) => (
|
||||
<div className="wc-block-components-checkout-step__heading">
|
||||
<Title
|
||||
aria-hidden="true"
|
||||
|
@ -27,6 +31,18 @@ const StepHeading = ( { title, stepHeadingContent } ) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
interface FormStepProps {
|
||||
id?: string;
|
||||
className?: string;
|
||||
title?: string;
|
||||
legend?: string;
|
||||
description?: string;
|
||||
children?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
showStepNumber?: boolean;
|
||||
stepHeadingContent?: () => JSX.Element | undefined;
|
||||
}
|
||||
|
||||
const FormStep = ( {
|
||||
id,
|
||||
className,
|
||||
|
@ -36,8 +52,8 @@ const FormStep = ( {
|
|||
children,
|
||||
disabled = false,
|
||||
showStepNumber = true,
|
||||
stepHeadingContent = () => {},
|
||||
} ) => {
|
||||
stepHeadingContent = () => undefined,
|
||||
}: FormStepProps ): JSX.Element => {
|
||||
// If the form step doesn't have a legend or title, render a <div> instead
|
||||
// of a <fieldset>.
|
||||
const Element = legend || title ? 'fieldset' : 'div';
|
||||
|
@ -80,16 +96,4 @@ const FormStep = ( {
|
|||
);
|
||||
};
|
||||
|
||||
FormStep.propTypes = {
|
||||
id: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
showStepNumber: PropTypes.bool,
|
||||
stepHeadingContent: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
legend: PropTypes.string,
|
||||
};
|
||||
|
||||
export default FormStep;
|
|
@ -2,17 +2,23 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useContainerWidthContext } from '@woocommerce/base-context';
|
||||
import { Panel } from '@woocommerce/blocks-checkout';
|
||||
import type { CartItem } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import OrderSummaryItem from './order-summary-item.js';
|
||||
import OrderSummaryItem from './order-summary-item';
|
||||
import './style.scss';
|
||||
|
||||
const OrderSummary = ( { cartItems = [] } ) => {
|
||||
interface OrderSummaryProps {
|
||||
cartItems: CartItem[];
|
||||
}
|
||||
|
||||
const OrderSummary = ( {
|
||||
cartItems = [],
|
||||
}: OrderSummaryProps ): null | JSX.Element => {
|
||||
const { isLarge, hasContainerWidth } = useContainerWidthContext();
|
||||
|
||||
if ( ! hasContainerWidth ) {
|
||||
|
@ -45,10 +51,4 @@ const OrderSummary = ( { cartItems = [] } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
OrderSummary.propTypes = {
|
||||
cartItems: PropTypes.arrayOf(
|
||||
PropTypes.shape( { key: PropTypes.string.isRequired } )
|
||||
),
|
||||
};
|
||||
|
||||
export default OrderSummary;
|
|
@ -14,11 +14,11 @@ import {
|
|||
__experimentalApplyCheckoutFilter,
|
||||
mustContain,
|
||||
} from '@woocommerce/blocks-checkout';
|
||||
import PropTypes from 'prop-types';
|
||||
import Dinero from 'dinero.js';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import { useMemo } from '@wordpress/element';
|
||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
||||
import { CartItem, isString } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -28,9 +28,14 @@ import ProductImage from '../product-image';
|
|||
import ProductLowStockBadge from '../product-low-stock-badge';
|
||||
import ProductMetadata from '../product-metadata';
|
||||
|
||||
const productPriceValidation = ( value ) => mustContain( value, '<price/>' );
|
||||
const productPriceValidation = ( value: string ): true | never =>
|
||||
mustContain( value, '<price/>' );
|
||||
|
||||
const OrderSummaryItem = ( { cartItem } ) => {
|
||||
interface OrderSummaryProps {
|
||||
cartItem: CartItem;
|
||||
}
|
||||
|
||||
const OrderSummaryItem = ( { cartItem }: OrderSummaryProps ): JSX.Element => {
|
||||
const {
|
||||
images,
|
||||
low_stock_remaining: lowStockRemaining,
|
||||
|
@ -72,13 +77,17 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
|||
|
||||
const regularPriceSingle = Dinero( {
|
||||
amount: parseInt( prices.raw_prices.regular_price, 10 ),
|
||||
precision: parseInt( prices.raw_prices.precision, 10 ),
|
||||
precision: isString( prices.raw_prices.precision )
|
||||
? parseInt( prices.raw_prices.precision, 10 )
|
||||
: prices.raw_prices.precision,
|
||||
} )
|
||||
.convertPrecision( priceCurrency.minorUnit )
|
||||
.getAmount();
|
||||
const priceSingle = Dinero( {
|
||||
amount: parseInt( prices.raw_prices.price, 10 ),
|
||||
precision: parseInt( prices.raw_prices.precision, 10 ),
|
||||
precision: isString( prices.raw_prices.precision )
|
||||
? parseInt( prices.raw_prices.precision, 10 )
|
||||
: prices.raw_prices.precision,
|
||||
} )
|
||||
.convertPrecision( priceCurrency.minorUnit )
|
||||
.getAmount();
|
||||
|
@ -126,7 +135,7 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
|||
<div className="wc-block-components-order-summary-item__image">
|
||||
<div className="wc-block-components-order-summary-item__quantity">
|
||||
<Label
|
||||
label={ quantity }
|
||||
label={ quantity.toString() }
|
||||
screenReaderLabel={ sprintf(
|
||||
/* translators: %d number of products of the same type in the cart */
|
||||
_n(
|
||||
|
@ -203,20 +212,4 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
OrderSummaryItem.propTypes = {
|
||||
cartItems: PropTypes.shape( {
|
||||
images: PropTypes.array,
|
||||
low_stock_remaining: PropTypes.number,
|
||||
name: PropTypes.string.isRequired,
|
||||
permalink: PropTypes.string,
|
||||
prices: PropTypes.shape( {
|
||||
price: PropTypes.string,
|
||||
regular_price: PropTypes.string,
|
||||
} ),
|
||||
quantity: PropTypes.number,
|
||||
summary: PropTypes.string,
|
||||
variation: PropTypes.array,
|
||||
} ),
|
||||
};
|
||||
|
||||
export default OrderSummaryItem;
|
|
@ -10,7 +10,13 @@ import { Icon, arrowBack } from '@woocommerce/icons';
|
|||
*/
|
||||
import './style.scss';
|
||||
|
||||
const ReturnToCartButton = ( { link } ) => {
|
||||
interface ReturnToCartButtonProps {
|
||||
link?: string;
|
||||
}
|
||||
|
||||
const ReturnToCartButton = ( {
|
||||
link,
|
||||
}: ReturnToCartButtonProps ): JSX.Element => {
|
||||
return (
|
||||
<a
|
||||
href={ link || CART_URL }
|
|
@ -6,8 +6,8 @@ import NumberFormat, {
|
|||
NumberFormatProps,
|
||||
} from 'react-number-format';
|
||||
import classNames from 'classnames';
|
||||
import type { Currency } from '@woocommerce/price-format';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { Currency } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -20,6 +20,8 @@ interface FormattedMonetaryAmountProps {
|
|||
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.
|
||||
style?: React.CSSProperties;
|
||||
renderText?: ( value: string ) => JSX.Element;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,22 +4,30 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { formatPrice } from '@woocommerce/price-format';
|
||||
import { createInterpolateElement } from '@wordpress/element';
|
||||
import type { Currency } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
interface PriceRangeProps {
|
||||
currency: Currency | Record< string, never >; // Currency configuration object;
|
||||
maxPrice: string | number;
|
||||
minPrice: string | number;
|
||||
priceClassName?: string;
|
||||
priceStyle?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const PriceRange = ( {
|
||||
currency,
|
||||
maxPrice,
|
||||
minPrice,
|
||||
priceClassName,
|
||||
priceStyle,
|
||||
} ) => {
|
||||
}: PriceRangeProps ) => {
|
||||
return (
|
||||
<>
|
||||
<span className="screen-reader-text">
|
||||
|
@ -58,6 +66,16 @@ const PriceRange = ( {
|
|||
);
|
||||
};
|
||||
|
||||
interface SalePriceProps {
|
||||
currency: Currency | Record< string, never >; // Currency configuration object.
|
||||
regularPriceClassName?: string;
|
||||
regularPriceStyle?: Record< string, string >;
|
||||
regularPrice: number | string;
|
||||
priceClassName?: string;
|
||||
priceStyle?: Record< string, string >;
|
||||
price: number | string;
|
||||
}
|
||||
|
||||
const SalePrice = ( {
|
||||
currency,
|
||||
regularPriceClassName,
|
||||
|
@ -66,7 +84,7 @@ const SalePrice = ( {
|
|||
priceClassName,
|
||||
priceStyle,
|
||||
price,
|
||||
} ) => {
|
||||
}: SalePriceProps ) => {
|
||||
return (
|
||||
<>
|
||||
<span className="screen-reader-text">
|
||||
|
@ -110,20 +128,35 @@ const SalePrice = ( {
|
|||
);
|
||||
};
|
||||
|
||||
interface ProductPriceProps {
|
||||
align?: 'left' | 'center' | 'right';
|
||||
className?: string;
|
||||
currency: Currency | Record< string, never >; // Currency configuration object.
|
||||
format: string;
|
||||
price: number | string;
|
||||
priceClassName?: string;
|
||||
priceStyle?: Record< string, string >;
|
||||
maxPrice?: number | string;
|
||||
minPrice?: number | string;
|
||||
regularPrice?: number | string;
|
||||
regularPriceClassName?: string;
|
||||
regularPriceStyle?: Record< string, string >;
|
||||
}
|
||||
|
||||
const ProductPrice = ( {
|
||||
align,
|
||||
className,
|
||||
currency,
|
||||
format = '<price/>',
|
||||
maxPrice = null,
|
||||
minPrice = null,
|
||||
price = null,
|
||||
maxPrice,
|
||||
minPrice,
|
||||
price,
|
||||
priceClassName,
|
||||
priceStyle,
|
||||
regularPrice,
|
||||
regularPriceClassName,
|
||||
regularPriceStyle,
|
||||
} ) => {
|
||||
}: ProductPriceProps ): JSX.Element => {
|
||||
const wrapperClassName = classNames(
|
||||
className,
|
||||
'price',
|
||||
|
@ -161,7 +194,7 @@ const ProductPrice = ( {
|
|||
regularPriceStyle={ regularPriceStyle }
|
||||
/>
|
||||
);
|
||||
} else if ( minPrice !== null && maxPrice !== null ) {
|
||||
} else if ( minPrice !== undefined && maxPrice !== undefined ) {
|
||||
priceComponent = (
|
||||
<PriceRange
|
||||
currency={ currency }
|
||||
|
@ -171,7 +204,7 @@ const ProductPrice = ( {
|
|||
priceStyle={ priceStyle }
|
||||
/>
|
||||
);
|
||||
} else if ( price !== null ) {
|
||||
} else if ( price ) {
|
||||
priceComponent = (
|
||||
<FormattedMonetaryAmount
|
||||
className={ classNames(
|
||||
|
@ -194,21 +227,4 @@ const ProductPrice = ( {
|
|||
);
|
||||
};
|
||||
|
||||
ProductPrice.propTypes = {
|
||||
align: PropTypes.oneOf( [ 'left', 'center', 'right' ] ),
|
||||
className: PropTypes.string,
|
||||
currency: PropTypes.object,
|
||||
format: PropTypes.string,
|
||||
price: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ),
|
||||
priceClassName: PropTypes.string,
|
||||
priceStyle: PropTypes.object,
|
||||
// Range price props
|
||||
maxPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ),
|
||||
minPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ),
|
||||
// On sale price props
|
||||
regularPrice: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ),
|
||||
regularPriceClassName: PropTypes.string,
|
||||
regularPriceStyle: PropTypes.object,
|
||||
};
|
||||
|
||||
export default ProductPrice;
|
|
@ -7,6 +7,8 @@ import {
|
|||
ExtensionsData,
|
||||
} from './cart-response';
|
||||
|
||||
import { ProductResponseItemData } from './product-response';
|
||||
|
||||
export interface CurrencyInfo {
|
||||
currency_code: string;
|
||||
currency_symbol: string;
|
||||
|
@ -131,7 +133,7 @@ export interface CartItem {
|
|||
prices: CartItemPrices;
|
||||
totals: CartItemTotals;
|
||||
extensions: ExtensionsData;
|
||||
item_data: Record< string, unknown >[];
|
||||
item_data: ProductResponseItemData[];
|
||||
}
|
||||
|
||||
export interface CartTotalsTaxLineItem {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|||
export const mustContain = (
|
||||
value: string,
|
||||
requiredValue: string
|
||||
): true | Error => {
|
||||
): true | never => {
|
||||
if ( ! value.includes( requiredValue ) ) {
|
||||
throw Error(
|
||||
sprintf(
|
||||
|
|
Loading…
Reference in New Issue