Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit 85495b1

Browse files
committed
add support for superscript style on price values
1 parent 57900e4 commit 85495b1

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

assets/js/atomic/blocks/product-elements/price-v2/block.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,9 @@
3636
"type": "number",
3737
"default": 0
3838
}
39-
}
39+
},
40+
"styles": [
41+
{ "name": "default", "label": "Default", "isDefault": true },
42+
{ "name": "price-super", "label": "Superscript", "isDefault": false }
43+
]
4044
}

assets/js/atomic/blocks/product-elements/price-v2/inner-blocks/current-price/block.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const Block = ( {
4949
priceStyle={ style }
5050
priceClassName={ priceClassName }
5151
currency={ currency }
52+
withSuperScript={ true }
5253
price={
5354
isDescendentOfSingleProductTemplate ? pricePreview : rawPrice
5455
}

assets/js/base/components/formatted-monetary-amount/index.tsx

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,37 @@ import './style.scss';
1818
interface FormattedMonetaryAmountProps
1919
extends Omit< NumberFormatProps, 'onValueChange' > {
2020
className?: string;
21-
displayType?: NumberFormatProps[ 'displayType' ];
2221
allowNegative?: boolean;
2322
isAllowed?: ( formattedValue: NumberFormatValues ) => boolean;
2423
value: number | string; // Value of money amount.
2524
currency: Currency | Record< string, never >; // Currency configuration object.
2625
onValueChange?: ( unit: number ) => void; // Function to call when value changes.
2726
style?: React.CSSProperties | undefined;
28-
renderText?: ( value: string ) => JSX.Element;
27+
renderText?: ( value: string ) => ReactElement | string;
28+
withSuperScript?: boolean;
2929
}
3030

31+
const applySuperscript =
32+
( currency: FormattedMonetaryAmountProps[ 'currency' ] ) =>
33+
( formattedValue: string ): ReactElement | string => {
34+
if ( ! currency.decimalSeparator ) {
35+
return formattedValue;
36+
}
37+
const pattern = new RegExp(
38+
`^(.*)([${ currency.decimalSeparator }])(([^${ currency.decimalSeparator }]*))$`
39+
);
40+
const matches = formattedValue.match( pattern );
41+
if ( ! matches ) {
42+
return formattedValue;
43+
}
44+
return (
45+
<>
46+
<>{ matches[ 1 ] }</>
47+
<sup>{ matches[ 3 ] }</sup>
48+
</>
49+
);
50+
};
51+
3152
/**
3253
* Formats currency data into the expected format for NumberFormat.
3354
*/
@@ -44,12 +65,7 @@ const currencyToNumberFormat = (
4465
};
4566
};
4667

47-
type CustomFormattedMonetaryAmountProps = Omit<
48-
FormattedMonetaryAmountProps,
49-
'currency'
50-
> & {
51-
currency: Currency | Record< string, never >;
52-
};
68+
const defaultRenderText = ( formattedAmount: string ) => formattedAmount;
5369

5470
/**
5571
* FormattedMonetaryAmount component.
@@ -62,8 +78,10 @@ const FormattedMonetaryAmount = ( {
6278
currency,
6379
onValueChange,
6480
displayType = 'text',
81+
withSuperScript = false,
82+
renderText,
6583
...props
66-
}: CustomFormattedMonetaryAmountProps ): ReactElement | null => {
84+
}: FormattedMonetaryAmountProps ): JSX.Element | null => {
6785
const value =
6886
typeof rawValue === 'string' ? parseInt( rawValue, 10 ) : rawValue;
6987

@@ -100,13 +118,20 @@ const FormattedMonetaryAmount = ( {
100118
}
101119
: () => void 0;
102120

121+
if ( ! renderText ) {
122+
renderText = withSuperScript
123+
? applySuperscript( currency )
124+
: defaultRenderText;
125+
}
126+
103127
return (
104128
<NumberFormat
105129
className={ classes }
106130
displayType={ displayType }
107131
{ ...numberFormatProps }
108132
value={ priceValue }
109133
onValueChange={ onValueChangeWrapper }
134+
renderText={ renderText }
110135
/>
111136
);
112137
};

assets/js/base/components/product-price/index.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface PriceRangeProps {
1717
/**
1818
* Currency configuration object
1919
*/
20-
currency: Currency | Record< string, never > | undefined;
20+
currency: Currency | Record< string, never >;
2121
/**
2222
* The maximum price for the range
2323
*/
@@ -38,6 +38,11 @@ interface PriceRangeProps {
3838
* **Note:** this excludes the dash in between the elements
3939
*/
4040
priceStyle?: React.CSSProperties | undefined;
41+
/**
42+
* If true, the decimal separator will be excluded and the amount after it
43+
* will be wrapped in a superscript element.
44+
*/
45+
withSuperScript: boolean | undefined;
4146
}
4247

4348
const PriceRange = ( {
@@ -46,6 +51,7 @@ const PriceRange = ( {
4651
minPrice,
4752
priceClassName,
4853
priceStyle = {},
54+
withSuperScript = false,
4955
}: PriceRangeProps ) => {
5056
return (
5157
<>
@@ -69,6 +75,7 @@ const PriceRange = ( {
6975
currency={ currency }
7076
value={ minPrice }
7177
style={ priceStyle }
78+
withSuperScript={ withSuperScript }
7279
/>
7380
&nbsp;&mdash;&nbsp;
7481
<FormattedMonetaryAmount
@@ -79,6 +86,7 @@ const PriceRange = ( {
7986
currency={ currency }
8087
value={ maxPrice }
8188
style={ priceStyle }
89+
withSuperScript={ withSuperScript }
8290
/>
8391
</span>
8492
</>
@@ -89,7 +97,7 @@ interface SalePriceProps {
8997
/**
9098
* Currency configuration object
9199
*/
92-
currency: Currency | Record< string, never > | undefined;
100+
currency: Currency | Record< string, never >;
93101
/**
94102
* CSS class to be applied to the regular price container
95103
*
@@ -121,7 +129,7 @@ interface SalePriceProps {
121129
/**
122130
* The new price during the sale
123131
*/
124-
price: number | string | undefined;
132+
price: number | string;
125133
}
126134

127135
const SalePrice = ( {
@@ -248,6 +256,11 @@ export interface ProductPriceProps {
248256
'marginTop' | 'marginRight' | 'marginBottom' | 'marginLeft'
249257
>
250258
| undefined;
259+
/**
260+
* If true, the decimal separator will be excluded and the amount after it
261+
* will be wrapped in a superscript element.
262+
*/
263+
withSuperScript: boolean | undefined;
251264
}
252265

253266
const ProductPrice = ( {
@@ -264,6 +277,7 @@ const ProductPrice = ( {
264277
regularPriceClassName,
265278
regularPriceStyle,
266279
style,
280+
withSuperScript = false,
267281
}: ProductPriceProps ): JSX.Element => {
268282
const wrapperClassName = classNames(
269283
className,
@@ -310,6 +324,7 @@ const ProductPrice = ( {
310324
minPrice={ minPrice }
311325
priceClassName={ priceClassName }
312326
priceStyle={ priceStyle }
327+
withSuperScript={ withSuperScript }
313328
/>
314329
);
315330
} else if ( price ) {
@@ -322,6 +337,7 @@ const ProductPrice = ( {
322337
currency={ currency }
323338
value={ price }
324339
style={ priceStyle }
340+
withSuperScript={ withSuperScript }
325341
/>
326342
);
327343
}

0 commit comments

Comments
 (0)