Skip to content

Commit

Permalink
feat: renamed onChange prop to onValueChange
Browse files Browse the repository at this point in the history
This change allows users to access original onChange event

Breaking Change: Renamed "onChange" to "onValueChange"
  • Loading branch information
cchanxzy committed Dec 9, 2020
1 parent e7674f3 commit 83d3806
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 115 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import CurrencyInput from 'react-currency-input-field';
defaultValue={1000}
allowDecimals={true}
decimalsLimit={2}
onChange={(value, name) => console.log(value, name)}
onValueChange={(value, name) => console.log(value, name)}
/>;
```

Expand Down Expand Up @@ -121,7 +121,7 @@ Example if `fixedDecimalLength` was 2:
| fixedDecimalLength | `number` | | Value will always have the specified length of decimals |
| id | `string` | | Component id |
| maxLength | `number` | | Maximum characters the user can enter |
| onChange | `function` | | Handle change in value |
| onValueChange | `function` | | Handle change in value |
| onBlurValue | `function` | | Handle value onBlur |
| placeholder | `string` | | Placeholder if no value |
| decimalScale | `number` | | Specify decimal scale for padding/trimming |
Expand Down
34 changes: 24 additions & 10 deletions src/components/CurrencyInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<
disabled = false,
maxLength: userMaxLength,
value: userValue,
onChange,
onValueChange,
onBlurValue,
fixedDecimalLength,
placeholder,
Expand All @@ -36,6 +36,8 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<
step,
disableGroupSeparators = false,
disableAbbreviations = false,
onChange,
onBlur,
...props
}: CurrencyInputProps,
ref
Expand Down Expand Up @@ -91,8 +93,8 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<
const processChange = (value: string, selectionStart?: number | null): void => {
const valueOnly = cleanValue({ value, ...cleanValueOptions });

if (!valueOnly) {
onChange && onChange(undefined, name);
if (valueOnly === '') {
onValueChange && onValueChange(undefined, name);
setStateValue('');
return;
}
Expand All @@ -102,7 +104,7 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<
}

if (valueOnly === '-') {
onChange && onChange(undefined, name);
onValueChange && onValueChange(undefined, name);
setStateValue(value);
return;
}
Expand All @@ -117,16 +119,24 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<

setStateValue(formattedValue);

onChange && onChange(valueOnly, name);
onValueChange && onValueChange(valueOnly, name);
};

const handleOnChange = ({
target: { value, selectionStart },
}: React.ChangeEvent<HTMLInputElement>): void => {
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
const {
target: { value, selectionStart },
} = event;

processChange(value, selectionStart);

onChange && onChange(event);
};

const handleOnBlur = ({ target: { value } }: React.ChangeEvent<HTMLInputElement>): void => {
const handleOnBlur = (event: React.FocusEvent<HTMLInputElement>): void => {
const {
target: { value },
} = event;

const valueOnly = cleanValue({ value, ...cleanValueOptions });

if (valueOnly === '-' || !valueOnly) {
Expand All @@ -143,14 +153,18 @@ export const CurrencyInput: FC<CurrencyInputProps> = forwardRef<
decimalSeparator,
decimalScale || fixedDecimalLength
);
onChange && onChange(newValue, name);

onValueChange && onValueChange(newValue, name);
onBlurValue && onBlurValue(newValue, name);

const formattedValue = formatValue({
...formatValueOptions,
value: newValue,
});

setStateValue(formattedValue);

onBlur && onBlur(event);
};

const handleOnKeyDown = ({ key }: React.KeyboardEvent<HTMLInputElement>) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/CurrencyInputProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export type CurrencyInputProps = Overwrite<
/**
* Handle change in value
*/
onChange?: (value: string | undefined, name?: string) => void;
onValueChange?: (value: string | undefined, name?: string) => void;

/**
* Handle value onBlur
Expand Down
32 changes: 17 additions & 15 deletions src/components/__tests__/CurrencyInput-abbreviated.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,69 @@ import CurrencyInput from '../CurrencyInput';
const id = 'validationCustom01';

describe('<CurrencyInput /> component > abbreviated', () => {
const onChangeSpy = jest.fn();
const onValueChangeSpy = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
});

it('should allow abbreviated values with k', () => {
const view = shallow(<CurrencyInput id={id} prefix="£" onChange={onChangeSpy} />);
const view = shallow(<CurrencyInput id={id} prefix="£" onValueChange={onValueChangeSpy} />);
view.find(`#${id}`).simulate('change', { target: { value: '£1.5k' } });
expect(onChangeSpy).toBeCalledWith('1500', undefined);
expect(onValueChangeSpy).toBeCalledWith('1500', undefined);

expect(view.update().find(`#${id}`).prop('value')).toBe('£1,500');
});

it('should allow abbreviated values with m', () => {
const view = shallow(<CurrencyInput id={id} prefix="£" onChange={onChangeSpy} />);
const view = shallow(<CurrencyInput id={id} prefix="£" onValueChange={onValueChangeSpy} />);
view.find(`#${id}`).simulate('change', { target: { value: '£2.123M' } });
expect(onChangeSpy).toBeCalledWith('2123000', undefined);
expect(onValueChangeSpy).toBeCalledWith('2123000', undefined);

expect(view.update().find(`#${id}`).prop('value')).toBe('£2,123,000');
});

