Skip to content

Commit 8e13eed

Browse files
committed
Uplift MaskedInput to use FormGroup
1 parent 01d6161 commit 8e13eed

File tree

6 files changed

+91
-217
lines changed

6 files changed

+91
-217
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"eslint-plugin-react-hooks": "^1.7.0",
4848
"jest": "^24.9.0",
4949
"nhsuk-frontend": "^3.0.2",
50-
"nhsuk-react-components": "^1.0.1",
50+
"nhsuk-react-components": "^1.1.4-test.1",
5151
"node-sass": "^4.12.0",
5252
"node-sass-tilde-importer": "^1.0.2",
5353
"prettier": "^1.18.2",
@@ -67,7 +67,7 @@
6767
"typescript": "^3.6.3"
6868
},
6969
"peerDependencies": {
70-
"nhsuk-react-components": "^1.0.1",
70+
"nhsuk-react-components": "^1.1.4-test.1",
7171
"react": "^16.9.3",
7272
"react-dom": "^16.9.3"
7373
},

src/components/masked-input/MaskedInput.tsx

+25-54
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,42 @@
1-
import React, { HTMLProps, useState, useEffect, RefObject } from 'react';
2-
import { useFormContext, Label, ErrorMessage, Hint } from 'nhsuk-react-components';
1+
import React, { HTMLProps } from 'react';
2+
import FormGroup from 'nhsuk-react-components/lib/util/FormGroup';
3+
import { FormElementProps } from 'nhsuk-react-components/lib/util/types/FormTypes';
4+
import { InputWidth } from 'nhsuk-react-components/lib/util/types/NHSUKTypes';
35
import InputMask, { ReactInputMask } from 'react-input-mask';
46
import classNames from 'classnames';
57

6-
type MaskedInputProps = HTMLProps<HTMLInputElement> & {
7-
labelProps?: HTMLProps<HTMLLabelElement>;
8-
hint?: string;
9-
error?: boolean | string;
10-
width?: '2' | '3' | '4' | '5' | '10';
11-
mask: string;
12-
maskChar?: string;
13-
formatChars?: { [character: string]: string };
14-
alwaysShowMask?: boolean;
15-
inputRef?: (instance: HTMLInputElement | null) => any;
16-
ref?: string | ((instance: ReactInputMask | null) => void) | RefObject<ReactInputMask> | null;
17-
};
18-
19-
const MaskedInput: React.FC<MaskedInputProps> = ({
20-
className,
21-
children,
22-
id,
23-
labelProps,
24-
hint,
25-
width,
26-
error,
27-
...rest
28-
}) => {
29-
const { isForm, setError } = useFormContext();
30-
const [name] = useState<string>(
31-
rest.name || `masked-input_${(Math.random() + 1).toString(36).substring(2, 7)}`,
32-
);
8+
type InputMaskRef =
9+
| string
10+
| ((instance: ReactInputMask | null) => void)
11+
| React.RefObject<ReactInputMask>
12+
| null;
3313

34-
useEffect(() => {
35-
if (isForm) {
36-
setError(name, Boolean(error));
37-
}
38-
}, [error, name, isForm]);
14+
type MaskedInputProps = HTMLProps<HTMLInputElement> &
15+
FormElementProps & {
16+
width?: InputWidth;
17+
mask: string;
18+
maskChar?: string;
19+
formatChars?: { [character: string]: string };
20+
alwaysShowMask?: boolean;
21+
inputRef?: (instance: HTMLInputElement | null) => any;
22+
ref?: InputMaskRef;
23+
};
3924

40-
return (
41-
<>
42-
{children ? (
43-
<Label
44-
className={labelProps ? labelProps.className : undefined}
45-
htmlFor={id}
46-
id={id ? `${id}-label` : undefined}
47-
>
48-
{children}
49-
</Label>
50-
) : null}
51-
{hint ? <Hint id={id ? `${id}-hint` : undefined}>{hint}</Hint> : null}
52-
{error && typeof error === 'string' ? (
53-
<ErrorMessage id={id ? `${id}-error` : undefined}>{error}</ErrorMessage>
54-
) : null}
25+
const MaskedInput: React.FC<MaskedInputProps> = props => (
26+
<FormGroup<MaskedInputProps> inputType="input" {...props}>
27+
{({ className, width, error, ref, ...rest }) => (
5528
<InputMask
5629
className={classNames(
5730
'nhsuk-input',
5831
{ [`nhsuk-input--width-${width}`]: width },
5932
{ 'nhsuk-input--error': error },
6033
className,
6134
)}
62-
id={id}
63-
aria-describedby={children && id ? `${id}-label` : undefined}
6435
{...rest}
6536
/>
66-
</>
67-
);
68-
};
37+
)}
38+
</FormGroup>
39+
);
6940

