Skip to content

Commit

Permalink
refactor: refactorng after review
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Sep 18, 2023
1 parent 029f3d9 commit 9ef3e26
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 47 deletions.
16 changes: 5 additions & 11 deletions src/Form/FormControl.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import FormControlDecoratorGroup from './FormControlDecoratorGroup';

import { callAllHandlers, useHasValue } from './fieldUtils';

const DEFAULT_MASK_VALUE = '00-00-000';

const FormControl = React.forwardRef(({
as,
className,
Expand All @@ -21,7 +19,6 @@ const FormControl = React.forwardRef(({
autoResize,
onChange,
hasInputMask,
mask,
...props
}, ref) => {
const {
Expand Down Expand Up @@ -76,7 +73,7 @@ const FormControl = React.forwardRef(({
className={className}
>
<RBFormControl
as={hasInputMask ? IMaskInput : as}
as={hasInputMask?.length ? IMaskInput : as}
ref={resolvedRef}
size={size}
isInvalid={isInvalid}
Expand All @@ -85,7 +82,7 @@ const FormControl = React.forwardRef(({
'has-value': hasValue,
})}
onChange={handleOnChange}
mask={mask}
mask={hasInputMask}
{...controlProps}
/>
</FormControlDecoratorGroup>
Expand Down Expand Up @@ -128,10 +125,8 @@ FormControl.propTypes = {
isInvalid: PropTypes.bool,
/** Only for `as="textarea"`. Specifies whether the input can be resized according to the height of content. */
autoResize: PropTypes.bool,
/** Specifies whether to use an input mask for the input. */
hasInputMask: PropTypes.bool,
/** Specifies the input mask to be used if `hasInputMask` is set to `true`. */
mask: PropTypes.string,
/** Specifies what format to use for the input mask. */
hasInputMask: PropTypes.string,
};

FormControl.defaultProps = {
Expand All @@ -150,8 +145,7 @@ FormControl.defaultProps = {
isValid: undefined,
isInvalid: undefined,
autoResize: false,
hasInputMask: false,
mask: DEFAULT_MASK_VALUE,
hasInputMask: undefined,
};

export default FormControl;
54 changes: 27 additions & 27 deletions src/Form/form-control.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,9 @@ or [select attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element
```

## Input masks
Paragon uses the [react-imask](https://www.npmjs.com/package/react-imask) library, which allows you to add masks of different types for inputs.
To create your own mask, you need to pass the required mask pattern (`+{1}(000)000-00-00`) to the `mask` property. <br />
Paragon uses the [react-imask](https://www.npmjs.com/package/react-imask) library,
which allows you to add masks of different types for inputs.
To create your own mask, you need to pass the required mask pattern (`+{1}(000)000-00-00`) to the `hasInputMask` property. <br />
See [react-imask](https://imask.js.org) for documentation on available props.

```jsx live
Expand All @@ -179,8 +180,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>Phone</h3>
<Form.Group>
<Form.Control
hasInputMask
mask="+{1}(000)000-00-00"
hasInputMask="+{1}(000)000-00-00"
value={value}
onChange={handleChange}
leadingElement={<Icon src={FavoriteBorder} />}
Expand All @@ -193,8 +193,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>Credit card</h3>
<Form.Group>
<Form.Control
hasInputMask
mask="0000 0000 0000 0000"
hasInputMask="0000 0000 0000 0000"
value={value}
onChange={handleChange}
leadingElement={<Icon src={FavoriteBorder} />}
Expand All @@ -206,8 +205,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>Date</h3>
<Form.Group>
<Form.Control
hasInputMask
mask={Date}
hasInputMask={Date}
value={value}
onChange={handleChange}
leadingElement={<Icon src={FavoriteBorder} />}
Expand All @@ -219,8 +217,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>Secure password</h3>
<Form.Group>
<Form.Control
hasInputMask
mask="XXX-XX-0000"
hasInputMask="XXX-XX-0000"
value={value}
definitions={{
X: {
Expand All @@ -239,8 +236,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>OTP password</h3>
<Form.Group>
<Form.Control
hasInputMask
mask="G-00000"
hasInputMask="G-00000"
value={value}
onChange={handleChange}
leadingElement={<Icon src={FavoriteBorder} />}
Expand All @@ -253,8 +249,7 @@ See [react-imask](https://imask.js.org) for documentation on available props.
<h3>Course prise</h3>
<Form.Group>
<Form.Control
hasInputMask
mask="$num"
hasInputMask="$num"
blocks={{
num: {
// nested masks are available!
Expand Down Expand Up @@ -293,25 +288,30 @@ See [react-imask](https://imask.js.org) for documentation on available props.
```

## Input masks with clear value
`unmask` prop allows get and set value and unmasked value easily
To get a value without a mask, you need to use `onChange` instead of `onAccept` to handle changes.

```jsx live
() => {
const [value, setValue] = useState('');
console.log(value);

return (
<Form.Group>
<Form.Control
hasInputMask
mask="+{1}(000)000-00-00"
leadingElement={<Icon src={FavoriteBorder} />}
trailingElement={<Icon src={Verified} />}
floatingLabel="What is your phone number?"
value={value}
onAccept={(_, mask) => setValue(mask._unmaskedValue)}
/>
</Form.Group>
<>
<Form.Group>
<Form.Control
hasInputMask="+{1}(000)000-00-00"
leadingElement={<Icon src={FavoriteBorder} />}
trailingElement={<Icon src={Verified} />}
floatingLabel="What is your phone number?"
value={value}
// depending on prop above first argument is
// `value` if `unmask=false`,
// `unmaskedValue` if `unmask=true`,
// `typedValue` if `unmask='typed'`
onAccept={(_, mask) => setValue(mask._unmaskedValue)}
/>
</Form.Group>
Unmasked value: {JSON.stringify(value)}
</>
);
}
```
Expand Down
23 changes: 14 additions & 9 deletions src/Form/tests/FormControl.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { useState } from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import {
fireEvent, render, screen, act,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import FormControl from '../FormControl';

Expand All @@ -14,8 +17,7 @@ function Component({ isClearValue }) {

return (
<FormControl
hasInputMask
mask="+{1}(000)000-00-00"
hasInputMask="+{1}(000)000-00-00"
value={inputValue}
onChange={isClearValue ? onChangeFunc : (e) => setInputValue(e.target.value)}
onAccept={isClearValue ? onChangeFunc : (value) => setInputValue(value)}
Expand All @@ -25,9 +27,10 @@ function Component({ isClearValue }) {
}

describe('FormControl', () => {
it('textarea changes its height with autoResize prop', () => {
it('textarea changes its height with autoResize prop', async () => {
const useReferenceSpy = jest.spyOn(React, 'useRef').mockReturnValue(ref);
const onChangeFunc = jest.fn();
const inputText = 'new text';
render(
<FormControl as="textarea" autoResize onChange={onChangeFunc} data-testid="form-control-textarea" />,
);
Expand All @@ -41,17 +44,19 @@ describe('FormControl', () => {
expect(useReferenceSpy).toHaveBeenCalledTimes(1);
expect(ref.current.style.height).toBe('0px');

fireEvent.change(textarea, { target: { value: 'new text' } });
await userEvent.type(textarea, inputText);

expect(onChangeFunc).toHaveBeenCalledTimes(1);
expect(onChangeFunc).toHaveBeenCalledTimes(inputText.length);
expect(ref.current.style.height).toEqual(`${ref.current.scrollHeight + ref.current.offsetHeight}px`);
});
it('should apply and accept input mask for phone numbers', () => {
render(<Component />);

const input = screen.getByTestId('form-control-with-mask');
fireEvent.change(input, { target: { value: '1234567890' } });
expect(input.value).toBe('+1(234)567-89-0');
act(() => {
const input = screen.getByTestId('form-control-with-mask');
userEvent.type(input, '1234567890');
expect(input.value).toBe('+1(234)567-89-0');
});
});
it('should be cleared from the mask elements value', () => {
render(<Component isClearValue />);
Expand Down

0 comments on commit 9ef3e26

Please sign in to comment.