it('should allow abbreviated values with b', () => {
const view = shallow(<CurrencyInput id={id} prefix="£" onChange={onChangeSpy} />);
const view = shallow(<CurrencyInput id={id} prefix="£" onValueChange={onValueChangeSpy} />);
view.find(`#${id}`).simulate('change', { target: { value: '£1.599B' } });
expect(onChangeSpy).toBeCalledWith('1599000000', undefined);
expect(onValueChangeSpy).toBeCalledWith('1599000000', undefined);

expect(view.update().find(`#${id}`).prop('value')).toBe('£1,599,000,000');
});

it('should not abbreviate any other letters', () => {
const view = shallow(<CurrencyInput id={id} prefix="£" onChange={onChangeSpy} />);
const view = shallow(<CurrencyInput id={id} prefix="£" onValueChange={onValueChangeSpy} />);
view.find(`#${id}`).simulate('change', { target: { value: '£1.5e' } });
expect(onChangeSpy).toBeCalledWith('1.5', undefined);
expect(onValueChangeSpy).toBeCalledWith('1.5', undefined);

expect(view.update().find(`#${id}`).prop('value')).toBe('£1.5');
});

it('should not allow abbreviation without number', () => {
const view = shallow(<CurrencyInput id={id} onChange={onChangeSpy} />);
const view = shallow(<CurrencyInput id={id} onValueChange={onValueChangeSpy} />);
view.find(`#${id}`).simulate('change', { target: { value: 'k' } });
expect(onChangeSpy).toBeCalledWith(undefined, undefined);
expect(onValueChangeSpy).toBeCalledWith(undefined, undefined);
expect(view.update().find(`#${id}`).prop('value')).toBe('');

view.find(`#${id}`).simulate('change', { target: { value: 'M' } });
expect(onChangeSpy).toBeCalledWith(undefined, undefined);
expect(onValueChangeSpy).toBeCalledWith(undefined, undefined);
expect(view.update().find(`#${id}`).prop('value')).toBe('');
});

describe('disableAbbreviations', () => {
it('should not allow abbreviations if disableAbbreviations is true', () => {
const view = shallow(<CurrencyInput id={id} onChange={onChangeSpy} disableAbbreviations />);
const view = shallow(
<CurrencyInput id={id} onValueChange={onValueChangeSpy} disableAbbreviations />
);
view.find(`#${id}`).simulate('change', { target: { value: '1k' } });
expect(view.update().find(`#${id}`).prop('value')).toBe('1');

view.find(`#${id}`).simulate('change', { target: { value: '23m' } });
expect(onChangeSpy).toBeCalledWith('23', undefined);
expect(onValueChangeSpy).toBeCalledWith('23', undefined);
expect(view.update().find(`#${id}`).prop('value')).toBe('23');

view.find(`#${id}`).simulate('change', { target: { value: '55b' } });
expect(onChangeSpy).toBeCalledWith('55', undefined);
expect(onValueChangeSpy).toBeCalledWith('55', undefined);
expect(view.update().find(`#${id}`).prop('value')).toBe('55');
});
});
Expand Down
16 changes: 8 additions & 8 deletions src/components/__tests__/CurrencyInput-decimals.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,48 @@ import CurrencyInput from '../CurrencyInput';
const id = 'validationCustom01';

describe('<CurrencyInput /> component > decimals', () => {
const onChangeSpy = jest.fn();
const onValueChangeSpy = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
});

it('should allow value with decimals if allowDecimals is true', () => {
const view = shallow(
<CurrencyInput allowDecimals={true} id={id} prefix="£" onChange={onChangeSpy} />
<CurrencyInput allowDecimals={true} id={id} prefix="£" onValueChange={onValueChangeSpy} />
);
view.find(`#${id}`).simulate('change', { target: { value: '£1,234.56' } });
expect(onChangeSpy).toBeCalledWith('1234.56', undefined);
expect(onValueChangeSpy).toBeCalledWith('1234.56', undefined);

const updatedView = view.update();
expect(updatedView.find(`#${id}`).prop('value')).toBe('£1,234.56');
});

it('should disallow value with decimals if allowDecimals is false', () => {
const view = shallow(
<CurrencyInput allowDecimals={false} id={id} prefix="£" onChange={onChangeSpy} />
<CurrencyInput allowDecimals={false} id={id} prefix="£" onValueChange={onValueChangeSpy} />
);
view.find(`#${id}`).simulate('change', { target: { value: '£1,234.56' } });
expect(onChangeSpy).toBeCalledWith('1234', undefined);
expect(onValueChangeSpy).toBeCalledWith('1234', undefined);

const updatedView = view.update();
expect(updatedView.find(`#${id}`).prop('value')).toBe('£1,234');
});

it('should limit decimals to decimalsLimit length', () => {
const view = shallow(
<CurrencyInput id={id} decimalsLimit={3} prefix="£" onChange={onChangeSpy} />
<CurrencyInput id={id} decimalsLimit={3} prefix="£" onValueChange={onValueChangeSpy} />
);
view.find(`#${id}`).simulate('change', { target: { value: '£1,234.56789' } });
expect(onChangeSpy).toBeCalledWith('1234.567', undefined);
expect(onValueChangeSpy).toBeCalledWith('1234.567', undefined);

const updatedView = view.update();
expect(updatedView.find(`#${id}`).prop('value')).toBe('£1,234.567');
});

it('should be disabled if disabled prop is true', () => {
const view = shallow(
<CurrencyInput id={id} decimalsLimit={3} disabled={true} onChange={onChangeSpy} />
<CurrencyInput id={id} decimalsLimit={3} disabled={true} onValueChange={onValueChangeSpy} />
);
expect(view.find(`#${id}`).prop('disabled')).toBe(true);
});
Expand Down
Loading

0 comments on commit 83d3806

Please sign in to comment.