Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/nexxtway/react-rainbow in…
Browse files Browse the repository at this point in the history
…to feat-add-picklist-prop-size
  • Loading branch information
yvmunayev committed Oct 13, 2022
2 parents d51cd2c + db0f77d commit 8e8b99a
Show file tree
Hide file tree
Showing 22 changed files with 521 additions and 40 deletions.
8 changes: 2 additions & 6 deletions src/components/CurrencyInput/helpers/formatCurrency.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
export default function formatCurrency(value, locale, options) {
export default function formatCurrency({ value, locale, options }) {
if (value === '-' || value === '' || value === null) {
return value;
}
const number = Number(value);

if (!Number.isNaN(number)) {
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
...options,
});
return formatter.format(number);
return new Intl.NumberFormat(locale, options).format(number);
}

return '';
Expand Down
12 changes: 6 additions & 6 deletions src/components/CurrencyInput/helpers/formatInteger.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const TYPE = ['group', 'integer', 'minusSign'];

export default function formatInteger(value, locale, options) {
export default function formatInteger({ integer, locale, options }) {
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
...options,
minimumIntegerDigits: undefined,
});
const parts = formatter.formatToParts(Number(value));
return parts.reduce((acc, part) => {
if (TYPE.includes(part.type)) {
return acc + part.value;
const parts = formatter.formatToParts(Number(integer));
return parts.reduce((acc, { type, value }) => {
if (TYPE.includes(type)) {
return acc + value;
}
return acc;
}, '');
Expand Down
9 changes: 7 additions & 2 deletions src/components/CurrencyInput/helpers/getSeparator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const NUMBER = 100000.99;

export default function getSeparator(locale, type, options) {
const formatter = new Intl.NumberFormat(locale, options);
export default function getSeparator({ locale, type, style, currency }) {
const formatter = new Intl.NumberFormat(locale, {
style,
currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
const parts = formatter.formatToParts(NUMBER);
return parts.find(part => part.type === type).value;
}
8 changes: 4 additions & 4 deletions src/components/CurrencyInput/helpers/normalizeValue.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import formatInteger from './formatInteger';

export default function normalizeValue(value, locale, decimalSeparator, options) {
export default function normalizeValue({ value, locale, decimalSeparator, options }) {
const stringValue = String(value);
if (value === '-' || value === '' || value === null) {
return value;
}

if (!Number.isNaN(Number(value))) {
const [stringInteger, stringDecimal] = stringValue.split('.');
const formattedInteger = formatInteger(stringInteger, locale, options);
const [integer, fraction] = stringValue.split('.');
const formattedInteger = formatInteger({ integer, locale, options });

return stringValue.indexOf('.') !== -1
? `${formattedInteger}${decimalSeparator}${stringDecimal || ''}`
? `${formattedInteger}${decimalSeparator}${fraction || ''}`
: formattedInteger;
}

Expand Down
8 changes: 6 additions & 2 deletions src/components/CurrencyInput/hooks/useDecimalSeparator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useMemo } from 'react';
import { getSeparator } from '../helpers';

export default function useDecimalSeparator(locale, options) {
return useMemo(() => getSeparator(locale, 'decimal', options), [locale, options]);
export default function useDecimalSeparator({ locale, style, currency }) {
return useMemo(() => getSeparator({ locale, type: 'decimal', style, currency }), [
currency,
locale,
style,
]);
}
8 changes: 6 additions & 2 deletions src/components/CurrencyInput/hooks/useGroupSeparator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useMemo } from 'react';
import { getSeparator } from '../helpers';

export default function useGroupSeparator(locale, options) {
return useMemo(() => getSeparator(locale, 'group', options), [locale, options]);
export default function useGroupSeparator({ locale, style, currency }) {
return useMemo(() => getSeparator({ locale, type: 'group', style, currency }), [
currency,
locale,
style,
]);
}
1 change: 1 addition & 0 deletions src/components/CurrencyInput/hooks/useOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default function useOptions(props) {
} = props;
return useMemo(
() => ({
style: 'currency',
currency,
currencyDisplay,
currencySign,
Expand Down
28 changes: 13 additions & 15 deletions src/components/CurrencyInput/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,25 @@ const CurrencyInput = forwardRef((props, ref) => {
label,
labelAlignment,
hideLabel,
locale,
locale: localeProp,
currency,
size,
} = useReduxForm(props);

const inputRef = useRef();
const inputId = useUniqueIdentifier('counter-input');
const inputId = useUniqueIdentifier('currency-input');
const errorMessageId = useErrorMessageId(error);
const labelId = useLabelId(label);

const [focused, setFocused] = useState(false);
const [cursor, setCursor] = useState(0);
const options = useOptions(props);
const currentLocale = useLocale(locale);
const decimalSeparator = useDecimalSeparator(currentLocale, options);
const groupSeparator = useGroupSeparator(currentLocale, options);
const locale = useLocale(localeProp);
const decimalSeparator = useDecimalSeparator({ locale, style: 'currency', currency });
const groupSeparator = useGroupSeparator({ locale, style: 'currency', currency });

const normalizedValue = normalizeValue(value, currentLocale, decimalSeparator, options);
const currentValue = focused ? normalizedValue : formatCurrency(value, currentLocale, options);
const normalizedValue = normalizeValue({ value, locale, decimalSeparator, options });
const currentValue = focused ? normalizedValue : formatCurrency({ value, locale, options });

const isReadOnly = !!(!disabled && readOnly);

Expand All @@ -90,12 +91,12 @@ const CurrencyInput = forwardRef((props, ref) => {
const handleChange = event => {
const { value: newValue, selectionStart } = event.target;
const cleanValue = clearValue(newValue, decimalSeparator);
const normalizeNewValue = normalizeValue(
cleanValue,
currentLocale,
const normalizeNewValue = normalizeValue({
value: cleanValue,
locale,
decimalSeparator,
options,
);
});

if (isValidStringNumber(cleanValue) && normalizeNewValue !== normalizedValue) {
onChange(cleanValue);
Expand Down Expand Up @@ -257,16 +258,13 @@ CurrencyInput.propTypes = {
* length) when formatted. Possible values are from 1 to 21; The default is 1. */
minimumIntegerDigits: PropTypes.number,
/** The minimum number of fraction digits to use. Possible values are from 0 to 20;
* the default for plain number and percent formatting is 0;
* the default for currency formatting is the number of minor unit digits provided by the ISO 4217 currency code list
* (2 if the list doesn't provide that information). */
minimumFractionDigits: PropTypes.number,
/** The maximum number of fraction digits to use. Possible values are from 0 to 20;
* the default for plain number formatting is the larger of minimumFractionDigits and 3;
* the default for currency formatting is the larger of minimumFractionDigits and
* the number of minor unit digits provided by the ISO 4217 currency code list
* (2 if the list doesn't provide that information);
* the default for percent formatting is the larger of minimumFractionDigits and 0. */
* (2 if the list doesn't provide that information); */
maximumFractionDigits: PropTypes.number,
/** The minimum number of significant digits to use. Possible values are from 1 to 21; The default is 1. */
minimumSignificantDigits: PropTypes.number,
Expand Down
1 change: 1 addition & 0 deletions src/components/HelpText/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const HelpText = React.forwardRef((props, ref) => {
tabIndex={tabIndex}
ariaLabelledby={helpTextId}
variant={variant}
iconSize={iconSize}
>
<Icon isFocused={isFocused} iconSize={iconSize} />
<AssistiveText text={variant} />
Expand Down
5 changes: 4 additions & 1 deletion src/components/HelpText/styled/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import styled from 'styled-components';
import attachThemeAttrs from '../../../styles/helpers/attachThemeAttrs';
import getIconSize from '../helpers/getIconSize';

export const StyledButton = attachThemeAttrs(styled.button)`
border: none;
background: transparent;
height: fit-content;
height: ${props => getIconSize(props.iconSize)}px;
width: ${props => getIconSize(props.iconSize)}px;
line-height: 0;
padding: 0;
border-radius: 1rem;
Expand Down
12 changes: 12 additions & 0 deletions src/components/PercentInput/helpers/formatPercent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function formatPercent({ value, locale, options }) {
if (value === '-' || value === '' || value === null) {
return value;
}
const number = Number(value);

if (!Number.isNaN(number)) {
return new Intl.NumberFormat(locale, options).format(number / 100);
}

return '';
}
2 changes: 2 additions & 0 deletions src/components/PercentInput/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as formatPercent } from './formatPercent';
export { default as normalizeValue } from './normalizeValue';
19 changes: 19 additions & 0 deletions src/components/PercentInput/helpers/normalizeValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import formatInteger from '../../CurrencyInput/helpers/formatInteger';

export default function normalizeValue({ value, locale, decimalSeparator, options }) {
const stringValue = String(value);
if (value === '-' || value === '' || value === null) {
return value;
}

if (!Number.isNaN(Number(value))) {
const [integer, fraction] = stringValue.split('.');
const formattedInteger = formatInteger({ integer: Number(integer) / 100, locale, options });

return stringValue.indexOf('.') !== -1
? `${formattedInteger}${decimalSeparator}${fraction || ''}`
: formattedInteger;
}

return '';
}
28 changes: 28 additions & 0 deletions src/components/PercentInput/hooks/useOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useMemo } from 'react';

export default function useOptions(props) {
const {
minimumIntegerDigits,
minimumFractionDigits,
maximumFractionDigits,
minimumSignificantDigits,
maximumSignificantDigits,
} = props;
return useMemo(
() => ({
style: 'percent',
minimumIntegerDigits,
minimumFractionDigits,
maximumFractionDigits,
minimumSignificantDigits,
maximumSignificantDigits,
}),
[
maximumFractionDigits,
maximumSignificantDigits,
minimumFractionDigits,
minimumIntegerDigits,
minimumSignificantDigits,
],
);
}
35 changes: 35 additions & 0 deletions src/components/PercentInput/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ReactNode, MouseEvent, FocusEvent, KeyboardEvent } from 'react';
import { BaseProps, IconPosition, LabelAlignment } from '../types';

export interface PercentInputProps extends BaseProps {
value?: number | string;
name?: string;
label?: ReactNode;
labelAlignment?: LabelAlignment;
hideLabel?: boolean;
placeholder?: string;
icon?: ReactNode;
iconPosition?: IconPosition;
bottomHelpText?: ReactNode;
required?: boolean;
error?: ReactNode;
disabled?: boolean;
readOnly?: boolean;
tabIndex?: number | string;
onChange?: (value?: string) => void;
onClick?: (event: MouseEvent<HTMLInputElement>) => void;
onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
id?: string;
variant?: 'default' | 'shaded' | 'bare';
locale?: string;
minimumIntegerDigits?: number;
minimumFractionDigits?: number;
maximumFractionDigits?: number;
minimumSignificantDigits?: number;
maximumSignificantDigits?: number;
size?: 'small' | 'medium' | 'large';
}

export default function(props: PercentInputProps): JSX.Element | null;
Loading

0 comments on commit 8e8b99a

Please sign in to comment.