7041
MaskedInput.defaultProps = {
7142
type: 'text',

src/components/masked-input/__tests__/MaskedInput.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import MaskedInput from '../MaskedInput';
44

55
describe('MaskedInput', () => {
66
it('matches snapshot', () => {
7-
const component = mount(<MaskedInput mask="999 999 9999">NHS Number</MaskedInput>);
7+
const component = mount(<MaskedInput mask="999 999 9999" label="NHS Number" />);
88
expect(component).toMatchSnapshot();
99
expect(component.text()).toBe('NHS Number');
1010
component.unmount();

src/components/masked-input/__tests__/__snapshots__/MaskedInput.test.tsx.snap

+47-21
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,58 @@
22

33
exports[`MaskedInput matches snapshot 1`] = `
44
<MaskedInput
5+
label="NHS Number"
56
mask="999 999 9999"
67
type="text"
78
>
8-
<Label>
9-
<BaseLabel>
10-
<label
11-
className="nhsuk-label"
12-
>
13-
NHS Number
14-
</label>
15-
</BaseLabel>
16-
</Label>
17-
<InputElement
18-
className="nhsuk-input"
9+
<FormGroup
10+
inputType="input"
11+
label="NHS Number"
1912
mask="999 999 9999"
2013
type="text"
2114
>
22-
<input
23-
className="nhsuk-input"
24-
onBlur={[Function]}
25-
onChange={[Function]}
26-
onFocus={[Function]}
27-
onMouseDown={[Function]}
28-
onPaste={[Function]}
29-
type="text"
30-
/>
31-
</InputElement>
15+
<div
16+
className="nhsuk-form-group"
17+
>
18+
<Label
19+
htmlFor="input_x82ib"
20+
id="input_x82ib--label"
21+
>
22+
<BaseLabel
23+
htmlFor="input_x82ib"
24+
id="input_x82ib--label"
25+
>
26+
<label
27+
className="nhsuk-label"
28+
htmlFor="input_x82ib"
29+
id="input_x82ib--label"
30+
>
31+
NHS Number
32+
</label>
33+
</BaseLabel>
34+
</Label>
35+
<InputElement
36+
aria-labelledby="input_x82ib--label"
37+
className="nhsuk-input"
38+
id="input_x82ib"
39+
mask="999 999 9999"
40+
name="input_x82ib"
41+
type="text"
42+
>
43+
<input
44+
aria-labelledby="input_x82ib--label"
45+
className="nhsuk-input"
46+
id="input_x82ib"
47+
name="input_x82ib"
48+
onBlur={[Function]}
49+
onChange={[Function]}
50+
onFocus={[Function]}
51+
onMouseDown={[Function]}
52+
onPaste={[Function]}
53+
type="text"
54+
/>
55+
</InputElement>
56+
</div>
57+
</FormGroup>
3258
</MaskedInput>
3359
`;

stories/MaskedInput.stories.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ stories
1111
<MaskedInput
1212
name="ni-number"
1313
hint="It's on your National Insurance card, benefit letter, payslip or P60. For example, QQ 12 34 56 C"
14+
label="National Insurance Number"
1415
width="10"
1516
mask="AA 99 99 99 A"
1617
formatChars={{
@@ -19,23 +20,20 @@ stories
1920
}}
2021
maskChar=""
2122
alwaysShowMask={false}
22-
>
23-
National Insurance Number
24-
</MaskedInput>
23+
/>
2524
</div>
2625
))
2726
.add('NHS Number Mask', () => (
2827
<div className="masked-input-demo">
2928
<MaskedInput
3029
name="ni-number"
3130
hint="Your 10 Digit NHS Number"
31+
label="NHS Number"
3232
width="10"
3333
mask="999 999 9999"
3434
maskChar=""
3535
autoComplete="off"
3636
alwaysShowMask={false}
37-
>
38-
NHS Number
39-
</MaskedInput>
37+
/>
4038
</div>
4139
));

0 commit comments

Comments
 (0)